From 5f91a62f6f9c9b6a336eb27e6f6254a7a0ecc7bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Fri, 16 Jan 2015 10:30:04 +0800 Subject: [PATCH] barriers: Separate implementation from public API This patch removes the X11 specific code from MetaBarrier and creates an abstraction layer MetaBarrierImpl. The existing X11 implementation is moved to a new GObject MetaBarrierImplX11 implementing the abstract interface MetaBarrierImpl which is instantiated by MetaBarrier when supported. While at it, move it to backends/ and properly name the files. https://bugzilla.gnome.org/show_bug.cgi?id=706655 --- src/Makefile.am | 5 +- src/backends/meta-barrier-private.h | 81 +++++++ .../barrier.c => backends/meta-barrier.c} | 172 ++++---------- src/backends/x11/meta-barrier-x11.c | 216 ++++++++++++++++++ src/backends/x11/meta-barrier-x11.h | 57 +++++ 5 files changed, 406 insertions(+), 125 deletions(-) create mode 100644 src/backends/meta-barrier-private.h rename src/{core/barrier.c => backends/meta-barrier.c} (69%) create mode 100644 src/backends/x11/meta-barrier-x11.c create mode 100644 src/backends/x11/meta-barrier-x11.h diff --git a/src/Makefile.am b/src/Makefile.am index 00ca3d5d7..a967c6093 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -61,6 +61,8 @@ libmutter_la_SOURCES = \ backends/meta-backend.c \ meta/meta-backend.h \ backends/meta-backend-private.h \ + backends/meta-barrier.c \ + backends/meta-barrier-private.h \ backends/meta-cursor.c \ backends/meta-cursor.h \ backends/meta-cursor-private.h \ @@ -85,6 +87,8 @@ libmutter_la_SOURCES = \ backends/edid.h \ backends/x11/meta-backend-x11.c \ backends/x11/meta-backend-x11.h \ + backends/x11/meta-barrier-x11.c \ + backends/x11/meta-barrier-x11.h \ backends/x11/meta-cursor-renderer-x11.c \ backends/x11/meta-cursor-renderer-x11.h \ backends/x11/meta-idle-monitor-xsync.c \ @@ -93,7 +97,6 @@ libmutter_la_SOURCES = \ backends/x11/meta-monitor-manager-xrandr.h \ core/meta-accel-parse.c \ core/meta-accel-parse.h \ - core/barrier.c \ meta/barrier.h \ core/bell.c \ core/bell.h \ diff --git a/src/backends/meta-barrier-private.h b/src/backends/meta-barrier-private.h new file mode 100644 index 000000000..1dbb1cb08 --- /dev/null +++ b/src/backends/meta-barrier-private.h @@ -0,0 +1,81 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* + * Copyright (C) 2014-2015 Red Hat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written by: + * Jasper St. Pierre + * Jonas Ådahl + */ + +#ifndef META_BARRIER_PRIVATE_H +#define META_BARRIER_PRIVATE_H + +G_BEGIN_DECLS + +#define META_TYPE_BARRIER_IMPL (meta_barrier_impl_get_type ()) +#define META_BARRIER_IMPL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BARRIER, MetaBarrierImpl)) +#define META_BARRIER_IMPL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_BARRIER_IMPL, MetaBarrierImplClass)) +#define META_IS_BARRIER_IMPL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BARRIER_IMPL)) +#define META_IS_BARRIER_IMPL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_BARRIER_IMPL)) +#define META_BARRIER_IMPL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_BARRIER_IMPL, MetaBarrierImplClass)) + +typedef struct _MetaBarrierImpl MetaBarrierImpl; +typedef struct _MetaBarrierImplClass MetaBarrierImplClass; + +struct _MetaBarrierImpl +{ + GObject parent; +}; + +struct _MetaBarrierImplClass +{ + GObjectClass parent_class; + + gboolean (*is_active) (MetaBarrierImpl *barrier); + void (*release) (MetaBarrierImpl *barrier, + MetaBarrierEvent *event); + void (*destroy) (MetaBarrierImpl *barrier); +}; + +GType meta_barrier_impl_get_type (void) G_GNUC_CONST; + +void _meta_barrier_emit_hit_signal (MetaBarrier *barrier, + MetaBarrierEvent *event); +void _meta_barrier_emit_left_signal (MetaBarrier *barrier, + MetaBarrierEvent *event); + +void meta_barrier_event_unref (MetaBarrierEvent *event); + +G_END_DECLS + +struct _MetaBarrierPrivate +{ + MetaDisplay *display; + + int x1; + int y1; + int x2; + int y2; + + MetaBarrierDirection directions; + + MetaBarrierImpl *impl; +}; + +#endif /* META_BARRIER_PRIVATE_H */ diff --git a/src/core/barrier.c b/src/backends/meta-barrier.c similarity index 69% rename from src/core/barrier.c rename to src/backends/meta-barrier.c index a0f8950a7..ab4fdbe06 100644 --- a/src/core/barrier.c +++ b/src/backends/meta-barrier.c @@ -10,15 +10,14 @@ #include -#include -#include #include #include -#include "display-private.h" +#include "backends/x11/meta-backend-x11.h" +#include "backends/x11/meta-barrier-x11.h" #include "mutter-enum-types.h" -#include "core.h" G_DEFINE_TYPE (MetaBarrier, meta_barrier, G_TYPE_OBJECT) +G_DEFINE_TYPE (MetaBarrierImpl, meta_barrier_impl, G_TYPE_OBJECT) enum { PROP_0, @@ -45,21 +44,6 @@ enum { static guint obj_signals[LAST_SIGNAL]; -struct _MetaBarrierPrivate -{ - MetaDisplay *display; - - int x1; - int y1; - int x2; - int y2; - - MetaBarrierDirection directions; - - PointerBarrier xbarrier; -}; - -static void meta_barrier_event_unref (MetaBarrierEvent *event); static void meta_barrier_get_property (GObject *object, @@ -133,13 +117,11 @@ 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); + meta_bug ("MetaBarrier %p was destroyed while it was still active.", + barrier); } G_OBJECT_CLASS (meta_barrier_parent_class)->dispose (object); @@ -148,7 +130,12 @@ meta_barrier_dispose (GObject *object) gboolean meta_barrier_is_active (MetaBarrier *barrier) { - return barrier->priv->xbarrier != 0; + MetaBarrierImpl *impl = barrier->priv->impl; + + if (impl) + return META_BARRIER_IMPL_GET_CLASS (impl)->is_active (impl); + else + return FALSE; } /** @@ -165,15 +152,10 @@ void meta_barrier_release (MetaBarrier *barrier, MetaBarrierEvent *event) { -#ifdef HAVE_XI23 - MetaBarrierPrivate *priv = barrier->priv; - if (META_DISPLAY_HAS_XINPUT_23 (priv->display)) - { - XIBarrierReleasePointer (priv->display->xdisplay, - META_VIRTUAL_CORE_POINTER_ID, - priv->xbarrier, event->event_id); - } -#endif /* HAVE_XI23 */ + MetaBarrierImpl *impl = barrier->priv->impl; + + if (impl) + META_BARRIER_IMPL_GET_CLASS (impl)->release (impl, event); } static void @@ -181,31 +163,22 @@ 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; - } +#if defined(HAVE_XI23) + if (META_IS_BACKEND_X11 (meta_get_backend ()) && + !meta_is_wayland_compositor ()) + priv->impl = meta_barrier_impl_x11_new (barrier); +#endif - dpy = priv->display->xdisplay; - root = DefaultRootWindow (dpy); + if (priv->impl == NULL) + g_warning ("Created a non-working barrier"); - priv->xbarrier = XFixesCreatePointerBarrier (dpy, root, - priv->x1, priv->y1, - priv->x2, priv->y2, - priv->directions, 0, NULL); - - /* Take a ref that we'll release when the XID dies inside destroy(), - * so that the object stays alive and doesn't get GC'd. */ + /* Take a ref that we'll release in destroy() so that the object stays + * alive while active. */ g_object_ref (barrier); - g_hash_table_insert (priv->display->xids, &priv->xbarrier, barrier); - G_OBJECT_CLASS (meta_barrier_parent_class)->constructed (object); } @@ -306,20 +279,10 @@ meta_barrier_class_init (MetaBarrierClass *klass) void meta_barrier_destroy (MetaBarrier *barrier) { - MetaBarrierPrivate *priv = barrier->priv; - Display *dpy; + MetaBarrierImpl *impl = barrier->priv->impl; - if (priv->display == NULL) - return; - - dpy = priv->display->xdisplay; - - if (!meta_barrier_is_active (barrier)) - return; - - XFixesDestroyPointerBarrier (dpy, priv->xbarrier); - g_hash_table_remove (priv->display->xids, &priv->xbarrier); - priv->xbarrier = 0; + if (impl) + return META_BARRIER_IMPL_GET_CLASS (impl)->destroy (impl); g_object_unref (barrier); } @@ -330,71 +293,32 @@ meta_barrier_init (MetaBarrier *barrier) barrier->priv = G_TYPE_INSTANCE_GET_PRIVATE (barrier, META_TYPE_BARRIER, MetaBarrierPrivate); } -#ifdef HAVE_XI23 +void +_meta_barrier_emit_hit_signal (MetaBarrier *barrier, + MetaBarrierEvent *event) +{ + g_signal_emit (barrier, obj_signals[HIT], 0, event); +} + +void +_meta_barrier_emit_left_signal (MetaBarrier *barrier, + MetaBarrierEvent *event) +{ + g_signal_emit (barrier, obj_signals[LEFT], 0, event); +} + static void -meta_barrier_fire_event (MetaBarrier *barrier, - XIBarrierEvent *xevent) +meta_barrier_impl_class_init (MetaBarrierImplClass *klass) { - MetaBarrierEvent *event = g_slice_new0 (MetaBarrierEvent); - - event->ref_count = 1; - event->event_id = xevent->eventid; - event->time = xevent->time; - event->dt = xevent->dtime; - - event->x = xevent->root_x; - event->y = xevent->root_y; - event->dx = xevent->dx; - event->dy = xevent->dy; - - event->released = (xevent->flags & XIBarrierPointerReleased) != 0; - event->grabbed = (xevent->flags & XIBarrierDeviceIsGrabbed) != 0; - - 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 (); - } - - meta_barrier_event_unref (event); + klass->is_active = NULL; + klass->release = NULL; + klass->destroy = NULL; } -gboolean -meta_display_process_barrier_xevent (MetaDisplay *display, - XIEvent *event) +static void +meta_barrier_impl_init (MetaBarrierImpl *impl) { - MetaBarrier *barrier; - XIBarrierEvent *xev; - - if (event == NULL) - return FALSE; - - switch (event->evtype) - { - case XI_BarrierHit: - case XI_BarrierLeave: - break; - default: - return FALSE; - } - - xev = (XIBarrierEvent *) event; - barrier = g_hash_table_lookup (display->xids, &xev->barrier); - if (barrier != NULL) - { - meta_barrier_fire_event (barrier, xev); - return TRUE; - } - - return FALSE; } -#endif /* HAVE_XI23 */ static MetaBarrierEvent * meta_barrier_event_ref (MetaBarrierEvent *event) @@ -406,7 +330,7 @@ meta_barrier_event_ref (MetaBarrierEvent *event) return event; } -static void +void meta_barrier_event_unref (MetaBarrierEvent *event) { g_return_if_fail (event != NULL); diff --git a/src/backends/x11/meta-barrier-x11.c b/src/backends/x11/meta-barrier-x11.c new file mode 100644 index 000000000..1a813c43d --- /dev/null +++ b/src/backends/x11/meta-barrier-x11.c @@ -0,0 +1,216 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* + * Copyright (C) 2014-2015 Red Hat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written by: + * Jasper St. Pierre + * Jonas Ådahl + */ + +/** + * SECTION:barrier-x11 + * @Title: MetaBarrierImplX11 + * @Short_Description: Pointer barriers implementation for X11 + */ + +#include "config.h" + +#ifdef HAVE_XI23 + +#include + +#include +#include +#include +#include "backends/x11/meta-barrier-x11.h" +#include "display-private.h" + +struct _MetaBarrierImplX11Private +{ + MetaBarrier *barrier; + PointerBarrier xbarrier; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (MetaBarrierImplX11, meta_barrier_impl_x11, + META_TYPE_BARRIER_IMPL) + +static gboolean +_meta_barrier_impl_x11_is_active (MetaBarrierImpl *impl) +{ + MetaBarrierImplX11 *self = META_BARRIER_IMPL_X11 (impl); + MetaBarrierImplX11Private *priv = + meta_barrier_impl_x11_get_instance_private (self); + + return priv->xbarrier != 0; +} + +static void +_meta_barrier_impl_x11_release (MetaBarrierImpl *impl, + MetaBarrierEvent *event) +{ + MetaBarrierImplX11 *self = META_BARRIER_IMPL_X11 (impl); + MetaBarrierImplX11Private *priv = + meta_barrier_impl_x11_get_instance_private (self); + MetaDisplay *display = priv->barrier->priv->display; + + if (META_DISPLAY_HAS_XINPUT_23 (display)) + { + XIBarrierReleasePointer (display->xdisplay, + META_VIRTUAL_CORE_POINTER_ID, + priv->xbarrier, event->event_id); + } +} + +static void +_meta_barrier_impl_x11_destroy (MetaBarrierImpl *impl) +{ + MetaBarrierImplX11 *self = META_BARRIER_IMPL_X11 (impl); + MetaBarrierImplX11Private *priv = + meta_barrier_impl_x11_get_instance_private (self); + MetaDisplay *display = priv->barrier->priv->display; + Display *dpy; + + if (display == NULL) + return; + + dpy = display->xdisplay; + + if (!meta_barrier_is_active (priv->barrier)) + return; + + XFixesDestroyPointerBarrier (dpy, priv->xbarrier); + g_hash_table_remove (display->xids, &priv->xbarrier); + priv->xbarrier = 0; +} + +MetaBarrierImpl * +meta_barrier_impl_x11_new (MetaBarrier *barrier) +{ + MetaBarrierImplX11 *self; + MetaBarrierImplX11Private *priv; + MetaDisplay *display = barrier->priv->display; + Display *dpy; + Window root; + + if (display == NULL) + { + g_warning ("A display must be provided when constructing a barrier."); + return NULL; + } + + self = g_object_new (META_TYPE_BARRIER_IMPL_X11, NULL); + priv = meta_barrier_impl_x11_get_instance_private (self); + priv->barrier = barrier; + + dpy = display->xdisplay; + root = DefaultRootWindow (dpy); + + priv->xbarrier = XFixesCreatePointerBarrier (dpy, root, + barrier->priv->x1, + barrier->priv->y1, + barrier->priv->x2, + barrier->priv->y2, + barrier->priv->directions, + 0, NULL); + + g_hash_table_insert (display->xids, &priv->xbarrier, barrier); + + return META_BARRIER_IMPL (self); +} + +static void +meta_barrier_fire_xevent (MetaBarrier *barrier, + XIBarrierEvent *xevent) +{ + MetaBarrierEvent *event = g_slice_new0 (MetaBarrierEvent); + + event->ref_count = 1; + event->event_id = xevent->eventid; + event->time = xevent->time; + event->dt = xevent->dtime; + + event->x = xevent->root_x; + event->y = xevent->root_y; + event->dx = xevent->dx; + event->dy = xevent->dy; + + event->released = (xevent->flags & XIBarrierPointerReleased) != 0; + event->grabbed = (xevent->flags & XIBarrierDeviceIsGrabbed) != 0; + + switch (xevent->evtype) + { + case XI_BarrierHit: + _meta_barrier_emit_hit_signal (barrier, event); + break; + case XI_BarrierLeave: + _meta_barrier_emit_left_signal (barrier, event); + break; + default: + g_assert_not_reached (); + } + + meta_barrier_event_unref (event); +} + +gboolean +meta_display_process_barrier_xevent (MetaDisplay *display, + XIEvent *event) +{ + MetaBarrier *barrier; + XIBarrierEvent *xev; + + if (event == NULL) + return FALSE; + + switch (event->evtype) + { + case XI_BarrierHit: + case XI_BarrierLeave: + break; + default: + return FALSE; + } + + xev = (XIBarrierEvent *) event; + barrier = g_hash_table_lookup (display->xids, &xev->barrier); + if (barrier != NULL) + { + meta_barrier_fire_xevent (barrier, xev); + return TRUE; + } + + return FALSE; +} + +static void +meta_barrier_impl_x11_class_init (MetaBarrierImplX11Class *klass) +{ + MetaBarrierImplClass *impl_class = META_BARRIER_IMPL_CLASS (klass); + + impl_class->is_active = _meta_barrier_impl_x11_is_active; + impl_class->release = _meta_barrier_impl_x11_release; + impl_class->destroy = _meta_barrier_impl_x11_destroy; +} + +static void +meta_barrier_impl_x11_init (MetaBarrierImplX11 *self) +{ +} + +#endif /* HAVE_XI23 */ diff --git a/src/backends/x11/meta-barrier-x11.h b/src/backends/x11/meta-barrier-x11.h new file mode 100644 index 000000000..802494c1f --- /dev/null +++ b/src/backends/x11/meta-barrier-x11.h @@ -0,0 +1,57 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* + * Copyright (C) 2015 Red Hat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written by: + * Jonas Ådahl + */ + +#ifndef META_BARRIER_X11_H +#define META_BARRIER_X11_H + +#include "backends/meta-barrier-private.h" + +G_BEGIN_DECLS + +#define META_TYPE_BARRIER_IMPL_X11 (meta_barrier_impl_x11_get_type ()) +#define META_BARRIER_IMPL_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BARRIER, MetaBarrierImplX11)) +#define META_BARRIER_IMPL_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_BARRIER_IMPL_X11, MetaBarrierImplX11Class)) +#define META_IS_BARRIER_IMPL_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BARRIER_IMPL_X11)) +#define META_IS_BARRIER_IMPL_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_BARRIER_IMPL_X11)) +#define META_BARRIER_IMPL_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_BARRIER_IMPL_X11, MetaBarrierImplX11Class)) + +typedef struct _MetaBarrierImplX11 MetaBarrierImplX11; +typedef struct _MetaBarrierImplX11Class MetaBarrierImplX11Class; +typedef struct _MetaBarrierImplX11Private MetaBarrierImplX11Private; + +struct _MetaBarrierImplX11 +{ + MetaBarrierImpl parent; +}; + +struct _MetaBarrierImplX11Class +{ + MetaBarrierImplClass parent_class; +}; + +MetaBarrierImpl *meta_barrier_impl_x11_new (MetaBarrier *barrier); + +G_END_DECLS + +#endif /* META_BARRIER_X11_H1 */