]> Pileus Git - ~andy/gtk/blobdiff - gdk/gdkdisplay.c
GdkFrameClockIdle: remove timeouts in dispose
[~andy/gtk] / gdk / gdkdisplay.c
index b2d65d2a13f4fdcb292c6330c1d20edb6de9ee8c..79d162b2a9df6261ac18b4612e2b8904ab82646a 100644 (file)
@@ -16,9 +16,7 @@
  * Library General Public License for more details.
  *
  * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "config.h"
@@ -188,6 +186,7 @@ gdk_display_init (GdkDisplay *display)
   display->double_click_time = 250;
   display->double_click_distance = 5;
 
+  display->touch_implicit_grabs = g_array_new (FALSE, FALSE, sizeof (GdkTouchGrabInfo));
   display->device_grabs = g_hash_table_new (NULL, NULL);
   display->motion_hint_info = g_hash_table_new_full (NULL, NULL, NULL,
                                                      (GDestroyNotify) g_free);
@@ -236,6 +235,8 @@ gdk_display_finalize (GObject *object)
                                NULL);
   g_hash_table_destroy (display->device_grabs);
 
+  g_array_free (display->touch_implicit_grabs, TRUE);
+
   g_hash_table_destroy (display->motion_hint_info);
   g_hash_table_destroy (display->pointers_info);
   g_hash_table_destroy (display->multiple_click_info);
@@ -306,7 +307,11 @@ gdk_display_get_event (GdkDisplay *display)
 {
   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
 
+  if (display->event_pause_count > 0)
+    return NULL;
+
   GDK_DISPLAY_GET_CLASS (display)->queue_events (display);
+
   return _gdk_event_unqueue (display);
 }
 
@@ -694,6 +699,73 @@ _gdk_display_add_device_grab (GdkDisplay       *display,
   return info;
 }
 
+static void
+_gdk_display_break_touch_grabs (GdkDisplay *display,
+                                GdkDevice  *device,
+                                GdkWindow  *new_grab_window)
+{
+  guint i;
+
+  for (i = 0; i < display->touch_implicit_grabs->len; i++)
+    {
+      GdkTouchGrabInfo *info;
+
+      info = &g_array_index (display->touch_implicit_grabs,
+                             GdkTouchGrabInfo, i);
+
+      if (info->device == device && info->window != new_grab_window)
+        generate_grab_broken_event (GDK_WINDOW (info->window),
+                                    device, TRUE, new_grab_window);
+    }
+}
+
+void
+_gdk_display_add_touch_grab (GdkDisplay       *display,
+                             GdkDevice        *device,
+                             GdkEventSequence *sequence,
+                             GdkWindow        *window,
+                             GdkWindow        *native_window,
+                             GdkEventMask      event_mask,
+                             unsigned long     serial,
+                             guint32           time)
+{
+  GdkTouchGrabInfo info;
+
+  info.device = device;
+  info.sequence = sequence;
+  info.window = g_object_ref (window);
+  info.native_window = g_object_ref (native_window);
+  info.serial = serial;
+  info.event_mask = event_mask;
+  info.time = time;
+
+  g_array_append_val (display->touch_implicit_grabs, info);
+}
+
+gboolean
+_gdk_display_end_touch_grab (GdkDisplay       *display,
+                             GdkDevice        *device,
+                             GdkEventSequence *sequence)
+{
+  guint i;
+
+  for (i = 0; i < display->touch_implicit_grabs->len; i++)
+    {
+      GdkTouchGrabInfo *info;
+
+      info = &g_array_index (display->touch_implicit_grabs,
+                             GdkTouchGrabInfo, i);
+
+      if (info->device == device && info->sequence == sequence)
+        {
+          g_array_remove_index_fast (display->touch_implicit_grabs, i);
+          return TRUE;
+        }
+    }
+
+  return FALSE;
+}
+
 /* _gdk_synthesize_crossing_events only works inside one toplevel.
    This function splits things into two calls if needed, converting the
    coordinates to the right toplevel */
@@ -897,17 +969,28 @@ switch_to_pointer_grab (GdkDisplay        *display,
 
       if (grab == NULL) /* Ungrabbed, send events */
        {
-         pointer_window = NULL;
-         if (new_toplevel)
-           {
-             /* Find (possibly virtual) child window */
-             pointer_window =
-               _gdk_window_find_descendant_at (new_toplevel,
-                                               x, y,
-                                               NULL, NULL);
-           }
+          /* If the source device is a touch device, do not
+           * propagate any enter event yet, until one is
+           * synthesized when needed.
+           */
+          if (source_device &&
+              (gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHSCREEN))
+            info->need_touch_press_enter = TRUE;
 
-         if (pointer_window != last_grab->window)
+          pointer_window = NULL;
+
+          if (new_toplevel &&
+              !info->need_touch_press_enter)
+            {
+              /* Find (possibly virtual) child window */
+              pointer_window =
+                _gdk_window_find_descendant_at (new_toplevel,
+                                                x, y,
+                                                NULL, NULL);
+            }
+
+         if (!info->need_touch_press_enter &&
+             pointer_window != last_grab->window)
             synthesize_crossing_events (display, device, source_device,
                                         last_grab->window, pointer_window,
                                         GDK_CROSSING_UNGRAB, time, serial);
@@ -964,12 +1047,15 @@ _gdk_display_device_grab_update (GdkDisplay *display,
            next_grab = NULL; /* Actually its not yet active */
        }
 
+      if (next_grab)
+        _gdk_display_break_touch_grabs (display, device, next_grab->window);
+
       if ((next_grab == NULL && current_grab->implicit_ungrab) ||
-         (next_grab != NULL && current_grab->window != next_grab->window))
-       generate_grab_broken_event (GDK_WINDOW (current_grab->window),
+          (next_grab != NULL && current_grab->window != next_grab->window))
+        generate_grab_broken_event (GDK_WINDOW (current_grab->window),
                                     device,
-                                   current_grab->implicit,
-                                   next_grab? next_grab->window : NULL);
+                                    current_grab->implicit,
+                                    next_grab? next_grab->window : NULL);
 
       /* Remove old grab */
       grabs = g_list_delete_link (grabs, grabs);
@@ -1028,6 +1114,33 @@ _gdk_display_has_device_grab (GdkDisplay *display,
   return NULL;
 }
 
+GdkTouchGrabInfo *
+_gdk_display_has_touch_grab (GdkDisplay       *display,
+                             GdkDevice        *device,
+                             GdkEventSequence *sequence,
+                             gulong            serial)
+{
+  guint i;
+
+  for (i = 0; i < display->touch_implicit_grabs->len; i++)
+    {
+      GdkTouchGrabInfo *info;
+
+      info = &g_array_index (display->touch_implicit_grabs,
+                             GdkTouchGrabInfo, i);
+
+      if (info->device == device && info->sequence == sequence)
+        {
+          if (serial >= info->serial)
+            return info;
+          else
+            return NULL;
+        }
+    }
+
+  return NULL;
+}
+
 /* Returns true if last grab was ended
  * If if_child is non-NULL, end the grab only if the grabbed
  * window is the same as if_child or a descendant of it */
@@ -1494,7 +1607,7 @@ gdk_display_request_selection_notification (GdkDisplay *display,
 }
 
 /**
- * gdk_display_supports_clipboard_persistence
+ * gdk_display_supports_clipboard_persistence:
  * @display: a #GdkDisplay
  *
  * Returns whether the speicifed display supports clipboard
@@ -1515,7 +1628,7 @@ gdk_display_supports_clipboard_persistence (GdkDisplay *display)
 }
 
 /**
- * gdk_display_store_clipboard
+ * gdk_display_store_clipboard:
  * @display:          a #GdkDisplay
  * @clipboard_window: a #GdkWindow belonging to the clipboard owner
  * @time_:            a timestamp
@@ -1894,6 +2007,38 @@ gdk_display_notify_startup_complete (GdkDisplay  *display,
   GDK_DISPLAY_GET_CLASS (display)->notify_startup_complete (display, startup_id);
 }
 
+void
+_gdk_display_pause_events (GdkDisplay *display)
+{
+  display->event_pause_count++;
+}
+
+void
+_gdk_display_unpause_events (GdkDisplay *display)
+{
+  g_return_if_fail (display->event_pause_count > 0);
+
+  display->event_pause_count--;
+}
+
+void
+_gdk_display_flush_events (GdkDisplay *display)
+{
+  display->flushing_events = TRUE;
+
+  while (TRUE)
+    {
+      GdkEvent *event = _gdk_event_unqueue (display);
+      if (event == NULL)
+        break;
+
+      _gdk_event_emit (event);
+      gdk_event_free (event);
+    }
+
+  display->flushing_events = FALSE;
+}
+
 void
 _gdk_display_event_data_copy (GdkDisplay     *display,
                               const GdkEvent *event,