mirror of
https://github.com/labwc/labwc.git
synced 2026-02-13 04:27:49 -05:00
interactive: set grab parameters at cursor press
Add interactive_set_grab_context() which is called when the mouse button is first pressed, before interactive_begin(). This fixes two small issues: - The cursor origin position for interactive move/resize was slightly off (depending on mouse resolution), because it was set after the mouse had already moved slightly. Now it's exact. - If app- or keybind-initiated maximize (etc.) happened after the button press but before the mouse was moved, then interactive_begin() would still start move/resize even though the view might now be far away from the cursor. Now interactive_cancel() works as expected, even if called before interactive_begin(). Also, make sure to call interactive_cancel() for un-maximize as well.
This commit is contained in:
parent
3ea46ba45a
commit
a672e8a9fd
7 changed files with 90 additions and 36 deletions
|
|
@ -414,6 +414,7 @@ void seat_focus_override_end(struct seat *seat, bool restore_focus);
|
|||
*/
|
||||
void interactive_anchor_to_cursor(struct server *server, struct wlr_box *geo);
|
||||
|
||||
void interactive_set_grab_context(struct cursor_context *ctx);
|
||||
void interactive_begin(struct view *view, enum input_mode mode,
|
||||
enum lab_edge edges);
|
||||
void interactive_finish(struct view *view);
|
||||
|
|
|
|||
18
src/action.c
18
src/action.c
|
|
@ -1262,6 +1262,14 @@ run_action(struct view *view, struct server *server, struct action *action,
|
|||
break;
|
||||
case ACTION_TYPE_MOVE:
|
||||
if (view) {
|
||||
/*
|
||||
* If triggered by mousebind, grab context was already
|
||||
* set by button press handling. For keybind-triggered
|
||||
* Move, set it now from current cursor position.
|
||||
*/
|
||||
if (view != server->seat.pressed.ctx.view) {
|
||||
interactive_set_grab_context(ctx);
|
||||
}
|
||||
interactive_begin(view, LAB_INPUT_STATE_MOVE,
|
||||
LAB_EDGE_NONE);
|
||||
}
|
||||
|
|
@ -1285,9 +1293,13 @@ run_action(struct view *view, struct server *server, struct action *action,
|
|||
*/
|
||||
enum lab_edge resize_edges =
|
||||
action_get_int(action, "direction", LAB_EDGE_NONE);
|
||||
if (resize_edges == LAB_EDGE_NONE) {
|
||||
resize_edges = cursor_get_resize_edges(
|
||||
server->seat.cursor, ctx);
|
||||
/*
|
||||
* If triggered by mousebind, grab context was already
|
||||
* set by button press handling. For keybind-triggered
|
||||
* Resize, set it now from current cursor position.
|
||||
*/
|
||||
if (view != server->seat.pressed.ctx.view) {
|
||||
interactive_set_grab_context(ctx);
|
||||
}
|
||||
interactive_begin(view, LAB_INPUT_STATE_RESIZE,
|
||||
resize_edges);
|
||||
|
|
|
|||
|
|
@ -1147,6 +1147,7 @@ cursor_process_button_press(struct seat *seat, uint32_t button, uint32_t time_ms
|
|||
if (ctx.view || ctx.surface) {
|
||||
/* Store cursor context for later action processing */
|
||||
cursor_context_save(&seat->pressed, &ctx);
|
||||
interactive_set_grab_context(&ctx);
|
||||
}
|
||||
|
||||
if (server->input_mode == LAB_INPUT_STATE_MENU) {
|
||||
|
|
@ -1277,6 +1278,9 @@ cursor_finish_button_release(struct seat *seat, uint32_t button)
|
|||
/* Exit interactive move/resize mode */
|
||||
interactive_finish(server->grabbed_view);
|
||||
return true;
|
||||
} else if (server->grabbed_view) {
|
||||
/* Button was released without starting move/resize */
|
||||
interactive_cancel(server->grabbed_view);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -54,9 +54,34 @@ interactive_anchor_to_cursor(struct server *server, struct wlr_box *geo)
|
|||
geo->y = server->grab_box.y + (server->seat.cursor->y - server->grab_y);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called before interactive_begin() to set the initial grab parameters
|
||||
* (cursor position and view geometry). Once the cursor actually moves,
|
||||
* then interactive_begin() is called.
|
||||
*/
|
||||
void
|
||||
interactive_set_grab_context(struct cursor_context *ctx)
|
||||
{
|
||||
if (!ctx->view) {
|
||||
return;
|
||||
}
|
||||
struct server *server = ctx->view->server;
|
||||
if (server->input_mode != LAB_INPUT_STATE_PASSTHROUGH) {
|
||||
return;
|
||||
}
|
||||
|
||||
server->grabbed_view = ctx->view;
|
||||
server->grab_x = server->seat.cursor->x;
|
||||
server->grab_y = server->seat.cursor->y;
|
||||
server->grab_box = ctx->view->current;
|
||||
server->resize_edges =
|
||||
cursor_get_resize_edges(server->seat.cursor, ctx);
|
||||
}
|
||||
|
||||
void
|
||||
interactive_begin(struct view *view, enum input_mode mode, enum lab_edge edges)
|
||||
{
|
||||
assert(view);
|
||||
/*
|
||||
* This function sets up an interactive move or resize operation, where
|
||||
* the compositor stops propagating pointer events to clients and
|
||||
|
|
@ -65,7 +90,8 @@ interactive_begin(struct view *view, enum input_mode mode, enum lab_edge edges)
|
|||
struct server *server = view->server;
|
||||
struct seat *seat = &server->seat;
|
||||
|
||||
if (server->input_mode != LAB_INPUT_STATE_PASSTHROUGH) {
|
||||
if (server->input_mode != LAB_INPUT_STATE_PASSTHROUGH
|
||||
|| view != server->grabbed_view) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -108,21 +134,29 @@ interactive_begin(struct view *view, enum input_mode mode, enum lab_edge edges)
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Override resize edges if specified explicitly.
|
||||
* Otherwise, they were set already from cursor context.
|
||||
*/
|
||||
if (edges != LAB_EDGE_NONE) {
|
||||
server->resize_edges = edges;
|
||||
}
|
||||
|
||||
/*
|
||||
* If tiled or maximized in only one direction, reset
|
||||
* tiled state and un-maximize the relevant axes, but
|
||||
* keep the same geometry as the starting point.
|
||||
*/
|
||||
enum view_axis maximized = view->maximized;
|
||||
if (edges & LAB_EDGES_LEFT_RIGHT) {
|
||||
if (server->resize_edges & LAB_EDGES_LEFT_RIGHT) {
|
||||
maximized &= ~VIEW_AXIS_HORIZONTAL;
|
||||
}
|
||||
if (edges & LAB_EDGES_TOP_BOTTOM) {
|
||||
if (server->resize_edges & LAB_EDGES_TOP_BOTTOM) {
|
||||
maximized &= ~VIEW_AXIS_VERTICAL;
|
||||
}
|
||||
view_set_maximized(view, maximized);
|
||||
view_set_untiled(view);
|
||||
cursor_shape = cursor_get_from_edge(edges);
|
||||
cursor_shape = cursor_get_from_edge(server->resize_edges);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
@ -130,13 +164,6 @@ interactive_begin(struct view *view, enum input_mode mode, enum lab_edge edges)
|
|||
return;
|
||||
}
|
||||
|
||||
server->grabbed_view = view;
|
||||
/* Remember view and cursor positions at start of move/resize */
|
||||
server->grab_x = seat->cursor->x;
|
||||
server->grab_y = seat->cursor->y;
|
||||
server->grab_box = view->current;
|
||||
server->resize_edges = edges;
|
||||
|
||||
seat_focus_override_begin(seat, mode, cursor_shape);
|
||||
|
||||
/*
|
||||
|
|
@ -293,6 +320,8 @@ snap_to_region(struct view *view)
|
|||
void
|
||||
interactive_finish(struct view *view)
|
||||
{
|
||||
assert(view);
|
||||
|
||||
if (view->server->grabbed_view != view) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -314,16 +343,27 @@ interactive_finish(struct view *view)
|
|||
void
|
||||
interactive_cancel(struct view *view)
|
||||
{
|
||||
assert(view);
|
||||
|
||||
if (view->server->grabbed_view != view) {
|
||||
return;
|
||||
}
|
||||
|
||||
view->server->grabbed_view = NULL;
|
||||
|
||||
/*
|
||||
* It's possible that grabbed_view was set but interactive_begin()
|
||||
* wasn't called yet. In that case, we are done.
|
||||
*/
|
||||
if (view->server->input_mode != LAB_INPUT_STATE_MOVE
|
||||
&& view->server->input_mode != LAB_INPUT_STATE_RESIZE) {
|
||||
return;
|
||||
}
|
||||
|
||||
overlay_finish(&view->server->seat);
|
||||
|
||||
resize_indicator_hide(view);
|
||||
|
||||
view->server->grabbed_view = NULL;
|
||||
|
||||
/* Restore keyboard/pointer focus */
|
||||
seat_focus_override_end(&view->server->seat, /*restore_focus*/ true);
|
||||
}
|
||||
|
|
|
|||
13
src/view.c
13
src/view.c
|
|
@ -1433,14 +1433,11 @@ view_maximize(struct view *view, enum view_axis axis)
|
|||
bool store_natural_geometry = !in_interactive_move(view);
|
||||
view_set_shade(view, false);
|
||||
|
||||
if (axis != VIEW_AXIS_NONE) {
|
||||
/*
|
||||
* Maximize via keybind or client request cancels
|
||||
* interactive move/resize since we can't move/resize
|
||||
* a maximized view.
|
||||
*/
|
||||
interactive_cancel(view);
|
||||
}
|
||||
/*
|
||||
* Maximize/unmaximize via keybind or client request cancels
|
||||
* interactive move/resize.
|
||||
*/
|
||||
interactive_cancel(view);
|
||||
|
||||
/*
|
||||
* Update natural geometry for any axis that wasn't already
|
||||
|
|
|
|||
12
src/xdg.c
12
src/xdg.c
|
|
@ -454,11 +454,11 @@ handle_request_move(struct wl_listener *listener, void *data)
|
|||
* the provided serial against a list of button press serials sent to
|
||||
* this client, to prevent the client from requesting this whenever they
|
||||
* want.
|
||||
*
|
||||
* Note: interactive_begin() checks that view == server->grabbed_view.
|
||||
*/
|
||||
struct view *view = wl_container_of(listener, view, request_move);
|
||||
if (view == view->server->seat.pressed.ctx.view) {
|
||||
interactive_begin(view, LAB_INPUT_STATE_MOVE, LAB_EDGE_NONE);
|
||||
}
|
||||
interactive_begin(view, LAB_INPUT_STATE_MOVE, LAB_EDGE_NONE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -471,12 +471,12 @@ handle_request_resize(struct wl_listener *listener, void *data)
|
|||
* the provided serial against a list of button press serials sent to
|
||||
* this client, to prevent the client from requesting this whenever they
|
||||
* want.
|
||||
*
|
||||
* Note: interactive_begin() checks that view == server->grabbed_view.
|
||||
*/
|
||||
struct wlr_xdg_toplevel_resize_event *event = data;
|
||||
struct view *view = wl_container_of(listener, view, request_resize);
|
||||
if (view == view->server->seat.pressed.ctx.view) {
|
||||
interactive_begin(view, LAB_INPUT_STATE_RESIZE, event->edges);
|
||||
}
|
||||
interactive_begin(view, LAB_INPUT_STATE_RESIZE, event->edges);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -288,11 +288,11 @@ handle_request_move(struct wl_listener *listener, void *data)
|
|||
* the provided serial against a list of button press serials sent to
|
||||
* this client, to prevent the client from requesting this whenever they
|
||||
* want.
|
||||
*
|
||||
* Note: interactive_begin() checks that view == server->grabbed_view.
|
||||
*/
|
||||
struct view *view = wl_container_of(listener, view, request_move);
|
||||
if (view == view->server->seat.pressed.ctx.view) {
|
||||
interactive_begin(view, LAB_INPUT_STATE_MOVE, LAB_EDGE_NONE);
|
||||
}
|
||||
interactive_begin(view, LAB_INPUT_STATE_MOVE, LAB_EDGE_NONE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -305,12 +305,12 @@ handle_request_resize(struct wl_listener *listener, void *data)
|
|||
* the provided serial against a list of button press serials sent to
|
||||
* this client, to prevent the client from requesting this whenever they
|
||||
* want.
|
||||
*
|
||||
* Note: interactive_begin() checks that view == server->grabbed_view.
|
||||
*/
|
||||
struct wlr_xwayland_resize_event *event = data;
|
||||
struct view *view = wl_container_of(listener, view, request_resize);
|
||||
if (view == view->server->seat.pressed.ctx.view) {
|
||||
interactive_begin(view, LAB_INPUT_STATE_RESIZE, event->edges);
|
||||
}
|
||||
interactive_begin(view, LAB_INPUT_STATE_RESIZE, event->edges);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue