tUse a drawing box to move/resize windows - spkp - Stacking wayland compositor
(HTM) git clone git://git.z3bra.org/spkp.git
(DIR) Log
(DIR) Files
(DIR) Refs
---
(DIR) commit 1813f99552e6c439f35ea791a67b413734820345
(DIR) parent 2d59a0706e0f4c00478a50b3b7e027a179bf7a78
(HTM) Author: Willy Goiffon <dev@z3bra.org>
Date: Fri, 13 Nov 2020 15:49:07 +0100
Use a drawing box to move/resize windows
Diffstat:
M compositor.c | 85 +++++++++++++++++++------------
1 file changed, 52 insertions(+), 33 deletions(-)
---
(DIR) diff --git a/compositor.c b/compositor.c
t@@ -29,6 +29,7 @@
#include "arg.h"
+#define MAX(a,b) ((a)>(b)?(a):(b))
#define CLEANMASK(mask) (mask & ~(WLR_MODIFIER_CAPS|WLR_MODIFIER_SHIFT))
enum {
t@@ -54,6 +55,7 @@ struct state {
int grabmode;
double gx, gy;
+ struct wlr_box grabbox;
struct window *grabbed;
struct wlr_cursor *cursor;
t@@ -335,17 +337,22 @@ cb_frame_output(struct wl_listener *listener, void *data)
wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height);
wlr_renderer_clear(renderer, background);
+ rdata.output = wlr_output;
+ rdata.renderer = renderer;
+
wl_list_for_each_reverse(window, &output->server->windows, link) {
if (!window->mapped)
continue;
- rdata.output = wlr_output;
rdata.window = window;
- rdata.renderer = renderer;
clock_gettime(CLOCK_MONOTONIC, &rdata.when);
wlr_xdg_surface_for_each_surface(window->toplevel, render, &rdata);
}
+ struct state *server = output->server;
+ if (server->grabmode != NORMAL)
+ render_border(&server->grabbox, &rdata, 1);
+
/* render cursor by software in case the GPU doesn't handle it */
wlr_output_render_software_cursors(wlr_output, NULL);
t@@ -585,21 +592,16 @@ cb_motion(struct state *server, uint32_t time)
w = server->grabbed;
- struct wlr_box geom;
switch(server->grabmode) {
case MOVE:
- wlr_xdg_surface_get_geometry(w->toplevel, &geom);
- w->x = server->cursor->x - server->gx;
- w->y = server->cursor->y - server->gy;
+ server->grabbox.x = server->cursor->x - server->gx;
+ server->grabbox.y = server->cursor->y - server->gy;
return; /* NOTREACHED */;
break;
case RESIZE:
- wlr_xdg_surface_get_geometry(w->toplevel, &geom);
- geom.width = server->cursor->x - geom.x - w->x;
- geom.height = server->cursor->y - geom.y - w->y;
- wlr_xdg_toplevel_set_size(w->toplevel, geom.width, geom.height);
- return; /* NOTREACHED */;
- break;
+ server->grabbox.width = MAX(server->cursor->x - server->grabbox.x, 100);
+ server->grabbox.height = MAX(server->cursor->y - server->grabbox.y, 100);
+ return;
}
/*
t@@ -672,52 +674,69 @@ cb_click(struct wl_listener *listener, void *data)
struct wlr_event_pointer_button *ev;
struct window *w;
struct wlr_keyboard *kb;
+ struct wlr_box geom;
server = wl_container_of(listener, server, click);
kb = wlr_seat_get_keyboard(server->seat);
ev = data;
+ if (ev->state == WLR_BUTTON_RELEASED) {
+ switch(server->grabmode) {
+ case MOVE:
+ server->grabbed->x = server->grabbox.x;
+ server->grabbed->y = server->grabbox.y;
+ break;
+ case RESIZE:
+ geom.width = server->grabbox.width;
+ geom.height = server->grabbox.height;
+ wlr_xdg_toplevel_set_size(server->grabbed->toplevel, geom.width, geom.height);
+ break;
+ case NORMAL:
+ /* pass down event when not grabbing a window */
+ wlr_seat_pointer_notify_button(server->seat,
+ ev->time_msec, ev->button, ev->state);
+
+ }
+ server->grabmode = NORMAL;
+ return;
+ }
+
w = underneath(server, server->cursor->x, server->cursor->y);
/* don't enter grab mode when there is no window under the pointer */
if (!w) {
- wlr_seat_pointer_clear_focus(server->seat);
- server->grabmode = NORMAL;
return;
}
if ((w->area == BORDER || (kb->modifiers.depressed & WLR_MODIFIER_LOGO))
&& ev->state == WLR_BUTTON_PRESSED
&& server->grabmode == NORMAL) {
+
+ /*
+ * Save which window was clicked, and the coordinates
+ * of the event on that surface.
+ */
+ server->grabbed = w;
+ server->gx = w->sx;
+ server->gy = w->sy;
+ server->grabbox.x = w->x;
+ server->grabbox.y = w->y;
+
switch (ev->button) {
case BTN_LEFT:
+ wlr_xdg_surface_get_geometry(w->toplevel, &geom);
+ server->grabbox.width = geom.width;
+ server->grabbox.height = geom.height;
server->grabmode = MOVE;
break;
case BTN_RIGHT:
server->grabmode = RESIZE;
+ server->grabbox.width = w->sx + 2 * bordersize;
+ server->grabbox.height = w->sy + 2 * bordersize;
break;
}
}
- /* pass down event when not grabbing a window */
- if (server->grabmode == NORMAL)
- wlr_seat_pointer_notify_button(server->seat,
- ev->time_msec, ev->button, ev->state);
-
- /* every release event would reset the grab mode */
- if (ev->state == WLR_BUTTON_RELEASED) {
- server->grabmode = NORMAL;
- return;
- }
-
- /*
- * Save which window was clicked, and the coordinates
- * of the event on that surface.
- */
- server->grabbed = w;
- server->gx = w->sx;
- server->gy = w->sy;
-
/* bring window to the front */
wl_list_remove(&w->link);
wl_list_insert(&server->windows, &w->link);