2023-08-31 16:57:55 +08:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
# @author yutent<yutent.io@gmail.com>
|
|
|
|
# @date 2023/08/08 14:07:26
|
|
|
|
|
|
|
|
|
2023-09-08 18:38:39 +08:00
|
|
|
import gi, os, sys, json, shutil, hashlib, random
|
2023-08-31 16:57:55 +08:00
|
|
|
|
2023-09-06 14:47:56 +08:00
|
|
|
gi.require_version('Gtk', '3.0')
|
2023-08-31 16:57:55 +08:00
|
|
|
gi.require_version("WebKit2", "4.1")
|
|
|
|
|
|
|
|
|
|
|
|
from gi.repository import GObject, Gtk, Gdk, WebKit2, GLib, Gio, GdkPixbuf
|
2023-09-07 19:58:17 +08:00
|
|
|
from ._custom_window import create_same_window, create_custom_window
|
2023-08-31 16:57:55 +08:00
|
|
|
|
|
|
|
|
|
|
|
# 优先尝试使用指示器, 没有再使用 Gtk.StatusIcon
|
|
|
|
try:
|
|
|
|
# gir1.2-ayatanaappindicator3-0.1
|
|
|
|
gi.require_version('AyatanaAppIndicator3', '0.1')
|
|
|
|
from gi.repository import AyatanaAppIndicator3 as AppIndicator3
|
|
|
|
except:
|
|
|
|
AppIndicator3 = None
|
|
|
|
|
|
|
|
try:
|
|
|
|
# gir1.2-keybinder-3.0
|
|
|
|
gi.require_version("Keybinder", "3.0")
|
|
|
|
from gi.repository import Keybinder
|
|
|
|
|
|
|
|
# 初始化 Keybinder
|
|
|
|
Keybinder.init()
|
|
|
|
except:
|
|
|
|
Keybinder = None
|
|
|
|
|
2023-09-08 18:55:49 +08:00
|
|
|
from ._version import version
|
2023-08-31 16:57:55 +08:00
|
|
|
from ._settings import create_setting
|
|
|
|
from ._protocal import create_protocal
|
|
|
|
from ._notify import create_notify
|
|
|
|
from ._inject import Inject
|
|
|
|
from ._utils import get_monitor_info, pixbuf_to_dict, dict_to_pixbuf
|
|
|
|
|
|
|
|
|
2023-09-04 18:29:12 +08:00
|
|
|
|
|
|
|
env = {
|
|
|
|
"HOME_DIR": os.getenv('HOME'),
|
|
|
|
"CONFIG_DIR": os.path.join(os.getenv('HOME'), '.config'),
|
|
|
|
"CACHE_DIR": os.path.join(os.getenv('HOME'), '.cache')
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-08-31 16:57:55 +08:00
|
|
|
def noop():
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
2023-09-07 19:58:17 +08:00
|
|
|
|
2023-08-31 16:57:55 +08:00
|
|
|
class WebEngine(WebKit2.WebView):
|
|
|
|
|
|
|
|
__gsignals__ = {
|
|
|
|
'quit': (GObject.SignalFlags.RUN_FIRST, None, ())
|
|
|
|
}
|
2023-09-08 18:55:49 +08:00
|
|
|
app_name = 'WebEngine'
|
|
|
|
app_version = version
|
2023-09-08 17:22:59 +08:00
|
|
|
uuid = None
|
2023-08-31 16:57:55 +08:00
|
|
|
root = None
|
|
|
|
window = None
|
2023-09-08 15:06:42 +08:00
|
|
|
opener = None
|
2023-09-08 17:22:59 +08:00
|
|
|
children = set()
|
2023-09-06 15:30:09 +08:00
|
|
|
custom_bridge = None
|
2023-08-31 16:57:55 +08:00
|
|
|
|
2023-09-08 17:22:59 +08:00
|
|
|
def __init__(self, win, opener = None, uuid = None):
|
2023-08-31 16:57:55 +08:00
|
|
|
|
|
|
|
WebKit2.WebView.__init__(self)
|
|
|
|
|
2023-09-08 17:22:59 +08:00
|
|
|
if uuid is None:
|
|
|
|
self.uuid = random.randbytes(8).hex()
|
|
|
|
else:
|
|
|
|
self.uuid = uuid
|
|
|
|
|
2023-09-08 15:06:42 +08:00
|
|
|
self.opener = opener
|
2023-09-07 19:58:17 +08:00
|
|
|
self.window = win
|
|
|
|
|
2023-09-08 17:22:59 +08:00
|
|
|
if opener is not None:
|
|
|
|
opener.children.add(self)
|
|
|
|
|
2023-09-07 19:58:17 +08:00
|
|
|
if win.get_title() is None:
|
2023-09-08 18:55:49 +08:00
|
|
|
win.set_title(self.app_name)
|
2023-09-07 19:58:17 +08:00
|
|
|
|
|
|
|
if win.get_icon() is None and win.get_icon_name() is None:
|
|
|
|
win.set_icon_name('web-browser')
|
2023-08-31 16:57:55 +08:00
|
|
|
|
|
|
|
self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
|
|
|
|
self.display = Gdk.Display.get_default()
|
|
|
|
|
|
|
|
self.use(create_notify())
|
|
|
|
|
|
|
|
setting = create_setting()
|
|
|
|
self.use(setting)
|
|
|
|
|
|
|
|
|
|
|
|
im = self.get_input_method_context()
|
|
|
|
# 解决输入法候选框跟随问题
|
2023-09-06 12:21:56 +08:00
|
|
|
im.set_enable_preedit(False)
|
2023-08-31 16:57:55 +08:00
|
|
|
|
2023-09-06 12:21:56 +08:00
|
|
|
Inject(self, env).connect(self.called_by_js)
|
2023-08-31 16:57:55 +08:00
|
|
|
|
2023-09-06 17:02:37 +08:00
|
|
|
self.connect('create', self.create_new_window)
|
|
|
|
|
2023-09-08 15:06:42 +08:00
|
|
|
# 允许前端 widnow.close() 关闭窗口
|
2023-09-08 17:22:59 +08:00
|
|
|
self.connect('close', self.close_window)
|
|
|
|
win.connect("destroy", self.remove_from_opener) # 通过外部关闭窗口时从父级中移除
|
|
|
|
|
|
|
|
|
|
|
|
def remove_from_opener(self, win = None):
|
|
|
|
if self.opener is not None:
|
|
|
|
try:
|
|
|
|
self.opener.children.remove(self)
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
2023-09-06 17:02:37 +08:00
|
|
|
|
2023-09-08 17:22:59 +08:00
|
|
|
def close_window(self, wv = None):
|
|
|
|
self.remove_from_opener()
|
|
|
|
self.window.close()
|
2023-09-06 17:02:37 +08:00
|
|
|
|
|
|
|
|
2023-09-07 19:58:17 +08:00
|
|
|
# 响应原生js的 window.open
|
2023-09-06 17:02:37 +08:00
|
|
|
def create_new_window(self, webview, nav):
|
|
|
|
req = nav.get_request()
|
2023-09-07 19:58:17 +08:00
|
|
|
return create_same_window(self, req)
|
|
|
|
|
|
|
|
|
|
|
|
# 手动创建窗口
|
|
|
|
def new_window_by_custom(self, options = {}):
|
|
|
|
return create_custom_window(self, options)
|
|
|
|
|
|
|
|
|
|
|
|
def set_root(self, root, has_protocol = False):
|
2023-08-31 16:57:55 +08:00
|
|
|
self.root = root
|
2023-09-07 19:58:17 +08:00
|
|
|
|
|
|
|
if has_protocol:
|
|
|
|
return self
|
2023-08-31 16:57:55 +08:00
|
|
|
return self.use(create_protocal(root))
|
|
|
|
|
2023-09-06 14:16:57 +08:00
|
|
|
|
2023-08-31 16:57:55 +08:00
|
|
|
def use(self, middle_ware = noop, extra = None):
|
|
|
|
middle_ware(self, extra)
|
|
|
|
return self
|
|
|
|
|
|
|
|
|
|
|
|
def load(self, url = '/index.html'):
|
2023-09-07 19:58:17 +08:00
|
|
|
if url.startswith('http://') or url.startswith('https://'):
|
2023-09-07 10:41:42 +08:00
|
|
|
self.load_uri(url)
|
2023-08-31 16:57:55 +08:00
|
|
|
else:
|
2023-09-07 10:41:42 +08:00
|
|
|
if self.root is None:
|
|
|
|
raise EnvironmentError('web root dir not set!')
|
|
|
|
else:
|
2023-09-07 11:39:56 +08:00
|
|
|
if url.startswith('/'):
|
|
|
|
self.load_uri(f"app://{url}")
|
2023-09-07 19:58:17 +08:00
|
|
|
elif url.startswith('app://'):
|
|
|
|
self.load_uri(url)
|
2023-09-07 11:39:56 +08:00
|
|
|
else:
|
2023-09-07 19:58:17 +08:00
|
|
|
raise ValueError('url must starts with "/" or "app://"')
|
2023-08-31 16:57:55 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
2023-09-04 19:11:36 +08:00
|
|
|
def call_js(self, method, data = None, err = None):
|
|
|
|
if err is not None:
|
|
|
|
err = str(err)
|
|
|
|
scripts = 'native.$emit("' + method + '", ' + json.dumps(err) + ', ' + json.dumps(data) + ')'
|
2023-08-31 16:57:55 +08:00
|
|
|
self.evaluate_javascript(scripts, -1)
|
|
|
|
|
|
|
|
|
|
|
|
def called_by_js(self, webview, message):
|
|
|
|
|
|
|
|
data = json.loads(message.get_js_value().to_json(0))
|
|
|
|
|
|
|
|
event = data.get('event')
|
|
|
|
callback = data.get('callback')
|
|
|
|
params = data.get('data')
|
|
|
|
output = None
|
2023-09-04 19:11:36 +08:00
|
|
|
_error = None
|
2023-08-31 16:57:55 +08:00
|
|
|
|
|
|
|
|
|
|
|
match event:
|
2023-09-08 18:38:39 +08:00
|
|
|
|
|
|
|
case 'app':
|
|
|
|
_error, output = self._app_handler(params)
|
2023-09-04 18:29:12 +08:00
|
|
|
|
2023-08-31 16:57:55 +08:00
|
|
|
case 'fs':
|
2023-09-08 18:38:39 +08:00
|
|
|
_error, output = self._fs_handler(params)
|
2023-08-31 16:57:55 +08:00
|
|
|
|
|
|
|
|
|
|
|
case 'clipboard':
|
2023-09-08 18:38:39 +08:00
|
|
|
_error, output = self._clipboard_handler(params)
|
2023-08-31 16:57:55 +08:00
|
|
|
|
|
|
|
# 读取图片, 返回图片像素数据
|
|
|
|
case 'image':
|
|
|
|
filename = params['value']
|
|
|
|
pixbuf = GdkPixbuf.Pixbuf.new_from_file(filename)
|
|
|
|
output = pixbuf_to_dict(pixbuf, filename)
|
|
|
|
|
|
|
|
case 'monitor':
|
|
|
|
if params['action'] == 'get-all':
|
|
|
|
monitor_num = self.display.get_n_monitors()
|
|
|
|
monitors = [self.display.get_monitor(i) for i in range(monitor_num)]
|
|
|
|
output = [get_monitor_info(m) for m in monitors]
|
|
|
|
|
|
|
|
elif params['action'] == 'get-primary':
|
|
|
|
monitor = self.display.get_primary_monitor()
|
|
|
|
output = get_monitor_info(monitor)
|
|
|
|
|
|
|
|
|
|
|
|
case 'keybinder':
|
2023-09-08 18:38:39 +08:00
|
|
|
_error, output = self._keybinder_handler(params)
|
2023-09-06 14:16:57 +08:00
|
|
|
|
2023-08-31 16:57:55 +08:00
|
|
|
|
|
|
|
case 'tray':
|
|
|
|
if params['action'] == 'create':
|
|
|
|
pass
|
|
|
|
|
|
|
|
elif params['action'] == 'remove':
|
|
|
|
pass
|
|
|
|
|
2023-09-08 15:06:42 +08:00
|
|
|
case 'opener':
|
|
|
|
callback = 'opener_message'
|
|
|
|
output = params.get('data')
|
2023-09-08 17:22:59 +08:00
|
|
|
uuid = json.dumps(self.uuid if self.opener else None)
|
|
|
|
scripts = f"native.$emit('opener_message', {json.dumps(output)}, {uuid})"
|
2023-09-08 15:06:42 +08:00
|
|
|
if self.opener is None:
|
|
|
|
self.evaluate_javascript(scripts, -1)
|
|
|
|
else:
|
|
|
|
self.opener.evaluate_javascript(scripts, -1)
|
|
|
|
return
|
2023-09-08 17:22:59 +08:00
|
|
|
|
|
|
|
case 'children':
|
|
|
|
callback = 'opener_message'
|
|
|
|
output = params.get('data')
|
|
|
|
uuid = params.get('uuid')
|
|
|
|
scripts = f"native.$emit('opener_message', {json.dumps(output)})"
|
|
|
|
if len(self.children) == 0:
|
|
|
|
self.evaluate_javascript(scripts, -1)
|
|
|
|
else:
|
|
|
|
if uuid is None:
|
|
|
|
for child in self.children:
|
|
|
|
child.evaluate_javascript(scripts, -1)
|
|
|
|
else:
|
|
|
|
for child in self.children:
|
|
|
|
if child.uuid == uuid:
|
|
|
|
child.evaluate_javascript(scripts, -1)
|
2023-09-08 17:50:10 +08:00
|
|
|
break
|
2023-09-08 17:22:59 +08:00
|
|
|
return
|
2023-09-08 15:06:42 +08:00
|
|
|
|
2023-08-31 16:57:55 +08:00
|
|
|
case 'window':
|
2023-09-08 18:38:39 +08:00
|
|
|
_error, output = self._window_handler(params)
|
2023-08-31 16:57:55 +08:00
|
|
|
|
|
|
|
|
2023-09-06 14:16:57 +08:00
|
|
|
case 'notify':
|
|
|
|
if self.notify is None:
|
|
|
|
_error = ImportError('Notify module not found. Need to install gir1.2-notify-0.7 if you use debian.')
|
|
|
|
else:
|
|
|
|
title = params.get('title')
|
|
|
|
summary = params.get('summary')
|
|
|
|
icon = params.get('icon')
|
|
|
|
progress = params.get('progress')
|
|
|
|
urgency = params.get('urgency')
|
2023-08-31 16:57:55 +08:00
|
|
|
|
2023-09-06 14:16:57 +08:00
|
|
|
self.notify.create(title, summary, icon, progress, urgency, params.get('callback'))
|
2023-08-31 16:57:55 +08:00
|
|
|
|
|
|
|
|
2023-09-06 14:16:57 +08:00
|
|
|
case 'proxy':
|
2023-09-08 18:38:39 +08:00
|
|
|
_error, output = self._proxy_handler(params)
|
2023-08-31 16:57:55 +08:00
|
|
|
|
|
|
|
|
2023-09-06 14:16:57 +08:00
|
|
|
case 'md5':
|
|
|
|
output = hashlib.md5(str(params.get('value'))).hexdigest()
|
2023-08-31 16:57:55 +08:00
|
|
|
|
2023-09-06 15:30:09 +08:00
|
|
|
case _:
|
|
|
|
if self.custom_bridge is None:
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
_error, output = self.custom_bridge(event, params)
|
|
|
|
|
2023-09-06 14:16:57 +08:00
|
|
|
# 有回调则返回结果
|
|
|
|
if callback:
|
|
|
|
self.call_js(callback, output, _error)
|
|
|
|
|
2023-08-31 16:57:55 +08:00
|
|
|
|
2023-09-08 18:38:39 +08:00
|
|
|
def _app_handler(self, params = {}):
|
|
|
|
_error = None
|
|
|
|
output = None
|
|
|
|
match(params.get('action')):
|
|
|
|
# 退出app
|
|
|
|
case 'quit':
|
|
|
|
self.close_window()
|
|
|
|
self.emit('quit')
|
|
|
|
|
|
|
|
case 'relaunch':
|
|
|
|
py = sys.executable
|
|
|
|
os.execl(py, py, *sys.argv)
|
|
|
|
|
|
|
|
return (_error, output)
|
|
|
|
|
2023-08-31 16:57:55 +08:00
|
|
|
|
2023-09-08 18:38:39 +08:00
|
|
|
def _fs_handler(self, params = {}):
|
2023-09-06 14:16:57 +08:00
|
|
|
_error = None
|
|
|
|
output = None
|
|
|
|
filepath = params.get('filepath')
|
2023-08-31 16:57:55 +08:00
|
|
|
|
2023-09-06 14:16:57 +08:00
|
|
|
match(params.get('action')):
|
|
|
|
case 'access':
|
|
|
|
try:
|
2023-09-06 17:02:37 +08:00
|
|
|
file = open(filepath, params.get('mode'))
|
|
|
|
file.close()
|
|
|
|
output = True
|
2023-09-06 14:16:57 +08:00
|
|
|
except Exception as err:
|
|
|
|
output = False
|
|
|
|
|
|
|
|
case 'read':
|
|
|
|
try:
|
|
|
|
with open(filepath, params.get('mode')) as file:
|
|
|
|
output = file.read()
|
|
|
|
if params.get('mode').find('b') > -1:
|
|
|
|
output = list(output)
|
|
|
|
except Exception as err:
|
|
|
|
_error = err
|
|
|
|
|
|
|
|
case 'write':
|
|
|
|
# 调整以支持二进制数据写入
|
|
|
|
try:
|
|
|
|
with open(filepath, params.get('mode')) as file:
|
|
|
|
buff = params['content']
|
|
|
|
|
|
|
|
if params.get('mode').find('b') > -1:
|
|
|
|
buff = bytes(buff)
|
|
|
|
|
|
|
|
output = file.write(buff)
|
|
|
|
except Exception as err:
|
|
|
|
_error = err
|
|
|
|
|
|
|
|
case 'exists':
|
|
|
|
output = os.path.exists(filepath)
|
|
|
|
|
|
|
|
case 'list':
|
|
|
|
with os.scandir(filepath) as entries:
|
|
|
|
output = [{
|
|
|
|
"name": it.name,
|
|
|
|
"path": os.path.join(filepath, it.name),
|
|
|
|
"is_dir": it.is_dir(),
|
|
|
|
"size": it.stat().st_size,
|
|
|
|
"atime": int(it.stat().st_atime),
|
|
|
|
"mtime": int(it.stat().st_mtime),
|
|
|
|
} for it in entries]
|
|
|
|
|
|
|
|
case 'remove':
|
|
|
|
if os.path.isfile(filepath):
|
|
|
|
output = os.remove(filepath)
|
|
|
|
elif os.path.isdir(filepath):
|
|
|
|
output = os.removedirs(filepath)
|
|
|
|
|
|
|
|
case 'rename':
|
|
|
|
if os.path.exists(filepath):
|
|
|
|
output = shutil.move(filepath, params['target'])
|
|
|
|
|
|
|
|
case 'copy':
|
|
|
|
if os.path.exists(filepath):
|
|
|
|
output = shutil.copy2(filepath, params['target'])
|
|
|
|
|
|
|
|
case 'isfile':
|
|
|
|
output = os.path.isfile(filepath)
|
|
|
|
|
|
|
|
case 'isdir':
|
|
|
|
output = os.path.isdir(filepath)
|
|
|
|
|
|
|
|
return (_error, output)
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-09-08 18:38:39 +08:00
|
|
|
def _clipboard_handler(self, params = {}):
|
2023-09-06 14:16:57 +08:00
|
|
|
_error = None
|
|
|
|
output = None
|
2023-08-31 16:57:55 +08:00
|
|
|
|
2023-09-06 14:16:57 +08:00
|
|
|
match(params.get('action')):
|
|
|
|
# 读文本
|
|
|
|
case 'wait_for_text':
|
|
|
|
output = self.clipboard.wait_for_text()
|
|
|
|
|
|
|
|
# 写文本
|
|
|
|
case 'set_text':
|
|
|
|
self.clipboard.set_text(params['value'], -1)
|
|
|
|
|
|
|
|
# 写图片
|
|
|
|
case 'set_image':
|
|
|
|
image = params['value']
|
|
|
|
# 前端传进来的值, 如果是路径的话, 直接读取
|
|
|
|
if type(image) == str:
|
|
|
|
image = GdkPixbuf.Pixbuf.new_from_file(image)
|
|
|
|
else:
|
|
|
|
image = dict_to_pixbuf(image)
|
2023-08-31 16:57:55 +08:00
|
|
|
|
2023-09-06 14:16:57 +08:00
|
|
|
self.clipboard.set_image(image)
|
|
|
|
self.clipboard.store()
|
2023-08-31 16:57:55 +08:00
|
|
|
|
2023-09-06 14:16:57 +08:00
|
|
|
# 读图片
|
|
|
|
case 'wait_for_image':
|
|
|
|
output = self.clipboard.wait_for_image()
|
|
|
|
output = pixbuf_to_dict(output, 'noname.png')
|
2023-08-31 16:57:55 +08:00
|
|
|
|
2023-09-06 14:16:57 +08:00
|
|
|
# 清除剪切板
|
|
|
|
case 'clear':
|
|
|
|
self.clipboard.clear()
|
2023-08-31 16:57:55 +08:00
|
|
|
|
2023-09-06 14:16:57 +08:00
|
|
|
return (_error, output)
|
2023-08-31 16:57:55 +08:00
|
|
|
|
2023-09-06 12:21:56 +08:00
|
|
|
|
2023-09-08 18:38:39 +08:00
|
|
|
def _keybinder_handler(self, params = {}):
|
2023-09-06 14:16:57 +08:00
|
|
|
_error = None
|
|
|
|
output = None
|
|
|
|
keymap = params.get('value')
|
|
|
|
shortcut_callback = params.get('shortcut_callback') or ''
|
|
|
|
|
|
|
|
|
|
|
|
if params['action'] == 'register':
|
|
|
|
# 绑定之前, 先解绑, 避免被重复绑定
|
|
|
|
if Keybinder:
|
|
|
|
Keybinder.unbind(keymap)
|
|
|
|
output = Keybinder.bind(
|
|
|
|
keymap,
|
|
|
|
lambda km : self.call_js(shortcut_callback)
|
|
|
|
)
|
|
|
|
|
|
|
|
elif params['action'] == 'unregister':
|
|
|
|
if Keybinder:
|
|
|
|
Keybinder.unbind(keymap)
|
2023-09-06 12:21:56 +08:00
|
|
|
output = True
|
2023-09-06 14:16:57 +08:00
|
|
|
|
|
|
|
elif params['action'] == 'supported':
|
|
|
|
if Keybinder:
|
|
|
|
output = Keybinder.supported()
|
|
|
|
else:
|
|
|
|
output = False
|
|
|
|
|
|
|
|
return (_error, output)
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-09-08 18:38:39 +08:00
|
|
|
def _window_handler(self, params = {}):
|
2023-09-06 14:16:57 +08:00
|
|
|
_error = None
|
|
|
|
output = None
|
|
|
|
|
|
|
|
match(params.get('action')):
|
2023-09-07 19:58:17 +08:00
|
|
|
|
|
|
|
case 'create':
|
|
|
|
self.new_window_by_custom(params.get('options'))
|
|
|
|
|
2023-09-08 15:06:42 +08:00
|
|
|
case 'close':
|
2023-09-08 17:22:59 +08:00
|
|
|
self.close_window()
|
2023-09-08 15:06:42 +08:00
|
|
|
|
2023-09-06 14:16:57 +08:00
|
|
|
case 'fullscreen':
|
|
|
|
self.window.fullscreen()
|
|
|
|
|
|
|
|
case 'unfullscreen':
|
|
|
|
self.window.unfullscreen()
|
|
|
|
|
|
|
|
case 'maximize':
|
|
|
|
self.window.maximize()
|
|
|
|
|
|
|
|
case 'unmaximize':
|
|
|
|
self.window.unmaximize()
|
|
|
|
|
|
|
|
case 'set_title':
|
|
|
|
self.window.set_title(params['value'] or '')
|
|
|
|
|
|
|
|
case 'resize':
|
|
|
|
self.window.resize(params['value'].get('width'), params['value'].get('height'))
|
|
|
|
|
|
|
|
case 'set_opacity':
|
|
|
|
self.window.set_opacity(params['value'])
|
|
|
|
|
|
|
|
case 'set_keep_above':
|
|
|
|
self.window.set_keep_above(params['value'])
|
|
|
|
|
|
|
|
case 'set_keep_below':
|
|
|
|
self.window.set_keep_below(params['value'])
|
|
|
|
|
|
|
|
case 'move':
|
|
|
|
self.window.move(params['value'].get('x'), params['value'].get('y'))
|
|
|
|
|
|
|
|
case 'toggle_visible':
|
|
|
|
if self.window.is_visible():
|
|
|
|
self.window.hide()
|
2023-09-06 12:21:56 +08:00
|
|
|
else:
|
2023-09-06 14:16:57 +08:00
|
|
|
self.window.present()
|
2023-09-06 12:21:56 +08:00
|
|
|
|
2023-09-06 14:16:57 +08:00
|
|
|
case 'hide':
|
|
|
|
self.window.hide()
|
2023-09-06 12:21:56 +08:00
|
|
|
|
2023-09-06 14:16:57 +08:00
|
|
|
case 'show':
|
|
|
|
self.window.present()
|
|
|
|
|
|
|
|
case 'is_visible':
|
|
|
|
output = self.window.is_visible()
|
|
|
|
|
|
|
|
|
|
|
|
return (_error, output)
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-09-08 18:38:39 +08:00
|
|
|
def _proxy_handler(self, params = {}):
|
2023-09-06 14:16:57 +08:00
|
|
|
dm = self.get_website_data_manager()
|
|
|
|
output = True
|
|
|
|
_error = None
|
|
|
|
if params['action'] == 'disable':
|
|
|
|
dm.set_network_proxy_settings(WebKit2.NetworkProxyMode.NO_PROXY, None)
|
|
|
|
elif params['action'] == 'system':
|
|
|
|
dm.set_network_proxy_settings(WebKit2.NetworkProxyMode.DEFAULT, None)
|
|
|
|
else:
|
|
|
|
try:
|
|
|
|
proxy = WebKit2.NetworkProxySettings(params['url'], params['ignore'])
|
|
|
|
dm.set_network_proxy_settings(WebKit2.NetworkProxyMode.CUSTOM, proxy)
|
|
|
|
except Exception as err:
|
|
|
|
_error = err
|
|
|
|
output = False
|
|
|
|
return (_error, output)
|
2023-08-31 16:57:55 +08:00
|
|
|
|
2023-09-07 19:58:17 +08:00
|
|
|
|