Grabbing pointer and keyboard correctly
- From: Owen Taylor <otaylor redhat com>
- To: gnome-libs-devel gnome org
- Subject: Grabbing pointer and keyboard correctly
- Date: Thu, 21 Mar 2002 16:56:43 -0500 (EST)
In response to:
http://bugzilla.gnome.org/show_bug.cgi?id=75748
Which complains about the gnome-date-edit window not getting
the focus, and attributes it to GTK+ (though gnome-date-edit
wasn't even grabbing the keyboard...) I made up the following
patch.
This code corresponds to how GtkMenu does popups (though is
considerably simpler) and people would be advised to copy
this in other places where a "pseudo-menu" is needed.
Regards,
Owen
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/libgnomeui/ChangeLog,v
retrieving revision 1.131
diff -u -p -r1.131 ChangeLog
--- ChangeLog 21 Mar 2002 06:52:41 -0000 1.131
+++ ChangeLog 21 Mar 2002 21:52:07 -0000
@@ -1,3 +1,19 @@
+Thu Mar 21 16:47:55 2002 Owen Taylor <otaylor redhat com>
+
+ * libgnomeui/gnome-dateedit.c (select_clicked):
+ Fix grabbing so that:
+
+ - it grabs the keyboard to the window, not just the mouse
+ - it handles failure, and doesn't leave a window up
+ with no grab.
+ - it grabs before popping up the window. (Not really
+ needed here because we pop up on button release, but
+ generally a good thing.)
+
+ * libgnomeui/gnome-dateedit.c (hide_popup): Don't
+ need to ungrab the pointer, since hiding a window
+ automatically ungrabs.
+
2002-03-20 Cody Russell <cody jhu edu>
* libgnomeui/gnome-icon-list.c: Fix a warning that appears with
Index: libgnomeui/gnome-dateedit.c
===================================================================
RCS file: /cvs/gnome/libgnomeui/libgnomeui/gnome-dateedit.c,v
retrieving revision 1.68
diff -u -p -r1.68 gnome-dateedit.c
--- libgnomeui/gnome-dateedit.c 26 Feb 2002 18:28:45 -0000 1.68
+++ libgnomeui/gnome-dateedit.c 21 Mar 2002 21:52:07 -0000
@@ -112,7 +112,6 @@ hide_popup (GnomeDateEdit *gde)
{
gtk_widget_hide (gde->_priv->cal_popup);
gtk_grab_remove (gde->_priv->cal_popup);
- gdk_pointer_ungrab (GDK_CURRENT_TIME);
}
static void
@@ -237,6 +236,26 @@ position_popup (GnomeDateEdit *gde)
gtk_window_move (GTK_WINDOW (gde->_priv->cal_popup), x, y);
}
+static gboolean
+popup_grab_on_window (GdkWindow *window,
+ guint32 activate_time)
+{
+ if ((gdk_pointer_grab (window, TRUE,
+ GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+ GDK_POINTER_MOTION_MASK,
+ NULL, NULL, activate_time) == 0)) {
+ if (gdk_keyboard_grab (window, TRUE,
+ activate_time) == 0)
+ return TRUE;
+ else {
+ gdk_pointer_ungrab (activate_time);
+ return FALSE;
+ }
+ }
+
+ return FALSE;
+}
+
static void
select_clicked (GtkWidget *widget, GnomeDateEdit *gde)
{
@@ -244,6 +263,15 @@ select_clicked (GtkWidget *widget, Gnome
GDate *date;
int month;
+ /* Temporarily grab pointer and keyboard on a window we know exists; we
+ * do this so that the grab (with owner events == TRUE) affects
+ * events generated when the window is mapped, such as enter
+ * notify events on subwidgets. If the grab fails, bail out.
+ */
+ if (!popup_grab_on_window (widget->window,
+ gtk_get_current_event_time ()))
+ return;
+
str = gtk_entry_get_text (GTK_ENTRY (gde->_priv->date_entry));
date = g_date_new ();
@@ -285,16 +313,16 @@ select_clicked (GtkWidget *widget, Gnome
position_popup (gde);
+ gtk_grab_add (gde->_priv->cal_popup);
+
gtk_widget_show (gde->_priv->cal_popup);
gtk_widget_grab_focus (gde->_priv->calendar);
- gtk_grab_add (gde->_priv->cal_popup);
-
- gdk_pointer_grab (gde->_priv->cal_popup->window, TRUE,
- (GDK_BUTTON_PRESS_MASK
- | GDK_BUTTON_RELEASE_MASK
- | GDK_POINTER_MOTION_MASK),
- NULL, NULL, GDK_CURRENT_TIME);
+ /* Now transfer our grabs to the popup window; this
+ * should always succeed.
+ */
+ popup_grab_on_window (gde->_priv->cal_popup->window,
+ gtk_get_current_event_time ());
}
typedef struct {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]