[mutter/wip/barriers-try-2: 35/36] barrier: Add signals for barrier events
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/barriers-try-2: 35/36] barrier: Add signals for barrier events
- Date: Mon, 10 Dec 2012 01:19:28 +0000 (UTC)
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]