Какое событие я могу подключить к такому пожару, как только мое окно Gtk3 * уже * закрылось? - PullRequest
0 голосов
/ 10 февраля 2020

Я хочу выполнить некоторый код сразу после закрытия моего окна Gtk3. Я пробовал delete-event, destroy и destroy-event, который, кажется, вообще не срабатывает.

Я понимаю, что между Gdk и Gtk есть какая-то разница, но я не совсем уверен в том, что это. Я предполагаю, что спрашиваю о правильной вещи.

Я создаю окно с привязкой node.js gtk_window_new() и закрываю его с gtk_window_close(). При этом и при использовании событий, упомянутых выше, обработчики событий запускаются, пока окно все еще находится на экране.

edit:

В соответствии с запросом, пример кода:

const gi = require('node-gtk')
const Gtk = gi.require('Gtk', '3.0');

gi.startLoop();
Gtk.init();

const win = new Gtk.Window();
win.on('destroy', () => Gtk.mainQuit());
win.on('delete-event', () => false);

const button = new Gtk.Button({ label: 'Do it' });
win.add(button);
button.on('clicked', function () {win.close();});

win.showAll();
Gtk.main();

shell_command("wmctrl -lG");

function shell_command(cmd_str) {

    const execSync = require('child_process').execSync;
    code = execSync(cmd_str);
    return code.toString();

}

В моей системе Linux Mint 19.3, приведенный выше код создает небольшое окно с 1 кнопкой. При нажатии кнопки происходит сбой выполнения со следующей ошибкой терминала:

Error: Command failed: wmctrl -lG
X Error of failed request:  BadWindow (invalid Window parameter)
  Major opcode of failed request:  20 (X_GetProperty)
  Resource id in failed request:  0x6c00003
  Serial number of failed request:  26
  Current serial number in output stream:  26

Идентификатор окна 0x6c00003 - это идентификатор окна, созданного с помощью вышеуказанного кода, что подтверждается запуском wmctrl после запуска сценария, но перед нажатием кнопки.

Если я просто помещаю вызов на wmctrl в таймере 50 мс, он работает без ошибок.

setTimeout(function () {shell_command("wmctrl -lG");}, 50);

Это то, что заставляет меня поверить, что это состояние гонки. Я думаю, что wmctrl получает идентификаторы окна, когда мое окно все еще существует, но затем продолжает запрашивать эти идентификаторы после , когда мое окно закрылось, и это вызывает вышеуказанную ошибку. Это моя теория, и если она верна, Gtk.main() возвращается до того, как окно действительно исчезнет (и то же самое верно и для других упомянутых событий).

1 Ответ

1 голос
/ 10 февраля 2020
#include <gtk/gtk.h>

gboolean destroy(gpointer window, gpointer testing);

void destroy1(GtkWidget *window, gpointer testing);

int main(int argc, char *argv[]) {

  GtkWidget *window;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

  gtk_widget_add_events(GTK_WIDGET(window), GDK_ALL_EVENTS_MASK);

  gtk_widget_show(window);

  g_signal_connect(window, "destroy", G_CALLBACK(destroy1), NULL);
  g_signal_connect(window, "destroy-event", G_CALLBACK(destroy), NULL);

  gtk_main();

  printf("closing application \n");
  // you could try to add the code here 
  //which will be only be exited after the window is destroyed
  sleep(10);
  return 0;
}

void destroy1(GtkWidget *window, gpointer testing) {
  printf("sleeping for 5 seconds \n");
  gtk_widget_destroy(GTK_WIDGET(window));
  sleep(5);
  gtk_main_quit();
  printf("i have slept \n");
}

gboolean destroy(gpointer window, gpointer testing) {
  printf("sleeping for 5 seconds \n");
  sleep(5);
  printf("i have slept \n");

  return TRUE;
  }

После полного разрушения окна основное l oop закончится. Таким образом, вы можете попробовать добавить свой код после gtk_main ();

Сигнал :: destroy-event посылается при разрушении gdk-окна. Вы редко получаете этот сигнал, потому что большинство виджетов отключается от своего окна, прежде чем уничтожить его, поэтому ни один виджет не владеет окном во время уничтожения. (https://www.gnu.org/software/guile-gnome/docs/gtk/html/GtkWidget.html).

...