Невозможно открыть GtkWindow из апплета корицы

Когда я пытаюсь открыть GtkWindow из апплета Cinnamon, весь рабочий стол зависает.
В файле ~/.cinnamon/glass.log ошибок нет.

const Gtk = imports.gi.Gtk;

function MyApplet(orientation)
{
    this._init(orientation);
}

MyApplet.prototype =
{
    __proto__: Applet.IconApplet.prototype,

    _init: function(orientation)
    {
        Applet.IconApplet.prototype._init.call(this, orientation);

        try {
            this.set_applet_icon_name("dialog-question");
            this.set_applet_tooltip("test");
        }
        catch (e) {
            global.logError(e);
        };
    },

    on_applet_clicked: function(event)
    {            
        Gtk.init(null, 0);

        let mwindow = new Gtk.Window ({type : Gtk.WindowType.TOPLEVEL});

        mwindow.title = "Hello World!";
        mwindow.connect ("destroy", function(){Gtk.main_quit()});

        mwindow.show();

        Gtk.main();
    }
};

function main(metadata, orientation)
{
    let myApplet = new MyApplet(orientation);
    return myApplet;
}

Код выполняется до Gtk.main(), после чего окно не отображается и рабочий стол зависает.
Кто-нибудь знает, как заставить его работать правильно?


person Nicolas    schedule 15.03.2013    source источник
comment
Я не знаю, но вы уверены, что вызов Gtk.init действительно нужен? И вообще, я думаю, у вас параметры поменялись местами, должно быть Gtk.init(0, null).   -  person rodrigo    schedule 16.03.2013
comment
Согласно документации, кажется, вы правы, но использование Gtk.init(0, null) делает Expected type utf8 for Argument 'argv' but got type 'number' (nil), а Gtk.init(null, 0) хорошо работает в простом сценарии Gjs (за исключением апплетов корицы). Кроме того, кажется, что я могу удалить Gtk.init из апплета корицы, не внося никаких изменений.   -  person Nicolas    schedule 16.03.2013


Ответы (2)


Javascript не поддерживает многопоточность, поэтому вызов Gtk.main(); прерывает работу Cinnamon.
Апплет Cinnamon уже запускает основной цикл, а вызов Gtk.main(); пытается создать еще один.
Таким образом, невозможно открыть GtkWindow из апплета Cinnamon. непосредственно в Javascript.
Решением может быть открытие GtkWindow через скрипт Python и использование DBus для связи между апплетом Cinnamon и окном Python/GTK.

Открытая проблема в Cinnamon GitHub

person Nicolas    schedule 20.03.2013

Вот как вы можете это сделать:

const Gtk = imports.gi.Gtk;
const Util = imports.misc.util;

function MyApplet(orientation)
{
    this._init(orientation);
}

MyApplet.prototype =
{
    __proto__: Applet.IconApplet.prototype,

    _init: function(orientation)
    {
        Applet.IconApplet.prototype._init.call(this, orientation);

        try {
            this.set_applet_icon_name("dialog-question");
            this.set_applet_tooltip("test");
        }
        catch (e) {
            global.logError(e);
        };
    },

    on_applet_clicked: function(event)
    {            
        //path to your applet directory; hardcoded for now!
        let path="~/.local/share/cinnamon/applets/[email protected]";
        //create in your applet directory a file "yourgtkfile.js" and
        //make it executable "chmod +x yourgtkfile.js"
        Util.spawnCommandLine(path + "/yourgtkfile.js");
    }
    };

    function main(metadata, orientation)
    {
        let myApplet = new MyApplet(orientation);
        return myApplet;
    }

Вы можете скопировать/вставить это в свой gtkfile.js. (Замените #!/usr/bin/gjs на #!/usr/bin/cjs)

Или этот (взято из здесь) (Замените #!/usr/bin/gjs на #!/usr/bin/cjs):

#!/usr/bin/cjs

const Lang = imports.lang;
const Gtk = imports.gi.Gtk;

const Application = new Lang.Class({
    //A Class requires an explicit Name parameter. This is the Class Name.
    Name: 'Application',

    //create the application
    _init: function() {
        this.application = new Gtk.Application();

       //connect to 'activate' and 'startup' signals to handlers.
       this.application.connect('activate', Lang.bind(this, this._onActivate));
       this.application.connect('startup', Lang.bind(this, this._onStartup));
    },

    //create the UI
    _buildUI: function() {
        this._window = new Gtk.ApplicationWindow({ application: this.application,
                                                   title: "Hello World!" });
        this._window.set_default_size(200, 200);
        this.label = new Gtk.Label({ label: "Hello World" });
        this._window.add(this.label);
    },

    //handler for 'activate' signal
    _onActivate: function() {
        //show the window and all child widgets
        this._window.show_all();
    },

    //handler for 'startup' signal
    _onStartup: function() {
        this._buildUI();
    }
});

//run the application
let app = new Application();
app.application.run(ARGV);

Я предполагал, что вам не нужно общаться с только что запущенным приложением :)

person eiro    schedule 21.06.2014