summaryrefslogtreecommitdiff
path: root/community/cinnamon-settings-daemon/systemd-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'community/cinnamon-settings-daemon/systemd-support.patch')
-rw-r--r--community/cinnamon-settings-daemon/systemd-support.patch535
1 files changed, 535 insertions, 0 deletions
diff --git a/community/cinnamon-settings-daemon/systemd-support.patch b/community/cinnamon-settings-daemon/systemd-support.patch
new file mode 100644
index 000000000..3c8b115e8
--- /dev/null
+++ b/community/cinnamon-settings-daemon/systemd-support.patch
@@ -0,0 +1,535 @@
+diff --git a/plugins/media-keys/csd-media-keys-manager.c b/plugins/media-keys/csd-media-keys-manager.c
+index 02930a3..7c1c519 100644
+--- a/plugins/media-keys/csd-media-keys-manager.c
++++ b/plugins/media-keys/csd-media-keys-manager.c
+@@ -39,6 +39,7 @@
+ #include <gdk/gdkx.h>
+ #include <gtk/gtk.h>
+ #include <gio/gdesktopappinfo.h>
++#include <gio/gunixfdlist.h>
+
+ #ifdef HAVE_GUDEV
+ #include <gudev/gudev.h>
+@@ -121,6 +122,10 @@ static const gchar kb_introspection_xml[] =
+ #define VOLUME_STEP 5 /* percents for one volume button press */
+ #define MAX_VOLUME 65536.0
+
++#define SYSTEMD_DBUS_NAME "org.freedesktop.login1"
++#define SYSTEMD_DBUS_PATH "/org/freedesktop/login1"
++#define SYSTEMD_DBUS_INTERFACE "org.freedesktop.login1.Manager"
++
+ #define CSD_MEDIA_KEYS_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CSD_TYPE_MEDIA_KEYS_MANAGER, CsdMediaKeysManagerPrivate))
+
+ typedef struct {
+@@ -167,6 +172,10 @@ struct CsdMediaKeysManagerPrivate
+ GDBusProxy *power_screen_proxy;
+ GDBusProxy *power_keyboard_proxy;
+
++ /* systemd stuff */
++ GDBusProxy *logind_proxy;
++ gint inhibit_keys_fd;
++
+ /* Multihead stuff */
+ GdkScreen *current_screen;
+ GSList *screens;
+@@ -2213,6 +2222,11 @@ csd_media_keys_manager_stop (CsdMediaKeysManager *manager)
+ }
+ #endif /* HAVE_GUDEV */
+
++ if (priv->logind_proxy) {
++ g_object_unref (priv->logind_proxy);
++ priv->logind_proxy = NULL;
++ }
++
+ if (priv->settings) {
+ g_object_unref (priv->settings);
+ priv->settings = NULL;
+@@ -2356,9 +2370,85 @@ csd_media_keys_manager_class_init (CsdMediaKeysManagerClass *klass)
+ }
+
+ static void
++inhibit_done (GObject *source,
++ GAsyncResult *result,
++ gpointer user_data)
++{
++ GDBusProxy *proxy = G_DBUS_PROXY (source);
++ CsdMediaKeysManager *manager = CSD_MEDIA_KEYS_MANAGER (user_data);
++ GError *error = NULL;
++ GVariant *res;
++ GUnixFDList *fd_list = NULL;
++ gint idx;
++
++ res = g_dbus_proxy_call_with_unix_fd_list_finish (proxy, &fd_list, result, &error);
++ if (res == NULL) {
++ g_warning ("Unable to inhibit keypresses: %s", error->message);
++ g_error_free (error);
++ } else {
++ g_variant_get (res, "(h)", &idx);
++ manager->priv->inhibit_keys_fd = g_unix_fd_list_get (fd_list, idx, &error);
++ if (manager->priv->inhibit_keys_fd == -1) {
++ g_warning ("Failed to receive system inhibitor fd: %s", error->message);
++ g_error_free (error);
++ }
++ g_debug ("System inhibitor fd is %d", manager->priv->inhibit_keys_fd);
++ g_object_unref (fd_list);
++ g_variant_unref (res);
++ }
++}
++
++static void
+ csd_media_keys_manager_init (CsdMediaKeysManager *manager)
+ {
++ GError *error;
++ GDBusConnection *bus;
++
++ error = NULL;
+ manager->priv = CSD_MEDIA_KEYS_MANAGER_GET_PRIVATE (manager);
++
++ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
++ if (bus == NULL) {
++ g_warning ("Failed to connect to system bus: %s",
++ error->message);
++ g_error_free (error);
++ return;
++ }
++
++ manager->priv->logind_proxy =
++ g_dbus_proxy_new_sync (bus,
++ 0,
++ NULL,
++ SYSTEMD_DBUS_NAME,
++ SYSTEMD_DBUS_PATH,
++ SYSTEMD_DBUS_INTERFACE,
++ NULL,
++ &error);
++
++ if (manager->priv->logind_proxy == NULL) {
++ g_warning ("Failed to connect to systemd: %s",
++ error->message);
++ g_error_free (error);
++ }
++
++ g_object_unref (bus);
++
++ g_debug ("Adding system inhibitors for power keys");
++ manager->priv->inhibit_keys_fd = -1;
++ g_dbus_proxy_call_with_unix_fd_list (manager->priv->logind_proxy,
++ "Inhibit",
++ g_variant_new ("(ssss)",
++ "handle-power-key:handle-suspend-key:handle-hibernate-key",
++ g_get_user_name (),
++ "Cinnamon handling keypresses",
++ "block"),
++ 0,
++ G_MAXINT,
++ NULL,
++ NULL,
++ inhibit_done,
++ manager);
++
+ }
+
+ static void
+@@ -2375,6 +2465,8 @@ csd_media_keys_manager_finalize (GObject *object)
+
+ if (media_keys_manager->priv->start_idle_id != 0)
+ g_source_remove (media_keys_manager->priv->start_idle_id);
++ if (media_keys_manager->priv->inhibit_keys_fd != -1)
++ close (media_keys_manager->priv->inhibit_keys_fd);
+
+ G_OBJECT_CLASS (csd_media_keys_manager_parent_class)->finalize (object);
+ }
+diff --git a/plugins/power/csd-power-manager.c b/plugins/power/csd-power-manager.c
+index b54cb5b..b9c5429 100644
+--- a/plugins/power/csd-power-manager.c
++++ b/plugins/power/csd-power-manager.c
+@@ -32,6 +32,7 @@
+ #include <libupower-glib/upower.h>
+ #include <libnotify/notify.h>
+ #include <canberra-gtk.h>
++#include <gio/gunixfdlist.h>
+
+ #include <X11/extensions/dpms.h>
+
+@@ -79,6 +80,10 @@
+ #define CSD_POWER_MANAGER_CRITICAL_ALERT_TIMEOUT 5 /* seconds */
+ #define CSD_POWER_MANAGER_LID_CLOSE_SAFETY_TIMEOUT 30 /* seconds */
+
++#define SYSTEMD_DBUS_NAME "org.freedesktop.login1"
++#define SYSTEMD_DBUS_PATH "/org/freedesktop/login1"
++#define SYSTEMD_DBUS_INTERFACE "org.freedesktop.login1.Manager"
++
+ /* Keep this in sync with gnome-shell */
+ #define SCREENSAVER_FADE_TIME 10 /* seconds */
+
+@@ -203,6 +208,13 @@ struct CsdPowerManagerPrivate
+ GtkStatusIcon *status_icon;
+ guint xscreensaver_watchdog_timer_id;
+ gboolean is_virtual_machine;
++
++ /* systemd stuff */
++ GDBusProxy *logind_proxy;
++ gint inhibit_lid_switch_fd;
++ gboolean inhibit_lid_switch_taken;
++ gint inhibit_suspend_fd;
++ gboolean inhibit_suspend_taken;
+ };
+
+ enum {
+@@ -3350,30 +3362,6 @@ lock_screensaver (CsdPowerManager *manager)
+ if (!do_lock)
+ return;
+
+- /* connect to the screensaver first */
+- g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+- G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
+- NULL,
+- GS_DBUS_NAME,
+- GS_DBUS_PATH,
+- GS_DBUS_INTERFACE,
+- NULL,
+- sleep_cb_screensaver_proxy_ready_cb,
+- manager);
+-}
+-
+-static void
+-upower_notify_sleep_cb (UpClient *client,
+- UpSleepKind sleep_kind,
+- CsdPowerManager *manager)
+-{
+- gboolean do_lock;
+-
+- do_lock = g_settings_get_boolean (manager->priv->settings,
+- "lock-on-suspend");
+- if (!do_lock)
+- return;
+-
+ /* connect to the screensaver first */
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
+@@ -3384,46 +3372,6 @@ upower_notify_sleep_cb (UpClient *client,
+ NULL,
+ sleep_cb_screensaver_proxy_ready_cb,
+ manager);
+-
+-}
+-
+-static void
+-upower_notify_resume_cb (UpClient *client,
+- UpSleepKind sleep_kind,
+- CsdPowerManager *manager)
+-{
+- gboolean ret;
+- GError *error = NULL;
+-
+- /* this displays the unlock dialogue so the user doesn't have
+- * to move the mouse or press any key before the window comes up */
+- if (manager->priv->screensaver_proxy != NULL) {
+- g_dbus_proxy_call (manager->priv->screensaver_proxy,
+- "SimulateUserActivity",
+- NULL,
+- G_DBUS_CALL_FLAGS_NONE,
+- -1, NULL, NULL, NULL);
+- }
+-
+- if (manager->priv->screensaver_proxy != NULL) {
+- g_object_unref (manager->priv->screensaver_proxy);
+- manager->priv->screensaver_proxy = NULL;
+- }
+-
+- /* close existing notifications on resume, the system power
+- * state is probably different now */
+- notify_close_if_showing (manager->priv->notification_low);
+- notify_close_if_showing (manager->priv->notification_discharging);
+-
+- /* ensure we turn the panel back on after resume */
+- ret = gnome_rr_screen_set_dpms_mode (manager->priv->x11_screen,
+- GNOME_RR_DPMS_ON,
+- &error);
+- if (!ret) {
+- g_warning ("failed to turn the panel on after resume: %s",
+- error->message);
+- g_error_free (error);
+- }
+ }
+
+ static void
+@@ -3582,6 +3530,219 @@ disable_builtin_screensaver (gpointer unused)
+ return TRUE;
+ }
+
++static void
++inhibit_lid_switch_done (GObject *source,
++ GAsyncResult *result,
++ gpointer user_data)
++{
++ GDBusProxy *proxy = G_DBUS_PROXY (source);
++ CsdPowerManager *manager = CSD_POWER_MANAGER (user_data);
++ GError *error = NULL;
++ GVariant *res;
++ GUnixFDList *fd_list = NULL;
++ gint idx;
++
++ res = g_dbus_proxy_call_with_unix_fd_list_finish (proxy, &fd_list, result, &error);
++ if (res == NULL) {
++ g_warning ("Unable to inhibit lid switch: %s", error->message);
++ g_error_free (error);
++ } else {
++ g_variant_get (res, "(h)", &idx);
++ manager->priv->inhibit_lid_switch_fd = g_unix_fd_list_get (fd_list, idx, &error);
++ if (manager->priv->inhibit_lid_switch_fd == -1) {
++ g_warning ("Failed to receive system inhibitor fd: %s", error->message);
++ g_error_free (error);
++ }
++ g_debug ("System inhibitor fd is %d", manager->priv->inhibit_lid_switch_fd);
++ g_object_unref (fd_list);
++ g_variant_unref (res);
++ }
++}
++
++static void
++inhibit_lid_switch (CsdPowerManager *manager)
++{
++ GVariant *params;
++
++ if (manager->priv->inhibit_lid_switch_taken) {
++ g_debug ("already inhibited lid-switch");
++ return;
++ }
++ g_debug ("Adding lid switch system inhibitor");
++ manager->priv->inhibit_lid_switch_taken = TRUE;
++
++ params = g_variant_new ("(ssss)",
++ "handle-lid-switch",
++ g_get_user_name (),
++ "Multiple displays attached",
++ "block");
++ g_dbus_proxy_call_with_unix_fd_list (manager->priv->logind_proxy,
++ "Inhibit",
++ params,
++ 0,
++ G_MAXINT,
++ NULL,
++ NULL,
++ inhibit_lid_switch_done,
++ manager);
++}
++
++static void
++inhibit_suspend_done (GObject *source,
++ GAsyncResult *result,
++ gpointer user_data)
++{
++ GDBusProxy *proxy = G_DBUS_PROXY (source);
++ CsdPowerManager *manager = CSD_POWER_MANAGER (user_data);
++ GError *error = NULL;
++ GVariant *res;
++ GUnixFDList *fd_list = NULL;
++ gint idx;
++
++ res = g_dbus_proxy_call_with_unix_fd_list_finish (proxy, &fd_list, result, &error);
++ if (res == NULL) {
++ g_warning ("Unable to inhibit suspend: %s", error->message);
++ g_error_free (error);
++ } else {
++ g_variant_get (res, "(h)", &idx);
++ manager->priv->inhibit_suspend_fd = g_unix_fd_list_get (fd_list, idx, &error);
++ if (manager->priv->inhibit_suspend_fd == -1) {
++ g_warning ("Failed to receive system inhibitor fd: %s", error->message);
++ g_error_free (error);
++ }
++ g_debug ("System inhibitor fd is %d", manager->priv->inhibit_suspend_fd);
++ g_object_unref (fd_list);
++ g_variant_unref (res);
++ }
++}
++
++/* We take a delay inhibitor here, which causes logind to send a
++ * PrepareToSleep signal, which gives us a chance to lock the screen
++ * and do some other preparations.
++ */
++static void
++inhibit_suspend (CsdPowerManager *manager)
++{
++ if (manager->priv->inhibit_suspend_taken) {
++ g_debug ("already inhibited lid-switch");
++ return;
++ }
++ g_debug ("Adding suspend delay inhibitor");
++ manager->priv->inhibit_suspend_taken = TRUE;
++ g_dbus_proxy_call_with_unix_fd_list (manager->priv->logind_proxy,
++ "Inhibit",
++ g_variant_new ("(ssss)",
++ "sleep",
++ g_get_user_name (),
++ "Cinnamon needs to lock the screen",
++ "delay"),
++ 0,
++ G_MAXINT,
++ NULL,
++ NULL,
++ inhibit_suspend_done,
++ manager);
++}
++
++static void
++uninhibit_suspend (CsdPowerManager *manager)
++{
++ if (manager->priv->inhibit_suspend_fd == -1) {
++ g_debug ("no suspend delay inhibitor");
++ return;
++ }
++ g_debug ("Removing suspend delay inhibitor");
++ close (manager->priv->inhibit_suspend_fd);
++ manager->priv->inhibit_suspend_fd = -1;
++ manager->priv->inhibit_suspend_taken = FALSE;
++}
++
++static void
++handle_suspend_actions (CsdPowerManager *manager)
++{
++ gboolean do_lock;
++
++ do_lock = g_settings_get_boolean (manager->priv->settings,
++ "lock-on-suspend");
++ if (do_lock)
++ lock_screensaver (manager);
++
++ /* lift the delay inhibit, so logind can proceed */
++ uninhibit_suspend (manager);
++}
++
++static void
++handle_resume_actions (CsdPowerManager *manager)
++{
++ gboolean ret;
++ GError *error = NULL;
++
++ /* this displays the unlock dialogue so the user doesn't have
++ * to move the mouse or press any key before the window comes up */
++ g_dbus_connection_call (manager->priv->connection,
++ GS_DBUS_NAME,
++ GS_DBUS_PATH,
++ GS_DBUS_INTERFACE,
++ "SimulateUserActivity",
++ NULL, NULL,
++ G_DBUS_CALL_FLAGS_NONE, -1,
++ NULL, NULL, NULL);
++
++ /* close existing notifications on resume, the system power
++ * state is probably different now */
++ notify_close_if_showing (manager->priv->notification_low);
++ notify_close_if_showing (manager->priv->notification_discharging);
++
++ /* ensure we turn the panel back on after resume */
++ ret = gnome_rr_screen_set_dpms_mode (manager->priv->x11_screen,
++ GNOME_RR_DPMS_ON,
++ &error);
++ if (!ret) {
++ g_warning ("failed to turn the panel on after resume: %s",
++ error->message);
++ g_error_free (error);
++ }
++
++ /* set up the delay again */
++ inhibit_suspend (manager);
++}
++
++static void
++upower_notify_sleep_cb (UpClient *client,
++ UpSleepKind sleep_kind,
++ CsdPowerManager *manager)
++{
++ handle_suspend_actions (manager);
++}
++
++static void
++upower_notify_resume_cb (UpClient *client,
++ UpSleepKind sleep_kind,
++ CsdPowerManager *manager)
++{
++ handle_resume_actions (manager);
++}
++
++static void
++logind_proxy_signal_cb (GDBusProxy *proxy,
++ const gchar *sender_name,
++ const gchar *signal_name,
++ GVariant *parameters,
++ gpointer user_data)
++{
++ CsdPowerManager *manager = CSD_POWER_MANAGER (user_data);
++ gboolean is_about_to_suspend;
++
++ if (g_strcmp0 (signal_name, "PrepareForSleep") != 0)
++ return;
++ g_variant_get (parameters, "(b)", &is_about_to_suspend);
++ if (is_about_to_suspend) {
++ handle_suspend_actions (manager);
++ } else {
++ handle_resume_actions (manager);
++ }
++}
++
+ static gboolean
+ is_hardware_a_virtual_machine (void)
+ {
+@@ -3647,6 +3808,26 @@ csd_power_manager_start (CsdPowerManager *manager,
+ if (manager->priv->x11_screen == NULL)
+ return FALSE;
+
++ /* Set up the logind proxy */
++ manager->priv->logind_proxy =
++ g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
++ 0,
++ NULL,
++ SYSTEMD_DBUS_NAME,
++ SYSTEMD_DBUS_PATH,
++ SYSTEMD_DBUS_INTERFACE,
++ NULL,
++ error);
++ g_signal_connect (manager->priv->logind_proxy, "g-signal",
++ G_CALLBACK (logind_proxy_signal_cb),
++ manager);
++
++ /* Set up a delay inhibitor to be informed about suspend attempts */
++ inhibit_suspend (manager);
++
++ /* Disable logind's lid handling while g-s-d is active */
++ inhibit_lid_switch (manager);
++
+ /* track the active session */
+ manager->priv->session = cinnamon_settings_session_new ();
+ g_signal_connect (manager->priv->session, "notify::state",
+@@ -3856,6 +4037,22 @@ csd_power_manager_stop (CsdPowerManager *manager)
+ manager->priv->up_client = NULL;
+ }
+
++ if (manager->priv->inhibit_lid_switch_fd != -1) {
++ close (manager->priv->inhibit_lid_switch_fd);
++ manager->priv->inhibit_lid_switch_fd = -1;
++ manager->priv->inhibit_lid_switch_taken = FALSE;
++ }
++ if (manager->priv->inhibit_suspend_fd != -1) {
++ close (manager->priv->inhibit_suspend_fd);
++ manager->priv->inhibit_suspend_fd = -1;
++ manager->priv->inhibit_suspend_taken = FALSE;
++ }
++
++ if (manager->priv->logind_proxy != NULL) {
++ g_object_unref (manager->priv->logind_proxy);
++ manager->priv->logind_proxy = NULL;
++ }
++
+ if (manager->priv->x11_screen != NULL) {
+ g_object_unref (manager->priv->x11_screen);
+ manager->priv->x11_screen = NULL;
+@@ -3928,6 +4125,8 @@ static void
+ csd_power_manager_init (CsdPowerManager *manager)
+ {
+ manager->priv = CSD_POWER_MANAGER_GET_PRIVATE (manager);
++ manager->priv->inhibit_lid_switch_fd = -1;
++ manager->priv->inhibit_suspend_fd = -1;
+ }
+
+ static void