diff --git a/src/Makefile.am b/src/Makefile.am index 68b1d1874..686d6627f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -37,7 +37,8 @@ INCLUDES += \ endif mutter_built_sources = \ - mutter-enum-types.h \ + $(dbus_idle_built_sources) \ + mutter-enum-types.h \ mutter-enum-types.c if HAVE_WAYLAND @@ -306,6 +307,8 @@ xml_in_files = \ 50-mutter-windows.xml.in xml_DATA = $(xml_in_files:.xml.in=.xml) +dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h + gsettings_SCHEMAS = org.gnome.mutter.gschema.xml @INTLTOOL_XML_NOMERGE_RULE@ @GSETTINGS_RULES@ @@ -362,6 +365,16 @@ mutter-enum-types.c: stamp-mutter-enum-types.h mutter-enum-types.c.in cp xgen-tetc mutter-enum-types.c && \ rm -f xgen-tetc +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 \ + $(srcdir)/idle-monitor.xml + if HAVE_WAYLAND wayland/%-protocol.c : $(top_builddir)/protocol/%.xml mkdir -p wayland diff --git a/src/core/display.c b/src/core/display.c index 0bf16e02e..3a6827e25 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -991,8 +991,10 @@ meta_display_open (void) meta_error_trap_pop (the_display); } - - meta_display_ungrab (the_display); + + meta_idle_monitor_init_dbus (); + + meta_display_ungrab (the_display); /* Done opening new display */ the_display->display_opening = FALSE; @@ -2308,8 +2310,8 @@ meta_display_handle_event (MetaDisplay *display, meta_window_update_sync_request_counter (alarm_window, new_counter_value); filter_out_event = TRUE; /* GTK doesn't want to see this really */ } - - meta_idle_monitor_handle_xevent_all (event); + else + meta_idle_monitor_handle_xevent_all (event); } #endif /* HAVE_XSYNC */ diff --git a/src/core/meta-idle-monitor-private.h b/src/core/meta-idle-monitor-private.h index 39f3c8e76..f301e4fd6 100644 --- a/src/core/meta-idle-monitor-private.h +++ b/src/core/meta-idle-monitor-private.h @@ -27,3 +27,4 @@ void meta_idle_monitor_handle_xevent_all (XEvent *xevent); +void meta_idle_monitor_init_dbus (void); diff --git a/src/core/meta-idle-monitor.c b/src/core/meta-idle-monitor.c index eace00b39..568e6db72 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)); @@ -596,3 +597,261 @@ meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor) return _xsyncvalue_to_int64 (value); } + +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 +create_monitor_skeleton (GDBusObjectManagerServer *manager, + MetaIdleMonitor *monitor, + const char *path) +{ + MetaDBusIdleMonitor *skeleton; + MetaDBusObjectSkeleton *object; + + 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_device_added (ClutterDeviceManager *device_manager, + ClutterInputDevice *device, + GDBusObjectManagerServer *manager) +{ + + MetaIdleMonitor *monitor; + int device_id; + char *path; + + 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); + + create_monitor_skeleton (manager, monitor, path); + g_free (path); +} + +static void +on_device_removed (ClutterDeviceManager *device_manager, + ClutterInputDevice *device, + GDBusObjectManagerServer *manager) +{ + int device_id; + char *path; + + device_id = clutter_input_device_get_device_id (device); + path = g_strdup_printf ("/org/gnome/Mutter/IdleMonitor/Device%d", device_id); + g_dbus_object_manager_server_unexport (manager, path); + g_free (path); + + g_clear_object (&device_monitors[device_id]); + if (device_id == device_id_max) + device_id_max--; +} + +static void +on_bus_acquired (GDBusConnection *connection, + const char *name, + gpointer user_data) +{ + GDBusObjectManagerServer *manager; + ClutterDeviceManager *device_manager; + MetaIdleMonitor *monitor; + GSList *devices, *iter; + char *path; + + 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_monitor_get_core (); + path = g_strdup ("/org/gnome/Mutter/IdleMonitor/Core"); + create_monitor_skeleton (manager, monitor, path); + g_free (path); + + 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_signal_connect_object (device_manager, "device-removed", + G_CALLBACK (on_device_removed), manager, 0); + + g_dbus_object_manager_server_set_connection (manager, connection); +} + +static void +on_name_acquired (GDBusConnection *connection, + const char *name, + gpointer user_data) +{ + meta_verbose ("Acquired name %s\n", name); +} + +static void +on_name_lost (GDBusConnection *connection, + const char *name, + gpointer user_data) +{ + meta_verbose ("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/idle-monitor.xml b/src/idle-monitor.xml new file mode 100644 index 000000000..34a26dd93 --- /dev/null +++ b/src/idle-monitor.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + +