Restore Drag mouse bindings and proper double click

Fixes #258 and #259

Reported-by: @ahmadraniri1994
Reported-by: @01micko
Suggested-by: bi4k8 <bi4k8@github>
This commit is contained in:
Consolatis 2022-02-27 20:36:49 +01:00 committed by Johan Malm
parent 97846ae45b
commit 64f7b9dd2b
2 changed files with 40 additions and 14 deletions

View file

@ -473,8 +473,9 @@ struct view *desktop_view_at_cursor(struct server *server);
* cursor_rebase - set cursor icon for and send motion-event to surface below it * cursor_rebase - set cursor icon for and send motion-event to surface below it
* @seat - current seat * @seat - current seat
* @time_msec - time now * @time_msec - time now
* @force - disable check for skipping already focused surface
*/ */
void cursor_rebase(struct seat *seat, uint32_t time_msec); void cursor_rebase(struct seat *seat, uint32_t time_msec, bool force);
/** /**
* cursor_set - set cursor icon * cursor_set - set cursor icon

View file

@ -24,7 +24,7 @@ is_surface(enum ssd_part_type view_area)
} }
void void
cursor_rebase(struct seat *seat, uint32_t time_msec) cursor_rebase(struct seat *seat, uint32_t time_msec, bool force)
{ {
double sx, sy; double sx, sy;
struct wlr_scene_node *node; struct wlr_scene_node *node;
@ -38,6 +38,20 @@ cursor_rebase(struct seat *seat, uint32_t time_msec)
} }
if (surface) { if (surface) {
if (!force && surface == seat->seat->pointer_state.focused_surface) {
/*
* Usually we prevent re-entering an already focued surface
* because it sends useless leave and enter events.
*
* They may also seriously confuse clients if sent between
* connected events like a double click (#258) or fast scroll
* events caused by a touchpad (#225).
*
* If we just want to update the cursor image though
* the @force argument may be used to allow re-entering.
*/
return;
}
wlr_seat_pointer_notify_clear_focus(seat->seat); wlr_seat_pointer_notify_clear_focus(seat->seat);
wlr_seat_pointer_notify_enter(seat->seat, surface, sx, sy); wlr_seat_pointer_notify_enter(seat->seat, surface, sx, sy);
wlr_seat_pointer_notify_motion(seat->seat, time_msec, sx, sy); wlr_seat_pointer_notify_motion(seat->seat, time_msec, sx, sy);
@ -195,15 +209,6 @@ process_cursor_motion(struct server *server, uint32_t time)
} else if (server->input_mode == LAB_INPUT_STATE_RESIZE) { } else if (server->input_mode == LAB_INPUT_STATE_RESIZE) {
process_cursor_resize(server, time); process_cursor_resize(server, time);
return; return;
} else if (server->seat.active_view && !server->seat.drag_icon) {
/* Button has been pressed while over a view surface */
struct view *view = server->seat.active_view;
double sx = server->seat.cursor->x - view->x;
double sy = server->seat.cursor->y - view->y;
sx = sx < 0 ? 0 : (sx > view->w ? view->w : sx);
sy = sy < 0 ? 0 : (sy > view->h ? view->h : sy);
wlr_seat_pointer_notify_motion(server->seat.seat, time, sx, sy);
return;
} }
/* Otherwise, find view under the pointer and send the event along */ /* Otherwise, find view under the pointer and send the event along */
@ -292,7 +297,21 @@ process_cursor_motion(struct server *server, uint32_t time)
hover->node = NULL; hover->node = NULL;
} }
if (surface && if (server->seat.active_view && !server->seat.drag_icon) {
/*
* Button has been pressed while over a view surface
* and is still held down. Just send the adjusted motion
* events to the focused surface so we can keep scrolling
* or selecting text even if the cursor moves outside of
* the surface.
*/
view = server->seat.active_view;
double sx = server->seat.cursor->x - view->x;
double sy = server->seat.cursor->y - view->y;
sx = sx < 0 ? 0 : (sx > view->w ? view->w : sx);
sy = sy < 0 ? 0 : (sy > view->h ? view->h : sy);
wlr_seat_pointer_notify_motion(server->seat.seat, time, sx, sy);
} else if (surface &&
!input_inhibit_blocks_surface(&server->seat, surface->resource)) { !input_inhibit_blocks_surface(&server->seat, surface->resource)) {
bool focus_changed = bool focus_changed =
wlr_seat->pointer_state.focused_surface != surface; wlr_seat->pointer_state.focused_surface != surface;
@ -316,6 +335,9 @@ process_cursor_motion(struct server *server, uint32_t time)
/* /*
* Clear pointer focus so future button events and such are not * Clear pointer focus so future button events and such are not
* sent to the last client to have the cursor over it. * sent to the last client to have the cursor over it.
*
* Except if we started pressing a button on the last client and
* are not currently in drag and drop mode.
*/ */
wlr_seat_pointer_clear_focus(wlr_seat); wlr_seat_pointer_clear_focus(wlr_seat);
} }
@ -332,7 +354,8 @@ cursor_update_focus(struct server *server)
{ {
struct timespec now; struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now); clock_gettime(CLOCK_MONOTONIC, &now);
cursor_rebase(&server->seat, msec(&now)); /* Focus surface under cursor if it isn't already focused */
cursor_rebase(&server->seat, msec(&now), false);
} }
void void
@ -693,7 +716,9 @@ cursor_button(struct wl_listener *listener, void *data)
server->input_mode = LAB_INPUT_STATE_PASSTHROUGH; server->input_mode = LAB_INPUT_STATE_PASSTHROUGH;
server->grabbed_view = NULL; server->grabbed_view = NULL;
} }
cursor_rebase(&server->seat, event->time_msec);
/* Focus surface under cursor and force updating the cursor icon */
cursor_rebase(&server->seat, event->time_msec, true);
return; return;
} }
goto mousebindings; goto mousebindings;