Расширение GNOME Shell, ожидающее открытия нового окна

Я пишу расширение оболочки GNOME на JavaScript, которое изменяет все окна приложений.

В качестве упражнения я хочу начать с получения имени приложения только для одного открытого окна и отображения его на панели.

Прямо сейчас в Зазеркалье я могу получить все открытые окна, набрав

>>> 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, я не могу получить имя открытого окна, потому что результатом 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() не вызывается при создании новых окон.

Кто-нибудь знает, что здесь происходит? Мой синтаксис неверен? Должен ли я использовать другой сигнал?

Любая помощь будет оценена по достоинству.

Файл .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);
}

person T. Andromedon    schedule 28.09.2018    source источник
comment
Если ваш код довольно мал, вы, вероятно, могли бы опубликовать его целиком. Возможно, проблема связана с использованием this, что трудно сказать по вашему фрагменту. Также посмотрите здесь, где global.screen недавно устарел: GNOMEHub.github. /гном-оболочка/коммит/   -  person andy.holmes    schedule 30.09.2018
comment
Я только что обновил свой вопрос, чтобы включить весь код в файл extension.js. Также спасибо за информацию о global.screen.   -  person T. Andromedon    schedule 01.10.2018


Ответы (1)


В итоге я понял, как решить мою проблему. Проблема заключалась в том, какие сигналы я слушал и где я их слушал. После долгих исследований я также заметил, что большинство расширений являются объектно-ориентированными, поэтому я изменил свой код, чтобы отразить это. Ниже мой новый работающий объектно-ориентированный код.

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();
}
person T. Andromedon    schedule 01.10.2018