backend: Poll events from the host X11 server ourselves

I was accidentally pulling events from the Xwayland server under
nested for the idle monitor, which is wrong. Whoops.
This commit is contained in:
Jasper St. Pierre 2014-04-22 10:14:59 -04:00
parent 3c0ca1f2af
commit 3d091e514d
4 changed files with 157 additions and 39 deletions

View File

@ -49,6 +49,8 @@ struct _MetaBackendClass
{
GObjectClass parent_class;
void (* post_init) (MetaBackend *backend);
MetaIdleMonitor * (* create_idle_monitor) (MetaBackend *backend,
int device_id);
MetaMonitorManager * (* create_monitor_manager) (MetaBackend *backend);

View File

@ -77,6 +77,12 @@ meta_backend_finalize (GObject *object)
G_OBJECT_CLASS (meta_backend_parent_class)->finalize (object);
}
static void
meta_backend_real_post_init (MetaBackend *backend)
{
/* Do nothing */
}
static void
meta_backend_class_init (MetaBackendClass *klass)
{
@ -84,6 +90,8 @@ meta_backend_class_init (MetaBackendClass *klass)
object_class->constructed = meta_backend_constructed;
object_class->finalize = meta_backend_finalize;
klass->post_init = meta_backend_real_post_init;
}
static void
@ -109,6 +117,12 @@ meta_backend_create_idle_monitor (MetaBackend *backend,
return META_BACKEND_GET_CLASS (backend)->create_idle_monitor (backend, device_id);
}
static void
meta_backend_post_init (MetaBackend *backend)
{
META_BACKEND_GET_CLASS (backend)->post_init (backend);
}
MetaIdleMonitor *
meta_backend_get_idle_monitor (MetaBackend *backend,
int device_id)
@ -217,4 +231,6 @@ meta_clutter_init (void)
source = g_source_new (&event_funcs, sizeof (GSource));
g_source_attach (source, NULL);
g_source_unref (source);
meta_backend_post_init (_backend);
}

View File

@ -26,15 +26,149 @@
#include "meta-backend-x11.h"
#include <gdk/gdkx.h>
#include <clutter/x11/clutter-x11.h>
#include <X11/extensions/sync.h>
#include <meta/util.h>
#include "meta-idle-monitor-xsync.h"
#include "meta-monitor-manager-xrandr.h"
#include "backends/meta-monitor-manager-dummy.h"
G_DEFINE_TYPE (MetaBackendX11, meta_backend_x11, META_TYPE_BACKEND);
struct _MetaBackendX11Private
{
/* The host X11 display */
Display *xdisplay;
GSource *source;
int xsync_event_base;
int xsync_error_base;
};
typedef struct _MetaBackendX11Private MetaBackendX11Private;
G_DEFINE_TYPE_WITH_PRIVATE (MetaBackendX11, meta_backend_x11, META_TYPE_BACKEND);
static void
handle_alarm_notify (MetaBackend *backend,
XEvent *xevent)
{
int i;
for (i = 0; i <= backend->device_id_max; i++)
if (backend->device_monitors[i])
meta_idle_monitor_xsync_handle_xevent (backend->device_monitors[i], (XSyncAlarmNotifyEvent*)xevent);
}
static void
handle_host_xevent (MetaBackend *backend,
XEvent *xevent)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
if (xevent->type == (priv->xsync_event_base + XSyncAlarmNotify))
handle_alarm_notify (backend, xevent);
clutter_x11_handle_event (xevent);
}
typedef struct {
GSource base;
GPollFD event_poll_fd;
MetaBackend *backend;
} XEventSource;
static gboolean
x_event_source_prepare (GSource *source,
int *timeout)
{
XEventSource *x_source = (XEventSource *) source;
MetaBackend *backend = x_source->backend;
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
*timeout = -1;
return XPending (priv->xdisplay);
}
static gboolean
x_event_source_check (GSource *source)
{
XEventSource *x_source = (XEventSource *) source;
MetaBackend *backend = x_source->backend;
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
return XPending (priv->xdisplay);
}
static gboolean
x_event_source_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
XEventSource *x_source = (XEventSource *) source;
MetaBackend *backend = x_source->backend;
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
while (XPending (priv->xdisplay))
{
XEvent xev;
XNextEvent (priv->xdisplay, &xev);
handle_host_xevent (backend, &xev);
}
return TRUE;
}
static GSourceFuncs x_event_funcs = {
x_event_source_prepare,
x_event_source_check,
x_event_source_dispatch,
};
static GSource *
x_event_source_new (MetaBackend *backend)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
GSource *source;
XEventSource *x_source;
source = g_source_new (&x_event_funcs, sizeof (XEventSource));
x_source = (XEventSource *) source;
x_source->backend = backend;
x_source->event_poll_fd.fd = ConnectionNumber (priv->xdisplay);
x_source->event_poll_fd.events = G_IO_IN;
g_source_add_poll (source, &x_source->event_poll_fd);
g_source_attach (source, NULL);
return source;
}
static void
meta_backend_x11_post_init (MetaBackend *backend)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
int major, minor;
priv->xdisplay = clutter_x11_get_default_display ();
priv->source = x_event_source_new (backend);
if (!XSyncQueryExtension (priv->xdisplay, &priv->xsync_event_base, &priv->xsync_error_base))
meta_fatal ("Could not initialize XSync");
if (!XSyncInitialize (priv->xdisplay, &major, &minor))
meta_fatal ("Could not initialize XSync");
META_BACKEND_CLASS (meta_backend_x11_parent_class)->post_init (backend);
}
static MetaIdleMonitor *
meta_backend_x11_create_idle_monitor (MetaBackend *backend,
@ -62,6 +196,7 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
{
MetaBackendClass *backend_class = META_BACKEND_CLASS (klass);
backend_class->post_init = meta_backend_x11_post_init;
backend_class->create_idle_monitor = meta_backend_x11_create_idle_monitor;
backend_class->create_monitor_manager = meta_backend_x11_create_monitor_manager;
}
@ -69,35 +204,6 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
static void
meta_backend_x11_init (MetaBackendX11 *x11)
{
/* When running as an X11 compositor, we install our own event filter and
* pass events to Clutter explicitly, so we need to prevent Clutter from
* handling our events.
*
* However, when running as a Wayland compostior under X11 nested, Clutter
* Clutter needs to see events related to its own window. We need to
* eventually replace this with a proper frontend / backend split: Clutter
* under nested is connecting to the "host X server" to get its events it
* needs to put up a window, and GTK+ is connecting to the "inner X server".
* The two would the same in the X11 compositor case, but not when running
* XWayland as a Wayland compositor.
*/
if (!meta_is_wayland_compositor ())
{
clutter_x11_set_display (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
clutter_x11_disable_event_retrieval ();
}
}
void
meta_backend_x11_handle_alarm_notify (MetaBackend *backend,
XEvent *xevent)
{
int i;
if (!META_IS_BACKEND_X11 (backend))
return;
for (i = 0; i <= backend->device_id_max; i++)
if (backend->device_monitors[i])
meta_idle_monitor_xsync_handle_xevent (backend->device_monitors[i], (XSyncAlarmNotifyEvent*)xevent);
/* We do X11 event retrieval ourselves */
clutter_x11_disable_event_retrieval ();
}

View File

@ -35,7 +35,6 @@
#include "bell.h"
#include "workspace-private.h"
#include "backends/meta-backend.h"
#include "backends/x11/meta-backend-x11.h"
#include "backends/native/meta-idle-monitor-native.h"
#include "x11/window-x11.h"
@ -1264,11 +1263,6 @@ handle_other_xevent (MetaDisplay *display,
meta_window_update_sync_request_counter (alarm_window, new_counter_value);
bypass_gtk = TRUE; /* GTK doesn't want to see this really */
}
else
{
MetaBackend *backend = meta_get_backend ();
meta_backend_x11_handle_alarm_notify (backend, event);
}
goto out;
}