summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJasper St. Pierre <jstpierre@mecheye.net>2014-06-29 20:54:39 -0400
committerJasper St. Pierre <jstpierre@mecheye.net>2014-06-29 20:56:40 -0400
commitfe5402d32ebf7f332a2c5f71b9ae50dcf68892fd (patch)
tree6e3438ab36c6f25b8aab0c0f959b9e4ae2ef0185
parent57404341376280281bbc3ef80e7613c18e611d5c (diff)
downloadgtk+-fe5402d32ebf7f332a2c5f71b9ae50dcf68892fd.tar.gz
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.
-rw-r--r--gtk/gtkcellrendereraccel.c24
1 files changed, 10 insertions, 14 deletions
diff --git a/gtk/gtkcellrendereraccel.c b/gtk/gtkcellrendereraccel.c
index 73aea9d847..55dd8128e6 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);