Обрабатывать файлы, передаваемые в качестве аргументов в командной строке в Gjs Gtk.Application

Я пытаюсь написать приложение GNOME GTK3, используя Gjs, который обрабатывает файлы, передаваемые в качестве аргументов командной строки. Для этого я подключаю open сигнал о Gtk.Application и установить Gio.ApplicationFlags.HANDLES_OPEN флаг:

#!/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)

Когда я запускаю программу с аргументом файла, я ожидаю _onOpen быть вызванным с GFile прошло. Но вместо _onActivate называется, как если бы я запустил его без каких-либо аргументов файла:

$ ./open-files.js open-files.js 
Gjs-Message: JS LOG: starting application
Gjs-Message: JS LOG: activating application

Я бегу gjs@1.44.

1 ответ

Решение

Есть расхождение в том, как GJS ARGV определяется относительно соглашений на других языках. В, например, С, argv[0] это имя программы, а первый аргумент начинается с argv[1], В GJS название программы System.programInvocationNameи первый аргумент ARGV[0],

К сожалению, будучи частью библиотеки C, Gtk.Application ожидает, что вы передадите аргументы в соответствии с соглашением C. Вы можете сделать это:

ARGV.unshift(System.programInvocationName);

То, что происходило, было ./open-files.js open-files.js ставил ['open-files.js'] как ARGV, который Gtk.Application интерпретировал как название программы, без других аргументов. Если бы вы запустили программу с двумя аргументами файла, вы бы увидели, что она "открыла" только второй файл.

PS. К сожалению, в GJS 1.44, похоже, есть ошибка, которая мешает open сигнал от работы правильно. На данный момент, я бы предложил обойти эту проблему путем создания подклассов Gtk.Application вместо того, чтобы проксировать это. Ваша программа будет выглядеть так:

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)
Другие вопросы по тегам