From c1a2dd3e27429d729041eaa05cf43810b1d46e6e Mon Sep 17 00:00:00 2001 From: "Andrew J. Hesford" Date: Mon, 22 Jan 2024 15:38:14 -0500 Subject: [PATCH 1/3] view, xdg: notify clients when tiling windows --- include/view.h | 1 + src/view.c | 14 ++++++++++++++ src/xdg.c | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/include/view.h b/include/view.h index 866b6928..a568945c 100644 --- a/include/view.h +++ b/include/view.h @@ -94,6 +94,7 @@ struct view_impl { void (*map)(struct view *view); void (*set_activated)(struct view *view, bool activated); void (*set_fullscreen)(struct view *view, bool fullscreen); + void (*set_tiled)(struct view *view); /* * client_request is true if the client unmapped its own * surface; false if we are just minimizing the view. The two diff --git a/src/view.c b/src/view.c index 8a42b304..14379804 100644 --- a/src/view.c +++ b/src/view.c @@ -1051,6 +1051,10 @@ view_set_untiled(struct view *view) view->tiled = VIEW_EDGE_INVALID; view->tiled_region = NULL; zfree(view->tiled_region_evacuate); + + if (view->impl->set_tiled) { + view->impl->set_tiled(view); + } } void @@ -1771,6 +1775,11 @@ view_snap_to_edge(struct view *view, enum view_edge edge, view_set_untiled(view); view_set_output(view, output); view->tiled = edge; + + if (view->impl->set_tiled) { + view->impl->set_tiled(view); + } + view_apply_tiled_geometry(view); } @@ -1804,6 +1813,11 @@ view_snap_to_region(struct view *view, struct region *region, } view_set_untiled(view); view->tiled_region = region; + + if (view->impl->set_tiled) { + view->impl->set_tiled(view); + } + view_apply_region_geometry(view); } diff --git a/src/xdg.c b/src/xdg.c index 666264de..c338ad83 100644 --- a/src/xdg.c +++ b/src/xdg.c @@ -423,6 +423,41 @@ xdg_toplevel_view_set_fullscreen(struct view *view, bool fullscreen) fullscreen); } +static void +xdg_toplevel_view_set_tiled(struct view *view) +{ + enum wlr_edges edge; + + /* + * Edge-snapped view are considered tiled on the snapped edge and those + * perpendicular to it. + */ + switch (view->tiled) { + case VIEW_EDGE_LEFT: + edge = WLR_EDGE_LEFT | WLR_EDGE_TOP | WLR_EDGE_BOTTOM; + break; + case VIEW_EDGE_RIGHT: + edge = WLR_EDGE_RIGHT | WLR_EDGE_TOP | WLR_EDGE_BOTTOM; + break; + case VIEW_EDGE_UP: + edge = WLR_EDGE_TOP | WLR_EDGE_LEFT | WLR_EDGE_RIGHT; + break; + case VIEW_EDGE_DOWN: + edge = WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT; + break; + default: + edge = WLR_EDGE_NONE; + } + + if (view->tiled_region) { + /* Region-snapped views are considered tiled on all edges */ + edge = WLR_EDGE_LEFT | WLR_EDGE_RIGHT | + WLR_EDGE_TOP | WLR_EDGE_BOTTOM; + } + + wlr_xdg_toplevel_set_tiled(xdg_toplevel_from_view(view), edge); +} + static struct view * lookup_view_by_xdg_toplevel(struct server *server, struct wlr_xdg_toplevel *xdg_toplevel) @@ -594,6 +629,7 @@ static const struct view_impl xdg_toplevel_view_impl = { .map = xdg_toplevel_view_map, .set_activated = xdg_toplevel_view_set_activated, .set_fullscreen = xdg_toplevel_view_set_fullscreen, + .set_tiled = xdg_toplevel_view_set_tiled, .unmap = xdg_toplevel_view_unmap, .maximize = xdg_toplevel_view_maximize, .minimize = xdg_toplevel_view_minimize, From 9f51384b6ac73dba404b636f356bf942a772a14d Mon Sep 17 00:00:00 2001 From: "Andrew J. Hesford" Date: Mon, 22 Jan 2024 19:04:16 -0500 Subject: [PATCH 2/3] interactive: reset tiled state when dragging out of snapped position This ensures that client-side decorations (and maybe other client behaviors) behave intuitively during interative moves, but means that drag to snapped position -> drag to maximize -> un-maximize will put the window back to its natural geometry (saved before the first snap) rather than back to the snapped position. This is a change in behavior, but a) simplifies the logic a bit, because the tiled state is always in sync with the window geometry and b) in some sense is "more correct", because the window has been "visually" un-tiled the minute the window starts dragging. Note that maximizing using an action (including the button) a window that has been snapped and then un-maximizing the window will put the window back to the snapped position, as it always has. --- src/interactive.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/interactive.c b/src/interactive.c index b09ba01c..432027a6 100644 --- a/src/interactive.c +++ b/src/interactive.c @@ -69,6 +69,7 @@ interactive_begin(struct view *view, enum input_mode mode, uint32_t edges) geometry.height); view_set_shade(view, false); + view_set_untiled(view); view_restore_to(view, geometry); } else { /* Store natural geometry at start of move */ @@ -201,9 +202,8 @@ interactive_finish(struct view *view) } if (view->server->input_mode == LAB_INPUT_STATE_MOVE) { - /* Reset tiled state if not snapped */ - if (!snap_to_region(view) && !snap_to_edge(view)) { - view_set_untiled(view); + if (!snap_to_region(view)) { + snap_to_edge(view); } } From 3162bbb3c23a077c5c6fdb5f350beab86f6850b8 Mon Sep 17 00:00:00 2001 From: "Andrew J. Hesford" Date: Mon, 22 Jan 2024 22:11:53 -0500 Subject: [PATCH 3/3] xdg: add snapping.notifyClient option to control tiling events --- docs/labwc-config.5.scd | 40 ++++++++++++++++++++++++++++------ docs/rc.xml.all | 3 ++- include/config/rcxml.h | 9 ++++++++ include/view.h | 2 +- src/config/rcxml.c | 13 +++++++++++ src/view.c | 26 +++++++++++----------- src/xdg.c | 48 +++++++++++++++++++++++++---------------- 7 files changed, 100 insertions(+), 41 deletions(-) diff --git a/docs/labwc-config.5.scd b/docs/labwc-config.5.scd index 1e0a553e..13751813 100644 --- a/docs/labwc-config.5.scd +++ b/docs/labwc-config.5.scd @@ -236,16 +236,44 @@ this is for compatibility with Openbox. ## WINDOW SNAPPING -The following two options relate to triggering window actions when moving -windows using the mouse. +Windows may be "snapped" to an edge or user-defined region of an output when +activated with SnapToEdge actions or, optionally, by dragging windows to the +edges of an output. Edge snapping causes a window to occupy half of its output, +extending outward from the snapped edge. ** - The distance in pixels from the edge of an output for window Move - operations to trigger SnapToEdge. A range of 0 disables window snapping. - Default is 1. + If an interactive move ends with the cursor a maximum distance *range*, + (in pixels) from the edge of an output, the move will trigger a + SnapToEdge action for that edge. A *range* of 0 disables snapping via + interactive moves. Default is 1. ** [yes|no] - Maximize window if Move operation ends on the top edge. Default is yes. + If *yes*, an interactive move that snaps a window to the top edge will + maximize the window. If *no*, snapping will behave as it does with other + edges, causing the window to occupy the top half of an output. Default + is yes. + +** [always|region|edge|never] + Snapping windows can trigger corresponding tiling events for native + Wayland clients. Clients may use these events to alter their rendering + based on knowledge that some edges of the view are confined to edges of + a snapping region or output. For example, rounded corners may become + square when tiled, or media players may letter-box or pillar-box video + rather than imposing rigid aspect ratios on windows that will violate + the constraints of window snapping. + + - When *always* is specified, any window that is snapped to either an + output edge or a user-defined region will receive a tiling event. + + - When *region* is specified, only windows snapped to a user-defined + region will receive an event. + + - When *edge* is specified, only windows snapped to an output edge will + receive an event. + + - When *never* is specified, tiling events will never be triggered. + + The default is "always". ## REGIONS diff --git a/docs/rc.xml.all b/docs/rc.xml.all index 7f59a1d3..423bcb74 100644 --- a/docs/rc.xml.all +++ b/docs/rc.xml.all @@ -78,10 +78,11 @@ no - + 1 yes + always