mirror of
https://github.com/labwc/labwc.git
synced 2025-11-04 13:30:07 -05:00
cursor: Fix out-of-surface movement for unmanaged surfaces
This commit is contained in:
parent
f7b1bc1de8
commit
7c6c018f43
6 changed files with 57 additions and 36 deletions
|
|
@ -559,6 +559,7 @@ void seat_finish(struct server *server);
|
|||
void seat_reconfigure(struct server *server);
|
||||
void seat_focus_surface(struct seat *seat, struct wlr_surface *surface);
|
||||
void seat_set_focus_layer(struct seat *seat, struct wlr_layer_surface_v1 *layer);
|
||||
void seat_reset_pressed(struct seat *seat);
|
||||
|
||||
void interactive_begin(struct view *view, enum input_mode mode,
|
||||
uint32_t edges);
|
||||
|
|
|
|||
72
src/cursor.c
72
src/cursor.c
|
|
@ -196,6 +196,42 @@ input_inhibit_blocks_surface(struct seat *seat, struct wl_resource *resource)
|
|||
&& inhibiting_client != wl_resource_get_client(resource);
|
||||
}
|
||||
|
||||
static void
|
||||
process_cursor_motion_out_of_surface(struct server *server, uint32_t time)
|
||||
{
|
||||
struct view *view = server->seat.pressed.view;
|
||||
struct wlr_scene_node *node = server->seat.pressed.node;
|
||||
struct wlr_surface *surface = server->seat.pressed.surface;
|
||||
assert(surface);
|
||||
int lx, ly;
|
||||
|
||||
if (view) {
|
||||
lx = view->x;
|
||||
ly = view->y;
|
||||
} else if (node && wlr_surface_is_layer_surface(surface)) {
|
||||
wlr_scene_node_coords(node, &lx, &ly);
|
||||
#if HAVE_XWAYLAND
|
||||
} else if (node && node->parent == server->unmanaged_tree) {
|
||||
wlr_scene_node_coords(node, &lx, &ly);
|
||||
#endif
|
||||
} else {
|
||||
wlr_log(WLR_ERROR, "Can't detect surface for out-of-surface movement");
|
||||
return;
|
||||
}
|
||||
|
||||
double sx = server->seat.cursor->x - lx;
|
||||
double sy = server->seat.cursor->y - ly;
|
||||
/* Take into account invisible xdg-shell CSD borders */
|
||||
if (view && view->type == LAB_XDG_SHELL_VIEW && view->xdg_surface) {
|
||||
struct wlr_box geo;
|
||||
wlr_xdg_surface_get_geometry(view->xdg_surface, &geo);
|
||||
sx += geo.x;
|
||||
sy += geo.y;
|
||||
}
|
||||
|
||||
wlr_seat_pointer_notify_motion(server->seat.seat, time, sx, sy);
|
||||
}
|
||||
|
||||
static void
|
||||
process_cursor_motion(struct server *server, uint32_t time)
|
||||
{
|
||||
|
|
@ -289,29 +325,7 @@ process_cursor_motion(struct server *server, uint32_t time)
|
|||
* or selecting text even if the cursor moves outside of
|
||||
* the surface.
|
||||
*/
|
||||
int lx, ly;
|
||||
view = server->seat.pressed.view;
|
||||
if (view) {
|
||||
lx = view->x;
|
||||
ly = view->y;
|
||||
} else if (wlr_surface_is_layer_surface(server->seat.pressed.surface)) {
|
||||
wlr_scene_node_coords(server->seat.pressed.node, &lx, &ly);
|
||||
} else {
|
||||
wlr_log(WLR_ERROR, "Can't detect surface for out-of-surface movement");
|
||||
return;
|
||||
}
|
||||
sx = server->seat.cursor->x - lx;
|
||||
sy = server->seat.cursor->y - ly;
|
||||
|
||||
/* Take into account invisible xdg-shell CSD borders */
|
||||
if (view && view->type == LAB_XDG_SHELL_VIEW
|
||||
&& view->xdg_surface) {
|
||||
struct wlr_box geo;
|
||||
wlr_xdg_surface_get_geometry(view->xdg_surface, &geo);
|
||||
sx += geo.x;
|
||||
sy += geo.y;
|
||||
}
|
||||
wlr_seat_pointer_notify_motion(server->seat.seat, time, sx, sy);
|
||||
process_cursor_motion_out_of_surface(server, time);
|
||||
} else if (surface && !input_inhibit_blocks_surface(
|
||||
&server->seat, surface->resource)) {
|
||||
bool focus_changed =
|
||||
|
|
@ -364,9 +378,7 @@ start_drag(struct wl_listener *listener, void *data)
|
|||
{
|
||||
struct seat *seat = wl_container_of(listener, seat, start_drag);
|
||||
struct wlr_drag *wlr_drag = data;
|
||||
seat->pressed.view = NULL;
|
||||
seat->pressed.node = NULL;
|
||||
seat->pressed.surface = NULL;
|
||||
seat_reset_pressed(seat);
|
||||
seat->drag_icon = wlr_drag->icon;
|
||||
if (!seat->drag_icon) {
|
||||
wlr_log(WLR_ERROR,
|
||||
|
|
@ -713,19 +725,17 @@ cursor_button(struct wl_listener *listener, void *data)
|
|||
|
||||
/* handle _release_ */
|
||||
if (event->state == WLR_BUTTON_RELEASED) {
|
||||
seat->pressed.view = NULL;
|
||||
seat->pressed.node = NULL;
|
||||
if (seat->pressed.surface && seat->pressed.surface != surface) {
|
||||
struct wlr_surface *pressed_surface = seat->pressed.surface;
|
||||
seat_reset_pressed(seat);
|
||||
if (pressed_surface && pressed_surface != surface) {
|
||||
/*
|
||||
* Button released but originally pressed over a different surface.
|
||||
* Just send the release event to the still focused surface.
|
||||
*/
|
||||
wlr_seat_pointer_notify_button(seat->seat, event->time_msec,
|
||||
event->button, event->state);
|
||||
seat->pressed.surface = NULL;
|
||||
return;
|
||||
}
|
||||
seat->pressed.surface = NULL;
|
||||
if (server->input_mode == LAB_INPUT_STATE_MENU) {
|
||||
if (close_menu) {
|
||||
menu_close_root(server);
|
||||
|
|
|
|||
|
|
@ -146,8 +146,7 @@ unmap(struct lab_layer_surface *layer)
|
|||
seat_set_focus_layer(seat, NULL);
|
||||
}
|
||||
if (seat->pressed.surface == layer->scene_layer_surface->layer_surface->surface) {
|
||||
seat->pressed.node = NULL;
|
||||
seat->pressed.surface = NULL;
|
||||
seat_reset_pressed(seat);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -369,3 +369,11 @@ seat_set_focus_layer(struct seat *seat, struct wlr_layer_surface_v1 *layer)
|
|||
seat->focused_layer = layer;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
seat_reset_pressed(struct seat *seat)
|
||||
{
|
||||
seat->pressed.view = NULL;
|
||||
seat->pressed.node = NULL;
|
||||
seat->pressed.surface = NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -813,8 +813,7 @@ view_destroy(struct view *view)
|
|||
|
||||
if (server->seat.pressed.view == view) {
|
||||
/* Mouse was pressed on surface and is still pressed */
|
||||
server->seat.pressed.view = NULL;
|
||||
server->seat.pressed.surface = NULL;
|
||||
seat_reset_pressed(&server->seat);
|
||||
}
|
||||
|
||||
if (server->focused_view == view) {
|
||||
|
|
|
|||
|
|
@ -57,6 +57,8 @@ unmanaged_handle_unmap(struct wl_listener *listener, void *data)
|
|||
struct xwayland_unmanaged *unmanaged =
|
||||
wl_container_of(listener, unmanaged, unmap);
|
||||
struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface;
|
||||
struct seat *seat = &unmanaged->server->seat;
|
||||
|
||||
wl_list_remove(&unmanaged->link);
|
||||
wl_list_remove(&unmanaged->set_geometry.link);
|
||||
|
||||
|
|
@ -64,9 +66,11 @@ unmanaged_handle_unmap(struct wl_listener *listener, void *data)
|
|||
* Mark the node as gone so a racing configure event
|
||||
* won't try to reposition the node while unmapped.
|
||||
*/
|
||||
if (unmanaged->node && seat->pressed.node == unmanaged->node) {
|
||||
seat_reset_pressed(seat);
|
||||
}
|
||||
unmanaged->node = NULL;
|
||||
|
||||
struct seat *seat = &unmanaged->server->seat;
|
||||
if (seat->seat->keyboard_state.focused_surface == xsurface->surface) {
|
||||
/*
|
||||
* Try to focus on parent surface
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue