[mutter/wip/barriers: 16/16] barrier: Add signals for when a barrier gets hit



commit 7395de9426e2b4a2458290ad213c05700c9b5143
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Mon Jul 30 15:57:53 2012 -0300

    barrier: Add signals for when a barrier gets hit
    
    We want to know when a barrier gets hit so that we can implement
    message tray pressure.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=677215

 src/core/barrier.c         |  101 ++++++++++++++++++++++++++++++++++++++++++++
 src/core/device-map-xi2.c  |    2 +-
 src/core/devices-xi2.c     |    3 +
 src/core/display-private.h |    7 +++
 src/core/display.c         |   10 ++++
 src/meta/barrier.h         |   16 +++++++
 6 files changed, 138 insertions(+), 1 deletions(-)
---
diff --git a/src/core/barrier.c b/src/core/barrier.c
index 254d4e0..ee8738d 100644
--- a/src/core/barrier.c
+++ b/src/core/barrier.c
@@ -4,6 +4,7 @@
 
 #include <glib-object.h>
 
+#include <X11/extensions/XInput2.h>
 #include <X11/extensions/Xfixes.h>
 #include <meta/util.h>
 #include <meta/barrier.h>
@@ -31,6 +32,14 @@ enum {
 
 static GParamSpec *obj_props[PROP_LAST];
 
+enum {
+  HIT,
+
+  LAST_SIGNAL,
+};
+
+static guint obj_signals[LAST_SIGNAL];
+
 struct _MetaBarrierPrivate
 {
   MetaDisplay *display;
@@ -183,6 +192,7 @@ meta_barrier_activate (MetaBarrier *barrier)
                                               priv->x2, priv->y2,
                                               priv->directions,
                                               n_devices, devices);
+  g_hash_table_insert (priv->display->barriers, GINT_TO_POINTER (priv->barrier), g_object_ref (barrier));
 }
 
 static void
@@ -255,6 +265,24 @@ meta_barrier_class_init (MetaBarrierClass *klass)
 
   g_object_class_install_properties (object_class, PROP_LAST, obj_props);
 
+  /**
+   * MetaBarrier::hit:
+   * @barrier: The #MetaBarrier that was hit
+   * @event: A #MetaBarrierEvent that has the details of how
+   * things were hit.
+   *
+   * When a pointer barrier is hit, this will trigger. This
+   * requires an XI2-enabled server.
+   */
+  obj_signals[HIT] =
+    g_signal_new ("hit",
+                  G_TYPE_FROM_CLASS (object_class),
+                  G_SIGNAL_RUN_FIRST,
+                  0,
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE, 1,
+                  META_TYPE_BARRIER_HIT_EVENT);
+
   g_type_class_add_private (object_class, sizeof(MetaBarrierPrivate));
 }
 
@@ -276,6 +304,7 @@ meta_barrier_destroy (MetaBarrier *barrier)
     return;
 
   XFixesDestroyPointerBarrier (dpy, priv->barrier);
+  g_hash_table_remove (priv->display->barriers, GINT_TO_POINTER (priv->barrier));
   priv->barrier = 0;
 }
 
@@ -284,3 +313,75 @@ meta_barrier_init (MetaBarrier *barrier)
 {
   barrier->priv = GET_PRIVATE (barrier);
 }
+
+static void
+meta_barrier_hit (MetaBarrier          *barrier,
+                  XIBarrierNotifyEvent *xevent)
+{
+  MetaBarrierHitEvent *event = g_slice_new0 (MetaBarrierHitEvent);
+
+  event->ref_count = 1;
+  event->event_id = xevent->event_id;
+  event->dt = xevent->dt;
+
+  event->x = xevent->x;
+  event->y = xevent->y;
+  event->dx = xevent->dx;
+  event->dy = xevent->dy;
+  event->raw_dx = xevent->raw_dx;
+  event->raw_dy = xevent->raw_dy;
+
+  g_signal_emit (barrier, obj_signals[HIT], 0, event);
+}
+
+gboolean
+meta_display_process_barrier_event (MetaDisplay *display,
+                                    XEvent      *ev)
+{
+  if (ev->type == GenericEvent &&
+      ev->xcookie.extension == display->xinput2_opcode)
+    {
+      MetaBarrier *barrier;
+      XIBarrierNotifyEvent *xev;
+
+      g_assert (display->have_xinput2 == TRUE);
+
+      xev = (XIBarrierNotifyEvent *) ev->xcookie.data;
+
+      if (xev->evtype != XI_BarrierHitNotify)
+        return FALSE;
+
+      barrier = g_hash_table_lookup (display->barriers, GINT_TO_POINTER (xev->barrier));
+      if (barrier != NULL)
+        {
+          meta_barrier_hit (barrier, xev);
+          return TRUE;
+        }
+    }
+  return FALSE;
+}
+
+static MetaBarrierHitEvent *
+meta_barrier_hit_event_ref (MetaBarrierHitEvent *event)
+{
+  g_return_val_if_fail (event != NULL, NULL);
+  g_return_val_if_fail (event->ref_count > 0, NULL);
+
+  g_atomic_int_inc ((volatile int *)&event->ref_count);
+  return event;
+}
+
+static void
+meta_barrier_hit_event_unref (MetaBarrierHitEvent *event)
+{
+  g_return_if_fail (event != NULL);
+  g_return_if_fail (event->ref_count > 0);
+
+  if (g_atomic_int_dec_and_test ((volatile int *)&event->ref_count))
+    g_slice_free (MetaBarrierHitEvent, event);
+}
+
+G_DEFINE_BOXED_TYPE (MetaBarrierHitEvent,
+                     meta_barrier_hit_event,
+                     meta_barrier_hit_event_ref,
+                     meta_barrier_hit_event_unref)
diff --git a/src/core/device-map-xi2.c b/src/core/device-map-xi2.c
index 1d778b8..bc99006 100644
--- a/src/core/device-map-xi2.c
+++ b/src/core/device-map-xi2.c
@@ -28,7 +28,7 @@
 #include "input-events.h"
 
 #define XINPUT2_VERSION_MAJOR 2
-#define XINPUT2_VERSION_MINOR 2
+#define XINPUT2_VERSION_MINOR 3
 
 G_DEFINE_TYPE (MetaDeviceMapXI2, meta_device_map_xi2, META_TYPE_DEVICE_MAP)
 
diff --git a/src/core/devices-xi2.c b/src/core/devices-xi2.c
index 53fb9dc..62e7384 100644
--- a/src/core/devices-xi2.c
+++ b/src/core/devices-xi2.c
@@ -105,6 +105,9 @@ meta_device_xi2_translate_event_mask (guint  evmask,
       XISetMask (mask, XI_TouchUpdate);
     }
 
+  /* XXX: Find a way to do this better. */
+  XISetMask (mask, XI_BarrierHitNotify);
+
   return mask;
 }
 
diff --git a/src/core/display-private.h b/src/core/display-private.h
index 4643db1..d972979 100644
--- a/src/core/display-private.h
+++ b/src/core/display-private.h
@@ -40,6 +40,7 @@
 #include "keybindings-private.h"
 #include "device-map-private.h"
 #include <meta/prefs.h>
+#include <meta/barrier.h>
 
 #ifdef HAVE_STARTUP_NOTIFICATION
 #include <libsn/sn.h>
@@ -279,6 +280,9 @@ struct _MetaDisplay
   unsigned int meta_mask;
   MetaKeyCombo overlay_key_combo;
   gboolean overlay_key_only_pressed;
+
+  /* barriers */
+  GHashTable *barriers;
   
   /* Monitor cache */
   unsigned int monitor_cache_invalidated : 1;
@@ -321,6 +325,7 @@ struct _MetaDisplay
   int damage_error_base;
   int xfixes_event_base;
   int xfixes_error_base;
+  int xfixes_major_opcode;
   
 #ifdef HAVE_STARTUP_NOTIFICATION
   SnDisplay *sn_display;
@@ -506,5 +511,7 @@ MetaGrabInfo * meta_display_get_grab_info            (MetaDisplay  *display,
 MetaFocusInfo * meta_display_get_focus_info          (MetaDisplay  *display,
                                                       MetaDevice   *device);
 
+gboolean meta_display_process_barrier_event (MetaDisplay *display,
+                                             XEvent      *ev);
 
 #endif
diff --git a/src/core/display.c b/src/core/display.c
index 7479367..8a7686d 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -794,6 +794,10 @@ meta_display_open (void)
   meta_verbose ("Not compiled with Xcursor support\n");
 #endif /* !HAVE_XCURSOR */
 
+  the_display->barriers = g_hash_table_new_full (g_direct_hash,
+                                                 g_direct_equal,
+                                                 NULL, g_object_unref);
+
   /* Create the leader window here. Set its properties and
    * use the timestamp from one of the PropertyNotify events
    * that will follow.
@@ -1988,6 +1992,12 @@ event_callback (XEvent   *event,
       filter_out_event = FALSE;
       bypass_compositor = FALSE;
     }
+  else if (display->have_xinput2 &&
+           meta_display_process_barrier_event (display, event))
+    {
+      filter_out_event = TRUE;
+      bypass_compositor = TRUE;
+    }
   else
 #endif
   if (meta_input_event_get_type (display, event, &evtype))
diff --git a/src/meta/barrier.h b/src/meta/barrier.h
index 42460fc..97aae20 100644
--- a/src/meta/barrier.h
+++ b/src/meta/barrier.h
@@ -45,6 +45,22 @@ typedef enum {
   META_BARRIER_DIRECTION_NEGATIVE_Y = (1L << 3),
 } MetaBarrierDirection;
 
+typedef struct {
+  int ref_count;
+
+  int event_id;
+  int dt;
+  double x;
+  double y;
+  double dx;
+  double dy;
+  double raw_dx;
+  double raw_dy;
+} MetaBarrierHitEvent;
+
+#define META_TYPE_BARRIER_HIT_EVENT (meta_barrier_hit_event_get_type ())
+GType meta_barrier_hit_event_get_type (void) G_GNUC_CONST;
+
 G_END_DECLS
 
 #endif /* __META_BARRIER_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]