#!/usr/bin/python3 import gi, json, os gi.require_version("Gtk", "3.0") gi.require_version("WebKit2", "4.1") from gi.repository import Gtk, Gdk, WebKit2, GLib from gi.repository.GdkPixbuf import Pixbuf class WebKitWindow(Gtk.Window): def __init__(self): Gtk.Window.__init__(self, title="WebKit Example") self.set_default_size(800, 600) settings = WebKit2.Settings() settings.set_enable_page_cache(True) settings.set_enable_offline_web_application_cache(True) settings.set_property('javascript-can-access-clipboard', True) settings.set_property('javascript-can-open-windows-automatically', True) settings.set_property("user-agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/605.1.15 (KHTML, like Gecko) weapp/1.0.0 Version/16.4 Safari/605.1.15") manager = WebKit2.UserContentManager() script = open(self.file_path('./inject.js'), 'r').read() frame = WebKit2.UserContentInjectedFrames.ALL_FRAMES time = WebKit2.UserScriptInjectionTime.END script = WebKit2.UserScript(script, frame, time, None, None) manager.add_script(script) manager.connect('script-message-received::app', self.on_script_message) manager.register_script_message_handler('app') self.webview = WebKit2.WebView.new_with_user_content_manager(manager) self.webview.set_settings(settings) self.webview.connect("decide-policy", self.on_decide_policy) self.webview.load_uri("http://127.0.0.1:10086/index.html") # self.webview.load_uri("https://benchmark.wkit.fun") self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) self.add(self.webview) def create_tray(self): indicator = Gtk.StatusIcon.new_from_icon_name('youtube') indicator.connect('activate', self.toggle_visible) return indicator def toggle_visible(self, icon): # trayIcon print(icon) if self.is_active(): self.hide() else: self.present() def file_path(self, filepath): root = os.path.dirname(os.path.realpath(__file__)) return os.path.join(root, filepath) def on_script_message(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') match event: case 'fs': pass case 'clipboard': output = None # 读文本 if params['action'] == 'wait_for_text': output = self.clipboard.wait_for_text() # 写文本 elif params['action'] == 'set_text': self.clipboard.set_text(params['value'], -1) # 写图片 elif params['action'] == 'set_image': image = params['value'] # 前端传进来的值, 如果是路径的话, 直接读取 if type(image) == str: image = Pixbuf.new_from_file(image) else: image = Pixbuf.new_from_data( data = bytes(image['bytes']), colorspace = image['colorspace'], has_alpha = image['has_alpha'], bits_per_sample = image['bits_per_sample'], width = image['width'], height = image['height'], rowstride = image['rowstride'] ) self.clipboard.set_image(image) self.clipboard.store() # 清除剪切板 elif params['action'] == 'clear': self.clipboard.clear() # 回调给前端 if callback and output: scripts = 'native.$emit("' + callback + '",' + json.dumps(output) + ')' print(scripts) self.webview.evaluate_javascript(scripts, -1) # 退出app case 'quit': Gtk.main_quit() # 读取图片, 返回图片像素数据 case 'image': filename = params['value'] pixbuf = Pixbuf.new_from_file(filename) image = { "width": pixbuf.get_width(), "height": pixbuf.get_height(), "colorspace": pixbuf.get_colorspace(), "has_alpha": pixbuf. get_has_alpha(), "bits_per_sample": pixbuf.get_bits_per_sample(), "rowstride": pixbuf.get_rowstride(), "filepath": filename, "bytes": list(pixbuf.get_pixels()) } scripts = 'native.$emit("' + callback + '",' + json.dumps(image) + ')' self.webview.evaluate_javascript(scripts, -1) case _: if callback : res = {"foo": 123, "bar": (11,22,33)} scripts = 'native.$emit("' + callback + '",' + json.dumps(res) + ')' print(scripts) self.webview.evaluate_javascript(scripts, -1) def on_decide_policy(self, webview, decision, decision_type): if decision_type == WebKit2.PolicyDecisionType.NAVIGATION_ACTION: navigation_action = decision.get_navigation_action() request = navigation_action.get_request() uri = request.get_uri() if uri == "about:blank": # Open the developer tools window inspector = webview.get_inspector() inspector.show() else: decision.use() win = WebKitWindow() win.connect("destroy", Gtk.main_quit) win.show_all() tray = win.create_tray() Gtk.main()