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
This commit is contained in:
Jonas Ådahl 2015-01-16 10:30:04 +08:00 committed by Jasper St. Pierre
parent 152b2dab59
commit 5f91a62f6f
5 changed files with 406 additions and 125 deletions

View File

@ -61,6 +61,8 @@ libmutter_la_SOURCES = \
backends/meta-backend.c \ backends/meta-backend.c \
meta/meta-backend.h \ meta/meta-backend.h \
backends/meta-backend-private.h \ backends/meta-backend-private.h \
backends/meta-barrier.c \
backends/meta-barrier-private.h \
backends/meta-cursor.c \ backends/meta-cursor.c \
backends/meta-cursor.h \ backends/meta-cursor.h \
backends/meta-cursor-private.h \ backends/meta-cursor-private.h \
@ -85,6 +87,8 @@ libmutter_la_SOURCES = \
backends/edid.h \ backends/edid.h \
backends/x11/meta-backend-x11.c \ backends/x11/meta-backend-x11.c \
backends/x11/meta-backend-x11.h \ 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.c \
backends/x11/meta-cursor-renderer-x11.h \ backends/x11/meta-cursor-renderer-x11.h \
backends/x11/meta-idle-monitor-xsync.c \ backends/x11/meta-idle-monitor-xsync.c \
@ -93,7 +97,6 @@ libmutter_la_SOURCES = \
backends/x11/meta-monitor-manager-xrandr.h \ backends/x11/meta-monitor-manager-xrandr.h \
core/meta-accel-parse.c \ core/meta-accel-parse.c \
core/meta-accel-parse.h \ core/meta-accel-parse.h \
core/barrier.c \
meta/barrier.h \ meta/barrier.h \
core/bell.c \ core/bell.c \
core/bell.h \ core/bell.h \

View File

@ -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 <jstpierre@mecheye.net>
* Jonas Ådahl <jadahl@gmail.com>
*/
#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 */

View File

@ -10,15 +10,14 @@
#include <glib-object.h> #include <glib-object.h>
#include <X11/extensions/XInput2.h>
#include <X11/extensions/Xfixes.h>
#include <meta/util.h> #include <meta/util.h>
#include <meta/barrier.h> #include <meta/barrier.h>
#include "display-private.h" #include "backends/x11/meta-backend-x11.h"
#include "backends/x11/meta-barrier-x11.h"
#include "mutter-enum-types.h" #include "mutter-enum-types.h"
#include "core.h"
G_DEFINE_TYPE (MetaBarrier, meta_barrier, G_TYPE_OBJECT) G_DEFINE_TYPE (MetaBarrier, meta_barrier, G_TYPE_OBJECT)
G_DEFINE_TYPE (MetaBarrierImpl, meta_barrier_impl, G_TYPE_OBJECT)
enum { enum {
PROP_0, PROP_0,
@ -45,21 +44,6 @@ enum {
static guint obj_signals[LAST_SIGNAL]; 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 static void
meta_barrier_get_property (GObject *object, meta_barrier_get_property (GObject *object,
@ -133,13 +117,11 @@ static void
meta_barrier_dispose (GObject *object) meta_barrier_dispose (GObject *object)
{ {
MetaBarrier *barrier = META_BARRIER (object); MetaBarrier *barrier = META_BARRIER (object);
MetaBarrierPrivate *priv = barrier->priv;
if (meta_barrier_is_active (barrier)) if (meta_barrier_is_active (barrier))
{ {
meta_bug ("MetaBarrier wrapper %p for X barrier %ld was destroyed" meta_bug ("MetaBarrier %p was destroyed while it was still active.",
" while the X barrier is still active.", barrier);
barrier, priv->xbarrier);
} }
G_OBJECT_CLASS (meta_barrier_parent_class)->dispose (object); G_OBJECT_CLASS (meta_barrier_parent_class)->dispose (object);
@ -148,7 +130,12 @@ meta_barrier_dispose (GObject *object)
gboolean gboolean
meta_barrier_is_active (MetaBarrier *barrier) 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, meta_barrier_release (MetaBarrier *barrier,
MetaBarrierEvent *event) MetaBarrierEvent *event)
{ {
#ifdef HAVE_XI23 MetaBarrierImpl *impl = barrier->priv->impl;
MetaBarrierPrivate *priv = barrier->priv;
if (META_DISPLAY_HAS_XINPUT_23 (priv->display)) if (impl)
{ META_BARRIER_IMPL_GET_CLASS (impl)->release (impl, event);
XIBarrierReleasePointer (priv->display->xdisplay,
META_VIRTUAL_CORE_POINTER_ID,
priv->xbarrier, event->event_id);
}
#endif /* HAVE_XI23 */
} }
static void static void
@ -181,31 +163,22 @@ meta_barrier_constructed (GObject *object)
{ {
MetaBarrier *barrier = META_BARRIER (object); MetaBarrier *barrier = META_BARRIER (object);
MetaBarrierPrivate *priv = barrier->priv; MetaBarrierPrivate *priv = barrier->priv;
Display *dpy;
Window root;
g_return_if_fail (priv->x1 == priv->x2 || priv->y1 == priv->y2); g_return_if_fail (priv->x1 == priv->x2 || priv->y1 == priv->y2);
if (priv->display == NULL) #if defined(HAVE_XI23)
{ if (META_IS_BACKEND_X11 (meta_get_backend ()) &&
g_warning ("A display must be provided when constructing a barrier."); !meta_is_wayland_compositor ())
return; priv->impl = meta_barrier_impl_x11_new (barrier);
} #endif
dpy = priv->display->xdisplay; if (priv->impl == NULL)
root = DefaultRootWindow (dpy); g_warning ("Created a non-working barrier");
priv->xbarrier = XFixesCreatePointerBarrier (dpy, root, /* Take a ref that we'll release in destroy() so that the object stays
priv->x1, priv->y1, * alive while active. */
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. */
g_object_ref (barrier); g_object_ref (barrier);
g_hash_table_insert (priv->display->xids, &priv->xbarrier, barrier);
G_OBJECT_CLASS (meta_barrier_parent_class)->constructed (object); G_OBJECT_CLASS (meta_barrier_parent_class)->constructed (object);
} }
@ -306,20 +279,10 @@ meta_barrier_class_init (MetaBarrierClass *klass)
void void
meta_barrier_destroy (MetaBarrier *barrier) meta_barrier_destroy (MetaBarrier *barrier)
{ {
MetaBarrierPrivate *priv = barrier->priv; MetaBarrierImpl *impl = barrier->priv->impl;
Display *dpy;
if (priv->display == NULL) if (impl)
return; return META_BARRIER_IMPL_GET_CLASS (impl)->destroy (impl);
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;
g_object_unref (barrier); g_object_unref (barrier);
} }
@ -330,72 +293,33 @@ meta_barrier_init (MetaBarrier *barrier)
barrier->priv = G_TYPE_INSTANCE_GET_PRIVATE (barrier, META_TYPE_BARRIER, MetaBarrierPrivate); barrier->priv = G_TYPE_INSTANCE_GET_PRIVATE (barrier, META_TYPE_BARRIER, MetaBarrierPrivate);
} }
#ifdef HAVE_XI23 void
static void _meta_barrier_emit_hit_signal (MetaBarrier *barrier,
meta_barrier_fire_event (MetaBarrier *barrier, MetaBarrierEvent *event)
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:
g_signal_emit (barrier, obj_signals[HIT], 0, event); g_signal_emit (barrier, obj_signals[HIT], 0, event);
break; }
case XI_BarrierLeave:
void
_meta_barrier_emit_left_signal (MetaBarrier *barrier,
MetaBarrierEvent *event)
{
g_signal_emit (barrier, obj_signals[LEFT], 0, event); g_signal_emit (barrier, obj_signals[LEFT], 0, event);
break;
default:
g_assert_not_reached ();
} }
meta_barrier_event_unref (event); static void
} meta_barrier_impl_class_init (MetaBarrierImplClass *klass)
gboolean
meta_display_process_barrier_xevent (MetaDisplay *display,
XIEvent *event)
{ {
MetaBarrier *barrier; klass->is_active = NULL;
XIBarrierEvent *xev; klass->release = NULL;
klass->destroy = NULL;
}
if (event == NULL) static void
return FALSE; meta_barrier_impl_init (MetaBarrierImpl *impl)
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 * static MetaBarrierEvent *
meta_barrier_event_ref (MetaBarrierEvent *event) meta_barrier_event_ref (MetaBarrierEvent *event)
{ {
@ -406,7 +330,7 @@ meta_barrier_event_ref (MetaBarrierEvent *event)
return event; return event;
} }
static void void
meta_barrier_event_unref (MetaBarrierEvent *event) meta_barrier_event_unref (MetaBarrierEvent *event)
{ {
g_return_if_fail (event != NULL); g_return_if_fail (event != NULL);

View File

@ -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 <jstpierre@mecheye.net>
* Jonas Ådahl <jadahl@gmail.com>
*/
/**
* SECTION:barrier-x11
* @Title: MetaBarrierImplX11
* @Short_Description: Pointer barriers implementation for X11
*/
#include "config.h"
#ifdef HAVE_XI23
#include <glib-object.h>
#include <X11/extensions/XInput2.h>
#include <X11/extensions/Xfixes.h>
#include <meta/barrier.h>
#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 */

View File

@ -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 <jadahl@gmail.com>
*/
#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 */