سؤال

When I try to open a GtkWindow from a cinnamon applet, the entire desktop freezes.
No errors in the ~/.cinnamon/glass.log file.

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

The code is executed until Gtk.main() then no window is displayed and the desktop get frozen.
Anyone knows how to make it work correctly?

هل كانت مفيدة؟

المحلول

Javascript can't do multithreading, that's why calling Gtk.main(); breaks Cinnamon.
Cinnamon applet already runs a main loop and the call of Gtk.main(); tries to create another one.
So it's not possible to open a GtkWindow from a cinnamon applet directly in Javascript.
The solution could be to open a GtkWindow through a Python script, and to use DBus to communicate between the Cinnamon applet and the Python/GTK window.

Opened issue in Cinnamon GitHub

نصائح أخرى

This is how you can do it:

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/your_applet@you.org";
        //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;
    }

You can copy/paste this in yourgtkfile.js. (Change #!/usr/bin/gjs with #!/usr/bin/cjs)

Or, this one (taken from here) (Change #!/usr/bin/gjs with #!/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);

I supposed that you don't need to communicate with the app just launched :)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top