]> Pileus Git - ~andy/gtk/blobdiff - gdk/gdkwindow.c
Migrate to XDG config dir for custom papers
[~andy/gtk] / gdk / gdkwindow.c
index f5f07b21a861a74f190262bded10289fc6630a92..2683073d0993b8ce1ddf580958731ae1b645ad2b 100644 (file)
@@ -1243,11 +1243,12 @@ get_native_device_event_mask (GdkWindow *private,
        * lists due to some non-native child window.
        */
       if (gdk_window_is_toplevel (private) ||
-         mask & GDK_BUTTON_PRESS_MASK)
-       mask |=
-         GDK_POINTER_MOTION_MASK |
-         GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
-         GDK_SCROLL_MASK;
+          mask & GDK_BUTTON_PRESS_MASK)
+        mask |=
+          GDK_TOUCH_MASK |
+          GDK_POINTER_MOTION_MASK |
+          GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+          GDK_SCROLL_MASK;
 
       return mask;
     }
@@ -8115,7 +8116,7 @@ static const guint type_masks[] = {
   GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT            = 28 */
   GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29 */
   GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE                  = 30 */
-  GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK,/* GDK_SCROLL= 31 */
+  GDK_SCROLL_MASK | GDK_SMOOTH_SCROLL_MASK,/* GDK_SCROLL= 31 */
   0, /* GDK_WINDOW_STATE = 32 */
   0, /* GDK_SETTING = 33 */
   0, /* GDK_OWNER_CHANGE = 34 */
@@ -8170,6 +8171,15 @@ is_motion_type (GdkEventType type)
         type == GDK_LEAVE_NOTIFY;
 }
 
+static gboolean
+is_touch_type (GdkEventType type)
+{
+  return type == GDK_TOUCH_BEGIN ||
+         type == GDK_TOUCH_UPDATE ||
+         type == GDK_TOUCH_END ||
+         type == GDK_TOUCH_CANCEL;
+}
+
 static GdkWindow *
 find_common_ancestor (GdkWindow *win1,
                      GdkWindow *win2)
@@ -8251,7 +8261,6 @@ _gdk_make_event (GdkWindow    *window,
       event->touch.state = the_state;
       break;
 
-
     case GDK_SCROLL:
       event->scroll.time = the_time;
       event->scroll.state = the_state;
@@ -8340,14 +8349,27 @@ send_crossing_event (GdkDisplay                 *display,
   GdkEvent *event;
   guint32 window_event_mask, type_event_mask;
   GdkDeviceGrabInfo *grab;
+  GdkTouchGrabInfo *touch_grab = NULL;
   GdkPointerWindowInfo *pointer_info;
   gboolean block_event = FALSE;
+  GdkEventSequence *sequence;
 
   grab = _gdk_display_has_device_grab (display, device, serial);
   pointer_info = _gdk_display_get_pointer_info (display, device);
 
-  if (grab != NULL &&
-      !grab->owner_events)
+  sequence = gdk_event_get_event_sequence (event_in_queue);
+  if (sequence)
+    touch_grab = _gdk_display_has_touch_grab (display, device, sequence, serial);
+
+  if (touch_grab)
+    {
+      if (window != touch_grab->window)
+        return;
+
+      window_event_mask = touch_grab->event_mask;
+    }
+  else if (grab != NULL &&
+           !grab->owner_events)
     {
       /* !owner_event => only report events wrt grab window, ignore rest */
       if ((GdkWindow *)window != grab->window)
@@ -9117,15 +9139,33 @@ get_event_window (GdkDisplay                 *display,
                   GdkEventType                type,
                   GdkModifierType             mask,
                   guint                      *evmask_out,
+                  gboolean                    pointer_emulated,
                   gulong                      serial)
 {
-  guint evmask;
+  guint evmask, emulated_mask = 0;
   GdkWindow *grab_window;
   GdkDeviceGrabInfo *grab;
   GdkTouchGrabInfo *touch_grab;
 
   touch_grab = _gdk_display_has_touch_grab (display, device, sequence, serial);
-  grab = _gdk_display_has_device_grab (display, device, serial);
+  grab = _gdk_display_get_last_device_grab (display, device);
+
+  if (is_touch_type (type) && pointer_emulated)
+    {
+      switch (type)
+        {
+        case GDK_TOUCH_BEGIN:
+          emulated_mask |= GDK_BUTTON_PRESS_MASK;
+          break;
+        case GDK_TOUCH_UPDATE:
+          emulated_mask |= GDK_POINTER_MOTION_MASK;
+          break;
+        case GDK_TOUCH_END:
+          emulated_mask |= GDK_BUTTON_RELEASE_MASK;
+        default:
+          break;
+        }
+    }
 
   if (touch_grab != NULL &&
       (!grab || grab->implicit || touch_grab->serial >= grab->serial_start))
@@ -9133,7 +9173,7 @@ get_event_window (GdkDisplay                 *display,
       evmask = touch_grab->event_mask;
       evmask = update_evmask_for_button_motion (evmask, mask);
 
-      if (evmask & type_masks[type])
+      if (evmask & (type_masks[type] | emulated_mask))
         {
           if (evmask_out)
             *evmask_out = evmask;
@@ -9150,7 +9190,7 @@ get_event_window (GdkDisplay                 *display,
 
       grab_window = grab->window;
 
-      if (evmask & type_masks[type])
+      if (evmask & (type_masks[type] | emulated_mask))
        {
          if (evmask_out)
            *evmask_out = evmask;
@@ -9165,7 +9205,7 @@ get_event_window (GdkDisplay                 *display,
       evmask = pointer_window->event_mask;
       evmask = update_evmask_for_button_motion (evmask, mask);
 
-      if (evmask & type_masks[type])
+      if (evmask & (type_masks[type] | emulated_mask))
        {
          if (evmask_out)
            *evmask_out = evmask;
@@ -9181,7 +9221,7 @@ get_event_window (GdkDisplay                 *display,
       evmask = grab->event_mask;
       evmask = update_evmask_for_button_motion (evmask, mask);
 
-      if (evmask & type_masks[type])
+      if (evmask & (type_masks[type] | emulated_mask))
        {
          if (evmask_out)
            *evmask_out = evmask;
@@ -9208,7 +9248,9 @@ proxy_pointer_event (GdkDisplay                 *display,
   gdouble toplevel_x, toplevel_y;
   guint32 time_;
   gboolean non_linear, need_synthetic_enter = FALSE;
+  gint event_type;
 
+  event_type = source_event->type;
   event_window = source_event->any.window;
   gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
   gdk_event_get_state (source_event, &state);
@@ -9229,8 +9271,8 @@ proxy_pointer_event (GdkDisplay                 *display,
 
   if (pointer_info->need_touch_press_enter &&
       gdk_device_get_source (pointer_info->last_slave) != GDK_SOURCE_TOUCHSCREEN &&
-      gdk_device_get_source (pointer_info->last_slave) != GDK_SOURCE_TOUCHPAD)
-
+      (source_event->type != GDK_TOUCH_UPDATE ||
+       _gdk_event_get_pointer_emulated (source_event)))
     {
       pointer_info->need_touch_press_enter = FALSE;
       need_synthetic_enter = TRUE;
@@ -9359,8 +9401,32 @@ proxy_pointer_event (GdkDisplay                 *display,
                                     source_event->type,
                                     state,
                                     &evmask,
+                                    _gdk_event_get_pointer_emulated (source_event),
                                     serial);
 
+      if (event_type == GDK_TOUCH_UPDATE)
+        {
+          if (_gdk_event_get_pointer_emulated (source_event))
+            {
+              /* Touch events emulating pointer events are transformed back
+               * to pointer events if:
+               * 1 - The event window doesn't select for touch events
+               * 2 - There's no touch grab for this sequence, which means
+               *     it was started as a pointer sequence, but a device
+               *     grab added touch events afterwards, the sequence must
+               *     not mutate in this case.
+               */
+              if ((evmask & GDK_TOUCH_MASK) == 0 ||
+                  !_gdk_display_has_touch_grab (display, device, sequence, serial))
+                event_type = GDK_MOTION_NOTIFY;
+            }
+          else if ((evmask & GDK_TOUCH_MASK) == 0)
+            return TRUE;
+        }
+
+      if (is_touch_type (source_event->type) && !is_touch_type (event_type))
+        state |= GDK_BUTTON1_MASK;
+
       if (event_win &&
           gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_MASTER &&
           gdk_window_get_device_events (event_win, device) == 0)
@@ -9382,6 +9448,7 @@ proxy_pointer_event (GdkDisplay                 *display,
       is_hint = FALSE;
 
       if (event_win &&
+          event_type == GDK_MOTION_NOTIFY &&
          (evmask & GDK_POINTER_MOTION_HINT_MASK))
        {
           gulong *device_serial;
@@ -9402,32 +9469,53 @@ proxy_pointer_event (GdkDisplay                 *display,
       if (!event_win)
         return TRUE;
 
-      if (!display->ignore_core_events)
-        {
-          GdkEventType event_type;
-
-          event_type = source_event->type;
-
-          event = gdk_event_new (event_type);
-          event->any.window = g_object_ref (event_win);
-          event->any.send_event = source_event->any.send_event;
-          event->motion.time = time_;
-          convert_toplevel_coords_to_window (event_win,
-                                             toplevel_x, toplevel_y,
-                                             &event->motion.x, &event->motion.y);
-          event->motion.x_root = source_event->motion.x_root;
-          event->motion.y_root = source_event->motion.y_root;
-          event->motion.state = state;
-          event->motion.is_hint = is_hint;
-          event->motion.device = source_event->motion.device;
-          event->motion.axes = g_memdup (source_event->motion.axes,
-                                         sizeof (gdouble) * gdk_device_get_n_axes (source_event->motion.device));
-          gdk_event_set_source_device (event, source_device);
-
-          /* Just insert the event */
-          _gdk_event_queue_insert_after (gdk_window_get_display (event_win),
-                                         source_event, event);
+      event = gdk_event_new (event_type);
+      event->any.window = g_object_ref (event_win);
+      event->any.send_event = source_event->any.send_event;
+
+      gdk_event_set_device (event, gdk_event_get_device (source_event));
+      gdk_event_set_source_device (event, source_device);
+
+      if (event_type == GDK_TOUCH_UPDATE)
+       {
+         event->touch.time = time_;
+         event->touch.state = state | GDK_BUTTON1_MASK;
+         event->touch.sequence = source_event->touch.sequence;
+         event->touch.emulating_pointer = source_event->touch.emulating_pointer;
+         convert_toplevel_coords_to_window (event_win,
+                                            toplevel_x, toplevel_y,
+                                            &event->touch.x, &event->touch.y);
+         gdk_event_get_root_coords (source_event,
+                                    &event->touch.x_root,
+                                    &event->touch.y_root);
+
+         event->touch.axes = g_memdup (source_event->touch.axes,
+                                       sizeof (gdouble) * gdk_device_get_n_axes (source_event->touch.device));
+       }
+      else
+       {
+         event->motion.time = time_;
+         event->motion.state = state;
+         event->motion.is_hint = is_hint;
+
+         convert_toplevel_coords_to_window (event_win,
+                                            toplevel_x, toplevel_y,
+                                            &event->motion.x, &event->motion.y);
+         gdk_event_get_root_coords (source_event,
+                                    &event->motion.x_root,
+                                    &event->motion.y_root);
+
+         if (is_touch_type (source_event->type))
+           event->motion.axes = g_memdup (source_event->touch.axes,
+                                          sizeof (gdouble) * gdk_device_get_n_axes (source_event->touch.device));
+         else
+           event->motion.axes = g_memdup (source_event->motion.axes,
+                                          sizeof (gdouble) * gdk_device_get_n_axes (source_event->motion.device));
        }
+
+      /* Just insert the event */
+      _gdk_event_queue_insert_after (gdk_window_get_display (event_win),
+                                    source_event, event);
     }
 
   /* unlink all move events from queue.
@@ -9451,6 +9539,7 @@ proxy_button_event (GdkEvent *source_event,
   GdkWindow *parent;
   GdkEvent *event;
   GdkPointerWindowInfo *pointer_info;
+  GdkDeviceGrabInfo *pointer_grab;
   guint state;
   guint32 time_;
   GdkEventType type;
@@ -9476,11 +9565,14 @@ proxy_button_event (GdkEvent *source_event,
   sequence = gdk_event_get_event_sequence (source_event);
 
   pointer_info = _gdk_display_get_pointer_info (display, device);
+  pointer_grab = _gdk_display_has_device_grab (display, device, serial);
 
   if ((type == GDK_BUTTON_PRESS ||
        type == GDK_TOUCH_BEGIN) &&
       !source_event->any.send_event &&
-      _gdk_display_has_device_grab (display, device, serial) == NULL)
+      (!pointer_grab ||
+       (type == GDK_TOUCH_BEGIN && pointer_grab->implicit &&
+        !_gdk_event_get_pointer_emulated (source_event))))
     {
       pointer_window =
        _gdk_window_find_descendant_at (toplevel_window,
@@ -9544,16 +9636,40 @@ proxy_button_event (GdkEvent *source_event,
                                 sequence,
                                 pointer_window,
                                 type, state,
-                                &evmask, serial);
+                                &evmask,
+                                _gdk_event_get_pointer_emulated (source_event),
+                                serial);
+
+  if (type == GDK_TOUCH_BEGIN || type == GDK_TOUCH_END)
+    {
+      if (_gdk_event_get_pointer_emulated (source_event))
+        {
+          if ((evmask & GDK_TOUCH_MASK) == 0 ||
+              !_gdk_display_has_touch_grab (display, device, sequence, serial))
+            {
+              if (type == GDK_TOUCH_BEGIN)
+                type = GDK_BUTTON_PRESS;
+              else if (type == GDK_TOUCH_END)
+                type = GDK_BUTTON_RELEASE;
+            }
+        }
+      else if ((evmask & GDK_TOUCH_MASK) == 0)
+        return TRUE;
+    }
+
+  if (source_event->type == GDK_TOUCH_END && !is_touch_type (type))
+    state |= GDK_BUTTON1_MASK;
 
-  if (event_win == NULL || display->ignore_core_events)
+  if (event_win == NULL)
     return TRUE;
 
   if (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_MASTER &&
       gdk_window_get_device_events (event_win, device) == 0)
     return TRUE;
 
-  if (type == GDK_BUTTON_PRESS &&
+  if ((type == GDK_BUTTON_PRESS ||
+       (type == GDK_TOUCH_BEGIN &&
+        _gdk_event_get_pointer_emulated (source_event))) &&
       pointer_info->need_touch_press_enter)
     {
       GdkCrossingMode mode;
@@ -9562,8 +9678,7 @@ proxy_button_event (GdkEvent *source_event,
        * which synthesized a leave notify event, so synthesize another enter
        * notify to tell the pointer is on the window.
        */
-      if (gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHSCREEN ||
-          gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHPAD)
+      if (gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHSCREEN)
         mode = GDK_CROSSING_TOUCH_BEGIN;
       else
         mode = GDK_CROSSING_DEVICE_SWITCH;
@@ -9577,6 +9692,13 @@ proxy_button_event (GdkEvent *source_event,
                                        state, time_, source_event,
                                        serial, FALSE);
     }
+  else if (type == GDK_SCROLL &&
+           (((evmask & GDK_SMOOTH_SCROLL_MASK) == 0 &&
+             source_event->scroll.direction == GDK_SCROLL_SMOOTH) ||
+            ((evmask & GDK_SMOOTH_SCROLL_MASK) != 0 &&
+             source_event->scroll.direction != GDK_SCROLL_SMOOTH &&
+             _gdk_event_get_pointer_emulated (source_event))))
+    return FALSE;
 
   event = _gdk_make_event (event_win, type, source_event, FALSE);
 
@@ -9588,20 +9710,34 @@ proxy_button_event (GdkEvent *source_event,
       convert_toplevel_coords_to_window (event_win,
                                         toplevel_x, toplevel_y,
                                         &event->button.x, &event->button.y);
-      event->button.x_root = source_event->button.x_root;
-      event->button.y_root = source_event->button.y_root;
-      event->button.state = state;
-      event->button.device = source_event->button.device;
-      event->button.axes = g_memdup (source_event->button.axes,
-                                     sizeof (gdouble) * gdk_device_get_n_axes (source_event->button.device));
+      gdk_event_get_root_coords (source_event,
+                                &event->button.x_root,
+                                &event->button.y_root);
+      gdk_event_set_device (event, gdk_event_get_device (source_event));
       gdk_event_set_source_device (event, source_device);
 
+      if (is_touch_type (source_event->type))
+        {
+          if (type == GDK_BUTTON_RELEASE)
+            event->button.state |= GDK_BUTTON1_MASK;
+         event->button.button = 1;
+         event->button.axes = g_memdup (source_event->touch.axes,
+                                        sizeof (gdouble) * gdk_device_get_n_axes (source_event->touch.device));
+       }
+      else
+       {
+         event->button.button = source_event->button.button;
+         event->button.axes = g_memdup (source_event->button.axes,
+                                        sizeof (gdouble) * gdk_device_get_n_axes (source_event->button.device));
+       }
+
       if (type == GDK_BUTTON_PRESS)
         _gdk_event_button_generate (display, event);
-      else if (type == GDK_BUTTON_RELEASE &&
+      else if ((type == GDK_BUTTON_RELEASE ||
+                (type == GDK_TOUCH_END &&
+                 _gdk_event_get_pointer_emulated (source_event))) &&
                pointer_window == pointer_info->window_under_pointer &&
-               (gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHSCREEN ||
-                gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHPAD))
+               gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHSCREEN)
         {
           /* Synthesize a leave notify event
            * whenever a touch device is released
@@ -9622,13 +9758,15 @@ proxy_button_event (GdkEvent *source_event,
       convert_toplevel_coords_to_window (event_win,
                                          toplevel_x, toplevel_y,
                                          &event->button.x, &event->button.y);
-      event->touch.x_root = source_event->touch.x_root;
-      event->touch.y_root = source_event->touch.y_root;
+      gdk_event_get_root_coords (source_event,
+                                &event->touch.x_root,
+                                &event->touch.y_root);
       event->touch.state = state;
       event->touch.device = source_event->touch.device;
       event->touch.axes = g_memdup (source_event->touch.axes,
                                      sizeof (gdouble) * gdk_device_get_n_axes (source_event->touch.device));
       event->touch.sequence = source_event->touch.sequence;
+      event->touch.emulating_pointer = source_event->touch.emulating_pointer;
 
       gdk_event_set_source_device (event, source_device);
 
@@ -9660,6 +9798,8 @@ proxy_button_event (GdkEvent *source_event,
       event->scroll.y_root = source_event->scroll.y_root;
       event->scroll.state = state;
       event->scroll.device = source_event->scroll.device;
+      event->scroll.delta_x = source_event->scroll.delta_x;
+      event->scroll.delta_y = source_event->scroll.delta_y;
       gdk_event_set_source_device (event, source_device);
       return TRUE;
 
@@ -9878,7 +10018,9 @@ _gdk_windowing_got_event (GdkDisplay *display,
         }
     }
 
-  if (pointer_info)
+  if (pointer_info &&
+      (!is_touch_type (event->type) ||
+       _gdk_event_get_pointer_emulated (event)))
     {
       guint old_state, old_button;
 
@@ -9895,6 +10037,9 @@ _gdk_windowing_got_event (GdkDisplay *display,
       if (event->type == GDK_BUTTON_PRESS ||
           event->type == GDK_BUTTON_RELEASE)
         pointer_info->button = event->button.button;
+      else if (event->type == GDK_TOUCH_BEGIN ||
+               event->type == GDK_TOUCH_END)
+        pointer_info->button = 1;
 
       if (device &&
           (pointer_info->state != old_state ||
@@ -10283,7 +10428,7 @@ gdk_window_get_root_origin (GdkWindow *window,
 /**
  * gdk_window_get_frame_extents:
  * @window: a toplevel #GdkWindow
- * @rect: rectangle to fill with bounding box of the window frame
+ * @rect: (out): rectangle to fill with bounding box of the window frame
  *
  * Obtains the bounding box of the window, including window manager
  * titlebar/borders if any. The frame position is given in root window