From 37602e153b1a8c020dbefe2a499851ac0edd2df8 Mon Sep 17 00:00:00 2001 From: Ilia Bozhinov Date: Tue, 5 Jan 2021 20:18:38 +0100 Subject: [PATCH] types: add wlr_xdg_foreign_registry --- include/meson.build | 5 ++ include/wlr/config.h.in | 2 + include/wlr/types/wlr_xdg_foreign_registry.h | 75 ++++++++++++++++++++ meson.build | 14 +++- meson_options.txt | 1 + types/meson.build | 6 ++ types/wlr_xdg_foreign_registry.c | 73 +++++++++++++++++++ util/meson.build | 15 ++-- 8 files changed, 183 insertions(+), 8 deletions(-) create mode 100644 include/wlr/types/wlr_xdg_foreign_registry.h create mode 100644 types/wlr_xdg_foreign_registry.c diff --git a/include/meson.build b/include/meson.build index e2428e8d..dbd81a05 100644 --- a/include/meson.build +++ b/include/meson.build @@ -7,6 +7,11 @@ endif if conf_data.get('WLR_HAS_XWAYLAND', 0) != 1 exclude_files += 'xwayland.h' endif +if conf_data.get('WLR_HAS_XDG_FOREIGN', 0) != 1 + exclude_files += [ + 'types/wlr_xdg_foreign_registry.h', + ] +endif install_subdir('wlr', install_dir: get_option('includedir'), diff --git a/include/wlr/config.h.in b/include/wlr/config.h.in index c139a4d6..3cec1f1a 100644 --- a/include/wlr/config.h.in +++ b/include/wlr/config.h.in @@ -13,4 +13,6 @@ #mesondefine WLR_HAS_XCB_ERRORS #mesondefine WLR_HAS_XCB_ICCCM +#mesondefine WLR_HAS_XDG_FOREIGN + #endif diff --git a/include/wlr/types/wlr_xdg_foreign_registry.h b/include/wlr/types/wlr_xdg_foreign_registry.h new file mode 100644 index 00000000..462a9a86 --- /dev/null +++ b/include/wlr/types/wlr_xdg_foreign_registry.h @@ -0,0 +1,75 @@ +/* + * This an unstable interface of wlroots. No guarantees are made regarding the + * future consistency of this API. + */ +#ifndef WLR_USE_UNSTABLE +#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features" +#endif + +#ifndef WLR_TYPES_WLR_XDG_FOREIGN_REGISTRY_H +#define WLR_TYPES_WLR_XDG_FOREIGN_REGISTRY_H + +#include + +#define WLR_XDG_FOREIGN_HANDLE_SIZE 37 + +/** + * wlr_xdg_foreign_registry is used for storing a list of exported surfaces with + * the xdg-foreign family of protocols. + * + * It can be used to allow interoperability between clients using different + * versions of the protocol (if all versions use the same registry). + */ +struct wlr_xdg_foreign_registry { + struct wl_list exported_surfaces; // struct wlr_xdg_foreign_exported_surface + + struct wl_listener display_destroy; + struct { + struct wl_signal destroy; + } events; +}; + +struct wlr_xdg_foreign_exported { + struct wl_list link; // wlr_xdg_foreign_registry::exported_surfaces + struct wlr_xdg_foreign_registry *registry; + + struct wlr_surface *surface; + + char handle[WLR_XDG_FOREIGN_HANDLE_SIZE]; + + struct { + struct wl_signal destroy; + } events; +}; + +/** + * Create an empty wlr_xdg_foreign_registry. + * + * It will be destroyed when the associated display is destroyed. + */ +struct wlr_xdg_foreign_registry *wlr_xdg_foreign_registry_create( + struct wl_display *display); + +/** + * Add the given exported surface to the registry and assign it a unique handle. + * The caller is responsible for removing the exported surface from the repository + * if it is destroyed. + * + * Returns true if the initialization was successful. + */ +bool wlr_xdg_foreign_exported_init(struct wlr_xdg_foreign_exported *surface, + struct wlr_xdg_foreign_registry *registry); + +/** + * Find an exported surface with the given handle, or NULL if such a surface + * does not exist. + */ +struct wlr_xdg_foreign_exported *wlr_xdg_foreign_registry_find_by_handle( + struct wlr_xdg_foreign_registry *registry, const char *handle); + +/** + * Remove the given surface from the registry it was previously added in. + */ +void wlr_xdg_foreign_exported_finish(struct wlr_xdg_foreign_exported *surface); + +#endif diff --git a/meson.build b/meson.build index c6835fbe..be1b8aa9 100644 --- a/meson.build +++ b/meson.build @@ -87,6 +87,7 @@ conf_data.set10('WLR_HAS_X11_BACKEND', false) conf_data.set10('WLR_HAS_XWAYLAND', false) conf_data.set10('WLR_HAS_XCB_ERRORS', false) conf_data.set10('WLR_HAS_XCB_ICCCM', false) +conf_data.set10('WLR_HAS_XDG_FOREIGN', false) # Clang complains about some zeroed initializer lists (= {0}), even though they # are valid @@ -109,8 +110,16 @@ pixman = dependency('pixman-1') math = cc.find_library('m') rt = cc.find_library('rt') -uuid = dependency('uuid', required: false) -uuid_create = cc.has_function('uuid_create') +if not get_option('xdg-foreign').disabled() + uuid = dependency('uuid', required: false) + uuid_create = cc.has_function('uuid_create') + if uuid.found() or uuid_create + conf_data.set10('WLR_HAS_XDG_FOREIGN', true) + elif get_option('xdg-foreign').enabled() + error('Missing dependency uuid and uuid_create function not available ' + + 'cannot build with xdg-foreign support') + endif +endif wlr_files = [] wlr_deps = [ @@ -171,6 +180,7 @@ summary({ 'x11_backend': conf_data.get('WLR_HAS_X11_BACKEND', 0) == 1, 'xcb-icccm': conf_data.get('WLR_HAS_XCB_ICCCM', 0) == 1, 'xcb-errors': conf_data.get('WLR_HAS_XCB_ERRORS', 0) == 1, + 'xdg-foreign': conf_data.get('WLR_HAS_XDG_FOREIGN', 0) == 1, }, bool_yn: true) if get_option('examples') diff --git a/meson_options.txt b/meson_options.txt index 382ef2a6..e4ff6019 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -7,3 +7,4 @@ option('xwayland', type: 'feature', value: 'auto', yield: true, description: 'En option('x11-backend', type: 'feature', value: 'auto', description: 'Enable X11 backend') option('examples', type: 'boolean', value: true, description: 'Build example applications') option('icon_directory', description: 'Location used to look for cursors (default: ${datadir}/icons)', type: 'string', value: '') +option('xdg-foreign', type: 'feature', value: 'auto', description: 'Enable xdg-foreign protocol') diff --git a/types/meson.build b/types/meson.build index 80978176..a2052b3a 100644 --- a/types/meson.build +++ b/types/meson.build @@ -66,3 +66,9 @@ wlr_files += files( 'wlr_xdg_decoration_v1.c', 'wlr_xdg_output_v1.c', ) + +if conf_data.get('WLR_HAS_XDG_FOREIGN', 0) == 1 + wlr_files += files( + 'wlr_xdg_foreign_registry.c', + ) +endif diff --git a/types/wlr_xdg_foreign_registry.c b/types/wlr_xdg_foreign_registry.c new file mode 100644 index 00000000..7af137b5 --- /dev/null +++ b/types/wlr_xdg_foreign_registry.c @@ -0,0 +1,73 @@ +#include +#include "util/signal.h" +#include "util/uuid.h" +#include +#include +#include + +bool wlr_xdg_foreign_exported_init( + struct wlr_xdg_foreign_exported *exported, + struct wlr_xdg_foreign_registry *registry) { + do { + if (!generate_uuid(exported->handle)) { + return false; + } + } while (wlr_xdg_foreign_registry_find_by_handle(registry, exported->handle) != NULL); + + exported->registry = registry; + wl_list_insert(®istry->exported_surfaces, &exported->link); + + wl_signal_init(&exported->events.destroy); + return true; +} + +struct wlr_xdg_foreign_exported *wlr_xdg_foreign_registry_find_by_handle( + struct wlr_xdg_foreign_registry *registry, const char *handle) { + if (handle == NULL || strlen(handle) >= WLR_XDG_FOREIGN_HANDLE_SIZE) { + return NULL; + } + + struct wlr_xdg_foreign_exported *exported; + wl_list_for_each(exported, ®istry->exported_surfaces, link) { + if (strcmp(handle, exported->handle) == 0) { + return exported; + } + } + + return NULL; +} + +void wlr_xdg_foreign_exported_finish(struct wlr_xdg_foreign_exported *surface) { + wlr_signal_emit_safe(&surface->events.destroy, NULL); + surface->registry = NULL; + wl_list_remove(&surface->link); + wl_list_init(&surface->link); +} + +static void foreign_registry_handle_display_destroy(struct wl_listener *listener, + void *data) { + struct wlr_xdg_foreign_registry *registry = + wl_container_of(listener, registry, display_destroy); + + wlr_signal_emit_safe(®istry->events.destroy, NULL); + + // Implementations are supposed to remove all surfaces + assert(wl_list_empty(®istry->exported_surfaces)); + free(registry); +} + + +struct wlr_xdg_foreign_registry *wlr_xdg_foreign_registry_create( + struct wl_display *display) { + struct wlr_xdg_foreign_registry *registry = calloc(1, sizeof(*registry)); + if (!registry) { + return NULL; + } + + registry->display_destroy.notify = foreign_registry_handle_display_destroy; + wl_display_add_destroy_listener(display, ®istry->display_destroy); + + wl_list_init(®istry->exported_surfaces); + wl_signal_init(®istry->events.destroy); + return registry; +} diff --git a/util/meson.build b/util/meson.build index 06996a4e..6b423980 100644 --- a/util/meson.build +++ b/util/meson.build @@ -8,10 +8,13 @@ wlr_files += files( 'time.c', ) -if uuid.found() - wlr_deps += uuid - add_project_arguments('-DHAS_LIBUUID=1', language: 'c') -else - add_project_arguments('-DHAS_LIBUUID=0', language: 'c') + +if conf_data.get('WLR_HAS_XDG_FOREIGN', 0) == 1 + if uuid.found() + wlr_deps += uuid + add_project_arguments('-DHAS_LIBUUID=1', language: 'c') + else + add_project_arguments('-DHAS_LIBUUID=0', language: 'c') + endif + wlr_files += files('uuid.c') endif -wlr_files += files('uuid.c')