commit 65176f9e2fe203a8e5d10b907bb9821e899be8ca
parent 30c2643a28f795a0b441dd834ea9580b0002c587
Author: Leon Plickat <leonhenrik.plickat@stud.uni-goettingen.de>
Date: Fri, 2 Aug 2019 18:18:17 +0200
Resize views by dragging their borders
This matches Rios behaviour, with the small exception that wios resizing
is smooth while Rios snaps to a grid.
Diffstat:
M | include/server.h | | | 4 | ++++ |
M | input.c | | | 163 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- |
M | output.c | | | 36 | ++++++++++++++++++++++++++++++++++-- |
3 files changed, 200 insertions(+), 3 deletions(-)
diff --git a/include/server.h b/include/server.h
@@ -26,6 +26,10 @@ enum wio_input_state {
INPUT_STATE_RESIZE_SELECT,
INPUT_STATE_RESIZE_START,
INPUT_STATE_RESIZE_END,
+ INPUT_STATE_BORDER_DRAG_TOP,
+ INPUT_STATE_BORDER_DRAG_RIGHT,
+ INPUT_STATE_BORDER_DRAG_BOTTOM,
+ INPUT_STATE_BORDER_DRAG_LEFT,
INPUT_STATE_DELETE_SELECT,
INPUT_STATE_HIDE_SELECT,
};
diff --git a/input.c b/input.c
@@ -134,6 +134,22 @@ static void process_cursor_motion(struct wio_server *server, uint32_t time) {
wlr_xcursor_manager_set_cursor_image(server->cursor_mgr,
"top_left_corner", server->cursor);
break;
+ case INPUT_STATE_BORDER_DRAG_TOP:
+ wlr_xcursor_manager_set_cursor_image(server->cursor_mgr,
+ "top_side", server->cursor);
+ break;
+ case INPUT_STATE_BORDER_DRAG_RIGHT:
+ wlr_xcursor_manager_set_cursor_image(server->cursor_mgr,
+ "right_side", server->cursor);
+ break;
+ case INPUT_STATE_BORDER_DRAG_BOTTOM:
+ wlr_xcursor_manager_set_cursor_image(server->cursor_mgr,
+ "bottom_side", server->cursor);
+ break;
+ case INPUT_STATE_BORDER_DRAG_LEFT:
+ wlr_xcursor_manager_set_cursor_image(server->cursor_mgr,
+ "left_side", server->cursor);
+ break;
case INPUT_STATE_RESIZE_END:
case INPUT_STATE_NEW_END:
wlr_xcursor_manager_set_cursor_image(server->cursor_mgr,
@@ -296,6 +312,69 @@ static void new_view(struct wio_server *server) {
}
}
+bool wio_border_drag(
+ struct wio_server *server, struct wlr_event_pointer_button *event) {
+ if (event->button != BTN_RIGHT) {
+ return false;
+ }
+ struct wlr_box border_box = {
+ .x = 0, .y = 0,
+ .width = 0, .height = 0,
+ };
+ struct wio_view *view;
+ struct wlr_surface *surface = NULL;
+ wl_list_for_each(view, &server->views, link) {
+ // Top border
+ border_box.height = window_border;
+ border_box.width = view->xdg_surface->surface->current.width;
+ border_box.x = view->x;
+ border_box.y = view->y - window_border;
+ if (wlr_box_contains_point(
+ &border_box, server->cursor->x, server->cursor->y)) {
+ view_begin_interactive(view, surface, view->x, view->y,
+ "top_side", INPUT_STATE_BORDER_DRAG_TOP);
+ return true;
+ }
+
+ // Right border
+ border_box.height = view->xdg_surface->surface->current.height;
+ border_box.width = window_border;
+ border_box.x = view->x + view->xdg_surface->surface->current.width;
+ border_box.y = view->y;
+ if (wlr_box_contains_point(
+ &border_box, server->cursor->x, server->cursor->y)) {
+ view_begin_interactive(view, surface, view->x, view->y,
+ "right_side", INPUT_STATE_BORDER_DRAG_RIGHT);
+ return true;
+ }
+
+ // Bottom border
+ border_box.height = window_border;
+ border_box.width = view->xdg_surface->surface->current.width;
+ border_box.x = view->x;
+ border_box.y = view->y + view->xdg_surface->surface->current.height;
+ if (wlr_box_contains_point(
+ &border_box, server->cursor->x, server->cursor->y)) {
+ view_begin_interactive(view, surface, view->x, view->y,
+ "bottom_side", INPUT_STATE_BORDER_DRAG_BOTTOM);
+ return true;
+ }
+
+ // Left border
+ border_box.height = view->xdg_surface->surface->current.height;
+ border_box.width = window_border;
+ border_box.x = view->x - window_border;
+ border_box.y = view->y;
+ if (wlr_box_contains_point(
+ &border_box, server->cursor->x, server->cursor->y)) {
+ view_begin_interactive(view, surface, view->x, view->y,
+ "left_side", INPUT_STATE_BORDER_DRAG_LEFT);
+ return true;
+ }
+ }
+ return false;
+}
+
static void handle_button_internal(
struct wio_server *server, struct wlr_event_pointer_button *event) {
// TODO: open menu if the client doesn't handle the button press
@@ -305,6 +384,7 @@ static void handle_button_internal(
.width = server->menu.width, .height = server->menu.height,
};
int x1, x2, y1, y2;
+ uint32_t width, height;
switch (server->input_state) {
case INPUT_STATE_NONE:
if (event->state == WLR_BUTTON_PRESSED && event->button == BTN_RIGHT) {
@@ -357,6 +437,84 @@ static void handle_button_internal(
server->input_state = INPUT_STATE_RESIZE_END;
}
break;
+ case INPUT_STATE_BORDER_DRAG_TOP:
+ y1 = server->interactive.view->y + server->interactive.view->xdg_surface->surface->current.height;
+ y2 = server->cursor->y;
+ x1 = server->interactive.view->x;
+ if (y2 < y1) {
+ int _ = y1;
+ y1 = y2;
+ y2 = _;
+ }
+ wio_view_move(server->interactive.view,
+ x1, y1);
+ width = server->interactive.view->xdg_surface->surface->current.width;
+ height = y2 - y1;
+ if (height < 100) {
+ height = 100;
+ }
+ wlr_xdg_toplevel_set_size(
+ server->interactive.view->xdg_surface, width, height);
+ view_end_interactive(server);
+ break;
+ case INPUT_STATE_BORDER_DRAG_LEFT:
+ x1 = server->interactive.view->x + server->interactive.view->xdg_surface->surface->current.width;
+ x2 = server->cursor->x;
+ y1 = server->interactive.view->y;
+ if (x2 < x1) {
+ int _ = x1;
+ x1 = x2;
+ x2 = _;
+ }
+ wio_view_move(server->interactive.view,
+ x1, y1);
+ width = x2 - x1;
+ height = server->interactive.view->xdg_surface->surface->current.height;
+ if (width < 100) {
+ width = 100;
+ }
+ wlr_xdg_toplevel_set_size(
+ server->interactive.view->xdg_surface, width, height);
+ view_end_interactive(server);
+ break;
+ case INPUT_STATE_BORDER_DRAG_BOTTOM:
+ x1 = server->interactive.view->x;
+ y1 = server->interactive.view->y, y2 = server->cursor->y;
+ if (y2 < y1) {
+ int _ = y1;
+ y1 = y2;
+ y2 = _;
+ }
+ wio_view_move(server->interactive.view,
+ x1, y1);
+ width = server->interactive.view->xdg_surface->surface->current.width;
+ height = y2 - y1;
+ if (width < 100) {
+ width = 100;
+ }
+ wlr_xdg_toplevel_set_size(
+ server->interactive.view->xdg_surface, width, height);
+ view_end_interactive(server);
+ break;
+ case INPUT_STATE_BORDER_DRAG_RIGHT:
+ x1 = server->interactive.view->x, x2 = server->cursor->x;
+ y1 = server->interactive.view->y;
+ if (x2 < x1) {
+ int _ = x1;
+ x1 = x2;
+ x2 = _;
+ }
+ wio_view_move(server->interactive.view,
+ x1, y1);
+ width = x2 - x1;
+ height = server->interactive.view->xdg_surface->surface->current.height;
+ if (width < 100) {
+ width = 100;
+ }
+ wlr_xdg_toplevel_set_size(
+ server->interactive.view->xdg_surface, width, height);
+ view_end_interactive(server);
+ break;
case INPUT_STATE_RESIZE_END:
x1 = server->interactive.sx, x2 = server->cursor->x;
y1 = server->interactive.sy, y2 = server->cursor->y;
@@ -372,7 +530,7 @@ static void handle_button_internal(
}
wio_view_move(server->interactive.view,
x1, y1);
- uint32_t width = x2 - x1, height = y2 - y1;
+ width = x2 - x1, height = y2 - y1;
if (width < 100) {
width = 100;
}
@@ -429,6 +587,9 @@ void server_cursor_button(struct wl_listener *listener, void *data) {
struct wlr_surface *surface = NULL;
struct wio_view *view = wio_view_at(
server, server->cursor->x, server->cursor->y, &surface, &sx, &sy);
+ if (wio_border_drag(server, event)) {
+ return;
+ }
if (server->input_state == INPUT_STATE_NONE && view) {
wio_view_focus(view, surface);
wlr_seat_pointer_notify_button(server->seat,
diff --git a/output.c b/output.c
@@ -306,9 +306,41 @@ static void output_frame(struct wl_listener *listener, void *data) {
wlr_xdg_surface_for_each_surface(view->xdg_surface,
render_surface, &rdata);
}
+ view = server->interactive.view;
switch (server->input_state) {
- case INPUT_STATE_MOVE:;
- struct wio_view *view = server->interactive.view;
+ case INPUT_STATE_BORDER_DRAG_TOP:
+ render_view_border(renderer, output, view,
+ view->x,
+ server->cursor->y,
+ view->xdg_surface->surface->current.width,
+ view->xdg_surface->surface->current.height - (server->cursor->y - server->interactive.sy),
+ 1);
+ break;
+ case INPUT_STATE_BORDER_DRAG_LEFT:
+ render_view_border(renderer, output, view,
+ server->cursor->x,
+ view->y,
+ view->xdg_surface->surface->current.width - (server->cursor->x - server->interactive.sx),
+ view->xdg_surface->surface->current.height,
+ 1);
+ break;
+ case INPUT_STATE_BORDER_DRAG_BOTTOM:
+ render_view_border(renderer, output, view,
+ view->x,
+ view->y,
+ view->xdg_surface->surface->current.width,
+ server->cursor->y - server->interactive.sy,
+ 1);
+ break;
+ case INPUT_STATE_BORDER_DRAG_RIGHT:
+ render_view_border(renderer, output, view,
+ view->x,
+ view->y,
+ server->cursor->x - server->interactive.sx,
+ view->xdg_surface->surface->current.height,
+ 1);
+ break;
+ case INPUT_STATE_MOVE:
render_view_border(renderer, output, view,
server->cursor->x - server->interactive.sx,
server->cursor->y - server->interactive.sy,