mirror of
https://github.com/labwc/labwc.git
synced 2026-04-10 08:21:07 -04:00
cursor: Prevent application crash on drag-and-drop
Wlroots resets the focused surface on Drag and Drop. Before this patch we tried to enforce a client side cursor image update by forcefully clearing the focus which, even though `wlr_seat->pointer_state.focused_surface` was `NULL`, was sent to the drag source. After the clear we are sending an enter event for the surface under the cursor and if this surface was the drag source itself it was heavily confused. This caused all kinds of weird behavior from spawning new drag icons constantly to outright crashing the application. Reported-by: @Flrian Bisected-by: @Flrian
This commit is contained in:
parent
2c83a5fcb8
commit
3076380aca
1 changed files with 41 additions and 31 deletions
72
src/cursor.c
72
src/cursor.c
|
|
@ -345,7 +345,6 @@ cursor_update_common(struct server *server, struct cursor_context *ctx,
|
|||
return;
|
||||
}
|
||||
|
||||
/* TODO: verify drag_icon logic */
|
||||
if (seat->pressed.surface && ctx->surface != seat->pressed.surface
|
||||
&& !update_pressed_surface(seat, ctx)
|
||||
&& !seat->drag_icon) {
|
||||
|
|
@ -362,36 +361,7 @@ cursor_update_common(struct server *server, struct cursor_context *ctx,
|
|||
return;
|
||||
}
|
||||
|
||||
if (ctx->surface && !input_inhibit_blocks_surface(seat,
|
||||
ctx->surface->resource)) {
|
||||
/*
|
||||
* Cursor is over an input-enabled client surface. The
|
||||
* cursor image will be set by request_cursor_notify()
|
||||
* in response to the enter event.
|
||||
*/
|
||||
if (ctx->surface != wlr_seat->pointer_state.focused_surface
|
||||
|| seat->server_cursor != LAB_CURSOR_CLIENT) {
|
||||
/*
|
||||
* Enter the surface if necessary. Usually we
|
||||
* prevent re-entering an already focused
|
||||
* surface, because the extra leave and enter
|
||||
* events can confuse clients (e.g. break
|
||||
* double-click detection).
|
||||
*
|
||||
* We do however send a leave/enter event pair
|
||||
* if a server-side cursor was set and we need
|
||||
* to trigger a cursor image update.
|
||||
*/
|
||||
wlr_seat_pointer_notify_clear_focus(wlr_seat);
|
||||
wlr_seat_pointer_notify_enter(wlr_seat, ctx->surface,
|
||||
ctx->sx, ctx->sy);
|
||||
seat->server_cursor = LAB_CURSOR_CLIENT;
|
||||
}
|
||||
if (cursor_has_moved) {
|
||||
wlr_seat_pointer_notify_motion(wlr_seat, time_msec,
|
||||
ctx->sx, ctx->sy);
|
||||
}
|
||||
} else {
|
||||
if (!ctx->surface) {
|
||||
/*
|
||||
* Cursor is over a server (labwc) surface. Clear focus
|
||||
* from the focused client (if any, no-op otherwise) and
|
||||
|
|
@ -402,6 +372,46 @@ cursor_update_common(struct server *server, struct cursor_context *ctx,
|
|||
if (!seat->drag_icon) {
|
||||
cursor_set(seat, cursor_get_from_ssd(ctx->type));
|
||||
}
|
||||
} else if (input_inhibit_blocks_surface(seat, ctx->surface->resource)) {
|
||||
/*
|
||||
* Cursor is over an inhibited surface
|
||||
*
|
||||
* TODO: we might want to check for locked surface as well here
|
||||
*/
|
||||
return;
|
||||
} else {
|
||||
/*
|
||||
* Cursor is over an input-enabled client surface. The
|
||||
* cursor image will be set by request_cursor_notify()
|
||||
* in response to the enter event.
|
||||
*/
|
||||
|
||||
if (ctx->surface == wlr_seat->pointer_state.focused_surface
|
||||
&& seat->server_cursor != LAB_CURSOR_CLIENT) {
|
||||
/*
|
||||
* Leave and enter the surface if necessary.
|
||||
* Usually we prevent re-entering an already
|
||||
* focused surface, because the extra leave
|
||||
* and enter events can confuse or even crash
|
||||
* clients (e.g. break double-click detection,
|
||||
* crash on touchpad scrolling or drag-and-drop).
|
||||
*
|
||||
* We do however send a leave/enter event pair
|
||||
* if a server-side cursor was set and we need
|
||||
* to trigger a client cursor image update.
|
||||
*/
|
||||
wlr_seat_pointer_notify_clear_focus(wlr_seat);
|
||||
}
|
||||
|
||||
/* Enter the surface if necessary, no-op otherwise */
|
||||
wlr_seat_pointer_notify_enter(
|
||||
wlr_seat, ctx->surface, ctx->sx, ctx->sy);
|
||||
seat->server_cursor = LAB_CURSOR_CLIENT;
|
||||
|
||||
if (cursor_has_moved) {
|
||||
wlr_seat_pointer_notify_motion(
|
||||
wlr_seat, time_msec, ctx->sx, ctx->sy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue