mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-15 22:05:24 -05:00
wayland+input: add support for toplevel edge constraints
Edge constraints are new (not yet available in a wayland-protocols
release) toplevel states, acting as a complement to the existing tiled
states.
Tiled tells us we shouldn't draw shadows etc *outside our window
geometry*.
Constrained tells us the window cannot be resized in the constrained
direction.
This patch does a couple of things:
* Recognize the new states when debug logging
* Change is_top_left() etc to look at the new constrained state
instead of the tiled state. These functions are used when both
choosing cursor shape, and when determining if/how to resize a
window on a CSD edge click-and-drag.
* Update cursor shape selection to use the default (left_ptr) shape
when on a constrained edge (or corner).
* Update CSD resize triggering, to not trigger a resize when attempted
on a constrained edge (or corner).
See
86750c99ed:
An edge constraint is an complementery state to the tiled state,
meaning that it's not only tiled, but constrained in a way that it
can't resize in that direction.
This typically means that the constrained edge is tiled against a
monitor edge. An example configuration is two windows tiled next
to each other on a single monitor. Together they cover the whole
work area.
The left window would have the following tiled and edge constraint
state:
[ tiled_top, tiled_right, tiled_bottom, tiled_left,
constrained_top, constrained_bottom, constrained_left ]
while the right window would have the following:
[ tiled_top, tiled_right, tiled_bottom, tiled_left,
constrained_top, constrained_bottom, constrained_right ]
This aims to replace and deprecate the
`gtk_surface1.configure_edges` event and the
`gtk_surface1.edge_constraint` enum.
This commit is contained in:
parent
091aa90f1a
commit
23431e3ecf
4 changed files with 114 additions and 30 deletions
|
|
@ -61,6 +61,12 @@
|
|||
|
||||
## Unreleased
|
||||
### Added
|
||||
|
||||
* Support for toplevel edge constraints. When the compositor indicates
|
||||
the toplevel has edge constraints, foot will not allow the window to
|
||||
be resized (via CSDs) in the constrained directions.
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
* UTF-8 error recovery now discards fewer bytes.
|
||||
|
|
@ -83,6 +89,8 @@
|
|||
([#2016][2016]). You can manually set the [old
|
||||
one](https://codeberg.org/dnkl/foot/src/tag/1.21.0/foot.ini#L72), if
|
||||
you prefer it over the new regex.
|
||||
* A tiled window can now be resized in the corners (via CSDs), unless
|
||||
the compositor has indicated the toplevel has edge constraints.
|
||||
|
||||
[2006]: https://codeberg.org/dnkl/foot/issues/2006
|
||||
[2009]: https://codeberg.org/dnkl/foot/issues/2009
|
||||
|
|
|
|||
71
input.c
71
input.c
|
|
@ -2280,7 +2280,7 @@ is_top_left(const struct terminal *term, int x, int y)
|
|||
{
|
||||
int csd_border_size = term->conf->csd.border_width;
|
||||
return (
|
||||
(!term->window->is_tiled_top && !term->window->is_tiled_left) &&
|
||||
(!term->window->is_constrained_top && !term->window->is_constrained_left) &&
|
||||
((term->active_surface == TERM_SURF_BORDER_LEFT && y < 10 * term->scale) ||
|
||||
(term->active_surface == TERM_SURF_BORDER_TOP && x < (10 + csd_border_size) * term->scale)));
|
||||
}
|
||||
|
|
@ -2290,7 +2290,7 @@ is_top_right(const struct terminal *term, int x, int y)
|
|||
{
|
||||
int csd_border_size = term->conf->csd.border_width;
|
||||
return (
|
||||
(!term->window->is_tiled_top && !term->window->is_tiled_right) &&
|
||||
(!term->window->is_constrained_top && !term->window->is_constrained_right) &&
|
||||
((term->active_surface == TERM_SURF_BORDER_RIGHT && y < 10 * term->scale) ||
|
||||
(term->active_surface == TERM_SURF_BORDER_TOP && x > term->width + 1 * csd_border_size * term->scale - 10 * term->scale)));
|
||||
}
|
||||
|
|
@ -2301,7 +2301,7 @@ is_bottom_left(const struct terminal *term, int x, int y)
|
|||
int csd_title_size = term->conf->csd.title_height;
|
||||
int csd_border_size = term->conf->csd.border_width;
|
||||
return (
|
||||
(!term->window->is_tiled_bottom && !term->window->is_tiled_left) &&
|
||||
(!term->window->is_constrained_bottom && !term->window->is_constrained_left) &&
|
||||
((term->active_surface == TERM_SURF_BORDER_LEFT && y > csd_title_size * term->scale + term->height) ||
|
||||
(term->active_surface == TERM_SURF_BORDER_BOTTOM && x < (10 + csd_border_size) * term->scale)));
|
||||
}
|
||||
|
|
@ -2312,7 +2312,7 @@ is_bottom_right(const struct terminal *term, int x, int y)
|
|||
int csd_title_size = term->conf->csd.title_height;
|
||||
int csd_border_size = term->conf->csd.border_width;
|
||||
return (
|
||||
(!term->window->is_tiled_bottom && !term->window->is_tiled_right) &&
|
||||
(!term->window->is_constrained_bottom && !term->window->is_constrained_right) &&
|
||||
((term->active_surface == TERM_SURF_BORDER_RIGHT && y > csd_title_size * term->scale + term->height) ||
|
||||
(term->active_surface == TERM_SURF_BORDER_BOTTOM && x > term->width + 1 * csd_border_size * term->scale - 10 * term->scale)));
|
||||
}
|
||||
|
|
@ -2324,10 +2324,23 @@ xcursor_for_csd_border(struct terminal *term, int x, int y)
|
|||
else if (is_top_right(term, x, y)) return CURSOR_SHAPE_TOP_RIGHT_CORNER;
|
||||
else if (is_bottom_left(term, x, y)) return CURSOR_SHAPE_BOTTOM_LEFT_CORNER;
|
||||
else if (is_bottom_right(term, x, y)) return CURSOR_SHAPE_BOTTOM_RIGHT_CORNER;
|
||||
else if (term->active_surface == TERM_SURF_BORDER_LEFT) return CURSOR_SHAPE_LEFT_SIDE;
|
||||
else if (term->active_surface == TERM_SURF_BORDER_RIGHT) return CURSOR_SHAPE_RIGHT_SIDE;
|
||||
else if (term->active_surface == TERM_SURF_BORDER_TOP) return CURSOR_SHAPE_TOP_SIDE;
|
||||
else if (term->active_surface == TERM_SURF_BORDER_BOTTOM) return CURSOR_SHAPE_BOTTOM_SIDE;
|
||||
|
||||
else if (term->active_surface == TERM_SURF_BORDER_LEFT)
|
||||
return !term->window->is_constrained_left
|
||||
? CURSOR_SHAPE_LEFT_SIDE : CURSOR_SHAPE_LEFT_PTR;
|
||||
|
||||
else if (term->active_surface == TERM_SURF_BORDER_RIGHT)
|
||||
return !term->window->is_constrained_right
|
||||
? CURSOR_SHAPE_RIGHT_SIDE : CURSOR_SHAPE_LEFT_PTR;
|
||||
|
||||
else if (term->active_surface == TERM_SURF_BORDER_TOP)
|
||||
return !term->window->is_constrained_top
|
||||
? CURSOR_SHAPE_TOP_SIDE : CURSOR_SHAPE_LEFT_PTR;
|
||||
|
||||
else if (term->active_surface == TERM_SURF_BORDER_BOTTOM)
|
||||
return !term->window->is_constrained_bottom
|
||||
? CURSOR_SHAPE_BOTTOM_SIDE : CURSOR_SHAPE_LEFT_PTR;
|
||||
|
||||
else {
|
||||
BUG("Unreachable");
|
||||
return CURSOR_SHAPE_NONE;
|
||||
|
|
@ -3095,15 +3108,8 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
|
|||
case TERM_SURF_BORDER_RIGHT:
|
||||
case TERM_SURF_BORDER_TOP:
|
||||
case TERM_SURF_BORDER_BOTTOM: {
|
||||
static const enum xdg_toplevel_resize_edge map[] = {
|
||||
[TERM_SURF_BORDER_LEFT] = XDG_TOPLEVEL_RESIZE_EDGE_LEFT,
|
||||
[TERM_SURF_BORDER_RIGHT] = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT,
|
||||
[TERM_SURF_BORDER_TOP] = XDG_TOPLEVEL_RESIZE_EDGE_TOP,
|
||||
[TERM_SURF_BORDER_BOTTOM] = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM,
|
||||
};
|
||||
|
||||
if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED) {
|
||||
enum xdg_toplevel_resize_edge resize_type;
|
||||
enum xdg_toplevel_resize_edge resize_type = XDG_TOPLEVEL_RESIZE_EDGE_NONE;
|
||||
|
||||
int x = seat->mouse.x;
|
||||
int y = seat->mouse.y;
|
||||
|
|
@ -3116,11 +3122,36 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
|
|||
resize_type = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT;
|
||||
else if (is_bottom_right(term, x, y))
|
||||
resize_type = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT;
|
||||
else
|
||||
resize_type = map[term->active_surface];
|
||||
else {
|
||||
if (term->active_surface == TERM_SURF_BORDER_LEFT &&
|
||||
!term->window->is_constrained_left)
|
||||
{
|
||||
resize_type = XDG_TOPLEVEL_RESIZE_EDGE_LEFT;
|
||||
}
|
||||
|
||||
xdg_toplevel_resize(
|
||||
term->window->xdg_toplevel, seat->wl_seat, serial, resize_type);
|
||||
else if (term->active_surface == TERM_SURF_BORDER_RIGHT &&
|
||||
!term->window->is_constrained_right)
|
||||
{
|
||||
resize_type = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT;
|
||||
}
|
||||
|
||||
else if (term->active_surface == TERM_SURF_BORDER_TOP &&
|
||||
!term->window->is_constrained_top)
|
||||
{
|
||||
resize_type = XDG_TOPLEVEL_RESIZE_EDGE_TOP;
|
||||
}
|
||||
|
||||
else if (term->active_surface == TERM_SURF_BORDER_BOTTOM &&
|
||||
!term->window->is_constrained_bottom)
|
||||
{
|
||||
resize_type = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM;
|
||||
}
|
||||
}
|
||||
|
||||
if (resize_type != XDG_TOPLEVEL_RESIZE_EDGE_NONE) {
|
||||
xdg_toplevel_resize(
|
||||
term->window->xdg_toplevel, seat->wl_seat, serial, resize_type);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
52
wayland.c
52
wayland.c
|
|
@ -852,6 +852,10 @@ xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel,
|
|||
bool is_tiled_bottom = false;
|
||||
bool is_tiled_left = false;
|
||||
bool is_tiled_right = false;
|
||||
bool is_constrained_top = false;
|
||||
bool is_constrained_bottom = false;
|
||||
bool is_constrained_left = false;
|
||||
bool is_constrained_right = false;
|
||||
bool is_suspended UNUSED = false;
|
||||
|
||||
#if defined(LOG_ENABLE_DBG) && LOG_ENABLE_DBG
|
||||
|
|
@ -869,6 +873,12 @@ xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel,
|
|||
[XDG_TOPLEVEL_STATE_TILED_BOTTOM] = "tiled:bottom",
|
||||
#if defined(XDG_TOPLEVEL_STATE_SUSPENDED_SINCE_VERSION) /* wayland-protocols >= 1.32 */
|
||||
[XDG_TOPLEVEL_STATE_SUSPENDED] = "suspended",
|
||||
#endif
|
||||
#if defined(XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT_SINCE_VERSION)
|
||||
[XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT] = "constrained:left",
|
||||
[XDG_TOPLEVEL_STATE_CONSTRAINED_RIGHT] = "constrained:right",
|
||||
[XDG_TOPLEVEL_STATE_CONSTRAINED_TOP] = "constrained:top",
|
||||
[XDG_TOPLEVEL_STATE_CONSTRAINED_BOTTOM] = "constrained:bottom",
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
|
@ -889,10 +899,10 @@ xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel,
|
|||
case XDG_TOPLEVEL_STATE_SUSPENDED: is_suspended = true; break;
|
||||
#endif
|
||||
#if defined(XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT_SINCE_VERSION)
|
||||
case XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT: is_tiled_left = true; break;
|
||||
case XDG_TOPLEVEL_STATE_CONSTRAINED_RIGHT: is_tiled_right = true; break;
|
||||
case XDG_TOPLEVEL_STATE_CONSTRAINED_TOP: is_tiled_top = true; break;
|
||||
case XDG_TOPLEVEL_STATE_CONSTRAINED_BOTTOM: is_tiled_bottom = true; break;
|
||||
case XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT: is_constrained_left = true; break;
|
||||
case XDG_TOPLEVEL_STATE_CONSTRAINED_RIGHT: is_constrained_right = true; break;
|
||||
case XDG_TOPLEVEL_STATE_CONSTRAINED_TOP: is_constrained_top = true; break;
|
||||
case XDG_TOPLEVEL_STATE_CONSTRAINED_BOTTOM: is_constrained_bottom = true; break;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -933,6 +943,10 @@ xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel,
|
|||
win->configure.is_tiled_bottom = is_tiled_bottom;
|
||||
win->configure.is_tiled_left = is_tiled_left;
|
||||
win->configure.is_tiled_right = is_tiled_right;
|
||||
win->configure.is_constrained_top = is_constrained_top;
|
||||
win->configure.is_constrained_bottom = is_constrained_bottom;
|
||||
win->configure.is_constrained_left = is_constrained_left;
|
||||
win->configure.is_constrained_right = is_constrained_right;
|
||||
win->configure.width = width;
|
||||
win->configure.height = height;
|
||||
}
|
||||
|
|
@ -1056,14 +1070,22 @@ xdg_surface_configure(void *data, struct xdg_surface *xdg_surface,
|
|||
win->is_maximized = win->configure.is_maximized;
|
||||
win->is_fullscreen = win->configure.is_fullscreen;
|
||||
win->is_resizing = win->configure.is_resizing;
|
||||
|
||||
win->is_tiled_top = win->configure.is_tiled_top;
|
||||
win->is_tiled_bottom = win->configure.is_tiled_bottom;
|
||||
win->is_tiled_left = win->configure.is_tiled_left;
|
||||
win->is_tiled_right = win->configure.is_tiled_right;
|
||||
|
||||
win->is_constrained_top = win->configure.is_constrained_top;
|
||||
win->is_constrained_bottom = win->configure.is_constrained_bottom;
|
||||
win->is_constrained_left = win->configure.is_constrained_left;
|
||||
win->is_constrained_right = win->configure.is_constrained_right;
|
||||
|
||||
win->is_tiled = (win->is_tiled_top ||
|
||||
win->is_tiled_bottom ||
|
||||
win->is_tiled_left ||
|
||||
win->is_tiled_right);
|
||||
|
||||
win->csd_mode = win->configure.csd_mode;
|
||||
|
||||
bool enable_csd = win->csd_mode == CSD_YES && !win->is_fullscreen;
|
||||
|
|
@ -1239,13 +1261,23 @@ handle_global(void *data, struct wl_registry *registry,
|
|||
return;
|
||||
|
||||
/*
|
||||
* We *require* version 1, but _can_ use version 5. Version 2
|
||||
* adds 'tiled' window states. We use that information to
|
||||
* restore the window size when window is un-tiled. Version 5
|
||||
* adds 'wm_capabilities'. We use that information to draw
|
||||
* window decorations.
|
||||
* We *require* version 1, but _can_ use version 2, 5 or 7, if
|
||||
* available.
|
||||
*
|
||||
* Version 2 adds 'tiled' window states. We use this
|
||||
* information to restore the window size when window is
|
||||
* un-tiled.
|
||||
*
|
||||
* Version 5 adds 'wm_capabilities'. We use this information
|
||||
* to draw window decorations.
|
||||
*
|
||||
* Version 7 adds 'constrained' window states. We use this
|
||||
* information to determine whether to allow window resize
|
||||
* (via CSDs) or not.
|
||||
*/
|
||||
#if defined(XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION)
|
||||
#if defined(XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT_SINCE_VERSION)
|
||||
const uint32_t preferred = XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT_SINCE_VERSION;
|
||||
#elif defined(XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION)
|
||||
const uint32_t preferred = XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION;
|
||||
#elif defined(XDG_TOPLEVEL_STATE_TILED_LEFT_SINCE_VERSION)
|
||||
const uint32_t preferred = XDG_TOPLEVEL_STATE_TILED_LEFT_SINCE_VERSION;
|
||||
|
|
|
|||
13
wayland.h
13
wayland.h
|
|
@ -402,6 +402,12 @@ struct wl_window {
|
|||
bool is_tiled_left;
|
||||
bool is_tiled_right;
|
||||
bool is_tiled; /* At least one of is_tiled_{top,bottom,left,right} is true */
|
||||
|
||||
bool is_constrained_top;
|
||||
bool is_constrained_bottom;
|
||||
bool is_constrained_left;
|
||||
bool is_constrained_right;
|
||||
|
||||
struct {
|
||||
int width;
|
||||
int height;
|
||||
|
|
@ -409,10 +415,17 @@ struct wl_window {
|
|||
bool is_fullscreen:1;
|
||||
bool is_maximized:1;
|
||||
bool is_resizing:1;
|
||||
|
||||
bool is_tiled_top:1;
|
||||
bool is_tiled_bottom:1;
|
||||
bool is_tiled_left:1;
|
||||
bool is_tiled_right:1;
|
||||
|
||||
bool is_constrained_top:1;
|
||||
bool is_constrained_bottom:1;
|
||||
bool is_constrained_left:1;
|
||||
bool is_constrained_right:1;
|
||||
|
||||
enum csd_mode csd_mode;
|
||||
} configure;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue