首页 > 解决方案 > 等待新窗口打开的 GNOME Shell 扩展

问题描述

我正在用 JavaScript 编写一个修改所有应用程序窗口的 GNOME Shell 扩展。

作为一个练习,我想首先获取一个打开的窗口的应用程序名称并将其显示在面板中。

现在,在窥镜中,我可以通过键入获得所有打开的窗口

>>> global.screen.get_active_workspace().list_windows()
r(0) = [object instance proxy GType:MetaWindowX11 ...], ...

我可以通过键入来获取列表中第一个窗口的名称

>>> Shell.WindowTracker.get_default().get_window_app(r(0)[0]).get_name()
r(1) = <name of application>

但是,当我尝试在我的扩展extension.js文件中执行此操作然后重新启动 GNOME Shell 时,我无法获得打开窗口的名称,因为结果global.screen.get_active_workspace().list_windows()undefined.

我认为这可能会发生,因为我的扩展是在创建窗口之前执行的,所以我开始研究如何等到创建窗口后再对窗口执行操作。

这是我真正陷入困境的地方。

在我的扩展程序的init()函数中,我试图添加一个事件侦听器,update()它在接收到window-created信号时运行我的函数。

window-created信号来自MetaDisplay对象

这是我的代码到目前为止的样子:

let display = global.display;
display.connect('window-created', Lang.bind(this, this.update));

代码编译没有错误,但是update()在创建新窗口时没有调用我的函数。

有谁知道这里发生了什么?我的语法错了吗?我应该使用不同的信号吗?

任何帮助,将不胜感激。

完整的 extension.js 文件

const St = imports.gi.St;
const Main = imports.ui.main;
const Lang = imports.lang;
const Shell = imports.gi.Shell;

let text, button;

function init() {
    button = new St.Bin({ style_class: 'panel-button', 
                          reactive: true, 
                          can_focus: true, 
                          x_fill: true, 
                          y_fill: false, 
                          track_hover: true });

    let display = global.display;
    display.connect('window-created', Lang.bind(this, this.update));
}

function update() {
    let window = global.screen.get_active_workspace().list_windows()[0];
    let name = Shell.WindowTracker.get_default().get_window_app(window).get_name();

    text = new St.Label({ text: name });
    button.set_child(text);
}

function enable() {
    Main.panel._rightBox.insert_child_at_index(button, 0);
}

function disable() {
    Main.panel._rightBox.remove_child(button);
}

标签: gtkcentos7gnome-shellgnome-shell-extensions

解决方案


我最终想出了如何解决我的问题。问题在于我在听哪些信号以及我在哪里听。经过大量研究,我还注意到大多数扩展都是面向对象的,因此我更改了代码以反映这一点。下面是我的新的、有效的、面向对象的代码。

const St = imports.gi.St;
const Main = imports.ui.main;
const Lang = imports.lang;
const Shell = imports.gi.Shell;

let button;

function MyApplication() {
    this._init();
}

MyApplication.prototype = {
    _init: function() {
        button = new St.Bin({ style_class: 'panel-button', 
                              reactive: true, 
                              can_focus: true, 
                              x_fill: true, 
                              y_fill: false, 
                              track_hover: true });
    },

    _update: function() {
        text = new St.Label({ text: Shell.WindowTracker.get_default().focus_app.get_name() });
        button.set_child(text);
    },

    enable: function() {
        Main.panel._rightBox.insert_child_at_index(button, 0);
        let callbackID = global.display.connect('notify::focus-window', Lang.bind(this, this._update));
    },

    disable: function() {
        Main.panel._rightBox.remove_child(button);
    }
};

function init() {
    return new MyApplication();
}

推荐阅读