mirror of
https://github.com/labwc/labwc.git
synced 2026-03-14 05:33:52 -04:00
cursor: generalize seat->pressed
This commit moduralize seat_{set,reset}_pressed() into
cursor_context_save() so that we can also have seat->hovered later.
This commit is contained in:
parent
4fcb873f6f
commit
acb3da7903
8 changed files with 97 additions and 68 deletions
|
|
@ -38,6 +38,14 @@ struct cursor_context {
|
||||||
double sx, sy;
|
double sx, sy;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Used to persistently store cursor context (e.g. in seat->pressed) */
|
||||||
|
struct cursor_context_saved {
|
||||||
|
struct cursor_context ctx;
|
||||||
|
struct wl_listener view_destroy;
|
||||||
|
struct wl_listener node_destroy;
|
||||||
|
struct wl_listener surface_destroy;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get_cursor_context - find view, surface and scene_node at cursor
|
* get_cursor_context - find view, surface and scene_node at cursor
|
||||||
*
|
*
|
||||||
|
|
@ -65,6 +73,13 @@ void cursor_set(struct seat *seat, enum lab_cursors cursor);
|
||||||
|
|
||||||
void cursor_set_visible(struct seat *seat, bool visible);
|
void cursor_set_visible(struct seat *seat, bool visible);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Safely store a cursor context to saved_ctx. saved_ctx is cleared when either
|
||||||
|
* of its node, surface and view is destroyed.
|
||||||
|
*/
|
||||||
|
void cursor_context_save(struct cursor_context_saved *saved_ctx,
|
||||||
|
const struct cursor_context *ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cursor_get_resize_edges - calculate resize edge based on cursor position
|
* cursor_get_resize_edges - calculate resize edge based on cursor position
|
||||||
* @cursor - the current cursor (usually server->seat.cursor)
|
* @cursor - the current cursor (usually server->seat.cursor)
|
||||||
|
|
|
||||||
|
|
@ -65,8 +65,7 @@ struct seat {
|
||||||
struct input_method_relay *input_method_relay;
|
struct input_method_relay *input_method_relay;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is usually zeroed and is only set on button press while the
|
* Cursor context saved when a mouse button is pressed on a view/surface.
|
||||||
* mouse is over a view or surface, and zeroed on button release.
|
|
||||||
* It is used to send cursor motion events to a surface even though
|
* It is used to send cursor motion events to a surface even though
|
||||||
* the cursor has left the surface in the meantime.
|
* the cursor has left the surface in the meantime.
|
||||||
*
|
*
|
||||||
|
|
@ -76,10 +75,8 @@ struct seat {
|
||||||
* It is also used to:
|
* It is also used to:
|
||||||
* - determine the target view for action in "Drag" mousebind
|
* - determine the target view for action in "Drag" mousebind
|
||||||
* - validate view move/resize requests from CSD clients
|
* - validate view move/resize requests from CSD clients
|
||||||
*
|
|
||||||
* Both (view && !surface) and (surface && !view) are possible.
|
|
||||||
*/
|
*/
|
||||||
struct cursor_context pressed;
|
struct cursor_context_saved pressed;
|
||||||
|
|
||||||
struct lab_set bound_buttons;
|
struct lab_set bound_buttons;
|
||||||
|
|
||||||
|
|
@ -139,7 +136,6 @@ struct seat {
|
||||||
struct wl_list tablet_pads;
|
struct wl_list tablet_pads;
|
||||||
|
|
||||||
struct wl_listener constraint_commit;
|
struct wl_listener constraint_commit;
|
||||||
struct wl_listener pressed_surface_destroy;
|
|
||||||
|
|
||||||
struct wlr_virtual_pointer_manager_v1 *virtual_pointer;
|
struct wlr_virtual_pointer_manager_v1 *virtual_pointer;
|
||||||
struct wl_listener new_virtual_pointer;
|
struct wl_listener new_virtual_pointer;
|
||||||
|
|
@ -392,8 +388,6 @@ void seat_pointer_end_grab(struct seat *seat, struct wlr_surface *surface);
|
||||||
void seat_focus_lock_surface(struct seat *seat, struct wlr_surface *surface);
|
void seat_focus_lock_surface(struct seat *seat, struct wlr_surface *surface);
|
||||||
|
|
||||||
void seat_set_focus_layer(struct seat *seat, struct wlr_layer_surface_v1 *layer);
|
void seat_set_focus_layer(struct seat *seat, struct wlr_layer_surface_v1 *layer);
|
||||||
void seat_set_pressed(struct seat *seat, struct cursor_context *ctx);
|
|
||||||
void seat_reset_pressed(struct seat *seat);
|
|
||||||
void seat_output_layout_changed(struct seat *seat);
|
void seat_output_layout_changed(struct seat *seat);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ handle_drag_start(struct wl_listener *listener, void *data)
|
||||||
struct wlr_drag *drag = data;
|
struct wlr_drag *drag = data;
|
||||||
|
|
||||||
seat->drag.active = true;
|
seat->drag.active = true;
|
||||||
seat_reset_pressed(seat);
|
cursor_context_save(&seat->pressed, NULL);
|
||||||
if (drag->icon) {
|
if (drag->icon) {
|
||||||
/* Cleans up automatically on drag->icon->events.destroy */
|
/* Cleans up automatically on drag->icon->events.destroy */
|
||||||
wlr_scene_drag_icon_create(seat->drag.icons, drag->icon);
|
wlr_scene_drag_icon_create(seat->drag.icons, drag->icon);
|
||||||
|
|
|
||||||
|
|
@ -437,8 +437,72 @@ cursor_update_image(struct seat *seat)
|
||||||
cursor_names[cursor]);
|
cursor_names[cursor]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clear_cursor_context(struct cursor_context_saved *saved_ctx)
|
||||||
|
{
|
||||||
|
if (saved_ctx->node_destroy.notify) {
|
||||||
|
wl_list_remove(&saved_ctx->node_destroy.link);
|
||||||
|
}
|
||||||
|
if (saved_ctx->surface_destroy.notify) {
|
||||||
|
wl_list_remove(&saved_ctx->surface_destroy.link);
|
||||||
|
}
|
||||||
|
if (saved_ctx->view_destroy.notify) {
|
||||||
|
wl_list_remove(&saved_ctx->view_destroy.link);
|
||||||
|
}
|
||||||
|
*saved_ctx = (struct cursor_context_saved) {0};
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_ctx_node_destroy(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
struct cursor_context_saved *saved_ctx =
|
||||||
|
wl_container_of(listener, saved_ctx, node_destroy);
|
||||||
|
clear_cursor_context(saved_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_ctx_surface_destroy(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
struct cursor_context_saved *saved_ctx =
|
||||||
|
wl_container_of(listener, saved_ctx, surface_destroy);
|
||||||
|
clear_cursor_context(saved_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_ctx_view_destroy(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
struct cursor_context_saved *saved_ctx =
|
||||||
|
wl_container_of(listener, saved_ctx, view_destroy);
|
||||||
|
clear_cursor_context(saved_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cursor_context_save(struct cursor_context_saved *saved_ctx,
|
||||||
|
const struct cursor_context *ctx)
|
||||||
|
{
|
||||||
|
assert(saved_ctx);
|
||||||
|
|
||||||
|
clear_cursor_context(saved_ctx);
|
||||||
|
if (!ctx) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
saved_ctx->ctx = *ctx;
|
||||||
|
if (ctx->node) {
|
||||||
|
saved_ctx->node_destroy.notify = handle_ctx_node_destroy;
|
||||||
|
wl_signal_add(&ctx->node->events.destroy, &saved_ctx->node_destroy);
|
||||||
|
}
|
||||||
|
if (ctx->surface) {
|
||||||
|
saved_ctx->surface_destroy.notify = handle_ctx_surface_destroy;
|
||||||
|
wl_signal_add(&ctx->surface->events.destroy, &saved_ctx->surface_destroy);
|
||||||
|
}
|
||||||
|
if (ctx->view) {
|
||||||
|
saved_ctx->view_destroy.notify = handle_ctx_view_destroy;
|
||||||
|
wl_signal_add(&ctx->view->events.destroy, &saved_ctx->view_destroy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
update_pressed_surface(struct seat *seat, struct cursor_context *ctx)
|
update_pressed_surface(struct seat *seat, const struct cursor_context *ctx)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* In most cases, we don't want to leave one surface and enter
|
* In most cases, we don't want to leave one surface and enter
|
||||||
|
|
@ -454,10 +518,10 @@ update_pressed_surface(struct seat *seat, struct cursor_context *ctx)
|
||||||
if (!wlr_seat_pointer_has_grab(seat->seat)) {
|
if (!wlr_seat_pointer_has_grab(seat->seat)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (seat->pressed.surface && ctx->surface != seat->pressed.surface) {
|
if (seat->pressed.ctx.surface && ctx->surface != seat->pressed.ctx.surface) {
|
||||||
struct wlr_surface *toplevel = get_toplevel(ctx->surface);
|
struct wlr_surface *toplevel = get_toplevel(ctx->surface);
|
||||||
if (toplevel && toplevel == get_toplevel(seat->pressed.surface)) {
|
if (toplevel && toplevel == get_toplevel(seat->pressed.ctx.surface)) {
|
||||||
seat_set_pressed(seat, ctx);
|
cursor_context_save(&seat->pressed, ctx);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -487,7 +551,7 @@ cursor_update_common(struct server *server, struct cursor_context *ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: verify drag_icon logic */
|
/* TODO: verify drag_icon logic */
|
||||||
if (seat->pressed.surface && ctx->surface != seat->pressed.surface
|
if (seat->pressed.ctx.surface && ctx->surface != seat->pressed.ctx.surface
|
||||||
&& !update_pressed_surface(seat, ctx)
|
&& !update_pressed_surface(seat, ctx)
|
||||||
&& !seat->drag.active) {
|
&& !seat->drag.active) {
|
||||||
if (cursor_has_moved) {
|
if (cursor_has_moved) {
|
||||||
|
|
@ -499,7 +563,7 @@ cursor_update_common(struct server *server, struct cursor_context *ctx,
|
||||||
* if the cursor moves outside of the surface.
|
* if the cursor moves outside of the surface.
|
||||||
*/
|
*/
|
||||||
int lx, ly;
|
int lx, ly;
|
||||||
wlr_scene_node_coords(seat->pressed.node, &lx, &ly);
|
wlr_scene_node_coords(seat->pressed.ctx.node, &lx, &ly);
|
||||||
*sx = server->seat.cursor->x - lx;
|
*sx = server->seat.cursor->x - lx;
|
||||||
*sy = server->seat.cursor->y - ly;
|
*sy = server->seat.cursor->y - ly;
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -597,8 +661,8 @@ cursor_process_motion(struct server *server, uint32_t time, double *sx, double *
|
||||||
* moving/resizing the wrong view
|
* moving/resizing the wrong view
|
||||||
*/
|
*/
|
||||||
mousebind->pressed_in_context = false;
|
mousebind->pressed_in_context = false;
|
||||||
actions_run(seat->pressed.view, server,
|
actions_run(seat->pressed.ctx.view, server,
|
||||||
&mousebind->actions, &seat->pressed);
|
&mousebind->actions, &seat->pressed.ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1073,7 +1137,7 @@ cursor_process_button_press(struct seat *seat, uint32_t button, uint32_t time_ms
|
||||||
|
|
||||||
if (ctx.view || ctx.surface) {
|
if (ctx.view || ctx.surface) {
|
||||||
/* Store cursor context for later action processing */
|
/* Store cursor context for later action processing */
|
||||||
seat_set_pressed(seat, &ctx);
|
cursor_context_save(&seat->pressed, &ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (server->input_mode == LAB_INPUT_STATE_MENU) {
|
if (server->input_mode == LAB_INPUT_STATE_MENU) {
|
||||||
|
|
@ -1138,12 +1202,12 @@ cursor_process_button_release(struct seat *seat, uint32_t button,
|
||||||
{
|
{
|
||||||
struct server *server = seat->server;
|
struct server *server = seat->server;
|
||||||
struct cursor_context ctx = get_cursor_context(server);
|
struct cursor_context ctx = get_cursor_context(server);
|
||||||
struct wlr_surface *pressed_surface = seat->pressed.surface;
|
struct wlr_surface *pressed_surface = seat->pressed.ctx.surface;
|
||||||
|
|
||||||
/* Always notify button release event when it's not bound */
|
/* Always notify button release event when it's not bound */
|
||||||
const bool notify = !lab_set_contains(&seat->bound_buttons, button);
|
const bool notify = !lab_set_contains(&seat->bound_buttons, button);
|
||||||
|
|
||||||
seat_reset_pressed(seat);
|
cursor_context_save(&seat->pressed, NULL);
|
||||||
|
|
||||||
if (server->input_mode == LAB_INPUT_STATE_MENU) {
|
if (server->input_mode == LAB_INPUT_STATE_MENU) {
|
||||||
/* TODO: take into account overflow of time_msec */
|
/* TODO: take into account overflow of time_msec */
|
||||||
|
|
|
||||||
40
src/seat.c
40
src/seat.c
|
|
@ -848,46 +848,6 @@ seat_set_focus_layer(struct seat *seat, struct wlr_layer_surface_v1 *layer)
|
||||||
seat->focused_layer = layer;
|
seat->focused_layer = layer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
pressed_surface_destroy(struct wl_listener *listener, void *data)
|
|
||||||
{
|
|
||||||
struct seat *seat = wl_container_of(listener, seat,
|
|
||||||
pressed_surface_destroy);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Using data directly prevents 'unused variable'
|
|
||||||
* warning when compiling without asserts
|
|
||||||
*/
|
|
||||||
assert(data == seat->pressed.surface);
|
|
||||||
|
|
||||||
seat_reset_pressed(seat);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
seat_set_pressed(struct seat *seat, struct cursor_context *ctx)
|
|
||||||
{
|
|
||||||
assert(ctx);
|
|
||||||
assert(ctx->view || ctx->surface);
|
|
||||||
seat_reset_pressed(seat);
|
|
||||||
|
|
||||||
seat->pressed = *ctx;
|
|
||||||
|
|
||||||
if (ctx->surface) {
|
|
||||||
seat->pressed_surface_destroy.notify = pressed_surface_destroy;
|
|
||||||
wl_signal_add(&ctx->surface->events.destroy,
|
|
||||||
&seat->pressed_surface_destroy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
seat_reset_pressed(struct seat *seat)
|
|
||||||
{
|
|
||||||
if (seat->pressed.surface) {
|
|
||||||
wl_list_remove(&seat->pressed_surface_destroy.link);
|
|
||||||
}
|
|
||||||
seat->pressed = (struct cursor_context){0};
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
seat_output_layout_changed(struct seat *seat)
|
seat_output_layout_changed(struct seat *seat)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2612,10 +2612,6 @@ view_destroy(struct view *view)
|
||||||
server->session_lock_manager->last_active_view = NULL;
|
server->session_lock_manager->last_active_view = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (server->seat.pressed.view == view) {
|
|
||||||
seat_reset_pressed(&server->seat);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (view->tiled_region_evacuate) {
|
if (view->tiled_region_evacuate) {
|
||||||
zfree(view->tiled_region_evacuate);
|
zfree(view->tiled_region_evacuate);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -400,7 +400,7 @@ handle_request_move(struct wl_listener *listener, void *data)
|
||||||
* want.
|
* want.
|
||||||
*/
|
*/
|
||||||
struct view *view = wl_container_of(listener, view, request_move);
|
struct view *view = wl_container_of(listener, view, request_move);
|
||||||
if (view == view->server->seat.pressed.view) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -418,7 +418,7 @@ handle_request_resize(struct wl_listener *listener, void *data)
|
||||||
*/
|
*/
|
||||||
struct wlr_xdg_toplevel_resize_event *event = data;
|
struct wlr_xdg_toplevel_resize_event *event = data;
|
||||||
struct view *view = wl_container_of(listener, view, request_resize);
|
struct view *view = wl_container_of(listener, view, request_resize);
|
||||||
if (view == view->server->seat.pressed.view) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -289,7 +289,7 @@ handle_request_move(struct wl_listener *listener, void *data)
|
||||||
* want.
|
* want.
|
||||||
*/
|
*/
|
||||||
struct view *view = wl_container_of(listener, view, request_move);
|
struct view *view = wl_container_of(listener, view, request_move);
|
||||||
if (view == view->server->seat.pressed.view) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -307,7 +307,7 @@ handle_request_resize(struct wl_listener *listener, void *data)
|
||||||
*/
|
*/
|
||||||
struct wlr_xwayland_resize_event *event = data;
|
struct wlr_xwayland_resize_event *event = data;
|
||||||
struct view *view = wl_container_of(listener, view, request_resize);
|
struct view *view = wl_container_of(listener, view, request_resize);
|
||||||
if (view == view->server->seat.pressed.view) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue