? 04-may-2.patch
? Birnan
? birnan
? client-motion-0.patch
? emfle
? emulate-motion-hint-rc1.patch
? emulate-motion-hint1.patch
? emulate-motion-hint2.patch
? global-motion-1.patch
? huh
? may-02.patch
? may-03.patch
? may-04.patch
? may-05.patch
? may-6.patch
? notebook
? wind
? gdk/birnan
? gdk/emfle
? gdk/frut
? gdk/global-motion-1.patch
? gdk/global_motion
? gtk/global-enter-leave.patch
? gtk/unbirnan
Index: gdk/gdkwindow.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkwindow.h,v
retrieving revision 1.51
diff -u -p -u -r1.51 gdkwindow.h
--- gdk/gdkwindow.h	11 Jul 2004 13:26:57 -0000	1.51
+++ gdk/gdkwindow.h	13 May 2005 16:20:58 -0000
@@ -215,6 +215,14 @@ struct _GdkPointerHooks 
 typedef struct _GdkWindowObject GdkWindowObject;
 typedef struct _GdkWindowObjectClass GdkWindowObjectClass;
 
+typedef void (* GdkMotionHandler) (GdkWindow *	window,
+				   gint		x,
+				   gint		y,
+				   gdouble	x_root,
+				   gdouble	y_root,
+				   gint		mask,
+				   gpointer	data);
+
 #define GDK_TYPE_WINDOW              (gdk_window_object_get_type ())
 #define GDK_WINDOW(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WINDOW, GdkWindow))
 #define GDK_WINDOW_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WINDOW, GdkWindowObjectClass))
@@ -333,6 +341,9 @@ void          gdk_window_remove_filter  
 void          gdk_window_scroll                (GdkWindow *window,
                                                 gint       dx,
                                                 gint       dy);
+void	      gdk_window_set_motion_handler    (GdkWindow	 *window,
+						GdkMotionHandler  handler,
+						gpointer	  data);
 
 /* 
  * This allows for making shaped (partially transparent) windows
Index: gdk/x11/gdkdisplay-x11.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkdisplay-x11.h,v
retrieving revision 1.21
diff -u -p -u -r1.21 gdkdisplay-x11.h
--- gdk/x11/gdkdisplay-x11.h	17 Mar 2005 01:54:39 -0000	1.21
+++ gdk/x11/gdkdisplay-x11.h	13 May 2005 16:20:58 -0000
@@ -148,9 +148,14 @@ struct _GdkDisplayX11
   guint xdnd_atoms_precached : 1;
   guint motif_atoms_precached : 1;
   guint use_sync : 1;
+  guint send_next_motion_event : 1;
 
   /* Alpha mask picture format */
   XRenderPictFormat *mask_format;
+
+  gulong query_pointer_serial;
+
+  guint pointer_xgrab_event_mask;
 };
 
 struct _GdkDisplayX11Class
Index: gdk/x11/gdkdnd-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkdnd-x11.c,v
retrieving revision 1.78
diff -u -p -u -r1.78 gdkdnd-x11.c
--- gdk/x11/gdkdnd-x11.c	16 Mar 2005 03:17:27 -0000	1.78
+++ gdk/x11/gdkdnd-x11.c	13 May 2005 16:20:58 -0000
@@ -1605,6 +1605,7 @@ motif_top_level_enter (GdkEvent *event,
 
   event->dnd.type = GDK_DRAG_ENTER;
   event->dnd.context = new_context;
+  event->dnd.send_event = FALSE;
   g_object_ref (new_context);
 
   display_x11->current_dest_drag = new_context;
@@ -1627,6 +1628,7 @@ motif_top_level_leave (GdkEvent *event,
       (timestamp >= display_x11->current_dest_drag->start_time))
     {
       event->dnd.type = GDK_DRAG_LEAVE;
+      event->dnd.send_event = FALSE;
       /* Pass ownership of context to the event */
       event->dnd.context = display_x11->current_dest_drag;
 
@@ -1659,6 +1661,7 @@ motif_motion (GdkEvent *event,
 
       event->dnd.type = GDK_DRAG_MOTION;
       event->dnd.context = display_x11->current_dest_drag;
+      event->dnd.send_event = FALSE;
       g_object_ref (display_x11->current_dest_drag);
 
       event->dnd.time = timestamp;
@@ -1740,6 +1743,7 @@ motif_drop_start (GdkEvent *event,
   event->dnd.time = timestamp;
   event->dnd.x_root = x_root;
   event->dnd.y_root = y_root;
+  event->dnd.send_event = FALSE;
 
   g_object_ref (new_context);
   display_x11->current_dest_drag = new_context;
@@ -1977,6 +1981,7 @@ xdnd_status_filter (GdkXEvent *xev,
   if (context)
     {
       GdkDragContextPrivateX11 *private = PRIVATE_DATA (context);
+
       if (private->drag_status == GDK_DRAG_STATUS_MOTION_WAIT)
 	private->drag_status = GDK_DRAG_STATUS_DRAG;
       
@@ -2030,6 +2035,7 @@ xdnd_finished_filter (GdkXEvent *xev,
       
       event->dnd.type = GDK_DROP_FINISHED;
       event->dnd.context = context;
+      event->dnd.send_event = FALSE;
       g_object_ref (context);
 
       return GDK_FILTER_TRANSLATE;
@@ -2764,6 +2770,7 @@ xdnd_enter_filter (GdkXEvent *xev,
 
   event->dnd.type = GDK_DRAG_ENTER;
   event->dnd.context = new_context;
+  event->dnd.send_event = FALSE;
   g_object_ref (new_context);
 
   display_x11->current_dest_drag = new_context;
@@ -2801,6 +2808,7 @@ xdnd_leave_filter (GdkXEvent *xev,
       event->dnd.type = GDK_DRAG_LEAVE;
       /* Pass ownership of context to the event */
       event->dnd.context = display_x11->current_dest_drag;
+      event->dnd.send_event = FALSE;
 
       display_x11->current_dest_drag = NULL;
 
@@ -2844,6 +2852,7 @@ xdnd_position_filter (GdkXEvent *xev,
     {
       event->dnd.type = GDK_DRAG_MOTION;
       event->dnd.context = display_x11->current_dest_drag;
+      event->dnd.send_event = FALSE;
       g_object_ref (display_x11->current_dest_drag);
 
       event->dnd.time = time;
@@ -2897,6 +2906,7 @@ xdnd_drop_filter (GdkXEvent *xev,
       private = PRIVATE_DATA (display_x11->current_dest_drag);
 
       event->dnd.type = GDK_DROP_START;
+      event->dnd.send_event = FALSE;
 
       event->dnd.context = display_x11->current_dest_drag;
       g_object_ref (display_x11->current_dest_drag);
@@ -3419,7 +3429,7 @@ gdk_drag_motion (GdkDragContext *context
       else
 	return TRUE;
     }
-
+  
   return FALSE;
 }
 
@@ -3599,7 +3609,7 @@ gdk_drag_status (GdkDragContext   *conte
       xev.xclient.data.l[2] = 0;
       xev.xclient.data.l[3] = 0;
       xev.xclient.data.l[4] = xdnd_action_to_atom (display, action);
-      
+
       if (!xdnd_send_xevent (context, context->source_window,
 			     FALSE, &xev))
 	GDK_NOTE (DND, 
Index: gdk/x11/gdkevents-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkevents-x11.c,v
retrieving revision 1.147
diff -u -p -u -r1.147 gdkevents-x11.c
--- gdk/x11/gdkevents-x11.c	5 May 2005 00:12:21 -0000	1.147
+++ gdk/x11/gdkevents-x11.c	13 May 2005 16:20:58 -0000
@@ -84,6 +84,7 @@ struct _GdkEventTypeX11
   gint n_events;
 };
 
+
 /* 
  * Private function declarations
  */
@@ -197,6 +198,7 @@ _gdk_x11_events_uninit_screen (GdkScreen
   screen_x11->xsettings_client = NULL;
 }
 
+
 void 
 _gdk_events_init (GdkDisplay *display)
 {
@@ -227,7 +229,6 @@ _gdk_events_init (GdkDisplay *display)
 					 NULL);
 }
 
-
 /**
  * gdk_events_pending:
  * 
@@ -840,6 +841,32 @@ set_user_time (GdkWindow *window,
 }
 
 static gboolean
+window_gets_event (GdkWindowObject *obj, guint mask)
+{
+  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (obj));
+
+  if (display_x11->pointer_xgrab_window == obj)
+    {
+      if (display_x11->pointer_xgrab_owner_events)
+	{
+	  /* We dispatch this event if either the window or the grab
+	   * selected for it
+	   */
+	  return (obj->event_mask | display_x11->pointer_xgrab_event_mask) & mask;
+	}
+      else
+	{
+	  /* owner_events == TRUE means we wouldn't have gotten this
+	   * event in the first place if it shouldn't be passed on
+	   */
+	  return TRUE;
+	}
+    }
+  
+  return (obj && (obj->event_mask & mask));
+}
+
+static gboolean
 gdk_event_translate (GdkDisplay *display,
 		     GdkEvent   *event,
 		     XEvent     *xevent,
@@ -1031,6 +1058,14 @@ gdk_event_translate (GdkDisplay *display
           return_val = FALSE;
           break;
         }
+
+      display_x11->send_next_motion_event = TRUE;
+
+      if (!window_gets_event (window_private, GDK_KEY_PRESS_MASK))
+	{
+	  return_val = FALSE;
+	  break;
+	}
       translate_key_event (display, event, xevent);
       set_user_time (window, event);
       break;
@@ -1042,6 +1077,14 @@ gdk_event_translate (GdkDisplay *display
           break;
         }
       
+      display_x11->send_next_motion_event = TRUE;
+      
+      if (!window_gets_event (window_private, GDK_KEY_RELEASE_MASK))
+	{
+	  return_val = FALSE;
+	  break;
+	}
+      
       /* Emulate detectable auto-repeat by checking to see
        * if the next event is a key press with the same
        * keycode and timestamp, and if so, ignoring the event.
@@ -1080,6 +1123,8 @@ gdk_event_translate (GdkDisplay *display
 	  break;
 	}
       
+      display_x11->send_next_motion_event = TRUE;
+      
       /* If we get a ButtonPress event where the button is 4 or 5,
 	 it's a Scroll event */
       switch (xevent->xbutton.button)
@@ -1088,6 +1133,14 @@ gdk_event_translate (GdkDisplay *display
         case 5: /* down */
         case 6: /* left */
         case 7: /* right */
+
+	  if (!window_gets_event (window_private,
+				 GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK))
+	    {
+	      return_val = FALSE;
+	      break;
+	    }
+	  
 	  event->scroll.type = GDK_SCROLL;
 
           if (xevent->xbutton.button == 4)
@@ -1109,10 +1162,15 @@ gdk_event_translate (GdkDisplay *display
 	  event->scroll.device = display->core_pointer;
 
 	  set_screen_from_root (display, event, xevent->xbutton.root);
-	  
           break;
           
         default:
+	  if (!window_gets_event (window_private, GDK_BUTTON_PRESS_MASK))
+	    {
+	      return_val = FALSE;
+	      break;
+	    }
+	  
 	  event->button.type = GDK_BUTTON_PRESS;
 	  event->button.window = window;
 	  event->button.time = xevent->xbutton.time;
@@ -1148,6 +1206,8 @@ gdk_event_translate (GdkDisplay *display
 	  return_val = FALSE;
 	  break;
 	}
+
+      display_x11->send_next_motion_event = TRUE;
       
       /* We treat button presses as scroll wheel events, so ignore the release */
       if (xevent->xbutton.button == 4 || xevent->xbutton.button == 5 ||
@@ -1157,6 +1217,12 @@ gdk_event_translate (GdkDisplay *display
 	  break;
 	}
 
+      if (!window_gets_event (window_private, GDK_BUTTON_RELEASE_MASK))
+	{
+	  return_val = FALSE;
+	  break;
+	}
+      
       event->button.type = GDK_BUTTON_RELEASE;
       event->button.window = window;
       event->button.time = xevent->xbutton.time;
@@ -1170,7 +1236,6 @@ gdk_event_translate (GdkDisplay *display
       event->button.device = display->core_pointer;
 
       set_screen_from_root (display, event, xevent->xbutton.root);
-      
       break;
       
     case MotionNotify:
@@ -1187,6 +1252,55 @@ gdk_event_translate (GdkDisplay *display
 	  return_val = FALSE;
 	  break;
 	}
+
+      /* We select for motion notifies on all windows, so we need to skip
+       * motions on windows that didn't select for them at the gdk level
+       */
+
+      if (display_x11->pointer_xgrab_window != window_private)
+	{
+	  gboolean get_event = FALSE;
+
+	  if (window_gets_event (window_private, GDK_POINTER_MOTION_MASK))
+	    {
+	      get_event = TRUE;
+	    }
+	  else if ((xevent->xmotion.state & Button1Mask) &&
+		   window_gets_event (window_private, GDK_BUTTON1_MOTION_MASK))
+	    {
+	      get_event = TRUE;
+	    }
+	  else if ((xevent->xmotion.state & Button2Mask) &&
+		   window_gets_event (window_private, GDK_BUTTON2_MOTION_MASK))
+	    {
+	      get_event = TRUE;
+	    }
+	  else if ((xevent->xmotion.state & Button3Mask) &&
+		   window_gets_event (window_private, GDK_BUTTON3_MOTION_MASK))
+	    {
+	      get_event = TRUE;
+	    }
+	  
+	  if (!get_event)
+	    {
+	      event->any.send_event |= GDK_SKIP_EVENT_FLAG;
+	    }
+	  else if (window_private->event_mask & GDK_POINTER_MOTION_HINT_MASK)
+	    {
+	      if (display_x11->send_next_motion_event)
+		{
+		  display_x11->send_next_motion_event = FALSE;
+		}
+	      else if (display_x11->query_pointer_serial && xevent->xmotion.serial >= display_x11->query_pointer_serial)
+		{
+		  display_x11->query_pointer_serial = 0;
+		}
+	      else
+		{
+		  event->any.send_event |= GDK_SKIP_EVENT_FLAG;
+		}
+	    }
+	}
       
       event->motion.type = GDK_MOTION_NOTIFY;
       event->motion.window = window;
@@ -1199,6 +1313,9 @@ gdk_event_translate (GdkDisplay *display
       event->motion.state = (GdkModifierType) xevent->xmotion.state;
       event->motion.is_hint = xevent->xmotion.is_hint;
       event->motion.device = display->core_pointer;
+
+      if (window_private && window_private->event_mask & GDK_POINTER_MOTION_HINT_MASK)
+	event->motion.is_hint = TRUE;
       
       set_screen_from_root (display, event, xevent->xmotion.root);
       
@@ -1216,6 +1333,15 @@ gdk_event_translate (GdkDisplay *display
           return_val = FALSE;
           break;
         }
+
+      display_x11->send_next_motion_event = TRUE;
+      
+      /* We select for Enter/Leave on all windows, so we need to skip
+       * the events on windows where the app didn't select at the
+       * gdk level
+       */
+      if (!window_gets_event (window_private, GDK_LEAVE_NOTIFY_MASK))
+	event->any.send_event |= GDK_SKIP_EVENT_FLAG;
       
       /* Handle focusing (in the case where no window manager is running */
       if (toplevel && xevent->xcrossing.detail != NotifyInferior)
@@ -1314,6 +1440,15 @@ gdk_event_translate (GdkDisplay *display
           break;
         }
       
+      display_x11->send_next_motion_event = TRUE;
+
+      /* We select for Enter/Leave on all windows, so we need to skip
+       * the events on windows where the app didn't select at the
+       * gdk level
+       */
+      if (!window_gets_event (window_private, GDK_LEAVE_NOTIFY_MASK))
+	event->any.send_event |= GDK_SKIP_EVENT_FLAG;
+      
       /* Handle focusing (in the case where no window manager is running */
       if (toplevel && xevent->xcrossing.detail != NotifyInferior)
 	{
@@ -1701,6 +1836,7 @@ gdk_event_translate (GdkDisplay *display
       GDK_NOTE (EVENTS,
 		g_message ("unmap notify:\t\twindow: %ld",
 			   xevent->xmap.window));
+      display_x11->send_next_motion_event = TRUE;
       
       event->any.type = GDK_UNMAP;
       event->any.window = window;      
@@ -1726,6 +1862,7 @@ gdk_event_translate (GdkDisplay *display
       GDK_NOTE (EVENTS,
 		g_message ("map notify:\t\twindow: %ld",
 			   xevent->xmap.window));
+      display_x11->send_next_motion_event = TRUE;
       
       event->any.type = GDK_MAP;
       event->any.window = window;
@@ -2240,6 +2377,55 @@ gdk_event_check (GSource *source) 
   return retval;
 }
 
+static void
+generate_global_motion (GdkEvent *event)
+{
+  gint mask;
+  gint x, y;
+  gdouble x_root, y_root;
+  GdkWindowObject *obj;
+
+  obj = (GdkWindowObject *)event->any.window;
+  
+  if (!obj)
+    return;
+  
+  if (event->type == GDK_MOTION_NOTIFY)
+    {
+      mask = event->motion.state;
+      x = event->motion.x;
+      y = event->motion.y;
+      x_root = event->motion.x_root;
+      y_root = event->motion.y_root;
+    }
+  else if (event->type == GDK_ENTER_NOTIFY ||
+	   event->type == GDK_LEAVE_NOTIFY)
+    {
+      mask = event->crossing.state;
+      x = event->crossing.x;
+      y = event->crossing.y;
+      x_root = event->crossing.x_root;
+      y_root = event->crossing.y_root;
+    }
+  else
+    {
+      return;
+    }
+
+  while (obj)
+    {
+      GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (obj->impl);
+      
+      if (impl->motion_handler)
+	impl->motion_handler ((GdkWindow *)obj, x, y, x_root, y_root, mask, impl->motion_handler_data);
+      
+      x += obj->x;
+      y += obj->y;
+
+      obj = obj->parent;
+    }
+}
+
 static gboolean  
 gdk_event_dispatch (GSource    *source,
 		    GSourceFunc callback,
@@ -2255,8 +2441,13 @@ gdk_event_dispatch (GSource    *source,
 
   if (event)
     {
-      if (_gdk_event_func)
-	(*_gdk_event_func) (event, _gdk_event_data);
+      if (!(event->any.send_event & GDK_SKIP_EVENT_FLAG))
+	{
+	  if (_gdk_event_func)
+	    (*_gdk_event_func) (event, _gdk_event_data);
+	}
+      
+      generate_global_motion (event);
       
       gdk_event_free (event);
     }
Index: gdk/x11/gdkmain-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkmain-x11.c,v
retrieving revision 1.164
diff -u -p -u -r1.164 gdkmain-x11.c
--- gdk/x11/gdkmain-x11.c	16 Mar 2005 03:17:27 -0000	1.164
+++ gdk/x11/gdkmain-x11.c	13 May 2005 16:20:58 -0000
@@ -238,6 +238,7 @@ gdk_pointer_grab (GdkWindow *	  window,
       display_x11->pointer_xgrab_window = (GdkWindowObject *)window;
       display_x11->pointer_xgrab_serial = serial;
       display_x11->pointer_xgrab_owner_events = owner_events;
+      display_x11->pointer_xgrab_event_mask = event_mask;
     }
 
   return gdk_x11_convert_grab_status (return_val);
Index: gdk/x11/gdkprivate-x11.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkprivate-x11.h,v
retrieving revision 1.37
diff -u -p -u -r1.37 gdkprivate-x11.h
--- gdk/x11/gdkprivate-x11.h	2 May 2005 23:29:23 -0000	1.37
+++ gdk/x11/gdkprivate-x11.h	13 May 2005 16:20:58 -0000
@@ -177,6 +177,11 @@ extern const int         _gdk_event_mask
 extern GdkAtom		 _gdk_selection_property;
 extern gboolean          _gdk_synchronize;
 
+/* Or'ed into event->any.send_event when the event should be skipped
+ * by the dispatch code
+ */
+#define GDK_SKIP_EVENT_FLAG		(1 << 1)
+
 #define GDK_PIXMAP_SCREEN(pix)	      (GDK_DRAWABLE_IMPL_X11 (((GdkPixmapObject *)pix)->impl)->screen)
 #define GDK_PIXMAP_DISPLAY(pix)       (GDK_SCREEN_X11 (GDK_PIXMAP_SCREEN (pix))->display)
 #define GDK_PIXMAP_XROOTWIN(pix)      (GDK_SCREEN_X11 (GDK_PIXMAP_SCREEN (pix))->xroot_window)
Index: gdk/x11/gdkwindow-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkwindow-x11.c,v
retrieving revision 1.236
diff -u -p -u -r1.236 gdkwindow-x11.c
--- gdk/x11/gdkwindow-x11.c	17 Mar 2005 01:54:39 -0000	1.236
+++ gdk/x11/gdkwindow-x11.c	13 May 2005 16:20:58 -0000
@@ -644,6 +644,39 @@ setup_toplevel_window (GdkWindow *window
   ensure_sync_counter (window);
 }
 
+static gint
+gdk_event_mask_to_x_event_mask (GdkWindowImplX11 *impl,
+				gint		  gdk_mask)
+{
+  gint result, i;
+
+  result = 0;
+  for (i = 0; i < _gdk_nenvent_masks; i++)
+    {
+      if (gdk_mask & (1 << (i + 1)))
+	result |= _gdk_event_mask_table[i];
+    }
+
+  if (gdk_mask & GDK_POINTER_MOTION_HINT_MASK)
+    {
+      result &= ~PointerMotionHintMask;
+
+      result |= KeyPressMask;
+      result |= KeyReleaseMask;
+      result |= ButtonPressMask;
+      result |= ButtonReleaseMask;
+    }
+
+  /* We need to select for enter/leave events on all windows
+   * so that we can generate global motion events
+   */
+  result |= LeaveWindowMask;
+  result |= EnterWindowMask;
+  result |= PointerMotionMask;
+  
+  return result;
+}
+
 /**
  * gdk_window_new:
  * @parent: a #GdkWindow, or %NULL to create the window as a child of
@@ -683,7 +716,6 @@ gdk_window_new (GdkWindow     *parent,
   
   unsigned int class;
   const char *title;
-  int i;
   
   g_return_val_if_fail (attributes != NULL, NULL);
   
@@ -769,13 +801,9 @@ gdk_window_new (GdkWindow     *parent,
   xvisual = ((GdkVisualPrivate*) visual)->xvisual;
   
   xattributes.event_mask = StructureNotifyMask | PropertyChangeMask;
-  for (i = 0; i < _gdk_nenvent_masks; i++)
-    {
-      if (attributes->event_mask & (1 << (i + 1)))
-	xattributes.event_mask |= _gdk_event_mask_table[i];
-    }
+  xattributes.event_mask = gdk_event_mask_to_x_event_mask (impl, attributes->event_mask);
   private->event_mask = attributes->event_mask;
-  
+
   if (xattributes.event_mask)
     xattributes_mask |= CWEventMask;
   
@@ -3254,6 +3282,8 @@ _gdk_windowing_get_pointer (GdkDisplay  
     return;
 
   default_screen = gdk_display_get_default_screen (display);
+
+  GDK_DISPLAY_X11 (display)->query_pointer_serial = NextRequest (GDK_DISPLAY_XDISPLAY (display));
   
   XQueryPointer (GDK_SCREEN_XDISPLAY (default_screen),
 		 GDK_SCREEN_XROOTWIN (default_screen),
@@ -3285,19 +3315,24 @@ _gdk_windowing_window_get_pointer (GdkDi
   int winy = 0;
   unsigned int xmask = 0;
   gint xoffset, yoffset;
+  Display *xdisplay;
 
   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
   
+  xdisplay = GDK_DISPLAY_XDISPLAY (display);
+  
   _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
 
+  GDK_DISPLAY_X11 (display)->query_pointer_serial = NextRequest (xdisplay);
+  
   return_val = NULL;
   if (!GDK_WINDOW_DESTROYED (window) &&
-      XQueryPointer (GDK_WINDOW_XDISPLAY (window),
+      XQueryPointer (xdisplay,
 		     GDK_WINDOW_XID (window),
 		     &root, &child, &rootx, &rooty, &winx, &winy, &xmask))
     {
       if (child)
-	return_val = gdk_window_lookup_for_display (GDK_WINDOW_DISPLAY (window), child);
+	return_val = gdk_window_lookup_for_display (display, child);
     }
   
   *x = winx + xoffset;
@@ -3358,6 +3393,7 @@ _gdk_windowing_window_at_pointer (GdkDis
   int rootx = -1, rooty = -1;
   int winx, winy;
   unsigned int xmask;
+  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
 
   screen = gdk_display_get_default_screen (display);
   
@@ -3369,6 +3405,8 @@ _gdk_windowing_window_at_pointer (GdkDis
    * than we'll end up with inaccurate values for win_x, win_y
    * and the result.
    */
+  display_x11->query_pointer_serial = NextRequest (xdisplay);
+  
   gdk_x11_display_grab (display);
   XQueryPointer (xdisplay, xwindow,
 		 &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
@@ -3381,6 +3419,7 @@ _gdk_windowing_window_at_pointer (GdkDis
   while (xwindow)
     {
       xwindow_last = xwindow;
+      display_x11->query_pointer_serial = NextRequest (xdisplay);
       XQueryPointer (xdisplay, xwindow,
 		     &root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask);
     }
@@ -3442,7 +3481,6 @@ gdk_window_set_events (GdkWindow       *
 		       GdkEventMask     event_mask)
 {
   long xevent_mask;
-  int i;
   
   g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
@@ -3450,12 +3488,8 @@ gdk_window_set_events (GdkWindow       *
   if (!GDK_WINDOW_DESTROYED (window))
     {
       GDK_WINDOW_OBJECT (window)->event_mask = event_mask;
-      xevent_mask = StructureNotifyMask | PropertyChangeMask;
-      for (i = 0; i < _gdk_nenvent_masks; i++)
-	{
-	  if (event_mask & (1 << (i + 1)))
-	    xevent_mask |= _gdk_event_mask_table[i];
-	}
+
+      xevent_mask = gdk_event_mask_to_x_event_mask (GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)window)->impl), event_mask);
       
       XSelectInput (GDK_WINDOW_XDISPLAY (window),
 		    GDK_WINDOW_XID (window),
@@ -5888,6 +5922,33 @@ gdk_window_configure_finished (GdkWindow
 	}
     }
 #endif
+}
+
+/**
+ * gdk_set_motion_handler:
+ * @window: a #GdkWindow
+ * @handler: the address of a function that is called when the mouse cursor moves inside this window
+ * @data: a pointer that is passed to @handler.
+ * 
+ * This function sets a motion handler that is called every time the mouse cursor
+ * moves inside @window or one of @window's children. The callback is called
+ * regardless of whether GDK_MOTION_NOTIFY_MASK is in the event_mask for @window,
+ * 
+ * Since: 2.8
+ **/
+void
+gdk_window_set_motion_handler (GdkWindow	 *window,
+			       GdkMotionHandler  handler,
+			       gpointer		 data)
+{
+  GdkWindowImplX11 *impl;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)window)->impl);
+
+  impl->motion_handler = handler;
+  impl->motion_handler_data = data;
 }
 
 #define __GDK_WINDOW_X11_C__
Index: gdk/x11/gdkwindow-x11.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkwindow-x11.h,v
retrieving revision 1.19
diff -u -p -u -r1.19 gdkwindow-x11.h
--- gdk/x11/gdkwindow-x11.h	5 May 2005 00:12:21 -0000	1.19
+++ gdk/x11/gdkwindow-x11.h	13 May 2005 16:20:58 -0000
@@ -78,6 +78,9 @@ struct _GdkWindowImplX11
   gint8 toplevel_window_type;
   guint override_redirect : 1;
   guint use_synchronized_configure : 1;
+
+  GdkMotionHandler motion_handler;
+  gpointer motion_handler_data;
 };
  
 struct _GdkWindowImplX11Class 
@@ -119,7 +122,7 @@ struct _GdkToplevelX11
   guint have_fullscreen : 1;    /* _NET_WM_STATE_FULLSCREEN */
 
   guint is_leader : 1;
-  
+
   gulong map_serial;	/* Serial of last transition from unmapped */
   
   GdkPixmap *icon_pixmap;
Index: gtk/gtkbutton.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkbutton.c,v
retrieving revision 1.125
diff -u -p -u -r1.125 gtkbutton.c
--- gtk/gtkbutton.c	31 Mar 2005 17:04:25 -0000	1.125
+++ gtk/gtkbutton.c	13 May 2005 16:20:58 -0000
@@ -763,7 +763,6 @@ gtk_button_pressed (GtkButton *button)
 {
   g_return_if_fail (GTK_IS_BUTTON (button));
 
-  
   g_signal_emit (button, button_signals[PRESSED], 0);
 }
 
Index: gtk/gtkprivate.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkprivate.h,v
retrieving revision 1.29
diff -u -p -u -r1.29 gtkprivate.h
--- gtk/gtkprivate.h	22 Mar 2005 02:14:55 -0000	1.29
+++ gtk/gtkprivate.h	13 May 2005 16:20:58 -0000
@@ -49,7 +49,9 @@ typedef enum
   PRIVATE_GTK_CHILD_VISIBLE     = 1 <<  10,  /* If widget should be mapped when parent is mapped */
   PRIVATE_GTK_REDRAW_ON_ALLOC   = 1 <<  11,  /* If we should queue a draw on the entire widget when it is reallocated */
   PRIVATE_GTK_ALLOC_NEEDED      = 1 <<  12,  /* If we we should allocate even if the allocation is the same */
-  PRIVATE_GTK_REQUEST_NEEDED    = 1 <<  13   /* Whether we need to call gtk_widget_size_request */
+  PRIVATE_GTK_REQUEST_NEEDED    = 1 <<  13,  /* Whether we need to call gtk_widget_size_request */
+  PRIVATE_GTK_HAS_POINTER	= 1 <<  14,
+  PRIVATE_GTK_HAD_POINTER	= 1 <<  15
 } GtkPrivateFlags;
 
 /* Macros for extracting a widgets private_flags from GtkWidget.
@@ -67,6 +69,8 @@ typedef enum
 #define GTK_WIDGET_REDRAW_ON_ALLOC(obj)   ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_REDRAW_ON_ALLOC) != 0)
 #define GTK_WIDGET_ALLOC_NEEDED(obj)      ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_ALLOC_NEEDED) != 0)
 #define GTK_WIDGET_REQUEST_NEEDED(obj)    ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_REQUEST_NEEDED) != 0)
+#define GTK_WIDGET_HAS_POINTER(obj)	  ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_HAS_POINTER) != 0)
+#define GTK_WIDGET_HAD_POINTER(obj)	  ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_HAD_POINTER) != 0)
 
 /* Macros for setting and clearing private widget flags.
  * we use a preprocessor string concatenation here for a clear
Index: gtk/gtkruler.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkruler.c,v
retrieving revision 1.37
diff -u -p -u -r1.37 gtkruler.c
--- gtk/gtkruler.c	4 Apr 2005 06:28:07 -0000	1.37
+++ gtk/gtkruler.c	13 May 2005 16:20:58 -0000
@@ -373,7 +373,7 @@ gtk_ruler_draw_pos (GtkRuler *ruler)
   g_return_if_fail (GTK_IS_RULER (ruler));
 
   if (GTK_RULER_GET_CLASS (ruler)->draw_pos)
-     GTK_RULER_GET_CLASS (ruler)->draw_pos (ruler);
+    GTK_RULER_GET_CLASS (ruler)->draw_pos (ruler);
 }
 
 
Index: gtk/gtkviewport.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkviewport.c,v
retrieving revision 1.75
diff -u -p -u -r1.75 gtkviewport.c
--- gtk/gtkviewport.c	26 Mar 2005 05:49:14 -0000	1.75
+++ gtk/gtkviewport.c	13 May 2005 16:20:58 -0000
@@ -553,11 +553,7 @@ gtk_viewport_set_shadow_type (GtkViewpor
     {
       viewport->shadow_type = type;
 
-      if (GTK_WIDGET_VISIBLE (viewport))
-	{
-	  gtk_widget_size_allocate (GTK_WIDGET (viewport), &(GTK_WIDGET (viewport)->allocation));
-	  gtk_widget_queue_draw (GTK_WIDGET (viewport));
-	}
+      gtk_widget_queue_resize (GTK_WIDGET (viewport));
 
       g_object_notify (G_OBJECT (viewport), "shadow-type");
     }
Index: gtk/gtkwidget.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwidget.c,v
retrieving revision 1.400
diff -u -p -u -r1.400 gtkwidget.c
--- gtk/gtkwidget.c	2 May 2005 23:29:24 -0000	1.400
+++ gtk/gtkwidget.c	13 May 2005 16:20:59 -0000
@@ -120,6 +120,9 @@ enum {
   ACCEL_CLOSURES_CHANGED,
   SCREEN_CHANGED,
   CAN_ACTIVATE_ACCEL,
+  GLOBAL_ENTER,
+  GLOBAL_LEAVE,
+  GLOBAL_MOTION,
   LAST_SIGNAL
 };
 
@@ -1370,6 +1373,37 @@ gtk_widget_class_init (GtkWidgetClass *k
 		  _gtk_marshal_VOID__OBJECT,
 		  G_TYPE_NONE, 1,
 		  GDK_TYPE_SCREEN);
+  widget_signals[GLOBAL_ENTER] =
+    g_signal_new ("global_enter",
+		  G_TYPE_FROM_CLASS (gobject_class),
+		  G_SIGNAL_RUN_LAST,
+		  G_STRUCT_OFFSET (GtkWidgetClass, global_enter),
+		  NULL, NULL,
+		  _gtk_marshal_VOID__INT_INT,
+		  G_TYPE_NONE, 2,
+		  G_TYPE_INT,
+		  G_TYPE_INT);
+  widget_signals[GLOBAL_LEAVE] =
+    g_signal_new ("global_leave",
+		  G_TYPE_FROM_CLASS (gobject_class),
+		  G_SIGNAL_RUN_LAST,
+		  G_STRUCT_OFFSET (GtkWidgetClass, global_leave),
+		  NULL, NULL,
+		  _gtk_marshal_VOID__INT_INT,
+		  G_TYPE_NONE, 2,
+		  G_TYPE_INT,
+		  G_TYPE_INT);
+  widget_signals[GLOBAL_MOTION] =
+    g_signal_new ("global_motion",
+		  G_TYPE_FROM_CLASS (gobject_class),
+		  G_SIGNAL_RUN_LAST,
+		  G_STRUCT_OFFSET (GtkWidgetClass, global_motion),
+		  NULL, NULL,
+		  _gtk_marshal_VOID__INT_INT,
+		  G_TYPE_NONE, 2,
+		  G_TYPE_INT,
+		  G_TYPE_INT);
+  
 /**
  * GtkWidget::can-activate-accel:
  * @widget: the object which received the signal
Index: gtk/gtkwidget.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwidget.h,v
retrieving revision 1.155
diff -u -p -u -r1.155 gtkwidget.h
--- gtk/gtkwidget.h	6 May 2005 03:12:33 -0000	1.155
+++ gtk/gtkwidget.h	13 May 2005 16:20:59 -0000
@@ -404,9 +404,13 @@ struct _GtkWidgetClass
                                       guint      signal_id);
 
   /* Padding for future expansion */
-  void (*_gtk_reserved2) (void);
-  void (*_gtk_reserved3) (void);
-  void (*_gtk_reserved4) (void);
+  void	       (*global_enter)	     (GtkWidget *widget,
+				      gint	 x,
+				      gint	 y);
+  void         (*global_leave)	     (GtkWidget *widget);
+  void	       (*global_motion)	     (GtkWidget *widget,
+				      gint	 x,
+				      gint	 y);
   void (*_gtk_reserved5) (void);
   void (*_gtk_reserved6) (void);
   void (*_gtk_reserved7) (void);
Index: gtk/gtkwindow.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.c,v
retrieving revision 1.289
diff -u -p -u -r1.289 gtkwindow.c
--- gtk/gtkwindow.c	26 Mar 2005 05:49:15 -0000	1.289
+++ gtk/gtkwindow.c	13 May 2005 16:20:59 -0000
@@ -167,6 +167,10 @@ struct _GtkWindowPrivate
   guint skips_pager : 1;
   guint accept_focus : 1;
   guint focus_on_map : 1;
+
+  int pointer_x;
+  int pointer_y;
+  GtkWidget *pointer_widget;
 };
 
 static void gtk_window_class_init         (GtkWindowClass    *klass);
@@ -3984,6 +3988,248 @@ gtk_window_unmap (GtkWidget *widget)
   priv->below_initially = state & GDK_WINDOW_STATE_BELOW;
 }
 
+static GtkWidget *
+widget_at_point (GtkWidget *widget,
+		 int *x, int *y)
+{
+  GList *children;
+  GList *l;
+  GtkWidget *retval;
+
+  if (!GTK_IS_CONTAINER (widget))
+    return widget;
+
+  children = gtk_container_get_children (GTK_CONTAINER (widget));
+
+  retval = widget;
+  for (l = children; l != NULL; l = l->next)
+    {
+      GtkWidget *child = l->data;
+      
+      if (GTK_WIDGET_MAPPED (child))
+	{
+	  int child_x = *x;
+	  int child_y = *y;
+	  
+	  if (child_x >= child->allocation.x &&
+	      child_y >= child->allocation.y &&
+	      child_x < child->allocation.x + child->allocation.width &&
+	      child_y < child->allocation.y + child->allocation.height)
+	    {
+	      if (!GTK_WIDGET_NO_WINDOW (child))
+		{
+		  child_x -= child->allocation.x;
+		  child_y -= child->allocation.y;
+		}
+	      
+	      retval = widget_at_point (child, &child_x, &child_y);
+	      goto done;
+	    }
+	}
+    }
+
+ done:
+  g_list_free (children);
+  return retval;
+}
+
+/* A function that converts (x, y) which are relative to widget->window
+ * into coordinates relative to @widget
+ */
+static void
+window_to_widget (GtkWidget *widget,
+		  int x, int y,
+		  int *widget_x, int *widget_y)
+{
+  if (GTK_WIDGET_TOPLEVEL (widget))
+    {
+      *widget_x = x;
+      *widget_y = y;
+    }
+  else if (!GTK_WIDGET_NO_WINDOW (widget))
+    {
+      int window_pos_x, window_pos_y;
+
+      gdk_window_get_position (widget->window, &window_pos_x, &window_pos_y);
+
+      *widget_x = x + (window_pos_x - widget->allocation.x);
+      *widget_y = y + (window_pos_y - widget->allocation.y);
+    }
+  else
+    {
+      *widget_x = x - widget->allocation.x;
+      *widget_y = y - widget->allocation.y;
+    }
+}
+
+/**
+ * foreach_hierarchy:
+ * @widget: a #GtkWidget
+ * @x: a coordinate relative to widget->window
+ * @y: a coordinate relative to widget->window
+ * @callback: a function that is called for every mapped child of @widget
+ *    containing (@x, @y), including @widget itself if it contains (@x, @y)
+ *
+ * (x, y) must be in the part of widget->window that isn't clipped by parents
+ **/
+static void
+foreach_hierarchy (GtkWidget *widget,
+		   int	      x,
+		   int	      y,
+		   void    (* callback) (GtkWidget *widget, int x, int y))
+{
+  if (GTK_WIDGET_MAPPED (widget))
+    {
+      int widget_x, widget_y;
+
+      window_to_widget (widget, x, y, &widget_x, &widget_y);
+      
+      if (widget_x >= 0 &&
+	  widget_y >= 0 &&
+	  widget_x <  widget->allocation.width &&
+	  widget_y <  widget->allocation.height)
+	{
+	  callback (widget, widget_x, widget_y);
+	  
+	  if (GTK_IS_CONTAINER (widget))
+	    {
+	      GList *l, *children;
+	      int child_x, child_y;
+
+	      children = gtk_container_get_children (GTK_CONTAINER (widget));
+	      
+	      for (l = children; l != NULL; l = l->next)
+		{
+		  GtkWidget *child = l->data;
+		  GdkWindow *window;
+		  gboolean clipped;
+		  GSList *sl, *windows;
+
+		  /* Compute (child_x, child_y) = (x, y) in coordinates relative to child->window.
+		   *
+		   * We need to walk the windows from the top down, so that we can detect when (x, y)
+		   * is clipped.
+		   */
+		  window = child->window;
+		  windows = NULL;
+		  while (window && window != widget->window)
+		    {
+		      windows = g_slist_prepend (windows, window);
+		      window = gdk_window_get_parent (window);
+		    }
+
+		  child_x = x;
+		  child_y = y;
+
+		  clipped = FALSE;
+		  for (sl = windows; sl != NULL; sl = sl->next)
+		    {
+		      int window_x, window_y;
+		      int window_width, window_height;
+		      
+		      window = sl->data;
+		      
+		      gdk_window_get_position (window, &window_x, &window_y);
+		      gdk_drawable_get_size (window, &window_width, &window_height);
+		      
+		      child_x -= window_x;
+		      child_y -= window_y;
+
+		      if (child_x < 0 || child_y < 0 ||
+			  child_x >= window_width ||
+			  child_y >= window_height)
+			{
+			  clipped = TRUE;
+			  break;
+			}
+		    }
+
+		  g_slist_free (windows);
+		  
+		  if (!clipped)
+		    foreach_hierarchy (child, child_x, child_y, callback);
+		}
+	      
+	      g_list_free (children);
+	    }
+	}
+    }
+}
+
+static void
+mark_had_pointer (GtkWidget *widget, int x, int y)
+{
+  GTK_PRIVATE_SET_FLAG (widget, GTK_HAD_POINTER);
+}
+
+static void
+mark_has_pointer (GtkWidget *widget, int x, int y)
+{
+  GTK_PRIVATE_SET_FLAG (widget, GTK_HAS_POINTER);
+}
+
+static void
+send_global_event (GtkWidget *widget, int x, int y)
+{
+  static int serial = 0;
+
+  serial ++;
+  
+  if (GTK_WIDGET_HAD_POINTER (widget) && 
+      !GTK_WIDGET_HAS_POINTER (widget))
+    {
+#if 0
+      g_print ("%d leave %s\n", serial, gtk_widget_get_name (widget));
+#endif
+      g_signal_emit_by_name (widget, "global_leave", x, y);
+    }
+  
+  if (GTK_WIDGET_HAS_POINTER (widget) &&
+      !GTK_WIDGET_HAD_POINTER (widget))
+    {
+#if 0
+      g_print ("%d enter %s\n", serial, gtk_widget_get_name (widget));
+#endif
+      g_signal_emit_by_name (widget, "global_enter", x, y);
+    }
+  
+  if (GTK_WIDGET_HAS_POINTER (widget) &&
+      GTK_WIDGET_HAD_POINTER (widget))
+    {
+#if 0
+      g_print ("%d motion %s\n", serial, gtk_widget_get_name (widget));
+#endif
+      g_signal_emit_by_name (widget, "global_motion", x, y);
+    }
+  
+  GTK_PRIVATE_UNSET_FLAG (widget, GTK_HAS_POINTER);
+  GTK_PRIVATE_UNSET_FLAG (widget, GTK_HAD_POINTER);
+}
+
+static void
+on_global_motion (GdkWindow *	window,
+		  int		x,
+		  int		y,
+		  double	x_root,
+		  double	y_root,
+		  int		mask,
+		  gpointer	data)
+{
+  GtkWidget *widget = GTK_WIDGET (data);
+  GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (widget);
+
+  int old_x = priv->pointer_x;
+  int old_y = priv->pointer_y;
+
+  priv->pointer_x = x;
+  priv->pointer_y = y;
+
+  foreach_hierarchy (widget, old_x, old_y, mark_had_pointer);
+  foreach_hierarchy (widget, x, y, mark_has_pointer);
+  foreach_hierarchy (widget, old_x, old_y, send_global_event);
+  foreach_hierarchy (widget, x, y, send_global_event);
+}
+
 static void
 gtk_window_realize (GtkWidget *widget)
 {
@@ -4092,6 +4338,8 @@ gtk_window_realize (GtkWidget *widget)
   
   widget->window = gdk_window_new (parent_window, &attributes, attributes_mask);
 
+  gdk_window_set_motion_handler (widget->window, on_global_motion, widget);
+  
   gdk_window_enable_synchronized_configure (widget->window);
     
   gdk_window_set_user_data (widget->window, window);
@@ -5792,7 +6040,7 @@ gtk_window_expose (GtkWidget      *widge
 {
   if (!GTK_WIDGET_APP_PAINTABLE (widget))
     gtk_window_paint (widget, &event->area);
-  
+
   if (GTK_WIDGET_CLASS (parent_class)->expose_event)
     return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
 
