[mutter/wip/barriers-try-2: 35/36] barrier: Add signals for barrier events



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

    barrier: Add signals for barrier events
    
    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         |  119 ++++++++++++++++++++++++++++++++++++++++++++
 src/core/display-private.h |    7 +++
 src/core/display.c         |   19 +++++++
 src/core/screen.c          |    2 +
 src/meta/barrier.h         |   15 ++++++
 5 files changed, 162 insertions(+), 0 deletions(-)
---
diff --git a/src/core/barrier.c b/src/core/barrier.c
index 9dceb47..1df175d 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,15 @@ enum {
 
 static GParamSpec *obj_props[PROP_LAST];
 
+enum {
+  HIT,
+  LEFT,
+
+  LAST_SIGNAL,
+};
+
+static guint obj_signals[LAST_SIGNAL];
+
 struct _MetaBarrierPrivate
 {
   MetaDisplay *display;
@@ -179,6 +189,7 @@ meta_barrier_activate (MetaBarrier *barrier)
                                               priv->x1, priv->y1,
                                               priv->x2, priv->y2,
                                               priv->directions, 0, NULL);
+  g_hash_table_insert (priv->display->barriers, GINT_TO_POINTER (priv->barrier), g_object_ref (barrier));
 }
 
 static void
@@ -238,6 +249,42 @@ 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
+   * the barrier was 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_EVENT);
+
+  /**
+   * MetaBarrier::left:
+   * @barrier: The #MetaBarrier that was left
+   * @event: A #MetaBarrierEvent that has the details of how
+   * the barrier was left.
+   *
+   * When a pointer barrier hitbox was left, this will trigger.
+   * This requires an XI2-enabled server.
+   */
+  obj_signals[LEFT] =
+    g_signal_new ("left",
+                  G_TYPE_FROM_CLASS (object_class),
+                  G_SIGNAL_RUN_FIRST,
+                  0,
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE, 1,
+                  META_TYPE_BARRIER_EVENT);
+
   g_type_class_add_private (object_class, sizeof(MetaBarrierPrivate));
 }
 
@@ -259,6 +306,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;
 }
 
@@ -267,3 +315,74 @@ meta_barrier_init (MetaBarrier *barrier)
 {
   barrier->priv = GET_PRIVATE (barrier);
 }
+
+static void
+meta_barrier_send_event (MetaBarrier    *barrier,
+                         XIBarrierEvent *xevent)
+{
+  MetaBarrierEvent *event = g_slice_new0 (MetaBarrierEvent);
+
+  event->ref_count = 1;
+  event->event_id = xevent->eventid;
+  event->dt = xevent->dtime;
+
+  event->x = xevent->root_x;
+  event->y = xevent->root_y;
+  event->dx = xevent->dx;
+  event->dy = xevent->dy;
+
+  event->blocked = !!(xevent->flags & XIBarrierPointerReleased);
+
+  switch (xevent->evtype)
+    {
+    case XI_BarrierHit:
+      g_signal_emit (barrier, obj_signals[HIT], 0, event);
+      break;
+    case XI_BarrierLeave:
+      g_signal_emit (barrier, obj_signals[LEFT], 0, event);
+      break;
+    default:
+      g_assert_not_reached ();
+    }
+}
+
+gboolean
+meta_display_process_barrier_event (MetaDisplay    *display,
+                                    XIBarrierEvent *xev)
+{
+  MetaBarrier *barrier;
+
+  barrier = g_hash_table_lookup (display->barriers, GINT_TO_POINTER (xev->barrier));
+  if (barrier != NULL)
+    {
+      meta_barrier_send_event (barrier, xev);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static MetaBarrierEvent *
+meta_barrier_event_ref (MetaBarrierEvent *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_event_unref (MetaBarrierEvent *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 (MetaBarrierEvent, event);
+}
+
+G_DEFINE_BOXED_TYPE (MetaBarrierEvent,
+                     meta_barrier_event,
+                     meta_barrier_event_ref,
+                     meta_barrier_event_unref)
diff --git a/src/core/display-private.h b/src/core/display-private.h
index b4c1b71..0b18db2 100644
--- a/src/core/display-private.h
+++ b/src/core/display-private.h
@@ -39,6 +39,7 @@
 #include <meta/display.h>
 #include "keybindings-private.h"
 #include <meta/prefs.h>
+#include <meta/barrier.h>
 
 #ifdef HAVE_STARTUP_NOTIFICATION
 #include <libsn/sn.h>
@@ -244,6 +245,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;
@@ -448,4 +452,7 @@ void meta_display_overlay_key_activate (MetaDisplay *display);
 /* In above-tab-keycode.c */
 guint meta_display_get_above_tab_keycode (MetaDisplay *display);
 
+gboolean meta_display_process_barrier_event (MetaDisplay    *display,
+                                             XIBarrierEvent *event);
+
 #endif
diff --git a/src/core/display.c b/src/core/display.c
index 6217af3..e65e21d 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -809,6 +809,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.
@@ -1832,6 +1836,10 @@ get_input_event (MetaDisplay *display,
         case XI_Leave:
           return xev;
           break;
+        case XI_BarrierHit:
+        case XI_BarrierLeave:
+          return xev;
+          break;
         default:
           break;
         }
@@ -2396,6 +2404,11 @@ event_callback (XEvent   *event,
 
             }
           break;
+        case XI_BarrierHit:
+        case XI_BarrierLeave:
+          if (meta_display_process_barrier_event (display, (XIBarrierEvent *) xev))
+            filter_out_event = bypass_compositor = TRUE;
+          break;
         }
     }
   else
@@ -2927,6 +2940,9 @@ event_get_modified_window (MetaDisplay *display,
         case XI_Enter:
         case XI_Leave:
           return ((XIEnterEvent *) xev)->event;
+        case XI_BarrierHit:
+        case XI_BarrierLeave:
+          return ((XIBarrierEvent *) xev)->event;
         }
     }
 
@@ -3223,6 +3239,9 @@ meta_spew_xi2event (MetaDisplay *display,
     case XI_Leave:
       name = "XI_Leave";
       break;
+    case XI_BarrierHit:
+      name = "XI_BarrierHit";
+      break;
     }
 
   /* TODO: extra */
diff --git a/src/core/screen.c b/src/core/screen.c
index f86f06a..ff85150 100644
--- a/src/core/screen.c
+++ b/src/core/screen.c
@@ -750,6 +750,8 @@ meta_screen_new (MetaDisplay *display,
     XISetMask (mask.mask, XI_FocusIn);
     XISetMask (mask.mask, XI_FocusOut);
     XISetMask (mask.mask, XI_Motion);
+    XISetMask (mask.mask, XI_BarrierHit);
+    XISetMask (mask.mask, XI_BarrierLeave);
     XISelectEvents (xdisplay, xroot, &mask, 1);
 
     event_mask = (SubstructureRedirectMask | SubstructureNotifyMask |
diff --git a/src/meta/barrier.h b/src/meta/barrier.h
index 66e513b..a1694e2 100644
--- a/src/meta/barrier.h
+++ b/src/meta/barrier.h
@@ -47,6 +47,21 @@ 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;
+  gboolean blocked;
+} MetaBarrierEvent;
+
+#define META_TYPE_BARRIER_EVENT (meta_barrier_event_get_type ())
+GType meta_barrier_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]