From 6696284c40b1bc6b7e69acbb3d21d0ca193d3763 Mon Sep 17 00:00:00 2001 From: Consolatis <40171-Consolatis@users.noreply.gitlab.freedesktop.org> Date: Sat, 14 Dec 2024 04:06:16 +0100 Subject: [PATCH] wlr-foreign-toplevel: add 4 new states - always on top - visible on all workspaces - rolled up - urgent --- .../wlr_foreign_toplevel_management_v1.h | 38 +++++- ...oreign-toplevel-management-unstable-v1.xml | 94 ++++++++++++-- types/wlr_foreign_toplevel_management_v1.c | 122 +++++++++++++++++- 3 files changed, 240 insertions(+), 14 deletions(-) diff --git a/include/wlr/types/wlr_foreign_toplevel_management_v1.h b/include/wlr/types/wlr_foreign_toplevel_management_v1.h index d21c5fc70..6c3b99aa5 100644 --- a/include/wlr/types/wlr_foreign_toplevel_management_v1.h +++ b/include/wlr/types/wlr_foreign_toplevel_management_v1.h @@ -30,10 +30,14 @@ struct wlr_foreign_toplevel_manager_v1 { }; enum wlr_foreign_toplevel_handle_v1_state { - WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MAXIMIZED = (1 << 0), - WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MINIMIZED = (1 << 1), - WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ACTIVATED = (1 << 2), - WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN = (1 << 3), + WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MAXIMIZED = (1 << 0), + WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MINIMIZED = (1 << 1), + WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ACTIVATED = (1 << 2), + WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN = (1 << 3), + WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ALWAYS_ON_TOP = (1 << 4), + WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ON_ALL_WORKSPACES = (1 << 5), + WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ROLLED_UP = (1 << 6), + WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_URGENT = (1 << 7), }; struct wlr_foreign_toplevel_handle_v1_output { @@ -69,6 +73,9 @@ struct wlr_foreign_toplevel_handle_v1 { // struct wlr_foreign_toplevel_handle_v1_fullscreen_event struct wl_signal request_fullscreen; struct wl_signal request_close; + struct wl_signal request_always_on_top; + struct wl_signal request_on_all_workspaces; + struct wl_signal request_roll_up; // struct wlr_foreign_toplevel_handle_v1_set_rectangle_event struct wl_signal set_rectangle; @@ -99,6 +106,21 @@ struct wlr_foreign_toplevel_handle_v1_fullscreen_event { struct wlr_output *output; }; +struct wlr_foreign_toplevel_handle_v1_always_on_top_event { + struct wlr_foreign_toplevel_handle_v1 *toplevel; + bool always_on_top; +}; + +struct wlr_foreign_toplevel_handle_v1_on_all_workspaces_event { + struct wlr_foreign_toplevel_handle_v1 *toplevel; + bool on_all_workspaces; +}; + +struct wlr_foreign_toplevel_handle_v1_roll_up_event { + struct wlr_foreign_toplevel_handle_v1 *toplevel; + bool roll_up; +}; + struct wlr_foreign_toplevel_handle_v1_set_rectangle_event { struct wlr_foreign_toplevel_handle_v1 *toplevel; struct wlr_surface *surface; @@ -139,6 +161,14 @@ void wlr_foreign_toplevel_handle_v1_set_activated( struct wlr_foreign_toplevel_handle_v1 *toplevel, bool activated); void wlr_foreign_toplevel_handle_v1_set_fullscreen( struct wlr_foreign_toplevel_handle_v1* toplevel, bool fullscreen); +void wlr_foreign_toplevel_handle_v1_set_always_on_top( + struct wlr_foreign_toplevel_handle_v1* toplevel, bool always_on_top); +void wlr_foreign_toplevel_handle_v1_set_on_all_workspaces( + struct wlr_foreign_toplevel_handle_v1* toplevel, bool on_all_workspaces); +void wlr_foreign_toplevel_handle_v1_set_rolled_up( + struct wlr_foreign_toplevel_handle_v1* toplevel, bool rolled_up); +void wlr_foreign_toplevel_handle_v1_set_urgent( + struct wlr_foreign_toplevel_handle_v1* toplevel, bool urgent); /** * Set the parent of a toplevel. If the parent changed from its previous diff --git a/protocol/wlr-foreign-toplevel-management-unstable-v1.xml b/protocol/wlr-foreign-toplevel-management-unstable-v1.xml index 108133715..49f30ccaa 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. @@ -146,14 +146,45 @@ - The different states that a toplevel can have. These have the same meaning - as the states with the same names defined in xdg-toplevel + The different states that a toplevel can have. + A compositor may not support all states in which case they will never be set. - - - - + + + + + + + The exact policy in regards to what "stacking order" means is compositor policy. + In a auto tiling compositor for example this could mean that toplevels with this + state set are always positioned in the most prominent tile. In a more traditional + stacking compositor this usually means that applicatios with this state set are + rendered top-most on a given workspace. In X11 terms this is known as 'above'. + + + + + Toplevels with this state set should show up on all workspaces. What exactly this + means is compositor policy. For example in a tag based compositor a toplevel with + this state set could show up on any tag. In X11 terms this is known as 'sticky'. + + + + + Toplevel with this state set are "rolled up" so that only the titlebar is visible. + In X11 terms this is known as 'shade'. + + + + + Toplevel with this state set are requesting attention. This state can only be set + by the compositor. The circumstances when this state is enabled and disabled is + compositor policy. A compositor may for example use the xdg-activation protocol + to treat activation requests with invalid tokens as a request for urgency and + disable this state again once the toplevel receives focus. + + @@ -266,5 +297,50 @@ + + + + + + Requests that the toplevel be set to always on top. + If the state actually changes, this will be indicated by the state event. + + + + + + Requests that the toplevel stops being set to always on top. + If the state actually changes, this will be indicated by the state event. + + + + + + Requests that the toplevel be shown on all workspaces. + If the state actually changes, this will be indicated by the state event. + + + + + + Requests that the toplevel is not shown on all workspaces. + If the state actually changes, this will be indicated by the state event. + + + + + + Requests that the toplevel be rolled up (shaded). + If the state actually changes, this will be indicated by the state event. + + + + + + Requests that the toplevel be rolled down (unshaded). + If the state actually changes, this will be indicated by the state event. + + + diff --git a/types/wlr_foreign_toplevel_management_v1.c b/types/wlr_foreign_toplevel_management_v1.c index f06fdb7b7..0e0c57285 100644 --- a/types/wlr_foreign_toplevel_management_v1.c +++ b/types/wlr_foreign_toplevel_management_v1.c @@ -7,7 +7,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 #define FOREIGN_TOPLEVEL_HANDLE_V1_STATE_COUNT 32 @@ -70,6 +70,79 @@ static void foreign_toplevel_handle_unset_minimized(struct wl_client *client, toplevel_send_minimized_event(resource, false); } +static void toplevel_send_always_on_top_event(struct wl_resource *resource, + bool state) { + struct wlr_foreign_toplevel_handle_v1 *toplevel = + toplevel_handle_from_resource(resource); + if (!toplevel) { + return; + } + + struct wlr_foreign_toplevel_handle_v1_always_on_top_event event = { + .toplevel = toplevel, + .always_on_top = state, + }; + wl_signal_emit_mutable(&toplevel->events.request_always_on_top, &event); +} + +static void foreign_toplevel_handle_set_always_on_top(struct wl_client *client, + struct wl_resource *resource) { + toplevel_send_always_on_top_event(resource, true); +} + +static void foreign_toplevel_handle_unset_always_on_top(struct wl_client *client, + struct wl_resource *resource) { + toplevel_send_always_on_top_event(resource, false); +} +static void toplevel_send_on_all_workspaces_event(struct wl_resource *resource, + bool state) { + struct wlr_foreign_toplevel_handle_v1 *toplevel = + toplevel_handle_from_resource(resource); + if (!toplevel) { + return; + } + + struct wlr_foreign_toplevel_handle_v1_on_all_workspaces_event event = { + .toplevel = toplevel, + .on_all_workspaces = state, + }; + wl_signal_emit_mutable(&toplevel->events.request_on_all_workspaces, &event); +} + +static void foreign_toplevel_handle_set_on_all_workspaces(struct wl_client *client, + struct wl_resource *resource) { + toplevel_send_on_all_workspaces_event(resource, true); +} + +static void foreign_toplevel_handle_unset_on_all_workspaces(struct wl_client *client, + struct wl_resource *resource) { + toplevel_send_on_all_workspaces_event(resource, false); +} +static void toplevel_send_roll_up_event(struct wl_resource *resource, + bool state) { + struct wlr_foreign_toplevel_handle_v1 *toplevel = + toplevel_handle_from_resource(resource); + if (!toplevel) { + return; + } + + struct wlr_foreign_toplevel_handle_v1_roll_up_event event = { + .toplevel = toplevel, + .roll_up = state, + }; + wl_signal_emit_mutable(&toplevel->events.request_roll_up, &event); +} + +static void foreign_toplevel_handle_set_roll_up(struct wl_client *client, + struct wl_resource *resource) { + toplevel_send_roll_up_event(resource, true); +} + +static void foreign_toplevel_handle_unset_roll_up(struct wl_client *client, + struct wl_resource *resource) { + toplevel_send_roll_up_event(resource, false); +} + static void toplevel_send_fullscreen_event(struct wl_resource *resource, bool state, struct wl_resource *output_resource) { struct wlr_foreign_toplevel_handle_v1 *toplevel = @@ -172,6 +245,12 @@ static const struct zwlr_foreign_toplevel_handle_v1_interface toplevel_handle_im .destroy = foreign_toplevel_handle_destroy, .set_fullscreen = foreign_toplevel_handle_set_fullscreen, .unset_fullscreen = foreign_toplevel_handle_unset_fullscreen, + .set_always_on_top = foreign_toplevel_handle_set_always_on_top, + .unset_always_on_top = foreign_toplevel_handle_unset_always_on_top, + .set_visible_on_all_workspaces = foreign_toplevel_handle_set_on_all_workspaces, + .unset_visible_on_all_workspaces = foreign_toplevel_handle_unset_on_all_workspaces, + .set_rolled_up = foreign_toplevel_handle_set_roll_up, + .unset_rolled_up = foreign_toplevel_handle_unset_roll_up, }; static void toplevel_idle_send_done(void *data) { @@ -355,6 +434,22 @@ static void fill_array_from_toplevel_state(struct wl_array *states, && (state & WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN)) { data[nstates++] = ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN; } + if (version >= ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ALWAYS_ON_TOP_SINCE_VERSION + && (state & WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ALWAYS_ON_TOP)) { + data[nstates++] = ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ALWAYS_ON_TOP; + } + if (version >= ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ON_ALL_WORKSPACES_SINCE_VERSION + && (state & WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ON_ALL_WORKSPACES)) { + data[nstates++] = ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ON_ALL_WORKSPACES; + } + if (version >= ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ROLLED_UP_SINCE_VERSION + && (state & WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ROLLED_UP)) { + data[nstates++] = ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ROLLED_UP; + } + if (version >= ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_URGENT_SINCE_VERSION + && (state & WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_URGENT)) { + data[nstates++] = ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_URGENT; + } assert(nstates <= FOREIGN_TOPLEVEL_HANDLE_V1_STATE_COUNT); *states = (struct wl_array){ @@ -409,6 +504,28 @@ void wlr_foreign_toplevel_handle_v1_set_fullscreen( set_state(toplevel, fullscreen, WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN); } +void wlr_foreign_toplevel_handle_v1_set_always_on_top( + struct wlr_foreign_toplevel_handle_v1 *toplevel, bool always_on_top) { + set_state(toplevel, always_on_top, + WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ALWAYS_ON_TOP); +} + +void wlr_foreign_toplevel_handle_v1_set_on_all_workspaces( + struct wlr_foreign_toplevel_handle_v1 *toplevel, bool on_all_workspaces) { + set_state(toplevel, on_all_workspaces, + WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ON_ALL_WORKSPACES); +} + +void wlr_foreign_toplevel_handle_v1_set_rolled_up( + struct wlr_foreign_toplevel_handle_v1 *toplevel, bool rolled_up) { + set_state(toplevel, rolled_up, WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ROLLED_UP); +} + +void wlr_foreign_toplevel_handle_v1_set_urgent( + struct wlr_foreign_toplevel_handle_v1 *toplevel, bool urgent) { + set_state(toplevel, urgent, WLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_URGENT); +} + static void toplevel_resource_send_parent( struct wl_resource *toplevel_resource, struct wlr_foreign_toplevel_handle_v1 *parent) { @@ -540,6 +657,9 @@ wlr_foreign_toplevel_handle_v1_create( wl_signal_init(&toplevel->events.request_activate); wl_signal_init(&toplevel->events.request_fullscreen); wl_signal_init(&toplevel->events.request_close); + wl_signal_init(&toplevel->events.request_always_on_top); + wl_signal_init(&toplevel->events.request_on_all_workspaces); + wl_signal_init(&toplevel->events.request_roll_up); wl_signal_init(&toplevel->events.set_rectangle); wl_signal_init(&toplevel->events.destroy);