]> Pileus Git - ~andy/gtk/blobdiff - gdk/gdkevents.c
[broadway] Cancel key events after seeing them
[~andy/gtk] / gdk / gdkevents.c
index fa61e082b99c9c93c09f71be66a28523d541be00..29dff076d00c9951f829a33f4adf480bb0aded15 100644 (file)
@@ -27,6 +27,7 @@
 #include "config.h"
 
 #include "gdkinternals.h"
+#include "gdkdisplayprivate.h"
 
 #include <string.h>
 #include <math.h>
@@ -59,9 +60,16 @@ struct _GdkIOClosure
 /* Private variable declarations
  */
 
-GdkEventFunc   _gdk_event_func = NULL;    /* Callback for events */
-gpointer       _gdk_event_data = NULL;
-GDestroyNotify _gdk_event_notify = NULL;
+static GdkEventFunc   _gdk_event_func = NULL;    /* Callback for events */
+static gpointer       _gdk_event_data = NULL;
+static GDestroyNotify _gdk_event_notify = NULL;
+
+void
+_gdk_event_emit (GdkEvent *event)
+{
+  if (_gdk_event_func)
+    (*_gdk_event_func) (event, _gdk_event_data);
+}
 
 /*********************************************
  * Functions for maintaining the event queue *
@@ -269,6 +277,45 @@ gdk_event_handler_set (GdkEventFunc   func,
   _gdk_event_notify = notify;
 }
 
+/**
+ * gdk_events_pending:
+ *
+ * Checks if any events are ready to be processed for any display.
+ *
+ * Return value: %TRUE if any events are pending.
+ */
+gboolean
+gdk_events_pending (void)
+{
+  GSList *list, *l;
+  gboolean pending;
+
+  pending = FALSE;
+  list = gdk_display_manager_list_displays (gdk_display_manager_get ());
+  for (l = list; l; l = l->next)
+    {
+      if (_gdk_event_queue_find_first (l->data))
+        {
+          pending = TRUE;
+          goto out;
+        }
+    }
+
+  for (l = list; l; l = l->next)
+    {
+      if (gdk_display_has_pending (l->data))
+        {
+          pending = TRUE;
+          goto out;
+        }
+    }
+
+ out:
+  g_slist_free (list);
+
+  return pending;
+}
+
 /**
  * gdk_event_get:
  * 
@@ -282,16 +329,21 @@ gdk_event_handler_set (GdkEventFunc   func,
 GdkEvent*
 gdk_event_get (void)
 {
-  GSList *tmp_list;
+  GSList *list, *l;
+  GdkEvent *event;
 
-  for (tmp_list = _gdk_displays; tmp_list; tmp_list = tmp_list->next)
+  event = NULL;
+  list = gdk_display_manager_list_displays (gdk_display_manager_get ());
+  for (l = list; l; l = l->next)
     {
-      GdkEvent *event = gdk_display_get_event (tmp_list->data);
+      event = gdk_display_get_event (l->data);
       if (event)
-       return event;
+        break;
     }
 
-  return NULL;
+  g_slist_free (list);
+
+  return event;
 }
 
 /**
@@ -307,16 +359,21 @@ gdk_event_get (void)
 GdkEvent*
 gdk_event_peek (void)
 {
-  GSList *tmp_list;
+  GSList *list, *l;
+  GdkEvent *event;
 
-  for (tmp_list = _gdk_displays; tmp_list; tmp_list = tmp_list->next)
+  event = NULL;
+  list = gdk_display_manager_list_displays (gdk_display_manager_get ());
+  for (l = list; l; l = l->next)
     {
-      GdkEvent *event = gdk_display_peek_event (tmp_list->data);
+      event = gdk_display_peek_event (l->data);
       if (event)
-       return event;
+        break;
     }
 
-  return NULL;
+  g_slist_free (list);
+
+  return event;
 }
 
 /**
@@ -446,9 +503,9 @@ gdk_event_copy (const GdkEvent *event)
 {
   GdkEventPrivate *new_private;
   GdkEvent *new_event;
-  
+
   g_return_val_if_fail (event != NULL, NULL);
-  
+
   new_event = gdk_event_new (GDK_NOTHING);
   new_private = (GdkEventPrivate *)new_event;
 
@@ -462,21 +519,22 @@ gdk_event_copy (const GdkEvent *event)
 
       new_private->screen = private->screen;
       new_private->device = private->device;
+      new_private->source_device = private->source_device;
     }
-  
+
   switch (event->any.type)
     {
     case GDK_KEY_PRESS:
     case GDK_KEY_RELEASE:
       new_event->key.string = g_strdup (event->key.string);
       break;
-      
+
     case GDK_ENTER_NOTIFY:
     case GDK_LEAVE_NOTIFY:
       if (event->crossing.subwindow != NULL)
-       g_object_ref (event->crossing.subwindow);
+        g_object_ref (event->crossing.subwindow);
       break;
-      
+
     case GDK_DRAG_ENTER:
     case GDK_DRAG_LEAVE:
     case GDK_DRAG_MOTION:
@@ -485,38 +543,53 @@ gdk_event_copy (const GdkEvent *event)
     case GDK_DROP_FINISHED:
       g_object_ref (event->dnd.context);
       break;
-      
+
     case GDK_EXPOSE:
     case GDK_DAMAGE:
       if (event->expose.region)
-       new_event->expose.region = cairo_region_copy (event->expose.region);
+        new_event->expose.region = cairo_region_copy (event->expose.region);
       break;
-      
+
     case GDK_SETTING:
       new_event->setting.name = g_strdup (new_event->setting.name);
       break;
 
     case GDK_BUTTON_PRESS:
+    case GDK_2BUTTON_PRESS:
+    case GDK_3BUTTON_PRESS:
     case GDK_BUTTON_RELEASE:
-      if (event->button.axes) 
-       new_event->button.axes = g_memdup (event->button.axes, 
-                                            sizeof (gdouble) * event->button.device->num_axes);
+      if (event->button.axes)
+        new_event->button.axes = g_memdup (event->button.axes,
+                                           sizeof (gdouble) * gdk_device_get_n_axes (event->button.device));
       break;
 
     case GDK_MOTION_NOTIFY:
-      if (event->motion.axes) 
-       new_event->motion.axes = g_memdup (event->motion.axes, 
-                                          sizeof (gdouble) * event->motion.device->num_axes);
-      
+      if (event->motion.axes)
+        new_event->motion.axes = g_memdup (event->motion.axes,
+                                           sizeof (gdouble) * gdk_device_get_n_axes (event->motion.device));
       break;
-      
+
+    case GDK_OWNER_CHANGE:
+      new_event->owner_change.owner = event->owner_change.owner;
+      if (new_event->owner_change.owner)
+        g_object_ref (new_event->owner_change.owner);
+      break;
+
+    case GDK_SELECTION_CLEAR:
+    case GDK_SELECTION_NOTIFY:
+    case GDK_SELECTION_REQUEST:
+      new_event->selection.requestor = event->selection.requestor;
+      if (new_event->selection.requestor)
+        g_object_unref (new_event->selection.requestor);
+      break;
+
     default:
       break;
     }
 
   if (gdk_event_is_allocated (event))
-    _gdk_windowing_event_data_copy (event, new_event);
-  
+    _gdk_display_event_data_copy (gdk_display_get_default (), event, new_event);
+
   return new_event;
 }
 
@@ -532,6 +605,8 @@ gdk_event_copy (const GdkEvent *event)
 void
 gdk_event_free (GdkEvent *event)
 {
+  GdkDisplay *display;
+
   g_return_if_fail (event != NULL);
 
   if (event->any.window)
@@ -561,6 +636,8 @@ gdk_event_free (GdkEvent *event)
       break;
 
     case GDK_BUTTON_PRESS:
+    case GDK_2BUTTON_PRESS:
+    case GDK_3BUTTON_PRESS:
     case GDK_BUTTON_RELEASE:
       g_free (event->button.axes);
       break;
@@ -579,11 +656,25 @@ gdk_event_free (GdkEvent *event)
       g_free (event->setting.name);
       break;
       
+    case GDK_OWNER_CHANGE:
+      if (event->owner_change.owner)
+        g_object_unref (event->owner_change.owner);
+      break;
+
+    case GDK_SELECTION_CLEAR:
+    case GDK_SELECTION_NOTIFY:
+    case GDK_SELECTION_REQUEST:
+      if (event->selection.requestor)
+        g_object_unref (event->selection.requestor);
+      break;
+
     default:
       break;
     }
 
-  _gdk_windowing_event_data_free (event);
+  display = gdk_display_get_default ();
+  if (display)
+    _gdk_display_event_data_free (display, event);
 
   g_hash_table_remove (event_hash, event);
   g_slice_free (GdkEventPrivate, (GdkEventPrivate*) event);
@@ -637,7 +728,6 @@ gdk_event_get_time (const GdkEvent *event)
        return event->dnd.time;
       case GDK_CLIENT_EVENT:
       case GDK_VISIBILITY_NOTIFY:
-      case GDK_NO_EXPOSE:
       case GDK_CONFIGURE:
       case GDK_FOCUS_CHANGE:
       case GDK_NOTHING:
@@ -701,11 +791,8 @@ gdk_event_get_state (const GdkEvent        *event,
        *state =  event->crossing.state;
         return TRUE;
       case GDK_PROPERTY_NOTIFY:
-       *state =  event->property.state;
-        return TRUE;
       case GDK_VISIBILITY_NOTIFY:
       case GDK_CLIENT_EVENT:
-      case GDK_NO_EXPOSE:
       case GDK_CONFIGURE:
       case GDK_FOCUS_CHANGE:
       case GDK_SELECTION_CLEAR:
@@ -865,7 +952,7 @@ gdk_event_get_root_coords (const GdkEvent *event,
 /**
  * gdk_event_get_axis:
  * @event: a #GdkEvent
- * @axis_use: (out): the axis use to look for
+ * @axis_use: the axis use to look for
  * @value: (out): location to store the value found
  * 
  * Extract the axis value for a particular axis use from
@@ -1072,11 +1159,75 @@ gdk_event_get_device (const GdkEvent *event)
     }
 }
 
+/**
+ * gdk_event_set_source_device:
+ * @event: a #GdkEvent
+ * @device: a #GdkDevice
+ *
+ * Sets the slave device for @event to @device.
+ *
+ * The event must have been allocated by GTK+,
+ * for instance by gdk_event_copy().
+ *
+ * Since: 3.0
+ **/
+void
+gdk_event_set_source_device (GdkEvent  *event,
+                             GdkDevice *device)
+{
+  GdkEventPrivate *private;
+
+  g_return_if_fail (gdk_event_is_allocated (event));
+  g_return_if_fail (GDK_IS_DEVICE (device));
+
+  private = (GdkEventPrivate *) event;
+
+  private->source_device = device;
+}
+
+/**
+ * gdk_event_get_source_device:
+ * @event: a #GdkEvent
+ *
+ * This function returns the hardware (slave) #GdkDevice that has
+ * triggered the event, falling back to the virtual (master) device
+ * (as in gdk_event_get_device()) if the event wasn't caused by
+ * interaction with a hardware device. This may happen for example
+ * in synthesized crossing events after a #GdkWindow updates its
+ * geometry or a grab is acquired/released.
+ *
+ * If the event does not contain a device field, this function will
+ * return %NULL.
+ *
+ * Returns: (transfer none): a #GdkDevice, or %NULL.
+ *
+ * Since: 3.0
+ **/
+GdkDevice *
+gdk_event_get_source_device (const GdkEvent *event)
+{
+  GdkEventPrivate *private;
+
+  g_return_val_if_fail (event != NULL, NULL);
+
+  if (!gdk_event_is_allocated (event))
+    return NULL;
+
+  private = (GdkEventPrivate *) event;
+
+  if (private->source_device)
+    return private->source_device;
+
+  /* Fallback to event device */
+  return gdk_event_get_device (event);
+}
+
 /**
  * gdk_event_request_motions:
  * @event: a valid #GdkEvent
  *
  * Request more motion notifies if @event is a motion notify hint event.
+ *
  * This function should be used instead of gdk_window_get_pointer() to
  * request further motion notifies, because it also works for extension
  * events where motion notifies are provided for devices other than the
@@ -1084,7 +1235,7 @@ gdk_event_get_device (const GdkEvent *event)
  * motion events from a %GDK_MOTION_NOTIFY event usually works like this:
  *
  * |[
- * { 
+ * {
  *   /&ast; motion_event handler &ast;/
  *   x = motion_event->x;
  *   y = motion_event->y;
@@ -1144,7 +1295,7 @@ gdk_events_get_axis_distances (GdkEvent *event1,
  * gdk_events_get_distance:
  * @event1: first #GdkEvent
  * @event2: second #GdkEvent
- * @distance: return location for the distance
+ * @distance: (out): return location for the distance
  *
  * If both events have X/Y information, the distance between both coordinates
  * (as in a straight line going from @event1 to @event2) will be returned.
@@ -1167,7 +1318,7 @@ gdk_events_get_distance (GdkEvent *event1,
  * gdk_events_get_angle:
  * @event1: first #GdkEvent
  * @event2: second #GdkEvent
- * @angle: return location for the relative angle between both events
+ * @angle: (out): return location for the relative angle between both events
  *
  * If both events contain X/Y information, this function will return %TRUE
  * and return in @angle the relative angle from @event1 to @event2. The rotation
@@ -1278,7 +1429,7 @@ gdk_event_set_screen (GdkEvent  *event,
  * to which <literal>event->motion.x_root</literal> and
  * <literal>event->motion.y_root</literal> are relative.
  * 
- * Return value: the screen for the event
+ * Return value: (transfer none): the screen for the event
  *
  * Since: 2.2
  **/
@@ -1338,20 +1489,15 @@ gdk_get_show_events (void)
 
 static void
 gdk_synthesize_click (GdkDisplay *display,
-                     GdkEvent   *event,
-                     gint        nclicks)
+                      GdkEvent   *event,
+                      gint        nclicks)
 {
-  GdkEvent temp_event;
   GdkEvent *event_copy;
-  GList *link;
-  
-  g_return_if_fail (event != NULL);
-  
-  temp_event = *event;
-  temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
 
-  event_copy = gdk_event_copy (&temp_event);
-  link = _gdk_event_queue_append (display, event_copy);
+  event_copy = gdk_event_copy (event);
+  event_copy->type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
+
+  _gdk_event_queue_append (display, event_copy);
 }
 
 void
@@ -1360,6 +1506,8 @@ _gdk_event_button_generate (GdkDisplay *display,
 {
   GdkMultipleClickInfo *info;
 
+  g_return_if_fail (event->type == GDK_BUTTON_PRESS);
+
   info = g_hash_table_lookup (display->multiple_click_info, event->button.device);
 
   if (G_UNLIKELY (!info))
@@ -1436,7 +1584,7 @@ gdk_synthesize_window_state (GdkWindow     *window,
   temp_event.window_state.type = GDK_WINDOW_STATE;
   temp_event.window_state.send_event = FALSE;
   
-  old = ((GdkWindowObject*) temp_event.window_state.window)->state;
+  old = temp_event.window_state.window->state;
   
   temp_event.window_state.new_window_state = old;
   temp_event.window_state.new_window_state |= set_flags;
@@ -1451,7 +1599,7 @@ gdk_synthesize_window_state (GdkWindow     *window,
    * inconsistent state to the user.
    */
   
-  ((GdkWindowObject*) window)->state = temp_event.window_state.new_window_state;
+  window->state = temp_event.window_state.new_window_state;
 
   if (temp_event.window_state.changed_mask & GDK_WINDOW_STATE_WITHDRAWN)
     _gdk_window_update_viewable (window);
@@ -1461,7 +1609,7 @@ gdk_synthesize_window_state (GdkWindow     *window,
    * Non-toplevels do use the GDK_WINDOW_STATE_WITHDRAWN flag
    * internally so we needed to update window->state.
    */
-  switch (((GdkWindowObject*) window)->window_type)
+  switch (window->window_type)
     {
     case GDK_WINDOW_TOPLEVEL:
     case GDK_WINDOW_TEMP: /* ? */