Merge branch 'feature/wlr_foreign_new_states' into 'master'

Draft: wlr-foreign-toplevel: add 4 new states

See merge request wlroots/wlroots!4942
This commit is contained in:
Consolatis 2026-01-22 20:30:14 +01:00
commit 3c0662933b
3 changed files with 239 additions and 13 deletions

View file

@ -7,7 +7,7 @@
#include <wlr/util/log.h>
#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) {
@ -541,6 +658,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);