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.
master
Isaac Freund 5 years ago committed by Simon Ser
parent 7c309ba4d3
commit 1282c3b12f

@ -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…
Cancel
Save