From c3fcf11eb76b7110b9520579d84976b6987a6314 Mon Sep 17 00:00:00 2001 From: Juan RP Date: Fri, 19 Oct 2012 09:46:38 +0200 Subject: [PATCH] gnome-settings-daemon: add 2 patches for screensaver and using systemd logind. --- .../gnome-settings-daemon.rshlibs | 15 - .../patches/0000-screensaver.patch | 145 ++ ...keys-Use-logind-for-suspending-and-r.patch | 1473 +++++++++++++++++ srcpkgs/gnome-settings-daemon/template | 28 +- 4 files changed, 1638 insertions(+), 23 deletions(-) create mode 100644 srcpkgs/gnome-settings-daemon/patches/0000-screensaver.patch create mode 100644 srcpkgs/gnome-settings-daemon/patches/0001-power-and-media-keys-Use-logind-for-suspending-and-r.patch diff --git a/srcpkgs/gnome-settings-daemon/gnome-settings-daemon.rshlibs b/srcpkgs/gnome-settings-daemon/gnome-settings-daemon.rshlibs index ecbfd41b17..5ac26e3924 100644 --- a/srcpkgs/gnome-settings-daemon/gnome-settings-daemon.rshlibs +++ b/srcpkgs/gnome-settings-daemon/gnome-settings-daemon.rshlibs @@ -30,21 +30,6 @@ libwacom.so.2 libXtst.so.6 libcups.so.2 libsystemd-login.so.0 -libatk-1.0.so.0 -libpangocairo-1.0.so.0 -libcairo-gobject.so.2 -libpango-1.0.so.0 libcolord.so.1 liblcms2.so.2 libXfixes.so.3 -libssl3.so -libsmime3.so -libnssutil3.so -libplds4.so -libdl.so.2 -libgssapi_krb5.so.2 -libkrb5.so.3 -libk5crypto.so.3 -libcom_err.so.2 -libcrypt.so.1 -libz.so.1 diff --git a/srcpkgs/gnome-settings-daemon/patches/0000-screensaver.patch b/srcpkgs/gnome-settings-daemon/patches/0000-screensaver.patch new file mode 100644 index 0000000000..211fc44b36 --- /dev/null +++ b/srcpkgs/gnome-settings-daemon/patches/0000-screensaver.patch @@ -0,0 +1,145 @@ +From b47e4019a12ac84fba31e1c631d878ce03fa3808 Mon Sep 17 00:00:00 2001 +From: Rui Matos +Date: Wed, 17 Oct 2012 22:44:54 +0000 +Subject: power: Add a watchdog to keep X's builtin screen saver disabled + +X's builtin screen saver may activate DPMS. Since we want to activate +DPMS ourselves according to our own policy we must make sure that X's +screen saver remains disabled. + +This code is a copy of the original found in gs-watcher-x11.c from +gnome-screensaver which stopped being used in GNOME 3.6. + +https://bugzilla.gnome.org/show_bug.cgi?id=686339 +--- +diff --git a/plugins/power/gsd-power-manager.c b/plugins/power/gsd-power-manager.c +index 0e06495..070cf32 100644 +--- a/plugins/power/gsd-power-manager.c ++++ b/plugins/power/gsd-power-manager.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -80,6 +81,8 @@ + /* Keep this in sync with gnome-shell */ + #define SCREENSAVER_FADE_TIME 10 /* seconds */ + ++#define XSCREENSAVER_WATCHDOG_TIMEOUT 120 /* seconds */ ++ + enum { + GSD_POWER_IDLETIME_NULL_ID, + GSD_POWER_IDLETIME_DIM_ID, +@@ -197,6 +200,7 @@ struct GsdPowerManagerPrivate + GsdPowerIdleMode current_idle_mode; + guint lid_close_safety_timer_id; + GtkStatusIcon *status_icon; ++ guint xscreensaver_watchdog_timer_id; + }; + + enum { +@@ -3621,6 +3625,77 @@ engine_session_active_changed_cb (GnomeSettingsSession *session, + idle_set_mode (manager, GSD_POWER_IDLE_MODE_NORMAL); + } + ++/* This timer goes off every few minutes, whether the user is idle or not, ++ to try and clean up anything that has gone wrong. ++ ++ It calls disable_builtin_screensaver() so that if xset has been used, ++ or some other program (like xlock) has messed with the XSetScreenSaver() ++ settings, they will be set back to sensible values (if a server extension ++ is in use, messing with xlock can cause the screensaver to never get a wakeup ++ event, and could cause monitor power-saving to occur, and all manner of ++ heinousness.) ++ ++ This code was originally part of gnome-screensaver, see ++ http://git.gnome.org/browse/gnome-screensaver/tree/src/gs-watcher-x11.c?id=fec00b12ec46c86334cfd36b37771cc4632f0d4d#n530 ++ */ ++static gboolean ++disable_builtin_screensaver (gpointer unused) ++{ ++ int current_server_timeout, current_server_interval; ++ int current_prefer_blank, current_allow_exp; ++ int desired_server_timeout, desired_server_interval; ++ int desired_prefer_blank, desired_allow_exp; ++ ++ XGetScreenSaver (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), ++ ¤t_server_timeout, ++ ¤t_server_interval, ++ ¤t_prefer_blank, ++ ¤t_allow_exp); ++ ++ desired_server_timeout = current_server_timeout; ++ desired_server_interval = current_server_interval; ++ desired_prefer_blank = current_prefer_blank; ++ desired_allow_exp = current_allow_exp; ++ ++ desired_server_interval = 0; ++ ++ /* I suspect (but am not sure) that DontAllowExposures might have ++ something to do with powering off the monitor as well, at least ++ on some systems that don't support XDPMS? Who know... */ ++ desired_allow_exp = AllowExposures; ++ ++ /* When we're not using an extension, set the server-side timeout to 0, ++ so that the server never gets involved with screen blanking, and we ++ do it all ourselves. (However, when we *are* using an extension, ++ we tell the server when to notify us, and rather than blanking the ++ screen, the server will send us an X event telling us to blank.) ++ */ ++ desired_server_timeout = 0; ++ ++ if (desired_server_timeout != current_server_timeout ++ || desired_server_interval != current_server_interval ++ || desired_prefer_blank != current_prefer_blank ++ || desired_allow_exp != current_allow_exp) { ++ ++ g_debug ("disabling server builtin screensaver:" ++ " (xset s %d %d; xset s %s; xset s %s)", ++ desired_server_timeout, ++ desired_server_interval, ++ (desired_prefer_blank ? "blank" : "noblank"), ++ (desired_allow_exp ? "expose" : "noexpose")); ++ ++ XSetScreenSaver (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), ++ desired_server_timeout, ++ desired_server_interval, ++ desired_prefer_blank, ++ desired_allow_exp); ++ ++ XSync (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), FALSE); ++ } ++ ++ return TRUE; ++} ++ + gboolean + gsd_power_manager_start (GsdPowerManager *manager, + GError **error) +@@ -3778,6 +3853,9 @@ gsd_power_manager_start (GsdPowerManager *manager, + /* set the initial dim time that can adapt for the user */ + refresh_idle_dim_settings (manager); + ++ manager->priv->xscreensaver_watchdog_timer_id = g_timeout_add_seconds (XSCREENSAVER_WATCHDOG_TIMEOUT, ++ disable_builtin_screensaver, ++ NULL); + gnome_settings_profile_end (NULL); + return TRUE; + } +@@ -3829,6 +3907,11 @@ gsd_power_manager_stop (GsdPowerManager *manager) + + g_clear_object (&manager->priv->idletime); + g_clear_object (&manager->priv->status_icon); ++ ++ if (manager->priv->xscreensaver_watchdog_timer_id > 0) { ++ g_source_remove (manager->priv->xscreensaver_watchdog_timer_id); ++ manager->priv->xscreensaver_watchdog_timer_id = 0; ++ } + } + + static void +-- +cgit v0.9.0.2 diff --git a/srcpkgs/gnome-settings-daemon/patches/0001-power-and-media-keys-Use-logind-for-suspending-and-r.patch b/srcpkgs/gnome-settings-daemon/patches/0001-power-and-media-keys-Use-logind-for-suspending-and-r.patch new file mode 100644 index 0000000000..41bfddf11f --- /dev/null +++ b/srcpkgs/gnome-settings-daemon/patches/0001-power-and-media-keys-Use-logind-for-suspending-and-r.patch @@ -0,0 +1,1473 @@ +From 79ead5309fe21e77cfe58adc6a9340953c2d52f4 Mon Sep 17 00:00:00 2001 +From: Richard Hughes +Date: Fri, 21 Sep 2012 11:56:53 +0100 +Subject: [PATCH] power and media-keys: Use logind for suspending and + rebooting the system + +Use the new logind features to suspend and resume but making sure we opt out +of logind handling the sleep and power keys, and also inhibiting for lid close +auto-suspend if there is an external monitor connected. + +Also use a delay inihibit for logind so that we can do actions on suspend like +blanking the screen using the screensaver and also poking the screensaver on +resume. + +https://bugzilla.gnome.org/show_bug.cgi?id=680689 +--- + plugins/common/Makefile.am | 4 +- + plugins/common/gsd-power-helper.c | 203 -------- + plugins/common/gsd-power-helper.h | 35 -- + plugins/media-keys/gsd-media-keys-manager.c | 156 +++++-- + plugins/power/gsd-power-manager.c | 699 +++++++++++++++++++--------- + 5 files changed, 595 insertions(+), 502 deletions(-) + delete mode 100644 plugins/common/gsd-power-helper.c + delete mode 100644 plugins/common/gsd-power-helper.h + +diff --git a/plugins/common/Makefile.am b/plugins/common/Makefile.am +index 7e50db4..b0e907c 100644 +--- a/plugins/common/Makefile.am ++++ b/plugins/common/Makefile.am +@@ -6,9 +6,7 @@ libcommon_la_SOURCES = \ + gsd-keygrab.c \ + gsd-keygrab.h \ + gsd-input-helper.c \ +- gsd-input-helper.h \ +- gsd-power-helper.c \ +- gsd-power-helper.h ++ gsd-input-helper.h + + libcommon_la_CPPFLAGS = \ + $(AM_CPPFLAGS) +diff --git a/plugins/common/gsd-power-helper.c b/plugins/common/gsd-power-helper.c +deleted file mode 100644 +index 27d0eda..0000000 +--- a/plugins/common/gsd-power-helper.c ++++ /dev/null +@@ -1,203 +0,0 @@ +-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- +- * +- * Copyright (C) 2012 Bastien Nocera +- * +- * 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, write to the Free Software +- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +- * +- */ +- +-#include "config.h" +- +-#include "gsd-power-helper.h" +- +-#define SYSTEMD_DBUS_NAME "org.freedesktop.login1" +-#define SYSTEMD_DBUS_PATH "/org/freedesktop/login1" +-#define SYSTEMD_DBUS_INTERFACE "org.freedesktop.login1.Manager" +- +-#define CONSOLEKIT_DBUS_NAME "org.freedesktop.ConsoleKit" +-#define CONSOLEKIT_DBUS_PATH_MANAGER "/org/freedesktop/ConsoleKit/Manager" +-#define CONSOLEKIT_DBUS_INTERFACE_MANAGER "org.freedesktop.ConsoleKit.Manager" +- +-#ifdef HAVE_SYSTEMD +-static void +-systemd_stop (void) +-{ +- GDBusConnection *bus; +- +- bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL); +- g_dbus_connection_call (bus, +- SYSTEMD_DBUS_NAME, +- SYSTEMD_DBUS_PATH, +- SYSTEMD_DBUS_INTERFACE, +- "PowerOff", +- g_variant_new ("(b)", FALSE), +- NULL, 0, G_MAXINT, NULL, NULL, NULL); +- g_object_unref (bus); +-} +- +-static void +-systemd_suspend (void) +-{ +- GDBusConnection *bus; +- +- bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL); +- g_dbus_connection_call (bus, +- SYSTEMD_DBUS_NAME, +- SYSTEMD_DBUS_PATH, +- SYSTEMD_DBUS_INTERFACE, +- "Suspend", +- g_variant_new ("(b)", TRUE), +- NULL, 0, G_MAXINT, NULL, NULL, NULL); +- g_object_unref (bus); +-} +- +-static void +-systemd_hibernate (void) +-{ +- GDBusConnection *bus; +- +- bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL); +- g_dbus_connection_call (bus, +- SYSTEMD_DBUS_NAME, +- SYSTEMD_DBUS_PATH, +- SYSTEMD_DBUS_INTERFACE, +- "Hibernate", +- g_variant_new ("(b)", TRUE), +- NULL, 0, G_MAXINT, NULL, NULL, NULL); +- g_object_unref (bus); +-} +- +-#else /* HAVE_SYSTEMD */ +- +-static void +-consolekit_stop_cb (GObject *source_object, +- GAsyncResult *res, +- gpointer user_data) +-{ +- GVariant *result; +- GError *error = NULL; +- +- result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), +- res, +- &error); +- if (result == NULL) { +- g_warning ("couldn't stop using ConsoleKit: %s", +- error->message); +- g_error_free (error); +- } else { +- g_variant_unref (result); +- } +-} +- +-static void +-consolekit_stop (void) +-{ +- GError *error = NULL; +- GDBusProxy *proxy; +- +- /* power down the machine in a safe way */ +- proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, +- G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, +- NULL, +- CONSOLEKIT_DBUS_NAME, +- CONSOLEKIT_DBUS_PATH_MANAGER, +- CONSOLEKIT_DBUS_INTERFACE_MANAGER, +- NULL, &error); +- if (proxy == NULL) { +- g_warning ("cannot connect to ConsoleKit: %s", +- error->message); +- g_error_free (error); +- return; +- } +- g_dbus_proxy_call (proxy, +- "Stop", +- NULL, +- G_DBUS_CALL_FLAGS_NONE, +- -1, NULL, +- consolekit_stop_cb, NULL); +- g_object_unref (proxy); +-} +-static void +-upower_sleep_cb (GObject *source_object, +- GAsyncResult *res, +- gpointer user_data) +-{ +- GVariant *result; +- GError *error = NULL; +- +- result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), +- res, +- &error); +- if (result == NULL) { +- g_warning ("couldn't sleep using UPower: %s", +- error->message); +- g_error_free (error); +- } else { +- g_variant_unref (result); +- } +-} +- +-static void +-upower_suspend (GDBusProxy *upower_proxy) +-{ +- g_dbus_proxy_call (upower_proxy, +- "Suspend", +- NULL, +- G_DBUS_CALL_FLAGS_NONE, +- -1, NULL, +- upower_sleep_cb, NULL); +-} +- +-static void +-upower_hibernate (GDBusProxy *upower_proxy) +-{ +- g_dbus_proxy_call (upower_proxy, +- "Hibernate", +- NULL, +- G_DBUS_CALL_FLAGS_NONE, +- -1, NULL, +- upower_sleep_cb, NULL); +-} +-#endif /* HAVE_SYSTEMD */ +- +-void +-gsd_power_suspend (GDBusProxy *upower_proxy) +-{ +-#ifdef HAVE_SYSTEMD +- systemd_suspend (); +-#else +- upower_suspend (upower_proxy); +-#endif +-} +- +-void +-gsd_power_poweroff (void) +-{ +-#ifdef HAVE_SYSTEMD +- systemd_stop (); +-#else +- consolekit_stop (); +-#endif +-} +- +-void +-gsd_power_hibernate (GDBusProxy *upower_proxy) +-{ +-#ifdef HAVE_SYSTEMD +- systemd_hibernate (); +-#else +- upower_hibernate (upower_proxy); +-#endif +-} +diff --git a/plugins/common/gsd-power-helper.h b/plugins/common/gsd-power-helper.h +deleted file mode 100644 +index e3be14f..0000000 +--- a/plugins/common/gsd-power-helper.h ++++ /dev/null +@@ -1,35 +0,0 @@ +-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- +- * +- * Copyright (C) 2012 Bastien Nocera +- * +- * 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, write to the Free Software +- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +- */ +- +-#ifndef __GSD_POWER_HELPER_H +-#define __GSD_POWER_HELPER_H +- +-#include +- +-G_BEGIN_DECLS +- +-#include +- +-void gsd_power_suspend (GDBusProxy *upower_proxy); +-void gsd_power_hibernate (GDBusProxy *upower_proxy); +-void gsd_power_poweroff (void); +- +-G_END_DECLS +- +-#endif /* __GSD_POWER_HELPER_H */ +diff --git a/plugins/media-keys/gsd-media-keys-manager.c b/plugins/media-keys/gsd-media-keys-manager.c +index 9c84d7f..a2f277e 100644 +--- a/plugins/media-keys/gsd-media-keys-manager.c ++++ b/plugins/media-keys/gsd-media-keys-manager.c +@@ -39,6 +39,7 @@ + #include + #include + #include ++#include + + #ifdef HAVE_GUDEV + #include +@@ -51,7 +52,6 @@ + #include "shortcuts-list.h" + #include "gsd-osd-window.h" + #include "gsd-input-helper.h" +-#include "gsd-power-helper.h" + #include "gsd-enums.h" + + #include +@@ -105,6 +105,10 @@ static const gchar introspection_xml[] = + #define KEY_CURRENT_INPUT_SOURCE "current" + #define KEY_INPUT_SOURCES "sources" + ++#define SYSTEMD_DBUS_NAME "org.freedesktop.login1" ++#define SYSTEMD_DBUS_PATH "/org/freedesktop/login1" ++#define SYSTEMD_DBUS_INTERFACE "org.freedesktop.login1.Manager" ++ + #define GSD_MEDIA_KEYS_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_MEDIA_KEYS_MANAGER, GsdMediaKeysManagerPrivate)) + + typedef struct { +@@ -148,10 +152,13 @@ struct GsdMediaKeysManagerPrivate + + /* Power stuff */ + GSettings *power_settings; +- GDBusProxy *upower_proxy; + GDBusProxy *power_screen_proxy; + GDBusProxy *power_keyboard_proxy; + ++ /* systemd stuff */ ++ GDBusProxy *logind_proxy; ++ gint inhibit_keys_fd; ++ + /* Multihead stuff */ + GdkScreen *current_screen; + GSList *screens; +@@ -1618,6 +1625,38 @@ do_toggle_contrast_action (GsdMediaKeysManager *manager) + } + + static void ++power_action_suspend (GsdMediaKeysManager *manager) ++{ ++#ifndef HAVE_SYSTEMD ++ g_warning ("no systemd support"); ++ return; ++#endif ++ g_dbus_proxy_call (manager->priv->logind_proxy, ++ "Suspend", ++ g_variant_new ("(b)", TRUE), ++ G_DBUS_CALL_FLAGS_NONE, ++ G_MAXINT, ++ manager->priv->bus_cancellable, ++ NULL, NULL); ++} ++ ++static void ++power_action_hibernate (GsdMediaKeysManager *manager) ++{ ++#ifndef HAVE_SYSTEMD ++ g_warning ("no systemd support"); ++ return; ++#endif ++ g_dbus_proxy_call (manager->priv->logind_proxy, ++ "Hibernate", ++ g_variant_new ("(b)", TRUE), ++ G_DBUS_CALL_FLAGS_NONE, ++ G_MAXINT, ++ manager->priv->bus_cancellable, ++ NULL, NULL); ++} ++ ++static void + do_config_power_action (GsdMediaKeysManager *manager, + const gchar *config_key) + { +@@ -1627,14 +1666,14 @@ do_config_power_action (GsdMediaKeysManager *manager, + config_key); + switch (action_type) { + case GSD_POWER_ACTION_SUSPEND: +- gsd_power_suspend (manager->priv->upower_proxy); ++ power_action_suspend (manager); + break; + case GSD_POWER_ACTION_INTERACTIVE: + case GSD_POWER_ACTION_SHUTDOWN: + gnome_session_shutdown (manager); + break; + case GSD_POWER_ACTION_HIBERNATE: +- gsd_power_hibernate (manager->priv->upower_proxy); ++ power_action_hibernate (manager); + break; + case GSD_POWER_ACTION_BLANK: + case GSD_POWER_ACTION_NOTHING: +@@ -2248,6 +2287,7 @@ gsd_media_keys_manager_stop (GsdMediaKeysManager *manager) + } + #endif /* HAVE_GUDEV */ + ++ g_clear_object (&priv->logind_proxy); + if (priv->settings) { + g_object_unref (priv->settings); + priv->settings = NULL; +@@ -2268,11 +2308,6 @@ gsd_media_keys_manager_stop (GsdMediaKeysManager *manager) + priv->power_keyboard_proxy = NULL; + } + +- if (priv->upower_proxy) { +- g_object_unref (priv->upower_proxy); +- priv->upower_proxy = NULL; +- } +- + if (priv->cancellable != NULL) { + g_cancellable_cancel (priv->cancellable); + g_object_unref (priv->cancellable); +@@ -2363,9 +2398,85 @@ gsd_media_keys_manager_class_init (GsdMediaKeysManagerClass *klass) + } + + static void ++inhibit_done (GObject *source, ++ GAsyncResult *result, ++ gpointer user_data) ++{ ++ GDBusProxy *proxy = G_DBUS_PROXY (source); ++ GsdMediaKeysManager *manager = GSD_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 + gsd_media_keys_manager_init (GsdMediaKeysManager *manager) + { ++ GError *error; ++ GDBusConnection *bus; ++ ++ error = NULL; + manager->priv = GSD_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 (), ++ "GNOME handling keypresses", ++ "block"), ++ 0, ++ G_MAXINT, ++ NULL, ++ NULL, ++ inhibit_done, ++ manager); ++ + } + + static void +@@ -2382,6 +2493,8 @@ gsd_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 (gsd_media_keys_manager_parent_class)->finalize (object); + } +@@ -2401,21 +2514,6 @@ xrandr_ready_cb (GObject *source_object, + } + + static void +-upower_ready_cb (GObject *source_object, +- GAsyncResult *res, +- GsdMediaKeysManager *manager) +-{ +- GError *error = NULL; +- +- manager->priv->upower_proxy = g_dbus_proxy_new_finish (res, &error); +- if (manager->priv->upower_proxy == NULL) { +- g_warning ("Failed to get proxy for upower: %s", +- error->message); +- g_error_free (error); +- } +-} +- +-static void + power_screen_ready_cb (GObject *source_object, + GAsyncResult *res, + GsdMediaKeysManager *manager) +@@ -2517,16 +2615,6 @@ register_manager (GsdMediaKeysManager *manager) + manager->priv->bus_cancellable, + (GAsyncReadyCallback) on_bus_gotten, + manager); +- +- g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, +- G_DBUS_PROXY_FLAGS_NONE, +- NULL, +- "org.freedesktop.UPower", +- "/org/freedesktop/UPower", +- "org.freedesktop.UPower", +- NULL, +- (GAsyncReadyCallback) upower_ready_cb, +- manager); + } + + GsdMediaKeysManager * +diff --git a/plugins/power/gsd-power-manager.c b/plugins/power/gsd-power-manager.c +index 070cf32..18fcedf 100644 +--- a/plugins/power/gsd-power-manager.c ++++ b/plugins/power/gsd-power-manager.c +@@ -1,7 +1,7 @@ + /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2007 William Jon McCann +- * Copyright (C) 2011 Richard Hughes ++ * Copyright (C) 2011-2012 Richard Hughes + * Copyright (C) 2011 Ritesh Khadgaray + * + * This program is free software; you can redistribute it and/or modify +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + + #define GNOME_DESKTOP_USE_UNSTABLE_API + #include +@@ -43,7 +44,6 @@ + #include "gnome-settings-session.h" + #include "gsd-enums.h" + #include "gsd-power-manager.h" +-#include "gsd-power-helper.h" + + #define GNOME_SESSION_DBUS_NAME "org.gnome.SessionManager" + #define GNOME_SESSION_DBUS_PATH "/org/gnome/SessionManager" +@@ -78,6 +78,10 @@ + #define GSD_POWER_MANAGER_RECALL_DELAY 30 /* seconds */ + #define GSD_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 */ + +@@ -193,14 +197,20 @@ struct GsdPowerManagerPrivate + ca_context *canberra_context; + ca_proplist *critical_alert_loop_props; + guint32 critical_alert_timeout_id; +- GDBusProxy *screensaver_proxy; + GDBusProxy *session_proxy; + GDBusProxy *session_presence_proxy; + GpmIdletime *idletime; + GsdPowerIdleMode current_idle_mode; +- guint lid_close_safety_timer_id; + GtkStatusIcon *status_icon; + guint xscreensaver_watchdog_timer_id; ++ ++ /* systemd stuff */ ++ GDBusProxy *logind_proxy; ++ gint inhibit_lid_switch_fd; ++ gboolean inhibit_lid_switch_taken; ++ gint inhibit_suspend_fd; ++ gboolean inhibit_suspend_taken; ++ guint inhibit_lid_switch_timer_id; + }; + + enum { +@@ -217,8 +227,8 @@ static GIcon *engine_get_icon (GsdPowerManager *manager); + static gchar *engine_get_summary (GsdPowerManager *manager); + static void do_power_action_type (GsdPowerManager *manager, GsdPowerActionType action_type); + static void do_lid_closed_action (GsdPowerManager *manager); +-static void lock_screensaver (GsdPowerManager *manager); +-static void kill_lid_close_safety_timer (GsdPowerManager *manager); ++static void uninhibit_lid_switch (GsdPowerManager *manager); ++static gboolean external_monitor_is_connected (GnomeRRScreen *screen); + + G_DEFINE_TYPE (GsdPowerManager, gsd_power_manager, G_TYPE_OBJECT) + +@@ -2048,6 +2058,57 @@ gnome_session_shutdown (void) + } + + static void ++action_poweroff (GsdPowerManager *manager) ++{ ++ if (manager->priv->logind_proxy == NULL) { ++ g_warning ("no systemd support"); ++ return; ++ } ++ g_dbus_proxy_call (manager->priv->logind_proxy, ++ "PowerOff", ++ g_variant_new ("(b)", FALSE), ++ G_DBUS_CALL_FLAGS_NONE, ++ G_MAXINT, ++ NULL, ++ NULL, ++ NULL); ++} ++ ++static void ++action_suspend (GsdPowerManager *manager) ++{ ++ if (manager->priv->logind_proxy == NULL) { ++ g_warning ("no systemd support"); ++ return; ++ } ++ g_dbus_proxy_call (manager->priv->logind_proxy, ++ "Suspend", ++ g_variant_new ("(b)", FALSE), ++ G_DBUS_CALL_FLAGS_NONE, ++ G_MAXINT, ++ NULL, ++ NULL, ++ NULL); ++} ++ ++static void ++action_hibernate (GsdPowerManager *manager) ++{ ++ if (manager->priv->logind_proxy == NULL) { ++ g_warning ("no systemd support"); ++ return; ++ } ++ g_dbus_proxy_call (manager->priv->logind_proxy, ++ "Hibernate", ++ g_variant_new ("(b)", FALSE), ++ G_DBUS_CALL_FLAGS_NONE, ++ G_MAXINT, ++ NULL, ++ NULL, ++ NULL); ++} ++ ++static void + do_power_action_type (GsdPowerManager *manager, + GsdPowerActionType action_type) + { +@@ -2056,19 +2117,19 @@ do_power_action_type (GsdPowerManager *manager, + + switch (action_type) { + case GSD_POWER_ACTION_SUSPEND: +- gsd_power_suspend (manager->priv->upower_proxy); ++ action_suspend (manager); + break; + case GSD_POWER_ACTION_INTERACTIVE: + gnome_session_shutdown (); + break; + case GSD_POWER_ACTION_HIBERNATE: +- gsd_power_hibernate (manager->priv->upower_proxy); ++ action_hibernate (manager); + break; + case GSD_POWER_ACTION_SHUTDOWN: + /* this is only used on critically low battery where + * hibernate is not available and is marginally better + * than just powering down the computer mid-write */ +- gsd_power_poweroff (); ++ action_poweroff (manager); + break; + case GSD_POWER_ACTION_BLANK: + ret = gnome_rr_screen_set_dpms_mode (manager->priv->x11_screen, +@@ -2140,85 +2201,20 @@ upower_kbd_toggle (GsdPowerManager *manager, + return ret; + } + +-static void +-do_lid_open_action (GsdPowerManager *manager) +-{ +- gboolean ret; +- GError *error = NULL; +- +- /* play a sound, using sounds from the naming spec */ +- ca_context_play (manager->priv->canberra_context, 0, +- CA_PROP_EVENT_ID, "lid-open", +- /* TRANSLATORS: this is the sound description */ +- CA_PROP_EVENT_DESCRIPTION, _("Lid has been opened"), +- NULL); +- +- /* ensure we turn the panel back on after lid open */ +- 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 lid open: %s", +- error->message); +- g_clear_error (&error); +- } +- +- /* only toggle keyboard if present and already toggled off */ +- if (manager->priv->upower_kdb_proxy != NULL && +- manager->priv->kbd_brightness_old != -1) { +- ret = upower_kbd_toggle (manager, &error); +- if (!ret) { +- g_warning ("failed to turn the kbd backlight on: %s", +- error->message); +- g_error_free (error); +- } +- } +- +- kill_lid_close_safety_timer (manager); +-} +- + static gboolean +-is_on (GnomeRROutput *output) ++inhibit_lid_switch_timer_cb (GsdPowerManager *manager) + { +- GnomeRRCrtc *crtc; +- +- crtc = gnome_rr_output_get_crtc (output); +- if (!crtc) +- return FALSE; +- return gnome_rr_crtc_get_current_mode (crtc) != NULL; +-} +- +-static gboolean +-non_laptop_outputs_are_all_off (GnomeRRScreen *screen) +-{ +- GnomeRROutput **outputs; +- int i; +- +- outputs = gnome_rr_screen_list_outputs (screen); +- for (i = 0; outputs[i] != NULL; i++) { +- if (gnome_rr_output_is_laptop (outputs[i])) +- continue; +- +- if (is_on (outputs[i])) +- return FALSE; ++ if (!external_monitor_is_connected (manager->priv->x11_screen) || ++ g_settings_get_boolean (manager->priv->settings, ++ "lid-close-suspend-with-external-monitor")) { ++ g_debug ("no external monitors for a while; uninhibiting lid close"); ++ uninhibit_lid_switch (manager); ++ manager->priv->inhibit_lid_switch_timer_id = 0; ++ return G_SOURCE_REMOVE; + } + +- return TRUE; +-} +- +-/* Timeout callback used to check conditions when the laptop's lid is closed but +- * the machine is not suspended yet. We try to suspend again, so that the laptop +- * won't overheat if placed in a backpack. +- */ +-static gboolean +-lid_close_safety_timer_cb (GsdPowerManager *manager) +-{ +- manager->priv->lid_close_safety_timer_id = 0; +- +- g_debug ("lid has been closed for a while; trying to suspend again"); +- do_lid_closed_action (manager); +- +- return FALSE; ++ g_debug ("external monitor still there; trying again later"); ++ return G_SOURCE_CONTINUE; + } + + /* Sets up a timer to be triggered some seconds after closing the laptop lid +@@ -2226,82 +2222,73 @@ lid_close_safety_timer_cb (GsdPowerManager *manager) + * again in the timeout handler to see if we can suspend then. + */ + static void +-setup_lid_close_safety_timer (GsdPowerManager *manager) ++setup_inhibit_lid_switch_timer (GsdPowerManager *manager) + { +- if (manager->priv->lid_close_safety_timer_id != 0) ++ if (manager->priv->inhibit_lid_switch_timer_id != 0) { ++ g_debug ("lid close safety timer already set up"); + return; ++ } ++ ++ g_debug ("setting up lid close safety timer"); + +- manager->priv->lid_close_safety_timer_id = g_timeout_add_seconds (GSD_POWER_MANAGER_LID_CLOSE_SAFETY_TIMEOUT, +- (GSourceFunc) lid_close_safety_timer_cb, ++ manager->priv->inhibit_lid_switch_timer_id = g_timeout_add_seconds (GSD_POWER_MANAGER_LID_CLOSE_SAFETY_TIMEOUT, ++ (GSourceFunc) inhibit_lid_switch_timer_cb, + manager); +- g_source_set_name_by_id (manager->priv->lid_close_safety_timer_id, "[GsdPowerManager] lid close safety timer"); ++ g_source_set_name_by_id (manager->priv->inhibit_lid_switch_timer_id, "[GsdPowerManager] lid close safety timer"); + } + + static void +-kill_lid_close_safety_timer (GsdPowerManager *manager) ++restart_inhibit_lid_switch_timer (GsdPowerManager *manager) + { +- if (manager->priv->lid_close_safety_timer_id != 0) { +- g_source_remove (manager->priv->lid_close_safety_timer_id); +- manager->priv->lid_close_safety_timer_id = 0; ++ if (manager->priv->inhibit_lid_switch_timer_id != 0) { ++ g_debug ("restarting lid close safety timer"); ++ g_source_remove (manager->priv->inhibit_lid_switch_timer_id); ++ manager->priv->inhibit_lid_switch_timer_id = 0; ++ setup_inhibit_lid_switch_timer (manager); + } + } + + static void +-suspend_with_lid_closed (GsdPowerManager *manager) ++do_lid_open_action (GsdPowerManager *manager) + { + gboolean ret; + GError *error = NULL; +- GsdPowerActionType action_type; + +- /* maybe lock the screen if the lid is closed */ +- lock_screensaver (manager); +- +- /* we have different settings depending on AC state */ +- if (up_client_get_on_battery (manager->priv->up_client)) { +- action_type = g_settings_get_enum (manager->priv->settings, +- "lid-close-battery-action"); +- } else { +- action_type = g_settings_get_enum (manager->priv->settings, +- "lid-close-ac-action"); +- } +- +- /* check we won't melt when the lid is closed */ +- if (action_type != GSD_POWER_ACTION_SUSPEND && +- action_type != GSD_POWER_ACTION_HIBERNATE) { +- if (up_client_get_lid_force_sleep (manager->priv->up_client)) { +- g_warning ("to prevent damage, now forcing suspend"); +- do_power_action_type (manager, GSD_POWER_ACTION_SUSPEND); +- return; +- } +- } ++ /* play a sound, using sounds from the naming spec */ ++ ca_context_play (manager->priv->canberra_context, 0, ++ CA_PROP_EVENT_ID, "lid-open", ++ /* TRANSLATORS: this is the sound description */ ++ CA_PROP_EVENT_DESCRIPTION, _("Lid has been opened"), ++ NULL); + +- /* ensure we turn the panel back on after resume */ ++ /* ensure we turn the panel back on after lid open */ + ret = gnome_rr_screen_set_dpms_mode (manager->priv->x11_screen, +- GNOME_RR_DPMS_OFF, ++ GNOME_RR_DPMS_ON, + &error); + if (!ret) { +- g_warning ("failed to turn the panel off after lid close: %s", ++ g_warning ("failed to turn the panel on after lid open: %s", + error->message); +- g_error_free (error); ++ g_clear_error (&error); + } + +- /* only toggle keyboard if present and not already toggled */ +- if (manager->priv->upower_kdb_proxy && +- manager->priv->kbd_brightness_old == -1) { ++ /* only toggle keyboard if present and already toggled off */ ++ if (manager->priv->upower_kdb_proxy != NULL && ++ manager->priv->kbd_brightness_old != -1) { + ret = upower_kbd_toggle (manager, &error); + if (!ret) { +- g_warning ("failed to turn the kbd backlight off: %s", ++ g_warning ("failed to turn the kbd backlight on: %s", + error->message); + g_error_free (error); + } + } +- +- do_power_action_type (manager, action_type); + } + + static void + do_lid_closed_action (GsdPowerManager *manager) + { ++ gboolean ret; ++ GError *error = NULL; ++ + /* play a sound, using sounds from the naming spec */ + ca_context_play (manager->priv->canberra_context, 0, + CA_PROP_EVENT_ID, "lid-close", +@@ -2309,21 +2296,22 @@ do_lid_closed_action (GsdPowerManager *manager) + CA_PROP_EVENT_DESCRIPTION, _("Lid has been closed"), + NULL); + ++ /* turn the panel off if the lid is closed (mainly for Dells...) */ ++ ret = gnome_rr_screen_set_dpms_mode (manager->priv->x11_screen, ++ GNOME_RR_DPMS_OFF, ++ &error); ++ if (!ret) { ++ g_warning ("failed to turn the panel off after lid close: %s", ++ error->message); ++ g_error_free (error); ++ } ++ + /* refresh RANDR so we get an accurate view of what monitors are plugged in when the lid is closed */ + gnome_rr_screen_refresh (manager->priv->x11_screen, NULL); /* NULL-GError */ + +- /* perform policy action */ +- if (g_settings_get_boolean (manager->priv->settings, "lid-close-suspend-with-external-monitor") +- || non_laptop_outputs_are_all_off (manager->priv->x11_screen)) { +- g_debug ("lid is closed; suspending or hibernating"); +- suspend_with_lid_closed (manager); +- } else { +- g_debug ("lid is closed; not suspending nor hibernating since some external monitor outputs are still active"); +- setup_lid_close_safety_timer (manager); +- } ++ restart_inhibit_lid_switch_timer (manager); + } + +- + static void + up_client_changed_cb (UpClient *client, GsdPowerManager *manager) + { +@@ -2343,6 +2331,7 @@ up_client_changed_cb (UpClient *client, GsdPowerManager *manager) + if (manager->priv->lid_is_closed == tmp) + return; + manager->priv->lid_is_closed = tmp; ++ g_debug ("up changed: lid is now %s", tmp ? "closed" : "open"); + + /* fake a keypress */ + if (tmp) +@@ -3294,30 +3283,6 @@ gsd_power_manager_class_init (GsdPowerManagerClass *klass) + } + + static void +-sleep_cb_screensaver_proxy_ready_cb (GObject *source_object, +- GAsyncResult *res, +- gpointer user_data) +-{ +- GError *error = NULL; +- GsdPowerManager *manager = GSD_POWER_MANAGER (user_data); +- +- manager->priv->screensaver_proxy = g_dbus_proxy_new_for_bus_finish (res, &error); +- if (manager->priv->screensaver_proxy == NULL) { +- g_warning ("Could not connect to gnome-screensaver: %s", +- error->message); +- g_error_free (error); +- return; +- } +- +- /* Finish the upower_notify_sleep_cb() call by locking the screen */ +- g_debug ("gnome-screensaver activated, doing gnome-screensaver lock"); +- g_dbus_proxy_call (manager->priv->screensaver_proxy, +- "Lock", +- NULL, G_DBUS_CALL_FLAGS_NONE, -1, +- NULL, NULL, NULL); +-} +- +-static void + idle_dbus_signal_cb (GDBusProxy *proxy, + const gchar *sender_name, + const gchar *signal_name, +@@ -3469,75 +3434,38 @@ out: + } + + static void +-lock_screensaver (GsdPowerManager *manager) ++lock_screensaver (GsdPowerManager *manager, ++ GSourceFunc done_cb) + { + gboolean do_lock; + + do_lock = g_settings_get_boolean (manager->priv->settings_screensaver, + "lock-enabled"); +- if (!do_lock) ++ if (!do_lock && done_cb) { ++ done_cb (manager); + return; +- +- if (manager->priv->screensaver_proxy != NULL) { +- g_debug ("doing gnome-screensaver lock"); +- g_dbus_proxy_call (manager->priv->screensaver_proxy, +- "Lock", +- NULL, G_DBUS_CALL_FLAGS_NONE, -1, +- NULL, NULL, NULL); +- } else { +- /* 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, +- GsdPowerManager *manager) +-{ +- lock_screensaver (manager); +-} +- +-static void +-upower_notify_resume_cb (UpClient *client, +- UpSleepKind sleep_kind, +- GsdPowerManager *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); +- } +- +- /* 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); +- } ++ g_dbus_connection_call (manager->priv->connection, ++ GS_DBUS_NAME, ++ GS_DBUS_PATH, ++ GS_DBUS_INTERFACE, ++ "Lock", ++ NULL, NULL, ++ G_DBUS_CALL_FLAGS_NONE, -1, ++ NULL, NULL, NULL); ++ ++ /* Wait until gnome-shell shield animation is done ++ * ++ * FIXME: the shell should mark the lock as active ++ * when the shield is down, then we could wait for ++ * that. This would also fix the problem that we wait ++ * needlessly when the shell has already locked the ++ * screen because it is initiating the suspend. ++ * ++ * https://bugzilla.gnome.org/show_bug.cgi?id=685053 ++ */ ++ g_timeout_add (500, done_cb, manager); + } + + static void +@@ -3696,6 +3624,287 @@ 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); ++ GsdPowerManager *manager = GSD_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 (GsdPowerManager *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 ++uninhibit_lid_switch (GsdPowerManager *manager) ++{ ++ if (manager->priv->inhibit_lid_switch_fd == -1) { ++ g_debug ("no lid-switch inhibitor"); ++ return; ++ } ++ g_debug ("Removing lid switch system inhibitor"); ++ close (manager->priv->inhibit_lid_switch_fd); ++ manager->priv->inhibit_lid_switch_fd = -1; ++ manager->priv->inhibit_lid_switch_taken = FALSE; ++} ++ ++static void ++inhibit_suspend_done (GObject *source, ++ GAsyncResult *result, ++ gpointer user_data) ++{ ++ GDBusProxy *proxy = G_DBUS_PROXY (source); ++ GsdPowerManager *manager = GSD_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 (GsdPowerManager *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 (), ++ "GNOME needs to lock the screen", ++ "delay"), ++ 0, ++ G_MAXINT, ++ NULL, ++ NULL, ++ inhibit_suspend_done, ++ manager); ++} ++ ++static void ++uninhibit_suspend (GsdPowerManager *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 = TRUE; ++} ++ ++static gboolean ++randr_output_is_on (GnomeRROutput *output) ++{ ++ GnomeRRCrtc *crtc; ++ ++ crtc = gnome_rr_output_get_crtc (output); ++ if (!crtc) ++ return FALSE; ++ return gnome_rr_crtc_get_current_mode (crtc) != NULL; ++} ++ ++static gboolean ++external_monitor_is_connected (GnomeRRScreen *screen) ++{ ++ GnomeRROutput **outputs; ++ guint i; ++ ++ if (g_file_test ("/tmp/external_connected", G_FILE_TEST_EXISTS)) ++ return TRUE; ++ ++ /* see if we have more than one screen plugged in */ ++ outputs = gnome_rr_screen_list_outputs (screen); ++ for (i = 0; outputs[i] != NULL; i++) { ++ if (randr_output_is_on (outputs[i]) && ++ !gnome_rr_output_is_laptop (outputs[i])) ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++static void ++on_randr_event (GnomeRRScreen *screen, gpointer user_data) ++{ ++ GsdPowerManager *manager = GSD_POWER_MANAGER (user_data); ++ ++ /* when a second monitor is plugged in, we take the ++ * handle-lid-switch inhibitor lock of logind to prevent ++ * it from suspending. ++ * ++ * Uninhibiting is done in the inhibit_lid_switch_timer, ++ * since we want to give users a few seconds when unplugging ++ * and replugging an external monitor, not suspend right away. ++ */ ++ if (external_monitor_is_connected (screen) && ++ !g_settings_get_boolean (manager->priv->settings, ++ "lid-close-suspend-with-external-monitor")) { ++ inhibit_lid_switch (manager); ++ setup_inhibit_lid_switch_timer (manager); ++ } ++ else { ++ restart_inhibit_lid_switch_timer (manager); ++ } ++} ++ ++static gboolean ++screen_lock_done_cb (gpointer data) ++{ ++ GsdPowerManager *manager = data; ++ ++ /* lift the delay inhibit, so logind can proceed */ ++ uninhibit_suspend (manager); ++ ++ return FALSE; ++} ++ ++static void ++handle_suspend_actions (GsdPowerManager *manager) ++{ ++ gboolean ret; ++ GError *error = NULL; ++ ++ /* 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); ++ } ++ ++ lock_screensaver (manager, screen_lock_done_cb); ++} ++ ++static void ++handle_resume_actions (GsdPowerManager *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 ++logind_proxy_signal_cb (GDBusProxy *proxy, ++ const gchar *sender_name, ++ const gchar *signal_name, ++ GVariant *parameters, ++ gpointer user_data) ++{ ++ GsdPowerManager *manager = GSD_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); ++ } ++} ++ + gboolean + gsd_power_manager_start (GsdPowerManager *manager, + GError **error) +@@ -3705,6 +3914,25 @@ gsd_power_manager_start (GsdPowerManager *manager, + g_debug ("Starting power manager"); + gnome_settings_profile_start (NULL); + ++ 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); ++ if (manager->priv->logind_proxy == NULL) { ++ g_warning ("no systemd support"); ++ return FALSE; ++ } ++ 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); ++ + /* track the active session */ + manager->priv->session = gnome_settings_session_new (); + g_signal_connect (manager->priv->session, "notify::state", +@@ -3719,10 +3947,6 @@ gsd_power_manager_start (GsdPowerManager *manager, + G_CALLBACK (engine_settings_key_changed_cb), manager); + manager->priv->settings_screensaver = g_settings_new ("org.gnome.desktop.screensaver"); + manager->priv->up_client = up_client_new (); +- g_signal_connect (manager->priv->up_client, "notify-sleep", +- G_CALLBACK (upower_notify_sleep_cb), manager); +- g_signal_connect (manager->priv->up_client, "notify-resume", +- G_CALLBACK (upower_notify_resume_cb), manager); + manager->priv->lid_is_closed = up_client_get_lid_is_closed (manager->priv->up_client); + g_signal_connect (manager->priv->up_client, "device-added", + G_CALLBACK (engine_device_added_cb), manager); +@@ -3836,6 +4060,9 @@ gsd_power_manager_start (GsdPowerManager *manager, + manager->priv->x11_screen = gnome_rr_screen_new (gdk_screen_get_default (), error); + if (manager->priv->x11_screen == NULL) + return FALSE; ++ g_signal_connect (manager->priv->x11_screen, "changed", G_CALLBACK (on_randr_event), manager); ++ /* set up initial state */ ++ on_randr_event (manager->priv->x11_screen, manager); + + /* ensure the default dpms timeouts are cleared */ + ret = gnome_rr_screen_set_dpms_mode (manager->priv->x11_screen, +@@ -3865,6 +4092,11 @@ gsd_power_manager_stop (GsdPowerManager *manager) + { + g_debug ("Stopping power manager"); + ++ if (manager->priv->inhibit_lid_switch_timer_id != 0) { ++ g_source_remove (manager->priv->inhibit_lid_switch_timer_id); ++ manager->priv->inhibit_lid_switch_timer_id = 0; ++ } ++ + if (manager->priv->bus_cancellable != NULL) { + g_cancellable_cancel (manager->priv->bus_cancellable); + g_object_unref (manager->priv->bus_cancellable); +@@ -3876,8 +4108,6 @@ gsd_power_manager_stop (GsdPowerManager *manager) + manager->priv->introspection_data = NULL; + } + +- kill_lid_close_safety_timer (manager); +- + g_signal_handlers_disconnect_by_data (manager->priv->up_client, manager); + + g_clear_object (&manager->priv->connection); +@@ -3885,6 +4115,19 @@ gsd_power_manager_stop (GsdPowerManager *manager) + g_clear_object (&manager->priv->settings); + g_clear_object (&manager->priv->settings_screensaver); + g_clear_object (&manager->priv->up_client); ++ ++ 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; ++ } ++ ++ g_clear_object (&manager->priv->logind_proxy); + g_clear_object (&manager->priv->x11_screen); + + g_ptr_array_unref (manager->priv->devices_array); +@@ -3918,6 +4161,8 @@ static void + gsd_power_manager_init (GsdPowerManager *manager) + { + manager->priv = GSD_POWER_MANAGER_GET_PRIVATE (manager); ++ manager->priv->inhibit_lid_switch_fd = -1; ++ manager->priv->inhibit_suspend_fd = -1; + } + + static void +-- +1.7.12.2 + diff --git a/srcpkgs/gnome-settings-daemon/template b/srcpkgs/gnome-settings-daemon/template index e5e2d8c743..bd845ac5d4 100644 --- a/srcpkgs/gnome-settings-daemon/template +++ b/srcpkgs/gnome-settings-daemon/template @@ -1,18 +1,19 @@ # Template file for 'gnome-settings-daemon' pkgname=gnome-settings-daemon version=3.6.1 -revision=1 +revision=2 +patch_args="-Np1" build_style=gnu-configure subpackages="$pkgname-devel" configure_args="--disable-static --enable-cups ---disable-schemas-compile --enable-systemd --disable-packagekit" + --disable-schemas-compile --enable-systemd --disable-packagekit" depends="pulseaudio hicolor-icon-theme" -makedepends="pkg-config intltool libxslt docbook-xsl -colord-devel>=0.1.23_3 libxklavier-devel libnotify-devel -gtk+3-devel>=3.6.0_3 libcanberra-devel pulseaudio-devel nss-devel -startup-notification-devel gnome-desktop-devel>=3.6.0 libgnomekbd-devel -libxkbfile-devel xf86-input-wacom-devel libwacom-devel systemd-devel -ibus-devel>=1.4.99 cups-devel libgudev-devel upower-devel" +makedepends="automake pkg-config intltool libxslt docbook-xsl + colord-devel>=0.1.23_3 libxklavier-devel libnotify-devel + gtk+3-devel>=3.6.0_3 libcanberra-devel pulseaudio-devel nss-devel + startup-notification-devel gnome-desktop-devel>=3.6.0 libgnomekbd-devel + libxkbfile-devel xf86-input-wacom-devel libwacom-devel systemd-devel + ibus-devel>=1.4.99 cups-devel libgudev-devel upower-devel" fulldepends="gsettings-desktop-schemas" short_desc="GNOME settings daemon" maintainer="Juan RP " @@ -22,3 +23,14 @@ distfiles="${GNOME_SITE}/$pkgname/3.6/$pkgname-$version.tar.xz" checksum=1fe96e0709d7c618d90cc1bfcddc46eede3c2cdb305f5e7f4cb388d43dd5526a long_desc=" This package provides a daemon to handle settings on the GNOME desktop." + +pre_configure() { + aclocal && automake +} + +post_install() { + # Plugins that aren't installed still have schema references + # and cause gsettings errors - remove the references we're not using + sed -i '/org\.gnome\.settings-daemon\.plugins\.updates/d' \ + ${DESTDIR}/usr/share/glib-2.0/schemas/org.gnome.settings-daemon.plugins.gschema.xml +}