diff --git a/debian/phosh.postinst.in b/debian/phosh.postinst.in index fc3790d4e32b1492924d735dfe09664e0440eca0..75af5e0c5fdc241c3cc602aa93f02902924594ba 100644 --- a/debian/phosh.postinst.in +++ b/debian/phosh.postinst.in @@ -2,6 +2,17 @@ set -e +case "$1" in + configure) + # (used by unattended-upgrades etc.) + touch /var/run/reboot-required || true + + if ! grep -Fqsx dbus /run/reboot-required.pkgs; then + echo phosh >> /run/reboot-required.pkgs || true + fi + ;; +esac + if [ "$1" = triggered ]; then "/usr/lib/#MULTIARCH#/glib-2.0/gio-querymodules" "/usr/lib/#MULTIARCH#/phosh/plugins" || true "/usr/lib/#MULTIARCH#/glib-2.0/gio-querymodules" "/usr/lib/#MULTIARCH#/phosh/plugins/prefs" || true diff --git a/docs/gettingstarted.md b/docs/gettingstarted.md index 465f748c31857bb67cd9ac53f5510ab48d46d1c1..2c1238223f2aa12329caadf365cd081d71dc1584 100644 --- a/docs/gettingstarted.md +++ b/docs/gettingstarted.md @@ -74,7 +74,6 @@ as part GNOME session so the start sequence looks like phoc (compositor) -> gnome-session -> phosh (and other session components) ``` - ## Hints This is a unsorted list of hints when developing for Phosh @@ -99,6 +98,10 @@ e.g. the corresponding DBus service went away). In that case the widget should flip a boolean property so the parent container can hide the object via #g_object_bind_property(). +### Screen locking and blanking + +For details see [class@ScreenSaverManager]. + ### Debugging Since phosh is a GTK application you can use diff --git a/src/gnome-shell-manager.c b/src/gnome-shell-manager.c index e73e955508113e365a18fdffcf4b640d94dbe96e..89865fd9e0812debcc0ebff21f41c5c227f4bd09 100644 --- a/src/gnome-shell-manager.c +++ b/src/gnome-shell-manager.c @@ -238,10 +238,21 @@ grab_single_accelerator (PhoshGnomeShellManager *self, g_debug ("Using action id %d for accelerator %s", info->action_id, info->accelerator); g_hash_table_insert (self->info_by_action, GUINT_TO_POINTER (info->action_id), info); - phosh_shell_add_global_keyboard_action_entries (phosh_shell_get_default (), - action_entries, - G_N_ELEMENTS (action_entries), - info); + + if (g_strcmp0 (accelerator, "XF86PowerOff")) { + phosh_shell_add_global_keyboard_action_entries (phosh_shell_get_default (), + action_entries, + G_N_ELEMENTS (action_entries), + info); + } else { + /* + * FIXME: Don't allow binding of power keys so we can blank the screen + * See https://gitlab.gnome.org/GNOME/gnome-settings-daemon/-/issues/703 + * We don't return an error as we want g-s-d to handle all the other keys + */ + g_debug ("Skipping power key grab"); + } + g_assert (info->action_id > 0); return info->action_id; } diff --git a/src/screen-saver-manager.c b/src/screen-saver-manager.c index ddc5a4d14ebbb7e51435021738aa72248f65f1d4..260be011ff707ae94f62e96acd272082ae73f16a 100644 --- a/src/screen-saver-manager.c +++ b/src/screen-saver-manager.c @@ -9,6 +9,7 @@ #define G_LOG_DOMAIN "phosh-screen-saver-manager" #include "screen-saver-manager.h" +#include "session-presence.h" #include "shell.h" #include "idle-manager.h" #include "login1-manager-dbus.h" @@ -17,15 +18,31 @@ #include "session-presence.h" #include "util.h" +#include +#include + /** * PhoshScreenSaverManager: * * Provides the org.gnome.ScreenSaver DBus interface and handles logind's Session * - * See https://people.gnome.org/~mccann/gnome-screensaver/docs/gnome-screensaver.html - * for a (a bit outdated) interface description. It also handles the login1 session - * parts since those are closely related and this keeps #PhoshLockscreenManager free - * of the DBus handling. + * This handles the `org.gnome.ScreenSaver` DBus API for screen locking and unlocking. + * It also handles the login1 session parts since those are closely related and this + * keeps #PhoshLockscreenManager free of any session related DBus handling. + * + * These settings influence screen blanking and locking: + * + * `org.gnome.desktop.session idle-delay`: The session is considered idle after that many + * seconds of inactivity. This isn't monitored by phosh directly but is done by gnome-session that + * in turn uses `GnomeIdleMonitor` which then uses `/org/gnome/Mutter/IdleMonitor/Core` on DBus. + * `/org/gnome/Mutter/IdleMonitor/Core` is implemented by #PhoshIdleManager which in turn gets + * it from phoc which implements the `org_kde_kwin_idle` wayland protocol. + * + * `org.gnome.desktop.screensaver` `lock-enabled`: Whether the screen should be locked after + * the screen-saver is activated. + * + * `org.gnome.desktop.screensaver` `lock-delay`: How long after screen-saver activation should + * the screen be locked. */ #define SCREEN_SAVER_DBUS_NAME "org.gnome.ScreenSaver" @@ -36,6 +53,9 @@ enum { PROP_0, PROP_LOCKSCREEN_MANAGER, + PROP_LOCK_ENABLED, + PROP_LOCK_DELAY, + PROP_ACTIVE, PROP_LAST_PROP }; static GParamSpec *props[PROP_LAST_PROP]; @@ -50,6 +70,15 @@ typedef struct _PhoshScreenSaverManager int dbus_name_id; PhoshLockscreenManager *lockscreen_manager; PhoshSessionPresence *presence; /* gnome-session's presence interface */ + gboolean active; + + GSettings *settings; + gboolean lock_enabled; + gboolean lock_delay; + guint lock_delay_timer_id; + int inhibit_pwr_btn_fd; + int inhibit_suspend_fd; + PhoshMonitor *primary_monitor; PhoshDBusLoginSession *logind_session_proxy; PhoshDBusLoginManager *logind_manager_proxy; @@ -64,6 +93,69 @@ G_DEFINE_TYPE_WITH_CODE (PhoshScreenSaverManager, PHOSH_DBUS_TYPE_SCREEN_SAVER, phosh_screen_saver_manager_screen_saver_iface_init)); + +static gboolean +on_lock_delay_timer_expired (gpointer data) +{ + PhoshScreenSaverManager *self = PHOSH_SCREEN_SAVER_MANAGER (data); + + phosh_lockscreen_manager_set_locked (self->lockscreen_manager, TRUE); + + self->lock_delay_timer_id = 0; + return G_SOURCE_REMOVE; +} + +/* Activate or deactivate screen blank based on `active`. If `lock` is %TRUE locking + is also enabled (honoring the configure delay */ +static void +screen_saver_set_active (PhoshScreenSaverManager *self, gboolean active, gboolean lock) +{ + if (self->active == active) + return; + + g_debug ("Activiting screen saver: %d, lock: %d, lock_delay: %d", active, lock, + self->lock_delay); + + phosh_shell_enable_power_save (phosh_shell_get_default (), active); + + if (!active || !lock) { + g_clear_handle_id (&self->lock_delay_timer_id, g_source_remove); + return; + } + + /* Already locked, no locking to do */ + if (phosh_lockscreen_manager_get_locked (self->lockscreen_manager)) + return; + + /* no delay, lock right away */ + if (self->lock_delay == 0) { + g_clear_handle_id (&self->lock_delay_timer_id, g_source_remove); + phosh_lockscreen_manager_set_locked (self->lockscreen_manager, TRUE); + return; + } + + /* Timer already ticking, don't rearm */ + if (self->lock_delay_timer_id) + return; + + g_debug ("Arming lock delay timer for %d seconds", self->lock_delay); + self->lock_delay_timer_id = g_timeout_add_seconds (self->lock_delay, + on_lock_delay_timer_expired, + self); + g_source_set_name_by_id (self->lock_delay_timer_id, "[phosh] lock_delay_timer"); +} + + +static void +toggle_blank (GSimpleAction *action, GVariant *param, gpointer data) +{ + PhoshScreenSaverManager *self = PHOSH_SCREEN_SAVER_MANAGER (data); + + g_debug ("Power button press, toggling screensaver %d", !self->active); + screen_saver_set_active (self, !self->active, TRUE); +} + + static void phosh_screen_saver_manager_set_property (GObject *object, guint property_id, @@ -76,6 +168,12 @@ phosh_screen_saver_manager_set_property (GObject *object, case PROP_LOCKSCREEN_MANAGER: self->lockscreen_manager = g_value_dup_object (value); break; + case PROP_LOCK_ENABLED: + self->lock_enabled = g_value_get_boolean (value); + break; + case PROP_LOCK_DELAY: + self->lock_delay = g_value_get_int (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -95,6 +193,15 @@ phosh_screen_saver_manager_get_property (GObject *object, case PROP_LOCKSCREEN_MANAGER: g_value_set_object (value, self->lockscreen_manager); break; + case PROP_LOCK_ENABLED: + g_value_set_boolean (value, self->lock_enabled); + break; + case PROP_LOCK_DELAY: + g_value_set_int (value, self->lock_delay); + break; + case PROP_ACTIVE: + self->active = g_value_get_boolean (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -106,15 +213,13 @@ handle_get_active (PhoshDBusScreenSaver *skeleton, GDBusMethodInvocation *invocation) { PhoshScreenSaverManager *self = PHOSH_SCREEN_SAVER_MANAGER (skeleton); - gboolean locked; g_return_val_if_fail (PHOSH_IS_SCREEN_SAVER_MANAGER (self), FALSE); g_return_val_if_fail (PHOSH_IS_LOCKSCREEN_MANAGER (self->lockscreen_manager), FALSE); - locked = phosh_lockscreen_manager_get_locked (self->lockscreen_manager); - g_debug ("DBus call GetActive: %d", locked); + g_debug ("DBus call GetActive: %d", self->active); - phosh_dbus_screen_saver_complete_get_active (skeleton, invocation, locked); + phosh_dbus_screen_saver_complete_get_active (skeleton, invocation, self->active); return TRUE; } @@ -152,30 +257,27 @@ handle_lock (PhoshDBusScreenSaver *skeleton, g_debug ("DBus call lock"); phosh_lockscreen_manager_set_locked (self->lockscreen_manager, TRUE); + /* TODO: wait a little before blanking */ + screen_saver_set_active (self, TRUE, TRUE); phosh_dbus_screen_saver_complete_lock (skeleton, invocation); return TRUE; } + static gboolean handle_set_active (PhoshDBusScreenSaver *skeleton, GDBusMethodInvocation *invocation, - gboolean lock) + gboolean active) { PhoshScreenSaverManager *self = PHOSH_SCREEN_SAVER_MANAGER (skeleton); g_return_val_if_fail (PHOSH_IS_SCREEN_SAVER_MANAGER (self), FALSE); g_return_val_if_fail (PHOSH_IS_LOCKSCREEN_MANAGER (self->lockscreen_manager), FALSE); - g_debug ("DBus call SetActive: %d", lock); - if (lock) { - phosh_lockscreen_manager_set_locked (self->lockscreen_manager, lock); - } else { - /* Screensaver active and screeen locked is the same so just - discard requests to de-activate the screensaver */ - g_debug ("Ignoring request to deactivate screen saver"); - } + g_debug ("DBus call SetActive: %d, lock-enabled: %d", active, self->lock_enabled); + screen_saver_set_active (self, active, self->lock_enabled); phosh_dbus_screen_saver_complete_set_active (skeleton, invocation); @@ -193,27 +295,79 @@ phosh_screen_saver_manager_screen_saver_iface_init (PhoshDBusScreenSaverIface *i } static void -on_lockscreen_manager_notify_locked (PhoshScreenSaverManager *self, - GParamSpec *pspec, - PhoshLockscreenManager *lockscreen_manager) +notify_active_changed (PhoshScreenSaverManager *self) { - gboolean locked; GDBusInterfaceSkeleton *skeleton; g_return_if_fail (PHOSH_IS_SCREEN_SAVER_MANAGER (self)); - g_return_if_fail (PHOSH_IS_LOCKSCREEN_MANAGER (lockscreen_manager)); skeleton = G_DBUS_INTERFACE_SKELETON (self); - locked = phosh_lockscreen_manager_get_locked(self->lockscreen_manager); - g_debug ("Signaling ActiveChanged: %d", locked); + g_debug ("Signaling ActiveChanged: %d", self->active); g_dbus_connection_emit_signal (g_dbus_interface_skeleton_get_connection (skeleton), NULL, g_dbus_interface_skeleton_get_object_path (skeleton), SCREEN_SAVER_DBUS_NAME, "ActiveChanged", - g_variant_new ("(b)", locked), + g_variant_new ("(b)", self->active), NULL); + if (self->active) { + g_debug ("Uninhibited logind suspend handling"); + phosh_clear_fd (&self->inhibit_suspend_fd, NULL); + } +} + +static void +on_inhibit_suspend_finished (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + gboolean success; + PhoshScreenSaverManager *self = PHOSH_SCREEN_SAVER_MANAGER (user_data); + PhoshDBusLoginManager *proxy; + g_autoptr (GError) err = NULL; + g_autoptr (GUnixFDList) fd_list = NULL; + g_autoptr (GVariant) out_pipe_fd = NULL; + int idx; + + proxy = PHOSH_DBUS_LOGIN_MANAGER (source_object); + success = phosh_dbus_login_manager_call_inhibit_finish (proxy, + &out_pipe_fd, + &fd_list, + res, + &err); + if (!success) { + g_warning ("Failed to inhibit suspend: %s", err->message); + return; + } + + g_return_if_fail (fd_list && g_unix_fd_list_get_length (fd_list) == 1); + g_return_if_fail (PHOSH_IS_SCREEN_SAVER_MANAGER (self)); + + g_variant_get (out_pipe_fd, "h", &idx); + self->inhibit_suspend_fd = g_unix_fd_list_get (fd_list, idx, &err); + if (self->inhibit_suspend_fd < 0) { + g_warning ("Failed to get suspend inhibit fd: %s", err->message); + return; + } + + g_debug ("Inhibited logind suspend handling"); +} + +static void +phosh_screen_saver_manager_inhibit_suspend (PhoshScreenSaverManager *self) +{ + g_return_if_fail (PHOSH_IS_SCREEN_SAVER_MANAGER (self)); + + phosh_dbus_login_manager_call_inhibit (self->logind_manager_proxy, + "sleep", + g_get_user_name (), + "Phosh handling suspend", + "delay", + NULL, + self->cancel, + on_inhibit_suspend_finished, + self); } static void @@ -245,6 +399,22 @@ on_lockscreen_manager_wakeup_outputs (PhoshScreenSaverManager *self, } +static void +on_lockscreen_manager_locked_changed (PhoshScreenSaverManager *self) +{ + gboolean locked; + + g_return_if_fail (PHOSH_IS_SCREEN_SAVER_MANAGER (self)); + + locked = phosh_lockscreen_manager_get_locked (self->lockscreen_manager); + if (locked == TRUE) + return; + + g_debug ("Disabling lock delay timer on unlock"); + g_clear_handle_id (&self->lock_delay_timer_id, g_source_remove); +} + + static void on_logind_lock (PhoshScreenSaverManager *self, PhoshDBusLoginSession *proxy) { @@ -278,6 +448,7 @@ on_logind_prepare_for_sleep (PhoshScreenSaverManager *self, idle_manager = phosh_idle_manager_get_default (); phosh_idle_manager_reset_timers (idle_manager); + phosh_screen_saver_manager_inhibit_suspend (self); } } @@ -288,8 +459,9 @@ on_presence_status_changed (PhoshScreenSaverManager *self, guint32 status, gpoin g_return_if_fail (PHOSH_IS_SCREEN_SAVER_MANAGER (self)); g_debug ("Presence status changed: %d", status); + if (status == PHOSH_SESSION_PRESENCE_STATUS_IDLE) - phosh_lockscreen_manager_set_locked (self->lockscreen_manager, TRUE); + screen_saver_set_active (self, TRUE, self->lock_enabled); } @@ -307,11 +479,9 @@ on_name_acquired (GDBusConnection *connection, end up sending out signals early */ g_object_connect ( self->lockscreen_manager, - "swapped-object-signal::notify::locked", G_CALLBACK (on_lockscreen_manager_notify_locked), self, "swapped-object-signal::wakeup-outputs", G_CALLBACK (on_lockscreen_manager_wakeup_outputs), self, + "swapped-object-signal::notify::locked", G_CALLBACK (on_lockscreen_manager_locked_changed), self, NULL); - - on_lockscreen_manager_notify_locked (self, NULL, self->lockscreen_manager); } @@ -346,15 +516,21 @@ phosh_screen_saver_manager_dispose (GObject *object) g_cancellable_cancel (self->cancel); g_clear_object (&self->cancel); + g_clear_handle_id (&self->lock_delay_timer_id, g_source_remove); g_clear_handle_id (&self->idle_id, g_source_remove); g_clear_handle_id (&self->dbus_name_id, g_bus_unown_name); + phosh_clear_fd (&self->inhibit_pwr_btn_fd, NULL); + phosh_clear_fd (&self->inhibit_suspend_fd, NULL); + if (g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (self))) g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (self)); + g_clear_object (&self->settings); g_clear_object (&self->lockscreen_manager); g_clear_object (&self->logind_session_proxy); g_clear_object (&self->logind_manager_proxy); + g_clear_object (&self->primary_monitor); g_clear_object (&self->presence); @@ -419,6 +595,44 @@ on_logind_manager_get_session_finished (PhoshDBusLoginManager *object, } +static void +on_inhibit_pwr_button_finished (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + gboolean success; + PhoshScreenSaverManager *self = PHOSH_SCREEN_SAVER_MANAGER (user_data); + PhoshDBusLoginManager *proxy; + g_autoptr (GError) err = NULL; + g_autoptr (GUnixFDList) fd_list = NULL; + g_autoptr (GVariant) out_pipe_fd = NULL; + int idx; + + proxy = PHOSH_DBUS_LOGIN_MANAGER (source_object); + success = phosh_dbus_login_manager_call_inhibit_finish (proxy, + &out_pipe_fd, + &fd_list, + res, + &err); + if (!success) { + g_warning ("Failed to inhibit power button: %s", err->message); + return; + } + + g_return_if_fail (fd_list && g_unix_fd_list_get_length (fd_list) == 1); + g_return_if_fail (PHOSH_IS_SCREEN_SAVER_MANAGER (self)); + + g_variant_get (out_pipe_fd, "h", &idx); + self->inhibit_pwr_btn_fd = g_unix_fd_list_get (fd_list, idx, &err); + if (self->inhibit_pwr_btn_fd < 0) { + g_warning ("Failed to get power button inhibit fd: %s", err->message); + return; + } + + g_debug ("Inhibited logind power button handling"); +} + + static void on_logind_manager_proxy_new_for_bus_finish (GObject *source_object, GAsyncResult *res, @@ -452,6 +666,73 @@ on_logind_manager_proxy_new_for_bus_finish (GObject *source_obje } g_debug ("Connected to logind's session interface"); + + phosh_dbus_login_manager_call_inhibit (self->logind_manager_proxy, + "handle-power-key", + g_get_user_name (), + "Phosh handling power key", + "block", + NULL, + self->cancel, + on_inhibit_pwr_button_finished, + self); + + phosh_screen_saver_manager_inhibit_suspend (self); +} + + +static void +on_primary_monitor_power_mode_changed (PhoshScreenSaverManager *self, + GParamSpec *pspec, + PhoshMonitor *monitor) +{ + gboolean active; + PhoshMonitorPowerSaveMode mode; + + g_return_if_fail (PHOSH_IS_SCREEN_SAVER_MANAGER (self)); + g_return_if_fail (PHOSH_IS_MONITOR (monitor)); + + mode = phosh_monitor_get_power_save_mode (monitor); + + active = (mode == PHOSH_MONITOR_POWER_SAVE_MODE_OFF); + g_debug ("Screensaver marked as %sactive", active ? "" : "in"); + if (active != self->active) { + self->active = active; + g_object_notify_by_pspec(G_OBJECT (self), props[PROP_ACTIVE]); + notify_active_changed (self); + } + + if (self->active == FALSE) { + g_debug ("Disabling lock delay timer on power mode change"); + g_clear_handle_id (&self->lock_delay_timer_id, g_source_remove); + } +} + + +static void +on_primary_monitor_changed (PhoshScreenSaverManager *self, + GParamSpec *psepc, + PhoshShell *shell) +{ + g_return_if_fail (PHOSH_IS_SHELL (shell)); + g_return_if_fail (PHOSH_IS_SCREEN_SAVER_MANAGER (self)); + + if (self->primary_monitor) + g_signal_handlers_disconnect_by_data(self->primary_monitor, self); + + g_set_object (&self->primary_monitor, phosh_shell_get_primary_monitor (shell)); + + if (self->primary_monitor == NULL) { + g_clear_handle_id (&self->lock_delay_timer_id, g_source_remove); + return; + } + + g_signal_connect_object (self->primary_monitor, + "notify::power-mode", + G_CALLBACK (on_primary_monitor_power_mode_changed), + self, + G_CONNECT_SWAPPED); + on_primary_monitor_power_mode_changed (self, NULL, self->primary_monitor); } @@ -468,11 +749,32 @@ on_idle (PhoshScreenSaverManager *self) (GAsyncReadyCallback) on_logind_manager_proxy_new_for_bus_finish, self); + g_signal_connect_swapped (phosh_shell_get_default (), + "notify::primary-monitor", + G_CALLBACK (on_primary_monitor_changed), + self); + on_primary_monitor_changed (self, NULL, phosh_shell_get_default ()); + self->idle_id = 0; return G_SOURCE_REMOVE; } +static void +add_keybindings (PhoshScreenSaverManager *self) +{ + GActionEntry entries[] = { + { "XF86PowerOff", toggle_blank }, + }; + + /* g-s-manager's grab_single_accelerator makes sure g-s-d doesn't bind it */ + phosh_shell_add_global_keyboard_action_entries (phosh_shell_get_default (), + (GActionEntry*)entries, + G_N_ELEMENTS (entries), + self); +} + + static void phosh_screen_saver_manager_constructed (GObject *object) { @@ -491,6 +793,12 @@ phosh_screen_saver_manager_constructed (GObject *object) g_return_if_fail (PHOSH_IS_LOCKSCREEN_MANAGER (self->lockscreen_manager)); + self->settings = g_settings_new ("org.gnome.desktop.screensaver"); + g_settings_bind (self->settings, "lock-enabled", self, "lock-enabled", G_SETTINGS_BIND_GET); + g_settings_bind (self->settings, "lock-delay", self, "lock-delay", G_SETTINGS_BIND_GET); + + add_keybindings (self); + self->presence = phosh_session_presence_get_default_failable (); if (self->presence) { g_signal_connect_swapped (self->presence, @@ -521,6 +829,38 @@ phosh_screen_saver_manager_class_init (PhoshScreenSaverManagerClass *klass) PHOSH_TYPE_LOCKSCREEN_MANAGER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + /** + * PhoshScreenSaverManager:lock-enabled: + * + * Whether activating the screens saver should also lock the screen + */ + props[PROP_LOCK_ENABLED] = + g_param_spec_boolean ("lock-enabled", "", "", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + /** + * PhoshScreenSaverManager:lock-delay: + * + * Delay in seconds for screen lock after blank + */ + props[PROP_LOCK_DELAY] = + g_param_spec_int ("lock-delay", "", "", + 0, + G_MAXINT, + 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + /** + * PhoshScreenSaverManager:active + * + * Whether the screen saver is active + */ + props[PROP_ACTIVE] = + g_param_spec_boolean ("active", "", "", + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | + G_PARAM_EXPLICIT_NOTIFY); + g_object_class_install_properties (object_class, PROP_LAST_PROP, props); } @@ -529,6 +869,7 @@ static void phosh_screen_saver_manager_init (PhoshScreenSaverManager *self) { self->cancel = g_cancellable_new (); + self->inhibit_suspend_fd = -1; } diff --git a/src/shell.c b/src/shell.c index d86f56ed3c7a03204a333893ad69638b0e984e71..9e5d042e02c9c1cfbe0c6b12da53d8ac619c74ec 100644 --- a/src/shell.c +++ b/src/shell.c @@ -268,6 +268,20 @@ on_home_state_changed (PhoshShell *self, GParamSpec *pspec, PhoshHome *home) } +static void +on_primary_monitor_power_mode_changed (PhoshShell *self, GParamSpec *pspec, PhoshMonitor *monitor) +{ + PhoshMonitorPowerSaveMode mode; + + g_return_if_fail (PHOSH_IS_SHELL (self)); + g_return_if_fail (PHOSH_IS_MONITOR (monitor)); + + g_object_get (monitor, "power-mode", &mode, NULL); + + phosh_shell_set_state (self, PHOSH_STATE_BLANKED, mode == PHOSH_MONITOR_POWER_SAVE_MODE_OFF); +} + + static void on_primary_monitor_configured (PhoshShell *self, PhoshMonitor *monitor) { @@ -284,9 +298,15 @@ on_primary_monitor_configured (PhoshShell *self, PhoshMonitor *monitor) static void -setup_primary_monitor_configured_handler (PhoshShell *self) +setup_primary_monitor_signal_handlers (PhoshShell *self) { PhoshShellPrivate *priv = phosh_shell_get_instance_private (self); + + g_signal_connect_swapped (priv->primary_monitor, + "notify::power-mode", + G_CALLBACK (on_primary_monitor_power_mode_changed), + self); + g_signal_connect_object (priv->primary_monitor, "configured", G_CALLBACK (on_primary_monitor_configured), self, @@ -717,7 +737,7 @@ setup_idle_cb (PhoshShell *self) priv->network_auth_manager = phosh_network_auth_manager_new (); priv->portal_access_manager = phosh_portal_access_manager_new (); - setup_primary_monitor_configured_handler (self); + setup_primary_monitor_signal_handlers (self); /* Delay signaling the compositor a bit so that idle handlers get a * chance to run and the user has can unlock right away. Ideally @@ -756,24 +776,6 @@ type_setup (void) } -static void -on_builtin_monitor_power_mode_changed (PhoshShell *self, GParamSpec *pspec, PhoshMonitor *monitor) -{ - PhoshMonitorPowerSaveMode mode; - PhoshShellPrivate *priv; - - g_return_if_fail (PHOSH_IS_SHELL (self)); - g_return_if_fail (PHOSH_IS_MONITOR (monitor)); - priv = phosh_shell_get_instance_private (self); - - g_object_get (monitor, "power-mode", &mode, NULL); - /* Might be emitted on startup before lockscreen_manager is up */ - if (mode == PHOSH_MONITOR_POWER_SAVE_MODE_OFF && priv->lockscreen_manager) - phosh_shell_lock (self); - - phosh_shell_set_state (self, PHOSH_STATE_BLANKED, mode == PHOSH_MONITOR_POWER_SAVE_MODE_OFF); -} - static void phosh_shell_set_builtin_monitor (PhoshShell *self, PhoshMonitor *monitor) { @@ -787,10 +789,6 @@ phosh_shell_set_builtin_monitor (PhoshShell *self, PhoshMonitor *monitor) return; if (priv->builtin_monitor) { - /* Power mode listener */ - g_signal_handlers_disconnect_by_func (priv->builtin_monitor, - G_CALLBACK (on_builtin_monitor_power_mode_changed), - self); g_clear_object (&priv->builtin_monitor); if (priv->rotation_manager) @@ -801,11 +799,6 @@ phosh_shell_set_builtin_monitor (PhoshShell *self, PhoshMonitor *monitor) g_set_object (&priv->builtin_monitor, monitor); if (monitor) { - g_signal_connect_swapped (priv->builtin_monitor, - "notify::power-mode", - G_CALLBACK (on_builtin_monitor_power_mode_changed), - self); - if (priv->rotation_manager) phosh_rotation_manager_set_monitor (priv->rotation_manager, monitor); } @@ -1110,10 +1103,14 @@ phosh_shell_set_primary_monitor (PhoshShell *self, PhoshMonitor *monitor) if (monitor == priv->primary_monitor) return; - if (priv->primary_monitor) + if (priv->primary_monitor) { g_signal_handlers_disconnect_by_func (priv->primary_monitor, G_CALLBACK (on_primary_monitor_configured), self); + g_signal_handlers_disconnect_by_func (priv->builtin_monitor, + G_CALLBACK (on_primary_monitor_power_mode_changed), + self); + } if (monitor != NULL) { /* Make sure the new monitor exists */ @@ -1136,13 +1133,13 @@ phosh_shell_set_primary_monitor (PhoshShell *self, PhoshMonitor *monitor) g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PRIMARY_MONITOR]); - setup_primary_monitor_configured_handler (self); + setup_primary_monitor_signal_handlers (self); /* All monitors gone or disabled. See if monitor-manager finds a * fallback to enable. Do that in an idle callback so GTK can process * pending wayland events for the gone output */ if (monitor == NULL) { - /* No monitor we're not useful atm */ + /* No monitor - we're not useful atm */ notify_compositor_up_state (self, PHOSH_PRIVATE_SHELL_STATE_UNKNOWN); g_idle_add (select_fallback_monitor, self); } else { @@ -1642,16 +1639,16 @@ phosh_shell_fade_out (PhoshShell *self, guint timeout) void phosh_shell_enable_power_save (PhoshShell *self, gboolean enable) { - g_debug ("Entering power save mode"); - g_return_if_fail (PHOSH_IS_SHELL (self)); + PhoshShellPrivate *priv; + PhoshMonitorPowerSaveMode ps_mode; - /* - * Locking the outputs instructs g-s-d to tell us to put - * outputs into power save mode via org.gnome.Mutter.DisplayConfig - */ - phosh_shell_set_locked(self, enable); + g_debug ("Entering power save mode: %d", enable); + + g_return_if_fail (PHOSH_IS_SHELL (self)); + priv = phosh_shell_get_instance_private (self); - /* TODO: other means of power saving */ + ps_mode = enable ? PHOSH_MONITOR_POWER_SAVE_MODE_OFF : PHOSH_MONITOR_POWER_SAVE_MODE_ON; + phosh_monitor_manager_set_power_save_mode (priv->monitor_manager, ps_mode); } /** diff --git a/src/shell.h b/src/shell.h index 5bd6b8876ac240c2780b0d2854f3319a8757eafb..cc6c45fcff59f235fdd9c827556bf3900d5bd0f6 100644 --- a/src/shell.h +++ b/src/shell.h @@ -38,7 +38,7 @@ G_BEGIN_DECLS * PhoshShellStateFlags: * @PHOSH_STATE_NONE: No other state * @PHOSH_STATE_MODAL_SYSTEM_PROMPT: any modal prompt shown - * @PHOSH_STATE_BLANKED: built-in display off + * @PHOSH_STATE_BLANKED: primary display off * @PHOSH_STATE_LOCKED: displays locked * @PHOSH_STATE_SETTINGS: settings menu unfolded from top bar * @PHOSH_STATE_OVERVIEW: overview unfolded from bottom bar diff --git a/src/util.c b/src/util.c index 7f089fb69455bb74403e5e939ae7b112714a780f..9b7e1bb8b768f80be365717d0a6f55e44b8d5ae4 100644 --- a/src/util.c +++ b/src/util.c @@ -17,6 +17,7 @@ #include #include +#include #include @@ -538,3 +539,25 @@ phosh_util_get_stylesheet (const char *theme_name) return style; } + + +gboolean +phosh_clear_fd (int *fd, GError **err) +{ + gboolean success; + + g_return_val_if_fail (fd, FALSE); + +#if GLIB_CHECK_VERSION(2, 75, 1) + success = g_clear_fd (fd, err); +#else + if (*fd >= 0) { + success = g_close (*fd, err); + *fd = -1; + } else { + success = TRUE; + } +#endif + + return success; +} diff --git a/src/util.h b/src/util.h index 6e030fe8518c24c69428a414b2b8c45cd65064a9..39a1b9385411f4e6902117f561e71aad02f07e37 100644 --- a/src/util.h +++ b/src/util.h @@ -36,3 +36,4 @@ gboolean phosh_util_gesture_is_touch (GtkGestureSingle *gesture); gboolean phosh_util_have_gnome_software (gboolean scan); void phosh_util_toggle_style_class (GtkWidget *widget, const char *style_class, gboolean toggle); const char *phosh_util_get_stylesheet (const char *theme_name); +gboolean phosh_clear_fd (int *fd, GError **err);