backends/x11: Split up X11 backend into Cm and Nested

Split up the X11 backend into two parts, one for running as a
Compositing Manager, and one for running as a nested Wayland
compositor.

This commit also cleans up the compositor configuration calculation,
attempting to make it more approachable.

https://bugzilla.gnome.org/show_bug.cgi?id=777800
This commit is contained in:
Jonas Ådahl 2017-01-27 23:04:02 +08:00
parent 042a95ef98
commit 6d64123849
8 changed files with 512 additions and 221 deletions

View File

@ -135,6 +135,10 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES = \
backends/x11/meta-clutter-backend-x11.h \
backends/x11/meta-cursor-renderer-x11.c \
backends/x11/meta-cursor-renderer-x11.h \
backends/x11/cm/meta-backend-x11-cm.c \
backends/x11/cm/meta-backend-x11-cm.h \
backends/x11/nested/meta-backend-x11-nested.c \
backends/x11/nested/meta-backend-x11-nested.h \
backends/x11/nested/meta-cursor-renderer-x11-nested.c \
backends/x11/nested/meta-cursor-renderer-x11-nested.h \
backends/x11/meta-idle-monitor-xsync.c \

View File

@ -0,0 +1,177 @@
/*
* Copyright (C) 2017 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.
*/
#include "config.h"
#include "backends/x11/cm/meta-backend-x11-cm.h"
#include "backends/meta-backend-private.h"
#include "backends/x11/meta-cursor-renderer-x11.h"
#include "backends/x11/meta-monitor-manager-xrandr.h"
struct _MetaBackendX11Cm
{
MetaBackendX11 parent;
};
G_DEFINE_TYPE (MetaBackendX11Cm, meta_backend_x11_cm, META_TYPE_BACKEND_X11)
static void
take_touch_grab (MetaBackend *backend)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
Display *xdisplay = meta_backend_x11_get_xdisplay (x11);
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { META_VIRTUAL_CORE_POINTER_ID, sizeof (mask_bits), mask_bits };
XIGrabModifiers mods = { XIAnyModifier, 0 };
XISetMask (mask.mask, XI_TouchBegin);
XISetMask (mask.mask, XI_TouchUpdate);
XISetMask (mask.mask, XI_TouchEnd);
XIGrabTouchBegin (xdisplay, META_VIRTUAL_CORE_POINTER_ID,
DefaultRootWindow (xdisplay),
False, &mask, 1, &mods);
}
static void
meta_backend_x11_cm_post_init (MetaBackend *backend)
{
MetaBackendClass *parent_backend_class =
META_BACKEND_CLASS (meta_backend_x11_cm_parent_class);
parent_backend_class->post_init (backend);
take_touch_grab (backend);
}
static MetaMonitorManager *
meta_backend_x11_cm_create_monitor_manager (MetaBackend *backend)
{
return g_object_new (META_TYPE_MONITOR_MANAGER_XRANDR, NULL);
}
static MetaCursorRenderer *
meta_backend_x11_cm_create_cursor_renderer (MetaBackend *backend)
{
return g_object_new (META_TYPE_CURSOR_RENDERER_X11, NULL);
}
static void
meta_backend_x11_cm_update_screen_size (MetaBackend *backend,
int width,
int height)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
Display *xdisplay = meta_backend_x11_get_xdisplay (x11);
Window xwin = meta_backend_x11_get_xwindow (x11);
XResizeWindow (xdisplay, xwin, width, height);
}
static void
meta_backend_x11_cm_select_stage_events (MetaBackend *backend)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
Display *xdisplay = meta_backend_x11_get_xdisplay (x11);
Window xwin = meta_backend_x11_get_xwindow (x11);
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
XISetMask (mask.mask, XI_KeyPress);
XISetMask (mask.mask, XI_KeyRelease);
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Enter);
XISetMask (mask.mask, XI_Leave);
XISetMask (mask.mask, XI_FocusIn);
XISetMask (mask.mask, XI_FocusOut);
XISetMask (mask.mask, XI_Motion);
XISelectEvents (xdisplay, xwin, &mask, 1);
}
static gboolean
meta_backend_x11_cm_handle_host_xevent (MetaBackendX11 *backend_x11,
XEvent *event)
{
MetaBackend *backend = META_BACKEND (backend_x11);
MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend);
MetaMonitorManagerXrandr *monitor_manager_xrandr =
META_MONITOR_MANAGER_XRANDR (monitor_manager);
return meta_monitor_manager_xrandr_handle_xevent (monitor_manager_xrandr,
event);
}
static void
meta_backend_x11_cm_translate_device_event (MetaBackendX11 *x11,
XIDeviceEvent *device_event)
{
Window stage_window = meta_backend_x11_get_xwindow (x11);
if (device_event->event != stage_window)
{
device_event->event = stage_window;
/* As an X11 compositor, the stage window is always at 0,0, so
* using root coordinates will give us correct stage coordinates
* as well... */
device_event->event_x = device_event->root_x;
device_event->event_y = device_event->root_y;
}
}
static void
meta_backend_x11_cm_translate_crossing_event (MetaBackendX11 *x11,
XIEnterEvent *enter_event)
{
Window stage_window = meta_backend_x11_get_xwindow (x11);
if (enter_event->event != stage_window)
{
enter_event->event = stage_window;
enter_event->event_x = enter_event->root_x;
enter_event->event_y = enter_event->root_y;
}
}
static void
meta_backend_x11_cm_init (MetaBackendX11Cm *backend_x11_cm)
{
}
static void
meta_backend_x11_cm_class_init (MetaBackendX11CmClass *klass)
{
MetaBackendClass *backend_class = META_BACKEND_CLASS (klass);
MetaBackendX11Class *backend_x11_class = META_BACKEND_X11_CLASS (klass);
backend_class->post_init = meta_backend_x11_cm_post_init;
backend_class->create_monitor_manager = meta_backend_x11_cm_create_monitor_manager;
backend_class->create_cursor_renderer = meta_backend_x11_cm_create_cursor_renderer;
backend_class->update_screen_size = meta_backend_x11_cm_update_screen_size;
backend_class->select_stage_events = meta_backend_x11_cm_select_stage_events;
backend_x11_class->handle_host_xevent = meta_backend_x11_cm_handle_host_xevent;
backend_x11_class->translate_device_event = meta_backend_x11_cm_translate_device_event;
backend_x11_class->translate_crossing_event = meta_backend_x11_cm_translate_crossing_event;
}

View File

@ -0,0 +1,31 @@
/*
* Copyright (C) 2017 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.
*/
#ifndef META_BACKEND_X11_CM_H
#define META_BACKEND_X11_CM_H
#include <glib-object.h>
#include "backends/x11/meta-backend-x11.h"
#define META_TYPE_BACKEND_X11_CM (meta_backend_x11_cm_get_type ())
G_DECLARE_FINAL_TYPE (MetaBackendX11Cm, meta_backend_x11_cm,
META, BACKEND_X11_CM, MetaBackendX11)
#endif /* META_BACKEND_X11_CM_H */

View File

@ -39,30 +39,15 @@
#include <xkbcommon/xkbcommon-x11.h>
#include "meta-idle-monitor-xsync.h"
#include "meta-monitor-manager-xrandr.h"
#include "backends/meta-monitor-manager-dummy.h"
#include "backends/meta-stage.h"
#include "backends/x11/nested/meta-cursor-renderer-x11-nested.h"
#include "backends/x11/meta-clutter-backend-x11.h"
#include "backends/x11/meta-renderer-x11.h"
#include "meta/meta-cursor-tracker.h"
#include "meta-cursor-renderer-x11.h"
#ifdef HAVE_WAYLAND
#include "wayland/meta-wayland.h"
#endif
#include <meta/util.h>
#include "display-private.h"
#include "compositor/compositor-private.h"
typedef enum {
/* We're a traditional CM running under the host. */
META_BACKEND_X11_MODE_COMPOSITOR,
/* We're a nested X11 client */
META_BACKEND_X11_MODE_NESTED,
} MetaBackendX11Mode;
struct _MetaBackendX11Private
{
/* The host X11 display */
@ -70,8 +55,6 @@ struct _MetaBackendX11Private
xcb_connection_t *xcb;
GSource *source;
MetaBackendX11Mode mode;
int xsync_event_base;
int xsync_error_base;
@ -106,28 +89,23 @@ handle_alarm_notify (MetaBackend *backend,
event);
}
static void
meta_backend_x11_translate_device_event (MetaBackendX11 *x11,
XIDeviceEvent *device_event)
{
MetaBackendX11Class *backend_x11_class =
META_BACKEND_X11_GET_CLASS (x11);
backend_x11_class->translate_device_event (x11, device_event);
}
static void
translate_device_event (MetaBackendX11 *x11,
XIDeviceEvent *device_event)
{
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
Window stage_window = meta_backend_x11_get_xwindow (x11);
if (device_event->event != stage_window)
{
/* This codepath should only ever trigger as an X11 compositor,
* and never under nested, as under nested all backend events
* should be reported with respect to the stage window. */
g_assert (priv->mode == META_BACKEND_X11_MODE_COMPOSITOR);
device_event->event = stage_window;
/* As an X11 compositor, the stage window is always at 0,0, so
* using root coordinates will give us correct stage coordinates
* as well... */
device_event->event_x = device_event->root_x;
device_event->event_y = device_event->root_y;
}
meta_backend_x11_translate_device_event (x11, device_event);
if (!device_event->send_event && device_event->time != CurrentTime)
{
@ -145,12 +123,21 @@ translate_device_event (MetaBackendX11 *x11,
}
}
static void
meta_backend_x11_translate_crossing_event (MetaBackendX11 *x11,
XIEnterEvent *enter_event)
{
MetaBackendX11Class *backend_x11_class =
META_BACKEND_X11_GET_CLASS (x11);
if (backend_x11_class->translate_crossing_event)
backend_x11_class->translate_crossing_event (x11, enter_event);
}
static void
translate_crossing_event (MetaBackendX11 *x11,
XIEnterEvent *enter_event)
{
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
/* Throw out weird events generated by grabs. */
if (enter_event->mode == XINotifyGrab ||
enter_event->mode == XINotifyUngrab)
@ -159,14 +146,7 @@ translate_crossing_event (MetaBackendX11 *x11,
return;
}
Window stage_window = meta_backend_x11_get_xwindow (x11);
if (enter_event->event != stage_window &&
priv->mode == META_BACKEND_X11_MODE_COMPOSITOR)
{
enter_event->event = meta_backend_x11_get_xwindow (x11);
enter_event->event_x = enter_event->root_x;
enter_event->event_y = enter_event->root_y;
}
meta_backend_x11_translate_crossing_event (x11, enter_event);
}
static void
@ -254,6 +234,16 @@ keymap_changed (MetaBackend *backend)
g_signal_emit_by_name (backend, "keymap-changed", 0);
}
static gboolean
meta_backend_x11_handle_host_xevent (MetaBackendX11 *backend_x11,
XEvent *event)
{
MetaBackendX11Class *backend_x11_class =
META_BACKEND_X11_GET_CLASS (backend_x11);
return backend_x11_class->handle_host_xevent (backend_x11, event);
}
static void
handle_host_xevent (MetaBackend *backend,
XEvent *event)
@ -275,24 +265,8 @@ handle_host_xevent (MetaBackend *backend,
}
}
if (priv->mode == META_BACKEND_X11_MODE_NESTED && event->type == FocusIn)
{
#ifdef HAVE_WAYLAND
Window xwin = meta_backend_x11_get_xwindow(x11);
XEvent xev;
if (event->xfocus.window == xwin)
{
/* Since we've selected for KeymapStateMask, every FocusIn is followed immediately
* by a KeymapNotify event */
XMaskEvent(priv->xdisplay, KeymapStateMask, &xev);
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
meta_wayland_compositor_update_key_state (compositor, xev.xkeymap.key_vector, 32, 8);
}
#else
g_assert_not_reached ();
#endif
}
bypass_clutter = (meta_backend_x11_handle_host_xevent (x11, event) ||
bypass_clutter);
if (event->type == (priv->xsync_event_base + XSyncAlarmNotify))
handle_alarm_notify (backend, event);
@ -322,13 +296,6 @@ handle_host_xevent (MetaBackend *backend,
}
}
{
MetaMonitorManager *manager = meta_backend_get_monitor_manager (backend);
if (META_IS_MONITOR_MANAGER_XRANDR (manager) &&
meta_monitor_manager_xrandr_handle_xevent (META_MONITOR_MANAGER_XRANDR (manager), event))
bypass_clutter = TRUE;
}
if (!bypass_clutter)
{
handle_input_event (x11, event);
@ -416,24 +383,6 @@ x_event_source_new (MetaBackend *backend)
return source;
}
static void
take_touch_grab (MetaBackend *backend)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { META_VIRTUAL_CORE_POINTER_ID, sizeof (mask_bits), mask_bits };
XIGrabModifiers mods = { XIAnyModifier, 0 };
XISetMask (mask.mask, XI_TouchBegin);
XISetMask (mask.mask, XI_TouchUpdate);
XISetMask (mask.mask, XI_TouchEnd);
XIGrabTouchBegin (priv->xdisplay, META_VIRTUAL_CORE_POINTER_ID,
DefaultRootWindow (priv->xdisplay),
False, &mask, 1, &mods);
}
static void
on_device_added (ClutterDeviceManager *device_manager,
ClutterInputDevice *device,
@ -490,10 +439,6 @@ meta_backend_x11_post_init (MetaBackend *backend)
if (!has_xi)
meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n");
/* We only take the passive touch grab if we are a X11 compositor */
if (priv->mode == META_BACKEND_X11_MODE_COMPOSITOR)
take_touch_grab (backend);
priv->xcb = XGetXCBConnection (priv->xdisplay);
if (!xkb_x11_setup_xkb_extension (priv->xcb,
XKB_X11_MIN_MAJOR_XKB_VERSION,
@ -530,42 +475,6 @@ meta_backend_x11_create_idle_monitor (MetaBackend *backend,
NULL);
}
static MetaMonitorManager *
meta_backend_x11_create_monitor_manager (MetaBackend *backend)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
switch (priv->mode)
{
case META_BACKEND_X11_MODE_COMPOSITOR:
return g_object_new (META_TYPE_MONITOR_MANAGER_XRANDR, NULL);
case META_BACKEND_X11_MODE_NESTED:
return g_object_new (META_TYPE_MONITOR_MANAGER_DUMMY, NULL);
default:
g_assert_not_reached ();
}
}
static MetaCursorRenderer *
meta_backend_x11_create_cursor_renderer (MetaBackend *backend)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
switch (priv->mode)
{
case META_BACKEND_X11_MODE_COMPOSITOR:
return g_object_new (META_TYPE_CURSOR_RENDERER_X11, NULL);
break;
case META_BACKEND_X11_MODE_NESTED:
return g_object_new (META_TYPE_CURSOR_RENDERER_X11_NESTED, NULL);
break;
default:
g_assert_not_reached ();
}
}
static MetaRenderer *
meta_backend_x11_create_renderer (MetaBackend *backend)
{
@ -856,79 +765,6 @@ meta_backend_x11_handle_event (MetaBackendX11 *x11,
priv->cached_current_logical_monitor = NULL;
}
static void
meta_backend_x11_update_screen_size (MetaBackend *backend,
int width, int height)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
if (priv->mode == META_BACKEND_X11_MODE_NESTED)
{
ClutterActor *stage = meta_backend_get_stage (backend);
MetaRenderer *renderer = meta_backend_get_renderer (backend);
if (meta_is_stage_views_enabled ())
meta_renderer_rebuild_views (renderer);
clutter_actor_set_size (stage, width, height);
}
else
{
Window xwin = meta_backend_x11_get_xwindow (x11);
XResizeWindow (priv->xdisplay, xwin, width, height);
}
}
static void
meta_backend_x11_select_stage_events (MetaBackend *backend)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
Window xwin = meta_backend_x11_get_xwindow (x11);
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
XISetMask (mask.mask, XI_KeyPress);
XISetMask (mask.mask, XI_KeyRelease);
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Enter);
XISetMask (mask.mask, XI_Leave);
XISetMask (mask.mask, XI_FocusIn);
XISetMask (mask.mask, XI_FocusOut);
XISetMask (mask.mask, XI_Motion);
if (priv->mode == META_BACKEND_X11_MODE_NESTED)
{
/* When we're an X11 compositor, we can't take these events or else
* replaying events from our passive root window grab will cause
* them to come back to us.
*
* When we're a nested application, we want to behave like any other
* application, so select these events like normal apps do.
*/
XISetMask (mask.mask, XI_TouchBegin);
XISetMask (mask.mask, XI_TouchEnd);
XISetMask (mask.mask, XI_TouchUpdate);
}
XISelectEvents (priv->xdisplay, xwin, &mask, 1);
if (priv->mode == META_BACKEND_X11_MODE_NESTED)
{
/* We have no way of tracking key changes when the stage doesn't have
* focus, so we select for KeymapStateMask so that we get a complete
* dump of the keyboard state in a KeymapNotify event that immediately
* follows each FocusIn (and EnterNotify, but we ignore that.)
*/
XWindowAttributes xwa;
XGetWindowAttributes(priv->xdisplay, xwin, &xwa);
XSelectInput(priv->xdisplay, xwin,
xwa.your_event_mask | FocusChangeMask | KeymapStateMask);
}
}
static void
meta_backend_x11_class_init (MetaBackendX11Class *klass)
{
@ -937,8 +773,6 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
backend_class->create_clutter_backend = meta_backend_x11_create_clutter_backend;
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;
backend_class->create_cursor_renderer = meta_backend_x11_create_cursor_renderer;
backend_class->create_renderer = meta_backend_x11_create_renderer;
backend_class->grab_device = meta_backend_x11_grab_device;
backend_class->ungrab_device = meta_backend_x11_ungrab_device;
@ -947,25 +781,16 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
backend_class->set_keymap = meta_backend_x11_set_keymap;
backend_class->get_keymap = meta_backend_x11_get_keymap;
backend_class->lock_layout_group = meta_backend_x11_lock_layout_group;
backend_class->update_screen_size = meta_backend_x11_update_screen_size;
backend_class->select_stage_events = meta_backend_x11_select_stage_events;
backend_class->set_numlock = meta_backend_x11_set_numlock;
}
static void
meta_backend_x11_init (MetaBackendX11 *x11)
{
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
clutter_x11_request_reset_on_video_memory_purge ();
/* We do X11 event retrieval ourselves */
clutter_x11_disable_event_retrieval ();
if (meta_is_wayland_compositor ())
priv->mode = META_BACKEND_X11_MODE_NESTED;
else
priv->mode = META_BACKEND_X11_MODE_COMPOSITOR;
}
Display *

View File

@ -38,6 +38,13 @@ G_DECLARE_DERIVABLE_TYPE (MetaBackendX11, meta_backend_x11,
struct _MetaBackendX11Class
{
MetaBackendClass parent_class;
gboolean (* handle_host_xevent) (MetaBackendX11 *x11,
XEvent *event);
void (* translate_device_event) (MetaBackendX11 *x11,
XIDeviceEvent *device_event);
void (* translate_crossing_event) (MetaBackendX11 *x11,
XIEnterEvent *enter_event);
};
Display * meta_backend_x11_get_xdisplay (MetaBackendX11 *backend);

View File

@ -0,0 +1,168 @@
/*
* Copyright (C) 2017 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.
*/
#include "config.h"
#include "backends/x11/nested/meta-backend-x11-nested.h"
#include "backends/meta-monitor-manager-dummy.h"
#include "backends/x11/nested/meta-backend-x11-nested.h"
#include "backends/x11/nested/meta-cursor-renderer-x11-nested.h"
#include "wayland/meta-wayland.h"
struct _MetaBackendX11Nested
{
MetaBackendX11 parent;
};
G_DEFINE_TYPE (MetaBackendX11Nested, meta_backend_x11_nested,
META_TYPE_BACKEND_X11)
static MetaMonitorManager *
meta_backend_x11_nested_create_monitor_manager (MetaBackend *backend)
{
return g_object_new (META_TYPE_MONITOR_MANAGER_DUMMY, NULL);
}
static MetaCursorRenderer *
meta_backend_x11_nested_create_cursor_renderer (MetaBackend *backend)
{
return g_object_new (META_TYPE_CURSOR_RENDERER_X11_NESTED, NULL);
}
static void
meta_backend_x11_nested_update_screen_size (MetaBackend *backend,
int width,
int height)
{
ClutterActor *stage = meta_backend_get_stage (backend);
MetaRenderer *renderer = meta_backend_get_renderer (backend);
if (meta_is_stage_views_enabled ())
meta_renderer_rebuild_views (renderer);
clutter_actor_set_size (stage, width, height);
}
static void
meta_backend_x11_nested_select_stage_events (MetaBackend *backend)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
Display *xdisplay = meta_backend_x11_get_xdisplay (x11);
Window xwin = meta_backend_x11_get_xwindow (x11);
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
XISetMask (mask.mask, XI_KeyPress);
XISetMask (mask.mask, XI_KeyRelease);
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Enter);
XISetMask (mask.mask, XI_Leave);
XISetMask (mask.mask, XI_FocusIn);
XISetMask (mask.mask, XI_FocusOut);
XISetMask (mask.mask, XI_Motion);
/*
* When we're an X11 compositor, we can't take these events or else replaying
* events from our passive root window grab will cause them to come back to
* us.
*
* When we're a nested application, we want to behave like any other
* application, so select these events like normal apps do.
*/
XISetMask (mask.mask, XI_TouchBegin); XISetMask (mask.mask, XI_TouchEnd);
XISetMask (mask.mask, XI_TouchUpdate);
XISelectEvents (xdisplay, xwin, &mask, 1);
/*
* We have no way of tracking key changes when the stage doesn't have focus,
* so we select for KeymapStateMask so that we get a complete dump of the
* keyboard state in a KeymapNotify event that immediately follows each
* FocusIn (and EnterNotify, but we ignore that.)
*/
XWindowAttributes xwa;
XGetWindowAttributes(xdisplay, xwin, &xwa);
XSelectInput(xdisplay, xwin,
xwa.your_event_mask | FocusChangeMask | KeymapStateMask);
}
static gboolean
meta_backend_x11_nested_handle_host_xevent (MetaBackendX11 *x11,
XEvent *event)
{
#ifdef HAVE_WAYLAND
if (event->type == FocusIn)
{
Window xwin = meta_backend_x11_get_xwindow (x11);
XEvent xev;
if (event->xfocus.window == xwin)
{
MetaWaylandCompositor *compositor =
meta_wayland_compositor_get_default ();
Display *xdisplay = meta_backend_x11_get_xdisplay (x11);
/*
* Since we've selected for KeymapStateMask, every FocusIn is
* followed immediately by a KeymapNotify event.
*/
XMaskEvent (xdisplay, KeymapStateMask, &xev);
meta_wayland_compositor_update_key_state (compositor,
xev.xkeymap.key_vector,
32, 8);
}
}
#endif
return FALSE;
}
static void
meta_backend_x11_nested_translate_device_event (MetaBackendX11 *x11,
XIDeviceEvent *device_event)
{
/* This codepath should only ever trigger as an X11 compositor,
* and never under nested, as under nested all backend events
* should be reported with respect to the stage window.
*/
g_assert (device_event->event == meta_backend_x11_get_xwindow (x11));
}
static void
meta_backend_x11_nested_init (MetaBackendX11Nested *backend_x11_nested)
{
}
static void
meta_backend_x11_nested_class_init (MetaBackendX11NestedClass *klass)
{
MetaBackendClass *backend_class = META_BACKEND_CLASS (klass);
MetaBackendX11Class *backend_x11_class = META_BACKEND_X11_CLASS (klass);
backend_class->create_monitor_manager = meta_backend_x11_nested_create_monitor_manager;
backend_class->create_cursor_renderer = meta_backend_x11_nested_create_cursor_renderer;
backend_class->update_screen_size = meta_backend_x11_nested_update_screen_size;
backend_class->select_stage_events = meta_backend_x11_nested_select_stage_events;
backend_x11_class->handle_host_xevent = meta_backend_x11_nested_handle_host_xevent;
backend_x11_class->translate_device_event = meta_backend_x11_nested_translate_device_event;
}

View File

@ -0,0 +1,31 @@
/*
* Copyright (C) 2017 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.
*/
#ifndef META_BACKEND_X11_NESTED_H
#define META_BACKEND_X11_NESTED_H
#include <glib-object.h>
#include "backends/x11/meta-backend-x11.h"
#define META_TYPE_BACKEND_X11_NESTED (meta_backend_x11_nested_get_type ())
G_DECLARE_FINAL_TYPE (MetaBackendX11Nested, meta_backend_x11_nested,
META, BACKEND_X11_NESTED, MetaBackendX11)
#endif /* META_BACKEND_X11_NESTED_H */

View File

@ -80,10 +80,12 @@
#ifdef HAVE_WAYLAND
#include "wayland/meta-wayland.h"
#include "backends/x11/nested/meta-backend-x11-nested.h"
# endif
#include "backends/meta-backend-private.h"
#include "backends/x11/meta-backend-x11.h"
#include "backends/x11/cm/meta-backend-x11-cm.h"
#ifdef HAVE_NATIVE_BACKEND
#include "backends/native/meta-backend-native.h"
@ -397,6 +399,26 @@ check_for_wayland_session_type (void)
}
#endif
/*
* Determine the compositor configuration, i.e. whether to run as a Wayland
* compositor, as well as what backend to use.
*
* There are various different flags affecting this:
*
* --nested always forces the use of the nested X11 backend
* --display-server always forces the use of the native backend
* --wayland always forces the compositor type to be a Wayland compositor
*
* If no flag is passed that forces the compositor type, the compositor type
* is determined first from the logind session type, or if that fails, from the
* XDG_SESSION_TYPE enviornment variable.
*
* If no flag is passed that forces the backend type, the backend type is
* determined given the compositor type. If the compositor is a Wayland
* compositor, then the native backend is used, or the nested backend, would
* the native backend not be enabled at build time. If the compositor is not a
* Wayland compositor, then the X11 Compositing Manager backend is used.
*/
static void
calculate_compositor_configuration (MetaCompositorType *compositor_type,
GType *backend_gtype)
@ -413,22 +435,48 @@ calculate_compositor_configuration (MetaCompositorType *compositor_type,
if (!run_as_wayland_compositor)
run_as_wayland_compositor = check_for_wayland_session_type ();
#endif /* HAVE_NATIVE_BACKEND */
#ifdef CLUTTER_WINDOWING_EGL
if (opt_display_server || (run_as_wayland_compositor && !opt_nested))
*backend_gtype = META_TYPE_BACKEND_NATIVE;
else
#endif
#endif
#endif
*backend_gtype = META_TYPE_BACKEND_X11;
#ifdef HAVE_WAYLAND
if (run_as_wayland_compositor)
*compositor_type = META_COMPOSITOR_TYPE_WAYLAND;
else
#endif
#endif /* HAVE_WAYLAND */
*compositor_type = META_COMPOSITOR_TYPE_X11;
if (opt_nested)
{
*backend_gtype = META_TYPE_BACKEND_X11_NESTED;
return;
}
#ifdef HAVE_NATIVE_BACKEND
if (opt_display_server)
{
*backend_gtype = META_TYPE_BACKEND_NATIVE;
return;
}
#ifdef HAVE_WAYLAND
if (run_as_wayland_compositor)
{
*backend_gtype = META_TYPE_BACKEND_NATIVE;
return;
}
#endif /* HAVE_WAYLAND */
#endif /* HAVE_NATIVE_BACKEND */
#ifdef HAVE_WAYLAND
if (run_as_wayland_compositor)
{
*backend_gtype = META_TYPE_BACKEND_X11_NESTED;
return;
}
else
#endif /* HAVE_WAYLAND */
{
*backend_gtype = META_TYPE_BACKEND_X11_CM;
return;
}
}
static gboolean _compositor_configuration_overridden = FALSE;