mirror of
https://github.com/brl/mutter.git
synced 2024-12-01 04:10:43 -05:00
5e67e35ec5
As with the backend commit, this means all objects can reach the MetaContext by walking up the chain, thus can e.g. get the backend from the context, instead of the global singleton. This also is a squashed commit containing: compositor: Get backend via the context The MetaCompositor instance is owned by MetaDisplay, which is owned by MetaContext. Get the backend via that chain of ownership. dnd: Don't get backend from singleton window-actor: Don't get backend from singleton dnd: Don't get Wayland compositor via singleton background: Don't get the monitor manager from the singleton plugins: Don't get backend from singleton This applies to MetaPlugin, it's manager class, and the default plugin. feedback-actor: Pass a compositor pointer when constructing This allows getting to the display. later: Keep a pointer to the manager object This allows using the non-singleton API in idle callbacks. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2718>
1756 lines
49 KiB
C
1756 lines
49 KiB
C
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
/*
|
|
* Copyright (C) 2014 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>
|
|
*/
|
|
|
|
/**
|
|
* SECTION:meta-backend
|
|
* @title: MetaBackend
|
|
* @short_description: Handles monitor config, modesetting, cursor sprites, ...
|
|
*
|
|
* MetaBackend is the abstraction that deals with several things like:
|
|
* - Modesetting (depending on the backend, this can be done either by X or KMS)
|
|
* - Initializing the #MetaSettings
|
|
* - Setting up Monitor configuration
|
|
* - Input device configuration (using the #ClutterDeviceManager)
|
|
* - Creating the #MetaRenderer
|
|
* - Setting up the stage of the scene graph (using #MetaStage)
|
|
* - Creating the object that deals with the cursor (using #MetaCursorTracker)
|
|
* and its possible pointer constraint (using #MetaPointerConstraint)
|
|
* - Setting the cursor sprite (using #MetaCursorRenderer)
|
|
* - Interacting with logind (using the appropriate D-Bus interface)
|
|
* - Querying UPower (over D-Bus) to know when the lid is closed
|
|
* - Setup Remote Desktop / Screencasting (#MetaRemoteDesktop)
|
|
* - Setup the #MetaEgl object
|
|
*
|
|
* Note that the #MetaBackend is not a subclass of #ClutterBackend. It is
|
|
* responsible for creating the correct one, based on the backend that is
|
|
* used (#MetaBackendNative or #MetaBackendX11).
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "backends/meta-backend-private.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "backends/meta-barrier-private.h"
|
|
#include "backends/meta-cursor-renderer.h"
|
|
#include "backends/meta-cursor-tracker-private.h"
|
|
#include "backends/meta-idle-manager.h"
|
|
#include "backends/meta-idle-monitor-private.h"
|
|
#include "backends/meta-input-mapper-private.h"
|
|
#include "backends/meta-input-settings-private.h"
|
|
#include "backends/meta-logical-monitor.h"
|
|
#include "backends/meta-monitor-manager-dummy.h"
|
|
#include "backends/meta-settings-private.h"
|
|
#include "backends/meta-stage-private.h"
|
|
#include "backends/x11/meta-backend-x11.h"
|
|
#include "clutter/clutter-mutter.h"
|
|
#include "clutter/clutter-seat-private.h"
|
|
#include "compositor/meta-dnd-private.h"
|
|
#include "core/meta-context-private.h"
|
|
#include "meta/main.h"
|
|
#include "meta/meta-backend.h"
|
|
#include "meta/meta-context.h"
|
|
#include "meta/meta-enum-types.h"
|
|
#include "meta/util.h"
|
|
|
|
#ifdef HAVE_REMOTE_DESKTOP
|
|
#include "backends/meta-dbus-session-watcher.h"
|
|
#include "backends/meta-remote-access-controller-private.h"
|
|
#include "backends/meta-remote-desktop.h"
|
|
#include "backends/meta-screen-cast.h"
|
|
#endif
|
|
|
|
#ifdef HAVE_NATIVE_BACKEND
|
|
#include "backends/native/meta-backend-native.h"
|
|
#endif
|
|
|
|
#ifdef HAVE_WAYLAND
|
|
#include "wayland/meta-wayland.h"
|
|
#endif
|
|
|
|
enum
|
|
{
|
|
PROP_0,
|
|
|
|
PROP_CONTEXT,
|
|
PROP_CAPABILITIES,
|
|
|
|
N_PROPS
|
|
};
|
|
|
|
static GParamSpec *obj_props[N_PROPS];
|
|
|
|
enum
|
|
{
|
|
KEYMAP_CHANGED,
|
|
KEYMAP_LAYOUT_GROUP_CHANGED,
|
|
LAST_DEVICE_CHANGED,
|
|
LID_IS_CLOSED_CHANGED,
|
|
GPU_ADDED,
|
|
PREPARE_SHUTDOWN,
|
|
|
|
N_SIGNALS
|
|
};
|
|
|
|
static guint signals[N_SIGNALS];
|
|
|
|
static MetaBackend *_backend;
|
|
|
|
#define HIDDEN_POINTER_TIMEOUT 300 /* ms */
|
|
|
|
/**
|
|
* meta_get_backend:
|
|
*
|
|
* Accessor for the singleton MetaBackend.
|
|
*
|
|
* Returns: (transfer none): The only #MetaBackend there is.
|
|
*/
|
|
MetaBackend *
|
|
meta_get_backend (void)
|
|
{
|
|
return _backend;
|
|
}
|
|
|
|
struct _MetaBackendPrivate
|
|
{
|
|
MetaContext *context;
|
|
|
|
MetaMonitorManager *monitor_manager;
|
|
MetaOrientationManager *orientation_manager;
|
|
MetaCursorTracker *cursor_tracker;
|
|
MetaInputMapper *input_mapper;
|
|
MetaIdleManager *idle_manager;
|
|
MetaRenderer *renderer;
|
|
MetaColorManager *color_manager;
|
|
#ifdef HAVE_EGL
|
|
MetaEgl *egl;
|
|
#endif
|
|
MetaSettings *settings;
|
|
#ifdef HAVE_REMOTE_DESKTOP
|
|
MetaRemoteAccessController *remote_access_controller;
|
|
MetaDbusSessionWatcher *dbus_session_watcher;
|
|
MetaScreenCast *screen_cast;
|
|
MetaRemoteDesktop *remote_desktop;
|
|
#endif
|
|
|
|
#ifdef HAVE_LIBWACOM
|
|
WacomDeviceDatabase *wacom_db;
|
|
#endif
|
|
#ifdef HAVE_GNOME_DESKTOP
|
|
GnomePnpIds *pnp_ids;
|
|
#endif
|
|
|
|
ClutterContext *clutter_context;
|
|
ClutterSeat *default_seat;
|
|
ClutterActor *stage;
|
|
|
|
GList *gpus;
|
|
GList *hw_cursor_inhibitors;
|
|
|
|
gboolean is_pointer_position_initialized;
|
|
|
|
guint device_update_idle_id;
|
|
|
|
ClutterInputDevice *current_device;
|
|
|
|
MetaPointerConstraint *client_pointer_constraint;
|
|
MetaDnd *dnd;
|
|
|
|
guint upower_watch_id;
|
|
GDBusProxy *upower_proxy;
|
|
gboolean lid_is_closed;
|
|
gboolean on_battery;
|
|
|
|
guint sleep_signal_id;
|
|
GCancellable *cancellable;
|
|
GDBusConnection *system_bus;
|
|
|
|
uint32_t last_pointer_motion;
|
|
};
|
|
typedef struct _MetaBackendPrivate MetaBackendPrivate;
|
|
|
|
typedef struct _MetaBackendSource MetaBackendSource;
|
|
|
|
struct _MetaBackendSource
|
|
{
|
|
GSource parent;
|
|
MetaBackend *backend;
|
|
};
|
|
|
|
static void
|
|
initable_iface_init (GInitableIface *initable_iface);
|
|
|
|
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaBackend, meta_backend, G_TYPE_OBJECT,
|
|
G_ADD_PRIVATE (MetaBackend)
|
|
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
|
|
initable_iface_init));
|
|
|
|
static void
|
|
meta_backend_dispose (GObject *object)
|
|
{
|
|
MetaBackend *backend = META_BACKEND (object);
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
_backend = NULL;
|
|
|
|
g_clear_pointer (&priv->cursor_tracker, meta_cursor_tracker_destroy);
|
|
g_clear_object (&priv->current_device);
|
|
g_clear_object (&priv->color_manager);
|
|
g_clear_object (&priv->monitor_manager);
|
|
g_clear_object (&priv->orientation_manager);
|
|
#ifdef HAVE_REMOTE_DESKTOP
|
|
g_clear_object (&priv->remote_desktop);
|
|
g_clear_object (&priv->screen_cast);
|
|
g_clear_object (&priv->dbus_session_watcher);
|
|
g_clear_object (&priv->remote_access_controller);
|
|
#endif
|
|
|
|
#ifdef HAVE_LIBWACOM
|
|
g_clear_pointer (&priv->wacom_db, libwacom_database_destroy);
|
|
#endif
|
|
#ifdef HAVE_GNOME_DESKTOP
|
|
g_clear_object (&priv->pnp_ids);
|
|
#endif
|
|
|
|
if (priv->sleep_signal_id)
|
|
{
|
|
g_dbus_connection_signal_unsubscribe (priv->system_bus, priv->sleep_signal_id);
|
|
priv->sleep_signal_id = 0;
|
|
}
|
|
|
|
if (priv->upower_watch_id)
|
|
{
|
|
g_bus_unwatch_name (priv->upower_watch_id);
|
|
priv->upower_watch_id = 0;
|
|
}
|
|
|
|
g_cancellable_cancel (priv->cancellable);
|
|
g_clear_object (&priv->cancellable);
|
|
g_clear_object (&priv->system_bus);
|
|
g_clear_object (&priv->upower_proxy);
|
|
|
|
g_clear_handle_id (&priv->device_update_idle_id, g_source_remove);
|
|
|
|
g_clear_object (&priv->settings);
|
|
|
|
g_clear_pointer (&priv->default_seat, clutter_seat_destroy);
|
|
g_clear_pointer (&priv->stage, clutter_actor_destroy);
|
|
g_clear_pointer (&priv->idle_manager, meta_idle_manager_free);
|
|
g_clear_object (&priv->renderer);
|
|
g_clear_pointer (&priv->clutter_context, clutter_context_free);
|
|
g_clear_list (&priv->gpus, g_object_unref);
|
|
|
|
G_OBJECT_CLASS (meta_backend_parent_class)->dispose (object);
|
|
}
|
|
|
|
void
|
|
meta_backend_destroy (MetaBackend *backend)
|
|
{
|
|
g_object_run_dispose (G_OBJECT (backend));
|
|
g_object_unref (backend);
|
|
}
|
|
|
|
static void
|
|
meta_backend_sync_screen_size (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
int width, height;
|
|
|
|
meta_monitor_manager_get_screen_size (priv->monitor_manager, &width, &height);
|
|
|
|
META_BACKEND_GET_CLASS (backend)->update_screen_size (backend, width, height);
|
|
}
|
|
|
|
static void
|
|
reset_pointer_position (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
MetaMonitorManager *monitor_manager = priv->monitor_manager;
|
|
ClutterSeat *seat = priv->default_seat;
|
|
MetaLogicalMonitor *primary;
|
|
|
|
primary =
|
|
meta_monitor_manager_get_primary_logical_monitor (monitor_manager);
|
|
|
|
/* Move the pointer out of the way to avoid hovering over reactive
|
|
* elements (e.g. users list at login) causing undesired behaviour. */
|
|
clutter_seat_warp_pointer (seat,
|
|
primary->rect.x + primary->rect.width * 0.9,
|
|
primary->rect.y + primary->rect.height * 0.9);
|
|
}
|
|
|
|
static gboolean
|
|
should_have_cursor_renderer (ClutterInputDevice *device)
|
|
{
|
|
switch (clutter_input_device_get_device_type (device))
|
|
{
|
|
case CLUTTER_POINTER_DEVICE:
|
|
if (clutter_input_device_get_device_mode (device) ==
|
|
CLUTTER_INPUT_MODE_LOGICAL)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
case CLUTTER_TABLET_DEVICE:
|
|
return TRUE;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static void
|
|
update_cursors (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
ClutterSeat *seat = priv->default_seat;
|
|
MetaCursorRenderer *cursor_renderer;
|
|
ClutterInputDevice *pointer, *device;
|
|
GList *devices, *l;
|
|
|
|
pointer = clutter_seat_get_pointer (seat);
|
|
devices = clutter_seat_list_devices (seat);
|
|
devices = g_list_prepend (devices, pointer);
|
|
|
|
for (l = devices; l; l = l->next)
|
|
{
|
|
device = l->data;
|
|
|
|
if (!should_have_cursor_renderer (device))
|
|
continue;
|
|
|
|
cursor_renderer = meta_backend_get_cursor_renderer_for_device (backend,
|
|
device);
|
|
if (cursor_renderer)
|
|
meta_cursor_renderer_force_update (cursor_renderer);
|
|
}
|
|
|
|
g_list_free (devices);
|
|
}
|
|
|
|
void
|
|
meta_backend_monitors_changed (MetaBackend *backend)
|
|
{
|
|
meta_backend_sync_screen_size (backend);
|
|
update_cursors (backend);
|
|
}
|
|
|
|
static gboolean
|
|
update_last_device (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
priv->device_update_idle_id = 0;
|
|
g_signal_emit (backend, signals[LAST_DEVICE_CHANGED], 0,
|
|
priv->current_device);
|
|
|
|
return G_SOURCE_REMOVE;
|
|
}
|
|
|
|
static void
|
|
meta_backend_update_last_device (MetaBackend *backend,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
if (priv->current_device == device)
|
|
return;
|
|
|
|
if (!device ||
|
|
clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_LOGICAL)
|
|
return;
|
|
|
|
g_set_object (&priv->current_device, device);
|
|
|
|
if (priv->device_update_idle_id == 0)
|
|
{
|
|
priv->device_update_idle_id =
|
|
g_idle_add ((GSourceFunc) update_last_device, backend);
|
|
g_source_set_name_by_id (priv->device_update_idle_id,
|
|
"[mutter] update_last_device");
|
|
}
|
|
}
|
|
|
|
static inline gboolean
|
|
determine_hotplug_pointer_visibility (ClutterSeat *seat)
|
|
{
|
|
g_autoptr (GList) devices = NULL;
|
|
const GList *l;
|
|
gboolean has_touchscreen = FALSE, has_pointer = FALSE, has_tablet = FALSE;
|
|
|
|
devices = clutter_seat_list_devices (seat);
|
|
|
|
for (l = devices; l; l = l->next)
|
|
{
|
|
ClutterInputDevice *device = l->data;
|
|
ClutterInputDeviceType device_type;
|
|
|
|
device_type = clutter_input_device_get_device_type (device);
|
|
|
|
if (device_type == CLUTTER_TOUCHSCREEN_DEVICE)
|
|
has_touchscreen = TRUE;
|
|
if (device_type == CLUTTER_POINTER_DEVICE ||
|
|
device_type == CLUTTER_TOUCHPAD_DEVICE)
|
|
has_pointer = TRUE;
|
|
if (device_type == CLUTTER_TABLET_DEVICE ||
|
|
device_type == CLUTTER_PEN_DEVICE ||
|
|
device_type == CLUTTER_ERASER_DEVICE)
|
|
{
|
|
if (meta_is_wayland_compositor ())
|
|
has_tablet = TRUE;
|
|
else
|
|
has_pointer = TRUE;
|
|
}
|
|
}
|
|
|
|
return has_pointer && !has_touchscreen && !has_tablet;
|
|
}
|
|
|
|
static void
|
|
on_device_added (ClutterSeat *seat,
|
|
ClutterInputDevice *device,
|
|
gpointer user_data)
|
|
{
|
|
MetaBackend *backend = META_BACKEND (user_data);
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
ClutterInputDeviceType device_type;
|
|
|
|
if (clutter_input_device_get_device_mode (device) ==
|
|
CLUTTER_INPUT_MODE_LOGICAL)
|
|
return;
|
|
|
|
device_type = clutter_input_device_get_device_type (device);
|
|
|
|
if (device_type == CLUTTER_TOUCHSCREEN_DEVICE ||
|
|
device_type == CLUTTER_POINTER_DEVICE)
|
|
{
|
|
meta_cursor_tracker_set_pointer_visible (priv->cursor_tracker,
|
|
determine_hotplug_pointer_visibility (seat));
|
|
}
|
|
|
|
if (device_type == CLUTTER_TOUCHSCREEN_DEVICE ||
|
|
device_type == CLUTTER_TABLET_DEVICE ||
|
|
device_type == CLUTTER_PEN_DEVICE ||
|
|
device_type == CLUTTER_ERASER_DEVICE ||
|
|
device_type == CLUTTER_CURSOR_DEVICE ||
|
|
device_type == CLUTTER_PAD_DEVICE)
|
|
meta_input_mapper_add_device (priv->input_mapper, device);
|
|
}
|
|
|
|
static void
|
|
on_device_removed (ClutterSeat *seat,
|
|
ClutterInputDevice *device,
|
|
gpointer user_data)
|
|
{
|
|
MetaBackend *backend = META_BACKEND (user_data);
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
if (clutter_input_device_get_device_mode (device) ==
|
|
CLUTTER_INPUT_MODE_LOGICAL)
|
|
return;
|
|
|
|
meta_input_mapper_remove_device (priv->input_mapper, device);
|
|
|
|
/* If the device the user last interacted goes away, check again pointer
|
|
* visibility.
|
|
*/
|
|
if (priv->current_device == device)
|
|
{
|
|
MetaCursorTracker *cursor_tracker = priv->cursor_tracker;
|
|
|
|
g_clear_object (&priv->current_device);
|
|
g_clear_handle_id (&priv->device_update_idle_id, g_source_remove);
|
|
|
|
meta_cursor_tracker_set_pointer_visible (cursor_tracker,
|
|
determine_hotplug_pointer_visibility (seat));
|
|
}
|
|
|
|
if (priv->current_device == device)
|
|
meta_backend_update_last_device (backend, NULL);
|
|
}
|
|
|
|
static void
|
|
input_mapper_device_mapped_cb (MetaInputMapper *mapper,
|
|
ClutterInputDevice *device,
|
|
float matrix[6],
|
|
MetaInputSettings *input_settings)
|
|
{
|
|
meta_input_settings_set_device_matrix (input_settings, device, matrix);
|
|
}
|
|
|
|
static void
|
|
input_mapper_device_enabled_cb (MetaInputMapper *mapper,
|
|
ClutterInputDevice *device,
|
|
gboolean enabled,
|
|
MetaInputSettings *input_settings)
|
|
{
|
|
meta_input_settings_set_device_enabled (input_settings, device, enabled);
|
|
}
|
|
|
|
static void
|
|
input_mapper_device_aspect_ratio_cb (MetaInputMapper *mapper,
|
|
ClutterInputDevice *device,
|
|
double aspect_ratio,
|
|
MetaInputSettings *input_settings)
|
|
{
|
|
meta_input_settings_set_device_aspect_ratio (input_settings, device, aspect_ratio);
|
|
}
|
|
|
|
static void
|
|
on_prepare_shutdown (MetaContext *context,
|
|
MetaBackend *backend)
|
|
{
|
|
g_signal_emit (backend, signals[PREPARE_SHUTDOWN], 0);
|
|
}
|
|
|
|
static void
|
|
on_started (MetaContext *context,
|
|
MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
ClutterSeat *seat = priv->default_seat;
|
|
|
|
meta_cursor_tracker_set_pointer_visible (priv->cursor_tracker,
|
|
determine_hotplug_pointer_visibility (seat));
|
|
}
|
|
|
|
static void
|
|
meta_backend_real_post_init (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
ClutterSeat *seat = priv->default_seat;
|
|
MetaInputSettings *input_settings;
|
|
|
|
priv->stage = meta_stage_new (backend);
|
|
clutter_actor_realize (priv->stage);
|
|
META_BACKEND_GET_CLASS (backend)->select_stage_events (backend);
|
|
|
|
meta_monitor_manager_setup (priv->monitor_manager);
|
|
|
|
meta_backend_sync_screen_size (backend);
|
|
|
|
priv->idle_manager = meta_idle_manager_new (backend);
|
|
|
|
g_signal_connect_object (seat, "device-added",
|
|
G_CALLBACK (on_device_added), backend, 0);
|
|
g_signal_connect_object (seat, "device-removed",
|
|
G_CALLBACK (on_device_removed), backend,
|
|
G_CONNECT_AFTER);
|
|
|
|
priv->input_mapper = meta_input_mapper_new (backend);
|
|
|
|
input_settings = meta_backend_get_input_settings (backend);
|
|
|
|
if (input_settings)
|
|
{
|
|
g_signal_connect (priv->input_mapper, "device-mapped",
|
|
G_CALLBACK (input_mapper_device_mapped_cb),
|
|
input_settings);
|
|
g_signal_connect (priv->input_mapper, "device-enabled",
|
|
G_CALLBACK (input_mapper_device_enabled_cb),
|
|
input_settings);
|
|
g_signal_connect (priv->input_mapper, "device-aspect-ratio",
|
|
G_CALLBACK (input_mapper_device_aspect_ratio_cb),
|
|
input_settings);
|
|
}
|
|
|
|
#ifdef HAVE_REMOTE_DESKTOP
|
|
priv->dbus_session_watcher = g_object_new (META_TYPE_DBUS_SESSION_WATCHER, NULL);
|
|
priv->screen_cast = meta_screen_cast_new (backend,
|
|
priv->dbus_session_watcher);
|
|
priv->remote_desktop = meta_remote_desktop_new (backend,
|
|
priv->dbus_session_watcher);
|
|
priv->remote_access_controller =
|
|
meta_remote_access_controller_new (priv->remote_desktop, priv->screen_cast);
|
|
#endif /* HAVE_REMOTE_DESKTOP */
|
|
|
|
if (!meta_monitor_manager_is_headless (priv->monitor_manager))
|
|
{
|
|
reset_pointer_position (backend);
|
|
priv->is_pointer_position_initialized = TRUE;
|
|
}
|
|
|
|
meta_monitor_manager_post_init (priv->monitor_manager);
|
|
|
|
g_signal_connect (priv->context, "prepare-shutdown",
|
|
G_CALLBACK (on_prepare_shutdown), backend);
|
|
g_signal_connect (priv->context, "started",
|
|
G_CALLBACK (on_started), backend);
|
|
}
|
|
|
|
static gboolean
|
|
meta_backend_real_grab_device (MetaBackend *backend,
|
|
int device_id,
|
|
uint32_t timestamp)
|
|
{
|
|
/* Do nothing */
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
meta_backend_real_ungrab_device (MetaBackend *backend,
|
|
int device_id,
|
|
uint32_t timestamp)
|
|
{
|
|
/* Do nothing */
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
meta_backend_real_select_stage_events (MetaBackend *backend)
|
|
{
|
|
/* Do nothing */
|
|
}
|
|
|
|
static gboolean
|
|
meta_backend_real_is_lid_closed (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
return priv->lid_is_closed;
|
|
}
|
|
|
|
static MetaCursorTracker *
|
|
meta_backend_real_create_cursor_tracker (MetaBackend *backend)
|
|
{
|
|
return g_object_new (META_TYPE_CURSOR_TRACKER,
|
|
"backend", backend,
|
|
NULL);
|
|
}
|
|
|
|
static gboolean
|
|
meta_backend_real_is_headless (MetaBackend *backend)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
gboolean
|
|
meta_backend_is_lid_closed (MetaBackend *backend)
|
|
{
|
|
return META_BACKEND_GET_CLASS (backend)->is_lid_closed (backend);
|
|
}
|
|
|
|
gboolean
|
|
meta_backend_is_headless (MetaBackend *backend)
|
|
{
|
|
return META_BACKEND_GET_CLASS (backend)->is_headless (backend);
|
|
}
|
|
|
|
static void
|
|
upower_properties_changed (GDBusProxy *proxy,
|
|
GVariant *changed_properties,
|
|
GStrv invalidated_properties,
|
|
gpointer user_data)
|
|
{
|
|
MetaBackend *backend = user_data;
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
GVariant *v;
|
|
gboolean reset_idle_time = FALSE;
|
|
|
|
v = g_variant_lookup_value (changed_properties,
|
|
"LidIsClosed",
|
|
G_VARIANT_TYPE_BOOLEAN);
|
|
if (v)
|
|
{
|
|
gboolean lid_is_closed;
|
|
|
|
lid_is_closed = g_variant_get_boolean (v);
|
|
g_variant_unref (v);
|
|
|
|
if (lid_is_closed != priv->lid_is_closed)
|
|
{
|
|
priv->lid_is_closed = lid_is_closed;
|
|
g_signal_emit (backend, signals[LID_IS_CLOSED_CHANGED], 0,
|
|
priv->lid_is_closed);
|
|
|
|
if (!lid_is_closed)
|
|
reset_idle_time = TRUE;
|
|
}
|
|
}
|
|
|
|
v = g_variant_lookup_value (changed_properties,
|
|
"OnBattery",
|
|
G_VARIANT_TYPE_BOOLEAN);
|
|
if (v)
|
|
{
|
|
gboolean on_battery;
|
|
|
|
on_battery = g_variant_get_boolean (v);
|
|
g_variant_unref (v);
|
|
|
|
if (on_battery != priv->on_battery)
|
|
{
|
|
priv->on_battery = on_battery;
|
|
reset_idle_time = TRUE;
|
|
}
|
|
}
|
|
|
|
if (reset_idle_time)
|
|
meta_idle_manager_reset_idle_time (priv->idle_manager);
|
|
}
|
|
|
|
static void
|
|
upower_ready_cb (GObject *source_object,
|
|
GAsyncResult *res,
|
|
gpointer user_data)
|
|
{
|
|
MetaBackend *backend;
|
|
MetaBackendPrivate *priv;
|
|
GDBusProxy *proxy;
|
|
GError *error = NULL;
|
|
GVariant *v;
|
|
|
|
proxy = g_dbus_proxy_new_finish (res, &error);
|
|
if (!proxy)
|
|
{
|
|
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
g_warning ("Failed to create UPower proxy: %s", error->message);
|
|
g_error_free (error);
|
|
return;
|
|
}
|
|
|
|
backend = META_BACKEND (user_data);
|
|
priv = meta_backend_get_instance_private (backend);
|
|
|
|
priv->upower_proxy = proxy;
|
|
g_signal_connect (proxy, "g-properties-changed",
|
|
G_CALLBACK (upower_properties_changed), backend);
|
|
|
|
v = g_dbus_proxy_get_cached_property (proxy, "LidIsClosed");
|
|
if (v)
|
|
{
|
|
priv->lid_is_closed = g_variant_get_boolean (v);
|
|
g_variant_unref (v);
|
|
|
|
if (priv->lid_is_closed)
|
|
{
|
|
g_signal_emit (backend, signals[LID_IS_CLOSED_CHANGED], 0,
|
|
priv->lid_is_closed);
|
|
}
|
|
}
|
|
|
|
v = g_dbus_proxy_get_cached_property (proxy, "OnBattery");
|
|
if (v)
|
|
{
|
|
priv->on_battery = g_variant_get_boolean (v);
|
|
g_variant_unref (v);
|
|
}
|
|
}
|
|
|
|
static void
|
|
upower_appeared (GDBusConnection *connection,
|
|
const gchar *name,
|
|
const gchar *name_owner,
|
|
gpointer user_data)
|
|
{
|
|
MetaBackend *backend = META_BACKEND (user_data);
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
g_dbus_proxy_new (connection,
|
|
G_DBUS_PROXY_FLAGS_NONE,
|
|
NULL,
|
|
"org.freedesktop.UPower",
|
|
"/org/freedesktop/UPower",
|
|
"org.freedesktop.UPower",
|
|
priv->cancellable,
|
|
upower_ready_cb,
|
|
backend);
|
|
}
|
|
|
|
static void
|
|
upower_vanished (GDBusConnection *connection,
|
|
const gchar *name,
|
|
gpointer user_data)
|
|
{
|
|
MetaBackend *backend = META_BACKEND (user_data);
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
g_clear_object (&priv->upower_proxy);
|
|
}
|
|
|
|
static void
|
|
meta_backend_constructed (GObject *object)
|
|
{
|
|
MetaBackend *backend = META_BACKEND (object);
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
MetaBackendClass *backend_class =
|
|
META_BACKEND_GET_CLASS (backend);
|
|
|
|
g_assert (priv->context);
|
|
|
|
#ifdef HAVE_LIBWACOM
|
|
priv->wacom_db = libwacom_database_new ();
|
|
if (!priv->wacom_db)
|
|
{
|
|
g_warning ("Could not create database of Wacom devices, "
|
|
"expect tablets to misbehave");
|
|
}
|
|
#endif
|
|
|
|
if (backend_class->is_lid_closed == meta_backend_real_is_lid_closed)
|
|
{
|
|
priv->upower_watch_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM,
|
|
"org.freedesktop.UPower",
|
|
G_BUS_NAME_WATCHER_FLAGS_NONE,
|
|
upower_appeared,
|
|
upower_vanished,
|
|
backend,
|
|
NULL);
|
|
}
|
|
|
|
#ifdef HAVE_EGL
|
|
priv->egl = g_object_new (META_TYPE_EGL, NULL);
|
|
#endif
|
|
|
|
G_OBJECT_CLASS (meta_backend_parent_class)->constructed (object);
|
|
}
|
|
|
|
static void
|
|
meta_backend_set_property (GObject *object,
|
|
guint prop_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
MetaBackend *backend = META_BACKEND (object);
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_CONTEXT:
|
|
priv->context = g_value_get_object (value);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
meta_backend_get_property (GObject *object,
|
|
guint prop_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
MetaBackend *backend = META_BACKEND (object);
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_CONTEXT:
|
|
g_value_set_object (value, priv->context);
|
|
break;
|
|
case PROP_CAPABILITIES:
|
|
g_value_set_flags (value, meta_backend_get_capabilities (backend));
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
meta_backend_class_init (MetaBackendClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
object_class->dispose = meta_backend_dispose;
|
|
object_class->constructed = meta_backend_constructed;
|
|
object_class->set_property = meta_backend_set_property;
|
|
object_class->get_property = meta_backend_get_property;
|
|
|
|
klass->post_init = meta_backend_real_post_init;
|
|
klass->grab_device = meta_backend_real_grab_device;
|
|
klass->ungrab_device = meta_backend_real_ungrab_device;
|
|
klass->select_stage_events = meta_backend_real_select_stage_events;
|
|
klass->is_lid_closed = meta_backend_real_is_lid_closed;
|
|
klass->create_cursor_tracker = meta_backend_real_create_cursor_tracker;
|
|
klass->is_headless = meta_backend_real_is_headless;
|
|
|
|
obj_props[PROP_CONTEXT] =
|
|
g_param_spec_object ("context",
|
|
"context",
|
|
"MetaContext",
|
|
META_TYPE_CONTEXT,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
G_PARAM_STATIC_STRINGS);
|
|
obj_props[PROP_CAPABILITIES] =
|
|
g_param_spec_flags ("capabilities",
|
|
"capabilities",
|
|
"Backend capabilities",
|
|
META_TYPE_BACKEND_CAPABILITIES,
|
|
META_BACKEND_CAPABILITY_NONE,
|
|
G_PARAM_READABLE |
|
|
G_PARAM_STATIC_STRINGS);
|
|
g_object_class_install_properties (object_class, N_PROPS, obj_props);
|
|
|
|
signals[KEYMAP_CHANGED] =
|
|
g_signal_new ("keymap-changed",
|
|
G_TYPE_FROM_CLASS (object_class),
|
|
G_SIGNAL_RUN_LAST,
|
|
0,
|
|
NULL, NULL, NULL,
|
|
G_TYPE_NONE, 0);
|
|
signals[KEYMAP_LAYOUT_GROUP_CHANGED] =
|
|
g_signal_new ("keymap-layout-group-changed",
|
|
G_TYPE_FROM_CLASS (object_class),
|
|
G_SIGNAL_RUN_LAST,
|
|
0,
|
|
NULL, NULL, NULL,
|
|
G_TYPE_NONE, 1, G_TYPE_UINT);
|
|
signals[LAST_DEVICE_CHANGED] =
|
|
g_signal_new ("last-device-changed",
|
|
G_TYPE_FROM_CLASS (object_class),
|
|
G_SIGNAL_RUN_LAST,
|
|
0,
|
|
NULL, NULL, NULL,
|
|
G_TYPE_NONE, 1, CLUTTER_TYPE_INPUT_DEVICE);
|
|
signals[LID_IS_CLOSED_CHANGED] =
|
|
g_signal_new ("lid-is-closed-changed",
|
|
G_TYPE_FROM_CLASS (object_class),
|
|
G_SIGNAL_RUN_LAST,
|
|
0,
|
|
NULL, NULL, NULL,
|
|
G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
|
|
/**
|
|
* MetaBackend::gpu-added: (skip)
|
|
* @backend: the #MetaBackend
|
|
* @gpu: the #MetaGpu
|
|
*/
|
|
signals[GPU_ADDED] =
|
|
g_signal_new ("gpu-added",
|
|
G_TYPE_FROM_CLASS (klass),
|
|
G_SIGNAL_RUN_LAST,
|
|
0,
|
|
NULL, NULL, NULL,
|
|
G_TYPE_NONE, 1, META_TYPE_GPU);
|
|
signals[PREPARE_SHUTDOWN] =
|
|
g_signal_new ("prepare-shutdown",
|
|
G_TYPE_FROM_CLASS (klass),
|
|
G_SIGNAL_RUN_LAST,
|
|
0,
|
|
NULL, NULL, NULL,
|
|
G_TYPE_NONE, 0);
|
|
}
|
|
|
|
static MetaMonitorManager *
|
|
meta_backend_create_monitor_manager (MetaBackend *backend,
|
|
GError **error)
|
|
{
|
|
return META_BACKEND_GET_CLASS (backend)->create_monitor_manager (backend,
|
|
error);
|
|
}
|
|
|
|
static MetaColorManager *
|
|
meta_backend_create_color_manager (MetaBackend *backend)
|
|
{
|
|
return META_BACKEND_GET_CLASS (backend)->create_color_manager (backend);
|
|
}
|
|
|
|
static MetaRenderer *
|
|
meta_backend_create_renderer (MetaBackend *backend,
|
|
GError **error)
|
|
{
|
|
return META_BACKEND_GET_CLASS (backend)->create_renderer (backend, error);
|
|
}
|
|
|
|
static void
|
|
prepare_for_sleep_cb (GDBusConnection *connection,
|
|
const gchar *sender_name,
|
|
const gchar *object_path,
|
|
const gchar *interface_name,
|
|
const gchar *signal_name,
|
|
GVariant *parameters,
|
|
gpointer user_data)
|
|
{
|
|
MetaBackend *backend = user_data;
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
gboolean suspending;
|
|
|
|
g_variant_get (parameters, "(b)", &suspending);
|
|
if (suspending)
|
|
return;
|
|
|
|
meta_idle_manager_reset_idle_time (priv->idle_manager);
|
|
}
|
|
|
|
static void
|
|
system_bus_gotten_cb (GObject *object,
|
|
GAsyncResult *res,
|
|
gpointer user_data)
|
|
{
|
|
MetaBackend *backend = user_data;
|
|
MetaBackendPrivate *priv;
|
|
GDBusConnection *bus;
|
|
|
|
bus = g_bus_get_finish (res, NULL);
|
|
if (!bus)
|
|
return;
|
|
|
|
priv = meta_backend_get_instance_private (backend);
|
|
priv->system_bus = bus;
|
|
priv->sleep_signal_id =
|
|
g_dbus_connection_signal_subscribe (priv->system_bus,
|
|
"org.freedesktop.login1",
|
|
"org.freedesktop.login1.Manager",
|
|
"PrepareForSleep",
|
|
"/org/freedesktop/login1",
|
|
NULL,
|
|
G_DBUS_SIGNAL_FLAGS_NONE,
|
|
prepare_for_sleep_cb,
|
|
backend,
|
|
NULL);
|
|
}
|
|
|
|
static void
|
|
update_last_device_from_event (MetaBackend *backend,
|
|
ClutterEvent *event)
|
|
{
|
|
ClutterInputDevice *source;
|
|
|
|
/* Handled elsewhere */
|
|
if (event->type == CLUTTER_DEVICE_ADDED ||
|
|
event->type == CLUTTER_DEVICE_REMOVED)
|
|
return;
|
|
|
|
source = clutter_event_get_source_device (event);
|
|
if (source)
|
|
meta_backend_update_last_device (backend, source);
|
|
}
|
|
|
|
static void
|
|
update_pointer_visibility_from_event (MetaBackend *backend,
|
|
ClutterEvent *event)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
MetaCursorTracker *cursor_tracker = priv->cursor_tracker;
|
|
ClutterInputDevice *device;
|
|
ClutterInputDeviceType device_type;
|
|
uint32_t time_ms;
|
|
|
|
device = clutter_event_get_source_device (event);
|
|
if (clutter_input_device_get_device_mode (device) != CLUTTER_INPUT_MODE_PHYSICAL)
|
|
return;
|
|
|
|
device_type = clutter_input_device_get_device_type (device);
|
|
time_ms = clutter_event_get_time (event);
|
|
|
|
switch (device_type)
|
|
{
|
|
case CLUTTER_TOUCHSCREEN_DEVICE:
|
|
meta_cursor_tracker_set_pointer_visible (cursor_tracker, FALSE);
|
|
break;
|
|
case CLUTTER_POINTER_DEVICE:
|
|
case CLUTTER_TOUCHPAD_DEVICE:
|
|
priv->last_pointer_motion = time_ms;
|
|
meta_cursor_tracker_set_pointer_visible (cursor_tracker, TRUE);
|
|
break;
|
|
case CLUTTER_TABLET_DEVICE:
|
|
case CLUTTER_PEN_DEVICE:
|
|
case CLUTTER_ERASER_DEVICE:
|
|
case CLUTTER_CURSOR_DEVICE:
|
|
if (meta_is_wayland_compositor () &&
|
|
time_ms > priv->last_pointer_motion + HIDDEN_POINTER_TIMEOUT)
|
|
meta_cursor_tracker_set_pointer_visible (cursor_tracker, FALSE);
|
|
break;
|
|
case CLUTTER_KEYBOARD_DEVICE:
|
|
case CLUTTER_PAD_DEVICE:
|
|
case CLUTTER_EXTENSION_DEVICE:
|
|
case CLUTTER_JOYSTICK_DEVICE:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Mutter is responsible for pulling events off the X queue, so Clutter
|
|
* doesn't need (and shouldn't) run its normal event source which polls
|
|
* the X fd, but we do have to deal with dispatching events that accumulate
|
|
* in the clutter queue. This happens, for example, when clutter generate
|
|
* enter/leave events on mouse motion - several events are queued in the
|
|
* clutter queue but only one dispatched. It could also happen because of
|
|
* explicit calls to clutter_event_put(). We add a very simple custom
|
|
* event loop source which is simply responsible for pulling events off
|
|
* of the queue and dispatching them before we block for new events.
|
|
*/
|
|
|
|
static gboolean
|
|
clutter_source_prepare (GSource *source,
|
|
int *timeout)
|
|
{
|
|
*timeout = -1;
|
|
|
|
return clutter_events_pending ();
|
|
}
|
|
|
|
static gboolean
|
|
clutter_source_check (GSource *source)
|
|
{
|
|
return clutter_events_pending ();
|
|
}
|
|
|
|
static gboolean
|
|
clutter_source_dispatch (GSource *source,
|
|
GSourceFunc callback,
|
|
gpointer user_data)
|
|
{
|
|
MetaBackendSource *backend_source = (MetaBackendSource *) source;
|
|
ClutterEvent *event = clutter_event_get ();
|
|
|
|
if (event)
|
|
{
|
|
event->any.stage =
|
|
CLUTTER_STAGE (meta_backend_get_stage (backend_source->backend));
|
|
clutter_do_event (event);
|
|
meta_backend_update_from_event (backend_source->backend, event);
|
|
clutter_event_free (event);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static GSourceFuncs clutter_source_funcs = {
|
|
clutter_source_prepare,
|
|
clutter_source_check,
|
|
clutter_source_dispatch
|
|
};
|
|
|
|
static ClutterBackend *
|
|
meta_clutter_backend_constructor (gpointer user_data)
|
|
{
|
|
MetaBackend *backend = META_BACKEND (user_data);
|
|
|
|
return META_BACKEND_GET_CLASS (backend)->create_clutter_backend (backend);
|
|
}
|
|
|
|
static ClutterSeat *
|
|
meta_backend_create_default_seat (MetaBackend *backend,
|
|
GError **error)
|
|
{
|
|
return META_BACKEND_GET_CLASS (backend)->create_default_seat (backend, error);
|
|
}
|
|
|
|
static gboolean
|
|
init_clutter (MetaBackend *backend,
|
|
GError **error)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
MetaBackendSource *backend_source;
|
|
GSource *source;
|
|
|
|
priv->clutter_context = clutter_context_new (meta_clutter_backend_constructor,
|
|
backend,
|
|
error);
|
|
if (!priv->clutter_context)
|
|
return FALSE;
|
|
|
|
priv->default_seat = meta_backend_create_default_seat (backend, error);
|
|
if (!priv->default_seat)
|
|
return FALSE;
|
|
|
|
source = g_source_new (&clutter_source_funcs, sizeof (MetaBackendSource));
|
|
g_source_set_name (source, "[mutter] Backend");
|
|
backend_source = (MetaBackendSource *) source;
|
|
backend_source->backend = backend;
|
|
g_source_attach (source, NULL);
|
|
g_source_unref (source);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
meta_backend_post_init (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
META_BACKEND_GET_CLASS (backend)->post_init (backend);
|
|
|
|
meta_settings_post_init (priv->settings);
|
|
}
|
|
|
|
static gboolean
|
|
meta_backend_initable_init (GInitable *initable,
|
|
GCancellable *cancellable,
|
|
GError **error)
|
|
{
|
|
MetaBackend *backend = META_BACKEND (initable);
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
priv->settings = meta_settings_new (backend);
|
|
priv->orientation_manager = g_object_new (META_TYPE_ORIENTATION_MANAGER, NULL);
|
|
|
|
priv->monitor_manager = meta_backend_create_monitor_manager (backend, error);
|
|
if (!priv->monitor_manager)
|
|
return FALSE;
|
|
|
|
priv->color_manager = meta_backend_create_color_manager (backend);
|
|
|
|
priv->renderer = meta_backend_create_renderer (backend, error);
|
|
if (!priv->renderer)
|
|
return FALSE;
|
|
|
|
priv->cursor_tracker =
|
|
META_BACKEND_GET_CLASS (backend)->create_cursor_tracker (backend);
|
|
|
|
priv->dnd = meta_dnd_new (backend);
|
|
|
|
priv->cancellable = g_cancellable_new ();
|
|
g_bus_get (G_BUS_TYPE_SYSTEM,
|
|
priv->cancellable,
|
|
system_bus_gotten_cb,
|
|
backend);
|
|
|
|
if (!init_clutter (backend, error))
|
|
return FALSE;
|
|
|
|
meta_backend_post_init (backend);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
initable_iface_init (GInitableIface *initable_iface)
|
|
{
|
|
initable_iface->init = meta_backend_initable_init;
|
|
}
|
|
|
|
static void
|
|
meta_backend_init (MetaBackend *backend)
|
|
{
|
|
_backend = backend;
|
|
}
|
|
|
|
/**
|
|
* meta_backend_get_idle_monitor: (skip)
|
|
*/
|
|
MetaIdleMonitor *
|
|
meta_backend_get_idle_monitor (MetaBackend *backend,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
return meta_idle_manager_get_monitor (priv->idle_manager, device);
|
|
}
|
|
|
|
/**
|
|
* meta_backend_get_core_idle_monitor:
|
|
*
|
|
* Returns: (transfer none): the #MetaIdleMonitor that tracks server-global
|
|
* idle time for all devices.
|
|
*/
|
|
MetaIdleMonitor *
|
|
meta_backend_get_core_idle_monitor (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
return meta_idle_manager_get_core_monitor (priv->idle_manager);
|
|
}
|
|
|
|
/**
|
|
* meta_backend_get_idle_manager: (skip)
|
|
*/
|
|
MetaIdleManager *
|
|
meta_backend_get_idle_manager (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
return priv->idle_manager;
|
|
}
|
|
|
|
/**
|
|
* meta_backend_get_monitor_manager:
|
|
*
|
|
* Returns: (transfer none): A #MetaMonitorManager
|
|
*/
|
|
MetaMonitorManager *
|
|
meta_backend_get_monitor_manager (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
return priv->monitor_manager;
|
|
}
|
|
|
|
/**
|
|
* meta_backend_get_color_manager: (skip)
|
|
*/
|
|
MetaColorManager *
|
|
meta_backend_get_color_manager (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
return priv->color_manager;
|
|
}
|
|
|
|
/**
|
|
* meta_backend_get_orientation_manager: (skip)
|
|
*/
|
|
MetaOrientationManager *
|
|
meta_backend_get_orientation_manager (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
return priv->orientation_manager;
|
|
}
|
|
|
|
MetaCursorTracker *
|
|
meta_backend_get_cursor_tracker (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
return priv->cursor_tracker;
|
|
}
|
|
|
|
/**
|
|
* meta_backend_get_cursor_renderer: (skip)
|
|
*/
|
|
MetaCursorRenderer *
|
|
meta_backend_get_cursor_renderer (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
ClutterInputDevice *pointer;
|
|
|
|
if (!priv->default_seat)
|
|
return NULL;
|
|
|
|
pointer = clutter_seat_get_pointer (priv->default_seat);
|
|
|
|
return meta_backend_get_cursor_renderer_for_device (backend, pointer);
|
|
}
|
|
|
|
MetaCursorRenderer *
|
|
meta_backend_get_cursor_renderer_for_device (MetaBackend *backend,
|
|
ClutterInputDevice *device)
|
|
{
|
|
g_return_val_if_fail (META_IS_BACKEND (backend), NULL);
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
|
|
g_return_val_if_fail (clutter_input_device_get_device_type (device) !=
|
|
CLUTTER_KEYBOARD_DEVICE, NULL);
|
|
|
|
return META_BACKEND_GET_CLASS (backend)->get_cursor_renderer (backend,
|
|
device);
|
|
}
|
|
|
|
/**
|
|
* meta_backend_get_renderer: (skip)
|
|
*/
|
|
MetaRenderer *
|
|
meta_backend_get_renderer (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
return priv->renderer;
|
|
}
|
|
|
|
#ifdef HAVE_EGL
|
|
/**
|
|
* meta_backend_get_egl: (skip)
|
|
*/
|
|
MetaEgl *
|
|
meta_backend_get_egl (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
return priv->egl;
|
|
}
|
|
#endif /* HAVE_EGL */
|
|
|
|
/**
|
|
* meta_backend_get_settings: (skip)
|
|
*/
|
|
MetaSettings *
|
|
meta_backend_get_settings (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
return priv->settings;
|
|
}
|
|
|
|
#ifdef HAVE_REMOTE_DESKTOP
|
|
/**
|
|
* meta_backend_get_remote_desktop: (skip)
|
|
*/
|
|
MetaRemoteDesktop *
|
|
meta_backend_get_remote_desktop (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
return priv->remote_desktop;
|
|
}
|
|
|
|
/**
|
|
* meta_backend_get_screen_cast: (skip)
|
|
*/
|
|
MetaScreenCast *
|
|
meta_backend_get_screen_cast (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
return priv->screen_cast;
|
|
}
|
|
#endif /* HAVE_REMOTE_DESKTOP */
|
|
|
|
/**
|
|
* meta_backend_get_remote_access_controller:
|
|
* @backend: A #MetaBackend
|
|
*
|
|
* Return Value: (transfer none): The #MetaRemoteAccessController
|
|
*/
|
|
MetaRemoteAccessController *
|
|
meta_backend_get_remote_access_controller (MetaBackend *backend)
|
|
{
|
|
#ifdef HAVE_REMOTE_DESKTOP
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
return priv->remote_access_controller;
|
|
#else
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* meta_backend_is_rendering_hardware_accelerated:
|
|
* @backend: A #MetaBackend
|
|
*
|
|
* Returns: %TRUE if the rendering is hardware accelerated, otherwise
|
|
* %FALSE.
|
|
*/
|
|
gboolean
|
|
meta_backend_is_rendering_hardware_accelerated (MetaBackend *backend)
|
|
{
|
|
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
|
|
|
return meta_renderer_is_hardware_accelerated (renderer);
|
|
}
|
|
|
|
/**
|
|
* meta_backend_grab_device: (skip)
|
|
*/
|
|
gboolean
|
|
meta_backend_grab_device (MetaBackend *backend,
|
|
int device_id,
|
|
uint32_t timestamp)
|
|
{
|
|
return META_BACKEND_GET_CLASS (backend)->grab_device (backend, device_id, timestamp);
|
|
}
|
|
|
|
/**
|
|
* meta_backend_get_context:
|
|
* @backend: the #MetaBackend
|
|
*
|
|
* Returns: (transfer none): The #MetaContext
|
|
*/
|
|
MetaContext *
|
|
meta_backend_get_context (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
return priv->context;
|
|
}
|
|
|
|
/**
|
|
* meta_backend_ungrab_device: (skip)
|
|
*/
|
|
gboolean
|
|
meta_backend_ungrab_device (MetaBackend *backend,
|
|
int device_id,
|
|
uint32_t timestamp)
|
|
{
|
|
return META_BACKEND_GET_CLASS (backend)->ungrab_device (backend, device_id, timestamp);
|
|
}
|
|
|
|
/**
|
|
* meta_backend_finish_touch_sequence: (skip)
|
|
*/
|
|
void
|
|
meta_backend_finish_touch_sequence (MetaBackend *backend,
|
|
ClutterEventSequence *sequence,
|
|
MetaSequenceState state)
|
|
{
|
|
if (META_BACKEND_GET_CLASS (backend)->finish_touch_sequence)
|
|
META_BACKEND_GET_CLASS (backend)->finish_touch_sequence (backend,
|
|
sequence,
|
|
state);
|
|
}
|
|
|
|
MetaLogicalMonitor *
|
|
meta_backend_get_current_logical_monitor (MetaBackend *backend)
|
|
{
|
|
return META_BACKEND_GET_CLASS (backend)->get_current_logical_monitor (backend);
|
|
}
|
|
|
|
void
|
|
meta_backend_set_keymap (MetaBackend *backend,
|
|
const char *layouts,
|
|
const char *variants,
|
|
const char *options)
|
|
{
|
|
META_BACKEND_GET_CLASS (backend)->set_keymap (backend, layouts, variants, options);
|
|
}
|
|
|
|
/**
|
|
* meta_backend_get_keymap: (skip)
|
|
*/
|
|
struct xkb_keymap *
|
|
meta_backend_get_keymap (MetaBackend *backend)
|
|
|
|
{
|
|
return META_BACKEND_GET_CLASS (backend)->get_keymap (backend);
|
|
}
|
|
|
|
xkb_layout_index_t
|
|
meta_backend_get_keymap_layout_group (MetaBackend *backend)
|
|
{
|
|
return META_BACKEND_GET_CLASS (backend)->get_keymap_layout_group (backend);
|
|
}
|
|
|
|
void
|
|
meta_backend_lock_layout_group (MetaBackend *backend,
|
|
guint idx)
|
|
{
|
|
META_BACKEND_GET_CLASS (backend)->lock_layout_group (backend, idx);
|
|
}
|
|
|
|
/**
|
|
* meta_backend_get_stage:
|
|
* @backend: A #MetaBackend
|
|
*
|
|
* Gets the global #ClutterStage that's managed by this backend.
|
|
*
|
|
* Returns: (transfer none): the #ClutterStage
|
|
*/
|
|
ClutterActor *
|
|
meta_backend_get_stage (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
return priv->stage;
|
|
}
|
|
|
|
ClutterSeat *
|
|
meta_backend_get_default_seat (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
return priv->default_seat;
|
|
}
|
|
|
|
MetaPointerConstraint *
|
|
meta_backend_get_client_pointer_constraint (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
return priv->client_pointer_constraint;
|
|
}
|
|
|
|
/**
|
|
* meta_backend_set_client_pointer_constraint:
|
|
* @backend: a #MetaBackend object.
|
|
* @constraint: (nullable): the client constraint to follow.
|
|
*
|
|
* Sets the current pointer constraint and removes (and unrefs) the previous
|
|
* one. If @constraint is %NULL, this means that there is no
|
|
* #MetaPointerConstraint active.
|
|
*/
|
|
void
|
|
meta_backend_set_client_pointer_constraint (MetaBackend *backend,
|
|
MetaPointerConstraint *constraint)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
META_BACKEND_GET_CLASS (backend)->set_pointer_constraint (backend, constraint);
|
|
g_set_object (&priv->client_pointer_constraint, constraint);
|
|
}
|
|
|
|
ClutterBackend *
|
|
meta_backend_get_clutter_backend (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
ClutterContext *clutter_context;
|
|
|
|
clutter_context = priv->clutter_context;
|
|
if (!clutter_context)
|
|
return NULL;
|
|
|
|
return clutter_context_get_backend (clutter_context);
|
|
}
|
|
|
|
MetaBackendCapabilities
|
|
meta_backend_get_capabilities (MetaBackend *backend)
|
|
{
|
|
return META_BACKEND_GET_CLASS (backend)->get_capabilities (backend);
|
|
}
|
|
|
|
gboolean
|
|
meta_backend_is_stage_views_scaled (MetaBackend *backend)
|
|
{
|
|
MetaMonitorManager *monitor_manager =
|
|
meta_backend_get_monitor_manager (backend);
|
|
MetaLogicalMonitorLayoutMode layout_mode;
|
|
|
|
layout_mode = monitor_manager->layout_mode;
|
|
|
|
return layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL;
|
|
}
|
|
|
|
MetaInputMapper *
|
|
meta_backend_get_input_mapper (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
return priv->input_mapper;
|
|
}
|
|
|
|
MetaInputSettings *
|
|
meta_backend_get_input_settings (MetaBackend *backend)
|
|
{
|
|
return META_BACKEND_GET_CLASS (backend)->get_input_settings (backend);
|
|
}
|
|
|
|
/**
|
|
* meta_backend_get_dnd:
|
|
* @backend: A #MetaDnd
|
|
*
|
|
* Gets the global #MetaDnd that's managed by this backend.
|
|
*
|
|
* Returns: (transfer none): the #MetaDnd
|
|
*/
|
|
MetaDnd *
|
|
meta_backend_get_dnd (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
return priv->dnd;
|
|
}
|
|
|
|
void
|
|
meta_backend_notify_keymap_changed (MetaBackend *backend)
|
|
{
|
|
g_signal_emit (backend, signals[KEYMAP_CHANGED], 0);
|
|
}
|
|
|
|
void
|
|
meta_backend_notify_keymap_layout_group_changed (MetaBackend *backend,
|
|
unsigned int locked_group)
|
|
{
|
|
g_signal_emit (backend, signals[KEYMAP_LAYOUT_GROUP_CHANGED], 0,
|
|
locked_group);
|
|
}
|
|
|
|
void
|
|
meta_backend_add_gpu (MetaBackend *backend,
|
|
MetaGpu *gpu)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
priv->gpus = g_list_append (priv->gpus, gpu);
|
|
|
|
g_signal_emit (backend, signals[GPU_ADDED], 0, gpu);
|
|
}
|
|
|
|
GList *
|
|
meta_backend_get_gpus (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
return priv->gpus;
|
|
}
|
|
|
|
#ifdef HAVE_LIBWACOM
|
|
WacomDeviceDatabase *
|
|
meta_backend_get_wacom_database (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
return priv->wacom_db;
|
|
}
|
|
#endif
|
|
|
|
void
|
|
meta_backend_add_hw_cursor_inhibitor (MetaBackend *backend,
|
|
MetaHwCursorInhibitor *inhibitor)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
priv->hw_cursor_inhibitors = g_list_prepend (priv->hw_cursor_inhibitors,
|
|
inhibitor);
|
|
}
|
|
|
|
void
|
|
meta_backend_remove_hw_cursor_inhibitor (MetaBackend *backend,
|
|
MetaHwCursorInhibitor *inhibitor)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
priv->hw_cursor_inhibitors = g_list_remove (priv->hw_cursor_inhibitors,
|
|
inhibitor);
|
|
}
|
|
|
|
gboolean
|
|
meta_backend_is_hw_cursors_inhibited (MetaBackend *backend)
|
|
{
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
GList *l;
|
|
|
|
for (l = priv->hw_cursor_inhibitors; l; l = l->next)
|
|
{
|
|
MetaHwCursorInhibitor *inhibitor = l->data;
|
|
|
|
if (meta_hw_cursor_inhibitor_is_cursor_inhibited (inhibitor))
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
meta_backend_update_from_event (MetaBackend *backend,
|
|
ClutterEvent *event)
|
|
{
|
|
update_last_device_from_event (backend, event);
|
|
update_pointer_visibility_from_event (backend, event);
|
|
}
|
|
|
|
/**
|
|
* meta_backend_get_vendor_name:
|
|
* @backend: A #MetaBackend object
|
|
* @pnp_id: the PNP ID
|
|
*
|
|
* Find the full vendor name from the given PNP ID.
|
|
*
|
|
* Returns: (transfer full): A string containing the vendor name,
|
|
* or NULL when not found.
|
|
*/
|
|
char *
|
|
meta_backend_get_vendor_name (MetaBackend *backend,
|
|
const char *pnp_id)
|
|
{
|
|
#ifdef HAVE_GNOME_DESKTOP
|
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
|
|
if (!priv->pnp_ids)
|
|
priv->pnp_ids = gnome_pnp_ids_new ();
|
|
|
|
return gnome_pnp_ids_get_pnp_id (priv->pnp_ids, pnp_id);
|
|
#else
|
|
return g_strdup (pnp_id);
|
|
#endif
|
|
}
|