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:
parent
042a95ef98
commit
6d64123849
@ -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 \
|
||||
|
177
src/backends/x11/cm/meta-backend-x11-cm.c
Normal file
177
src/backends/x11/cm/meta-backend-x11-cm.c
Normal 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;
|
||||
}
|
||||
|
31
src/backends/x11/cm/meta-backend-x11-cm.h
Normal file
31
src/backends/x11/cm/meta-backend-x11-cm.h
Normal 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 */
|
@ -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 *
|
||||
|
@ -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);
|
||||
|
168
src/backends/x11/nested/meta-backend-x11-nested.c
Normal file
168
src/backends/x11/nested/meta-backend-x11-nested.c
Normal 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;
|
||||
}
|
31
src/backends/x11/nested/meta-backend-x11-nested.h
Normal file
31
src/backends/x11/nested/meta-backend-x11-nested.h
Normal 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 */
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user