窗口增加uuid属性; 新建窗口增加icon支持;增加父窗口向子窗口发送消息

master
yutent 2023-09-08 17:22:59 +08:00
parent 4ef23a703d
commit 6f7141560a
4 changed files with 79 additions and 13 deletions

View File

@ -37,6 +37,12 @@ def create_custom_window(origin, options):
win.set_wmclass(wmclass, 'WebEngine') win.set_wmclass(wmclass, 'WebEngine')
win.set_title(options.get('title') or '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: if options.get('frame') == False:
win.set_decorated(False) win.set_decorated(False)
@ -50,9 +56,7 @@ def create_custom_window(origin, options):
win.set_resizable(False) win.set_resizable(False)
web = WebEngine(win, origin, options.get('uuid'))
web = WebEngine(win, origin)
web.set_root(origin.root, True) web.set_root(origin.root, True)
web.set_zoom_level(origin.get_zoom_level()) web.set_zoom_level(origin.get_zoom_level())
web.set_settings(origin.get_settings()) web.set_settings(origin.get_settings())

View File

@ -13,13 +13,12 @@ from gi.repository import WebKit2
class Inject: class Inject:
def __init__(self, webview, env = {}): def __init__(self, webview, env = {}):
self.webview = webview
self.manager = webview.get_user_content_manager() self.manager = webview.get_user_content_manager()
script_data = open(self.abspath('./inject.js'), 'r').read() script_data = open(self.abspath('./inject.js'), 'r').read()
frame = WebKit2.UserContentInjectedFrames.ALL_FRAMES frame = WebKit2.UserContentInjectedFrames.ALL_FRAMES
time = WebKit2.UserScriptInjectionTime.END 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) script = WebKit2.UserScript(script_data, frame, time, None, None)
self.manager.add_script(script) self.manager.add_script(script)

View File

@ -3,7 +3,7 @@
# @date 2023/08/08 14:07:26 # @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('Gtk', '3.0')
gi.require_version("WebKit2", "4.1") gi.require_version("WebKit2", "4.1")
@ -61,18 +61,28 @@ class WebEngine(WebKit2.WebView):
'quit': (GObject.SignalFlags.RUN_FIRST, None, ()) 'quit': (GObject.SignalFlags.RUN_FIRST, None, ())
} }
uuid = None
root = None root = None
window = None window = None
opener = None opener = None
children = set()
custom_bridge = None custom_bridge = None
def __init__(self, win, opener = None): def __init__(self, win, opener = None, uuid = None):
WebKit2.WebView.__init__(self) WebKit2.WebView.__init__(self)
if uuid is None:
self.uuid = random.randbytes(8).hex()
else:
self.uuid = uuid
self.opener = opener self.opener = opener
self.window = win self.window = win
if opener is not None:
opener.children.add(self)
if win.get_title() is None: if win.get_title() is None:
win.set_title('WebEngine') win.set_title('WebEngine')
@ -97,9 +107,22 @@ class WebEngine(WebKit2.WebView):
self.connect('create', self.create_new_window) self.connect('create', self.create_new_window)
# 允许前端 widnow.close() 关闭窗口 # 允许前端 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 # 响应原生js的 window.open
def create_new_window(self, webview, nav): def create_new_window(self, webview, nav):
@ -173,7 +196,7 @@ class WebEngine(WebKit2.WebView):
# 退出app # 退出app
case 'quit': case 'quit':
self.window.close() self.close_window()
self.emit('quit') self.emit('quit')
# 读取图片, 返回图片像素数据 # 读取图片, 返回图片像素数据
@ -207,13 +230,31 @@ class WebEngine(WebKit2.WebView):
case 'opener': case 'opener':
callback = 'opener_message' callback = 'opener_message'
output = params.get('data') 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: if self.opener is None:
self.evaluate_javascript(scripts, -1) self.evaluate_javascript(scripts, -1)
else: else:
self.opener.evaluate_javascript(scripts, -1) self.opener.evaluate_javascript(scripts, -1)
return 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': case 'window':
_error, output = self._window_setting(params) _error, output = self._window_setting(params)
@ -402,7 +443,7 @@ class WebEngine(WebKit2.WebView):
self.new_window_by_custom(params.get('options')) self.new_window_by_custom(params.get('options'))
case 'close': case 'close':
self.window.close() self.close_window()
case 'fullscreen': case 'fullscreen':
self.window.fullscreen() self.window.fullscreen()

View File

@ -90,6 +90,19 @@ function base64(str = '') {
return btoa(str).replace(/[+=\/]/g, '') 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 { class NativeImage {
#origin #origin
@ -192,7 +205,7 @@ class EventEmitter {
window.native = new 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, { Object.assign(native, {
env: '{{env}}', env: '{{env}}',
@ -345,12 +358,21 @@ Object.assign(native, {
} }
}, },
opener: { opener: {
//
postMessage(data = {}) { postMessage(data = {}) {
return handler('opener', { action: 'postmessage', data }, NO_CALLBACK) return handler('opener', { action: 'postmessage', data }, NO_CALLBACK)
} }
}, },
children: {
postMessage(data = {}, uuid = null) {
return handler(
'children',
{ action: 'postmessage', data, uuid },
NO_CALLBACK
)
}
},
window: { window: {
uuid: '{{uuid}}',
create(options = {}) { create(options = {}) {
return handler('window', { action: 'create', options }) return handler('window', { action: 'create', options })
}, },