diff --git a/meson.build b/meson.build index ba47f9a..21785c7 100644 --- a/meson.build +++ b/meson.build @@ -77,6 +77,7 @@ dm_src = [ 'src/foreign.c', 'src/session-lock.c', 'src/session.c', + 'src/idle.c', 'src/widgets/base-widgets.c', 'src/widgets/taskbar-widget.c', 'src/widgets/dashboard-widget.c', diff --git a/src/foreign.c b/src/foreign.c index 4579e46..740c28b 100644 --- a/src/foreign.c +++ b/src/foreign.c @@ -154,8 +154,6 @@ static void diya_foreign_window_class_init(DiyaForeignWindowClass *class) g_object_class_install_properties (gobject_class, N_PROPERTIES, win_properties); } -static struct zwlr_foreign_toplevel_manager_v1 *g_toplevel_manager; - static void toplevel_handle_output_leave(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, struct wl_output *output) @@ -319,11 +317,10 @@ static const struct zwlr_foreign_toplevel_manager_v1_listener g_toplevel_manager .finished = toplevel_manager_handle_finished, }; -void diya_session_shell_foreign_toplevel_register(struct wl_registry *registry, uint32_t name, DiyaShell *shell) +void diya_session_shell_foreign_toplevel_register(gpointer mngr, DiyaShell *shell) { DiyaSessionShell* session_shell = DIYA_SESSION_SHELL(shell); - g_toplevel_manager = wl_registry_bind(registry, name, &zwlr_foreign_toplevel_manager_v1_interface, 3); - zwlr_foreign_toplevel_manager_v1_add_listener(g_toplevel_manager, &g_toplevel_manager_impl, (void *)session_shell); + zwlr_foreign_toplevel_manager_v1_add_listener(mngr, &g_toplevel_manager_impl, (void *)session_shell); } diff --git a/src/foreign.h b/src/foreign.h index e2ac4e2..f18d03d 100644 --- a/src/foreign.h +++ b/src/foreign.h @@ -24,7 +24,7 @@ enum diya_win_state USE_CLASS(DiyaShell); USE_CLASS(GAppInfo); -void diya_session_shell_foreign_toplevel_register(struct wl_registry *registry, uint32_t name, DiyaShell * shell); +void diya_session_shell_foreign_toplevel_register(gpointer mngr, DiyaShell * shell); DiyaShell* diya_foreign_window_get_shell(DiyaForeignWindow* window); diff --git a/src/idle.c b/src/idle.c new file mode 100644 index 0000000..a2fe5a4 --- /dev/null +++ b/src/idle.c @@ -0,0 +1,129 @@ +#include "idle.h" +#include "wayland.h" +#include "ext-idle-notify-v1.h" +#include "shell.h" + + +struct _DiyaIdleNotification +{ + DiyaShellObject parent; + struct ext_idle_notification_v1* notification; + guint timeout; +}; + +G_DEFINE_FINAL_TYPE(DiyaIdleNotification, diya_idle_notification, DIYA_TYPE_SHELL_OBJECT) + +static void diya_idle_notification_finalize(GObject* object) +{ + (void) object; + DiyaIdleNotification * self = DIYA_IDLE_NOTIFICATION(object); + if(self->notification) + { + ext_idle_notification_v1_destroy(self->notification); + self->notification = NULL; + } + g_debug("diya_idle_notification_finalize: %s", diya_object_to_string(object)); + G_OBJECT_CLASS(diya_idle_notification_parent_class)->finalize(object); +} + +static void diya_idle_notification_dispose(GObject* object) +{ + (void) object; + // DiyaIdleNotification * self = DIYA_IDLE_NOTIFICATION(object); + g_debug("diya_idle_notification_dispose: %s", diya_object_to_string(object)); + G_OBJECT_CLASS(diya_idle_notification_parent_class)->dispose(object); +} + +static void diya_idle_notification_init(DiyaIdleNotification * self) +{ + self->notification = NULL; +} + +static const gchar* diya_idle_notification_to_string(DiyaObject* object) +{ + (void) object; + return "DiyaIdleNotification - wayland client handle object"; +} + +static void diya_idle_notification_class_init(DiyaIdleNotificationClass *class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(class); + DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class); + + gobject_class->dispose = diya_idle_notification_dispose; + gobject_class->finalize = diya_idle_notification_finalize; + base_class->to_string = diya_idle_notification_to_string; + + g_signal_new(DIYA_SIGNAL_IDLE_NOTIF_IDLE, + DIYA_TYPE_IDLE_NOTIFICATION, + G_SIGNAL_DETAILED | + G_SIGNAL_ACTION | + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 0); + + g_signal_new(DIYA_SIGNAL_IDLE_NOTIF_RESUME, + DIYA_TYPE_IDLE_NOTIFICATION, + G_SIGNAL_DETAILED | + G_SIGNAL_ACTION | + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 0); +} + +void diya_idle(void *data, struct ext_idle_notification_v1 *notification) +{ + (void) notification; + DiyaIdleNotification* self = data; + g_signal_emit_by_name(self, DIYA_SIGNAL_IDLE_NOTIF_IDLE); + +} + +void diya_resume(void *data, struct ext_idle_notification_v1 *notification) +{ + (void) notification; + DiyaIdleNotification* self = data; + g_signal_emit_by_name(self, DIYA_SIGNAL_IDLE_NOTIF_RESUME); +} + +static const struct ext_idle_notification_v1_listener g_idle_listener_impl = +{ + .idled = diya_idle, + .resumed = diya_resume +}; + +void diya_idle_manager_register(gpointer mngr, DiyaShell *shell) +{ + (void) mngr; + (void) shell; +} + +DiyaIdleNotification* diya_shell_get_idle_notification(DiyaShell* shell, guint timeout_ms) +{ + DiyaWayland *wayland = diya_shell_get_wayland(shell); + struct ext_idle_notifier_v1* mngr = diya_wayland_get_idle_mngr(wayland); + if(!mngr) + { + return NULL; + } + DiyaIdleNotification* self = g_object_new(DIYA_TYPE_IDLE_NOTIFICATION, "shell", shell, NULL); + struct wl_seat *seat = diya_wayland_get_seat(wayland); + self->timeout = timeout_ms; + self->notification = ext_idle_notifier_v1_get_idle_notification(mngr, timeout_ms, seat); + ext_idle_notification_v1_add_listener(self->notification, &g_idle_listener_impl, self); + return self; +} + + +guint diya_shell_notification_get_timeout(DiyaIdleNotification* self) +{ + return self->timeout; +} \ No newline at end of file diff --git a/src/idle.h b/src/idle.h new file mode 100644 index 0000000..117d2cc --- /dev/null +++ b/src/idle.h @@ -0,0 +1,17 @@ +#ifndef DIYAC_IDLE_H +#define DIYAC_IDLE_H + +#include "base.h" + +#define DIYA_SIGNAL_IDLE_NOTIF_IDLE "idle" +#define DIYA_SIGNAL_IDLE_NOTIF_RESUME "resume" + +#define DIYA_TYPE_IDLE_NOTIFICATION (diya_idle_notification_get_type ()) +G_DECLARE_FINAL_TYPE (DiyaIdleNotification, diya_idle_notification, DIYA, IDLE_NOTIFICATION, DiyaShellObject) + +USE_CLASS(DiyaShell); + +void diya_idle_manager_register(gpointer mngr, DiyaShell *shell); +DiyaIdleNotification* diya_shell_get_idle_notification(DiyaShell* shell, guint timeout_ms); +guint diya_shell_notification_get_timeout(DiyaIdleNotification* self); +#endif /* DIYAC_IDLE_H */ \ No newline at end of file diff --git a/src/session-shell.c b/src/session-shell.c index 8b5cfb1..408d5b8 100644 --- a/src/session-shell.c +++ b/src/session-shell.c @@ -9,7 +9,7 @@ #include "background.h" #include "launcher.h" #include "session-lock.h" - +#include "idle.h" enum { NO_PROP, @@ -29,6 +29,7 @@ struct _DiyaSessionShell DiyaLauncher *launcher; GHashTable *windows; GtkSessionLockInstance *lock; + DiyaIdleNotification* idle_notif; }; G_DEFINE_FINAL_TYPE(DiyaSessionShell, diya_session_shell, DIYA_TYPE_SHELL) @@ -57,6 +58,11 @@ static void diya_session_shell_dispose(GObject *object) { g_object_unref(self->launcher); } + if (self->idle_notif) + { + g_object_unref(self->idle_notif); + self->idle_notif = NULL; + } G_OBJECT_CLASS(diya_session_shell_parent_class)->dispose(object); } @@ -136,11 +142,35 @@ static void diya_session_on_key_pressed(DiyaShell* shell, struct xkb_keymap *xkb */ } +static void diya_session_shell_idle(DiyaIdleNotification* notif, DiyaSessionShell* shell) +{ + assert(DIYA_IS_IDLE_NOTIFICATION(notif)); + assert(DIYA_IS_SESSION_SHELL(shell)); + g_debug("Shell IDLE"); +} + +static void diya_session_shell_resume(DiyaIdleNotification* notif, DiyaSessionShell* shell) +{ + assert(DIYA_IS_IDLE_NOTIFICATION(notif)); + assert(DIYA_IS_SESSION_SHELL(shell)); + g_critical("Shell RESUME"); +} + static void diya_session_shell_startup(DiyaShell *shell) { - diya_session_shell_init_background(DIYA_SESSION_SHELL(shell)); - diya_session_shell_launcher_init(DIYA_SESSION_SHELL(shell)); + DiyaSessionShell* self = DIYA_SESSION_SHELL(shell); + diya_session_shell_init_background(self); + diya_session_shell_launcher_init(self); g_signal_connect(shell, DIYA_SIGNAL_SHELL_KEY_PRESSED, G_CALLBACK(diya_session_on_key_pressed), NULL); + + /** + * TODO: + * - read timeout from setting + * - implement widget that handle idle (turn off display + lock) + */ + self->idle_notif = diya_shell_get_idle_notification(shell, 5000); + g_signal_connect(self->idle_notif, DIYA_SIGNAL_IDLE_NOTIF_IDLE, G_CALLBACK(diya_session_shell_idle), self); + g_signal_connect(self->idle_notif, DIYA_SIGNAL_IDLE_NOTIF_RESUME, G_CALLBACK(diya_session_shell_resume), self); } static void diya_session_shell_active(DiyaShell *shell) @@ -155,6 +185,7 @@ static void diya_session_shell_class_init(DiyaSessionShellClass *class) DiyaShellClass *base_shell_class = DIYA_SHELL_CLASS(class); base_shell_class->foreign_register = diya_session_shell_foreign_toplevel_register; + base_shell_class->idle_notifier_register = diya_idle_manager_register; base_shell_class->startup_handle = diya_session_shell_startup; base_shell_class->active_handle = diya_session_shell_active; @@ -266,6 +297,7 @@ static void diya_session_shell_init(DiyaSessionShell *self) self->background = NULL; self->launcher = NULL; self->lock = gtk_session_lock_instance_new(); + self->idle_notif = NULL; 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); diff --git a/src/shell.h b/src/shell.h index b7fb295..46a548a 100644 --- a/src/shell.h +++ b/src/shell.h @@ -24,7 +24,7 @@ G_DECLARE_DERIVABLE_TYPE(DiyaShell, diya_shell, DIYA, SHELL, DiyaObject) struct wl_registry; -typedef void (*wl_protocol_manager_register_t)(struct wl_registry*, uint32_t,DiyaShell*); +typedef void (*wl_protocol_manager_register_t)(gpointer,DiyaShell*); struct _DiyaShellClass { diff --git a/src/virtual-keyboard.c b/src/virtual-keyboard.c index f573b13..9a15060 100644 --- a/src/virtual-keyboard.c +++ b/src/virtual-keyboard.c @@ -136,7 +136,6 @@ gboolean diya_vkb_key_is_modifier(DiyaVkbKey* self) * */ -static struct zwp_virtual_keyboard_manager_v1 *g_virtual_keyboard_manager = NULL; struct _DiyaVirtualKeyboard { @@ -385,16 +384,21 @@ DiyaVirtualKeyboard *diya_virtual_keyboard_new(DiyaShell *shell, const gchar *ke vkb->vkb_keymap = vkb_keymap; DiyaWayland *wayland = diya_shell_get_wayland(shell); struct wl_seat *seat = diya_wayland_get_seat(wayland); - vkb->keyboard = zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(g_virtual_keyboard_manager, seat); + struct zwp_virtual_keyboard_manager_v1* mngr = diya_wayland_get_virtual_keyboard_mngr(wayland); + if(!mngr) + { + return NULL; + } + vkb->keyboard = zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(mngr, seat); zwp_virtual_keyboard_v1_keymap(vkb->keyboard, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, fd, len); return vkb; } -void diya_virtual_keyboard_register(struct wl_registry *registry, uint32_t name, DiyaShell *shell) +void diya_virtual_keyboard_register(gpointer mngr, DiyaShell *shell) { - (void)shell; - g_virtual_keyboard_manager = wl_registry_bind(registry, name, &zwp_virtual_keyboard_manager_v1_interface, 1); + (void) shell; + (void) mngr; } void diya_virtual_keyboard_send_key(DiyaVirtualKeyboard *self, DiyaVkbKey* key, diya_vkb_state_t state) @@ -439,7 +443,7 @@ void diya_virtual_keyboard_send_key(DiyaVirtualKeyboard *self, DiyaVkbKey* key, } if(old_mods != self->key_mods) { - g_signal_emit_by_name(self,DIYA_SIGNAL_VKB_MODIFIER_CHANGED, NULL); + g_signal_emit_by_name(self,DIYA_SIGNAL_VKB_MODIFIER_CHANGED); } } diff --git a/src/virtual-keyboard.h b/src/virtual-keyboard.h index 8b45471..476f785 100644 --- a/src/virtual-keyboard.h +++ b/src/virtual-keyboard.h @@ -26,7 +26,7 @@ gboolean diya_vkb_key_is_modifier(DiyaVkbKey* key); DiyaVirtualKeyboard* diya_virtual_keyboard_new(DiyaShell* shell, const gchar* keymap_file); -void diya_virtual_keyboard_register(struct wl_registry *registry, uint32_t name, DiyaShell *shell); +void diya_virtual_keyboard_register(gpointer mngr, DiyaShell *shell); void diya_virtual_keyboard_send_key(DiyaVirtualKeyboard* vkb, DiyaVkbKey* key, diya_vkb_state_t state); DiyaVkbKey* diya_virtual_keyboard_get_key(DiyaVirtualKeyboard* vkb, uint32_t key); diff --git a/src/wayland.c b/src/wayland.c index dd22135..e2df76e 100644 --- a/src/wayland.c +++ b/src/wayland.c @@ -13,13 +13,40 @@ struct _DiyaWayland struct wl_compositor * compositor; struct wl_shm * shm; struct wl_seat * seat; + // protocol manager + struct zwlr_foreign_toplevel_manager_v1 * foreign_toplevel_mngr; + struct zwp_virtual_keyboard_manager_v1 * virtual_keyboard_mngr; + struct ext_idle_notifier_v1 * idle_notifier_mngr; }; G_DEFINE_FINAL_TYPE(DiyaWayland, diya_wayland, DIYA_TYPE_SHELL_OBJECT) +static void diya_wayland_finalize(GObject* object) +{ + (void) object; + DiyaWayland * self = DIYA_WAYLAND(object); + if(self->foreign_toplevel_mngr) + { + zwlr_foreign_toplevel_manager_v1_destroy(self->foreign_toplevel_mngr); + self->foreign_toplevel_mngr = NULL; + } + if(self->virtual_keyboard_mngr) + { + zwp_virtual_keyboard_manager_v1_destroy(self->virtual_keyboard_mngr); + self->virtual_keyboard_mngr = NULL; + } + if(self->idle_notifier_mngr) + { + ext_idle_notifier_v1_destroy(self->idle_notifier_mngr); + self->idle_notifier_mngr = NULL; + } + g_debug("diya_wayland_finalize: %s", diya_object_to_string(object)); + G_OBJECT_CLASS(diya_wayland_parent_class)->finalize(object); +} + static void diya_wayland_dispose(GObject* object) { (void) object; - //DiyaWayland * self = DIYA_WAYLAND(object); + // DiyaWayland * self = DIYA_WAYLAND(object); g_debug("diya_wayland_dispose: %s", diya_object_to_string(object)); G_OBJECT_CLASS(diya_wayland_parent_class)->dispose(object); } @@ -29,6 +56,9 @@ static void diya_wayland_init(DiyaWayland * self) self->compositor = NULL; self->shm = NULL; self->seat = NULL; + self->foreign_toplevel_mngr = NULL; + self->virtual_keyboard_mngr = NULL; + self->idle_notifier_mngr = NULL; } static const gchar* diya_wayland_to_string(DiyaObject* object) @@ -43,6 +73,7 @@ static void diya_wayland_class_init(DiyaWaylandClass *class) DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class); gobject_class->dispose = diya_wayland_dispose; + gobject_class->finalize = diya_wayland_finalize; //gobject_class->set_property = diya_lock_session_set_property; //gobject_class->get_property = diya_lock_session_get_property; base_class->to_string = diya_wayland_to_string; @@ -74,7 +105,8 @@ static void handle_global(void *data, struct wl_registry *registry, uint32_t nam { //diya_session_shell_foreign_toplevel_register(registry, name, data); g_debug("Wayland: register shell foreign top level manager"); - class->foreign_register(registry, name, data); + wayland->foreign_toplevel_mngr = wl_registry_bind(registry, name, &zwlr_foreign_toplevel_manager_v1_interface, 3); + class->foreign_register(wayland->foreign_toplevel_mngr, shell); } } if (g_strcmp0(interface, zwp_virtual_keyboard_manager_v1_interface.name) == 0) @@ -83,7 +115,8 @@ static void handle_global(void *data, struct wl_registry *registry, uint32_t nam { //diya_session_shell_foreign_toplevel_register(registry, name, data); g_debug("Wayland: register virtual keyboard manager"); - class->virtual_keyboard_register(registry, name, data); + wayland->virtual_keyboard_mngr = wl_registry_bind(registry, name, &zwp_virtual_keyboard_manager_v1_interface, 1); + class->virtual_keyboard_register(wayland->virtual_keyboard_mngr, shell); } } /* @@ -92,29 +125,30 @@ static void handle_global(void *data, struct wl_registry *registry, uint32_t nam diya_session_shell_session_lock_register(registry, name); } */ - else if (strcmp(interface, wl_compositor_interface.name) == 0) + else if (g_strcmp0(interface, wl_compositor_interface.name) == 0) { wayland->compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 4); } - else if (strcmp(interface, wl_shm_interface.name) == 0) + else if (g_strcmp0(interface, wl_shm_interface.name) == 0) { wayland->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); } - else if (strcmp(interface, wl_seat_interface.name) == 0) + else if (g_strcmp0(interface, wl_seat_interface.name) == 0) { wayland->seat = wl_registry_bind(registry, name, &wl_seat_interface, 7); } - else if(strcmp(interface, ext_idle_notifier_v1_interface.name) == 0) + else if(g_strcmp0(interface, ext_idle_notifier_v1_interface.name) == 0) { if(class->idle_notifier_register) { - class->idle_notifier_register(registry, name, data); + g_debug("Wayland: register ext_idle_notifier_v1_interface"); + wayland->idle_notifier_mngr = wl_registry_bind(registry, name, &ext_idle_notifier_v1_interface, 1);; + class->idle_notifier_register(wayland->idle_notifier_mngr, shell); } } } -static void handle_global_remove(void *data, struct wl_registry *registry, - uint32_t name) +static void handle_global_remove(void *data, struct wl_registry *registry,uint32_t name) { (void) data; (void) registry; @@ -185,4 +219,14 @@ struct wl_seat* diya_wayland_get_seat(DiyaWayland* self) { assert(self->seat); return self->seat; +} + +struct zwp_virtual_keyboard_manager_v1* diya_wayland_get_virtual_keyboard_mngr(DiyaWayland* self) +{ + return self->virtual_keyboard_mngr; +} + +struct ext_idle_notifier_v1* diya_wayland_get_idle_mngr(DiyaWayland* self) +{ + return self->idle_notifier_mngr; } \ No newline at end of file diff --git a/src/wayland.h b/src/wayland.h index 1ffefb9..9c0afd6 100644 --- a/src/wayland.h +++ b/src/wayland.h @@ -5,17 +5,14 @@ USE_CLASS(DiyaShell); -//#define DIYA_TYPE_WAYLAND_PROTOCOL_MANAGER (diya_wayland_protocol_manager_get_type()) -//G_DECLARE_DERIVABLE_TYPE(DiyaWaylandProtocolManager, diya_wayland_protocol_manager, DIYA, WAYLAND_PROTOCOL_MANAGER, DiyaObject) - #define DIYA_TYPE_WAYLAND (diya_wayland_get_type ()) G_DECLARE_FINAL_TYPE (DiyaWayland, diya_wayland, DIYA, WAYLAND, DiyaShellObject) - struct wl_surface* diya_wayland_create_surface(DiyaWayland * self); struct wl_output* diya_wayland_get_output(DiyaWayland * self, int index); struct wl_shm_pool * diya_wayland_create_shm_pool(DiyaWayland * self, int fd, guint size); struct wl_seat* diya_wayland_get_seat(DiyaWayland* self); - +struct zwp_virtual_keyboard_manager_v1* diya_wayland_get_virtual_keyboard_mngr(DiyaWayland* self); +struct ext_idle_notifier_v1* diya_wayland_get_idle_mngr(DiyaWayland* self); DiyaWayland* diya_wayland_new(DiyaShell *shell); #endif \ No newline at end of file