Scfy
新手上路
新手上路
阅读:964回复:5

gnome45桌面输入法扩展失效的问题

楼主#
更多 发布于:2023-10-10 10:32
运行在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:25
我在等fedora升级到gnome45,现在暂时没这个环境。


没看到你提示信息的图。
Scfy
新手上路
新手上路
板凳#
发布于:2023-10-10 11:45
这就是提示的错误

这些就是
Scfy
新手上路
新手上路
地板#
发布于: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={};
}
Scfy
新手上路
新手上路
5楼#
发布于:2023-10-10 14:21
dgod:你export default一下看看,constructor可能也得改
constructor(meta){
        this._uuid = meta.uuid;
        this._icons=[];
    ...
回到原帖
问题已解决,代码如下:

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方法.
游客

返回顶部