I am trying to write a GNOME GTK3 application using Gjs which handles files passed as command line arguments. In order to do so I connect the open
signal of the Gtk.Application
and set the Gio.ApplicationFlags.HANDLES_OPEN
flag:
#!/usr/bin/gjs
const Gio = imports.gi.Gio
const Gtk = imports.gi.Gtk
const Lang = imports.lang
const MyApplication = new Lang.Class({
Name: 'MyApplication',
_init: function() {
this.application = new Gtk.Application({
application_id: 'com.example.my-application',
flags: Gio.ApplicationFlags.HANDLES_OPEN
})
this.application.connect('startup', this._onStartup.bind(this))
this.application.connect('open', this._onOpen.bind(this))
this.application.connect('activate', this._onActivate.bind(this))
},
_onStartup: function() {
log('starting application')
},
_onOpen: function(application, files) {
log('opening ' + files.length + ' files')
this._onStartup()
},
_onActivate: function() {
log('activating application')
}
})
let app = new MyApplication()
app.application.run(ARGV)
When I run the program with a file argument I expect _onOpen
to be called with the GFile
passed in. But instead _onActivate
is called, like if I'd run it without any file arguments:
$ ./open-files.js open-files.js
Gjs-Message: JS LOG: starting application
Gjs-Message: JS LOG: activating application
I am running [email protected].
There's a discrepancy in how GJS's ARGV
is defined, relative to the conventions in other languages. In, for example, C, argv[0]
is the name of the program, and the first argument starts at argv[1]
. In GJS, the name of the program is System.programInvocationName
, and the first argument is ARGV[0]
.
Unfortunately, being part of a C library, Gtk.Application
expects you to pass in arguments according to the C convention. You can do this:
ARGV.unshift(System.programInvocationName);
What was happening was that ./open-files.js open-files.js
was putting ['open-files.js']
as ARGV
, which Gtk.Application
was interpreting as the name of the program, with no other arguments. If you'd run the program with two file arguments, you would have seen that it "opened" only the second file.
PS. Unfortunately there seems to be a bug in GJS 1.44 that prevents the open
signal from working correctly. For now, I'd suggest working around the problem by subclassing Gtk.Application
instead of proxying it. Your program would look like this:
const Gio = imports.gi.Gio
const Gtk = imports.gi.Gtk
const Lang = imports.lang
const System = imports.system
const MyApplication = new Lang.Class({
Name: 'MyApplication',
Extends: Gtk.Application,
_init: function(props={}) {
this.parent(props)
},
vfunc_startup: function() {
log('starting application')
this.parent()
},
vfunc_open: function(files, hint) {
log('opening ' + files.length + ' files')
},
vfunc_activate: function() {
log('activating application')
this.parent()
}
})
let app = new MyApplication({
application_id: 'com.example.my-application',
flags: Gio.ApplicationFlags.HANDLES_OPEN
})
ARGV.unshift(System.programInvocationName)
app.run(ARGV)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With