Search code examples
javascriptgnome-shellgnome-shell-extensions

My gnome-shell extension stops working after a lock-unlock screen cycle


I have written a (very simple) gnome-shell extension to switch focus mode (gnome-shell 3.10 on Ubuntu 14.04). The extension is available on github; I am waiting to submit it because it has a very annoying bug --- which I am unable to understand and so to fix.

The extension is based on the standard example extension, the code is so simple that I can paste it here completely, although it needs the icon files to work.

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);
}

...and it works perfectly, switching focus mode at every click, changing the icon and doing what it is supposed to do.

But if I lock and unlock the screen, the extension puzzling stops working. Clicking on the icon simply shows the same message (stuck on the focus mode it was in before locking). Enabling and disabling the extension will resume the correct working.

Shouldn't be the lock - unlock thing being transparent to the applications? And if not, there is some hook I can use to force an enable/disable on screen unlock? Looking glass does not show any error, nor there are logs anywhere to be seen.


Solution

  • In this case, Gnome-Shell calls the disable() function when you lock the screen and the enable() function when you unlock it. The init() function is executed once in your session. So, your button is adding a new connection to the same function every time you unlock your screen when you call the function inside enable().

    This link may help http://blog.mecheye.net/2011/11/modern-gnome-shell-extension-part-1/

    You can try something like the code below to use the event with enable() and disable()functions:

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