diff --git a/usr/lib/python3/dist-packages/webengine/gtk3/_custom_window.py b/usr/lib/python3/dist-packages/webengine/gtk3/_custom_window.py index 86197ba..adbfe34 100644 --- a/usr/lib/python3/dist-packages/webengine/gtk3/_custom_window.py +++ b/usr/lib/python3/dist-packages/webengine/gtk3/_custom_window.py @@ -37,6 +37,12 @@ def create_custom_window(origin, options): win.set_wmclass(wmclass, 'WebEngine') win.set_title(options.get('title') or 'WebEngine') + if options.get('icon_path'): + win.set_icon_from_file(options['icon_path']) + + if options.get('icon'): + win.set_icon_name(options['icon']) + if options.get('frame') == False: win.set_decorated(False) @@ -50,9 +56,7 @@ def create_custom_window(origin, options): win.set_resizable(False) - - - web = WebEngine(win, origin) + web = WebEngine(win, origin, options.get('uuid')) web.set_root(origin.root, True) web.set_zoom_level(origin.get_zoom_level()) web.set_settings(origin.get_settings()) diff --git a/usr/lib/python3/dist-packages/webengine/gtk3/_inject.py b/usr/lib/python3/dist-packages/webengine/gtk3/_inject.py index 21c8368..f58a4a7 100644 --- a/usr/lib/python3/dist-packages/webengine/gtk3/_inject.py +++ b/usr/lib/python3/dist-packages/webengine/gtk3/_inject.py @@ -13,13 +13,12 @@ from gi.repository import WebKit2 class Inject: def __init__(self, webview, env = {}): - self.webview = webview self.manager = webview.get_user_content_manager() script_data = open(self.abspath('./inject.js'), 'r').read() frame = WebKit2.UserContentInjectedFrames.ALL_FRAMES time = WebKit2.UserScriptInjectionTime.END - script_data = script_data.replace("'{{env}}'", json.dumps(env)) + script_data = script_data.replace("'{{env}}'", json.dumps(env)).replace("{{uuid}}", webview.uuid) script = WebKit2.UserScript(script_data, frame, time, None, None) self.manager.add_script(script) diff --git a/usr/lib/python3/dist-packages/webengine/gtk3/_webengine.py b/usr/lib/python3/dist-packages/webengine/gtk3/_webengine.py index 1e8be75..27fa22a 100644 --- a/usr/lib/python3/dist-packages/webengine/gtk3/_webengine.py +++ b/usr/lib/python3/dist-packages/webengine/gtk3/_webengine.py @@ -3,7 +3,7 @@ # @date 2023/08/08 14:07:26 -import gi, os, json, shutil, hashlib +import gi, os, json, shutil, hashlib, random gi.require_version('Gtk', '3.0') gi.require_version("WebKit2", "4.1") @@ -61,18 +61,28 @@ class WebEngine(WebKit2.WebView): 'quit': (GObject.SignalFlags.RUN_FIRST, None, ()) } + uuid = None root = None window = None opener = None + children = set() custom_bridge = None - def __init__(self, win, opener = None): + def __init__(self, win, opener = None, uuid = None): WebKit2.WebView.__init__(self) + if uuid is None: + self.uuid = random.randbytes(8).hex() + else: + self.uuid = uuid + self.opener = opener self.window = win + if opener is not None: + opener.children.add(self) + if win.get_title() is None: win.set_title('WebEngine') @@ -97,9 +107,22 @@ class WebEngine(WebKit2.WebView): self.connect('create', self.create_new_window) # 允许前端 widnow.close() 关闭窗口 - self.connect('close', lambda w: win.close()) + 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 + + + def close_window(self, wv = None): + self.remove_from_opener() + self.window.close() + # 响应原生js的 window.open def create_new_window(self, webview, nav): @@ -173,7 +196,7 @@ class WebEngine(WebKit2.WebView): # 退出app case 'quit': - self.window.close() + self.close_window() self.emit('quit') # 读取图片, 返回图片像素数据 @@ -207,12 +230,30 @@ class WebEngine(WebKit2.WebView): case 'opener': callback = 'opener_message' output = params.get('data') - scripts = 'native.$emit("opener_message", ' + json.dumps(output) + ')' + uuid = json.dumps(self.uuid if self.opener else None) + scripts = f"native.$emit('opener_message', {json.dumps(output)}, {uuid})" if self.opener is None: self.evaluate_javascript(scripts, -1) else: self.opener.evaluate_javascript(scripts, -1) return + + 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) + return case 'window': _error, output = self._window_setting(params) @@ -402,7 +443,7 @@ class WebEngine(WebKit2.WebView): self.new_window_by_custom(params.get('options')) case 'close': - self.window.close() + self.close_window() case 'fullscreen': self.window.fullscreen() diff --git a/usr/lib/python3/dist-packages/webengine/gtk3/inject.js b/usr/lib/python3/dist-packages/webengine/gtk3/inject.js index 0290976..120a8d4 100644 --- a/usr/lib/python3/dist-packages/webengine/gtk3/inject.js +++ b/usr/lib/python3/dist-packages/webengine/gtk3/inject.js @@ -90,6 +90,19 @@ function base64(str = '') { return btoa(str).replace(/[+=\/]/g, '') } +function _postMessage(data = {}, uuid = null) { + let ev = new Event('message') + Object.assign(ev, { + data, + source: { + postMessage(msg) { + native.children.postMessage(msg, uuid) + } + } + }) + window.dispatchEvent(ev) +} + class NativeImage { #origin @@ -192,7 +205,7 @@ class EventEmitter { window.native = new EventEmitter() -native.$on('opener_message', data => window.postMessage(data)) +native.$on('opener_message', (data, uuid) => _postMessage(data, uuid)) Object.assign(native, { env: '{{env}}', @@ -345,12 +358,21 @@ Object.assign(native, { } }, opener: { - // postMessage(data = {}) { return handler('opener', { action: 'postmessage', data }, NO_CALLBACK) } }, + children: { + postMessage(data = {}, uuid = null) { + return handler( + 'children', + { action: 'postmessage', data, uuid }, + NO_CALLBACK + ) + } + }, window: { + uuid: '{{uuid}}', create(options = {}) { return handler('window', { action: 'create', options }) },