diff options
Diffstat (limited to 'src/backends/meta-backend.c')
-rw-r--r-- | src/backends/meta-backend.c | 1663 |
1 files changed, 0 insertions, 1663 deletions
diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c deleted file mode 100644 index d4cd5d10f..000000000 --- a/src/backends/meta-backend.c +++ /dev/null @@ -1,1663 +0,0 @@ -/* -*- 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-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 "core/meta-context-private.h" -#include "meta/main.h" -#include "meta/meta-backend.h" -#include "meta/meta-context.h" -#include "meta/util.h" - -#ifdef HAVE_PROFILER -#include "backends/meta-profiler.h" -#endif - -#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, - - 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; - -static gboolean stage_views_disabled = FALSE; - -/** - * 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; -#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_PROFILER - MetaProfiler *profiler; -#endif - -#ifdef HAVE_LIBWACOM - WacomDeviceDatabase *wacom_db; -#endif - - ClutterBackend *clutter_backend; - 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; - - guint sleep_signal_id; - GCancellable *cancellable; - GDBusConnection *system_bus; -}; -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->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 - - 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); - -#ifdef HAVE_PROFILER - g_clear_object (&priv->profiler); -#endif - - g_clear_pointer (&priv->default_seat, clutter_seat_destroy); - g_clear_pointer (&priv->stage, clutter_actor_destroy); - g_clear_pointer (&priv->clutter_backend, clutter_backend_destroy); - g_clear_pointer (&priv->idle_manager, meta_idle_manager_free); - g_clear_object (&priv->renderer); - 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 = clutter_backend_get_default_seat (priv->clutter_backend); - 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 = clutter_backend_get_default_seat (priv->clutter_backend); - 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) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - ClutterSeat *seat = clutter_backend_get_default_seat (priv->clutter_backend); - ClutterInputDevice *device = clutter_seat_get_pointer (seat); - graphene_point_t point; - - meta_backend_sync_screen_size (backend); - - if (clutter_seat_query_state (seat, device, NULL, &point, NULL)) - { - /* If we're outside all monitors, warp the pointer back inside */ - if ((!meta_monitor_manager_get_logical_monitor_at (monitor_manager, - point.x, point.y) || - !priv->is_pointer_position_initialized) && - !meta_monitor_manager_is_headless (monitor_manager)) - { - reset_pointer_position (backend); - priv->is_pointer_position_initialized = TRUE; - } - } - - update_cursors (backend); -} - -static inline gboolean -check_has_pointing_device (ClutterSeat *seat) -{ - GList *l, *devices; - gboolean found = FALSE; - - devices = clutter_seat_list_devices (seat); - - for (l = devices; l; l = l->next) - { - ClutterInputDevice *device = l->data; - - if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_LOGICAL) - continue; - if (clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE || - clutter_input_device_get_device_type (device) == CLUTTER_KEYBOARD_DEVICE) - continue; - - found = TRUE; - break; - } - - g_list_free (devices); - - return found; -} - -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) - meta_cursor_tracker_set_pointer_visible (priv->cursor_tracker, FALSE); - else if (device_type == CLUTTER_POINTER_DEVICE && - !clutter_seat_has_touchscreen (seat)) - meta_cursor_tracker_set_pointer_visible (priv->cursor_tracker, TRUE); - - 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; - gboolean has_touchscreen, has_pointing_device; - ClutterInputDeviceType device_type; - - g_clear_object (&priv->current_device); - g_clear_handle_id (&priv->device_update_idle_id, g_source_remove); - - device_type = clutter_input_device_get_device_type (device); - has_touchscreen = clutter_seat_has_touchscreen (seat); - - if (device_type == CLUTTER_TOUCHSCREEN_DEVICE && has_touchscreen) - { - /* There's more touchscreens left, keep the pointer hidden */ - meta_cursor_tracker_set_pointer_visible (cursor_tracker, FALSE); - } - else if (device_type != CLUTTER_KEYBOARD_DEVICE) - { - has_pointing_device = check_has_pointing_device (seat); - meta_cursor_tracker_set_pointer_visible (cursor_tracker, - has_pointing_device && - !has_touchscreen); - } - } - - 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_stage_shown_cb (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - ClutterSeat *seat = clutter_backend_get_default_seat (priv->clutter_backend); - g_autoptr (GList) devices = NULL; - const GList *l; - - devices = clutter_seat_list_devices (seat); - for (l = devices; l; l = l->next) - { - ClutterInputDevice *device = l->data; - - if (clutter_input_device_get_device_mode (device) == - CLUTTER_INPUT_MODE_LOGICAL) - continue; - - if (clutter_input_device_get_device_type (device) != - CLUTTER_POINTER_DEVICE) - continue; - - meta_cursor_tracker_set_pointer_visible (priv->cursor_tracker, TRUE); - break; - } -} - -static void -meta_backend_real_post_init (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - ClutterSeat *seat = clutter_backend_get_default_seat (priv->clutter_backend); - MetaInputSettings *input_settings; - - priv->stage = meta_stage_new (backend); - clutter_actor_realize (priv->stage); - META_BACKEND_GET_CLASS (backend)->select_stage_events (backend); - g_signal_connect_object (priv->stage, "show", - G_CALLBACK (on_stage_shown_cb), backend, - G_CONNECT_SWAPPED); - - 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 (); - - 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); -} - -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); -} - -gboolean -meta_backend_is_lid_closed (MetaBackend *backend) -{ - return META_BACKEND_GET_CLASS (backend)->is_lid_closed (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 lid_is_closed; - - v = g_variant_lookup_value (changed_properties, - "LidIsClosed", - G_VARIANT_TYPE_BOOLEAN); - if (!v) - return; - - lid_is_closed = g_variant_get_boolean (v); - g_variant_unref (v); - - if (lid_is_closed == priv->lid_is_closed) - return; - - 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) - return; - - 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) - return; - 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); - } -} - -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) - return; - - 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); -} - -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; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_backend_class_init (MetaBackendClass *klass) -{ - const gchar *mutter_stage_views; - 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; - - 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); - 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); - - mutter_stage_views = g_getenv ("MUTTER_STAGE_VIEWS"); - stage_views_disabled = g_strcmp0 (mutter_stage_views, "0") == 0; -} - -static MetaMonitorManager * -meta_backend_create_monitor_manager (MetaBackend *backend, - GError **error) -{ - return META_BACKEND_GET_CLASS (backend)->create_monitor_manager (backend, - error); -} - -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); -} - -/* 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); - clutter_event_free (event); - } - - return TRUE; -} - -static GSourceFuncs clutter_source_funcs = { - clutter_source_prepare, - clutter_source_check, - clutter_source_dispatch -}; - -static ClutterBackend * -meta_get_clutter_backend (void) -{ - MetaBackend *backend = meta_get_backend (); - - return meta_backend_get_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; - - clutter_set_custom_backend_func (meta_get_clutter_backend); - - if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Unable to initialize Clutter"); - 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)); - 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); - -#ifdef HAVE_EGL - priv->egl = g_object_new (META_TYPE_EGL, NULL); -#endif - - 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->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 = g_object_new (META_TYPE_DND, NULL); - - priv->cancellable = g_cancellable_new (); - g_bus_get (G_BUS_TYPE_SYSTEM, - priv->cancellable, - system_bus_gotten_cb, - backend); - -#ifdef HAVE_PROFILER - priv->profiler = meta_profiler_new (); -#endif - - 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: (skip) - */ -MetaMonitorManager * -meta_backend_get_monitor_manager (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - return priv->monitor_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; - ClutterSeat *seat; - - seat = clutter_backend_get_default_seat (priv->clutter_backend); - pointer = clutter_seat_get_pointer (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; -} - -static gboolean -update_last_device (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - MetaCursorTracker *cursor_tracker = priv->cursor_tracker; - ClutterInputDeviceType device_type; - - priv->device_update_idle_id = 0; - device_type = clutter_input_device_get_device_type (priv->current_device); - - g_signal_emit (backend, signals[LAST_DEVICE_CHANGED], 0, - priv->current_device); - - switch (device_type) - { - case CLUTTER_KEYBOARD_DEVICE: - break; - case CLUTTER_TOUCHSCREEN_DEVICE: - meta_cursor_tracker_set_pointer_visible (cursor_tracker, FALSE); - break; - default: - meta_cursor_tracker_set_pointer_visible (cursor_tracker, TRUE); - break; - } - - return G_SOURCE_REMOVE; -} - -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"); - } -} - -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); - - if (!priv->clutter_backend) - { - priv->clutter_backend = - META_BACKEND_GET_CLASS (backend)->create_clutter_backend (backend); - } - - return priv->clutter_backend; -} - -void -meta_backend_prepare_shutdown (MetaBackend *backend) -{ - g_signal_emit (backend, signals[PREPARE_SHUTDOWN], 0); -} - -/** - * meta_is_stage_views_enabled: - * - * Returns whether the #ClutterStage can be rendered using multiple stage views. - * In practice, this means we can define a separate framebuffer for each - * #MetaLogicalMonitor, rather than rendering everything into a single - * framebuffer. For example: in X11, onle one single framebuffer is allowed. - */ -gboolean -meta_is_stage_views_enabled (void) -{ - if (!meta_is_wayland_compositor ()) - return FALSE; - - return !stage_views_disabled; -} - -gboolean -meta_is_stage_views_scaled (void) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaLogicalMonitorLayoutMode layout_mode; - - if (!meta_is_stage_views_enabled ()) - return FALSE; - - 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; -} |