From fe8fe42ea9e91955e357365bdb56e3db8024f79c Mon Sep 17 00:00:00 2001 From: Marco Martin Date: Thu, 21 Dec 2023 15:43:29 +0100 Subject: [PATCH] wayland: Add support for layer_surface_v1.set_exclusive_edge This can be used to disambiguate the exclusive edge when the anchors are on a corner (so there would be 2 candidates) it's quite quick and dirty mostly to understand if we do want to push for something along the lines (it should at least do a protocol error when the requested edge is not within the anchors) --- src/wayland/layershell_v1.cpp | 40 ++++++++++++++++++- .../protocols/wlr-layer-shell-unstable-v1.xml | 21 +++++++++- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/src/wayland/layershell_v1.cpp b/src/wayland/layershell_v1.cpp index 34f934cc63..bff7bb7cf7 100644 --- a/src/wayland/layershell_v1.cpp +++ b/src/wayland/layershell_v1.cpp @@ -18,7 +18,7 @@ namespace KWin { -static const int s_version = 3; +static const int s_version = 5; class LayerShellV1InterfacePrivate : public QtWaylandServer::zwlr_layer_shell_v1 { @@ -45,6 +45,7 @@ struct LayerSurfaceV1Commit std::optional margins; std::optional desiredSize; std::optional exclusiveZone; + std::optional exclusiveEdge; std::optional acknowledgedConfigure; std::optional acceptsFocus; }; @@ -57,6 +58,7 @@ struct LayerSurfaceV1State QMargins margins; QSize desiredSize = QSize(0, 0); int exclusiveZone = 0; + Qt::Edge exclusiveEdge = Qt::Edge(); bool acceptsFocus = false; bool configured = false; bool closed = false; @@ -82,6 +84,7 @@ protected: void zwlr_layer_surface_v1_destroy_resource(Resource *resource) override; void zwlr_layer_surface_v1_set_size(Resource *resource, uint32_t width, uint32_t height) override; void zwlr_layer_surface_v1_set_anchor(Resource *resource, uint32_t anchor) override; + void zwlr_layer_surface_v1_set_exclusive_edge(Resource *resource, uint32_t edge) override; void zwlr_layer_surface_v1_set_exclusive_zone(Resource *resource, int32_t zone) override; void zwlr_layer_surface_v1_set_margin(Resource *resource, int32_t top, int32_t right, int32_t bottom, int32_t left) override; void zwlr_layer_surface_v1_set_keyboard_interactivity(Resource *resource, uint32_t keyboard_interactivity) override; @@ -203,6 +206,23 @@ void LayerSurfaceV1InterfacePrivate::zwlr_layer_surface_v1_set_anchor(Resource * } } +void LayerSurfaceV1InterfacePrivate::zwlr_layer_surface_v1_set_exclusive_edge(Resource *resource, uint32_t edge) +{ + if (!edge) { + pending.exclusiveEdge = Qt::Edge(); + } else if (edge == anchor_top) { + pending.exclusiveEdge = Qt::TopEdge; + } else if (edge == anchor_right) { + pending.exclusiveEdge = Qt::RightEdge; + } else if (edge == anchor_bottom) { + pending.exclusiveEdge = Qt::BottomEdge; + } else if (edge == anchor_left) { + pending.exclusiveEdge = Qt::LeftEdge; + } else { + wl_resource_post_error(resource->handle, error_invalid_exclusive_edge, "Invalid exclusive edge: %d", edge); + } +} + void LayerSurfaceV1InterfacePrivate::zwlr_layer_surface_v1_set_exclusive_zone(Resource *, int32_t zone) { pending.exclusiveZone = zone; @@ -302,6 +322,15 @@ void LayerSurfaceV1InterfacePrivate::apply(LayerSurfaceV1Commit *commit) } } + if (commit->exclusiveEdge.has_value() || commit->anchor.has_value()) { + const quint32 exclusiveEdge = commit->exclusiveEdge.value_or(state.exclusiveEdge); + const quint32 anchor = commit->anchor.value_or(state.anchor); + if (exclusiveEdge && !(exclusiveEdge & anchor)) { + wl_resource_post_error(resource()->handle, error_invalid_exclusive_edge, "Exclusive edge is not of the anchors"); + return; + } + } + // detect reset if (!surface->isMapped() && state.firstBufferAttached) { state = LayerSurfaceV1State(); @@ -333,6 +362,10 @@ void LayerSurfaceV1InterfacePrivate::apply(LayerSurfaceV1Commit *commit) if (commit->exclusiveZone.has_value()) { state.exclusiveZone = commit->exclusiveZone.value(); } + if (commit->exclusiveEdge.has_value()) { + state.exclusiveEdge = commit->exclusiveEdge.value(); + } + if (commit->acceptsFocus.has_value()) { state.acceptsFocus = commit->acceptsFocus.value(); } @@ -449,6 +482,11 @@ Qt::Edge LayerSurfaceV1Interface::exclusiveEdge() const if (exclusiveZone() <= 0) { return Qt::Edge(); } + + if (d->state.exclusiveEdge) { + return d->state.exclusiveEdge; + } + if (anchor() == (Qt::LeftEdge | Qt::TopEdge | Qt::RightEdge) || anchor() == Qt::TopEdge) { return Qt::TopEdge; } diff --git a/src/wayland/protocols/wlr-layer-shell-unstable-v1.xml b/src/wayland/protocols/wlr-layer-shell-unstable-v1.xml index 0736a45e26..2d464090e3 100644 --- a/src/wayland/protocols/wlr-layer-shell-unstable-v1.xml +++ b/src/wayland/protocols/wlr-layer-shell-unstable-v1.xml @@ -25,7 +25,7 @@ THIS SOFTWARE. - + Clients can use this interface to assign the surface_layer role to wl_surfaces. Such surfaces are assigned to a "layer" of the output and @@ -100,7 +100,7 @@ - + An interface that may be implemented by a wl_surface, for surfaces that are designed to be rendered as a layer of a stacked desktop-like @@ -302,6 +302,7 @@ + @@ -321,5 +322,21 @@ + + + + + + Requests an edge for the exclusive zone to apply. The exclusive + edge will be automatically deduced from anchor points when possible, + but when the surface is anchored to a corner, it will be necessary + to set it explicitly to disambiguate, as it is not possible to deduce + which one of the two corner edges should be used. + + The edge must be one the surface is anchored to, otherwise the + invalid_exclusive_edge protocol error will be raised. + + +