gtk_grab_add() and key press events



While working on one of the older GTK+ bugs:

 (http://bugzilla.gnome.org/show_bug.cgi?id=424)

It came to my attention that there is a problem with key press
events and gtk_grab_add() - when the grab is on a non-toplevel
window, then the keyboard event is sent to the toplevel which
the grab is in and processed normally, and is in no sense
"grabbed."

I don't think this is correct behavior, and causes at least
bug #424, and probably other problems. So, I've applied
the following patch to the stable branch. 

The biggest problem I could see happening is if somebody
is handling key press events without returning a proper
return value - in that case, they could conceivably get
the same key press twice.


I'd appreciate it, if people would:

 - Look at this patch and see if they see any potential problems

 - Install the CVS from gtk-1-2 and test it a bunch.

(I've applied a large number of other patches as well, so the
latter would good for other reasons as well.)

Thanks,
                                        Owen

Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gtk+/ChangeLog,v
retrieving revision 1.1061.2.317
diff -u -r1.1061.2.317 ChangeLog
--- ChangeLog	2001/02/02 17:16:06	1.1061.2.317
+++ ChangeLog	2001/02/02 18:28:48
@@ -1,3 +1,9 @@
+Fri Feb  2 13:20:12 2001  Owen Taylor  <otaylor redhat com>
+
+	* gtk/gtkmain.c (gtk_propagate_event): When a grab
+	widget is in effect, give the grab widget a first
+	crack at KEY_PRESS/RELEASE events. (#424)
+
 Fri Feb  2 12:02:23 2001  Owen Taylor  <otaylor redhat com>
 
 	* gtk/gtkrc.c Makefile.am: Use $(libdir), not $(exe_prefix),
Index: gtk/gtkmain.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkmain.c,v
retrieving revision 1.112.2.7
diff -u -r1.112.2.7 gtkmain.c
--- gtk/gtkmain.c	2000/02/07 05:27:08	1.112.2.7
+++ gtk/gtkmain.c	2001/02/02 19:41:07
@@ -1281,6 +1281,8 @@
   
   handled_event = FALSE;
 
+  gtk_widget_ref (widget);
+      
   if ((event->type == GDK_KEY_PRESS) ||
       (event->type == GDK_KEY_RELEASE))
     {
@@ -1292,29 +1294,50 @@
       GtkWidget *window;
 
       window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
-      if (window)
-        {
-	  if (GTK_WIDGET_IS_SENSITIVE (window))
-	    gtk_widget_event (window, event);
 
-          handled_event = TRUE; /* don't send to widget */
-        }
+      /* If there is a grab within the window, give the grab widget
+       * a first crack at the key event
+       */
+      if (widget != window && GTK_WIDGET_HAS_GRAB (widget))
+	handled_event = gtk_widget_event (widget, event);
+
+      if (!handled_event)
+	{
+	  window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
+	  if (window)
+	    {
+	      if (GTK_WIDGET_IS_SENSITIVE (window))
+		gtk_widget_event (window, event);
+	      
+	      handled_event = TRUE; /* don't send to widget */
+	    }
+	}
     }
   
   /* Other events get propagated up the widget tree
    *  so that parents can see the button and motion
    *  events of the children.
    */
-  while (!handled_event && widget)
+  if (!handled_event)
     {
-      GtkWidget *tmp;
+      while (TRUE)
+	{
+	  GtkWidget *tmp;
+	  
+	  handled_event = !GTK_WIDGET_IS_SENSITIVE (widget) || gtk_widget_event (widget, event);
+	  tmp = widget->parent;
+	  gtk_widget_unref (widget);
 
-      gtk_widget_ref (widget);
-      handled_event = !GTK_WIDGET_IS_SENSITIVE (widget) || gtk_widget_event (widget, event);
-      tmp = widget->parent;
-      gtk_widget_unref (widget);
-      widget  = tmp;
+	  widget = tmp;
+	  
+	  if (!handled_event && widget)
+	    gtk_widget_ref (widget);
+	  else
+	    break;
+	}
     }
+  else
+    gtk_widget_unref (widget);
 }
 
 #if 0




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