commit c54aeba29cc945d4fb4e2f5b35c509244be263d8
parent 8442dc236f4d5b2e230c9cdf2e13278c6325a15e
Author: Drew DeVault <sir@cmpwn.com>
Date: Thu, 25 Apr 2019 12:42:48 -0400
Implement interactive resize
Diffstat:
M | include/server.h | | | 5 | ++++- |
M | input.c | | | 101 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- |
M | main.c | | | 2 | +- |
M | output.c | | | 60 | ++++++++++++++++++++++++++++++++++++++---------------------- |
4 files changed, 132 insertions(+), 36 deletions(-)
diff --git a/include/server.h b/include/server.h
@@ -12,6 +12,8 @@
#include <wlr/types/wlr_xcursor_manager.h>
#include <wlr/types/wlr_xdg_shell.h>
+static const int window_border = 5;
+
enum wio_input_state {
INPUT_STATE_NONE = 0,
INPUT_STATE_MENU,
@@ -20,7 +22,8 @@ enum wio_input_state {
INPUT_STATE_MOVE_SELECT,
INPUT_STATE_MOVE,
INPUT_STATE_RESIZE_SELECT,
- INPUT_STATE_RESIZE,
+ INPUT_STATE_RESIZE_START,
+ INPUT_STATE_RESIZE_END,
INPUT_STATE_DELETE_SELECT,
INPUT_STATE_HIDE_SELECT,
};
diff --git a/input.c b/input.c
@@ -99,6 +99,14 @@ static void process_cursor_motion(struct wio_server *server, uint32_t time) {
wlr_xcursor_manager_set_cursor_image(server->cursor_mgr,
"grabbing", server->cursor);
break;
+ case INPUT_STATE_RESIZE_START:
+ wlr_xcursor_manager_set_cursor_image(server->cursor_mgr,
+ "top_left_corner", server->cursor);
+ break;
+ case INPUT_STATE_RESIZE_END:
+ wlr_xcursor_manager_set_cursor_image(server->cursor_mgr,
+ "bottom_right_corner", server->cursor);
+ break;
default:
wlr_xcursor_manager_set_cursor_image(server->cursor_mgr,
"left_ptr", server->cursor);
@@ -138,6 +146,11 @@ static void menu_handle_button(
struct wio_server *server, struct wlr_event_pointer_button *event) {
server->menu.x = server->menu.y = -1;
switch (server->menu.selected) {
+ case 1:
+ server->input_state = INPUT_STATE_RESIZE_SELECT;
+ wlr_xcursor_manager_set_cursor_image(server->cursor_mgr,
+ "hand1", server->cursor);
+ break;
case 2:
server->input_state = INPUT_STATE_MOVE_SELECT;
wlr_xcursor_manager_set_cursor_image(server->cursor_mgr,
@@ -149,6 +162,30 @@ static void menu_handle_button(
}
}
+static void view_begin_interactive(struct wio_view *view,
+ struct wlr_surface *surface, double sx, double sy,
+ const char *cursor, enum wio_input_state state) {
+ wio_view_focus(view, surface);
+ view->server->interactive.view = view;
+ view->server->interactive.sx = (int)sx;
+ view->server->interactive.sy = (int)sy;
+ view->server->input_state = state;
+ wlr_xcursor_manager_set_cursor_image(view->server->cursor_mgr,
+ "grabbing", view->server->cursor);
+}
+
+static void view_end_interactive(struct wio_server *server) {
+ server->input_state = INPUT_STATE_NONE;
+ server->interactive.view = NULL;
+ if (server->interactive.cursor) {
+ wlr_cursor_set_surface(server->cursor, server->interactive.cursor,
+ server->interactive.hotspot_x, server->interactive.hotspot_y);
+ } else {
+ wlr_xcursor_manager_set_cursor_image(server->cursor_mgr,
+ "left_ptr", server->cursor);
+ }
+}
+
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
@@ -157,6 +194,7 @@ static void handle_button_internal(
.x = server->menu.x, .y = server->menu.y,
.width = server->menu.width, .height = server->menu.height,
};
+ int x1, x2, y1, y2;
switch (server->input_state) {
case INPUT_STATE_NONE:
if (event->state == WLR_BUTTON_PRESSED && event->button == BTN_RIGHT) {
@@ -177,20 +215,15 @@ static void handle_button_internal(
}
}
break;
- case INPUT_STATE_MOVE_SELECT:
+ case INPUT_STATE_RESIZE_SELECT:
if (event->state == WLR_BUTTON_PRESSED) {
double sx, sy;
struct wlr_surface *surface = NULL;
struct wio_view *view = wio_view_at(server,
server->cursor->x, server->cursor->y, &surface, &sx, &sy);
if (view != NULL) {
- wio_view_focus(view, surface);
- server->interactive.view = view;
- server->interactive.sx = (int)sx;
- server->interactive.sy = (int)sy;
- server->input_state = INPUT_STATE_MOVE;
- wlr_xcursor_manager_set_cursor_image(server->cursor_mgr,
- "grabbing", server->cursor);
+ view_begin_interactive(view, surface, sx, sy,
+ "bottom_right_corner", INPUT_STATE_RESIZE_START);
} else {
server->input_state = INPUT_STATE_NONE;
wlr_xcursor_manager_set_cursor_image(server->cursor_mgr,
@@ -198,15 +231,59 @@ static void handle_button_internal(
}
}
break;
+ case INPUT_STATE_RESIZE_START:
+ if (event->state == WLR_BUTTON_PRESSED) {
+ server->interactive.sx = server->cursor->x;
+ server->interactive.sy = server->cursor->y;
+ server->input_state = INPUT_STATE_RESIZE_END;
+ }
+ break;
+ case INPUT_STATE_RESIZE_END:
+ x1 = server->interactive.sx, x2 = server->cursor->x;
+ y1 = server->interactive.sy, y2 = server->cursor->y;
+ if (x2 < x1) {
+ int _ = x1;
+ x1 = x2;
+ x2 = _;
+ }
+ if (y2 < y1) {
+ int _ = y1;
+ y1 = y2;
+ y2 = _;
+ }
+ server->interactive.view->x = x1 + window_border;
+ server->interactive.view->y = y1 + window_border;
+ uint32_t width = x2 - x1, height = y2 - y1;
+ if (width < 100) {
+ width = 100;
+ }
+ 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_MOVE_SELECT:
+ if (event->state == WLR_BUTTON_PRESSED) {
+ double sx, sy;
+ struct wlr_surface *surface = NULL;
+ struct wio_view *view = wio_view_at(server,
+ server->cursor->x, server->cursor->y, &surface, &sx, &sy);
+ if (view != NULL) {
+ view_begin_interactive(view, surface, sx, sy,
+ "grabbing", INPUT_STATE_MOVE);
+ } else {
+ view_end_interactive(server);
+ }
+ }
+ break;
case INPUT_STATE_MOVE:
server->interactive.view->x =
server->cursor->x - server->interactive.sx;
server->interactive.view->y =
server->cursor->y - server->interactive.sy;
- server->input_state = INPUT_STATE_NONE;
- server->interactive.view = NULL;
- wlr_cursor_set_surface(server->cursor, server->interactive.cursor,
- server->interactive.hotspot_x, server->interactive.hotspot_y);
+ view_end_interactive(server);
break;
default:
// TODO
diff --git a/main.c b/main.c
@@ -72,7 +72,7 @@ static void gen_menu_textures(struct wio_server *server) {
}
int main(int argc, char **argv) {
- struct wio_server server;
+ struct wio_server server = { 0 };
wlr_log_init(WLR_DEBUG, NULL);
diff --git a/output.c b/output.c
@@ -134,8 +134,8 @@ static void render_menu(struct wio_output *output) {
}
static void render_view_border(struct wlr_renderer *renderer,
- struct wio_output *output, struct wio_view *view, int x, int y) {
- const int border = 5;
+ struct wio_output *output, struct wio_view *view,
+ int x, int y, int width, int height) {
float color[4];
if (view->xdg_surface->toplevel->current.activated) {
memcpy(color, active_border, sizeof(color));
@@ -144,31 +144,31 @@ static void render_view_border(struct wlr_renderer *renderer,
}
struct wlr_box borders;
// Top
- borders.x = x - border;
- borders.y = y - border;
- borders.width = view->xdg_surface->surface->current.width + border * 2;
- borders.height = border;
+ borders.x = x - window_border;
+ borders.y = y - window_border;
+ borders.width = width + window_border * 2;
+ borders.height = window_border;
wlr_render_rect(renderer, &borders, color,
output->wlr_output->transform_matrix);
// Right
- borders.x = x + view->xdg_surface->surface->current.width;
- borders.y = y - border;
- borders.width = border;
- borders.height = view->xdg_surface->surface->current.height + border * 2;
+ borders.x = x + width;
+ borders.y = y - window_border;
+ borders.width = window_border;
+ borders.height = height + window_border * 2;
wlr_render_rect(renderer, &borders, color,
output->wlr_output->transform_matrix);
// Bottom
- borders.x = x - border;
- borders.y = y + view->xdg_surface->surface->current.height;
- borders.width = view->xdg_surface->surface->current.width + border * 2;
- borders.height = border;
+ borders.x = x - window_border;
+ borders.y = y + height;
+ borders.width = width + window_border * 2;
+ borders.height = window_border;
wlr_render_rect(renderer, &borders, color,
output->wlr_output->transform_matrix);
// Left
- borders.x = x - border;
- borders.y = y - border;
- borders.width = border;
- borders.height = view->xdg_surface->surface->current.height + border * 2;
+ borders.x = x - window_border;
+ borders.y = y - window_border;
+ borders.width = window_border;
+ borders.height = height + window_border * 2;
wlr_render_rect(renderer, &borders, color,
output->wlr_output->transform_matrix);
}
@@ -203,13 +203,29 @@ static void output_frame(struct wl_listener *listener, void *data) {
.when = &now,
};
- render_view_border(renderer, output, view, view->x, view->y);
+ render_view_border(renderer, output, view, view->x, view->y,
+ view->xdg_surface->surface->current.width,
+ view->xdg_surface->surface->current.height);
wlr_xdg_surface_for_each_surface(view->xdg_surface,
render_surface, &rdata);
if (server->interactive.view == view) {
- render_view_border(renderer, output, view,
- server->cursor->x - server->interactive.sx,
- server->cursor->y - server->interactive.sy);
+ switch (server->input_state) {
+ case INPUT_STATE_MOVE:
+ render_view_border(renderer, output, view,
+ server->cursor->x - server->interactive.sx,
+ server->cursor->y - server->interactive.sy,
+ view->xdg_surface->surface->current.width,
+ view->xdg_surface->surface->current.height);
+ break;
+ case INPUT_STATE_RESIZE_END:
+ render_view_border(renderer, output, view,
+ server->interactive.sx, server->interactive.sy,
+ server->cursor->x - server->interactive.sx,
+ server->cursor->y - server->interactive.sy);
+ break;
+ default:
+ break;
+ }
}
}