mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-12-22 18:09:49 +01:00
Send pointer enter/leave on capability change
This is more correct according to the protocol and fixes issues with clients that wait for an enter event before processing pointer events.
This commit is contained in:
parent
7c309ba4d3
commit
1282c3b12f
3 changed files with 54 additions and 10 deletions
|
@ -11,6 +11,8 @@ extern const struct wlr_touch_grab_interface default_touch_grab_impl;
|
|||
void seat_client_create_pointer(struct wlr_seat_client *seat_client,
|
||||
uint32_t version, uint32_t id);
|
||||
void seat_client_destroy_pointer(struct wl_resource *resource);
|
||||
void seat_client_send_pointer_leave_raw(struct wlr_seat_client *seat_client,
|
||||
struct wlr_surface *surface);
|
||||
|
||||
void seat_client_create_keyboard(struct wlr_seat_client *seat_client,
|
||||
uint32_t version, uint32_t id);
|
||||
|
|
|
@ -316,6 +316,18 @@ void wlr_seat_set_capabilities(struct wlr_seat *wlr_seat,
|
|||
wl_list_for_each(client, &wlr_seat->clients, link) {
|
||||
// Make resources inert if necessary
|
||||
if ((capabilities & WL_SEAT_CAPABILITY_POINTER) == 0) {
|
||||
struct wlr_seat_client *focused_client =
|
||||
wlr_seat->pointer_state.focused_client;
|
||||
struct wlr_surface *focused_surface =
|
||||
wlr_seat->pointer_state.focused_surface;
|
||||
|
||||
if (focused_client != NULL && focused_surface != NULL) {
|
||||
seat_client_send_pointer_leave_raw(focused_client, focused_surface);
|
||||
}
|
||||
|
||||
// Note: we don't set focused client/surface to NULL since we need
|
||||
// them to send the enter event if the pointer is recreated
|
||||
|
||||
struct wl_resource *resource, *tmp;
|
||||
wl_resource_for_each_safe(resource, tmp, &client->pointers) {
|
||||
seat_client_destroy_pointer(resource);
|
||||
|
|
|
@ -129,6 +129,20 @@ static void seat_pointer_handle_surface_destroy(struct wl_listener *listener,
|
|||
wlr_seat_pointer_clear_focus(state->seat);
|
||||
}
|
||||
|
||||
void seat_client_send_pointer_leave_raw(struct wlr_seat_client *seat_client,
|
||||
struct wlr_surface *surface) {
|
||||
uint32_t serial = wlr_seat_client_next_serial(seat_client);
|
||||
struct wl_resource *resource;
|
||||
wl_resource_for_each(resource, &seat_client->pointers) {
|
||||
if (wlr_seat_client_from_pointer_resource(resource) == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
wl_pointer_send_leave(resource, serial, surface->resource);
|
||||
pointer_send_frame(resource);
|
||||
}
|
||||
}
|
||||
|
||||
void wlr_seat_pointer_enter(struct wlr_seat *wlr_seat,
|
||||
struct wlr_surface *surface, double sx, double sy) {
|
||||
if (wlr_seat->pointer_state.focused_surface == surface) {
|
||||
|
@ -149,16 +163,7 @@ void wlr_seat_pointer_enter(struct wlr_seat *wlr_seat,
|
|||
|
||||
// leave the previously entered surface
|
||||
if (focused_client != NULL && focused_surface != NULL) {
|
||||
uint32_t serial = wlr_seat_client_next_serial(focused_client);
|
||||
struct wl_resource *resource;
|
||||
wl_resource_for_each(resource, &focused_client->pointers) {
|
||||
if (wlr_seat_client_from_pointer_resource(resource) == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
wl_pointer_send_leave(resource, serial, focused_surface->resource);
|
||||
pointer_send_frame(resource);
|
||||
}
|
||||
seat_client_send_pointer_leave_raw(focused_client, focused_surface);
|
||||
}
|
||||
|
||||
// enter the current surface
|
||||
|
@ -404,6 +409,31 @@ void seat_client_create_pointer(struct wlr_seat_client *seat_client,
|
|||
wl_resource_set_implementation(resource, &pointer_impl, seat_client,
|
||||
&pointer_handle_resource_destroy);
|
||||
wl_list_insert(&seat_client->pointers, wl_resource_get_link(resource));
|
||||
|
||||
struct wlr_seat_client *focused_client =
|
||||
seat_client->seat->pointer_state.focused_client;
|
||||
struct wlr_surface *focused_surface =
|
||||
seat_client->seat->pointer_state.focused_surface;
|
||||
|
||||
// Send an enter event if there is a focused client/surface stored
|
||||
if (focused_client != NULL && focused_surface != NULL) {
|
||||
double sx = seat_client->seat->pointer_state.sx;
|
||||
double sy = seat_client->seat->pointer_state.sy;
|
||||
|
||||
uint32_t serial = wlr_seat_client_next_serial(focused_client);
|
||||
struct wl_resource *resource;
|
||||
wl_resource_for_each(resource, &focused_client->pointers) {
|
||||
if (wl_resource_get_id(resource) == id) {
|
||||
if (wlr_seat_client_from_pointer_resource(resource) == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
wl_pointer_send_enter(resource, serial, focused_surface->resource,
|
||||
wl_fixed_from_double(sx), wl_fixed_from_double(sy));
|
||||
pointer_send_frame(resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void seat_client_destroy_pointer(struct wl_resource *resource) {
|
||||
|
|
Loading…
Reference in a new issue