diff --git a/src/Makefile.am b/src/Makefile.am index 9071d1a06..a7e74067d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -33,6 +33,8 @@ mutter_built_sources = \ libmutter_la_SOURCES = \ core/async-getprop.c \ core/async-getprop.h \ + core/barrier.c \ + meta/barrier.h \ core/bell.c \ core/bell.h \ core/boxes.c \ @@ -157,6 +159,7 @@ libmutter_la_LIBADD = $(MUTTER_LIBS) # Headers installed for plugins; introspected information will # be extracted into Mutter-.gir libmutterinclude_base_headers = \ + meta/barrier.h \ meta/boxes.h \ meta/common.h \ meta/compositor-mutter.h \ diff --git a/src/core/barrier.c b/src/core/barrier.c new file mode 100644 index 000000000..69db69e6b --- /dev/null +++ b/src/core/barrier.c @@ -0,0 +1,243 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; c-basic-offset: 2; -*- */ + +#include "config.h" + +#include + +#include +#include +#include +#include "display-private.h" +#include "mutter-enum-types.h" +#include "core.h" + +G_DEFINE_TYPE (MetaBarrier, meta_barrier, G_TYPE_OBJECT) + +enum { + PROP_0, + + PROP_DISPLAY, + + PROP_X1, + PROP_Y1, + PROP_X2, + PROP_Y2, + PROP_DIRECTIONS, + + PROP_LAST, +}; + +static GParamSpec *obj_props[PROP_LAST]; + +struct _MetaBarrierPrivate +{ + MetaDisplay *display; + + int x1; + int y1; + int x2; + int y2; + + MetaBarrierDirection directions; + + PointerBarrier xbarrier; +}; + +static void +meta_barrier_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MetaBarrier *barrier = META_BARRIER (object); + MetaBarrierPrivate *priv = barrier->priv; + switch (prop_id) + { + case PROP_DISPLAY: + g_value_set_object (value, priv->display); + break; + case PROP_X1: + g_value_set_int (value, priv->x1); + break; + case PROP_Y1: + g_value_set_int (value, priv->y1); + break; + case PROP_X2: + g_value_set_int (value, priv->x2); + break; + case PROP_Y2: + g_value_set_int (value, priv->y2); + break; + case PROP_DIRECTIONS: + g_value_set_flags (value, priv->directions); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +meta_barrier_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MetaBarrier *barrier = META_BARRIER (object); + MetaBarrierPrivate *priv = barrier->priv; + switch (prop_id) + { + case PROP_DISPLAY: + priv->display = g_value_get_object (value); + break; + case PROP_X1: + priv->x1 = g_value_get_int (value); + break; + case PROP_Y1: + priv->y1 = g_value_get_int (value); + break; + case PROP_X2: + priv->x2 = g_value_get_int (value); + break; + case PROP_Y2: + priv->y2 = g_value_get_int (value); + break; + case PROP_DIRECTIONS: + priv->directions = g_value_get_flags (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +meta_barrier_dispose (GObject *object) +{ + MetaBarrier *barrier = META_BARRIER (object); + MetaBarrierPrivate *priv = barrier->priv; + + if (meta_barrier_is_active (barrier)) + { + meta_bug ("MetaBarrier wrapper %p for X barrier %ld was destroyed" + " while the X barrier is still active.", + barrier, priv->xbarrier); + } + + G_OBJECT_CLASS (meta_barrier_parent_class)->dispose (object); +} + +gboolean +meta_barrier_is_active (MetaBarrier *barrier) +{ + return barrier->priv->xbarrier != 0; +} + +static void +meta_barrier_constructed (GObject *object) +{ + MetaBarrier *barrier = META_BARRIER (object); + MetaBarrierPrivate *priv = barrier->priv; + Display *dpy; + Window root; + + g_return_if_fail (priv->x1 == priv->x2 || priv->y1 == priv->y2); + + if (priv->display == NULL) + { + g_warning ("A display must be provided when constructing a barrier."); + return; + } + + dpy = priv->display->xdisplay; + root = DefaultRootWindow (dpy); + + priv->xbarrier = XFixesCreatePointerBarrier (dpy, root, + priv->x1, priv->y1, + priv->x2, priv->y2, + priv->directions, 0, NULL); + + G_OBJECT_CLASS (meta_barrier_parent_class)->constructed (object); +} + +static void +meta_barrier_class_init (MetaBarrierClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = meta_barrier_get_property; + object_class->set_property = meta_barrier_set_property; + object_class->dispose = meta_barrier_dispose; + object_class->constructed = meta_barrier_constructed; + + obj_props[PROP_DISPLAY] = + g_param_spec_object ("display", + "Display", + "The display to construct the pointer barrier on", + META_TYPE_DISPLAY, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + obj_props[PROP_X1] = + g_param_spec_int ("x1", + "X1", + "The first X coordinate of the barrier", + 0, G_MAXSHORT, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + obj_props[PROP_Y1] = + g_param_spec_int ("y1", + "Y1", + "The first Y coordinate of the barrier", + 0, G_MAXSHORT, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + obj_props[PROP_X2] = + g_param_spec_int ("x2", + "X2", + "The second X coordinate of the barrier", + 0, G_MAXSHORT, G_MAXSHORT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + obj_props[PROP_Y2] = + g_param_spec_int ("y2", + "Y2", + "The second Y coordinate of the barrier", + 0, G_MAXSHORT, G_MAXSHORT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + obj_props[PROP_DIRECTIONS] = + g_param_spec_flags ("directions", + "Directions", + "A set of directions to let the pointer through", + META_TYPE_BARRIER_DIRECTION, + 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, PROP_LAST, obj_props); + + g_type_class_add_private (object_class, sizeof(MetaBarrierPrivate)); +} + +void +meta_barrier_destroy (MetaBarrier *barrier) +{ + MetaBarrierPrivate *priv = barrier->priv; + Display *dpy; + + if (priv->display == NULL) + return; + + dpy = priv->display->xdisplay; + + if (!meta_barrier_is_active (barrier)) + return; + + XFixesDestroyPointerBarrier (dpy, priv->xbarrier); + priv->xbarrier = 0; +} + +static void +meta_barrier_init (MetaBarrier *barrier) +{ + barrier->priv = G_TYPE_INSTANCE_GET_PRIVATE (barrier, META_TYPE_BARRIER, MetaBarrierPrivate); +} diff --git a/src/meta/barrier.h b/src/meta/barrier.h new file mode 100644 index 000000000..cf45daaf1 --- /dev/null +++ b/src/meta/barrier.h @@ -0,0 +1,50 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; c-basic-offset: 2; -*- */ + +#ifndef __META_BARRIER_H__ +#define __META_BARRIER_H__ + +#include + +#include + +G_BEGIN_DECLS + +#define META_TYPE_BARRIER (meta_barrier_get_type ()) +#define META_BARRIER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BARRIER, MetaBarrier)) +#define META_BARRIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_BARRIER, MetaBarrierClass)) +#define META_IS_BARRIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BARRIER)) +#define META_IS_BARRIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_BARRIER)) +#define META_BARRIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_BARRIER, MetaBarrierClass)) + +typedef struct _MetaBarrier MetaBarrier; +typedef struct _MetaBarrierClass MetaBarrierClass; +typedef struct _MetaBarrierPrivate MetaBarrierPrivate; + +struct _MetaBarrier +{ + GObject parent; + + MetaBarrierPrivate *priv; +}; + +struct _MetaBarrierClass +{ + GObjectClass parent_class; +}; + +GType meta_barrier_get_type (void) G_GNUC_CONST; + +gboolean meta_barrier_is_active (MetaBarrier *barrier); +void meta_barrier_destroy (MetaBarrier *barrier); + +/* Keep in sync with XFixes */ +typedef enum { + META_BARRIER_DIRECTION_POSITIVE_X = 1 << 0, + META_BARRIER_DIRECTION_POSITIVE_Y = 1 << 1, + META_BARRIER_DIRECTION_NEGATIVE_X = 1 << 2, + META_BARRIER_DIRECTION_NEGATIVE_Y = 1 << 3, +} MetaBarrierDirection; + +G_END_DECLS + +#endif /* __META_BARRIER_H__ */