|
阅读:3557回复: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方法. |
|

