哪个 gnome 函数负责切换工作区?

Which gnome function is responsible for switching workspaces?

Gio open "http://..." from terminal 从当前工作区切换到默认浏览器所在的工作区。当从其他应用程序(电子邮件等)打开链接时,也会发生同样的情况。

我想写一个扩展,我试图覆盖 js/ui 中的很多功能。其中一些阻止了例如通过键盘切换工作区,但似乎没有什么可以阻止工作区随着这些链接而改变。我猜 d-bus 激活与此有关,但由于这是我对 gnome 的第一次探索,我在这里感觉有点迷茫。

所以,我想覆盖一个负责工作区切换的 gnome 函数。基本上我想阻止所有切换然后从那里继续。据说in Mutter reference manual当活动工作区改变时,meta_compositor_switch_workspace()首先被调用。 Javascript 这个版本在 js/ui/windowManager.js:_switchWorkspace(shellwm, from, to, direction).

如果我重写那个函数,什么也不会发生。没有错误。这是一个错误的功能吗?难道我做错了什么?我应该自己覆盖 meta_compositor_switch_workspace 而不是 _switchWorkSpace 吗?如果我应该这样做,有什么帮助吗?

const Meta = imports.gi.Meta;
const Main = imports.ui.main;
const WindowManager = imports.ui.windowManager;


function mySwitchWorkspace(shellwm, from, to, direction) {
    log("in my switchWorkspace");
    //if ... {
    //        shellwm.completed_switch_workspace();
            return;
    //    }
    }

let old_sw = {};

function init() {
    old_sw = WindowManager.WindowManager.prototype._switchWorkspace;
    log(old_sw);
}

function enable() {
    WindowManager.WindowManager.prototype._switchWorkspace = mySwitchWorkspace;
    log(WindowManager.WindowManager.prototype._switchWorkspace);
}

function disable() {
    WindowManager.WindowManager.prototype._switchWorkspace = old_sw;
}

GNOME 的体系结构 Shell 以及它与扩展的关系并不是很明显,所以虽然您在正确的轨道上,但您在这里缺少了一些视角。

Mutter 是 window 管理器的库,而 GNOME Shell 在技术上是一个 Mutter 插件。 Meta.Plugin in GNOME Shell is Shell.WM. In the JavaScript code of windowManager.js 指向 Shell.WM 的变量的实现是 windowManager._shellwm:

// windowManager.js Line #590
this._shellwm.connect('switch-workspace', this._switchWorkspace.bind(this));

// windowManager.js Line #1799
_switchWorkspace(shellwm, from, to, direction) {
}

在上面的代码中,你可以看到Shell.WM::switch-workspaceboundthis._switchWorkspace()。尽管您已覆盖该函数,Function.prototype.bind() 会创建一个新的函数实例,因此将调用原始回调的副本而不是您的回调。

在这种情况下,没有存储处理程序 ID,因此您必须使用 gjs >= 1.64 (GNOME 3.36) 中的新助手断开信号:

let shellwm = global.window_manager
let handler = GObject.signal_handler_find(shellwm, {signalId: 'switch-workspace'});
shellwm.disconnect(handler);

完成后,您应该能够像普通信号回调一样连接覆盖,然后替换原始处理程序。

// Replacing the original handler when your extension is disabled
function disable() {
    shellwm = global.window_manager;
    wm = imports.ui.main.wm;
    shellwm.connect('switch-workspace', wm._switchWorkspace.bind(wm));
}