Мое расширение gnome-shell перестает работать после цикла блокировки-разблокировки экрана


Я написал (очень простое) расширение gnome-shell для переключения режима фокусировки (gnome-shell 3.10 на Ubuntu 14.04). Расширение доступно на github; я жду, чтобы отправить его, потому что у него есть очень раздражающая ошибка, которую я не могу понять и поэтому исправить.

Расширение основано на стандартном примере расширения, код настолько прост, что я могу вставить его сюда полностью, хотя для работы ему нужны файлы значков.
const FFM_VARIANT='sloppy';

const St = imports.gi.St;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const Gtk = imports.gi.Gtk;
const Gdk = imports.gi.Gdk;
const ExtensionUtils = imports.misc.extensionUtils;
const Meta = ExtensionUtils.getCurrentExtension();
const Util = imports.misc.util;
const Gio = imports.gi.Gio;

let text, button, icon_f, icon_c, wm_prefs;

var focus;
const FFM=0;
const CTF=1;

function _set_FFM() {
    focus = FFM;
    button.set_child(icon_f);
    wm_prefs.set_string('focus-mode', FFM_VARIANT);
}

function _set_CTF() {
    focus = CTF;
    button.set_child(icon_c);
    wm_prefs.set_string('focus-mode', 'click');
}

function _hideMsg() {
    if (text) {
        Main.uiGroup.remove_actor(text);
        text = null;
    }
}

function _showMsg(what) {
    if (!text) {
        text = new St.Label({ style_class: 'msg-label', text: what });
        Main.uiGroup.add_actor(text);
    }

    text.opacity = 255;
    let monitor = Main.layoutManager.primaryMonitor;
    text.set_position(Math.floor(monitor.width / 2 - text.width / 2),
            Math.floor(monitor.height / 2 - text.height / 2));
    Tweener.addTween(text,
            { opacity: 0,
                time: 3,
        transition: 'easeOutQuad',
        onComplete: _hideMsg });
}

function _switch() {
    _hideMsg();
    if (focus == FFM) {
        _showMsg("Setting Click-to-focus");
        _set_CTF();
    } else {
        _showMsg("Setting Focus-follow-mouse");
        _set_FFM();
    }
}

function init() {
    button = new St.Bin({ style_class: 'panel-button',
        reactive: true,
            can_focus: true,
            x_fill: true,
            y_fill: false,
            track_hover: true });
    Gtk.IconTheme.get_default().append_search_path(Meta.dir.get_child('icons').get_path());
    icon_f = new St.Icon({ icon_name: 'fmode',
        style_class: 'system-status-icon' });
    icon_c = new St.Icon({ icon_name: 'cmode',
        style_class: 'system-status-icon' });
    wm_prefs=new Gio.Settings({schema: 'org.gnome.desktop.wm.preferences'});
}

function enable() {
    // start with the current mode --- sync icon and internal state.
    what=wm_prefs.get_string('focus-mode');
    if (what == 'click') {
        _set_CTF();
    } else { // sloppy or mouse
        _set_FFM();
    }
    button.connect('button-press-event', _switch);
    Main.panel._rightBox.insert_child_at_index(button, 0);
}

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

...и это прекрасно работает, переключение режима фокусировки при каждом щелчке, изменение значка и выполнение того, что он должен делать.

Но если я заблокирую и разблокирую экран, загадка расширения перестанет работать. Щелчок по иконке просто показывает то же самое сообщение (застрявшее в режиме фокусировки, в котором оно было до блокировки). Включение и отключение расширения позволит возобновить правильную работу.

Разве блокировка-разблокировка не должна быть прозрачной для приложений? А если нет, то есть какой-то крюк, который я могу использовать, чтобы заставить включить / отключить разблокировку экрана? Зазеркалье не показывает никакой ошибки,и нигде не видно бревен.

2 2

2 ответа:

В этом случае Gnome-Shell вызывает функцию disable() при блокировке экрана и функцию enable() при его разблокировке. Функция init() выполняется один раз в сеансе. Таким образом, ваша кнопка добавляет новое соединение к той же функции каждый раз, когда вы разблокируете экран при вызове функции внутри enable().

Эта ссылка может помочь http://blog.mecheye.net/2011/11/modern-gnome-shell-extension-part-1/

Вы можете попробовать что-то вроде кода ниже, чтобы использовать событие с функциями enable() и disable():

var switch_event;
function enable() {
    switch_event = button.connect('button-press-event', _switch);
}

function disable() {
    button.disconnect(switch_event);
}

Я до сих пор не знаю, почему, но кажется, что перемещение вызова

 button.connect('button-press-event', _switch);

От enable() до init() исправляет проблему.

Тем не менее, если кто-то может объяснить почему, я отмечу их правильный ответ!.