[gtk+] gtkcellrendereraccel: Use a GtkInvisible to grab on



commit fe5402d32ebf7f332a2c5f71b9ae50dcf68892fd
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Sun Jun 29 20:54:39 2014 -0400

    gtkcellrendereraccel: Use a GtkInvisible to grab on
    
    Grabbing on a non-toplevel might not do what we want it to do, since it
    will go on the focused widget, not the grabbed widget. Since we don't
    focus the widget before clicking on it, that means that putting the
    focus somewhere else and then clicking on the accelerator editor will
    freeze the app. Additionally, since it's a global system grab that can't
    be exited except by a key press that we won't ever get, it effectively
    locks up your system as well unless you know how to break the grab or
    kill the app. Ouch.
    
    Since doing a device grab on a non-toplevel is generally considered a
    bad idea, just don't do it. Use a GtkInvisible and take a grab on that
    instead.

 gtk/gtkcellrendereraccel.c |   24 ++++++++++--------------
 1 files changed, 10 insertions(+), 14 deletions(-)
---
diff --git a/gtk/gtkcellrendereraccel.c b/gtk/gtkcellrendereraccel.c
index 73aea9d..55dd812 100644
--- a/gtk/gtkcellrendereraccel.c
+++ b/gtk/gtkcellrendereraccel.c
@@ -27,9 +27,9 @@
 #include "gtkmain.h"
 #include "gtksizerequest.h"
 #include "gtktypebuiltins.h"
+#include "gtkinvisible.h"
 #include "gtkprivate.h"
 
-
 /**
  * SECTION:gtkcellrendereraccel
  * @Short_description: Renders a keyboard accelerator in a cell
@@ -88,9 +88,9 @@ enum {
 struct _GtkCellRendererAccelPrivate
 {
   GtkWidget *edit_widget;
-  GtkWidget *grab_widget;
   GtkWidget *sizing_label;
 
+  GtkWidget *grab_invisible;
   GdkDevice *grab_keyboard;
   GdkDevice *grab_pointer;
 
@@ -526,7 +526,6 @@ grab_key_callback (GtkWidget            *widget,
   gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (priv->edit_widget));
   gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (priv->edit_widget));
   priv->edit_widget = NULL;
-  priv->grab_widget = NULL;
   priv->grab_keyboard = NULL;
   priv->grab_pointer = NULL;
 
@@ -553,9 +552,8 @@ ungrab_stuff (GtkWidget            *widget,
   priv->grab_keyboard = NULL;
   priv->grab_pointer = NULL;
 
-  g_signal_handlers_disconnect_by_func (priv->grab_widget,
-                                        G_CALLBACK (grab_key_callback),
-                                        accel);
+  gtk_widget_destroy (priv->grab_invisible);
+  priv->grab_invisible = NULL;
 }
 
 static void
@@ -664,7 +662,6 @@ gtk_cell_renderer_accel_start_editing (GtkCellRenderer      *cell,
   GtkWidget *label;
   GtkWidget *eventbox;
   GdkDevice *device, *keyb, *pointer;
-  GdkWindow *window;
   gboolean editable;
   guint32 time;
 
@@ -677,11 +674,8 @@ gtk_cell_renderer_accel_start_editing (GtkCellRenderer      *cell,
   if (editable == FALSE)
     return NULL;
 
-  window = gtk_widget_get_window (widget);
   context = gtk_widget_get_style_context (widget);
 
-  g_return_val_if_fail (window != NULL, NULL);
-
   if (event)
     device = gdk_event_get_device (event);
   else
@@ -703,13 +697,16 @@ gtk_cell_renderer_accel_start_editing (GtkCellRenderer      *cell,
 
   time = gdk_event_get_time (event);
 
-  if (gdk_device_grab (keyb, window,
+  priv->grab_invisible = gtk_invisible_new ();
+  gtk_widget_show (priv->grab_invisible);
+
+  if (gdk_device_grab (keyb, gtk_widget_get_window (priv->grab_invisible),
                        GDK_OWNERSHIP_WINDOW, FALSE,
                        GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK,
                        NULL, time) != GDK_GRAB_SUCCESS)
     return NULL;
 
-  if (gdk_device_grab (pointer, window,
+  if (gdk_device_grab (pointer, gtk_widget_get_window (priv->grab_invisible),
                        GDK_OWNERSHIP_WINDOW, FALSE,
                        GDK_BUTTON_PRESS_MASK,
                        NULL, time) != GDK_GRAB_SUCCESS)
@@ -720,9 +717,8 @@ gtk_cell_renderer_accel_start_editing (GtkCellRenderer      *cell,
 
   priv->grab_keyboard = keyb;
   priv->grab_pointer = pointer;
-  priv->grab_widget = widget;
 
-  g_signal_connect (G_OBJECT (widget), "key-press-event",
+  g_signal_connect (G_OBJECT (priv->grab_invisible), "key-press-event",
                     G_CALLBACK (grab_key_callback),
                     accel);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]