From 928231c51f62e098d4e4d94d8b8e323522894826 Mon Sep 17 00:00:00 2001 From: Dany LE Date: Wed, 5 Nov 2025 17:35:17 +0100 Subject: [PATCH] feat: add screencopy_v1 support + refactor wayland code --- meson.build | 1 + protocols/wlr-screencopy-unstable-v1.xml | 232 +++++++++++++++++++++++ src/foreign.c | 17 +- src/foreign.h | 2 +- src/idle.c | 2 +- src/idle.h | 1 - src/session-shell.c | 18 +- src/session.c | 8 +- src/shell.c | 26 ++- src/shell.h | 7 +- src/virtual-keyboard.c | 19 +- src/virtual-keyboard.h | 1 - src/wayland.c | 93 ++++++--- src/wayland.h | 16 +- 14 files changed, 381 insertions(+), 62 deletions(-) create mode 100644 protocols/wlr-screencopy-unstable-v1.xml diff --git a/meson.build b/meson.build index 79392ef..3a7f1a5 100644 --- a/meson.build +++ b/meson.build @@ -42,6 +42,7 @@ wl_protocols = [ 'protocols/wlr-foreign-toplevel-management-unstable-v1', 'protocols/virtual-keyboard-unstable-v1', 'protocols/wlr-output-power-management-unstable-v1', + 'protocols/wlr-screencopy-unstable-v1', ] foreach proto : wl_protocols diff --git a/protocols/wlr-screencopy-unstable-v1.xml b/protocols/wlr-screencopy-unstable-v1.xml new file mode 100644 index 0000000..50b1b7d --- /dev/null +++ b/protocols/wlr-screencopy-unstable-v1.xml @@ -0,0 +1,232 @@ + + + + Copyright © 2018 Simon Ser + Copyright © 2019 Andri Yngvason + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + This protocol allows clients to ask the compositor to copy part of the + screen content to a client buffer. + + Warning! The protocol described in this file is experimental and + backward incompatible changes may be made. Backward compatible changes + may be added together with the corresponding interface version bump. + Backward incompatible changes are done by bumping the version number in + the protocol and interface names and resetting the interface version. + Once the protocol is to be declared stable, the 'z' prefix and the + version number in the protocol and interface names are removed and the + interface version number is reset. + + + + + This object is a manager which offers requests to start capturing from a + source. + + + + + Capture the next frame of an entire output. + + + + + + + + + Capture the next frame of an output's region. + + The region is given in output logical coordinates, see + xdg_output.logical_size. The region will be clipped to the output's + extents. + + + + + + + + + + + + + All objects created by the manager will still remain valid, until their + appropriate destroy request has been called. + + + + + + + This object represents a single frame. + + When created, a series of buffer events will be sent, each representing a + supported buffer type. The "buffer_done" event is sent afterwards to + indicate that all supported buffer types have been enumerated. The client + will then be able to send a "copy" request. If the capture is successful, + the compositor will send a "flags" followed by a "ready" event. + + For objects version 2 or lower, wl_shm buffers are always supported, ie. + the "buffer" event is guaranteed to be sent. + + If the capture failed, the "failed" event is sent. This can happen anytime + before the "ready" event. + + Once either a "ready" or a "failed" event is received, the client should + destroy the frame. + + + + + Provides information about wl_shm buffer parameters that need to be + used for this frame. This event is sent once after the frame is created + if wl_shm buffers are supported. + + + + + + + + + + Copy the frame to the supplied buffer. The buffer must have a the + correct size, see zwlr_screencopy_frame_v1.buffer and + zwlr_screencopy_frame_v1.linux_dmabuf. The buffer needs to have a + supported format. + + If the frame is successfully copied, a "flags" and a "ready" events are + sent. Otherwise, a "failed" event is sent. + + + + + + + + + + + + + + + + Provides flags about the frame. This event is sent once before the + "ready" event. + + + + + + + Called as soon as the frame is copied, indicating it is available + for reading. This event includes the time at which presentation happened + at. + + The timestamp is expressed as tv_sec_hi, tv_sec_lo, tv_nsec triples, + each component being an unsigned 32-bit value. Whole seconds are in + tv_sec which is a 64-bit value combined from tv_sec_hi and tv_sec_lo, + and the additional fractional part in tv_nsec as nanoseconds. Hence, + for valid timestamps tv_nsec must be in [0, 999999999]. The seconds part + may have an arbitrary offset at start. + + After receiving this event, the client should destroy the object. + + + + + + + + + This event indicates that the attempted frame copy has failed. + + After receiving this event, the client should destroy the object. + + + + + + Destroys the frame. This request can be sent at any time by the client. + + + + + + + Same as copy, except it waits until there is damage to copy. + + + + + + + This event is sent right before the ready event when copy_with_damage is + requested. It may be generated multiple times for each copy_with_damage + request. + + The arguments describe a box around an area that has changed since the + last copy request that was derived from the current screencopy manager + instance. + + The union of all regions received between the call to copy_with_damage + and a ready event is the total damage since the prior ready event. + + + + + + + + + + + Provides information about linux-dmabuf buffer parameters that need to + be used for this frame. This event is sent once after the frame is + created if linux-dmabuf buffers are supported. + + + + + + + + + This event is sent once after all buffer events have been sent. + + The client should proceed to create a buffer of one of the supported + types, and send a "copy" request. + + + + diff --git a/src/foreign.c b/src/foreign.c index 1bbb7c6..92cae20 100644 --- a/src/foreign.c +++ b/src/foreign.c @@ -327,13 +327,6 @@ static const struct zwlr_foreign_toplevel_manager_v1_listener g_toplevel_manager .finished = toplevel_manager_handle_finished, }; -void diya_session_shell_foreign_toplevel_register(gpointer mngr, DiyaShell *shell) -{ - DiyaSessionShell* session_shell = DIYA_SESSION_SHELL(shell); - zwlr_foreign_toplevel_manager_v1_add_listener(mngr, &g_toplevel_manager_impl, (void *)session_shell); -} - - DiyaShell* diya_foreign_window_get_shell(DiyaForeignWindow* self) { assert(self); @@ -437,4 +430,14 @@ DiyaForeignWindow* diya_foreign_window_get_top_level(DiyaForeignWindow* self) win = win->parent_win; } return win; +} + +void diya_session_shell_foreign_toplevel_register(DiyaShell *shell) +{ + gpointer mngr = diya_wayland_request_service(diya_shell_get_wayland(shell), DIYA_WAYLAND_FOREIGN_TOP_LEVEL); + if(!mngr) + { + return; + } + zwlr_foreign_toplevel_manager_v1_add_listener(mngr, &g_toplevel_manager_impl, (void *)shell); } \ No newline at end of file diff --git a/src/foreign.h b/src/foreign.h index f18d03d..911f156 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(gpointer mngr, DiyaShell * shell); +void diya_session_shell_foreign_toplevel_register(DiyaShell * shell); DiyaShell* diya_foreign_window_get_shell(DiyaForeignWindow* window); diff --git a/src/idle.c b/src/idle.c index 4601934..58e8cd6 100644 --- a/src/idle.c +++ b/src/idle.c @@ -116,7 +116,7 @@ static const struct ext_idle_notification_v1_listener g_idle_listener_impl = 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); + struct ext_idle_notifier_v1* mngr = diya_wayland_request_service(wayland, DIYA_WAYLAND_IDLE_NOTIF); if(!mngr) { return NULL; diff --git a/src/idle.h b/src/idle.h index 593e002..360bfdb 100644 --- a/src/idle.h +++ b/src/idle.h @@ -11,7 +11,6 @@ G_DECLARE_FINAL_TYPE (DiyaIdleNotification, diya_idle_notification, DIYA, IDLE_N 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_idle_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 1da6824..895f8c4 100644 --- a/src/session-shell.c +++ b/src/session-shell.c @@ -10,6 +10,7 @@ #include "session-lock.h" #include "idle.h" #include "widgets/base-widgets.h" +#include "wayland.h" #define compiled_schema_path() (g_strconcat(g_getenv("GSETTINGS_SCHEMA_DIR"), "/gschemas.compiled", NULL)) @@ -163,6 +164,7 @@ void diya_session_init_settings(DiyaSessionShell* self) } else { + g_object_set(self,DIYA_PROP_SHELL_IDLE_TIMEOUT,DEFAULT_IDLE_TIMEOUT, NULL); g_warning("Unable to find schema ID %s", SESSION_SHELL_SCHEMA_ID); } } @@ -170,7 +172,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; @@ -208,16 +210,28 @@ static void diya_session_shell_active(DiyaShell *shell) diya_shell_monitor_input(shell); } +static void diya_session_service_register(DiyaShell* shell, int type) +{ + switch (type) + { + case DIYA_WAYLAND_FOREIGN_TOP_LEVEL: + diya_session_shell_foreign_toplevel_register(shell); + break; + default: + break; + } +} + static void diya_session_shell_class_init(DiyaSessionShellClass *class) { GObjectClass *gobject_class = G_OBJECT_CLASS(class); // DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class); DiyaShellClass *base_shell_class = DIYA_SHELL_CLASS(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_shell_class->on_wayland_service_registered = diya_session_service_register; /// base_class->to_string = diya_session_shell_to_string; gobject_class->dispose = diya_session_shell_dispose; gobject_class->finalize = diya_session_shell_finalize; diff --git a/src/session.c b/src/session.c index 57f3c7e..3870b2d 100644 --- a/src/session.c +++ b/src/session.c @@ -18,7 +18,13 @@ 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)); + DiyaSessionShell *shell = DIYA_SESSION_SHELL( + g_object_new( + DIYA_TYPE_SESSION_SHELL, + "name","dev.iohub.diya.session", + DIYA_PROP_SHELL_ENABLE_FOREIGN_MNGR, true, + DIYA_PROP_SHELL_ENABLE_SCREEN_COPY, true, + 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 0f18f2b..5fac414 100644 --- a/src/shell.c +++ b/src/shell.c @@ -21,6 +21,8 @@ enum PROP_SHELL_THEME, PROP_SHELL_IDLE_TO, PROP_SHELL_LOCK, + PROP_SHELL_ENABLE_FOREIGN_MNGR, + PROP_SHELL_ENABLE_SCREEN_COPY, N_PROPERTIES }; @@ -39,6 +41,8 @@ typedef struct _DiyaShellPrivate gchar *theme; DiyaIdleNotification *idle_notif; GtkSessionLockInstance *lock; + gboolean enable_foreign; + gboolean enable_screen_copy; } DiyaShellPrivate; G_DEFINE_TYPE_WITH_PRIVATE(DiyaShell, diya_shell, DIYA_TYPE_OBJECT); @@ -278,6 +282,12 @@ static void diya_shell_set_property(GObject *object, guint property_id, const GV priv->name = g_strdup(g_value_get_string(value)); init_gtk_application(self); break; + case PROP_SHELL_ENABLE_FOREIGN_MNGR: + priv->enable_foreign = g_value_get_boolean(value); + break; + case PROP_SHELL_ENABLE_SCREEN_COPY: + priv->enable_screen_copy = g_value_get_boolean(value); + break; case PROP_SHELL_IDLE_TO: if(priv->idle_notif) { @@ -338,6 +348,12 @@ static void diya_shell_get_property(GObject *object, guint property_id, GValue * // assert(priv->lock); g_value_set_pointer(value, priv->lock); break; + case PROP_SHELL_ENABLE_FOREIGN_MNGR: + g_value_set_boolean(value, priv->enable_foreign); + break; + case PROP_SHELL_ENABLE_SCREEN_COPY: + g_value_set_boolean(value, priv->enable_screen_copy); + break; case PROP_SHELL_IDLE_TO: if(priv->idle_notif) { @@ -420,6 +436,8 @@ static void diya_shell_init(DiyaShell *self) priv->theme = NULL; priv->idle_notif = NULL; priv->lock = NULL; + priv->enable_foreign = false; + priv->enable_screen_copy = false; } DiyaWayland *diya_shell_get_wayland(DiyaShell *shell) @@ -458,12 +476,11 @@ static void diya_shell_class_init(DiyaShellClass *class) DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class); base_class->to_string = diya_shell_to_string; - class->foreign_register = NULL; - class->virtual_keyboard_register = diya_virtual_keyboard_register; class->build_lock_window = NULL; class->startup_handle = NULL; class->active_handle = NULL; class->reload_handle = NULL; + class->on_wayland_service_registered = NULL; shell_properties[PROP_SHELL_WAYLAND] = g_param_spec_pointer(DIYA_PROP_SHELL_WAYLAND, NULL, "Shell wayland", G_PARAM_READABLE); // shell_properties[PROP_SHELL_NAME] = g_param_spec_string(DIYA_PROP_SHELL_NAME, NULL, "Shell name", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); @@ -471,6 +488,9 @@ static void diya_shell_class_init(DiyaShellClass *class) 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); + // enable wayland feature + shell_properties[PROP_SHELL_ENABLE_FOREIGN_MNGR] = g_param_spec_boolean(DIYA_PROP_SHELL_ENABLE_FOREIGN_MNGR, NULL, "Enable shell foreign window manager", false, G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY); + shell_properties[PROP_SHELL_ENABLE_SCREEN_COPY] = g_param_spec_boolean(DIYA_PROP_SHELL_ENABLE_SCREEN_COPY, NULL, "Enable shell screen copy", false, G_PARAM_READWRITE| G_PARAM_CONSTRUCT_ONLY); g_object_class_install_properties(gobject_class, N_PROPERTIES, shell_properties); @@ -778,7 +798,7 @@ void diya_shell_launch(DiyaShell *self, GAppInfo *app) void diya_shell_power_display(DiyaShell* self, gboolean mode) { DiyaShellPrivate *priv = diya_shell_get_instance_private(self); - struct zwlr_output_power_manager_v1 * mngr = diya_wayland_get_output_mngr(priv->wayland); + struct zwlr_output_power_manager_v1 * mngr = diya_wayland_request_service(priv->wayland, DIYA_WAYLAND_OUTPUT_POWER_MNRG); if(!mngr) { g_warning("Output power manager protocol is not available"); diff --git a/src/shell.h b/src/shell.h index 2240ff9..be23b3d 100644 --- a/src/shell.h +++ b/src/shell.h @@ -15,6 +15,8 @@ #define DIYA_PROP_SHELL_THEME "theme" #define DIYA_PROP_SHELL_IDLE_TIMEOUT "idle-timeout" #define DIYA_PROP_SHELL_LOCK "lock" +#define DIYA_PROP_SHELL_ENABLE_FOREIGN_MNGR "enable-wayland-foreign-toplevel" +#define DIYA_PROP_SHELL_ENABLE_SCREEN_COPY "enable-wayland-screen-copy" #define DIYA_SIGNAL_SHELL_KEYBOARD_ENTER "keyboard-enter" #define DIYA_SIGNAL_SHELL_KEYBOARD_LEAVE "keyboard-leave" @@ -34,14 +36,11 @@ G_DECLARE_DERIVABLE_TYPE(DiyaShell, diya_shell, DIYA, SHELL, DiyaObject) struct wl_registry; -typedef void (*wl_protocol_manager_register_t)(gpointer,DiyaShell*); - struct _DiyaShellClass { DiyaObjectClass parent_class; - wl_protocol_manager_register_t foreign_register; - wl_protocol_manager_register_t virtual_keyboard_register; GtkWindow* (*build_lock_window)(DiyaShell*); + void (*on_wayland_service_registered)(DiyaShell*, int); void (*startup_handle)(DiyaShell*); void (*active_handle)(DiyaShell*); void (*reload_handle)(DiyaShell*); diff --git a/src/virtual-keyboard.c b/src/virtual-keyboard.c index 9a15060..f7b8f0a 100644 --- a/src/virtual-keyboard.c +++ b/src/virtual-keyboard.c @@ -303,6 +303,8 @@ DiyaVirtualKeyboard *diya_virtual_keyboard_new(DiyaShell *shell, const gchar *ke struct xkb_context *vkb_ctx = NULL; struct xkb_keymap *vkb_keymap = NULL; gsize len = 0; + + vkb_ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!vkb_ctx) { @@ -379,28 +381,23 @@ DiyaVirtualKeyboard *diya_virtual_keyboard_new(DiyaShell *shell, const gchar *ke strcpy((char *)ptr, content); free(content); + DiyaVirtualKeyboard *vkb = g_object_new(DIYA_TYPE_VIRTUAL_KEYBOARD, "shell", shell, NULL); vkb->vkb_ctx = vkb_ctx; vkb->vkb_keymap = vkb_keymap; - DiyaWayland *wayland = diya_shell_get_wayland(shell); - struct wl_seat *seat = diya_wayland_get_seat(wayland); - struct zwp_virtual_keyboard_manager_v1* mngr = diya_wayland_get_virtual_keyboard_mngr(wayland); + struct zwp_virtual_keyboard_manager_v1* mngr = diya_wayland_request_service( diya_shell_get_wayland(shell),DIYA_WAYLAND_VIRTUAL_KEYBOARD); if(!mngr) { + g_object_unref(vkb); return NULL; } - vkb->keyboard = zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(mngr, seat); + vkb->keyboard = zwp_virtual_keyboard_manager_v1_create_virtual_keyboard( + mngr, + diya_wayland_get_seat(diya_shell_get_wayland(shell))); zwp_virtual_keyboard_v1_keymap(vkb->keyboard, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, fd, len); - return vkb; } -void diya_virtual_keyboard_register(gpointer mngr, DiyaShell *shell) -{ - (void) shell; - (void) mngr; -} - void diya_virtual_keyboard_send_key(DiyaVirtualKeyboard *self, DiyaVkbKey* key, diya_vkb_state_t state) { guint32 old_mods = self->key_mods; diff --git a/src/virtual-keyboard.h b/src/virtual-keyboard.h index 476f785..eb759e9 100644 --- a/src/virtual-keyboard.h +++ b/src/virtual-keyboard.h @@ -26,7 +26,6 @@ gboolean diya_vkb_key_is_modifier(DiyaVkbKey* key); DiyaVirtualKeyboard* diya_virtual_keyboard_new(DiyaShell* shell, const gchar* keymap_file); -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 9fb97a1..15cd313 100644 --- a/src/wayland.c +++ b/src/wayland.c @@ -5,6 +5,7 @@ #include "virtual-keyboard-unstable-v1.h" #include "ext-idle-notify-v1.h" #include "wlr-output-power-management-unstable-v1.h" +#include "wlr-screencopy-unstable-v1.h" #include "wayland.h" #include "shell.h" @@ -19,6 +20,7 @@ struct _DiyaWayland struct zwp_virtual_keyboard_manager_v1 * virtual_keyboard_mngr; struct ext_idle_notifier_v1 * idle_notifier_mngr; struct zwlr_output_power_manager_v1 * zwlr_output_power_manager_v1; + struct zwlr_screencopy_manager_v1* screencopy_manager_v1; }; G_DEFINE_FINAL_TYPE(DiyaWayland, diya_wayland, DIYA_TYPE_SHELL_OBJECT) @@ -46,6 +48,11 @@ static void diya_wayland_finalize(GObject* object) zwlr_output_power_manager_v1_destroy(self->zwlr_output_power_manager_v1); self->zwlr_output_power_manager_v1 = NULL; } + if(self->screencopy_manager_v1) + { + zwlr_screencopy_manager_v1_destroy(self->screencopy_manager_v1); + self->screencopy_manager_v1 = NULL; + } g_debug("diya_wayland_finalize: %s", diya_object_to_string(object)); G_OBJECT_CLASS(diya_wayland_parent_class)->finalize(object); } @@ -67,6 +74,7 @@ static void diya_wayland_init(DiyaWayland * self) self->virtual_keyboard_mngr = NULL; self->idle_notifier_mngr = NULL; self->zwlr_output_power_manager_v1 = NULL; + self->screencopy_manager_v1 = NULL; } static const gchar* diya_wayland_to_string(DiyaObject* object) @@ -102,31 +110,33 @@ static void handle_global(void *data, struct wl_registry *registry, uint32_t nam (void) version; DiyaWayland *wayland = data; DiyaShell * shell = diya_shell_object_get_shell(data); - + DiyaShellClass* class = DIYA_SHELL_GET_CLASS(shell); assert(DIYA_IS_WAYLAND(wayland)); assert(DIYA_IS_SHELL(shell)); - - DiyaShellClass * class = DIYA_SHELL_GET_CLASS(shell); - g_debug("WAYLAND GLOBAL: %s", interface); + gboolean enable_foreign, enable_screencopy; + g_object_get(shell, + DIYA_PROP_SHELL_ENABLE_FOREIGN_MNGR, &enable_foreign, + DIYA_PROP_SHELL_ENABLE_SCREEN_COPY, &enable_screencopy, + NULL + ); + diya_wayland_service_t service_type = DIYA_WAYLAND_UNEXPORTED; + g_debug("WAYLAND GLOBAL: %s version %d", interface, version); if (!wayland->foreign_toplevel_mngr && g_strcmp0(interface, zwlr_foreign_toplevel_manager_v1_interface.name) == 0) { - if(class->foreign_register) + if(enable_foreign) { //diya_session_shell_foreign_toplevel_register(registry, name, data); g_debug("Wayland: register shell foreign top level manager"); wayland->foreign_toplevel_mngr = wl_registry_bind(registry, name, &zwlr_foreign_toplevel_manager_v1_interface, 3); - class->foreign_register(wayland->foreign_toplevel_mngr, shell); + service_type = DIYA_WAYLAND_FOREIGN_TOP_LEVEL; } } if (!wayland->virtual_keyboard_mngr && g_strcmp0(interface, zwp_virtual_keyboard_manager_v1_interface.name) == 0) { - if(class->virtual_keyboard_register) - { - //diya_session_shell_foreign_toplevel_register(registry, name, data); - g_debug("Wayland: register virtual keyboard manager"); - 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); - } + //diya_session_shell_foreign_toplevel_register(registry, name, data); + g_debug("Wayland: register virtual keyboard manager"); + wayland->virtual_keyboard_mngr = wl_registry_bind(registry, name, &zwp_virtual_keyboard_manager_v1_interface, 1); + service_type = DIYA_WAYLAND_VIRTUAL_KEYBOARD; } /* else if(!g_strcmp0(interface, ext_session_lock_manager_v1_interface.name)) @@ -149,13 +159,27 @@ static void handle_global(void *data, struct wl_registry *registry, uint32_t nam else if(!wayland->idle_notifier_mngr && g_strcmp0(interface, ext_idle_notifier_v1_interface.name) == 0) { g_debug("Wayland: register ext_idle_notifier_v1_interface"); - wayland->idle_notifier_mngr = wl_registry_bind(registry, name, &ext_idle_notifier_v1_interface, 1);; + wayland->idle_notifier_mngr = wl_registry_bind(registry, name, &ext_idle_notifier_v1_interface, 2); + service_type = DIYA_WAYLAND_IDLE_NOTIF; } else if (!wayland->zwlr_output_power_manager_v1 && g_strcmp0(interface, zwlr_output_power_manager_v1_interface.name) == 0) { g_debug("Wayland: register zwlr_output_power_manager_v1_interface"); wayland->zwlr_output_power_manager_v1 = wl_registry_bind(registry, name, &zwlr_output_power_manager_v1_interface, 1); - //class->power_manager_register(wayland->zwlr_output_power_manager_v1, shell); + service_type = DIYA_WAYLAND_OUTPUT_POWER_MNRG; + } + else if(!wayland->screencopy_manager_v1 && g_strcmp0(interface, zwlr_screencopy_manager_v1_interface.name) == 0) + { + if(enable_screencopy) + { + g_debug("Wayland: register zwlr_screencopy_manager_v1"); + wayland->screencopy_manager_v1 = wl_registry_bind(registry, name, &zwlr_screencopy_manager_v1_interface, 3); + service_type = DIYA_WAYLAND_SCREEN_COPY; + } + } + if(service_type != DIYA_WAYLAND_UNEXPORTED && class->on_wayland_service_registered) + { + class->on_wayland_service_registered(shell, service_type); } } @@ -231,17 +255,32 @@ struct wl_seat* diya_wayland_get_seat(DiyaWayland* self) return self->seat; } -struct zwp_virtual_keyboard_manager_v1* diya_wayland_get_virtual_keyboard_mngr(DiyaWayland* self) +gpointer diya_wayland_request_service(DiyaWayland* self, diya_wayland_service_t type) { - return self->virtual_keyboard_mngr; -} - -struct ext_idle_notifier_v1* diya_wayland_get_idle_mngr(DiyaWayland* self) -{ - return self->idle_notifier_mngr; -} - -struct zwlr_output_power_manager_v1 * diya_wayland_get_output_mngr(DiyaWayland* self) -{ - return self->zwlr_output_power_manager_v1; + gpointer service = NULL; + switch (type) + { + case DIYA_WAYLAND_FOREIGN_TOP_LEVEL: + service = self->foreign_toplevel_mngr; + break; + case DIYA_WAYLAND_SCREEN_COPY: + service = self->screencopy_manager_v1; + break; + case DIYA_WAYLAND_IDLE_NOTIF: + service = self->idle_notifier_mngr; + break; + case DIYA_WAYLAND_VIRTUAL_KEYBOARD: + service = self->virtual_keyboard_mngr; + break; + case DIYA_WAYLAND_OUTPUT_POWER_MNRG: + service = self->zwlr_output_power_manager_v1; + default: + break; + } + if(!service) + { + g_critical("Unable to request wayland service %d: service unavailable or unregistered/disabled", type); + return NULL; + } + return service; } \ No newline at end of file diff --git a/src/wayland.h b/src/wayland.h index 6c9f9e3..b4a1799 100644 --- a/src/wayland.h +++ b/src/wayland.h @@ -5,6 +5,17 @@ USE_CLASS(DiyaShell); +typedef void (*wl_protocol_manager_register_t)(gpointer,gpointer); + +typedef enum { + DIYA_WAYLAND_UNEXPORTED, + DIYA_WAYLAND_FOREIGN_TOP_LEVEL, + DIYA_WAYLAND_SCREEN_COPY, + DIYA_WAYLAND_IDLE_NOTIF, + DIYA_WAYLAND_OUTPUT_POWER_MNRG, + DIYA_WAYLAND_VIRTUAL_KEYBOARD, +} diya_wayland_service_t; + #define DIYA_TYPE_WAYLAND (diya_wayland_get_type ()) G_DECLARE_FINAL_TYPE (DiyaWayland, diya_wayland, DIYA, WAYLAND, DiyaShellObject) @@ -12,8 +23,7 @@ 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); -struct zwlr_output_power_manager_v1 * diya_wayland_get_output_mngr(DiyaWayland* self); + +gpointer diya_wayland_request_service(DiyaWayland* self, diya_wayland_service_t type); DiyaWayland* diya_wayland_new(DiyaShell *shell); #endif \ No newline at end of file