18d670e69f
This object takes over the functionality of meta-idle-monitor-dbus.c, meta-idle-monitor.c and meta-backend.c, all related to higher level management of idle watches etc. The idle D-Bus API is changed to be initialized by the backend instead of MetaDisplay, as it's more of a backend functionality than what MetaDisplay usually deals with. It also takes over the work of implementing "core" idle monitors. The singleton API is replaced with thin wrapper functions on the backend. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1859>
377 lines
12 KiB
C
377 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-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 = meta_get_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)
|
|
{
|
|
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_get_replace_current_wm () ?
|
|
G_BUS_NAME_OWNER_FLAGS_REPLACE : 0),
|
|
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);
|
|
}
|