From 4c179a27c2fe301d51232934275250b63275f86b Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Tue, 26 Nov 2019 07:52:53 +0800 Subject: wayland: add grab zone for resizing window with mouse Today, we support resizing wayland windows when we detect a touch event in a defined grab zone. As part of implementing pseudo-decorations, we should have equivalent functionality for mouse input. And if we detect support for actual decorations we will not activate the grab zone as the decorations will provide this. --- video/out/wayland_common.c | 92 ++++++++++++++++++++++++++-------------------- video/out/wayland_common.h | 2 + 2 files changed, 54 insertions(+), 40 deletions(-) (limited to 'video') diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c index 2007836a3b..c9da326b5a 100644 --- a/video/out/wayland_common.c +++ b/video/out/wayland_common.c @@ -56,6 +56,9 @@ const struct m_sub_options wayland_conf = { }, }; +#define POINTER_EDGE_PIXELS 5 +#define TOUCH_EDGE_PIXELS 64 + static void xdg_wm_base_ping(void *data, struct xdg_wm_base *wm_base, uint32_t serial) { xdg_wm_base_pong(wm_base, serial); @@ -155,6 +158,8 @@ static void pointer_handle_motion(void *data, struct wl_pointer *pointer, wl->prev_fullscreen = wl->fullscreen; wl->mouse_x = wl_fixed_to_int(sx) * wl->scaling; wl->mouse_y = wl_fixed_to_int(sy) * wl->scaling; + wl->mouse_unscaled_x = sx; + wl->mouse_unscaled_y = sy; mp_input_set_mouse_pos(wl->vo->input_ctx, wl->mouse_x, wl->mouse_y); } @@ -165,6 +170,42 @@ static void window_move(struct vo_wayland_state *wl, uint32_t serial) xdg_toplevel_move(wl->xdg_toplevel, wl->seat, serial); } +static int check_for_resize(struct vo_wayland_state *wl, wl_fixed_t x_w, wl_fixed_t y_w, + int edge_pixels, enum xdg_toplevel_resize_edge *edge) +{ + if (wl->touch_entries || wl->fullscreen || wl->maximized) + return 0; + + int pos[2] = { wl_fixed_to_double(x_w), wl_fixed_to_double(y_w) }; + int left_edge = pos[0] < edge_pixels; + int top_edge = pos[1] < edge_pixels; + int right_edge = pos[0] > (mp_rect_w(wl->geometry) - edge_pixels); + int bottom_edge = pos[1] > (mp_rect_h(wl->geometry) - edge_pixels); + + if (left_edge) { + *edge = XDG_TOPLEVEL_RESIZE_EDGE_LEFT; + if (top_edge) + *edge = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT; + else if (bottom_edge) + *edge = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT; + } else if (right_edge) { + *edge = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT; + if (top_edge) + *edge = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT; + else if (bottom_edge) + *edge = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT; + } else if (top_edge) { + *edge = XDG_TOPLEVEL_RESIZE_EDGE_TOP; + } else if (bottom_edge) { + *edge = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM; + } else { + *edge = 0; + return 0; + } + + return 1; +} + static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) @@ -200,8 +241,16 @@ static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer, } if (!mp_input_test_dragging(wl->vo->input_ctx, wl->mouse_x, wl->mouse_y) && - (button == MP_MBTN_LEFT) && (state == MP_KEY_STATE_DOWN)) - window_move(wl, serial); + (button == MP_MBTN_LEFT) && (state == MP_KEY_STATE_DOWN)) { + uint32_t edges; + // Implement an edge resize zone if there are no decorations + if (!wl->xdg_toplevel_decoration && + check_for_resize(wl, wl->mouse_unscaled_x, wl->mouse_unscaled_y, + POINTER_EDGE_PIXELS, &edges)) + xdg_toplevel_resize(wl->xdg_toplevel, wl->seat, serial, edges); + else + window_move(wl, serial); + } } static void pointer_handle_axis(void *data, struct wl_pointer *wl_pointer, @@ -235,43 +284,6 @@ static const struct wl_pointer_listener pointer_listener = { pointer_handle_axis, }; -static int check_for_resize(struct vo_wayland_state *wl, wl_fixed_t x_w, wl_fixed_t y_w, - enum xdg_toplevel_resize_edge *edge) -{ - if (wl->touch_entries || wl->fullscreen || wl->maximized) - return 0; - - const int edge_pixels = 64; - int pos[2] = { wl_fixed_to_double(x_w), wl_fixed_to_double(y_w) }; - int left_edge = pos[0] < edge_pixels; - int top_edge = pos[1] < edge_pixels; - int right_edge = pos[0] > (mp_rect_w(wl->geometry) - edge_pixels); - int bottom_edge = pos[1] > (mp_rect_h(wl->geometry) - edge_pixels); - - if (left_edge) { - *edge = XDG_TOPLEVEL_RESIZE_EDGE_LEFT; - if (top_edge) - *edge = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT; - else if (bottom_edge) - *edge = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT; - } else if (right_edge) { - *edge = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT; - if (top_edge) - *edge = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT; - else if (bottom_edge) - *edge = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT; - } else if (top_edge) { - *edge = XDG_TOPLEVEL_RESIZE_EDGE_TOP; - } else if (bottom_edge) { - *edge = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM; - } else { - *edge = 0; - return 0; - } - - return 1; -} - static void touch_handle_down(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, struct wl_surface *surface, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) @@ -279,7 +291,7 @@ static void touch_handle_down(void *data, struct wl_touch *wl_touch, struct vo_wayland_state *wl = data; enum xdg_toplevel_resize_edge edge; - if (check_for_resize(wl, x_w, y_w, &edge)) { + if (check_for_resize(wl, x_w, y_w, TOUCH_EDGE_PIXELS, &edge)) { wl->touch_entries = 0; xdg_toplevel_resize(wl->xdg_toplevel, wl->seat, serial, edge); return; diff --git a/video/out/wayland_common.h b/video/out/wayland_common.h index f0c11e080a..2ca7d86a96 100644 --- a/video/out/wayland_common.h +++ b/video/out/wayland_common.h @@ -77,6 +77,8 @@ struct vo_wayland_state { int pending_vo_events; int mouse_x; int mouse_y; + int mouse_unscaled_x; + int mouse_unscaled_y; int scaling; int touch_entries; uint32_t pointer_id; -- cgit v1.2.3