From 52dac9bd09acbff718674b138577561002b08b98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kondor=20D=C3=A1niel?= Date: Sun, 16 Feb 2025 00:17:21 +0100 Subject: [PATCH 1/2] wlr-foreign-toplevel-management: update protocol --- ...oreign-toplevel-management-unstable-v1.xml | 44 +++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/protocol/wlr-foreign-toplevel-management-unstable-v1.xml b/protocol/wlr-foreign-toplevel-management-unstable-v1.xml index 108133715..4f54d7740 100644 --- a/protocol/wlr-foreign-toplevel-management-unstable-v1.xml +++ b/protocol/wlr-foreign-toplevel-management-unstable-v1.xml @@ -25,7 +25,7 @@ THIS SOFTWARE. - + The purpose of this protocol is to enable the creation of taskbars and docks by providing them with a list of opened applications and @@ -58,7 +58,7 @@ - + This event indicates that the compositor is done sending events to the zwlr_foreign_toplevel_manager_v1. The server will destroy the object @@ -68,7 +68,7 @@ - + A zwlr_foreign_toplevel_handle_v1 object represents an opened toplevel window. Each app may have multiple opened toplevels. @@ -266,5 +266,43 @@ + + + + + + This event is emitted when the client associated with this surface + announces that it implements a specific DBus interface, available + at the given DBus name and object path. The DBus interface announced + by this event is not tied to any specific surface, but to a client app. + + If an interface is available, both bus_name and object_path will be + non-null. bus_name will typically refer to an unique name, but can + potentially be a well-known name as well. If a previously announced + interface is no longer available, the event will be emitted for it + with bus_name and object_path set to null. + + + + + + + + + This event is emitted when the client associated with this surface + announces that it implements a specific DBus interface, available + at the given DBus name and object path. The DBus interface announced + by this event is specific to this toplevel. + + If an interface is available, both bus_name and object_path will be + non-null. bus_name will typically refer to an unique name, but can + potentially be a well-known name as well. If a previously announced + interface is no longer available, the event will be emitted for it + with bus_name and object_path set to null. + + + + + From 34d780bf75022c5c9502d14e7681c0239a4305bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kondor=20D=C3=A1niel?= Date: Sun, 16 Feb 2025 00:19:09 +0100 Subject: [PATCH 2/2] wlr-foreign-toplevel-management: add support for relaying DBus annotation --- .../wlr_foreign_toplevel_management_v1.h | 39 +++++ types/wlr_foreign_toplevel_management_v1.c | 150 +++++++++++++++++- 2 files changed, 188 insertions(+), 1 deletion(-) diff --git a/include/wlr/types/wlr_foreign_toplevel_management_v1.h b/include/wlr/types/wlr_foreign_toplevel_management_v1.h index c4abcb3dd..6c3fd322f 100644 --- a/include/wlr/types/wlr_foreign_toplevel_management_v1.h +++ b/include/wlr/types/wlr_foreign_toplevel_management_v1.h @@ -45,6 +45,13 @@ struct wlr_foreign_toplevel_handle_v1_output { struct wl_listener output_destroy; }; +struct wlr_foreign_toplevel_handle_v1_dbus_annotation { + struct wl_list link; + char *interface; + char *bus_name; + char *object_path; +}; + struct wlr_foreign_toplevel_handle_v1 { struct wlr_foreign_toplevel_manager_v1 *manager; struct wl_list resources; @@ -57,6 +64,9 @@ struct wlr_foreign_toplevel_handle_v1 { struct wl_list outputs; // wlr_foreign_toplevel_v1_output.link uint32_t state; // enum wlr_foreign_toplevel_v1_state + struct wl_list client_dbus_annotations; // wlr_foreign_toplevel_handle_v1_dbus_annotation.link + struct wl_list surface_dbus_annotations; // wlr_foreign_toplevel_handle_v1_dbus_annotation.link + struct { // struct wlr_foreign_toplevel_handle_v1_maximized_event struct wl_signal request_maximize; @@ -149,5 +159,34 @@ void wlr_foreign_toplevel_handle_v1_set_parent( struct wlr_foreign_toplevel_handle_v1 *toplevel, struct wlr_foreign_toplevel_handle_v1 *parent); +/** + * Add or update a DBus annotation for the client associated with this + * toplevel. Arguements should not be NULL. + */ +void wlr_foreign_toplevel_handle_v1_add_client_dbus_annotation( + struct wlr_foreign_toplevel_handle_v1 *toplevel, const char *interface, + const char *bus_name, const char *object_path); + +/** + * Remove an existing DBus annotation for the client associated with + * this toplevel. + */ +void wlr_foreign_toplevel_handle_v1_remove_client_dbus_annotation( + struct wlr_foreign_toplevel_handle_v1 *toplevel, const char *interface); + +/** + * Add or update a DBus annotation for this toplevel. Arguements should not be NULL. + */ +void wlr_foreign_toplevel_handle_v1_add_surface_dbus_annotation( + struct wlr_foreign_toplevel_handle_v1 *toplevel, const char *interface, + const char *bus_name, const char *object_path); + +/** + * Remove an existing DBus annotation for this toplevel. + */ +void wlr_foreign_toplevel_handle_v1_remove_surface_dbus_annotation( + struct wlr_foreign_toplevel_handle_v1 *toplevel, const char *interface); + + #endif diff --git a/types/wlr_foreign_toplevel_management_v1.c b/types/wlr_foreign_toplevel_management_v1.c index 23935d489..17c268ee1 100644 --- a/types/wlr_foreign_toplevel_management_v1.c +++ b/types/wlr_foreign_toplevel_management_v1.c @@ -8,7 +8,7 @@ #include #include "wlr-foreign-toplevel-management-unstable-v1-protocol.h" -#define FOREIGN_TOPLEVEL_MANAGEMENT_V1_VERSION 3 +#define FOREIGN_TOPLEVEL_MANAGEMENT_V1_VERSION 4 static const struct zwlr_foreign_toplevel_handle_v1_interface toplevel_handle_impl; @@ -486,6 +486,130 @@ void wlr_foreign_toplevel_handle_v1_set_parent( toplevel_update_idle_source(toplevel); } +static void toplevel_add_annotation(struct wl_list *list, const char *interface, + const char *bus_name, const char *object_path) { + assert ( (interface != NULL) && (bus_name != NULL) && (object_path != NULL) ); + + bool found = false; + struct wlr_foreign_toplevel_handle_v1_dbus_annotation *toplevel_annot = NULL; + wl_list_for_each(toplevel_annot, list, link) { + if (!strcmp(toplevel_annot->interface, interface)) { + found = true; + free(toplevel_annot->bus_name); + free(toplevel_annot->object_path); + toplevel_annot->bus_name = strdup(bus_name); + toplevel_annot->object_path = strdup(object_path); + break; + } + } + + if (!found) { + // this interface did not exist before + toplevel_annot = calloc(1, sizeof(struct wlr_foreign_toplevel_handle_v1_dbus_annotation)); + toplevel_annot->interface = strdup(interface); + toplevel_annot->bus_name = strdup(bus_name); + toplevel_annot->object_path = strdup(object_path); + wl_list_insert(list, &toplevel_annot->link); + } +} + +void wlr_foreign_toplevel_handle_v1_add_client_dbus_annotation( + struct wlr_foreign_toplevel_handle_v1 *toplevel, const char *interface, + const char *bus_name, const char *object_path) { + toplevel_add_annotation(&toplevel->client_dbus_annotations, + interface, bus_name, object_path); + + struct wl_resource *resource; + wl_resource_for_each(resource, &toplevel->resources) { + if (wl_resource_get_version(resource) >= + ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_CLIENT_DBUS_ANNOTATION_SINCE_VERSION) { + zwlr_foreign_toplevel_handle_v1_send_client_dbus_annotation( + resource, interface, bus_name, object_path); + } + } + + toplevel_update_idle_source(toplevel); +} + +void wlr_foreign_toplevel_handle_v1_add_surface_dbus_annotation( + struct wlr_foreign_toplevel_handle_v1 *toplevel, const char *interface, + const char *bus_name, const char *object_path) { + toplevel_add_annotation(&toplevel->surface_dbus_annotations, + interface, bus_name, object_path); + + struct wl_resource *resource; + wl_resource_for_each(resource, &toplevel->resources) { + if (wl_resource_get_version(resource) >= + ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_SURFACE_DBUS_ANNOTATION_SINCE_VERSION) { + zwlr_foreign_toplevel_handle_v1_send_surface_dbus_annotation( + resource, interface, bus_name, object_path); + } + } + + toplevel_update_idle_source(toplevel); +} + +static void toplevel_dbus_annotation_destroy( + struct wlr_foreign_toplevel_handle_v1_dbus_annotation *annot) { + wl_list_remove(&annot->link); + free(annot->interface); + free(annot->bus_name); + free(annot->object_path); + free(annot); +} + +void wlr_foreign_toplevel_handle_v1_remove_client_dbus_annotation( + struct wlr_foreign_toplevel_handle_v1 *toplevel, const char *interface) { + assert (interface != NULL); + + bool found = false; + struct wlr_foreign_toplevel_handle_v1_dbus_annotation *toplevel_annot, *tmp; + wl_list_for_each_safe(toplevel_annot, tmp, &toplevel->client_dbus_annotations, link) { + if (!strcmp(toplevel_annot->interface, interface)) { + toplevel_dbus_annotation_destroy(toplevel_annot); + found = true; + break; + } + } + + if (found) { + struct wl_resource *resource; + wl_resource_for_each(resource, &toplevel->resources) { + if (wl_resource_get_version(resource) >= + ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_CLIENT_DBUS_ANNOTATION_SINCE_VERSION) { + zwlr_foreign_toplevel_handle_v1_send_client_dbus_annotation( + resource, interface, NULL, NULL); + } + } + } +} + +void wlr_foreign_toplevel_handle_v1_remove_surface_dbus_annotation( + struct wlr_foreign_toplevel_handle_v1 *toplevel, const char *interface) { + assert (interface != NULL); + + bool found = false; + struct wlr_foreign_toplevel_handle_v1_dbus_annotation *toplevel_annot, *tmp; + wl_list_for_each_safe(toplevel_annot, tmp, &toplevel->surface_dbus_annotations, link) { + if (!strcmp(toplevel_annot->interface, interface)) { + toplevel_dbus_annotation_destroy(toplevel_annot); + found = true; + break; + } + } + + if (found) { + struct wl_resource *resource; + wl_resource_for_each(resource, &toplevel->resources) { + if (wl_resource_get_version(resource) >= + ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_SURFACE_DBUS_ANNOTATION_SINCE_VERSION) { + zwlr_foreign_toplevel_handle_v1_send_surface_dbus_annotation( + resource, interface, NULL, NULL); + } + } + } +} + void wlr_foreign_toplevel_handle_v1_destroy( struct wlr_foreign_toplevel_handle_v1 *toplevel) { if (!toplevel) { @@ -525,6 +649,14 @@ void wlr_foreign_toplevel_handle_v1_destroy( wlr_foreign_toplevel_handle_v1_set_parent(tl, NULL); } } + + struct wlr_foreign_toplevel_handle_v1_dbus_annotation *toplevel_annot, *tmp4; + wl_list_for_each_safe(toplevel_annot, tmp4, &toplevel->client_dbus_annotations, link) { + toplevel_dbus_annotation_destroy(toplevel_annot); + } + wl_list_for_each_safe(toplevel_annot, tmp4, &toplevel->surface_dbus_annotations, link) { + toplevel_dbus_annotation_destroy(toplevel_annot); + } free(toplevel->title); free(toplevel->app_id); @@ -568,6 +700,8 @@ wlr_foreign_toplevel_handle_v1_create( wl_list_init(&toplevel->resources); wl_list_init(&toplevel->outputs); + wl_list_init(&toplevel->client_dbus_annotations); + wl_list_init(&toplevel->surface_dbus_annotations); wl_signal_init(&toplevel->events.request_maximize); wl_signal_init(&toplevel->events.request_minimize); @@ -637,6 +771,20 @@ static void toplevel_send_details_to_toplevel_resource( toplevel_resource_send_parent(resource, toplevel->parent); + if (wl_resource_get_version(resource) >= + ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_CLIENT_DBUS_ANNOTATION_SINCE_VERSION) { + struct wlr_foreign_toplevel_handle_v1_dbus_annotation *annot; + wl_list_for_each(annot, &toplevel->client_dbus_annotations, link) { + zwlr_foreign_toplevel_handle_v1_send_surface_dbus_annotation( + resource, annot->interface, annot->bus_name, annot->object_path); + } + + wl_list_for_each(annot, &toplevel->surface_dbus_annotations, link) { + zwlr_foreign_toplevel_handle_v1_send_surface_dbus_annotation( + resource, annot->interface, annot->bus_name, annot->object_path); + } + } + zwlr_foreign_toplevel_handle_v1_send_done(resource); }