阅读:1886回复:5
gnome45桌面输入法扩展失效的问题
运行在archlinux上,只是用小小不使用任何输入法框架
gnome升级到45之后小小的gnome扩展就无法使用了,即使在扩展的配置文件中添加了gnome45的版本号也没用。提示信息如下图 图片:截图 2023-10-10 09-50-29.png 我自己修改了一部分导入,但还是不能用。还希望周先生提供支持 import GLib from 'gi://GLib'; import Gio from 'gi://Gio'; import GObject from 'gi://GObject'; import St from 'gi://St'; import * as Main from 'resource:///org/gnome/shell/ui/main.js'; import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; |
|
地板#
发布于:2023-10-10 11:51
dgod:我在等fedora升级到gnome45,现在暂时没这个环境。https://gjs.guide/extensions/upgrading/gnome-shell-45.html#esm 这是我找到的一些官方资料,但是我的道行比较浅消化不了 |
|
4楼#
发布于:2023-10-10 12:06
你export default一下看看,constructor可能也得改
constructor(meta){ this._uuid = meta.uuid; this._icons=[]; this._state=0; this._pid=0; this._win={}; this._signal_ids={}; } |
|
5楼#
发布于:2023-10-10 14:21
dgod:你export default一下看看,constructor可能也得改问题已解决,代码如下: import GLib from 'gi://GLib'; import Gio from 'gi://Gio'; import GObject from 'gi://GObject'; import St from 'gi://St'; import * as ExtensionUtils from 'resource:///org/gnome/shell/misc/extensionUtils.js'; import * as Main from 'resource:///org/gnome/shell/ui/main.js'; import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; const utils={ read(stream,count){ return new Promise(function(resolve,reject){ stream.read_bytes_async(count,0,null,function(source,res){ try{ var bytes=stream.read_bytes_finish(res).toArray(); if(bytes.length!=count){ reject(new Error("length not match")); return; } resolve(bytes); }catch(e){ reject(e); } }); }); }, async readInto(stream,count,buf,offset){ var temp=await this.read(stream,count); buf.set(temp,offset); }, write(stream,data,length){ return new Promise(function(resolve,reject){ if(length && length<data.length) data=data.subarray(0,length); stream.write_all_async(data,0,null,function(source,res){ try{ var [ok,bytes_written]=stream.write_all_finish(res); if(!ok || bytes_written!=data.length){ reject(new Error("write all fail")); return; } resolve(); }catch(e){ reject(e); } }); }); }, readTextFile(path){ const file=Gio.File.new_for_path(path); return new Promise((resolve)=>{ file.load_contents_async(null,(file_,res)=>{ try{ let [,contents]=file.load_contents_finish(res); var decoder=new TextDecoder(); resolve(decoder.decode(contents)); }catch(e){ resolve(null); } }); }); }, readIcon(path){ let icon; if(!this._icons) this._icons={}; if(this._icons[path]) return this._icons[path]; const file=Gio.File.new_for_path(path); icon=Gio.FileIcon.new(file); this._icons[path]=icon; return icon; }, setenv(o){ for(let k in o){ let v=o[k]; GLib.setenv(k,v,true); try{ let cmd=`systemctl --user set-environment ${k}=${v}`; GLib.spawn_command_line_async(cmd); }catch(e){ } } } }; class _LCallBuf{ constructor(){ this.MAGIC=0x4321; this.BUF_SIZE=1024; _LCallBuf.FLAG_SYNC=0x01; this.size=0; this.pos=0; this.data=new ArrayBuffer(this.BUF_SIZE); this.view=new DataView(this.data); this.u8=new Uint8Array(this.data); this.encoder=null; this.decoder=null; } start(seq,name,flag){ this.view.setUint16(0,0x4321,true); this.view.setUint16(2,seq,true); this.view.setUint16(4,0,true); this.view.setUint16(6,flag||0,true); this.pos=8; this.put(name); } stop(){ this.size=this.pos; this.view.setUint16(4,this.pos,true); } reset(){ this.size=0; this.pos=0; } put(v){ if(v===undefined || v===null) return; if(Array.isArray(v)){ for(var i=0;i<v.length;i++){ this.put(v[i]); } return; } if(typeof(v)=='number'){ this.pos=(this.pos+3)&~3; this.view.setInt32(this.pos,v,true); this.pos+=4; }else if(typeof(v)=='string'){ if(!this.encoder) this.encoder=new TextEncoder(); var {written}=this.encoder.encodeInto(v,this.u8.subarray(this.pos)); this.pos+=written; this.data[this.pos++]=0; }else{ throw Error("invalid type"); } } get_seq(){ return this.view.getUint16(2,true); } get_flag(){ return this.view.getUint16(6,true); } get_int(){ this.pos=(this.pos+3)&~3; if(this.size-this.pos<4) throw Error("not enough space"); var r=this.view.getInt32(this.pos,true); this.pos+=4; return r; } get_string(){ if(!this.TextDecoder) this.decoder=new TextDecoder(); for(var end=this.pos;end<this.size;end++){ if(this.u8[end]==0) break; } var r=this.decoder.decode(this.u8.subarray(this.pos,end)); this.pos=end+1; return r; } get_param(param){ var r=[]; if(!param) return r; for(var i=0;i<param.length;i++){ switch(param[i]){ case 'i': r.push(this.get_int()); break; case 's': r.push(this.get_string()); break; default: throw Error("invalid param type"); } } return r; } async read(stream){ await utils.readInto(stream,8,this.u8,0); if(this.view.getUint16(0,true)!=this.MAGIC) throw Error("invalid magic"); var len=this.view.getUint16(4,true); if(len<10 || len>this.BUF_SIZE) throw Error("invalid len"); await utils.readInto(stream,len-8,this.u8,8); this.size=len; this.pos=8; } write(stream){ return utils.write(stream,this.u8,this.size); } } class LLock{ constructor(){ this.queue=[]; } lock(){ return new Promise(resolve=>{ this.queue.push(resolve); if(this.queue.length==1){ resolve(); return; } }); } unlock(){ this.queue.shift(); if(this.queue.length==0) return; this.queue[0](); } } const LCall={ _conn:null, _tmr:undefined, _seq:0, _lock:new LLock(), _wait:[], _func:{}, init(){ utils.setenv({ GTK_IM_MODULE:'yong', QT_IM_MODULE:'yong', XIM: 'yong', XMODIFIERS: '@im=yong' }); this.connect(); }, destroy(){ this._wait.length=0; if(this._tmr){ clearTimeout(this._tmr); this._tmr=undefined; } if(this._conn){ this._conn.close(null); } if(this.onclose) this.onclose(); }, connect(){ this._tmr=undefined; var client=Gio.SocketClient.new(); client.connect_async(Gio.UnixSocketAddress.new("/tmp/yong-:0"),null,(source_object,res)=>{ try{ this._conn=client.connect_finish(res); }catch(e){ //console.log(e); this._tmr=setTimeout(this.connect.bind(this),5000); return; } this._read(); if(this.onconnect){ this.onconnect(); } }); }, _next_seq(){ var r=this._seq++; if(this._seq==65536) this._seq=0; return r; }, async _read(){ var buf=new _LCallBuf(); var stream=this._conn.get_input_stream(); while(true){ try{ await buf.read(stream); var seq=buf.get_seq(); var flag=buf.get_flag(); var name=buf.get_string(); if(name=='return'){ let ret=buf.get_int(); let i=this._wait.findIndex(e=>e.seq==seq); if(i==-1) continue; let cb=this._wait[i].cb; this._wait.splice(i,1); cb(ret); continue; } var func=this._func[name]; if(!func) continue; var param=buf.get_param(func.param); let ret=func.cb(...param); if((flag&_LCallBuf.FLAG_SYNC) && typeof(ret)=='number') await this.result(seq,ret); }catch(e){ console.log(e); this.destroy(); this._tmr=setTimeout(this.connect.bind(this),5000); break; } } }, _call(seq,name,flag,param){ return new Promise((resolve,reject)=>{ if(!this._conn || !this._conn.is_connected()){ reject(new Error("not connected")); return; } var stream=this._conn.get_output_stream(); var buf=new _LCallBuf(); buf.start(seq,name,flag); buf.put(param); buf.stop(); this._lock.lock().then(()=>{ return buf.write(stream); }).then(()=>{ resolve(); }).catch(e=>{ reject(e); }).finally(()=>{ this._lock.unlock(); }); }); }, call(name,param){ var seq=this._next_seq(); return this._call(seq,name,0,param); }, call_r(name,param){ return new Promise((resolve,reject)=>{ var seq=this._next_seq(); this._wait.push({seq,cb:resolve}); var tmr=setTimeout(()=>{ var i=this._wait.findIndex(e=>e.seq==seq); if(i>=0) this._wait.splice(i,1); reject(Error("timeout")); },2000); this._call(seq,name,_LCallBuf.FLAG_SYNC,param).then(()=>{ }).catch(e=>{ var i=this._wait.findIndex(e=>e.seq==seq); if(i>=0) this._wait.splice(i,1); reject(e); }); }); }, result(seq,val){ return this._call(seq,"return",0,val); }, add_func(cb,param,name){ if(!param) param=null; if(!name) name=cb.name; this._func[name]={param,cb}; }, clear_func(){ this._func={}; }, set_wm(){ return this.call_r("tool",[3,0]); }, trigger(state){ if(state===undefined) state=-1; return this.call_r("tool",[4,state]); }, set_lang(lang){ return this.call_r("tool",[1,lang]); }, run_config(){ return this.call_r("tool",[5,0]); } } const Indicator = GObject.registerClass( class Indicator extends PanelMenu.Button { _init() { super._init(0.0, 'yong'); let icon=new St.Icon({ icon_name: 'face-smile-symbolic', style_class: 'system-status-icon', }); let item = new PopupMenu.PopupMenuItem('设置'); item.connect('activate', () => { LCall.run_config(); }); this.menu.addMenuItem(item); } set_icon(path){ let icon=this.get_child_at_index(0); if(!icon){ icon=new St.Icon({ icon_name: 'face-smile-symbolic', style_class: 'system-status-icon', }); icon.set_gicon(utils.readIcon(path)); this.add_child(icon); }else{ icon.set_gicon(utils.readIcon(path)); } } }); export default class Extension { constructor(meta){ this._uuid = meta.uuid; this._icons=[]; this._state=0; this._pid=0; this._win={}; this._signal_ids={}; } find_window(title){ if(this._win[title]) return this._win[title]; let all=global.display.list_all_windows(); var win=all.find(e=>{ return e.get_pid()==this._pid && e.get_title()==title; }); if(win) this._win[title]=win; return win; } wm_make_above(title){ let win=this.find_window(title); if(!win) return; win.make_above(); } wm_move(title,x,y,rel){ let win=this.find_window(title); if(!win) return; if(!rel){ win.move_frame(false,x,y); }else{ let focus=global.display.focus_window; if(!focus) return; focus=get_compositor_private(); if(!focus) return; win.move_frame(false,x+focus.x,y+focus.y); } } update_icon(){ if(!this._icons || !this._icons[0] || !this._indicator) return; let i=1-this._state&0x01; if(!this._icons[i]) i=0; this._indicator.set_icon(this._icons[i]); } wm_icon(...path){ if(path && path.length>0){ this._icons=path; this.update_icon(); } } listen_position_stop(){ if(!this._focus) return; this._focus.disconnect(this._signal_ids['position-changed']); delete this._signal_ids['position-changed']; this._focus.disconnect(this._signal_ids['size-changed']); delete this._signal_ids['size-changed']; this._focus=null; console.log("listen stop"); } async _send_pos(){ if(!this._focus) return; let win=this._focus.get_compositor_private(); if(!win) return; this._pos={x:win.x,y:win.y}; if(this._sending_pos){ return; } try{ while(this._pos){ let pos=this._pos; this._pos=null; let param=pos.y<<16|pos.x; console.log(`focus win pos ${pos.x},${pos.y}`); await LCall.call('tool',[6,param]); } }catch(e){ console.log(e); } this._pos=null; this._sending_pos=false; } listen_position_start(){ if(this._focus){ if(this._focus==global.display.focus_window) return; this.listen_position_stop(); } this._focus=global.display.focus_window; if(!this._focus) return; console.log("listen start"); this._signal_ids['position-changed']=this._focus.connect('position-changed',this._send_pos.bind(this)); this._signal_ids['size-changed']=this._focus.connect('size-changed',()=>{ setTimeout(this._send_pos.bind(this),0); }); } wm_state(state){ this._state=state; this.update_icon(); state=state&0x01; if(state){ this.listen_position_start(); this._send_pos().catch(e=>console.log(e)); }else{ this.listen_position_stop(); } } enable() { LCall.init(); LCall.add_func(this.wm_make_above.bind(this),"s","wm_make_above"); LCall.add_func(this.wm_move.bind(this),"siii","wm_move"); LCall.add_func(this.wm_icon.bind(this),"ss","wm_icon"); LCall.add_func(this.wm_state.bind(this),"i","wm_state"); LCall.onconnect=()=>{ LCall.set_wm().then(pid=>{ this._pid=pid; console.log("connect: "+pid); this._indicator = new Indicator(); Main.panel.addToStatusArea(this._uuid, this._indicator); }).catch(e=>{ console.log(e); }); }; LCall.onclose=()=>{ console.log("close"); if(this._indicator){ this._indicator.destroy(); this._indicator = null; } this.listen_position_stop(); this._win={}; }; } disable() { LCall.destroy(); LCall.clear_func(); utils._icons=null; LCall.onconnect=null; LCall.onclose=null; if(this._indicator){ this._indicator.destroy(); this._indicator = null; } this.listen_position_stop(); this._win={}; } } function init(meta) { return new Extension(meta.uuid); } /** * TODO: * 实现窗口置顶和位置移动功能 */修改了导入部分,导出了Extension类以及修改了类中的constructor方法. |
|