c390f70edc
This means objects have an owner, where the chain eventually always leads to a MetaContext. This also means that all objects can find their way to other object instances via the chain, instead of scattered global singletons. This is a squashed commit originally containing the following: cursor-tracker: Don't get backend from singleton idle-manager: Don't get backend from singleton input-device: Pass pointer to backend during construction The backend is needed during construction to get the wacom database. input-mapper: Pass backend when constructing monitor: Don't get backend from singleton monitor-manager: Get backend directly from monitor manager remote: Get backend from manager class For the remote desktop and screen cast implementations, replace getting the backend from singletons with getting it via the manager classes. launcher: Pass backend during construction device-pool: Pass backend during construction Instead of passing the (maybe null) launcher, pass the backend, and get the launcher from there. That way we always have a way to some known context from the device pool. drm-buffer/gbm: Get backend via device pool cursor-renderer: Get backend directly from renderer input-device: Get backend getter input-settings: Add backend construct property and getter input-settings/x11: Don't get backend from singleton renderer: Get backend from renderer itself seat-impl: Add backend getter seat/native: Get backend from instance struct stage-impl: Get backend from stage impl itself x11/xkb-a11y: Don't get backend from singleton backend/x11/nested: Don't get Wayland compositor from singleton crtc: Add backend property Adding a link to the GPU isn't enough; the virtual CRTCs of virtual monitors doesn't have one. cursor-tracker: Don't get display from singleton remote: Don't get display from singleton seat: Don't get display from singleton backend/x11: Don't get display from singleton Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2718>
380 lines
12 KiB
C
380 lines
12 KiB
C
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
/*
|
|
* Copyright 2013-2021 Red Hat, Inc.
|
|
*
|
|
* 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, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
|
|
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "backends/meta-idle-manager.h"
|
|
|
|
#include "backends/meta-idle-monitor-private.h"
|
|
#include "clutter/clutter.h"
|
|
#include "meta/main.h"
|
|
#include "meta/meta-context.h"
|
|
#include "meta/meta-idle-monitor.h"
|
|
#include "meta/util.h"
|
|
|
|
#include "meta-dbus-idle-monitor.h"
|
|
|
|
typedef struct _MetaIdleManager
|
|
{
|
|
MetaBackend *backend;
|
|
guint dbus_name_id;
|
|
|
|
GHashTable *device_monitors;
|
|
} MetaIdleManager;
|
|
|
|
static gboolean
|
|
handle_get_idletime (MetaDBusIdleMonitor *skeleton,
|
|
GDBusMethodInvocation *invocation,
|
|
MetaIdleMonitor *monitor)
|
|
{
|
|
guint64 idletime;
|
|
|
|
idletime = meta_idle_monitor_get_idletime (monitor);
|
|
meta_dbus_idle_monitor_complete_get_idletime (skeleton, invocation, idletime);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
handle_reset_idletime (MetaDBusIdleMonitor *skeleton,
|
|
GDBusMethodInvocation *invocation,
|
|
MetaIdleMonitor *monitor)
|
|
{
|
|
if (!g_getenv ("MUTTER_DEBUG_RESET_IDLETIME"))
|
|
{
|
|
g_dbus_method_invocation_return_error_literal (invocation,
|
|
G_DBUS_ERROR,
|
|
G_DBUS_ERROR_UNKNOWN_METHOD,
|
|
"This method is for testing purposes only. MUTTER_DEBUG_RESET_IDLETIME must be set to use it");
|
|
return TRUE;
|
|
}
|
|
|
|
meta_idle_manager_reset_idle_time (meta_idle_monitor_get_manager (monitor));
|
|
meta_dbus_idle_monitor_complete_reset_idletime (skeleton, invocation);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
typedef struct {
|
|
MetaDBusIdleMonitor *dbus_monitor;
|
|
MetaIdleMonitor *monitor;
|
|
char *dbus_name;
|
|
guint watch_id;
|
|
guint name_watcher_id;
|
|
} DBusWatch;
|
|
|
|
static void
|
|
destroy_dbus_watch (gpointer data)
|
|
{
|
|
DBusWatch *watch = data;
|
|
|
|
g_object_unref (watch->dbus_monitor);
|
|
g_object_unref (watch->monitor);
|
|
g_free (watch->dbus_name);
|
|
g_bus_unwatch_name (watch->name_watcher_id);
|
|
|
|
g_free (watch);
|
|
}
|
|
|
|
static void
|
|
dbus_idle_callback (MetaIdleMonitor *monitor,
|
|
guint watch_id,
|
|
gpointer user_data)
|
|
{
|
|
DBusWatch *watch = user_data;
|
|
GDBusInterfaceSkeleton *skeleton = G_DBUS_INTERFACE_SKELETON (watch->dbus_monitor);
|
|
|
|
g_dbus_connection_emit_signal (g_dbus_interface_skeleton_get_connection (skeleton),
|
|
watch->dbus_name,
|
|
g_dbus_interface_skeleton_get_object_path (skeleton),
|
|
"org.gnome.Mutter.IdleMonitor",
|
|
"WatchFired",
|
|
g_variant_new ("(u)", watch_id),
|
|
NULL);
|
|
}
|
|
|
|
static void
|
|
name_vanished_callback (GDBusConnection *connection,
|
|
const char *name,
|
|
gpointer user_data)
|
|
{
|
|
DBusWatch *watch = user_data;
|
|
|
|
meta_idle_monitor_remove_watch (watch->monitor, watch->watch_id);
|
|
}
|
|
|
|
static DBusWatch *
|
|
make_dbus_watch (MetaDBusIdleMonitor *skeleton,
|
|
GDBusMethodInvocation *invocation,
|
|
MetaIdleMonitor *monitor)
|
|
{
|
|
DBusWatch *watch;
|
|
|
|
watch = g_new0 (DBusWatch, 1);
|
|
watch->dbus_monitor = g_object_ref (skeleton);
|
|
watch->monitor = g_object_ref (monitor);
|
|
watch->dbus_name = g_strdup (g_dbus_method_invocation_get_sender (invocation));
|
|
watch->name_watcher_id = g_bus_watch_name_on_connection (g_dbus_method_invocation_get_connection (invocation),
|
|
watch->dbus_name,
|
|
G_BUS_NAME_WATCHER_FLAGS_NONE,
|
|
NULL, /* appeared */
|
|
name_vanished_callback,
|
|
watch, NULL);
|
|
|
|
return watch;
|
|
}
|
|
|
|
static gboolean
|
|
handle_add_idle_watch (MetaDBusIdleMonitor *skeleton,
|
|
GDBusMethodInvocation *invocation,
|
|
guint64 interval,
|
|
MetaIdleMonitor *monitor)
|
|
{
|
|
DBusWatch *watch;
|
|
|
|
watch = make_dbus_watch (skeleton, invocation, monitor);
|
|
watch->watch_id = meta_idle_monitor_add_idle_watch (monitor, interval,
|
|
dbus_idle_callback, watch, destroy_dbus_watch);
|
|
|
|
meta_dbus_idle_monitor_complete_add_idle_watch (skeleton, invocation, watch->watch_id);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
handle_add_user_active_watch (MetaDBusIdleMonitor *skeleton,
|
|
GDBusMethodInvocation *invocation,
|
|
MetaIdleMonitor *monitor)
|
|
{
|
|
DBusWatch *watch;
|
|
|
|
watch = make_dbus_watch (skeleton, invocation, monitor);
|
|
watch->watch_id = meta_idle_monitor_add_user_active_watch (monitor,
|
|
dbus_idle_callback, watch,
|
|
destroy_dbus_watch);
|
|
|
|
meta_dbus_idle_monitor_complete_add_user_active_watch (skeleton, invocation, watch->watch_id);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
handle_remove_watch (MetaDBusIdleMonitor *skeleton,
|
|
GDBusMethodInvocation *invocation,
|
|
guint id,
|
|
MetaIdleMonitor *monitor)
|
|
{
|
|
meta_idle_monitor_remove_watch (monitor, id);
|
|
meta_dbus_idle_monitor_complete_remove_watch (skeleton, invocation);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
create_monitor_skeleton (GDBusObjectManagerServer *manager,
|
|
MetaIdleMonitor *monitor,
|
|
const char *path)
|
|
{
|
|
MetaDBusIdleMonitor *skeleton;
|
|
MetaDBusObjectSkeleton *object;
|
|
|
|
skeleton = meta_dbus_idle_monitor_skeleton_new ();
|
|
g_signal_connect (skeleton, "handle-add-idle-watch",
|
|
G_CALLBACK (handle_add_idle_watch), monitor);
|
|
g_signal_connect (skeleton, "handle-add-user-active-watch",
|
|
G_CALLBACK (handle_add_user_active_watch), monitor);
|
|
g_signal_connect (skeleton, "handle-remove-watch",
|
|
G_CALLBACK (handle_remove_watch), monitor);
|
|
g_signal_connect (skeleton, "handle-reset-idletime",
|
|
G_CALLBACK (handle_reset_idletime), monitor);
|
|
g_signal_connect (skeleton, "handle-get-idletime",
|
|
G_CALLBACK (handle_get_idletime), monitor);
|
|
|
|
object = meta_dbus_object_skeleton_new (path);
|
|
meta_dbus_object_skeleton_set_idle_monitor (object, skeleton);
|
|
|
|
g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object));
|
|
|
|
g_object_unref (skeleton);
|
|
g_object_unref (object);
|
|
}
|
|
|
|
static void
|
|
on_bus_acquired (GDBusConnection *connection,
|
|
const char *name,
|
|
gpointer user_data)
|
|
{
|
|
MetaIdleManager *manager = user_data;
|
|
GDBusObjectManagerServer *object_manager;
|
|
MetaIdleMonitor *monitor;
|
|
char *path;
|
|
|
|
object_manager = g_dbus_object_manager_server_new ("/org/gnome/Mutter/IdleMonitor");
|
|
|
|
/* We never clear the core monitor, as that's supposed to cumulate idle times from
|
|
all devices */
|
|
monitor = meta_idle_manager_get_core_monitor (manager);
|
|
path = g_strdup ("/org/gnome/Mutter/IdleMonitor/Core");
|
|
create_monitor_skeleton (object_manager, monitor, path);
|
|
g_free (path);
|
|
|
|
g_dbus_object_manager_server_set_connection (object_manager, connection);
|
|
}
|
|
|
|
static void
|
|
on_name_acquired (GDBusConnection *connection,
|
|
const char *name,
|
|
gpointer user_data)
|
|
{
|
|
meta_verbose ("Acquired name %s", name);
|
|
}
|
|
|
|
static void
|
|
on_name_lost (GDBusConnection *connection,
|
|
const char *name,
|
|
gpointer user_data)
|
|
{
|
|
meta_verbose ("Lost or failed to acquire name %s", name);
|
|
}
|
|
|
|
MetaIdleMonitor *
|
|
meta_idle_manager_get_monitor (MetaIdleManager *idle_manager,
|
|
ClutterInputDevice *device)
|
|
{
|
|
return g_hash_table_lookup (idle_manager->device_monitors, device);
|
|
}
|
|
|
|
MetaIdleMonitor *
|
|
meta_idle_manager_get_core_monitor (MetaIdleManager *idle_manager)
|
|
{
|
|
MetaBackend *backend = idle_manager->backend;
|
|
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
|
ClutterSeat *seat = clutter_backend_get_default_seat (clutter_backend);
|
|
|
|
return meta_backend_get_idle_monitor (backend,
|
|
clutter_seat_get_pointer (seat));
|
|
}
|
|
|
|
void
|
|
meta_idle_manager_reset_idle_time (MetaIdleManager *idle_manager)
|
|
{
|
|
MetaIdleMonitor *core_monitor;
|
|
|
|
core_monitor = meta_idle_manager_get_core_monitor (idle_manager);
|
|
meta_idle_monitor_reset_idletime (core_monitor);
|
|
}
|
|
|
|
static void
|
|
create_device_monitor (MetaIdleManager *idle_manager,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaIdleMonitor *idle_monitor;
|
|
|
|
if (g_hash_table_contains (idle_manager->device_monitors, device))
|
|
return;
|
|
|
|
idle_monitor = meta_idle_monitor_new (idle_manager, device);
|
|
g_hash_table_insert (idle_manager->device_monitors, device, idle_monitor);
|
|
}
|
|
|
|
static void
|
|
on_device_added (ClutterSeat *seat,
|
|
ClutterInputDevice *device,
|
|
gpointer user_data)
|
|
{
|
|
MetaIdleManager *idle_manager = user_data;
|
|
|
|
create_device_monitor (idle_manager, device);
|
|
}
|
|
|
|
static void
|
|
on_device_removed (ClutterSeat *seat,
|
|
ClutterInputDevice *device,
|
|
gpointer user_data)
|
|
{
|
|
MetaIdleManager *idle_manager = user_data;
|
|
|
|
g_hash_table_remove (idle_manager->device_monitors, device);
|
|
}
|
|
|
|
static void
|
|
create_device_monitors (MetaIdleManager *idle_manager,
|
|
ClutterSeat *seat)
|
|
{
|
|
GList *l, *devices;
|
|
|
|
create_device_monitor (idle_manager, clutter_seat_get_pointer (seat));
|
|
create_device_monitor (idle_manager, clutter_seat_get_keyboard (seat));
|
|
|
|
devices = clutter_seat_list_devices (seat);
|
|
for (l = devices; l; l = l->next)
|
|
{
|
|
ClutterInputDevice *device = l->data;
|
|
|
|
create_device_monitor (idle_manager, device);
|
|
}
|
|
|
|
g_list_free (devices);
|
|
}
|
|
|
|
MetaIdleManager *
|
|
meta_idle_manager_new (MetaBackend *backend)
|
|
{
|
|
MetaContext *context = meta_backend_get_context (backend);
|
|
ClutterSeat *seat = meta_backend_get_default_seat (backend);
|
|
MetaIdleManager *idle_manager;
|
|
|
|
idle_manager = g_new0 (MetaIdleManager, 1);
|
|
idle_manager->backend = backend;
|
|
|
|
idle_manager->dbus_name_id =
|
|
g_bus_own_name (G_BUS_TYPE_SESSION,
|
|
"org.gnome.Mutter.IdleMonitor",
|
|
G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
|
|
(meta_context_is_replacing (context) ?
|
|
G_BUS_NAME_OWNER_FLAGS_REPLACE :
|
|
G_BUS_NAME_OWNER_FLAGS_NONE),
|
|
on_bus_acquired,
|
|
on_name_acquired,
|
|
on_name_lost,
|
|
idle_manager,
|
|
NULL);
|
|
|
|
idle_manager->device_monitors =
|
|
g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_object_unref);
|
|
g_signal_connect (seat, "device-added",
|
|
G_CALLBACK (on_device_added), idle_manager);
|
|
g_signal_connect_after (seat, "device-removed",
|
|
G_CALLBACK (on_device_removed), idle_manager);
|
|
create_device_monitors (idle_manager, seat);
|
|
|
|
return idle_manager;
|
|
}
|
|
|
|
void
|
|
meta_idle_manager_free (MetaIdleManager *idle_manager)
|
|
{
|
|
g_clear_pointer (&idle_manager->device_monitors, g_hash_table_destroy);
|
|
g_bus_unown_name (idle_manager->dbus_name_id);
|
|
g_free (idle_manager);
|
|
}
|