From 47f097e09b9cf426867f2f2f0cf14096d3bade8c Mon Sep 17 00:00:00 2001 From: emersion Date: Sun, 27 May 2018 13:16:32 +0100 Subject: [PATCH] xdg-shell: add wlr_xdg_toplevel_set_tiled --- include/wlr/types/wlr_xdg_shell.h | 9 +++++ types/xdg_shell/wlr_xdg_shell.c | 2 +- types/xdg_shell/wlr_xdg_toplevel.c | 62 +++++++++++++++++++++++++++--- 3 files changed, 67 insertions(+), 6 deletions(-) diff --git a/include/wlr/types/wlr_xdg_shell.h b/include/wlr/types/wlr_xdg_shell.h index 22008563..11709c75 100644 --- a/include/wlr/types/wlr_xdg_shell.h +++ b/include/wlr/types/wlr_xdg_shell.h @@ -86,6 +86,7 @@ enum wlr_xdg_surface_role { struct wlr_xdg_toplevel_state { bool maximized, fullscreen, resizing, activated; + uint32_t tiled; // enum wlr_edges uint32_t width, height; uint32_t max_width, max_height; uint32_t min_width, min_height; @@ -246,6 +247,14 @@ uint32_t wlr_xdg_toplevel_set_fullscreen(struct wlr_xdg_surface *surface, uint32_t wlr_xdg_toplevel_set_resizing(struct wlr_xdg_surface *surface, bool resizing); +/** + * Request that this toplevel surface consider itself in a tiled layout and some + * edges are adjacent to another part of the tiling grid. `tiled_edges` is a + * bitfield of `enum wlr_edges`. Returns the associated configure serial. + */ +uint32_t wlr_xdg_toplevel_set_tiled(struct wlr_xdg_surface *surface, + uint32_t tiled_edges); + /** * Request that this xdg surface closes. */ diff --git a/types/xdg_shell/wlr_xdg_shell.c b/types/xdg_shell/wlr_xdg_shell.c index 9d171746..43b28ff0 100644 --- a/types/xdg_shell/wlr_xdg_shell.c +++ b/types/xdg_shell/wlr_xdg_shell.c @@ -3,7 +3,7 @@ #include "types/wlr_xdg_shell.h" #include "util/signal.h" -#define WM_BASE_VERSION 1 +#define WM_BASE_VERSION 2 static const struct xdg_wm_base_interface xdg_shell_impl; diff --git a/types/xdg_shell/wlr_xdg_toplevel.c b/types/xdg_shell/wlr_xdg_toplevel.c index 387897d9..5968c835 100644 --- a/types/xdg_shell/wlr_xdg_toplevel.c +++ b/types/xdg_shell/wlr_xdg_toplevel.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "types/wlr_xdg_shell.h" #include "util/signal.h" @@ -20,6 +21,8 @@ void handle_xdg_toplevel_ack_configure( configure->toplevel_state->resizing; surface->toplevel->current.activated = configure->toplevel_state->activated; + surface->toplevel->current.tiled = + configure->toplevel_state->tiled; } bool compare_xdg_surface_toplevel_state(struct wlr_xdg_toplevel *state) { @@ -58,6 +61,9 @@ bool compare_xdg_surface_toplevel_state(struct wlr_xdg_toplevel *state) { if (state->server_pending.resizing != configured.state.resizing) { return false; } + if (state->server_pending.tiled != configured.state.tiled) { + return false; + } if (state->server_pending.width == configured.width && state->server_pending.height == configured.height) { @@ -83,11 +89,10 @@ void send_xdg_toplevel_configure(struct wlr_xdg_surface *surface, } *configure->toplevel_state = surface->toplevel->server_pending; - uint32_t *s; struct wl_array states; wl_array_init(&states); if (surface->toplevel->server_pending.maximized) { - s = wl_array_add(&states, sizeof(uint32_t)); + uint32_t *s = wl_array_add(&states, sizeof(uint32_t)); if (!s) { wlr_log(L_ERROR, "Could not allocate state for maximized xdg_toplevel"); goto error_out; @@ -95,7 +100,7 @@ void send_xdg_toplevel_configure(struct wlr_xdg_surface *surface, *s = XDG_TOPLEVEL_STATE_MAXIMIZED; } if (surface->toplevel->server_pending.fullscreen) { - s = wl_array_add(&states, sizeof(uint32_t)); + uint32_t *s = wl_array_add(&states, sizeof(uint32_t)); if (!s) { wlr_log(L_ERROR, "Could not allocate state for fullscreen xdg_toplevel"); goto error_out; @@ -103,7 +108,7 @@ void send_xdg_toplevel_configure(struct wlr_xdg_surface *surface, *s = XDG_TOPLEVEL_STATE_FULLSCREEN; } if (surface->toplevel->server_pending.resizing) { - s = wl_array_add(&states, sizeof(uint32_t)); + uint32_t *s = wl_array_add(&states, sizeof(uint32_t)); if (!s) { wlr_log(L_ERROR, "Could not allocate state for resizing xdg_toplevel"); goto error_out; @@ -111,13 +116,52 @@ void send_xdg_toplevel_configure(struct wlr_xdg_surface *surface, *s = XDG_TOPLEVEL_STATE_RESIZING; } if (surface->toplevel->server_pending.activated) { - s = wl_array_add(&states, sizeof(uint32_t)); + uint32_t *s = wl_array_add(&states, sizeof(uint32_t)); if (!s) { wlr_log(L_ERROR, "Could not allocate state for activated xdg_toplevel"); goto error_out; } *s = XDG_TOPLEVEL_STATE_ACTIVATED; } + if (surface->toplevel->server_pending.tiled) { + if (wl_resource_get_version(surface->resource) >= + XDG_TOPLEVEL_STATE_TILED_LEFT_SINCE_VERSION) { + const struct { + enum wlr_edges edge; + enum xdg_toplevel_state state; + } tiled[] = { + { WLR_EDGE_LEFT, XDG_TOPLEVEL_STATE_TILED_LEFT }, + { WLR_EDGE_RIGHT, XDG_TOPLEVEL_STATE_TILED_RIGHT }, + { WLR_EDGE_TOP, XDG_TOPLEVEL_STATE_TILED_TOP }, + { WLR_EDGE_BOTTOM, XDG_TOPLEVEL_STATE_TILED_BOTTOM }, + }; + + for (size_t i = 0; i < sizeof(tiled)/sizeof(tiled[0]); ++i) { + if ((surface->toplevel->server_pending.tiled & + tiled[i].edge) == 0) { + continue; + } + + uint32_t *s = wl_array_add(&states, sizeof(uint32_t)); + if (!s) { + wlr_log(L_ERROR, + "Could not allocate state for tiled xdg_toplevel"); + goto error_out; + } + *s = tiled[i].state; + } + } else if (!surface->toplevel->server_pending.maximized) { + // This version doesn't support tiling, best we can do is make the + // toplevel maximized + uint32_t *s = wl_array_add(&states, sizeof(uint32_t)); + if (!s) { + wlr_log(L_ERROR, + "Could not allocate state for maximized xdg_toplevel"); + goto error_out; + } + *s = XDG_TOPLEVEL_STATE_MAXIMIZED; + } + } uint32_t width = surface->toplevel->server_pending.width; uint32_t height = surface->toplevel->server_pending.height; @@ -479,3 +523,11 @@ uint32_t wlr_xdg_toplevel_set_resizing(struct wlr_xdg_surface *surface, return schedule_xdg_surface_configure(surface); } + +uint32_t wlr_xdg_toplevel_set_tiled(struct wlr_xdg_surface *surface, + uint32_t tiled) { + assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL); + surface->toplevel->server_pending.tiled = tiled; + + return schedule_xdg_surface_configure(surface); +}