Domanda

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?

È stato utile?

Soluzione

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

Altri suggerimenti

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 :)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top