From b398551debf941e002a229fdf90721d16b299313 Mon Sep 17 00:00:00 2001 From: yutent Date: Tue, 12 Sep 2023 14:28:04 +0800 Subject: [PATCH] =?UTF-8?q?native=E5=AF=B9=E8=B1=A1=E5=8F=8A=E5=B1=9E?= =?UTF-8?q?=E6=80=A7=E6=94=B9=E4=B8=BA=E5=8F=AA=E8=AF=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dist-packages/webengine/gtk3/inject.js | 893 +++++++++--------- 1 file changed, 454 insertions(+), 439 deletions(-) diff --git a/usr/lib/python3/dist-packages/webengine/gtk3/inject.js b/usr/lib/python3/dist-packages/webengine/gtk3/inject.js index ba80e6d..c508c3d 100644 --- a/usr/lib/python3/dist-packages/webengine/gtk3/inject.js +++ b/usr/lib/python3/dist-packages/webengine/gtk3/inject.js @@ -3,488 +3,503 @@ * @author yutent * @date 2023/07/21 17:38:11 */ +!(function () { + const MIME_TYPES = { + html: 'text/html', + json: 'application/json', + js: 'application/javascript', + htm: 'text/html', + txt: 'text/plain', + css: 'text/css', + webp: 'image/webp', + jpg: 'image/jpg', + jpeg: 'image/jpeg', + png: 'image/png', + gif: 'image/gif', + svg: 'image/svg+xml', + ico: 'image/ico', + mp3: 'audio/mpeg', + ogg: 'audio/ogg', + m4a: 'audio/m4a', + amr: 'audio/amr', + mp4: 'video/mp4', + webm: 'video/webm', + wasm: 'application/wasm', + asm: 'application/asm', + zip: 'application/zip', + '7z': 'application/x-7z-compressed', + eot: 'application/vnd.ms-fontobject', + ttf: 'font/ttf', + otf: 'font/otf', + woff: 'font/woff', + woff2: 'font/woff2', + xls: 'application/vnd.ms-excel', + doc: 'application/msword', + xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' + } + const KEYS_MAP = { + shift: '', + ctrl: '', + alt: '', + super: '' + } -const MIME_TYPES = { - html: 'text/html', - json: 'application/json', - js: 'application/javascript', - htm: 'text/html', - txt: 'text/plain', - css: 'text/css', - webp: 'image/webp', - jpg: 'image/jpg', - jpeg: 'image/jpeg', - png: 'image/png', - gif: 'image/gif', - svg: 'image/svg+xml', - ico: 'image/ico', - mp3: 'audio/mpeg', - ogg: 'audio/ogg', - m4a: 'audio/m4a', - amr: 'audio/amr', - mp4: 'video/mp4', - webm: 'video/webm', - wasm: 'application/wasm', - asm: 'application/asm', - zip: 'application/zip', - '7z': 'application/x-7z-compressed', - eot: 'application/vnd.ms-fontobject', - ttf: 'font/ttf', - otf: 'font/otf', - woff: 'font/woff', - woff2: 'font/woff2', - xls: 'application/vnd.ms-excel', - doc: 'application/msword', - xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' -} -const KEYS_MAP = { - shift: '', - ctrl: '', - alt: '', - super: '' -} + const NO_CALLBACK = false + const CALL_ONCE = true -const NO_CALLBACK = false -const CALL_ONCE = true + const __events__ = Symbol('events') -function defer() { - let obj = {} - obj.promise = new Promise((resolve, reject) => { - obj.resolve = resolve - obj.reject = reject - }) - return obj -} + function defer() { + let obj = {} + obj.promise = new Promise((resolve, reject) => { + obj.resolve = resolve + obj.reject = reject + }) + return obj + } -function rand(prefix = 'cb_') { - return prefix + Math.random().toString().slice(2) -} + function rand(prefix = 'cb_') { + return prefix + Math.random().toString().slice(2) + } -function handler(event, data = {}, need = CALL_ONCE) { - let _ = defer() - let callback + function handler(event, data = {}, need = CALL_ONCE) { + let _ = defer() + let callback - if (need === NO_CALLBACK) { - _.resolve(true) - } else { - callback = rand() - native.$once(callback, (err, res) => { - if (err) { - _.reject(err) - } else { - _.resolve(res) + if (need === NO_CALLBACK) { + _.resolve(true) + } else { + callback = rand() + native.$once(callback, (err, res) => { + if (err) { + _.reject(err) + } else { + _.resolve(res) + } + }) + } + + window.webkit.messageHandlers.app.postMessage({ + event, + data, + callback + }) + return _.promise + } + + 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) + } + + function readonly(obj, key, value) { + Object.defineProperty(obj, key, { + get() { + return value + }, + enumerable: false + }) } - window.webkit.messageHandlers.app.postMessage({ - event, - data, - callback - }) - return _.promise -} + function _extend(origin, options = {}) { + for (let k in options) { + readonly(origin, k, options[k]) + } + } -function base64(str = '') { - return btoa(str).replace(/[+=\/]/g, '') -} + class NativeImage { + #origin -function _postMessage(data = {}, uuid = null) { - let ev = new Event('message') - Object.assign(ev, { - data, - source: { - postMessage(msg) { - native.children.postMessage(msg, uuid) + constructor(obj) { + this.#origin = obj + this.width = obj.width + this.height = obj.height + this.type = MIME_TYPES[obj.filepath.split('.').pop()] + } + + toJSON() { + return this.#origin + } + + export(type, base64) { + let _ = defer() + let canvas = document.createElement('canvas') + canvas.width = this.width + canvas.height = this.height + let ctx = canvas.getContext('2d') + let imgData = ctx.getImageData(0, 0, this.width, this.height) + let data = imgData.data + + for (let i = 0; i < this.#origin.bytes.length; i += 4) { + imgData.data[i] = this.#origin.bytes[i] + imgData.data[i + 1] = this.#origin.bytes[i + 1] + imgData.data[i + 2] = this.#origin.bytes[i + 2] + imgData.data[i + 3] = this.#origin.bytes[i + 3] } - } - }) - window.dispatchEvent(ev) -} -function readonly(obj, key, value) { - Object.defineProperty(obj, key, { - get() { - return value - }, - enumerable: false - }) -} + ctx.putImageData(imgData, 0, 0) -class NativeImage { - #origin - - constructor(obj) { - this.#origin = obj - this.width = obj.width - this.height = obj.height - this.type = MIME_TYPES[obj.filepath.split('.').pop()] - } - - toJSON() { - return this.#origin - } - - export(type, base64) { - let _ = defer() - let canvas = document.createElement('canvas') - canvas.width = this.width - canvas.height = this.height - let ctx = canvas.getContext('2d') - let imgData = ctx.getImageData(0, 0, this.width, this.height) - let data = imgData.data - - for (let i = 0; i < this.#origin.bytes.length; i += 4) { - imgData.data[i] = this.#origin.bytes[i] - imgData.data[i + 1] = this.#origin.bytes[i + 1] - imgData.data[i + 2] = this.#origin.bytes[i + 2] - imgData.data[i + 3] = this.#origin.bytes[i + 3] - } - - ctx.putImageData(imgData, 0, 0) - - if (base64) { - return canvas.toDataURL(type || this.type, 1) - } else { - canvas.toBlob(_.resolve, type || this.type, 1) - return _.promise - } - } - - toPNG() { - return this.export('image/png') - } - - toJPEG() { - return this.export('image/jpeg') - } - - toDataURL(type) { - return this.export(type, true) - } -} - -class EventEmitter { - // - __events__ = Object.create(null) - - $on(name, fn) { - if (this.__events__[name]) { - this.__events__[name].push(fn) - } else { - this.__events__[name] = [fn] - } - } - - $once(name, fn) { - fn.__once__ = true - this.$on(name, fn) - } - - $off(name, fn) { - if (this.__events__[name]) { - if (fn) { - this.__events__[name] = this.__events__[name].filter(it => it !== fn) + if (base64) { + return canvas.toDataURL(type || this.type, 1) } else { - this.__events__[name] = [] + canvas.toBlob(_.resolve, type || this.type, 1) + return _.promise } } + + toPNG() { + return this.export('image/png') + } + + toJPEG() { + return this.export('image/jpeg') + } + + toDataURL(type) { + return this.export(type, true) + } } - $emit(name, ...args) { - if (this.__events__[name]) { - for (let fn of this.__events__[name]) { - try { - fn.apply(this, args) - if (fn.__once__) { - this.$off(name, fn) - } - } catch (e) { - console.error(e) + class Native { + // + [__events__] = Object.create(null) + + $on(name, fn) { + if (this[__events__][name]) { + this[__events__][name].push(fn) + } else { + this[__events__][name] = [fn] + } + } + + $once(name, fn) { + fn.__once__ = true + this.$on(name, fn) + } + + $off(name, fn) { + if (this[__events__][name]) { + if (fn) { + this[__events__][name] = this[__events__][name].filter( + it => it !== fn + ) + } else { + this[__events__][name] = [] } } } - } - $destroy() { - this.__events__ = Object.create(null) - } -} - -readonly(window, 'native', new EventEmitter()) - -native.$on('opener_message', (data, uuid) => _postMessage(data, uuid)) - -Object.assign(native, { - env: '{{env}}', - app: { - name: '{{app_name}}', - version: '{{app_version}}', - quit() { - return handler('app', { action: 'quit' }, NO_CALLBACK) - }, - relaunch() { - return handler('app', { action: 'relaunch' }, NO_CALLBACK) - }, - getLocale() { - return native.env.LANG - } - }, - fs: { - access(filepath, mode = 'r') { - return handler('fs', { action: 'access', mode, filepath }) - }, - - read(filepath, mode = 'r') { - return handler('fs', { action: 'read', mode, filepath }).then(r => - mode.includes('b') ? new Uint8Array(r) : r - ) - }, - write(filepath, content = '', mode = 'w') { - return handler('fs', { - action: 'write', - mode, - filepath, - content - }) - }, - append(filepath, content = '', mode = 'a+') { - return handler('fs', { - action: 'write', - mode, - filepath, - content - }) - }, - exists(filepath) { - return handler('fs', { action: 'exists', filepath }) - }, - list(filepath) { - return handler('fs', { action: 'list', filepath }) - }, - isfile(filepath) { - return handler('fs', { action: 'isfile', filepath }) - }, - isdir(filepath) { - return handler('fs', { action: 'isdir', filepath }) - }, - remove(filepath) { - return handler('fs', { action: 'remove', filepath }) - }, - rename(filepath, target) { - return handler('fs', { action: 'rename', filepath, target }) - }, - copy(filepath, target) { - return handler('fs', { action: 'copy', filepath, target }) - }, - mkdir(filepath) { - return handler('fs', { action: 'mkdir', filepath }) - } - }, - image(filepath) { - return handler('image', { value: filepath }).then(r => new NativeImage(r)) - }, - clipboard: { - readText() { - return handler('clipboard', { action: 'wait_for_text' }) - }, - writeText(value) { - return handler('clipboard', { action: 'set_text', value }, NO_CALLBACK) - }, - readImage() { - return handler('clipboard', { action: 'wait_for_image' }).then(r => - r ? new NativeImage(r) : r - ) - }, - writeImage(value) { - // 暂不知原因, postMessage传给Gtk后, JSON.stringify()并未读取toJSON的结果 - if (typeof value === 'object') { - value = value.toJSON() - } - return handler('clipboard', { action: 'set_image', value }, NO_CALLBACK) - }, - clear() { - return handler('clipboard', { action: 'clear' }, NO_CALLBACK) - } - }, - screen: { - getAllDisplays() { - return handler('monitor', { action: 'get-all' }) - }, - getPrimaryDisplay() { - return handler('monitor', { action: 'get-primary' }) - } - }, - globalShortcut: { - get enabled() { - return handler('keybinder', { action: 'supported' }) - }, - register(keyMap, callback) { - let shortcut_callback = base64(keyMap) - native.$off(shortcut_callback) - native.$on(shortcut_callback, callback) - return handler('keybinder', { - action: 'register', - value: keyMap, - shortcut_callback - }) - }, - unregister(keyMap) { - let shortcut_callback = base64(keyMap) - native.$off(shortcut_callback) - return handler('keybinder', { action: 'unregister', value: keyMap }) - }, - unregisterAll(keyMaps) { - for (let it of keyMaps) { - this.unregister(it) + $emit(name, ...args) { + if (this[__events__][name]) { + for (let fn of this[__events__][name]) { + try { + fn.apply(this, args) + if (fn.__once__) { + this.$off(name, fn) + } + } catch (e) { + console.error(e) + } + } } } - }, - tray: { - create() { - // - }, - remove() { - // - }, - /** - * 设置普通状态的tray图标, 只需要传名称, 自动会去当前主题下去找 - */ - set_icon(name) { - return handler('tray', { action: 'set_icon', value: name }) - }, - - /** - * 设置警示图标, 同上 - */ - set_attention_icon(name) { - return handler('tray', { action: 'set_attention_icon', value: name }) - }, - - /** - * - */ - set_title(title) { - return handler('tray', { action: 'set_title', value: title }) - }, - - /** - * 修改tray图标状态 - * @param status 0: 隐藏, 1: 显示, 2: 重要(对应上面的attention_icon) - */ - set_status(status) { - return handler('tray', { action: 'set_status', value: status }) + $destroy() { + this[__events__] = Object.create(null) } - }, - 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 }) - }, + } - close() { - return handler('window', { action: 'close' }) - }, + readonly(window, 'native', new Native()) - isVisible() { - return handler('window', { action: 'is_visible' }) + native.$on('opener_message', (data, uuid) => _postMessage(data, uuid)) + + _extend(native, { + env: '{{env}}', + app: { + name: '{{app_name}}', + version: '{{app_version}}', + quit() { + return handler('app', { action: 'quit' }, NO_CALLBACK) + }, + relaunch() { + return handler('app', { action: 'relaunch' }, NO_CALLBACK) + }, + getLocale() { + return native.env.LANG + } }, - toggleVisible() { - handler('window', { action: 'toggle_visible' }, NO_CALLBACK) + fs: { + access(filepath, mode = 'r') { + return handler('fs', { action: 'access', mode, filepath }) + }, + + read(filepath, mode = 'r') { + return handler('fs', { action: 'read', mode, filepath }).then(r => + mode.includes('b') ? new Uint8Array(r) : r + ) + }, + write(filepath, content = '', mode = 'w') { + return handler('fs', { + action: 'write', + mode, + filepath, + content + }) + }, + append(filepath, content = '', mode = 'a+') { + return handler('fs', { + action: 'write', + mode, + filepath, + content + }) + }, + exists(filepath) { + return handler('fs', { action: 'exists', filepath }) + }, + list(filepath) { + return handler('fs', { action: 'list', filepath }) + }, + isfile(filepath) { + return handler('fs', { action: 'isfile', filepath }) + }, + isdir(filepath) { + return handler('fs', { action: 'isdir', filepath }) + }, + remove(filepath) { + return handler('fs', { action: 'remove', filepath }) + }, + rename(filepath, target) { + return handler('fs', { action: 'rename', filepath, target }) + }, + copy(filepath, target) { + return handler('fs', { action: 'copy', filepath, target }) + }, + mkdir(filepath) { + return handler('fs', { action: 'mkdir', filepath }) + } }, - hide() { - handler('window', { action: 'hide' }, NO_CALLBACK) + image(filepath) { + return handler('image', { value: filepath }).then(r => new NativeImage(r)) }, - show() { - handler('window', { action: 'show' }, NO_CALLBACK) + clipboard: { + readText() { + return handler('clipboard', { action: 'wait_for_text' }) + }, + writeText(value) { + return handler('clipboard', { action: 'set_text', value }, NO_CALLBACK) + }, + readImage() { + return handler('clipboard', { action: 'wait_for_image' }).then(r => + r ? new NativeImage(r) : r + ) + }, + writeImage(value) { + // 暂不知原因, postMessage传给Gtk后, JSON.stringify()并未读取toJSON的结果 + if (typeof value === 'object') { + value = value.toJSON() + } + return handler('clipboard', { action: 'set_image', value }, NO_CALLBACK) + }, + clear() { + return handler('clipboard', { action: 'clear' }, NO_CALLBACK) + } }, - fullscreen() { - handler('window', { action: 'fullscreen' }, NO_CALLBACK) + screen: { + getAllDisplays() { + return handler('monitor', { action: 'get-all' }) + }, + getPrimaryDisplay() { + return handler('monitor', { action: 'get-primary' }) + } }, - unfullscreen() { - handler('window', { action: 'unfullscreen' }, NO_CALLBACK) + globalShortcut: { + get enabled() { + return handler('keybinder', { action: 'supported' }) + }, + register(keyMap, callback) { + let shortcut_callback = base64(keyMap) + native.$off(shortcut_callback) + native.$on(shortcut_callback, callback) + return handler('keybinder', { + action: 'register', + value: keyMap, + shortcut_callback + }) + }, + unregister(keyMap) { + let shortcut_callback = base64(keyMap) + native.$off(shortcut_callback) + return handler('keybinder', { action: 'unregister', value: keyMap }) + }, + unregisterAll(keyMaps) { + for (let it of keyMaps) { + this.unregister(it) + } + } }, - maximize() { - handler('window', { action: 'maximize' }, NO_CALLBACK) + tray: { + create() { + // + }, + remove() { + // + }, + + /** + * 设置普通状态的tray图标, 只需要传名称, 自动会去当前主题下去找 + */ + set_icon(name) { + return handler('tray', { action: 'set_icon', value: name }) + }, + + /** + * 设置警示图标, 同上 + */ + set_attention_icon(name) { + return handler('tray', { action: 'set_attention_icon', value: name }) + }, + + /** + * + */ + set_title(title) { + return handler('tray', { action: 'set_title', value: title }) + }, + + /** + * 修改tray图标状态 + * @param status 0: 隐藏, 1: 显示, 2: 重要(对应上面的attention_icon) + */ + set_status(status) { + return handler('tray', { action: 'set_status', value: status }) + } }, - unmaximize() { - handler('window', { action: 'unmaximize' }, NO_CALLBACK) + opener: { + postMessage(data = {}) { + return handler('opener', { action: 'postmessage', data }, NO_CALLBACK) + } }, - setTitle(title = '') { - handler('window', { action: 'set_title', value: title }, NO_CALLBACK) + children: { + postMessage(data = {}, uuid = null) { + return handler( + 'children', + { action: 'postmessage', data, uuid }, + NO_CALLBACK + ) + } }, - resize(width = 0, height = 0) { + window: { + uuid: '{{uuid}}', + create(options = {}) { + return handler('window', { action: 'create', options }) + }, + + close() { + return handler('window', { action: 'close' }) + }, + + isVisible() { + return handler('window', { action: 'is_visible' }) + }, + toggleVisible() { + handler('window', { action: 'toggle_visible' }, NO_CALLBACK) + }, + hide() { + handler('window', { action: 'hide' }, NO_CALLBACK) + }, + show() { + handler('window', { action: 'show' }, NO_CALLBACK) + }, + fullscreen() { + handler('window', { action: 'fullscreen' }, NO_CALLBACK) + }, + unfullscreen() { + handler('window', { action: 'unfullscreen' }, NO_CALLBACK) + }, + maximize() { + handler('window', { action: 'maximize' }, NO_CALLBACK) + }, + unmaximize() { + handler('window', { action: 'unmaximize' }, NO_CALLBACK) + }, + setTitle(title = '') { + handler('window', { action: 'set_title', value: title }, NO_CALLBACK) + }, + resize(width = 0, height = 0) { + handler( + 'window', + { action: 'resize', value: { width, height } }, + NO_CALLBACK + ) + }, + move(x = 0, y = 0) { + handler('window', { action: 'move', value: { x, y } }, NO_CALLBACK) + }, + setOpacity(opacity = 1) { + handler( + 'window', + { action: 'set_opacity', value: opacity }, + NO_CALLBACK + ) + }, + alwayOnTop(setting = true) { + handler( + 'window', + { action: 'set_keep_above', value: setting }, + NO_CALLBACK + ) + }, + alwayOnBotttom(setting = true) { + handler( + 'window', + { action: 'set_keep_below', value: setting }, + NO_CALLBACK + ) + } + }, + notify({ title, summary, icon, progress = 0, urgency = 0, callback }) { + let eventName + if (callback) { + eventName = rand() + native.$once(eventName, callback) + } handler( - 'window', - { action: 'resize', value: { width, height } }, + 'notify', + { title, summary, icon, progress, urgency, callback: eventName }, NO_CALLBACK ) }, - move(x = 0, y = 0) { - handler('window', { action: 'move', value: { x, y } }, NO_CALLBACK) - }, - setOpacity(opacity = 1) { - handler('window', { action: 'set_opacity', value: opacity }, NO_CALLBACK) - }, - alwayOnTop(setting = true) { - handler( - 'window', - { action: 'set_keep_above', value: setting }, - NO_CALLBACK - ) - }, - alwayOnBotttom(setting = true) { - handler( - 'window', - { action: 'set_keep_below', value: setting }, - NO_CALLBACK - ) - } - }, - notify({ title, summary, icon, progress = 0, urgency = 0, callback }) { - let eventName - if (callback) { - eventName = rand() - native.$once(eventName, callback) - } - handler( - 'notify', - { title, summary, icon, progress, urgency, callback: eventName }, - NO_CALLBACK - ) - }, - md5(value = '') { - return handler('md5', { value }) - }, - - proxy: { - disable() { - return handler('proxy', { action: 'disable' }, NO_CALLBACK) + md5(value = '') { + return handler('md5', { value }) }, - system() { - return handler('proxy', { action: 'system' }, NO_CALLBACK) - }, - custom(url = '', ignore = null) { - return handler('proxy', { action: 'enable', url, ignore }, NO_CALLBACK) - } - }, - handler -}) + proxy: { + disable() { + return handler('proxy', { action: 'disable' }, NO_CALLBACK) + }, + system() { + return handler('proxy', { action: 'system' }, NO_CALLBACK) + }, + custom(url = '', ignore = null) { + return handler('proxy', { action: 'enable', url, ignore }, NO_CALLBACK) + } + }, + + handler + }) +})()