This repository has been archived on 2023-09-06. You can view files and clone it, but cannot push or open issues/pull-requests.
yutent
/
py-gtk-notes
Archived
1
0
Fork 0
py-gtk-notes/main.py

288 lines
7.9 KiB
Python
Executable File

#!/usr/bin/python3
import gi, json, os
gi.require_version("Gtk", "3.0")
gi.require_version("WebKit2", "4.1")
gi.require_version("Keybinder", "3.0")
from gi.repository import Gtk, Gdk, WebKit2, GLib, Keybinder
from gi.repository.GdkPixbuf import Pixbuf
# 优先尝试使用指示器, 没有再使用 Gtk.StatusIcon
try:
gi.require_version('AyatanaAppIndicator3', '0.1')
# 需要安装这个包 gir1.2-ayatanaappindicator3-0.1
from gi.repository import AyatanaAppIndicator3 as AppIndicator3
except (ValueError, ImportError):
AppIndicator3 = None
# 初始化 Keybinder
Keybinder.init()
def get_monitor_info(monitor):
return {
"model": monitor.props.model,
"scale_factor": monitor.props.scale_factor,
"manufacturer": monitor.props.manufacturer,
"refresh_rate": monitor.props.refresh_rate,
"is_primary": monitor.is_primary(),
"geometry": {
"width": monitor.props.geometry.width,
"height": monitor.props.geometry.height,
"x": monitor.props.geometry.x,
"y": monitor.props.geometry.y,
}
}
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_enable_developer_extras(True)
settings.set_enable_html5_database(True)
settings.set_enable_html5_local_storage(True)
settings.set_javascript_can_access_clipboard(True)
settings.set_javascript_can_open_windows_automatically(True)
settings.set_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.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):
if AppIndicator3 :
indicator = AppIndicator3.Indicator.new(
"youtube",
"youtube",
AppIndicator3.IndicatorCategory.APPLICATION_STATUS
)
indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)
else:
# windows 和 macos 必须传二进制图标, linux可传图标名称(自会去主题中找)
indicator = Gtk.StatusIcon.new_from_pixbuf(get_logo(32))
# linux
indicator = Gtk.StatusIcon.new_from_icon_name('youtube')
return indicator
# 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':
all_quit(self)
# 读取图片, 返回图片像素数据
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.send_message_to_page(WebKit2.UserMessage.new('blabla'))
self.webview.evaluate_javascript(scripts, -1)
case 'monitor':
if params['action'] == 'get-all':
display = Gdk.Display.get_default()
monitor_num = display.get_n_monitors()
monitors = [display.get_monitor(i) for i in range(monitor_num)]
monitors = [get_monitor_info(m) for m in monitors]
scripts = 'native.$emit("' + callback + '",' + json.dumps(monitors) + ')'
self.webview.evaluate_javascript(scripts, -1)
elif params['action'] == 'get-primary':
display = Gdk.Display.get_default()
monitor = display.get_primary_monitor()
info = get_monitor_info(monitor)
scripts = 'native.$emit("' + callback + '",' + json.dumps(info) + ')'
self.webview.evaluate_javascript(scripts, -1)
case 'keybinder':
output = None
keymap = params.get('value')
shortcut_callback = params.get('shortcut_callback') or ''
scripts = 'native.$emit("' + shortcut_callback + '")'
if params['action'] == 'register':
# 绑定之前, 先解绑, 避免被重复绑定
Keybinder.unbind(keymap)
output = Keybinder.bind(
keymap,
lambda km : self.webview.evaluate_javascript('native.$emit("' + shortcut_callback + '")', -1)
)
elif params['action'] == 'register':
pass
elif params['action'] == 'is-registered':
pass
elif params['action'] == 'supported':
output = Keybinder.supported()
scripts = 'native.$emit("' + callback + '",' + json.dumps(output) + ')'
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 all_quit(win):
print('朕要休息了~~~')
Gtk.main_quit()
win = WebKitWindow()
win.connect("destroy", all_quit)
win.show_all()
print(Keybinder.supported())
tray = win.create_tray()
Gtk.main()
python + gtk3 + webkit2 学习笔记
Python 60.1%
JavaScript 37.6%
HTML 2.3%