如何在窗口焦点移出事件时退出 GtkApplication?

问题描述 投票:0回答:1

这是 gtk3 中小部件“焦点移出事件”的示例。我的目标是在窗口失去焦点时通过单击窗口外部来退出窗口。但是组合框(子)小部件有问题。每当我单击组合框时,窗口就会失去焦点并关闭。但如果我点击一个比例小部件,就没问题。这是剧本--

#include <gtk/gtk.h>
//gcc `pkg-config --cflags gtk+-3.0` -o example Changer3.c`pkg-config --libs gtk+-3.0` 

gboolean quit_function (GtkWidget *widget, GdkEvent  *event, gpointer   user_data)
{
    GApplication *app=g_application_get_default();
    g_application_quit(app);
}

static void
activate (GtkApplication *app,
          gpointer        user_data)
{
    //create Window 
    GtkWidget *window;
    GtkWidget *center_vbox;
    GtkWidget *combobox;
    GtkWidget *scale;

    window = gtk_application_window_new (app);
    gtk_window_set_decorated (GTK_WINDOW(window), FALSE);
    gtk_window_set_default_size (GTK_WINDOW(window), 230, 100);
    gtk_widget_set_size_request (window, 230, 100);
    gtk_window_set_title (GTK_WINDOW(window), "config");
    gtk_window_set_resizable (GTK_WINDOW(window), FALSE);
    gtk_window_set_keep_above (GTK_WINDOW(window), TRUE);

    center_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
    gtk_container_add (GTK_CONTAINER (window), center_vbox);
    combobox = gtk_combo_box_new ();
    gtk_box_pack_start (GTK_BOX (center_vbox), combobox, FALSE, FALSE, 0);

    scale = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0, 50, 1);
    gtk_box_pack_start (GTK_BOX (center_vbox), scale, TRUE, TRUE, 0);

    //focus-out-event event to auto hide window
    gtk_widget_set_events (window, GDK_FOCUS_CHANGE_MASK);
    g_signal_connect (G_OBJECT(window), "focus-out-event", G_CALLBACK(quit_function), NULL);

    gtk_widget_show_all(window);
}

int
main (int    argc,
  char **argv)
{
  GtkApplication *app;
  int status;

  app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
  g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
  status = g_application_run (G_APPLICATION (app), argc, argv);
  g_object_unref (app);

  return status;
}

我想要窗口,以便当我单击任何子小部件(组合框/比例)时它不会关闭。但如果我点击窗口外部,应用程序窗口应该退出。

c gtk3
1个回答
0
投票

我知道这是一篇旧帖子,但如果对任何人都有用,我遇到了同样的问题,试图制作一个应用程序启动器,并可以选择在不集中时关闭,我的解决方案是使用 g_timeout (如果我没有这样做) ,程序继续运行并关闭),当计时器结束时,检查几件事:

ismoving=0;

gboolean on_button_press(GtkWidget *widget, GdkEventButton *event, gpointer data)
{
   // check for mouse button 1 to set ismoving
    if (event->type == GDK_BUTTON_PRESS && event->button == 1)
    {
        ismoving = 1;
    }
    //GDK_BUTTON_RELEASE doesn't work for me in Wayland
    return FALSE;
}

gboolean close_window_if_unfocused(gpointer widget)
{
    //submenu is a popup menu, dialog is a global variable that i use for dialogs
    if (gtk_widget_get_visible(submenu) || gtk_widget_get_visible(dialog) || ismoving)
    {
        ismoving = 0; // Changing this is a workaround because i don't know other way in Wayland
        return FALSE;
    }

    // I also check for modifier keys
    GdkModifierType modifier_state = gdk_keymap_get_modifier_state(gdk_keymap_get_for_display(gdk_display_get_default()));
    GdkSeat *seat = gdk_display_get_default_seat(gdk_display_get_default());
    GdkDevice *pointer = gdk_seat_get_pointer(seat);
    guint button_state = 0;

    gdk_device_get_state(pointer, gtk_widget_get_window(GTK_WIDGET(widget)), NULL, &button_state);

    if (!gtk_window_has_toplevel_focus(GTK_WINDOW(widget)) &&
        !(modifier_state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK | GDK_SUPER_MASK)))
    {
        gtk_widget_destroy(GTK_WIDGET(widget));
    }
    return FALSE;
}

gboolean on_focus_out(GtkWidget *widget, GdkEventFocus *event, gpointer user_data)
{
    g_timeout_add(100, close_window_if_unfocused, widget);
    return FALSE;
}

...

g_signal_connect(window, "key-release-event", G_CALLBACK(on_key_release), NULL); // check input
g_signal_connect(window, "focus-out-event", G_CALLBACK(on_focus_out), window);

如果您知道更好的解决方案,请告诉我,这适合我的情况

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.