From 234e5c835559b0afe56c2af246e2148ac5b47a07 Mon Sep 17 00:00:00 2001 From: Ali Akbar Date: Mon, 26 Aug 2019 20:31:54 +0700 Subject: Ensure lock on suspend and unlock on resume This patch is adopted from xfce4-screensaver: https://git.xfce.org/apps/xfce4-screensaver/commit/?id=9e53bb2866 Modified to match screen locking behavior of mate-power-manager. Introduced new Inhibitor lock to make sure lock was in place and user will be greeted with unlock dialog when resumes from suspend/ hibernate. --- src/gs-listener-dbus.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++- src/gs-listener-dbus.h | 2 + src/gs-monitor.c | 13 ++++++ 3 files changed, 119 insertions(+), 2 deletions(-) diff --git a/src/gs-listener-dbus.c b/src/gs-listener-dbus.c index a37e3f9..4abcd2b 100644 --- a/src/gs-listener-dbus.c +++ b/src/gs-listener-dbus.c @@ -96,7 +96,8 @@ struct GSListenerPrivate char *session_id; #ifdef WITH_SYSTEMD - gboolean have_systemd; + gboolean have_systemd; + gint logind_inhibit_lock; #endif guint32 ck_throttle_cookie; @@ -122,7 +123,8 @@ enum ACTIVE_CHANGED, THROTTLE_CHANGED, SHOW_MESSAGE, - LAST_SIGNAL + PREPARE_FOR_SLEEP, + LAST_SIGNAL, }; enum @@ -1619,6 +1621,66 @@ failure: gs_debug ("Failed to decode PropertiesChanged message."); return FALSE; } + +static gint +take_logind_inhibit_lock (DBusConnection *connection) +{ + DBusMessage *message; + DBusMessage *reply; + DBusError error; + DBusMessageIter reply_iter; + gint fd; + + const char* what = "sleep"; + const char* who = g_get_user_name (); + const char* why = "Lock screen before sleep"; + const char* mode = "delay"; + + g_return_val_if_fail (connection != NULL, FALSE); + + dbus_error_init (&error); + + message = dbus_message_new_method_call (SYSTEMD_LOGIND_SERVICE, + SYSTEMD_LOGIND_PATH, + SYSTEMD_LOGIND_INTERFACE, + "Inhibit"); + if (message == NULL) + { + gs_debug ("Couldn't allocate the dbus message"); + return 0; + } + + if (dbus_message_append_args (message, + DBUS_TYPE_STRING, &what, + DBUS_TYPE_STRING, &who, + DBUS_TYPE_STRING, &why, + DBUS_TYPE_STRING, &mode, + DBUS_TYPE_INVALID) == FALSE) + { + gs_debug ("Couldn't add args to the dbus message"); + return 0; + } + + reply = dbus_connection_send_with_reply_and_block (connection, message, + -1, &error); + dbus_message_unref (message); + + if (dbus_error_is_set (&error)) + { + gs_debug ("%s raised:\n %s\n\n", error.name, error.message); + dbus_error_free (&error); + return 0; + } + + dbus_message_iter_init (reply, &reply_iter); + dbus_message_iter_get_basic (&reply_iter, &fd); + + dbus_message_unref (reply); + + gs_debug ("System inhibitor fd is %d\n", fd); + + return fd; +} #endif static DBusHandlerResult @@ -1656,6 +1718,28 @@ listener_dbus_handle_system_message (DBusConnection *connection, g_signal_emit (listener, signals [LOCK], 0); } + return DBUS_HANDLER_RESULT_HANDLED; + } else if (dbus_message_is_signal (message, SYSTEMD_LOGIND_INTERFACE, "PrepareForSleep")) { + gboolean active = 0; + DBusError error; + + dbus_error_init (&error); + dbus_message_get_args (message, &error, DBUS_TYPE_BOOLEAN, &active, DBUS_TYPE_INVALID); + if (active) { + gs_debug ("Logind wanted to sleep"); + g_signal_emit (listener, signals [PREPARE_FOR_SLEEP], 0, active); + if (listener->priv->logind_inhibit_lock) { + gs_debug ("Releasing inihibitor lock"); + close (listener->priv->logind_inhibit_lock); + listener->priv->logind_inhibit_lock = 0; + } + } else { + gs_debug ("Logind resumed from sleep"); + listener->priv->logind_inhibit_lock = take_logind_inhibit_lock (listener->priv->system_connection); + g_signal_emit (listener, signals [PREPARE_FOR_SLEEP], 0, active); + } + gs_debug ("Logind PrepareForSleepHandled"); + return DBUS_HANDLER_RESULT_HANDLED; } else if (dbus_message_is_signal (message, DBUS_INTERFACE_PROPERTIES, "PropertiesChanged")) { @@ -2130,6 +2214,17 @@ gs_listener_class_init (GSListenerClass *klass) G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); + signals [PREPARE_FOR_SLEEP] = + g_signal_new ("prepare-for-sleep", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GSListenerClass, prepare_for_sleep), + NULL, + NULL, + g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, + 1, + G_TYPE_BOOLEAN); g_object_class_install_property (object_class, PROP_ACTIVE, @@ -2272,6 +2367,13 @@ gs_listener_acquire (GSListener *listener, ",interface='"SYSTEMD_LOGIND_SESSION_INTERFACE"'" ",member='Lock'", NULL); + dbus_bus_add_match (listener->priv->system_connection, + "type='signal'" + ",sender='"SYSTEMD_LOGIND_SERVICE"'" + ",interface='"SYSTEMD_LOGIND_INTERFACE"'" + ",member='PrepareForSleep'", + NULL); + listener->priv->logind_inhibit_lock = take_logind_inhibit_lock (listener->priv->system_connection); dbus_bus_add_match (listener->priv->system_connection, "type='signal'" ",sender='"SYSTEMD_LOGIND_SERVICE"'" diff --git a/src/gs-listener-dbus.h b/src/gs-listener-dbus.h index f86e75e..8f1192c 100644 --- a/src/gs-listener-dbus.h +++ b/src/gs-listener-dbus.h @@ -58,6 +58,8 @@ typedef struct const char *summary, const char *body, const char *icon); + void (* prepare_for_sleep) (GSListener *listener, + gboolean prepare); /* prepare or resume from sleep */ } GSListenerClass; diff --git a/src/gs-monitor.c b/src/gs-monitor.c index 732a59b..1601d75 100644 --- a/src/gs-monitor.c +++ b/src/gs-monitor.c @@ -280,6 +280,17 @@ static void listener_simulate_user_activity_cb(GSListener* listener, GSMonitor* gs_monitor_simulate_user_activity(monitor); } +static void listener_prepare_for_sleep_cb(GSListener* listener, gboolean prepare, GSMonitor* monitor) +{ + gboolean locked; + + gs_manager_get_lock_active(monitor->priv->manager, &locked); + if (locked) { + /* show unlock dialog */ + gs_manager_show_message(monitor->priv->manager, NULL, NULL, NULL); + } +} + static void _gs_monitor_update_from_prefs(GSMonitor* monitor, GSPrefs* prefs) { gboolean idle_detection_enabled; @@ -347,6 +358,7 @@ static void disconnect_listener_signals(GSMonitor* monitor) g_signal_handlers_disconnect_by_func(monitor->priv->listener, listener_throttle_changed_cb, monitor); g_signal_handlers_disconnect_by_func(monitor->priv->listener, listener_simulate_user_activity_cb, monitor); g_signal_handlers_disconnect_by_func(monitor->priv->listener, listener_show_message_cb, monitor); + g_signal_handlers_disconnect_by_func(monitor->priv->listener, listener_prepare_for_sleep_cb, monitor); } static void connect_listener_signals(GSMonitor* monitor) @@ -358,6 +370,7 @@ static void connect_listener_signals(GSMonitor* monitor) g_signal_connect(monitor->priv->listener, "throttle-changed", G_CALLBACK(listener_throttle_changed_cb), monitor); g_signal_connect(monitor->priv->listener, "simulate-user-activity", G_CALLBACK(listener_simulate_user_activity_cb), monitor); g_signal_connect(monitor->priv->listener, "show-message", G_CALLBACK(listener_show_message_cb), monitor); + g_signal_connect(monitor->priv->listener, "prepare-for-sleep", G_CALLBACK(listener_prepare_for_sleep_cb), monitor); } static void on_watcher_status_message_changed(GSWatcher* watcher, GParamSpec* pspec, GSMonitor* monitor) -- cgit v1.2.1