diff --git a/src/brightness-manager.c b/src/brightness-manager.c new file mode 100644 index 0000000000000000000000000000000000000000..5367c928562f06a6f75302d261461f246f1fdb4e --- /dev/null +++ b/src/brightness-manager.c @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2025 Phosh.mobi e.V. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Author: Guido Günther + */ + +#define G_LOG_DOMAIN "phosh-brightness-manager" + +#include "phosh-config.h" + +#include "brightness-manager.h" +#include "shell-priv.h" +#include "util.h" + +#define KEYBINDINGS_SCHEMA_ID "org.gnome.shell.keybindings" +#define KEYBINDING_KEY_BRIGHTNESS_UP "screen-brightness-up" +#define KEYBINDING_KEY_BRIGHTNESS_DOWN "screen-brightness-down" +#define KEYBINDING_KEY_BRIGHTNESS_UP_MONITOR "screen-brightness-up-monitor" +#define KEYBINDING_KEY_BRIGHTNESS_DOWN_MONITOR "screen-brightness-down-monitor" + +/** + * PhoshBrightnessManager: + * + * Manage backglight brightness + */ + +#define BRIGHTNESS_STEP_AMOUNT(max) ((max) < 20 ? 1 : (max) / 20) + +struct _PhoshBrightnessManager { + GObject parent; + + GStrv action_names; + GSettings *settings; + PhoshBacklight *backlight; +}; +G_DEFINE_TYPE (PhoshBrightnessManager, phosh_brightness_manager, G_TYPE_OBJECT) + + +static void +on_primary_monitor_changed (PhoshBrightnessManager *self, GParamSpec *psepc, PhoshShell *shell) +{ + PhoshMonitor *monitor = phosh_shell_get_primary_monitor (shell); + + if (monitor && monitor->backlight) { + g_set_object (&self->backlight, monitor->backlight); + } + + /* Fall back to built in display */ + if (!self->backlight) { + monitor = phosh_shell_get_builtin_monitor (shell); + if (monitor) + g_set_object (&self->backlight, monitor->backlight); + } + + if (self->backlight) + g_debug ("Found %s for brightness control", phosh_backlight_get_name (self->backlight)); +} + + +static void +adjust_brightness (PhoshBrightnessManager *self, gboolean up) +{ + PhoshShell *shell = phosh_shell_get_default (); + int min = 0, max = 0, step, brightness; + double percentage; + + if (!self->backlight) + return; + + phosh_backlight_get_range (self->backlight, &min, &max); + step = MAX (1, BRIGHTNESS_STEP_AMOUNT(max - min + 1)); + brightness = phosh_backlight_get_brightness (self->backlight); + + if (up) + brightness += step; + else + brightness -= step; + + brightness = CLAMP (brightness, min, max); + phosh_backlight_set_brightness (self->backlight, brightness); + + if (phosh_shell_get_state (shell) & PHOSH_STATE_SETTINGS) + return; + + percentage = 100.0 * (brightness - min) / (max - min); + phosh_shell_show_osd (phosh_shell_get_default (), + NULL, + "display-brightness-symbolic", + NULL, + percentage, + 100.0); +} + + +static void +on_brightness_up (GSimpleAction *action, GVariant *param, gpointer data) +{ + PhoshBrightnessManager *self = PHOSH_BRIGHTNESS_MANAGER (data); + + adjust_brightness (self, TRUE); +} + + +static void +on_brightness_down (GSimpleAction *action, GVariant *param, gpointer data) +{ + PhoshBrightnessManager *self = PHOSH_BRIGHTNESS_MANAGER (data); + + adjust_brightness (self, FALSE); +} + + +static void +add_keybindings (PhoshBrightnessManager *self) +{ + g_autoptr (GArray) actions = g_array_new (FALSE, TRUE, sizeof (GActionEntry)); + g_autoptr (GStrvBuilder) builder = g_strv_builder_new (); + + PHOSH_UTIL_BUILD_KEYBINDING (actions, + builder, + self->settings, + KEYBINDING_KEY_BRIGHTNESS_UP, + on_brightness_up); + PHOSH_UTIL_BUILD_KEYBINDING (actions, + builder, + self->settings, + KEYBINDING_KEY_BRIGHTNESS_DOWN, + on_brightness_down); + /* TODO: use current monitor */ + PHOSH_UTIL_BUILD_KEYBINDING (actions, + builder, + self->settings, + KEYBINDING_KEY_BRIGHTNESS_UP_MONITOR, + on_brightness_up); + /* TODO: use current monitor */ + PHOSH_UTIL_BUILD_KEYBINDING (actions, + builder, + self->settings, + KEYBINDING_KEY_BRIGHTNESS_DOWN_MONITOR, + on_brightness_down); + + phosh_shell_add_global_keyboard_action_entries (phosh_shell_get_default (), + (GActionEntry *)actions->data, + actions->len, + self); + self->action_names = g_strv_builder_end (builder); +} + + +static void +on_keybindings_changed (PhoshBrightnessManager *self) +{ + g_debug ("Updating keybindings in BrightnessManager"); + phosh_shell_remove_global_keyboard_action_entries (phosh_shell_get_default (), + self->action_names); + g_clear_pointer (&self->action_names, g_strfreev); + add_keybindings (self); +} + + +static void +phosh_brightness_manager_dispose (GObject *object) +{ + PhoshBrightnessManager *self = PHOSH_BRIGHTNESS_MANAGER (object); + + g_clear_pointer (&self->action_names, g_strfreev); + g_clear_object (&self->settings); + + G_OBJECT_CLASS (phosh_brightness_manager_parent_class)->dispose (object); +} + + +static void +phosh_brightness_manager_class_init (PhoshBrightnessManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = phosh_brightness_manager_dispose; +} + + +static void +phosh_brightness_manager_init (PhoshBrightnessManager *self) +{ + PhoshShell *shell = phosh_shell_get_default (); + GSettingsSchemaSource *source = g_settings_schema_source_get_default (); + g_autoptr (GSettingsSchema) schema = NULL; + + /* TODO: Drop once we can rely on GNOME 49 schema */ + schema = g_settings_schema_source_lookup (source, KEYBINDINGS_SCHEMA_ID, TRUE); + if (!schema) + return; + + if (!g_settings_schema_has_key (schema, KEYBINDING_KEY_BRIGHTNESS_UP)) + return; + + self->settings = g_settings_new (KEYBINDINGS_SCHEMA_ID); + g_signal_connect_object (self->settings, + "changed", + G_CALLBACK (on_keybindings_changed), + self, + G_CONNECT_SWAPPED); + add_keybindings (self); + + g_signal_connect_object (shell, + "notify::primary-monitor", + G_CALLBACK (on_primary_monitor_changed), + self, + G_CONNECT_SWAPPED); + on_primary_monitor_changed (self, NULL, shell); +} + + +PhoshBrightnessManager * +phosh_brightness_manager_new (void) +{ + return g_object_new (PHOSH_TYPE_BRIGHTNESS_MANAGER, NULL); +} diff --git a/src/brightness-manager.h b/src/brightness-manager.h new file mode 100644 index 0000000000000000000000000000000000000000..c10afbe6d0f2b0d8c0ae0e08945a8a87ec0b02d3 --- /dev/null +++ b/src/brightness-manager.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2025 Phosh.mobi e.V. + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#pragma once + +#include + +G_BEGIN_DECLS + +#define PHOSH_TYPE_BRIGHTNESS_MANAGER (phosh_brightness_manager_get_type ()) + +G_DECLARE_FINAL_TYPE (PhoshBrightnessManager, phosh_brightness_manager, PHOSH, BRIGHTNESS_MANAGER, GObject) + +PhoshBrightnessManager *phosh_brightness_manager_new (void); + +G_END_DECLS diff --git a/src/gnome-shell-manager.c b/src/gnome-shell-manager.c index 6e4c572f34b6aeb1f0d33411499143f6c4bab745..854aa2448d841d0892cbc5478f04817dce1cf122 100644 --- a/src/gnome-shell-manager.c +++ b/src/gnome-shell-manager.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2020 Purism SPC + * 2025 Phosh.mobi e.V. * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -12,9 +13,7 @@ #include "phosh-config.h" #include "gnome-shell-manager.h" -#include "osd-window.h" #include "shell-priv.h" -#include "util.h" #include "lockscreen-manager.h" #define GNOME_DESKTOP_USE_UNSTABLE_API @@ -30,7 +29,6 @@ */ #define GNOME_SHELL_DBUS_NAME "org.gnome.Shell" -#define OSD_HIDE_TIMEOUT 1 /* seconds */ static void phosh_gnome_shell_manager_gnome_shell_iface_init (PhoshDBusGnomeShellIface *iface); @@ -54,10 +52,6 @@ typedef struct _PhoshGnomeShellManager { guint repeat_delay_ms; guint repeat_interval_ms; - PhoshOsdWindow *osd; - gint osd_timeoutid; - gboolean osd_continue; - gboolean overview_active; } PhoshGnomeShellManager; @@ -136,28 +130,6 @@ handle_hide_monitor_labels (PhoshDBusGnomeShell *skeleton, } -static gboolean -on_osd_timeout (PhoshGnomeShellManager *self) -{ - gboolean ret; - ret = self->osd_continue ? G_SOURCE_CONTINUE : G_SOURCE_REMOVE; - if (!self->osd_continue) { - g_debug ("Closing osd"); - self->osd_timeoutid = 0; - if (self->osd) - gtk_widget_destroy (GTK_WIDGET (self->osd)); - } - self->osd_continue = FALSE; - return ret; -} - - -static void -on_osd_destroyed (PhoshGnomeShellManager *self) -{ - self->osd = NULL; - g_clear_handle_id (&self->osd_timeoutid, g_source_remove); -} static gboolean @@ -167,7 +139,7 @@ handle_show_osd (PhoshDBusGnomeShell *skeleton, { PhoshGnomeShellManager *self = PHOSH_GNOME_SHELL_MANAGER (skeleton); g_autofree char *connector = NULL, *icon = NULL, *label = NULL; - gdouble level = 0.0, maxlevel = 1.0; + double level = 0.0, maxlevel = 1.0; gboolean has_level; g_auto (GVariantDict) dict = G_VARIANT_DICT_INIT (NULL); @@ -183,33 +155,9 @@ handle_show_osd (PhoshDBusGnomeShell *skeleton, if (!has_level) level = -1.0; - g_debug ("DBus show osd: connector: %s icon: %s, label: %s, level %f/%f", - connector, icon, label, level, maxlevel); - - if (self->osd) { - self->osd_continue = TRUE; - g_object_set (self->osd, - "connector", connector, - "label", label, - "icon-name", icon, - "level", level, - "max-level", maxlevel, - NULL); - } else { - self->osd = PHOSH_OSD_WINDOW (phosh_osd_window_new (connector, label, icon, level, maxlevel)); - g_signal_connect_swapped (self->osd, "destroy", G_CALLBACK (on_osd_destroyed), self); - gtk_widget_set_visible (GTK_WIDGET (self->osd), TRUE); - } + phosh_shell_show_osd (phosh_shell_get_default (), connector, icon, label, level, maxlevel); - if (!self->osd_timeoutid) { - self->osd_timeoutid = g_timeout_add_seconds (OSD_HIDE_TIMEOUT, - (GSourceFunc) on_osd_timeout, - self); - g_source_set_name_by_id (self->osd_timeoutid, "[phosh] osd-timeout"); - } - - phosh_dbus_gnome_shell_complete_show_osd ( - skeleton, invocation); + phosh_dbus_gnome_shell_complete_show_osd (skeleton, invocation); return TRUE; } diff --git a/src/meson.build b/src/meson.build index b03b6e7cb1a7d1112d6e01ba0cb178c957c5ba1c..ee273d3b6a7693e9525329587c750bdf0ef5d38e 100644 --- a/src/meson.build +++ b/src/meson.build @@ -204,6 +204,7 @@ phosh_tool_sources = files( 'backlight-sysfs.c', 'backlight.c', 'bidi.c', + 'brightness-manager.c', 'call-notification.c', 'call.c', 'calls-manager.c', @@ -303,6 +304,7 @@ phosh_headers = files( 'backlight-sysfs.h', 'backlight.h', 'batteryinfo.h', + 'brightness-manager.h', 'bt-device-row.h', 'bt-info.h', 'bt-manager.h', diff --git a/src/osd-window.c b/src/osd-window.c index b99e2e61d30a0298ac0a291019615ec0b88e681c..d0e58c447d90aadb3d4037be248b6fd06702bc2e 100644 --- a/src/osd-window.c +++ b/src/osd-window.c @@ -276,11 +276,11 @@ phosh_osd_window_init (PhoshOsdWindow *self) GtkWidget * -phosh_osd_window_new (char *connector, - char *label, - char *icon_name, - double level, - double max_level) +phosh_osd_window_new (const char *connector, + const char *label, + const char *icon_name, + double level, + double max_level) { return g_object_new (PHOSH_TYPE_OSD_WINDOW, "anchor", ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP, diff --git a/src/osd-window.h b/src/osd-window.h index 9c1f95f40539637de11490dda497424d9a2185cd..0b91f205dd27cbf6106acab1a0ced802a05e52c7 100644 --- a/src/osd-window.h +++ b/src/osd-window.h @@ -13,8 +13,8 @@ G_DECLARE_FINAL_TYPE (PhoshOsdWindow, phosh_osd_window, PHOSH, OSD_WINDOW, PhoshSystemModal) -GtkWidget *phosh_osd_window_new (char *connector, - char *label, - char *icon_name, - double level, - double max_level); +GtkWidget *phosh_osd_window_new (const char *connector, + const char *label, + const char *icon_name, + double level, + double max_level); diff --git a/src/shell-priv.h b/src/shell-priv.h index 04ef015af4e679b86d91c149afc0b5aa3f35a96c..9f0147048bff44f94d83750887e25743e1852893 100644 --- a/src/shell-priv.h +++ b/src/shell-priv.h @@ -121,5 +121,11 @@ gboolean phosh_shell_activate_action (PhoshShell *self, GVariant *parameter); void phosh_shell_set_bg_alpha (PhoshShell *self, double alpha); +void phosh_shell_show_osd (PhoshShell *self, + const char *connector, + const char *icon, + const char *label, + double level, + double max_level); G_END_DECLS diff --git a/src/shell.c b/src/shell.c index 1a8dac02f9784a922ba4e7e69bc16671a0625c34..a64339c060083e5eaf337283f7a3603e4cd1918e 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2018 Purism SPC - * 2023-2025 The Phosh Developers + * 2023-2024 The Phosh Developers + * 2025 Phosh.mobi e.V. * * SPDX-License-Identifier: GPL-3.0-or-later * @@ -26,6 +27,7 @@ #include "phosh-config.h" #include "ambient.h" #include "background.h" +#include "brightness-manager.h" #include "drag-surface.h" #include "shell-priv.h" #include "app-tracker.h" @@ -60,6 +62,7 @@ #include "monitor-manager.h" #include "monitor/monitor.h" #include "mount-manager.h" +#include "osd-window.h" #include "power-menu-manager.h" #include "revealer.h" #include "settings.h" @@ -104,6 +107,7 @@ #include "phosh-settings-enums.h" #define WWAN_BACKEND_KEY "wwan-backend" +#define OSD_HIDE_TIMEOUT 1 /* seconds */ /** * PhoshShell: @@ -143,6 +147,10 @@ typedef struct gboolean overview_visible; GPtrArray *faders; /* for final fade out */ + PhoshOsdWindow *osd; + gint osd_timeoutid; + gboolean osd_continue; + GtkWidget *notification_banner; PhoshUdevManager *udev_manager; @@ -188,6 +196,7 @@ typedef struct PhoshCellBroadcastManager *cell_broadcast_manager; PhoshConnectivityManager *connectivity_manager; PhoshMprisManager *mpris_manager; + PhoshBrightnessManager *brightness_manager; /* sensors */ PhoshSensorProxyManager *sensor_proxy_manager; @@ -227,7 +236,7 @@ on_top_panel_activated (PhoshShell *self, PhoshShellPrivate *priv = phosh_shell_get_instance_private (self); g_return_if_fail (PHOSH_IS_TOP_PANEL (priv->top_panel)); - phosh_top_panel_toggle_fold (PHOSH_TOP_PANEL(priv->top_panel)); + phosh_top_panel_toggle_fold (PHOSH_TOP_PANEL (priv->top_panel)); } @@ -450,7 +459,7 @@ panels_dispose (PhoshShell *self) static void set_locked (PhoshShell *self, gboolean locked) { - PhoshShellPrivate *priv = phosh_shell_get_instance_private(self); + PhoshShellPrivate *priv = phosh_shell_get_instance_private (self); if (priv->locked == locked) return; @@ -539,7 +548,7 @@ static void phosh_shell_dispose (GObject *object) { PhoshShell *self = PHOSH_SHELL (object); - PhoshShellPrivate *priv = phosh_shell_get_instance_private(self); + PhoshShellPrivate *priv = phosh_shell_get_instance_private (self); g_clear_handle_id (&priv->startup_finished_id, g_source_remove); @@ -549,6 +558,7 @@ phosh_shell_dispose (GObject *object) g_clear_pointer (&priv->notification_banner, phosh_cp_widget_destroy); /* dispose managers in opposite order of declaration */ + g_clear_object (&priv->brightness_manager); g_clear_object (&priv->mpris_manager); g_clear_object (&priv->connectivity_manager); g_clear_object (&priv->cell_broadcast_manager); @@ -616,7 +626,9 @@ phosh_shell_finalize (GObject *object) static void -on_num_toplevels_changed (PhoshShell *self, GParamSpec *pspec, PhoshToplevelManager *toplevel_manager) +on_num_toplevels_changed (PhoshShell *self, + GParamSpec *pspec, + PhoshToplevelManager *toplevel_manager) { PhoshShellPrivate *priv; @@ -711,6 +723,37 @@ on_fade_out_timeout (PhoshShell *self) } +/* {{{ OSD */ + +static gboolean +on_osd_timeout (PhoshShell *self) +{ + PhoshShellPrivate *priv = phosh_shell_get_instance_private (self); + gboolean ret; + + ret = priv->osd_continue ? G_SOURCE_CONTINUE : G_SOURCE_REMOVE; + if (!priv->osd_continue) { + g_debug ("Closing osd"); + priv->osd_timeoutid = 0; + if (priv->osd) + gtk_widget_destroy (GTK_WIDGET (priv->osd)); + } + priv->osd_continue = FALSE; + return ret; +} + + +static void +on_osd_destroyed (PhoshShell *self) +{ + PhoshShellPrivate *priv = phosh_shell_get_instance_private (self); + + priv->osd = NULL; + g_clear_handle_id (&priv->osd_timeoutid, g_source_remove); +} + +/* }}} */ + static void notify_compositor_up_state (PhoshShell *self, enum phosh_private_shell_state state) { @@ -719,7 +762,8 @@ notify_compositor_up_state (PhoshShell *self, enum phosh_private_shell_state sta g_debug ("Notify compositor state: %d", state); phosh_private = phosh_wayland_get_phosh_private (phosh_wayland_get_default ()); - if (phosh_private && phosh_private_get_version (phosh_private) >= PHOSH_PRIVATE_SET_SHELL_STATE_SINCE_VERSION) + if (phosh_private && + phosh_private_get_version (phosh_private) >= PHOSH_PRIVATE_SET_SHELL_STATE_SINCE_VERSION) phosh_private_set_shell_state (phosh_private, state); } @@ -822,6 +866,7 @@ setup_idle_cb (PhoshShell *self) priv->emergency_calls_manager = phosh_emergency_calls_manager_new (); priv->power_menu_manager = phosh_power_menu_manager_new (); priv->cell_broadcast_manager = phosh_cell_broadcast_manager_new (); + priv->brightness_manager = phosh_brightness_manager_new (); setup_primary_monitor_signal_handlers (self); /* Setup event hooks late so state changes in UI files don't trigger feedback */ @@ -1063,7 +1108,7 @@ phosh_shell_constructed (GObject *object) self, "locked", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); - priv->idle_manager = phosh_idle_manager_get_default(); + priv->idle_manager = phosh_idle_manager_get_default (); priv->faders = g_ptr_array_new_with_free_func ((GDestroyNotify) (gtk_widget_destroy)); @@ -1202,7 +1247,8 @@ phosh_shell_remove_action (GActionMap *action_map, const char *action_name) } -static void phosh_shell_action_map_iface_init (GActionMapInterface *iface) +static void +phosh_shell_action_map_iface_init (GActionMapInterface *iface) { iface->lookup_action = phosh_shell_lookup_action; iface->add_action = phosh_shell_add_action; @@ -1291,7 +1337,6 @@ phosh_shell_class_init (PhoshShellClass *klass) PHOSH_TYPE_SHELL_STATE_FLAGS, PHOSH_STATE_NONE, G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); - /** * PhoshShell:overview-visible: * @@ -2123,11 +2168,11 @@ phosh_shell_get_usable_area (PhoshShell *self, int *x, int *y, int *width, int * g_return_if_fail (PHOSH_IS_SHELL (self)); monitor = phosh_shell_get_primary_monitor (self); - g_return_if_fail(monitor); + g_return_if_fail (monitor); mode = phosh_monitor_get_current_mode (monitor); g_return_if_fail (mode != NULL); - scale = MAX(1.0, phosh_monitor_get_fractional_scale (monitor)); + scale = MAX (1.0, phosh_monitor_get_fractional_scale (monitor)); g_debug ("Primary monitor %p scale is %f, mode: %dx%d, transform is %d", monitor, @@ -2136,7 +2181,7 @@ phosh_shell_get_usable_area (PhoshShell *self, int *x, int *y, int *width, int * mode->height, monitor->transform); - switch (phosh_monitor_get_transform(monitor)) { + switch (phosh_monitor_get_transform (monitor)) { case PHOSH_MONITOR_TRANSFORM_NORMAL: case PHOSH_MONITOR_TRANSFORM_180: case PHOSH_MONITOR_TRANSFORM_FLIPPED: @@ -2273,7 +2318,7 @@ phosh_shell_enable_power_save (PhoshShell *self, gboolean enable) * Returns: %TRUE if we were started from a display manager. %FALSE otherwise. */ gboolean -phosh_shell_started_by_display_manager(PhoshShell *self) +phosh_shell_started_by_display_manager (PhoshShell *self) { g_return_val_if_fail (PHOSH_IS_SHELL (self), FALSE); @@ -2290,7 +2335,7 @@ phosh_shell_started_by_display_manager(PhoshShell *self) * Returns: %TRUE if the shell finished startup. %FALSE otherwise. */ gboolean -phosh_shell_is_startup_finished(PhoshShell *self) +phosh_shell_is_startup_finished (PhoshShell *self) { PhoshShellPrivate *priv; @@ -2302,10 +2347,10 @@ phosh_shell_is_startup_finished(PhoshShell *self) void -phosh_shell_add_global_keyboard_action_entries (PhoshShell *self, +phosh_shell_add_global_keyboard_action_entries (PhoshShell *self, const GActionEntry *entries, - gint n_entries, - gpointer user_data) + gint n_entries, + gpointer user_data) { PhoshShellPrivate *priv; @@ -2594,4 +2639,43 @@ phosh_shell_get_lockscreen_type (PhoshShell *self) return klass->get_lockscreen_type (self); } + +void +phosh_shell_show_osd (PhoshShell *self, + const char *connector, + const char *icon, + const char *label, + double level, + double max_level) +{ + PhoshShellPrivate *priv = phosh_shell_get_instance_private (self); + + g_return_if_fail (PHOSH_IS_SHELL (self)); + + g_debug ("DBus show osd: connector: %s icon: %s, label: %s, level %f/%f", + connector, icon, label, level, max_level); + + if (priv->osd) { + priv->osd_continue = TRUE; + g_object_set (priv->osd, + "connector", connector, + "label", label, + "icon-name", icon, + "level", level, + "max-level", max_level, + NULL); + } else { + priv->osd = PHOSH_OSD_WINDOW (phosh_osd_window_new (connector, label, icon, level, max_level)); + g_signal_connect_swapped (priv->osd, "destroy", G_CALLBACK (on_osd_destroyed), self); + gtk_widget_set_visible (GTK_WIDGET (priv->osd), TRUE); + } + + if (!priv->osd_timeoutid) { + priv->osd_timeoutid = g_timeout_add_seconds (OSD_HIDE_TIMEOUT, + (GSourceFunc) on_osd_timeout, + self); + g_source_set_name_by_id (priv->osd_timeoutid, "[phosh] osd-timeout"); + } +} + /* }}} */