diff --git a/meson.build b/meson.build index 00e41ce..7182d91 100644 --- a/meson.build +++ b/meson.build @@ -33,7 +33,7 @@ lua = dependency('lua') # pkg_config = import('pkgconfig') # gnome = import('gnome') -gtk_layer_shell = dependency('gtk4-layer-shell-0', version: '>=1.1.0') +gtk_layer_shell = dependency('gtk4-layer-shell-0', version: '>=1.3.0') wayland_targets=[] wl_protocols = [ diff --git a/resources/css/login-shell.css b/resources/css/login-shell.css index 38bd4f3..b7300b1 100644 --- a/resources/css/login-shell.css +++ b/resources/css/login-shell.css @@ -1,20 +1,22 @@ @import url("resource:///dev/iohub/diya/shell/css/virtual-keyboard.css"); -#diya_login_shell +.diya-login-shell { + background-color: white; + opacity: 0.9; } -#diya_login_shell label.diya-login-header { +.diya-login-shell label.diya-login-header { font-size: 16px; font-weight: bold; } -#diya_login_shell label.diya-login-status { +.diya-login-shell label.diya-login-status { font-size: 12px; color: red; } -#diya_login_shell button.diya-btn-show-vkb +.diya-login-shell button.diya-btn-show-vkb { color: gray; min-width: 0px; diff --git a/src/login-shell.c b/src/login-shell.c index 9c9a438..a0e96eb 100644 --- a/src/login-shell.c +++ b/src/login-shell.c @@ -8,19 +8,18 @@ #define DBUS_SERVER_NAME "dev.iohub.diya.SessionManager" #define DBUS_SERVER_PATH "/dev/iohub/diya/SessionManager" #define DBUS_SERVER_ERROR_NAME "dev.iohub.diya.SessionManager.Error" -#define NAMESPACE "diya_login_shell" +#define NAMESPACE "diya-login-shell" struct _DiyaLoginShell { DiyaShell parent_object; - GtkSessionLockInstance *lock; GtkWidget *username; GtkWidget *password; GtkWidget *status; guint bus_watch_id; GtkWidget *vkb_widget; GtkWidget *revealer; - GList *windows; + }; G_DEFINE_FINAL_TYPE(DiyaLoginShell, diya_login_shell, DIYA_TYPE_SHELL); @@ -29,10 +28,6 @@ static void diya_login_shell_finalize(GObject *object) { DiyaLoginShell *self = DIYA_LOGIN_SHELL(object); g_debug("diya_login_shell_finalize: %s", diya_object_to_string(self)); - if (self->windows) - { - g_list_free(self->windows); - } G_OBJECT_CLASS(diya_login_shell_parent_class)->finalize(object); } @@ -40,27 +35,6 @@ static void diya_login_shell_dispose(GObject *object) { DiyaLoginShell *self = DIYA_LOGIN_SHELL(object); g_debug("diya_login_shell_dispose: %s", diya_object_to_string(self)); - if (self->lock) - { - if (gtk_session_lock_instance_is_locked(self->lock)) - { - gtk_session_lock_instance_unlock(self->lock); - } - g_object_unref(self->lock); - } - if (self->windows) - { - // destroyed all windows and free list - GList *it = NULL; - for (it = self->windows; it; it = it->next) - { - if (it->data) - { - gtk_window_destroy(GTK_WINDOW(it->data)); - } - } - // g_list_free(self->windows); - } if (self->bus_watch_id > 0) { g_bus_unwatch_name(self->bus_watch_id); @@ -71,11 +45,9 @@ static void diya_login_shell_dispose(GObject *object) static void diya_login_shell_init(DiyaLoginShell *self) { g_debug("diya_login_shell_init"); - self->lock = gtk_session_lock_instance_new(); self->username = NULL; self->password = NULL; self->status = NULL; - self->windows = NULL; self->bus_watch_id = 0; } @@ -178,14 +150,44 @@ static void do_login(GtkButton *button, DiyaLoginShell *self) // g_application_quit(G_APPLICATION(self->app)); } -static void add_new_monitor(DiyaLoginShell *self, GdkMonitor *monitor, gint position) + +static void diya_login_on_shell_idle(DiyaShell* shell) { - GtkWindow *window = GTK_WINDOW(gtk_application_window_new(diya_shell_get_application(DIYA_SHELL(self)))); - gtk_session_lock_instance_assign_window_to_monitor(self->lock, window, monitor); - gtk_widget_set_name(GTK_WIDGET(window), NAMESPACE); + (void) shell; + g_debug("diya_login_on_shell_idle"); + diya_shell_power_display(shell, false); +} + +static void diya_login_on_shell_resume(DiyaShell* shell) +{ + (void) shell; + g_debug("diya_login_on_shell_resume"); + diya_shell_power_display(shell, true); +} + +static void diya_login_shell_active(DiyaShell *shell) +{ + g_object_set(shell, DIYA_PROP_SHELL_IDLE_TIMEOUT, DEFAULT_IDLE_TIMEOUT, NULL); +} + +static void diya_login_shell_startup(DiyaShell *shell) +{ + g_warning("diya_login_shell_startup"); + g_signal_connect(shell, DIYA_SIGNAL_SHELL_IDLE, G_CALLBACK(diya_login_on_shell_idle), NULL); + g_signal_connect(shell, DIYA_SIGNAL_SHELL_RESUME, G_CALLBACK(diya_login_on_shell_resume), NULL); + diya_shell_lock(shell); +} + +static GtkWindow* diya_login_shell_create_window(DiyaShell* shell) +{ + DiyaLoginShell* self = DIYA_LOGIN_SHELL(shell); + GtkApplication * app; + g_object_get(shell, DIYA_PROP_SHELL_APPLICATION, &app, NULL); + assert(app); + GtkWindow *window = GTK_WINDOW(gtk_application_window_new(app)); + gtk_widget_add_css_class(GTK_WIDGET(window), NAMESPACE); GtkWidget *grid = gtk_grid_new(); - gtk_window_set_child(window, grid); gtk_grid_set_row_homogeneous(GTK_GRID(grid), false); GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); @@ -230,14 +232,14 @@ static void add_new_monitor(DiyaLoginShell *self, GdkMonitor *monitor, gint posi gtk_widget_set_can_focus(GTK_WIDGET(button), false); gtk_grid_attach(GTK_GRID(child_grid), button, 0, 0, 1, 1); // Not displayed, but allows testing that creating popups doesn't crash GTK - gtk_widget_set_tooltip_text(button, "Login"); + //gtk_widget_set_tooltip_text(button, "Login"); gtk_widget_set_hexpand(button, true); button = gtk_toggle_button_new_with_label("⌨"); gtk_widget_add_css_class(button, "diya-btn-show-vkb"); gtk_grid_attach(GTK_GRID(child_grid), button, 1, 0, 1, 1); gtk_box_append(GTK_BOX(box), child_grid); - gtk_widget_set_tooltip_text(button, "Show virtual keyboard"); + //gtk_widget_set_tooltip_text(button, "Show virtual keyboard"); gtk_widget_set_can_focus(GTK_WIDGET(button), false); self->status = gtk_label_new(NULL); @@ -265,73 +267,8 @@ static void add_new_monitor(DiyaLoginShell *self, GdkMonitor *monitor, gint posi gtk_widget_set_hexpand(box, true); gtk_widget_set_vexpand(box, false); - gtk_window_present(window); - - self->windows = g_list_insert(self->windows, window, position); -} - -static void on_monitor_changed(GListModel *monitor_lists, guint position, guint removed, guint added, gpointer object) -{ - g_debug("Monitor list changed at %d: added %d, removed %d", position, added, removed); - DiyaLoginShell *self = DIYA_LOGIN_SHELL(object); - if (removed > 0) - { - for (guint i = 0; i < removed; i++) - { - GtkWindow *win = GTK_WINDOW(g_list_nth(self->windows, position)); - if (win) - { - gtk_window_destroy(win); - self->windows = g_list_remove(self->windows, win); - } - } - } - if (added > 0) - { - for (guint i = 0; i < added; i++) - { - GdkMonitor *monitor = g_list_model_get_item(monitor_lists, position + i); - add_new_monitor(self, monitor, position + i); - } - } -} - -static void diya_login_on_shell_idle(DiyaShell* shell) -{ - (void) shell; - g_debug("diya_login_on_shell_idle"); - diya_shell_power_display(shell, false); -} - -static void diya_login_on_shell_resume(DiyaShell* shell) -{ - (void) shell; - g_debug("diya_login_on_shell_resume"); - diya_shell_power_display(shell, true); -} - -static void diya_login_shell_active(DiyaShell *shell) -{ - g_object_set(shell, DIYA_PROP_SHELL_IDLE_TIMEOUT, DEFAULT_IDLE_TIMEOUT, NULL); -} - -static void diya_login_shell_startup(DiyaShell *shell) -{ - DiyaLoginShell *self = DIYA_LOGIN_SHELL(shell); - if (!gtk_session_lock_instance_lock(self->lock)) - { - g_object_unref(self); - g_error("gtk_session_lock_instance_lock: Unable to lock the display"); - return; - } - GListModel *list = gdk_display_get_monitors(gdk_display_get_default()); - for (guint i = 0; i < g_list_model_get_n_items(list); i++) - { - GdkMonitor *monitor = g_list_model_get_item(list, i); - add_new_monitor(self, monitor, -1); - } - g_signal_connect(shell, DIYA_SIGNAL_SHELL_IDLE, G_CALLBACK(diya_login_on_shell_idle), NULL); - g_signal_connect(shell, DIYA_SIGNAL_SHELL_RESUME, G_CALLBACK(diya_login_on_shell_resume), NULL); + gtk_window_set_child(window, grid); + return window; } static void diya_login_shell_class_init(DiyaLoginShellClass *class) @@ -343,7 +280,7 @@ static void diya_login_shell_class_init(DiyaLoginShellClass *class) // gobject_class->get_property = diya_lock_session_get_property; DiyaShellClass *base_shell_class = DIYA_SHELL_CLASS(class); - base_shell_class->monitor_changed_handle = on_monitor_changed; + base_shell_class->build_lock_window = diya_login_shell_create_window; base_shell_class->startup_handle = diya_login_shell_startup; base_shell_class->active_handle = diya_login_shell_active; // base_shell_class->foreign_register = diya_session_shell_foreign_toplevel_register; diff --git a/src/session-lock.c b/src/session-lock.c index ee5c004..af6819a 100644 --- a/src/session-lock.c +++ b/src/session-lock.c @@ -3,69 +3,38 @@ #include #include "session-lock.h" -static void unlock_session(GtkButton *button, DiyaSessionShell *shell) +static void unlock_session(GtkButton *button, DiyaShell *shell) { (void)button; assert(shell); - diya_session_shell_unlock(shell); + diya_shell_unlock(shell); } -void diya_session_shell_lock(DiyaSessionShell* shell) +GtkWindow* diya_session_lock_create(DiyaShell* shell) { assert(shell); - GtkSessionLockInstance * lock; - g_object_get(shell, DIYA_PROP_SESSION_LOCK, &lock, NULL); - assert(lock); - if(gtk_session_lock_instance_is_locked(lock)) - { - g_warning("Shell session is already locked, doing nothing"); - return; - } - if(!gtk_session_lock_instance_lock(lock)) - { - g_error("gtk_session_lock_instance_lock:Unable to lock the current session"); - return; - } GtkApplication * app; g_object_get(shell, DIYA_PROP_SHELL_APPLICATION, &app, NULL); assert(app); - GdkDisplay *display = gdk_display_get_default(); - GListModel *monitors = gdk_display_get_monitors(display); - guint n_monitors = g_list_model_get_n_items(monitors); + GtkWindow *gtk_window = GTK_WINDOW(gtk_application_window_new(app)); - for (guint i = 0; i < n_monitors; ++i) - { - GdkMonitor *monitor = g_list_model_get_item(monitors, i); + GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_set_halign(box, GTK_ALIGN_CENTER); + gtk_widget_set_valign(box, GTK_ALIGN_CENTER); + gtk_box_set_spacing(GTK_BOX (box), 10); - GtkWindow *gtk_window = GTK_WINDOW(gtk_application_window_new(app)); - gtk_session_lock_instance_assign_window_to_monitor(lock, gtk_window, monitor); + GtkWidget *label = gtk_label_new("GTK Session Lock example"); + gtk_box_append(GTK_BOX(box), label); - GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); - gtk_widget_set_halign(box, GTK_ALIGN_CENTER); - gtk_widget_set_valign(box, GTK_ALIGN_CENTER); - gtk_box_set_spacing(GTK_BOX (box), 10); + GtkWidget *button = gtk_button_new_with_label("Unlock"); + g_signal_connect(button, "clicked", G_CALLBACK(unlock_session), shell); + gtk_box_append(GTK_BOX(box), button); - GtkWidget *label = gtk_label_new("GTK Session Lock example"); - gtk_box_append(GTK_BOX(box), label); + // Not displayed, but allows testing that creating popups doesn't crash GTK + gtk_widget_set_tooltip_text(button, "Foo Bar Baz"); - GtkWidget *button = gtk_button_new_with_label("Unlock"); - g_signal_connect(button, "clicked", G_CALLBACK(unlock_session), shell); - gtk_box_append(GTK_BOX(box), button); + gtk_window_set_child(GTK_WINDOW(gtk_window), box); - // Not displayed, but allows testing that creating popups doesn't crash GTK - gtk_widget_set_tooltip_text(button, "Foo Bar Baz"); - - gtk_window_set_child(GTK_WINDOW(gtk_window), box); - gtk_window_present(gtk_window); - } -} -void diya_session_shell_unlock(DiyaSessionShell* shell) -{ - assert(shell); - GtkSessionLockInstance * lock; - g_object_get(shell, DIYA_PROP_SESSION_LOCK, &lock, NULL); - assert(lock); - gtk_session_lock_instance_unlock(lock); - g_debug("gtk_session_lock_instance_unlock: Shell unlocked"); + return gtk_window; } \ No newline at end of file diff --git a/src/session-lock.h b/src/session-lock.h index 72fb423..41caaa7 100644 --- a/src/session-lock.h +++ b/src/session-lock.h @@ -3,7 +3,6 @@ #include "session-shell.h" -void diya_session_shell_lock(DiyaSessionShell* shell); -void diya_session_shell_unlock(DiyaSessionShell* shell); +GtkWindow* diya_session_lock_create(DiyaShell* shell); #endif \ No newline at end of file diff --git a/src/session-shell.c b/src/session-shell.c index 7af1cd0..8337618 100644 --- a/src/session-shell.c +++ b/src/session-shell.c @@ -1,7 +1,7 @@ #include "session-shell.h" #include -#include + #include #include "shell.h" @@ -17,7 +17,6 @@ enum { NO_PROP, SHELL_LAUNCHPAD_WIDGET, - SHELL_LOCK_SESSION, SHELL_WINDOWS, N_PROPERTIES }; @@ -29,7 +28,6 @@ struct _DiyaSessionShell DiyaShell parent; DiyaLauncher *launcher; GHashTable *windows; - GtkSessionLockInstance *lock; GSettings *settings; }; G_DEFINE_FINAL_TYPE(DiyaSessionShell, diya_session_shell, DIYA_TYPE_SHELL) @@ -47,10 +45,6 @@ static void diya_session_shell_dispose(GObject *object) DiyaSessionShell *self = DIYA_SESSION_SHELL(object); // g_hash_table_destroy(self->windows); g_debug("diya_session_shell_dispose: %s", diya_object_to_string(object)); - if (self->lock) - { - g_object_unref(self->lock); - } if (self->launcher) { g_object_unref(self->launcher); @@ -88,10 +82,6 @@ static void diya_session_shell_get_property(GObject *object, guint property_id, assert(self->launcher); g_value_set_pointer(value, self->launcher); break; - case SHELL_LOCK_SESSION: - assert(self->lock); - g_value_set_pointer(value, self->lock); - break; case SHELL_WINDOWS: g_value_set_pointer(value, self->windows); break; @@ -180,7 +170,7 @@ void diya_session_init_settings(DiyaSessionShell* self) static void diya_session_shell_startup(DiyaShell *shell) { DiyaSessionShell* self = DIYA_SESSION_SHELL(shell); - + const gchar* const* dirs = g_get_system_config_dirs(); gchar* path = NULL; @@ -227,7 +217,7 @@ static void diya_session_shell_class_init(DiyaSessionShellClass *class) base_shell_class->foreign_register = diya_session_shell_foreign_toplevel_register; base_shell_class->startup_handle = diya_session_shell_startup; base_shell_class->active_handle = diya_session_shell_active; - + base_shell_class->build_lock_window = diya_session_lock_create; /// base_class->to_string = diya_session_shell_to_string; gobject_class->dispose = diya_session_shell_dispose; gobject_class->finalize = diya_session_shell_finalize; @@ -235,7 +225,6 @@ static void diya_session_shell_class_init(DiyaSessionShellClass *class) gobject_class->get_property = diya_session_shell_get_property; shell_properties[SHELL_LAUNCHPAD_WIDGET] = g_param_spec_pointer(DIYA_PROP_SESSION_LAUNCHPAD, NULL, "Shell launchpad", G_PARAM_READWRITE); - shell_properties[SHELL_LOCK_SESSION] = g_param_spec_pointer(DIYA_PROP_SESSION_LOCK, NULL, "Shell lock session", G_PARAM_READABLE); shell_properties[SHELL_WINDOWS] = g_param_spec_pointer(DIYA_PROP_SESSION_WINDOWS, NULL, "Shell foreign windows", G_PARAM_READABLE); g_object_class_install_properties(gobject_class, N_PROPERTIES, shell_properties); @@ -289,44 +278,6 @@ static void diya_session_shell_class_init(DiyaSessionShellClass *class) G_TYPE_NONE, 1, G_TYPE_POINTER); - g_signal_new(DIYA_SIGNAL_SESSION_LOCKED, - DIYA_TYPE_SESSION_SHELL, - G_SIGNAL_DETAILED | - G_SIGNAL_ACTION | - G_SIGNAL_RUN_FIRST, - 0, - NULL, - NULL, - NULL, - G_TYPE_NONE, - 0); - g_signal_new(DIYA_SIGNAL_SESSION_UNLOCKED, - DIYA_TYPE_SESSION_SHELL, - G_SIGNAL_DETAILED | - G_SIGNAL_ACTION | - G_SIGNAL_RUN_FIRST, - 0, - NULL, - NULL, - NULL, - G_TYPE_NONE, - 0); -} - -static void on_session_locked(GtkSessionLockInstance *lock, DiyaSessionShell *shell) -{ - (void)lock; - assert(shell); - g_message("Session locked successfully"); - g_signal_emit_by_name(shell, DIYA_SIGNAL_SESSION_LOCKED); -} - -static void on_session_unlocked(GtkSessionLockInstance *lock, DiyaSessionShell *shell) -{ - (void)lock; - assert(shell); - g_message("Session unlocked"); - g_signal_emit_by_name(shell, DIYA_SIGNAL_SESSION_UNLOCKED); } static void diya_session_shell_init(DiyaSessionShell *self) @@ -334,10 +285,6 @@ static void diya_session_shell_init(DiyaSessionShell *self) // self->app = NULL; self->launcher = NULL; self->settings = NULL; - self->lock = gtk_session_lock_instance_new(); - g_signal_connect(self->lock, "locked", G_CALLBACK(on_session_locked), self); - // g_signal_connect(lock, "failed", G_CALLBACK(failed), NULL); - g_signal_connect(self->lock, "unlocked", G_CALLBACK(on_session_unlocked), self); self->windows = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref); } diff --git a/src/session-shell.h b/src/session-shell.h index f877aa2..8994697 100644 --- a/src/session-shell.h +++ b/src/session-shell.h @@ -9,11 +9,8 @@ #define DIYA_SIGNAL_FOREIGN_WINDOW_STATE_CHANGED "foreign-window-state-changed" #define DIYA_SIGNAL_FOREIGN_WINDOW_ADDED "foreign-window-added" #define DIYA_SIGNAL_FOREIGN_WINDOW_REMOVED "foreign-window-removed" -#define DIYA_SIGNAL_SESSION_LOCKED "session-locked" -#define DIYA_SIGNAL_SESSION_UNLOCKED "session-unlocked" #define DIYA_PROP_SESSION_LAUNCHPAD "launchpad" -#define DIYA_PROP_SESSION_LOCK "session-lock" #define DIYA_PROP_SESSION_WINDOWS "windows" #define SESSION_SHELL_SCHEMA_ID "dev.iohub.diya.session" diff --git a/src/session.c b/src/session.c index 5d7e9e1..57f3c7e 100644 --- a/src/session.c +++ b/src/session.c @@ -19,7 +19,7 @@ static void session_unlocked(DiyaSessionShell* shell, void* data) int main(int argc, char *argv[]) { DiyaSessionShell *shell = DIYA_SESSION_SHELL(g_object_new(DIYA_TYPE_SESSION_SHELL, "name","dev.iohub.diya.session", NULL)); - g_signal_connect(shell, DIYA_SIGNAL_SESSION_LOCKED, G_CALLBACK(session_locked), NULL); - g_signal_connect(shell, DIYA_SIGNAL_SESSION_UNLOCKED, G_CALLBACK(session_unlocked), NULL); + g_signal_connect(shell, DIYA_SIGNAL_SHELL_LOCKED, G_CALLBACK(session_locked), NULL); + g_signal_connect(shell, DIYA_SIGNAL_SHELL_UNLOCKED, G_CALLBACK(session_unlocked), NULL); return diya_shell_run(DIYA_SHELL(shell), argc, argv); } diff --git a/src/shell.c b/src/shell.c index 9b12302..0f18f2b 100644 --- a/src/shell.c +++ b/src/shell.c @@ -8,6 +8,7 @@ #include "hook.h" #include #include +#include #define diya_shell_config_theme(priv) (g_strconcat(g_get_home_dir(), "/.themes/", priv->theme ? priv->theme : "default", "/gtk-4.0/gtk.css", NULL)) #define diya_shell_config_theme_dir(priv) (g_strconcat(g_get_home_dir(), "/.themes/", priv->theme ? priv->theme : "default", "/gtk-4.0", NULL)) @@ -19,6 +20,7 @@ enum PROP_SHELL_NAME, PROP_SHELL_THEME, PROP_SHELL_IDLE_TO, + PROP_SHELL_LOCK, N_PROPERTIES }; @@ -36,6 +38,7 @@ typedef struct _DiyaShellPrivate DiyaHook *files_hook; gchar *theme; DiyaIdleNotification *idle_notif; + GtkSessionLockInstance *lock; } DiyaShellPrivate; G_DEFINE_TYPE_WITH_PRIVATE(DiyaShell, diya_shell, DIYA_TYPE_OBJECT); @@ -69,6 +72,14 @@ static void diya_shell_dispose(GObject *object) g_object_unref(priv->idle_notif); priv->idle_notif = NULL; } + if (priv->lock) + { + if (gtk_session_lock_instance_is_locked(priv->lock)) + { + gtk_session_lock_instance_unlock(priv->lock); + } + g_object_unref(priv->lock); + } if (priv->wayland) { g_object_unref(priv->wayland); @@ -187,13 +198,14 @@ static void on_gtk_app_startup(GtkApplication *app, void *data) { class->startup_handle(shell); } + /* if (class->monitor_changed_handle) { GListModel *monitor_list = gdk_display_get_monitors(gdk_display_get_default()); g_debug("listen to monitor changed"); g_signal_connect(monitor_list, "items-changed", G_CALLBACK(class->monitor_changed_handle), shell); } - + */ } static void on_gtk_app_active(GtkApplication *app, void *data) @@ -322,6 +334,10 @@ static void diya_shell_get_property(GObject *object, guint property_id, GValue * case PROP_SHELL_THEME: g_value_set_string(value, priv->theme); break; + case PROP_SHELL_LOCK: + // assert(priv->lock); + g_value_set_pointer(value, priv->lock); + break; case PROP_SHELL_IDLE_TO: if(priv->idle_notif) { @@ -338,6 +354,59 @@ static void diya_shell_get_property(GObject *object, guint property_id, GValue * } } + +static void on_shell_locked(GtkSessionLockInstance *lock, DiyaShell *shell) +{ + (void)lock; + assert(shell); + g_message("Shell locked successfully"); + g_signal_emit_by_name(shell, DIYA_SIGNAL_SHELL_LOCKED); +} + +static void on_shell_unlocked(GtkSessionLockInstance *lock, DiyaShell *shell) +{ + (void)lock; + assert(shell); + g_message("Shell unlocked"); + g_signal_emit_by_name(shell, DIYA_SIGNAL_SHELL_UNLOCKED); +} + +static void on_shell_lock_failed(GtkSessionLockInstance *lock, DiyaShell *shell) +{ + (void)lock; + assert(shell); + g_critical("Unable to lock shell"); + g_signal_emit_by_name(shell, DIYA_SIGNAL_SHELL_LOCK_FAILED); +} + +static void on_monitor_present(GtkSessionLockInstance* lock, GdkMonitor *monitor, DiyaShell *shell) +{ + assert(shell); + g_debug("Build lock window for monitor"); + DiyaShellClass *class = DIYA_SHELL_GET_CLASS(shell); + if(class->build_lock_window) + { + GtkWindow* window = class->build_lock_window(shell); + gtk_session_lock_instance_assign_window_to_monitor(lock, window, monitor); + } +} + + +static void diya_shell_init_lock(DiyaShell* self) +{ + DiyaShellPrivate *priv = diya_shell_get_instance_private(self); + if(priv->lock) + { + return; + } + priv->lock = gtk_session_lock_instance_new(); + g_signal_connect(priv->lock, DIYA_SIGNAL_SHELL_LOCKED, G_CALLBACK(on_shell_locked), self); + g_signal_connect(priv->lock, "failed", G_CALLBACK(on_shell_lock_failed), self); + g_signal_connect(priv->lock, DIYA_SIGNAL_SHELL_UNLOCKED, G_CALLBACK(on_shell_unlocked), self); + g_signal_connect(priv->lock, "monitor", G_CALLBACK(on_monitor_present), self); + +} + static void diya_shell_init(DiyaShell *self) { DiyaShellPrivate *priv = diya_shell_get_instance_private(self); @@ -350,6 +419,7 @@ static void diya_shell_init(DiyaShell *self) priv->files_hook = NULL; priv->theme = NULL; priv->idle_notif = NULL; + priv->lock = NULL; } DiyaWayland *diya_shell_get_wayland(DiyaShell *shell) @@ -390,7 +460,7 @@ static void diya_shell_class_init(DiyaShellClass *class) class->foreign_register = NULL; class->virtual_keyboard_register = diya_virtual_keyboard_register; - class->monitor_changed_handle = NULL; + class->build_lock_window = NULL; class->startup_handle = NULL; class->active_handle = NULL; class->reload_handle = NULL; @@ -400,6 +470,7 @@ static void diya_shell_class_init(DiyaShellClass *class) shell_properties[PROP_SHELL_APP] = g_param_spec_pointer(DIYA_PROP_SHELL_APPLICATION, NULL, "Shell application", G_PARAM_READABLE); shell_properties[PROP_SHELL_THEME] = g_param_spec_string(DIYA_PROP_SHELL_THEME, NULL, "Shell theme", NULL, G_PARAM_READWRITE); shell_properties[PROP_SHELL_IDLE_TO] = g_param_spec_uint(DIYA_PROP_SHELL_IDLE_TIMEOUT, NULL, "Shell IDLE timeout", 0, UINT32_MAX ,DEFAULT_IDLE_TIMEOUT, G_PARAM_READWRITE); + shell_properties[PROP_SHELL_LOCK] = g_param_spec_pointer(DIYA_PROP_SHELL_LOCK, NULL, "Shell lock", G_PARAM_READABLE); g_object_class_install_properties(gobject_class, N_PROPERTIES, shell_properties); @@ -519,6 +590,39 @@ static void diya_shell_class_init(DiyaShellClass *class) G_TYPE_NONE, 1, G_TYPE_POINTER); + g_signal_new(DIYA_SIGNAL_SHELL_LOCKED, + DIYA_TYPE_SHELL, + G_SIGNAL_DETAILED | + G_SIGNAL_ACTION | + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 0); + g_signal_new(DIYA_SIGNAL_SHELL_UNLOCKED, + DIYA_TYPE_SHELL, + G_SIGNAL_DETAILED | + G_SIGNAL_ACTION | + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 0); + g_signal_new(DIYA_SIGNAL_SHELL_LOCK_FAILED, + DIYA_TYPE_SHELL, + G_SIGNAL_DETAILED | + G_SIGNAL_ACTION | + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 0); } static int diya_shell_handle_local_options(GApplication *application, GVariantDict *options, gpointer user_data) @@ -702,4 +806,32 @@ gboolean diya_shell_watch_script(DiyaShell* self, const gchar* script) priv->files_hook = diya_hook_new(); } return diya_hook_install_lua(priv->files_hook, script); +} + +void diya_shell_lock(DiyaShell* self) +{ + DiyaShellPrivate *priv = diya_shell_get_instance_private(self); + if(!priv->lock) + { + diya_shell_init_lock(self); + } + if(gtk_session_lock_instance_is_locked(priv->lock)) + { + g_warning("Shell session is already locked, doing nothing"); + return; + } + if(!gtk_session_lock_instance_lock(priv->lock)) + { + g_error("gtk_session_lock_instance_lock:Unable to lock the current session"); + return; + } +} +void diya_shell_unlock(DiyaShell* self) +{ + DiyaShellPrivate *priv = diya_shell_get_instance_private(self); + if(priv->lock) + { + gtk_session_lock_instance_unlock(priv->lock); + g_debug("gtk_session_lock_instance_unlock: Shell unlocked"); + } } \ No newline at end of file diff --git a/src/shell.h b/src/shell.h index 0f423ff..2240ff9 100644 --- a/src/shell.h +++ b/src/shell.h @@ -14,7 +14,7 @@ #define DIYA_PROP_SHELL_APPLICATION "application" #define DIYA_PROP_SHELL_THEME "theme" #define DIYA_PROP_SHELL_IDLE_TIMEOUT "idle-timeout" - +#define DIYA_PROP_SHELL_LOCK "lock" #define DIYA_SIGNAL_SHELL_KEYBOARD_ENTER "keyboard-enter" #define DIYA_SIGNAL_SHELL_KEYBOARD_LEAVE "keyboard-leave" @@ -25,6 +25,9 @@ #define DIYA_SIGNAL_SHELL_RESUME "resume" #define DIYA_SIGNAL_SHELL_WINDOW_ENTER "shell-window-enter" #define DIYA_SIGNAL_SHELL_WINDOW_LEAVE "shell-window-leave" +#define DIYA_SIGNAL_SHELL_LOCKED "locked" +#define DIYA_SIGNAL_SHELL_UNLOCKED "unlocked" +#define DIYA_SIGNAL_SHELL_LOCK_FAILED "lock-failed" #define DIYA_TYPE_SHELL (diya_shell_get_type()) G_DECLARE_DERIVABLE_TYPE(DiyaShell, diya_shell, DIYA, SHELL, DiyaObject) @@ -38,7 +41,7 @@ struct _DiyaShellClass DiyaObjectClass parent_class; wl_protocol_manager_register_t foreign_register; wl_protocol_manager_register_t virtual_keyboard_register; - void (*monitor_changed_handle)(GListModel* /*list*/,guint /*position*/, guint /*removed*/,guint /*added*/, gpointer); + GtkWindow* (*build_lock_window)(DiyaShell*); void (*startup_handle)(DiyaShell*); void (*active_handle)(DiyaShell*); void (*reload_handle)(DiyaShell*); @@ -57,6 +60,8 @@ gboolean diya_shell_watch_script(DiyaShell* shell, const gchar* script); void diya_shell_unwatch_file(DiyaShell* shell, const gchar* file); void diya_shell_power_display(DiyaShell* shell, gboolean mode); void diya_shell_launch(DiyaShell* shell, GAppInfo* app); +void diya_shell_lock(DiyaShell* shell); +void diya_shell_unlock(DiyaShell* shell); int diya_shell_run(DiyaShell* shell, int argc, char **argv); #endif \ No newline at end of file diff --git a/src/widgets/taskbar-widget.c b/src/widgets/taskbar-widget.c index feebcca..188d9a7 100644 --- a/src/widgets/taskbar-widget.c +++ b/src/widgets/taskbar-widget.c @@ -1,5 +1,6 @@ #include "taskbar-widget.h" #include "foreign.h" +#include "session-lock.h" #define DEFAULT_APP_ICON_NAME "application-x-executable-symbolic" @@ -303,6 +304,7 @@ static void diya_dashboard_btn_test_clicked(GtkWidget *widget, gpointer user_dat DiyaShellWindow *self = user_data; DiyaSessionShell *shell = DIYA_SESSION_SHELL(diya_shell_window_get_shell(self)); g_return_if_fail(DIYA_IS_SESSION_SHELL(shell)); + diya_shell_lock(DIYA_SHELL(shell)); // TODO remove }