From a67c12e873bb008c35970ed7ed063e7517db708e Mon Sep 17 00:00:00 2001 From: Giovanni Campagna Date: Wed, 14 Aug 2013 13:51:05 +0200 Subject: [PATCH] MetaIdleMonitor: add a DBus interface for the idle monitor To allow other clients (gnome-session, gnome-settings-daemon) to monitor user activity, introduce a DBus interface for the idle monitor inside mutter. https://bugzilla.gnome.org/show_bug.cgi?id=706005 --- src/Makefile.am | 13 +- src/core/meta-idle-monitor-private.h | 1 + src/core/meta-idle-monitor.c | 230 +++++++++++++++++++++++++++ src/core/screen.c | 2 + src/wayland/meta-wayland.c | 2 + 5 files changed, 247 insertions(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 024de06ce..48fe6feef 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -37,6 +37,7 @@ endif mutter_built_sources = \ $(dbus_xrandr_built_sources) \ + $(dbus_idle_built_sources) \ mutter-enum-types.h \ mutter-enum-types.c @@ -388,12 +389,22 @@ mutter-enum-types.c: stamp-mutter-enum-types.h mutter-enum-types.c.in dbus_xrandr_built_sources = meta-dbus-xrandr.c meta-dbus-xrandr.h $(dbus_xrandr_built_sources) : Makefile.am xrandr.xml - $(AM_V_GEN)gdbus-codegen \ + $(AM_V_GEN)gdbus-codegen \ --interface-prefix org.gnome.Mutter \ --c-namespace MetaDBus \ --generate-c-code meta-dbus-xrandr \ xrandr.xml +dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h + +$(dbus_idle_built_sources) : Makefile.am idle-monitor.xml + $(AM_V_GEN)gdbus-codegen \ + --interface-prefix org.gnome.Mutter \ + --c-namespace MetaDBus \ + --generate-c-code meta-dbus-idle-monitor \ + --c-generate-object-manager \ + idle-monitor.xml + if HAVE_WAYLAND wayland/%-protocol.c : $(top_builddir)/protocol/%.xml $(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@ diff --git a/src/core/meta-idle-monitor-private.h b/src/core/meta-idle-monitor-private.h index f0f59354d..40608ffd9 100644 --- a/src/core/meta-idle-monitor-private.h +++ b/src/core/meta-idle-monitor-private.h @@ -28,3 +28,4 @@ void meta_idle_monitor_handle_xevent_all (XEvent *xevent); void meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor); +void meta_idle_monitor_init_dbus (void); diff --git a/src/core/meta-idle-monitor.c b/src/core/meta-idle-monitor.c index a2fba4c85..1da0c4b77 100644 --- a/src/core/meta-idle-monitor.c +++ b/src/core/meta-idle-monitor.c @@ -40,6 +40,7 @@ #include #include "display-private.h" #include "meta-idle-monitor-private.h" +#include "meta-dbus-idle-monitor.h" G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer)); @@ -700,3 +701,232 @@ meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor) g_list_foreach (closure.fired_watches, fire_wayland_watch, NULL); g_list_free (closure.fired_watches); } + +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; +} + +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_slice_free (DBusWatch, 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_slice_new (DBusWatch); + 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 +on_device_added (ClutterDeviceManager *device_manager, + ClutterInputDevice *device, + GDBusObjectManagerServer *manager) +{ + MetaDBusIdleMonitor *skeleton; + MetaIdleMonitor *monitor; + MetaDBusObjectSkeleton *object; + int device_id; + gboolean is_core; + char *path; + + is_core = clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER; + + if (is_core) + { + monitor = meta_idle_monitor_get_core (); + path = g_strdup ("/org/gnome/Mutter/IdleMonitor/Core"); + } + else + { + device_id = clutter_input_device_get_device_id (device); + monitor = meta_idle_monitor_get_for_device (device_id); + path = g_strdup_printf ("/org/gnome/Mutter/IdleMonitor/Device%d", device_id); + } + + skeleton = meta_dbus_idle_monitor_skeleton_new (); + g_signal_connect_object (skeleton, "handle-add-idle-watch", + G_CALLBACK (handle_add_idle_watch), monitor, 0); + g_signal_connect_object (skeleton, "handle-add-user-active-watch", + G_CALLBACK (handle_add_user_active_watch), monitor, 0); + g_signal_connect_object (skeleton, "handle-remove-watch", + G_CALLBACK (handle_remove_watch), monitor, 0); + g_signal_connect_object (skeleton, "handle-get-idletime", + G_CALLBACK (handle_get_idletime), monitor, 0); + + 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)); +} + +static void +on_bus_acquired (GDBusConnection *connection, + const char *name, + gpointer user_data) +{ + GDBusObjectManagerServer *manager; + ClutterDeviceManager *device_manager; + GSList *devices, *iter; + + manager = g_dbus_object_manager_server_new ("/org/gnome/Mutter/IdleMonitor"); + + device_manager = clutter_device_manager_get_default (); + devices = clutter_device_manager_list_devices (device_manager); + + for (iter = devices; iter; iter = iter->next) + on_device_added (device_manager, iter->data, manager); + + g_signal_connect_object (device_manager, "device-added", + G_CALLBACK (on_device_added), manager, 0); + + g_dbus_object_manager_server_set_connection (manager, g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL)); +} + +static void +on_name_acquired (GDBusConnection *connection, + const char *name, + gpointer user_data) +{ + meta_topic (META_DEBUG_DBUS, "Acquired name %s\n", name); +} + +static void +on_name_lost (GDBusConnection *connection, + const char *name, + gpointer user_data) +{ + meta_topic (META_DEBUG_DBUS, "Lost or failed to acquire name %s\n", name); +} + +void +meta_idle_monitor_init_dbus (void) +{ + static int dbus_name_id; + + if (dbus_name_id > 0) + return; + + 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, + NULL, NULL); +} + diff --git a/src/core/screen.c b/src/core/screen.c index ddf756934..4691daa1b 100644 --- a/src/core/screen.c +++ b/src/core/screen.c @@ -49,6 +49,7 @@ #include "meta-wayland-private.h" #endif #include "meta-cursor-tracker-private.h" +#include "meta-idle-monitor-private.h" #include @@ -694,6 +695,7 @@ meta_screen_new (MetaDisplay *display, if (!meta_is_wayland_compositor ()) #endif meta_monitor_manager_init_dbus (manager, NULL, NULL); + meta_idle_monitor_init_dbus (); screen->current_cursor = -1; /* invalid/unset */ screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen); diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c index a59e44fe5..1a4d3a816 100644 --- a/src/wayland/meta-wayland.c +++ b/src/wayland/meta-wayland.c @@ -1660,6 +1660,8 @@ on_display_config_ready (GObject *object, ok = meta_monitor_manager_init_dbus_finish (META_MONITOR_MANAGER (object), result, NULL); g_assert (ok); + meta_idle_monitor_init_dbus (); + /* Now we have X and DBus, and our stuff is on the bus. The only thing missing is gnome-session! */ start_gnome_session (user_data);