]> Pileus Git - ~andy/gtk/commitdiff
Initial version of input support
authorAlexander Larsson <alexl@redhat.com>
Fri, 29 May 2009 14:39:12 +0000 (16:39 +0200)
committerAlexander Larsson <alexl@redhat.com>
Fri, 29 May 2009 14:39:12 +0000 (16:39 +0200)
12 files changed:
gdk/gdkdisplay.h
gdk/gdkinternals.h
gdk/gdkwindow.c
gdk/gdkwindowimpl.h
gdk/x11/gdkdisplay-x11.h
gdk/x11/gdkevents-x11.c
gdk/x11/gdkinput-x11.c
gdk/x11/gdkinput-xfree.c
gdk/x11/gdkinput.c
gdk/x11/gdkinputprivate.h
gdk/x11/gdkmain-x11.c
gdk/x11/gdkwindow-x11.c

index 3c7bde322fdaa739da9e7d59951099da1a95f0e6..2838d44a02752bec47186c50d8638b9803bb174c 100644 (file)
@@ -91,6 +91,7 @@ struct _GdkDisplay
   const GdkDisplayPointerHooks *pointer_hooks; /* Current hooks for querying pointer */
   
   guint closed : 1;            /* Whether this display has been closed */
+  guint ignore_core_events : 1; /* Don't send core motion and button event */
 
   guint double_click_distance; /* Maximum distance between clicks in pixels */
   gint button_x[2];             /* The last 2 button click positions. */
index 94cce6aa0d177df74fc06c622ab038d1ca0d4fc9..a0c2d518df7ffcaf8f6217ec4bd740cba52bb96b 100644 (file)
@@ -187,6 +187,7 @@ typedef struct
   gboolean grab_one_pointer_release_event;
 } GdkPointerGrabInfo;
 
+typedef struct _GdkInputWindow GdkInputWindow;
 
 /* Private version of GdkWindowObject. The initial part of this strucuture
    is public for historical reasons. Don't change that part */
@@ -260,6 +261,7 @@ struct _GdkWindowObject
   guint native_visibility : 2; /* the native visibility of a impl windows */
 
   GdkWindowPaint *implicit_paint;
+  GdkInputWindow *input_window; /* only for impl windows */
 
   GList *outstanding_moves;
 
@@ -640,6 +642,10 @@ GdkRegion *_gdk_window_calculate_full_clip_region    (GdkWindow     *window,
                                                       gint          *base_y_offset);
 gboolean    _gdk_window_has_impl (GdkWindow *window);
 GdkWindow * _gdk_window_get_impl_window (GdkWindow *window);
+GdkWindow *_gdk_window_get_input_window_for_event (GdkWindow *native_window,
+                                                  GdkEventType event_type,
+                                                  int x, int y,
+                                                  gulong serial);
 GdkRegion  *_gdk_region_new_from_yxbanded_rects (GdkRectangle *rects, int n_rects);
 
 /*****************************
index a2b5d6d618aff7ceb1c921706e815039a4249f36..b20cf6950295748fb90866df9b640d2f1d88b072 100644 (file)
@@ -1596,6 +1596,10 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
                                           NULL, NULL);
            }
 
+
+         if (private->extension_events)
+           GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_window_destroy (window);
+
          if (gdk_window_has_impl (private))
            {
              GDK_WINDOW_IMPL_GET_IFACE (private->impl)->destroy (window, recursing_native, foreign_destroy);
@@ -8240,6 +8244,10 @@ send_crossing_event (GdkDisplay                 *display,
   else
     event_mask = GDK_ENTER_NOTIFY_MASK;
 
+  if (window->extension_events != 0)
+    GDK_WINDOW_IMPL_GET_IFACE (window->impl)->input_window_crossing (window,
+                                                                    type == GDK_ENTER_NOTIFY);
+
   if (window->event_mask & event_mask)
     {
       event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, TRUE);
@@ -8724,7 +8732,7 @@ proxy_pointer_event (GdkDisplay                 *display,
            }
        }
       
-      if (event_win)
+      if (event_win && !display->ignore_core_events)
        {
          event = _gdk_make_event (event_win, GDK_MOTION_NOTIFY, source_event, FALSE);
          event->motion.time = time_;
@@ -8814,7 +8822,7 @@ proxy_button_event (GdkEvent *source_event,
                                type, state,
                                NULL, serial);
 
-  if (event_win == NULL)
+  if (event_win == NULL || display->ignore_core_events)
     return TRUE;
   
   event = _gdk_make_event (event_win, type, source_event, FALSE);
@@ -8914,6 +8922,22 @@ gdk_window_print_tree (GdkWindow *window,
 
 #endif /* DEBUG_WINDOW_PRINTING */
 
+static gboolean
+is_input_event (GdkDisplay *display,
+               GdkEvent *event)
+{
+  GdkDevice *core_pointer;
+
+  core_pointer = gdk_display_get_core_pointer (display);
+  if ((event->type == GDK_MOTION_NOTIFY &&
+       event->motion.device != core_pointer) ||
+      (event->type == GDK_BUTTON_PRESS ||
+       event->type == GDK_BUTTON_RELEASE) &&
+      event->button.device != core_pointer)
+    return TRUE;
+  return FALSE;
+}
+
 void
 _gdk_windowing_got_event (GdkDisplay *display,
                          GList      *event_link,
@@ -8958,6 +8982,9 @@ _gdk_windowing_got_event (GdkDisplay *display,
       return;
     }
 
+  if (is_input_event (display, event))
+    return;
+
   if (!(is_button_type (event->type) ||
        is_motion_type (event->type)) ||
       GDK_WINDOW_TYPE (event_private) == GDK_WINDOW_ROOT)
@@ -9075,5 +9102,87 @@ _gdk_windowing_got_event (GdkDisplay *display,
     }
 }
 
+
+static GdkWindow *
+get_extension_event_window (GdkDisplay                 *display,
+                           GdkWindow                  *pointer_window,
+                           GdkEventType                type,
+                           gulong                      serial)
+{
+  guint evmask;
+  GdkWindow *grab_window;
+  GdkWindowObject *w;
+  GdkPointerGrabInfo *grab;
+
+  grab = _gdk_display_has_pointer_grab (display, serial);
+
+  if (grab != NULL && !grab->owner_events)
+    {
+      evmask = grab->event_mask;
+
+      grab_window = grab->window;
+
+      if (evmask & type_masks[type])
+       return grab_window;
+      else
+       return NULL;
+    }
+
+  w = (GdkWindowObject *)pointer_window;
+  while (w != NULL)
+    {
+      evmask = w->extension_events;
+
+      if (evmask & type_masks[type])
+       return (GdkWindow *)w;
+
+      w = w->parent;
+    }
+
+  if (grab != NULL &&
+      grab->owner_events)
+    {
+      evmask = grab->event_mask;
+
+      if (evmask & type_masks[type])
+       return grab->window;
+      else
+       return NULL;
+    }
+
+  return NULL;
+}
+
+
+GdkWindow *
+_gdk_window_get_input_window_for_event (GdkWindow *native_window,
+                                       GdkEventType event_type,
+                                       int x, int y,
+                                       gulong serial)
+{
+  GdkDisplay *display;
+  GdkWindow *toplevel_window;
+  GdkWindow *pointer_window;
+  GdkWindow *event_win;
+  gdouble toplevel_x, toplevel_y;
+
+  toplevel_x = x;
+  toplevel_y = y;
+
+  display = gdk_drawable_get_display (native_window);
+  toplevel_window = convert_coords_to_toplevel (native_window,
+                                               toplevel_x, toplevel_y,
+                                               &toplevel_x, &toplevel_y);
+  pointer_window = get_pointer_window (display, toplevel_window,
+                                      toplevel_x, toplevel_y, serial);
+  event_win = get_extension_event_window (display,
+                                         pointer_window,
+                                         event_type,
+                                         serial);
+
+  return event_win;
+}
+
+
 #define __GDK_WINDOW_C__
 #include "gdkaliasdef.c"
index d63e5a1ff3352caad433001c45e63c11602ed27b..1bedb3589972d4fbfc0fe69d166425d0c387433f 100644 (file)
@@ -128,6 +128,10 @@ struct _GdkWindowImplIface
   void         (* destroy)              (GdkWindow       *window,
                                         gboolean         recursing,
                                         gboolean         foreign_destroy);
+
+  void         (* input_window_destroy) (GdkWindow       *window);
+  void         (* input_window_crossing)(GdkWindow       *window,
+                                        gboolean         enter);
 };
 
 /* Interface Functions */
index e92418d379c19dfdf39d44b0b8b36562a2dd67f2..2873c2d67482d593552b4248cb0bcafea9e015cb 100644 (file)
@@ -133,11 +133,6 @@ struct _GdkDisplayX11
   /* input GdkWindow list */
   GList *input_windows;
 
-  gint input_ignore_core;
-  /* information about network port and host for gxid daemon */
-  gchar *input_gxid_host;
-  gint   input_gxid_port;
-
   /* Startup notification */
   gchar *startup_notification_id;
 
index 8d3141a8ee2b79b0b0c96942d24e7b9be8cb80fb..4565b3961b7be4fbe3d243da70af2818eb4505b6 100644 (file)
@@ -1125,9 +1125,7 @@ gdk_event_translate (GdkDisplay *display,
                           xevent->xbutton.x, xevent->xbutton.y,
                           xevent->xbutton.button));
       
-      if (window_private == NULL || 
-         ((window_private->extension_events != 0) &&
-           display_x11->input_ignore_core))
+      if (window_private == NULL)
        {
          return_val = FALSE;
          break;
@@ -1201,9 +1199,7 @@ gdk_event_translate (GdkDisplay *display,
                           xevent->xbutton.x, xevent->xbutton.y,
                           xevent->xbutton.button));
       
-      if (window_private == NULL ||
-         ((window_private->extension_events != 0) &&
-           display_x11->input_ignore_core))
+      if (window_private == NULL)
        {
          return_val = FALSE;
          break;
@@ -1241,9 +1237,7 @@ gdk_event_translate (GdkDisplay *display,
                           xevent->xmotion.x, xevent->xmotion.y,
                           (xevent->xmotion.is_hint) ? "true" : "false"));
       
-      if (window_private == NULL ||
-         ((window_private->extension_events != 0) &&
-           display_x11->input_ignore_core))
+      if (window_private == NULL)
        {
          return_val = FALSE;
          break;
@@ -1304,12 +1298,6 @@ gdk_event_translate (GdkDisplay *display,
            }
        }
 
-      /* Tell XInput stuff about it if appropriate */
-      if (window_private &&
-         !GDK_WINDOW_DESTROYED (window) &&
-         window_private->extension_events != 0)
-       _gdk_input_enter_event (&xevent->xcrossing, window);
-      
       event->crossing.type = GDK_ENTER_NOTIFY;
       event->crossing.window = window;
       
@@ -1854,7 +1842,7 @@ gdk_event_translate (GdkDisplay *display,
       if (window &&
          xevent->xconfigure.event == xevent->xconfigure.window &&
          !GDK_WINDOW_DESTROYED (window) &&
-         (window_private->extension_events != 0))
+         window_private->input_window != NULL)
        _gdk_input_configure_event (&xevent->xconfigure, window);
       
 #ifdef HAVE_XSYNC
@@ -2171,8 +2159,8 @@ gdk_event_translate (GdkDisplay *display,
          
          if (window_private &&
              !GDK_WINDOW_DESTROYED (window_private) &&
-             (window_private->extension_events != 0))
-           return_val = _gdk_input_other_event(event, xevent, window);
+             window_private->input_window)
+           return_val = _gdk_input_other_event (event, xevent, window);
          else
            return_val = FALSE;
          
index 9e2d81889fad911e868bc5c9e5a061bc4735b6b3..22e39a05c715778bce8f5a68d397e44994e66f6f 100644 (file)
@@ -21,7 +21,7 @@
  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
  * file for a list of people on the GTK+ Team.  See the ChangeLog
  * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
  */
 
 #include "config.h"
@@ -39,7 +39,7 @@ static GdkDevicePrivate *gdk_input_device_new            (GdkDisplay       *disp
                                                          XDeviceInfo      *device,
                                                          gint              include_core);
 static void              gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
-                                                         GdkInputWindow   *input_window,
+                                                         GdkWindow        *window,
                                                          gint             *axis_data,
                                                          gdouble          *axis_out,
                                                          gdouble          *x_out,
@@ -64,37 +64,26 @@ _gdk_input_find_device (GdkDisplay *display,
 }
 
 void
-_gdk_input_get_root_relative_geometry(Display *display, Window w, int *x_ret, int *y_ret,
-                                     int *width_ret, int *height_ret)
+_gdk_input_get_root_relative_geometry (GdkWindow *window,
+                                      int *x_ret, int *y_ret)
 {
-  Window root, parent, child;
-  Window *children;
-  guint nchildren;
+  Window child;
   gint x,y;
-  guint width, height;
-  guint border_widthc, depthc;
-   
-  XQueryTree (display, w, &root, &parent, &children, &nchildren);
-  if (children)
-    XFree(children);
-  
-  XGetGeometry (display, w, &root, &x, &y, &width, &height, &border_widthc, &depthc);
-
-  XTranslateCoordinates (display, w, root, 0, 0, &x, &y, &child);
+
+  XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
+                        GDK_WINDOW_XWINDOW (window),
+                        GDK_WINDOW_XROOTWIN (window),
+                        0, 0, &x, &y, &child);
+
   if (x_ret)
     *x_ret = x;
   if (y_ret)
     *y_ret = y;
-  if (width_ret)
-    *width_ret = width;
-  if (height_ret)
-    *height_ret = height;
 }
 
 static GdkDevicePrivate *
 gdk_input_device_new (GdkDisplay  *display,
-                     XDeviceInfo *device, 
+                     XDeviceInfo *device,
                      gint         include_core)
 {
   GdkDevicePrivate *gdkdev;
@@ -121,7 +110,7 @@ gdk_input_device_new (GdkDisplay  *display,
      for comparison purposes */
 
   tmp_name = g_ascii_strdown (gdkdev->info.name, -1);
-  
+
   if (!strcmp (tmp_name, "pointer"))
     gdkdev->info.source = GDK_SOURCE_MOUSE;
   else if (!strcmp (tmp_name, "wacom") ||
@@ -151,7 +140,7 @@ gdk_input_device_new (GdkDisplay  *display,
   gdkdev->button_state = 0;
 
   class = device->inputclassinfo;
-  for (i=0;i<device->num_classes;i++) 
+  for (i=0;i<device->num_classes;i++)
     {
       switch (class->class) {
       case ButtonClass:
@@ -160,7 +149,7 @@ gdk_input_device_new (GdkDisplay  *display,
        {
          XKeyInfo *xki = (XKeyInfo *)class;
          /* Hack to catch XFree86 3.3.1 bug. Other devices better
-          * not have exactly 25 keys... 
+          * not have exactly 25 keys...
           */
          if ((xki->min_keycode == 8) && (xki->max_keycode == 32))
            {
@@ -190,7 +179,7 @@ gdk_input_device_new (GdkDisplay  *display,
          gdkdev->info.axes = g_new0 (GdkDeviceAxis, xvi->num_axes);
          for (j=0;j<xvi->num_axes;j++)
            {
-             gdkdev->axes[j].resolution = 
+             gdkdev->axes[j].resolution =
                gdkdev->axes[j].xresolution = xvi->axes[j].resolution;
              gdkdev->axes[j].min_value =
                gdkdev->axes[j].xmin_value = xvi->axes[j].min_value;
@@ -211,7 +200,7 @@ gdk_input_device_new (GdkDisplay  *display,
            gdk_device_set_axis_use (&gdkdev->info, j++, GDK_AXIS_YTILT);
          if (j<xvi->num_axes)
            gdk_device_set_axis_use (&gdkdev->info, j++, GDK_AXIS_WHEEL);
-                      
+
          break;
        }
       }
@@ -247,20 +236,19 @@ gdk_input_device_new (GdkDisplay  *display,
  error:
 
   g_object_unref (gdkdev);
-  
+
   return NULL;
 }
 
 void
-_gdk_input_common_find_events(GdkWindow *window,
-                             GdkDevicePrivate *gdkdev,
-                             gint mask,
-                             XEventClass *classes,
-                             int *num_classes)
+_gdk_input_common_find_events (GdkDevicePrivate *gdkdev,
+                              gint mask,
+                              XEventClass *classes,
+                              int *num_classes)
 {
   gint i;
   XEventClass class;
-  
+
   i = 0;
   if (mask & GDK_BUTTON_PRESS_MASK)
     {
@@ -354,25 +342,42 @@ _gdk_input_common_find_events(GdkWindow *window,
 }
 
 void
-_gdk_input_common_select_events(GdkWindow *window,
-                               GdkDevicePrivate *gdkdev)
+_gdk_input_select_events (GdkWindow *impl_window,
+                         GdkDevicePrivate *gdkdev)
 {
   XEventClass classes[GDK_MAX_DEVICE_CLASSES];
   gint num_classes;
+  guint event_mask;
+  GdkWindowObject *w;
+  GdkInputWindow *iw;
+  GList *l;
 
-  if (gdkdev->info.mode == GDK_MODE_DISABLED)
-    _gdk_input_common_find_events(window, gdkdev, 0, classes, &num_classes);
-  else
-    _gdk_input_common_find_events(window, gdkdev, 
-                                 ((GdkWindowObject *)window)->extension_events,
-                                 classes, &num_classes);
-  
-  XSelectExtensionEvent (GDK_WINDOW_XDISPLAY (window),
-                        GDK_WINDOW_XWINDOW (window),
+  event_mask = 0;
+  iw = ((GdkWindowObject *)impl_window)->input_window;
+
+  if (gdkdev->info.mode != GDK_MODE_DISABLED &&
+      iw != NULL)
+    {
+      for (l = iw->windows; l != NULL; l = l->next)
+       {
+         w = l->data;
+         if (gdkdev->info.has_cursor || (w->extension_events & GDK_ALL_DEVICES_MASK))
+           event_mask |= w->extension_events;
+       }
+    }
+  event_mask &= ~GDK_ALL_DEVICES_MASK;
+
+  if (event_mask)
+    event_mask |= GDK_PROXIMITY_OUT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK;
+
+  _gdk_input_common_find_events (gdkdev, event_mask,
+                                classes, &num_classes);
+  XSelectExtensionEvent (GDK_WINDOW_XDISPLAY (impl_window),
+                        GDK_WINDOW_XWINDOW (impl_window),
                         classes, num_classes);
 }
 
-gint 
+gint
 _gdk_input_common_init (GdkDisplay *display,
                        gint        include_core)
 {
@@ -391,7 +396,7 @@ _gdk_input_common_init (GdkDisplay *display,
                                            event_base, 15 /* Number of events */);
 
       devices = XListInputDevices(display_x11->xdisplay, &num_devices);
-  
+
       for(loop=0; loop<num_devices; loop++)
        {
          GdkDevicePrivate *gdkdev = gdk_input_device_new(display,
@@ -410,21 +415,23 @@ _gdk_input_common_init (GdkDisplay *display,
 
 static void
 gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
-                                GdkInputWindow   *input_window,
+                                GdkWindow        *window,
                                 gint             *axis_data,
                                 gdouble          *axis_out,
                                 gdouble          *x_out,
                                 gdouble          *y_out)
 {
-  GdkWindowObject *window_private;
+  GdkWindowObject *priv, *impl_window;
+
   int i;
   int x_axis = 0;
   int y_axis = 0;
 
   double device_width, device_height;
   double x_offset, y_offset, x_scale, y_scale;
-  
-  window_private = (GdkWindowObject *) input_window->window;
+
+  priv = (GdkWindowObject *) window;
+  impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
 
   for (i=0; i<gdkdev->info.num_axes; i++)
     {
@@ -440,26 +447,24 @@ gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
          break;
        }
     }
-  
-  device_width = gdkdev->axes[x_axis].max_value - 
-                  gdkdev->axes[x_axis].min_value;
-  device_height = gdkdev->axes[y_axis].max_value - 
-                    gdkdev->axes[y_axis].min_value;
 
-  if (gdkdev->info.mode == GDK_MODE_SCREEN) 
+  device_width = gdkdev->axes[x_axis].max_value - gdkdev->axes[x_axis].min_value;
+  device_height = gdkdev->axes[y_axis].max_value - gdkdev->axes[y_axis].min_value;
+
+  if (gdkdev->info.mode == GDK_MODE_SCREEN)
     {
-      x_scale = gdk_screen_get_width (gdk_drawable_get_screen (input_window->window)) / device_width;
-      y_scale = gdk_screen_get_height (gdk_drawable_get_screen (input_window->window)) / device_height;
+      x_scale = gdk_screen_get_width (gdk_drawable_get_screen (window)) / device_width;
+      y_scale = gdk_screen_get_height (gdk_drawable_get_screen (window)) / device_height;
 
-      x_offset = - input_window->root_x;
-      y_offset = - input_window->root_y;
+      x_offset = - impl_window->input_window->root_x;
+      y_offset = - impl_window->input_window->root_y;
     }
   else                         /* GDK_MODE_WINDOW */
     {
       double x_resolution = gdkdev->axes[x_axis].resolution;
       double y_resolution = gdkdev->axes[y_axis].resolution;
       double device_aspect;
-      /* 
+      /*
        * Some drivers incorrectly report the resolution of the device
        * as zero (in partiular linuxwacom < 0.5.3 with usb tablets).
        * This causes the device_aspect to become NaN and totally
@@ -475,27 +480,24 @@ gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
          y_resolution = 1;
        }
       device_aspect = (device_height*y_resolution) /
-        (device_width*x_resolution);
-      if (device_aspect * window_private->width >= window_private->height)
+       (device_width*x_resolution);
+      if (device_aspect * priv->width >= priv->height)
        {
          /* device taller than window */
-         x_scale = window_private->width / device_width;
-         y_scale = (x_scale * x_resolution)
-           / y_resolution;
+         x_scale = priv->width / device_width;
+         y_scale = (x_scale * x_resolution) / y_resolution;
 
          x_offset = 0;
-         y_offset = -(device_height * y_scale - 
-                      window_private->height)/2;
+         y_offset = -(device_height * y_scale -  priv->height)/2;
        }
       else
        {
          /* window taller than device */
-         y_scale = window_private->height / device_height;
-         x_scale = (y_scale * y_resolution)
-           / x_resolution;
+         y_scale = priv->height / device_height;
+         x_scale = (y_scale * y_resolution) / x_resolution;
 
          y_offset = 0;
-         x_offset = - (device_width * x_scale - window_private->width)/2;
+         x_offset = - (device_width * x_scale - priv->width)/2;
        }
     }
 
@@ -504,13 +506,13 @@ gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
       switch (gdkdev->info.axes[i].use)
        {
        case GDK_AXIS_X:
-         axis_out[i] = x_offset + x_scale * (axis_data[x_axis] - 
+         axis_out[i] = x_offset + x_scale * (axis_data[x_axis] -
            gdkdev->axes[x_axis].min_value);
          if (x_out)
            *x_out = axis_out[i];
          break;
        case GDK_AXIS_Y:
-         axis_out[i] = y_offset + y_scale * (axis_data[y_axis] - 
+         axis_out[i] = y_offset + y_scale * (axis_data[y_axis] -
            gdkdev->axes[y_axis].min_value);
          if (y_out)
            *y_out = axis_out[i];
@@ -541,11 +543,18 @@ gdk_input_translate_state(guint state, guint device_state)
 gboolean
 _gdk_input_common_other_event (GdkEvent         *event,
                               XEvent           *xevent,
-                              GdkInputWindow   *input_window,
+                              GdkWindow        *window,
                               GdkDevicePrivate *gdkdev)
 {
+  GdkWindowObject *priv, *impl_window;
+  GdkInputWindow *input_window;
+
+  priv = (GdkWindowObject *) window;
+  impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
+  input_window = impl_window->input_window;
+
   if ((xevent->type == gdkdev->buttonpress_type) ||
-      (xevent->type == gdkdev->buttonrelease_type)) 
+      (xevent->type == gdkdev->buttonrelease_type))
     {
       XDeviceButtonEvent *xdbe = (XDeviceButtonEvent *)(xevent);
 
@@ -560,16 +569,16 @@ _gdk_input_common_other_event (GdkEvent         *event,
          gdkdev->button_state &= ~(1 << xdbe->button);
        }
       event->button.device = &gdkdev->info;
-      event->button.window = input_window->window;
+      event->button.window = window;
       event->button.time = xdbe->time;
 
       event->button.axes = g_new (gdouble, gdkdev->info.num_axes);
-      gdk_input_translate_coordinates (gdkdev,input_window, xdbe->axis_data,
-                                      event->button.axes, 
-                                      &event->button.x,&event->button.y);
-      event->button.x_root = event->button.x + input_window->root_x;
-      event->button.y_root = event->button.y + input_window->root_y;
-      event->button.state = gdk_input_translate_state(xdbe->state,xdbe->device_state);
+      gdk_input_translate_coordinates (gdkdev, window, xdbe->axis_data,
+                                      event->button.axes,
+                                      &event->button.x, &event->button.y);
+      event->button.x_root = event->button.x + priv->abs_x + input_window->root_x;
+      event->button.y_root = event->button.y + priv->abs_y + input_window->root_y;
+      event->button.state = gdk_input_translate_state (xdbe->state,xdbe->device_state);
       event->button.button = xdbe->button;
 
       if (event->button.type == GDK_BUTTON_PRESS)
@@ -588,8 +597,8 @@ _gdk_input_common_other_event (GdkEvent         *event,
        * a valid timestamp.
        */
       if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
-        gdk_x11_window_set_user_time (gdk_window_get_toplevel (input_window->window),
-                                      gdk_event_get_time (event));
+       gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
+                                     gdk_event_get_time (event));
       return TRUE;
   }
 
@@ -611,21 +620,21 @@ _gdk_input_common_other_event (GdkEvent         *event,
          g_warning ("Invalid device key code received");
          return FALSE;
        }
-      
+
       event->key.keyval = gdkdev->info.keys[xdke->keycode - gdkdev->min_keycode].keyval;
 
-      if (event->key.keyval == 0) 
+      if (event->key.keyval == 0)
        {
          GDK_NOTE (EVENTS,
            g_print ("\t\ttranslation - NONE\n"));
-         
+
          return FALSE;
        }
 
       event->key.type = (xdke->type == gdkdev->keypress_type) ?
        GDK_KEY_PRESS : GDK_KEY_RELEASE;
 
-      event->key.window = input_window->window;
+      event->key.window = window;
       event->key.time = xdke->time;
 
       event->key.state = gdk_input_translate_state(xdke->state, xdke->device_state)
@@ -654,26 +663,26 @@ _gdk_input_common_other_event (GdkEvent         *event,
        * a valid timestamp.
        */
       if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
-        gdk_x11_window_set_user_time (gdk_window_get_toplevel (input_window->window),
-                                      gdk_event_get_time (event));
+       gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
+                                     gdk_event_get_time (event));
       return TRUE;
     }
 
-  if (xevent->type == gdkdev->motionnotify_type) 
+  if (xevent->type == gdkdev->motionnotify_type)
     {
       XDeviceMotionEvent *xdme = (XDeviceMotionEvent *)(xevent);
 
       event->motion.device = &gdkdev->info;
-      
+
       event->motion.axes = g_new (gdouble, gdkdev->info.num_axes);
-      gdk_input_translate_coordinates(gdkdev,input_window,xdme->axis_data,
+      gdk_input_translate_coordinates(gdkdev,window,xdme->axis_data,
                                      event->motion.axes,
                                      &event->motion.x,&event->motion.y);
-      event->motion.x_root = event->motion.x + input_window->root_x;
-      event->motion.y_root = event->motion.y + input_window->root_y;
+      event->motion.x_root = event->motion.x + priv->abs_x + input_window->root_x;
+      event->motion.y_root = event->motion.y + priv->abs_y + input_window->root_y;
 
       event->motion.type = GDK_MOTION_NOTIFY;
-      event->motion.window = input_window->window;
+      event->motion.window = window;
       event->motion.time = xdme->time;
       event->motion.state = gdk_input_translate_state(xdme->state,
                                                      xdme->device_state);
@@ -686,14 +695,14 @@ _gdk_input_common_other_event (GdkEvent         *event,
                 event->motion.x, event->motion.y,
                 event->motion.state,
                 (xdme->is_hint) ? "true" : "false"));
-      
-      
+
+
       /* Update the timestamp of the latest user interaction, if the event has
        * a valid timestamp.
        */
       if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
-        gdk_x11_window_set_user_time (gdk_window_get_toplevel (input_window->window),
-                                      gdk_event_get_time (event));
+       gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
+                                     gdk_event_get_time (event));
       return TRUE;
     }
 
@@ -704,16 +713,16 @@ _gdk_input_common_other_event (GdkEvent         *event,
 
       event->proximity.device = &gdkdev->info;
       event->proximity.type = (xevent->type == gdkdev->proximityin_type)?
-       GDK_PROXIMITY_IN:GDK_PROXIMITY_OUT;
-      event->proximity.window = input_window->window;
+       GDK_PROXIMITY_IN:GDK_PROXIMITY_OUT;
+      event->proximity.window = window;
       event->proximity.time = xpne->time;
-      
+
       /* Update the timestamp of the latest user interaction, if the event has
        * a valid timestamp.
        */
       if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
-        gdk_x11_window_set_user_time (gdk_window_get_toplevel (input_window->window),
-                                      gdk_event_get_time (event));
+       gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
+                                     gdk_event_get_time (event));
       return TRUE;
   }
 
@@ -730,18 +739,17 @@ _gdk_device_get_history (GdkDevice         *device,
 {
   GdkTimeCoord **coords;
   XDeviceTimeCoord *device_coords;
-  GdkInputWindow *input_window;
+  GdkWindow *impl_window;
   GdkDevicePrivate *gdkdev;
   gint mode_return;
   gint axis_count_return;
   gint i;
 
   gdkdev = (GdkDevicePrivate *)device;
-  input_window = _gdk_input_window_find (window);
 
-  g_return_val_if_fail (input_window != NULL, FALSE);
+  impl_window = _gdk_window_get_impl_window (window);
 
-  device_coords = XGetDeviceMotionEvents (GDK_WINDOW_XDISPLAY (window),
+  device_coords = XGetDeviceMotionEvents (GDK_WINDOW_XDISPLAY (impl_window),
                                          gdkdev->xdevice,
                                          start, stop,
                                          n_events, &mode_return,
@@ -752,13 +760,13 @@ _gdk_device_get_history (GdkDevice         *device,
       coords = _gdk_device_allocate_history (device, *n_events);
 
       for (i = 0; i < *n_events; i++)
-        {
-          coords[i]->time = device_coords[i].time;
+       {
+         coords[i]->time = device_coords[i].time;
 
-          gdk_input_translate_coordinates (gdkdev, input_window,
-                                           device_coords[i].data,
-                                           coords[i]->axes, NULL, NULL);
-        }
+         gdk_input_translate_coordinates (gdkdev, window,
+                                          device_coords[i].data,
+                                          coords[i]->axes, NULL, NULL);
+       }
 
       XFreeDeviceMotionEvents (device_coords);
 
@@ -770,7 +778,7 @@ _gdk_device_get_history (GdkDevice         *device,
     return FALSE;
 }
 
-void 
+void
 gdk_device_get_state (GdkDevice       *device,
                      GdkWindow       *window,
                      gdouble         *axes,
@@ -784,7 +792,7 @@ gdk_device_get_state (GdkDevice       *device,
   if (GDK_IS_CORE (device))
     {
       gint x_int, y_int;
-      
+
       gdk_window_get_pointer (window, &x_int, &y_int, mask);
 
       if (axes)
@@ -796,16 +804,13 @@ gdk_device_get_state (GdkDevice       *device,
   else
     {
       GdkDevicePrivate *gdkdev;
-      GdkInputWindow *input_window;
       XDeviceState *state;
       XInputClass *input_class;
-      
+
       if (mask)
        gdk_window_get_pointer (window, NULL, NULL, mask);
-      
+
       gdkdev = (GdkDevicePrivate *)device;
-      input_window = _gdk_input_window_find (window);
-      g_return_if_fail (input_window != NULL);
 
       state = XQueryDeviceState (GDK_WINDOW_XDISPLAY (window),
                                 gdkdev->xdevice);
@@ -816,11 +821,11 @@ gdk_device_get_state (GdkDevice       *device,
            {
            case ValuatorClass:
              if (axes)
-               gdk_input_translate_coordinates (gdkdev, input_window,
+               gdk_input_translate_coordinates (gdkdev, window,
                                                 ((XValuatorState *)input_class)->valuators,
                                                 axes, NULL, NULL);
              break;
-             
+
            case ButtonClass:
              if (mask)
                {
index b51516b3e1d5367083bd528da31adb309a6b046f..10fd33d919d8aa15e533b490c6a37cc935cac7ca 100644 (file)
  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
  * file for a list of people on the GTK+ Team.  See the ChangeLog
  * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
  */
 
 /* forward declarations */
 
 static void gdk_input_check_proximity (GdkDisplay *display);
 
-void 
+void
 _gdk_input_init(GdkDisplay *display)
 {
   _gdk_init_input_core (display);
-  GDK_DISPLAY_X11 (display)->input_ignore_core = FALSE;
+  display->ignore_core_events = FALSE;
   _gdk_input_common_init (display, FALSE);
 }
 
@@ -47,7 +47,6 @@ gdk_device_set_mode (GdkDevice      *device,
 {
   GList *tmp_list;
   GdkDevicePrivate *gdkdev;
-  GdkInputMode old_mode;
   GdkInputWindow *input_window;
   GdkDisplayX11 *display_impl;
 
@@ -59,58 +58,35 @@ gdk_device_set_mode (GdkDevice      *device,
   if (device->mode == mode)
     return TRUE;
 
-  old_mode = device->mode;
   device->mode = mode;
 
-  display_impl = GDK_DISPLAY_X11 (gdkdev->display);
-
   if (mode == GDK_MODE_WINDOW)
-    {
-      device->has_cursor = FALSE;
-      for (tmp_list = display_impl->input_windows; tmp_list; tmp_list = tmp_list->next)
-       {
-         input_window = (GdkInputWindow *)tmp_list->data;
-         if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
-           _gdk_input_enable_window (input_window->window, gdkdev);
-         else
-           if (old_mode != GDK_MODE_DISABLED)
-             _gdk_input_disable_window (input_window->window, gdkdev);
-       }
-    }
+    device->has_cursor = FALSE;
   else if (mode == GDK_MODE_SCREEN)
+    device->has_cursor = TRUE;
+
+  display_impl = GDK_DISPLAY_X11 (gdkdev->display);
+  for (tmp_list = display_impl->input_windows; tmp_list; tmp_list = tmp_list->next)
     {
-      device->has_cursor = TRUE;
-      for (tmp_list = display_impl->input_windows; tmp_list; tmp_list = tmp_list->next)
-       _gdk_input_enable_window (((GdkInputWindow *)tmp_list->data)->window,
-                                 gdkdev);
-    }
-  else  /* mode == GDK_MODE_DISABLED */
-    {
-      for (tmp_list = display_impl->input_windows; tmp_list; tmp_list = tmp_list->next)
-       {
-         input_window = (GdkInputWindow *)tmp_list->data;
-         if (old_mode != GDK_MODE_WINDOW ||
-             input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
-           _gdk_input_disable_window (input_window->window, gdkdev);
-       }
+      input_window = (GdkInputWindow *)tmp_list->data;
+      _gdk_input_select_events (input_window->impl_window, gdkdev);
     }
 
   return TRUE;
-  
 }
 
 static void
 gdk_input_check_proximity (GdkDisplay *display)
 {
-  gint new_proximity = 0;
   GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (display);
   GList *tmp_list = display_impl->input_devices;
+  gint new_proximity = 0;
 
-  while (tmp_list && !new_proximity) 
+  while (tmp_list && !new_proximity)
     {
       GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
 
-      if (gdkdev->info.mode != GDK_MODE_DISABLED 
+      if (gdkdev->info.mode != GDK_MODE_DISABLED
          && !GDK_IS_CORE (gdkdev)
          && gdkdev->xdevice)
        {
@@ -118,7 +94,7 @@ gdk_input_check_proximity (GdkDisplay *display)
                                                  gdkdev->xdevice);
          XInputClass *xic;
          int i;
-         
+
          xic = state->data;
          for (i=0; i<state->num_classes; i++)
            {
@@ -135,117 +111,197 @@ gdk_input_check_proximity (GdkDisplay *display)
            }
 
          XFreeDeviceState (state);
-       }
+       }
       tmp_list = tmp_list->next;
     }
 
-  display_impl->input_ignore_core = new_proximity;
+  display->ignore_core_events = new_proximity;
 }
 
 void
 _gdk_input_configure_event (XConfigureEvent *xevent,
                            GdkWindow       *window)
 {
+  GdkWindowObject *priv = (GdkWindowObject *)window;
   GdkInputWindow *input_window;
   gint root_x, root_y;
 
-  input_window = _gdk_input_window_find(window);
-  g_return_if_fail (input_window != NULL);
-
-  _gdk_input_get_root_relative_geometry(GDK_WINDOW_XDISPLAY (window),
-                                       GDK_WINDOW_XWINDOW (window),
-                                       &root_x, &root_y, NULL, NULL);
-
-  input_window->root_x = root_x;
-  input_window->root_y = root_y;
+  input_window = priv->input_window;
+  if (input_window != NULL)
+    {
+      _gdk_input_get_root_relative_geometry (window, &root_x, &root_y);
+      input_window->root_x = root_x;
+      input_window->root_y = root_y;
+    }
 }
 
-void 
-_gdk_input_enter_event (XCrossingEvent *xevent, 
-                       GdkWindow      *window)
+void
+_gdk_input_crossing_event (GdkWindow *window,
+                          gboolean enter)
 {
+  GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
+  GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (display);
+  GdkWindowObject *priv = (GdkWindowObject *)window;
   GdkInputWindow *input_window;
   gint root_x, root_y;
 
-  input_window = _gdk_input_window_find (window);
-  g_return_if_fail (input_window != NULL);
+  if (enter)
+    {
+      gdk_input_check_proximity(display);
+
+      input_window = priv->input_window;
+      if (input_window != NULL)
+       {
+         _gdk_input_get_root_relative_geometry (window, &root_x, &root_y);
+         input_window->root_x = root_x;
+         input_window->root_y = root_y;
+       }
+    }
+  else
+    display->ignore_core_events = FALSE;
+}
+
+static GdkEventType
+get_input_event_type (GdkDevicePrivate *gdkdev,
+                     XEvent *xevent,
+                     int *core_x, int *core_y)
+{
+  if (xevent->type == gdkdev->buttonpress_type)
+    {
+      XDeviceButtonEvent *xie = (XDeviceButtonEvent *)(xevent);
+      *core_x = xie->x;
+      *core_y = xie->y;
+      return GDK_BUTTON_PRESS;
+    }
+
+  if (xevent->type == gdkdev->buttonrelease_type)
+    {
+      XDeviceButtonEvent *xie = (XDeviceButtonEvent *)(xevent);
+      *core_x = xie->x;
+      *core_y = xie->y;
+      return GDK_BUTTON_RELEASE;
+    }
+
+  if (xevent->type == gdkdev->keypress_type)
+    {
+      XDeviceKeyEvent *xie = (XDeviceKeyEvent *)(xevent);
+      *core_x = xie->x;
+      *core_y = xie->y;
+      return GDK_KEY_PRESS;
+    }
+
+  if (xevent->type == gdkdev->keyrelease_type)
+    {
+      XDeviceKeyEvent *xie = (XDeviceKeyEvent *)(xevent);
+      *core_x = xie->x;
+      *core_y = xie->y;
+      return GDK_KEY_RELEASE;
+    }
+
+  if (xevent->type == gdkdev->motionnotify_type)
+    {
+      XDeviceMotionEvent *xie = (XDeviceMotionEvent *)(xevent);
+      *core_x = xie->x;
+      *core_y = xie->y;
+      return GDK_MOTION_NOTIFY;
+    }
 
-  gdk_input_check_proximity(GDK_WINDOW_DISPLAY (window));
+  if (xevent->type == gdkdev->proximityin_type)
+    {
+      XProximityNotifyEvent *xie = (XProximityNotifyEvent *)(xevent);
+      *core_x = xie->x;
+      *core_y = xie->y;
+      return GDK_PROXIMITY_IN;
+    }
 
-  _gdk_input_get_root_relative_geometry(GDK_WINDOW_XDISPLAY (window),
-                                       GDK_WINDOW_XWINDOW(window),
-                                       &root_x, &root_y, NULL, NULL);
+  if (xevent->type == gdkdev->proximityout_type)
+    {
+      XProximityNotifyEvent *xie = (XProximityNotifyEvent *)(xevent);
+      *core_x = xie->x;
+      *core_y = xie->y;
+      return GDK_PROXIMITY_OUT;
+    }
 
-  input_window->root_x = root_x;
-  input_window->root_y = root_y;
+  *core_x = 0;
+  *core_y = 0;
+  return GDK_NOTHING;
 }
 
-gboolean 
-_gdk_input_other_event (GdkEvent *event, 
-                       XEvent *xevent, 
-                       GdkWindow *window)
+
+gboolean
+_gdk_input_other_event (GdkEvent *event,
+                       XEvent *xevent,
+                       GdkWindow *event_window)
 {
-  GdkInputWindow *input_window;
-  
+  GdkWindow *window;
+  GdkWindowObject *priv;
+  GdkInputWindow *iw;
   GdkDevicePrivate *gdkdev;
   gint return_val;
-  GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
-
-  input_window = _gdk_input_window_find(window);
-  g_return_val_if_fail (input_window != NULL, FALSE);
+  GdkEventType event_type;
+  int x, y;
+  GdkDisplay *display = GDK_WINDOW_DISPLAY (event_window);
+  GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (display);
 
   /* This is a sort of a hack, as there isn't any XDeviceAnyEvent -
      but it's potentially faster than scanning through the types of
      every device. If we were deceived, then it won't match any of
      the types for the device anyways */
-  gdkdev = _gdk_input_find_device (GDK_WINDOW_DISPLAY (window),
+  gdkdev = _gdk_input_find_device (display,
                                   ((XDeviceButtonEvent *)xevent)->deviceid);
   if (!gdkdev)
     return FALSE;                      /* we don't handle it - not an XInput event */
 
-  /* FIXME: It would be nice if we could just get rid of the events 
-     entirely, instead of having to ignore them */
+  event_type = get_input_event_type (gdkdev, xevent, &x, &y);
+  if (event_type == GDK_NOTHING)
+    return FALSE;
+
+  window = _gdk_window_get_input_window_for_event (event_window,
+                                                  event_type,
+                                                  x, y,
+                                                  xevent->xany.serial);
+  /* If we're not getting any event window its likely because we're outside the
+     window and there is no grab. We should still report according to the
+     implicit grab though. */
+  iw = ((GdkWindowObject *)event_window)->input_window;
+  if (window == NULL)
+    window = iw->button_down_window;
+
+  priv = (GdkWindowObject *)window;
+  if (window == NULL)
+    return FALSE;
+
   if (gdkdev->info.mode == GDK_MODE_DISABLED ||
-      (gdkdev->info.mode == GDK_MODE_WINDOW 
-       && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR))
+      !(gdkdev->info.has_cursor || (priv->extension_events & GDK_ALL_DEVICES_MASK)))
     return FALSE;
-  
-  if (!display_impl->input_ignore_core)
-    gdk_input_check_proximity(GDK_WINDOW_DISPLAY (window));
 
-  return_val = _gdk_input_common_other_event (event, xevent, 
-                                             input_window, gdkdev);
+  if (!display->ignore_core_events && priv->extension_events != 0)
+    gdk_input_check_proximity (GDK_WINDOW_DISPLAY (window));
 
-  if (return_val && event->type == GDK_PROXIMITY_OUT &&
-      display_impl->input_ignore_core)
-    gdk_input_check_proximity(GDK_WINDOW_DISPLAY (window));
+  return_val = _gdk_input_common_other_event (event, xevent, window, gdkdev);
 
-  return return_val;
-}
+  if (return_val && event->type == GDK_BUTTON_PRESS)
+    iw->button_down_window = window;
+  if (return_val && event->type == GDK_BUTTON_RELEASE)
+    iw->button_down_window = NULL;
 
-gboolean
-_gdk_input_enable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
-{
-  /* FIXME: watchout, gdkdev might be core pointer, never opened */
-  _gdk_input_common_select_events (window, gdkdev);
-  return TRUE;
-}
+  if (return_val && event->type == GDK_PROXIMITY_OUT &&
+      display->ignore_core_events)
+    gdk_input_check_proximity (GDK_WINDOW_DISPLAY (window));
 
-gboolean
-_gdk_input_disable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
-{
-  _gdk_input_common_select_events (window, gdkdev);
-  return TRUE;
+  return return_val;
 }
 
-gint 
-_gdk_input_grab_pointer (GdkWindow *     window,
+gint
+_gdk_input_grab_pointer (GdkWindow      *window,
+                        GdkWindow      *native_window, /* This is the toplevel */
                         gint            owner_events,
                         GdkEventMask    event_mask,
                         GdkWindow *     confine_to,
                         guint32         time)
 {
-  GdkInputWindow *input_window, *new_window;
+  GdkInputWindow *input_window;
+  GdkWindowObject *priv, *impl_window;
   gboolean need_ungrab;
   GdkDevicePrivate *gdkdev;
   GList *tmp_list;
@@ -255,36 +311,36 @@ _gdk_input_grab_pointer (GdkWindow *     window,
   GdkDisplayX11 *display_impl  = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
 
   tmp_list = display_impl->input_windows;
-  new_window = NULL;
   need_ungrab = FALSE;
 
   while (tmp_list)
     {
       input_window = (GdkInputWindow *)tmp_list->data;
 
-      if (input_window->window == window)
-       new_window = input_window;
-      else if (input_window->grabbed)
+      if (input_window->grabbed)
        {
          input_window->grabbed = FALSE;
          need_ungrab = TRUE;
+         break;
        }
-
       tmp_list = tmp_list->next;
     }
 
-  if (new_window)
+  priv = (GdkWindowObject *)window;
+  impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
+  input_window = impl_window->input_window;
+  if (priv->extension_events)
     {
-      new_window->grabbed = TRUE;
-      
+      g_assert (input_window != NULL);
+      input_window->grabbed = TRUE;
+
       tmp_list = display_impl->input_devices;
       while (tmp_list)
        {
          gdkdev = (GdkDevicePrivate *)tmp_list->data;
          if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice)
            {
-             _gdk_input_common_find_events (window, gdkdev,
-                                            event_mask,
+             _gdk_input_common_find_events (gdkdev, event_mask,
                                             event_classes, &num_classes);
 #ifdef G_ENABLE_DEBUG
              if (_gdk_debug_flags & GDK_DEBUG_NOGRABS)
@@ -292,10 +348,10 @@ _gdk_input_grab_pointer (GdkWindow *     window,
              else
 #endif
                result = XGrabDevice (display_impl->xdisplay, gdkdev->xdevice,
-                                     GDK_WINDOW_XWINDOW (window),
+                                     GDK_WINDOW_XWINDOW (native_window),
                                      owner_events, num_classes, event_classes,
                                      GrabModeAsync, GrabModeAsync, time);
-             
+
              /* FIXME: if failure occurs on something other than the first
                 device, things will be badly inconsistent */
              if (result != Success)
@@ -305,7 +361,7 @@ _gdk_input_grab_pointer (GdkWindow *     window,
        }
     }
   else
-    { 
+    {
       tmp_list = display_impl->input_devices;
       while (tmp_list)
        {
@@ -316,17 +372,16 @@ _gdk_input_grab_pointer (GdkWindow *     window,
              XUngrabDevice (display_impl->xdisplay, gdkdev->xdevice, time);
              gdkdev->button_state = 0;
            }
-         
+
          tmp_list = tmp_list->next;
        }
     }
 
   return Success;
-      
 }
 
-void 
-_gdk_input_ungrab_pointer (GdkDisplay *display, 
+void
+_gdk_input_ungrab_pointer (GdkDisplay *display,
                           guint32 time)
 {
   GdkInputWindow *input_window = NULL; /* Quiet GCC */
index 95a301d24d2e37794dd139bc6efe00179b486656..c33f09c9e40e7472bd5f91892b91c3b1fa8fa2ef 100644 (file)
@@ -21,7 +21,7 @@
  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
  * file for a list of people on the GTK+ Team.  See the ChangeLog
  * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
  */
 
 #include "config.h"
@@ -47,10 +47,10 @@ void
 _gdk_init_input_core (GdkDisplay *display)
 {
   GdkDevicePrivate *private;
-  
+
   display->core_pointer = g_object_new (GDK_TYPE_DEVICE, NULL);
   private = (GdkDevicePrivate *)display->core_pointer;
-  
+
   display->core_pointer->name = "Core Pointer";
   display->core_pointer->source = GDK_SOURCE_MOUSE;
   display->core_pointer->mode = GDK_MODE_SCREEN;
@@ -87,12 +87,12 @@ gdk_device_get_type (void)
          0,              /* n_preallocs */
          (GInstanceInitFunc) NULL,
        };
-      
+
       object_type = g_type_register_static (G_TYPE_OBJECT,
-                                            g_intern_static_string ("GdkDevice"),
-                                            &object_info, 0);
+                                           g_intern_static_string ("GdkDevice"),
+                                           &object_info, 0);
     }
-  
+
   return object_type;
 }
 
@@ -115,10 +115,10 @@ gdk_device_dispose (GObject *object)
     {
 #ifndef XINPUT_NONE
       if (gdkdev->xdevice)
-        {
-          XCloseDevice (GDK_DISPLAY_XDISPLAY (gdkdev->display), gdkdev->xdevice);
-          gdkdev->xdevice = NULL;
-        }
+       {
+         XCloseDevice (GDK_DISPLAY_XDISPLAY (gdkdev->display), gdkdev->xdevice);
+         gdkdev->xdevice = NULL;
+       }
       g_free (gdkdev->axes);
       gdkdev->axes = NULL;
 #endif /* !XINPUT_NONE */
@@ -140,7 +140,7 @@ gdk_device_dispose (GObject *object)
  *
  * Returns the list of available input devices for the default display.
  * The list is statically allocated and should not be freed.
- * 
+ *
  * Return value: a list of #GdkDevice
  **/
 GList *
@@ -155,16 +155,16 @@ gdk_devices_list (void)
  *
  * Returns the list of available input devices attached to @display.
  * The list is statically allocated and should not be freed.
- * 
+ *
  * Return value: a list of #GdkDevice
  *
  * Since: 2.2
  **/
-GList * 
+GList *
 gdk_display_list_devices (GdkDisplay *display)
 {
   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
-  
+
   return GDK_DISPLAY_X11 (display)->input_devices;
 }
 
@@ -219,6 +219,22 @@ gdk_device_set_axis_use (GdkDevice   *device,
     }
 }
 
+static gboolean
+impl_coord_in_window (GdkWindow *window,
+                     int impl_x,
+                     int impl_y)
+{
+  GdkWindowObject *priv = (GdkWindowObject *)window;
+
+  if (impl_x < priv->abs_x ||
+      impl_x > priv->abs_x + priv->width)
+    return FALSE;
+  if (impl_y < priv->abs_y ||
+      impl_y > priv->abs_y + priv->height)
+    return FALSE;
+  return TRUE;
+}
+
 /**
  * gdk_device_get_history:
  * @device: a #GdkDevice
@@ -227,14 +243,14 @@ gdk_device_set_axis_use (GdkDevice   *device,
  * @stop: ending timestamp for the range of events to return
  * @events: location to store a newly-allocated array of #GdkTimeCoord, or %NULL
  * @n_events: location to store the length of @events, or %NULL
- * 
+ *
  * Obtains the motion history for a device; given a starting and
  * ending timestamp, return all events in the motion history for
  * the device in the given range of time. Some windowing systems
  * do not support motion history, in which case, %FALSE will
  * be returned. (This is not distinguishable from the case where
  * motion history is supported and no events were found.)
- * 
+ *
  * Return value: %TRUE if the windowing system supports motion history and
  *  at least one event was found.
  **/
@@ -247,29 +263,38 @@ gdk_device_get_history  (GdkDevice         *device,
                         gint              *n_events)
 {
   GdkTimeCoord **coords = NULL;
+  GdkWindow *impl_window;
   gboolean result = FALSE;
   int tmp_n_events = 0;
-  int i;
+  int i, j;
 
   g_return_val_if_fail (GDK_WINDOW_IS_X11 (window), FALSE);
 
+  impl_window = _gdk_window_get_impl_window (window);
+
   if (GDK_WINDOW_DESTROYED (window))
     /* Nothing */ ;
   else if (GDK_IS_CORE (device))
     {
       XTimeCoord *xcoords;
-      
+
       xcoords = XGetMotionEvents (GDK_DRAWABLE_XDISPLAY (window),
-                                 GDK_DRAWABLE_XID (window),
+                                 GDK_DRAWABLE_XID (impl_window),
                                  start, stop, &tmp_n_events);
       if (xcoords)
        {
+         GdkWindowObject *priv = (GdkWindowObject *)window;
          coords = _gdk_device_allocate_history (device, tmp_n_events);
+         j = 0;
          for (i=0; i<tmp_n_events; i++)
            {
-             coords[i]->time = xcoords[i].time;
-             coords[i]->axes[0] = xcoords[i].x;
-             coords[i]->axes[1] = xcoords[i].y;
+             if (impl_coord_in_window (window, xcoords[i].x, xcoords[i].y))
+               {
+                 coords[j]->time = xcoords[i].time;
+                 coords[j]->axes[0] = xcoords[i].x - priv->abs_x;
+                 coords[j]->axes[1] = xcoords[i].y - priv->abs_y;
+                 j++;
+               }
            }
 
          XFree (xcoords);
@@ -292,7 +317,7 @@ gdk_device_get_history  (GdkDevice         *device,
   return result;
 }
 
-GdkTimeCoord ** 
+GdkTimeCoord **
 _gdk_device_allocate_history (GdkDevice *device,
                              gint       n_events)
 {
@@ -306,41 +331,48 @@ _gdk_device_allocate_history (GdkDevice *device,
   return result;
 }
 
-void 
+void
 gdk_device_free_history (GdkTimeCoord **events,
                         gint           n_events)
 {
   gint i;
-  
+
   for (i=0; i<n_events; i++)
     g_free (events[i]);
 
   g_free (events);
 }
 
-GdkInputWindow *
-_gdk_input_window_find(GdkWindow *window)
+static void
+unset_extension_events (GdkWindow *window)
 {
-  GList *tmp_list;
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
+  GdkWindowObject *window_private;
+  GdkWindowObject *impl_window;
+  GdkDisplayX11 *display_x11;
+  GdkInputWindow *iw;
 
-  /* Ensure we have a native window, or the input stuff won't work.
-     Its possible we could emulate this also, but at least this should make
-     it work. */
-  gdk_window_set_has_native (window, TRUE);
+  window_private = (GdkWindowObject*) window;
+  impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
+  iw = impl_window->input_window;
 
-  for (tmp_list=display_x11->input_windows; tmp_list; tmp_list=tmp_list->next)
-    if (((GdkInputWindow *)(tmp_list->data))->window == window)
-      return (GdkInputWindow *)(tmp_list->data);
+  display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
 
-  return NULL;      /* Not found */
-}
+  if (window_private->extension_events != 0)
+    {
+      g_assert (iw != NULL);
+      g_assert (g_list_find (iw->windows, window) != NULL);
+
+      iw->windows = g_list_remove (iw->windows, window);
+      if (iw->windows == NULL)
+       {
+         impl_window->input_window = NULL;
+         display_x11->input_windows = g_list_remove (display_x11->input_windows, iw);
+         g_free (iw);
+       }
+    }
 
-/* FIXME: this routine currently needs to be called between creation
-   and the corresponding configure event (because it doesn't get the
-   root_relative_geometry).  This should work with
-   gtk_window_set_extension_events, but will likely fail in other
-   cases */
+  window_private->extension_events = 0;
+}
 
 void
 gdk_input_set_extension_events (GdkWindow *window, gint mask,
@@ -348,6 +380,7 @@ gdk_input_set_extension_events (GdkWindow *window, gint mask,
 {
   GdkWindowObject *window_private;
   GList *tmp_list;
+  GdkWindowObject *impl_window;
   GdkInputWindow *iw;
   GdkDisplayX11 *display_x11;
 
@@ -359,52 +392,44 @@ gdk_input_set_extension_events (GdkWindow *window, gint mask,
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
+  impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
+
+  if (mode == GDK_EXTENSION_EVENTS_ALL && mask != 0)
+    mask |= GDK_ALL_DEVICES_MASK;
+
   if (mode == GDK_EXTENSION_EVENTS_NONE)
     mask = 0;
 
-  iw = _gdk_input_window_find (window);
+  iw = impl_window->input_window;
 
   if (mask != 0)
     {
       if (!iw)
-        {
-          iw = g_new(GdkInputWindow,1);
-
-          iw->window = window;
-          iw->mode = mode;
+       {
+         iw = g_new0 (GdkInputWindow,1);
 
-          iw->obscuring = NULL;
-          iw->num_obscuring = 0;
-          iw->grabbed = FALSE;
+         iw->impl_window = (GdkWindow *)impl_window;
 
-          display_x11->input_windows = g_list_append(display_x11->input_windows,iw);
-        }
+         iw->windows = NULL;
+         iw->grabbed = FALSE;
 
-      window_private->extension_events = mask;
+         display_x11->input_windows = g_list_append (display_x11->input_windows, iw);
 
 #ifndef XINPUT_NONE
-      /* Add enter window events to the event mask */
-      /* this is not needed for XINPUT_NONE */
-      gdk_window_set_events (window,
-                            gdk_window_get_events (window) | 
-                            GDK_ENTER_NOTIFY_MASK);
-
-      /* we might not receive ConfigureNotify so get the root_relative_geometry
-       * now, just in case */
-      _gdk_input_get_root_relative_geometry (GDK_WINDOW_XDISPLAY (window),
-                                             GDK_WINDOW_XWINDOW (window),
-                                             &iw->root_x, &iw->root_y, NULL, NULL);
+         /* we might not receive ConfigureNotify so get the root_relative_geometry
+          * now, just in case */
+         _gdk_input_get_root_relative_geometry (window, &iw->root_x, &iw->root_y);
 #endif /* !XINPUT_NONE */
+         impl_window->input_window = iw;
+       }
+
+      if (window_private->extension_events == 0)
+       iw->windows = g_list_append (iw->windows, window);
+      window_private->extension_events = mask;
     }
   else
     {
-      if (iw)
-       {
-         display_x11->input_windows = g_list_remove(display_x11->input_windows,iw);
-         g_free(iw);
-       }
-
-      window_private->extension_events = 0;
+      unset_extension_events (window);
     }
 
   for (tmp_list = display_x11->input_devices; tmp_list; tmp_list = tmp_list->next)
@@ -412,57 +437,14 @@ gdk_input_set_extension_events (GdkWindow *window, gint mask,
       GdkDevicePrivate *gdkdev = tmp_list->data;
 
       if (!GDK_IS_CORE (gdkdev))
-       {
-         if (mask != 0 && gdkdev->info.mode != GDK_MODE_DISABLED
-             && (gdkdev->info.has_cursor || mode == GDK_EXTENSION_EVENTS_ALL))
-           _gdk_input_enable_window (window,gdkdev);
-         else
-           _gdk_input_disable_window (window,gdkdev);
-       }
+       _gdk_input_select_events ((GdkWindow *)impl_window, gdkdev);
     }
 }
 
 void
 _gdk_input_window_destroy (GdkWindow *window)
 {
-  GdkInputWindow *input_window;
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
-
-  input_window = _gdk_input_window_find (window);
-  g_return_if_fail (input_window != NULL);
-
-  display_x11->input_windows = g_list_remove (display_x11->input_windows, input_window);
-  g_free(input_window);
-}
-
-void
-_gdk_input_exit (void)
-{
-  GList *tmp_list;
-  GSList *display_list;
-  GdkDevicePrivate *gdkdev;
-
-  for (display_list = _gdk_displays ; display_list ; display_list = display_list->next)
-    {
-      GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display_list->data);
-      
-      for (tmp_list = display_x11->input_devices; tmp_list; tmp_list = tmp_list->next)
-       {
-         gdkdev = (GdkDevicePrivate *)(tmp_list->data);
-         if (!GDK_IS_CORE (gdkdev))
-           {
-             gdk_device_set_mode (&gdkdev->info, GDK_MODE_DISABLED);
-             g_object_unref(gdkdev);
-           }
-       }
-      
-      g_list_free(display_x11->input_devices);
-      
-      for (tmp_list = display_x11->input_windows; tmp_list; tmp_list = tmp_list->next)
-       g_free(tmp_list->data);
-      
-      g_list_free(display_x11->input_windows);
-    }
+  unset_extension_events (window);
 }
 
 /**
@@ -471,10 +453,10 @@ _gdk_input_exit (void)
  * @axes: pointer to an array of axes
  * @use: the use to look for
  * @value: location to store the found value.
- * 
+ *
  * Interprets an array of double as axis values for a given device,
  * and locates the value in the array for a given axis use.
- * 
+ *
  * Return value: %TRUE if the given axis use was found, otherwise %FALSE
  **/
 gboolean
@@ -484,12 +466,12 @@ gdk_device_get_axis (GdkDevice  *device,
                     gdouble    *value)
 {
   gint i;
-  
+
   g_return_val_if_fail (device != NULL, FALSE);
 
   if (axes == NULL)
     return FALSE;
-  
+
   for (i=0; i<device->num_axes; i++)
     if (device->axes[i].use == use)
       {
@@ -497,7 +479,7 @@ gdk_device_get_axis (GdkDevice  *device,
          *value = axes[i];
        return TRUE;
       }
-  
+
   return FALSE;
 }
 
index 5cbd809debfad15a870f5dd61720d8d100290080..217e28c002a4855925408001607ffc4aaa79a42a 100644 (file)
@@ -41,7 +41,6 @@
 
 typedef struct _GdkAxisInfo    GdkAxisInfo;
 typedef struct _GdkDevicePrivate GdkDevicePrivate;
-typedef struct _GdkInputWindow GdkInputWindow;
 
 /* information about a device axis */
 struct _GdkAxisInfo
@@ -102,28 +101,25 @@ struct _GdkDeviceClass
   GObjectClass parent_class;
 };
 
+/* Addition used for extension_events mask */
+#define GDK_ALL_DEVICES_MASK (1<<30)
+
 struct _GdkInputWindow
 {
-  /* gdk window */
-  GdkWindow *window;
+  GList *windows; /* GdkWindow:s with extension_events set */
 
-  /* Extension mode (GDK_EXTENSION_EVENTS_ALL/CURSOR) */
-  GdkExtensionMode mode;
+  /* gdk window */
+  GdkWindow *impl_window; /* an impl window */
+  GdkWindow *button_down_window;
 
   /* position relative to root window */
   gint root_x;
   gint root_y;
 
-  /* rectangles relative to window of windows obscuring this one */
-  GdkRectangle *obscuring;
-  gint num_obscuring;
-
   /* Is there a pointer grab for this window ? */
   gint grabbed;
 };
 
-
-
 /* Global data */
 
 #define GDK_IS_CORE(d) (((GdkDevice *)(d)) == ((GdkDevicePrivate *)(d))->display->core_pointer)
@@ -139,18 +135,15 @@ void            _gdk_init_input_core         (GdkDisplay *display);
 /* The following functions are provided by each implementation
  * (xfree, gxi, and none)
  */
-gint             _gdk_input_enable_window     (GdkWindow        *window,
-                                             GdkDevicePrivate *gdkdev);
-gint             _gdk_input_disable_window    (GdkWindow        *window,
-                                             GdkDevicePrivate *gdkdev);
 void             _gdk_input_configure_event  (XConfigureEvent  *xevent,
                                              GdkWindow        *window);
-void             _gdk_input_enter_event      (XCrossingEvent   *xevent,
-                                             GdkWindow        *window);
+void             _gdk_input_crossing_event   (GdkWindow        *window,
+                                             gboolean          enter);
 gboolean         _gdk_input_other_event      (GdkEvent         *event,
                                              XEvent           *xevent,
                                              GdkWindow        *window);
 gint             _gdk_input_grab_pointer     (GdkWindow        *window,
+                                             GdkWindow        *native_window,
                                              gint              owner_events,
                                              GdkEventMask      event_mask,
                                              GdkWindow        *confine_to,
@@ -172,22 +165,18 @@ gint               _gdk_input_common_init               (GdkDisplay         *display,
                                                         gint              include_core);
 GdkDevicePrivate * _gdk_input_find_device               (GdkDisplay      *display,
                                                         guint32           id);
-void               _gdk_input_get_root_relative_geometry(Display          *display,
-                                                        Window            w,
+void               _gdk_input_get_root_relative_geometry(GdkWindow        *window,
                                                         int              *x_ret,
-                                                        int              *y_ret,
-                                                        int              *width_ret,
-                                                        int              *height_ret);
-void               _gdk_input_common_find_events        (GdkWindow        *window,
-                                                        GdkDevicePrivate *gdkdev,
+                                                        int              *y_ret);
+void               _gdk_input_common_find_events        (GdkDevicePrivate *gdkdev,
                                                         gint              mask,
                                                         XEventClass      *classes,
                                                         int              *num_classes);
-void               _gdk_input_common_select_events      (GdkWindow        *window,
+void               _gdk_input_select_events             (GdkWindow        *impl_window,
                                                         GdkDevicePrivate *gdkdev);
 gint               _gdk_input_common_other_event        (GdkEvent         *event,
                                                         XEvent           *xevent,
-                                                        GdkInputWindow   *input_window,
+                                                        GdkWindow        *window,
                                                         GdkDevicePrivate *gdkdev);
 
 #endif /* !XINPUT_NONE */
index 41639c478239c9427776f228970d76093e5728ba..08c7cffb4fc7505cbab92b0824ecca000755a92b 100644 (file)
@@ -251,7 +251,8 @@ gdk_pointer_grab (GdkWindow *         window,
    */
   xevent_mask &= ~PointerMotionHintMask;
   
-  return_val = _gdk_input_grab_pointer (native,
+  return_val = _gdk_input_grab_pointer (window,
+                                       native,
                                        owner_events,
                                        event_mask,
                                        confine_to,
index e29dc7b14b9473a16770c14b83aaa38e4cb04ce7..4d38fcbc47cc4a9f20a77103d963f5db2235cac6 100644 (file)
@@ -1036,9 +1036,6 @@ _gdk_x11_window_destroy (GdkWindow *window,
 
   _gdk_selection_window_destroyed (window);
   
-  if (private->extension_events != 0)
-    _gdk_input_window_destroy (window);
-
   toplevel = _gdk_x11_window_get_toplevel (window);
   if (toplevel)
     gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), toplevel);
@@ -5585,6 +5582,8 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface)
   iface->queue_antiexpose = _gdk_x11_window_queue_antiexpose;
   iface->queue_translation = _gdk_x11_window_queue_translation;
   iface->destroy = _gdk_x11_window_destroy;
+  iface->input_window_destroy = _gdk_input_window_destroy;
+  iface->input_window_crossing = _gdk_input_crossing_event;
 }
 
 #define __GDK_WINDOW_X11_C__