pointer/keyboard: Make sure not to get stale on client resources as well
Both the pointer/keyboard resource and surface resource can be destroyed at any point in the destruction process, so we need to have destroy listeners on both. To make the code easier to follow, rename ->focus to ->focus_surface at the same time, and rearrange the code so that the two of them are always grouped together.
This commit is contained in:
parent
414259a7f8
commit
a364c2a96b
@ -225,13 +225,25 @@ err_keymap_str:
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
release_focus (MetaWaylandKeyboard *keyboard)
|
||||
{
|
||||
keyboard->focus_resource = NULL;
|
||||
keyboard->focus_surface = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
keyboard_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandKeyboard *keyboard = wl_container_of (listener, keyboard, focus_surface_listener);
|
||||
release_focus (keyboard);
|
||||
}
|
||||
|
||||
keyboard->focus_resource = NULL;
|
||||
keyboard->focus = NULL;
|
||||
static void
|
||||
keyboard_handle_focus_resource_destroy (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandKeyboard *keyboard = wl_container_of (listener, keyboard, focus_resource_listener);
|
||||
release_focus (keyboard);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -287,10 +299,9 @@ default_grab_modifiers (MetaWaylandKeyboardGrab *grab, uint32_t serial,
|
||||
wl_keyboard_send_modifiers (resource, serial, mods_depressed,
|
||||
mods_latched, mods_locked, group);
|
||||
|
||||
if (pointer && pointer->focus && pointer->focus != keyboard->focus)
|
||||
if (pointer && pointer->focus_surface && pointer->focus_surface != keyboard->focus_surface)
|
||||
{
|
||||
pr = find_resource_for_surface (&keyboard->resource_list,
|
||||
pointer->focus);
|
||||
pr = find_resource_for_surface (&keyboard->resource_list, pointer->focus_surface);
|
||||
if (pr)
|
||||
{
|
||||
wl_keyboard_send_modifiers (pr, serial,
|
||||
@ -342,7 +353,10 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
|
||||
|
||||
wl_list_init (&keyboard->resource_list);
|
||||
wl_array_init (&keyboard->keys);
|
||||
|
||||
keyboard->focus_surface_listener.notify = keyboard_handle_focus_surface_destroy;
|
||||
keyboard->focus_resource_listener.notify = keyboard_handle_focus_resource_destroy;
|
||||
|
||||
keyboard->default_grab.interface = &default_keyboard_grab_interface;
|
||||
keyboard->default_grab.keyboard = keyboard;
|
||||
keyboard->grab = &keyboard->default_grab;
|
||||
@ -513,19 +527,27 @@ meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard,
|
||||
struct wl_resource *resource;
|
||||
uint32_t serial;
|
||||
|
||||
if (keyboard->focus == surface && keyboard->focus_resource != NULL)
|
||||
if (keyboard->focus_surface == surface && keyboard->focus_resource != NULL)
|
||||
return;
|
||||
|
||||
resource = keyboard->focus_resource;
|
||||
if (keyboard->focus_resource && keyboard->focus->resource)
|
||||
if (resource)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
serial = wl_display_next_serial (display);
|
||||
wl_keyboard_send_leave (resource, serial, keyboard->focus->resource);
|
||||
if (keyboard->focus_surface->resource)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
serial = wl_display_next_serial (display);
|
||||
wl_keyboard_send_leave (resource, serial, keyboard->focus_surface->resource);
|
||||
|
||||
meta_wayland_surface_focused_unset (keyboard->focus_surface);
|
||||
}
|
||||
|
||||
wl_list_remove (&keyboard->focus_resource_listener.link);
|
||||
wl_list_remove (&keyboard->focus_surface_listener.link);
|
||||
|
||||
meta_wayland_surface_focused_unset (keyboard->focus);
|
||||
keyboard->focus_resource = NULL;
|
||||
keyboard->focus_surface = NULL;
|
||||
}
|
||||
|
||||
resource = find_resource_for_surface (&keyboard->resource_list, surface);
|
||||
@ -558,14 +580,17 @@ meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard,
|
||||
wl_keyboard_send_enter (resource, serial, surface->resource,
|
||||
&keyboard->keys);
|
||||
}
|
||||
wl_resource_add_destroy_listener (surface->resource, &keyboard->focus_surface_listener);
|
||||
keyboard->focus_serial = serial;
|
||||
|
||||
meta_wayland_surface_focused_set (surface);
|
||||
}
|
||||
|
||||
keyboard->focus_resource = resource;
|
||||
keyboard->focus = surface;
|
||||
keyboard->focus_resource = resource;
|
||||
keyboard->focus_surface = surface;
|
||||
|
||||
wl_resource_add_destroy_listener (keyboard->focus_resource, &keyboard->focus_resource_listener);
|
||||
wl_resource_add_destroy_listener (keyboard->focus_surface->resource, &keyboard->focus_surface_listener);
|
||||
|
||||
keyboard->focus_serial = serial;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -591,8 +616,6 @@ meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard)
|
||||
xkb_context_unref (keyboard->xkb_context);
|
||||
|
||||
/* XXX: What about keyboard->resource_list? */
|
||||
if (keyboard->focus_resource)
|
||||
wl_list_remove (&keyboard->focus_surface_listener.link);
|
||||
wl_array_release (&keyboard->keys);
|
||||
}
|
||||
|
||||
@ -611,7 +634,7 @@ meta_wayland_keyboard_begin_modal (MetaWaylandKeyboard *keyboard,
|
||||
if (keyboard->grab != &keyboard->default_grab)
|
||||
return FALSE;
|
||||
|
||||
if (keyboard->focus)
|
||||
if (keyboard->focus_surface)
|
||||
{
|
||||
/* Fake key release events for the focused app */
|
||||
serial = wl_display_next_serial (keyboard->display);
|
||||
@ -653,7 +676,7 @@ meta_wayland_keyboard_end_modal (MetaWaylandKeyboard *keyboard,
|
||||
meta_wayland_keyboard_end_grab (keyboard);
|
||||
g_slice_free (MetaWaylandKeyboardGrab, grab);
|
||||
|
||||
if (keyboard->focus)
|
||||
if (keyboard->focus_surface)
|
||||
{
|
||||
/* Fake key press events for the focused app */
|
||||
serial = wl_display_next_serial (keyboard->display);
|
||||
|
@ -92,9 +92,11 @@ typedef struct
|
||||
struct _MetaWaylandKeyboard
|
||||
{
|
||||
struct wl_list resource_list;
|
||||
MetaWaylandSurface *focus;
|
||||
struct wl_resource *focus_resource;
|
||||
|
||||
MetaWaylandSurface *focus_surface;
|
||||
struct wl_listener focus_surface_listener;
|
||||
struct wl_resource *focus_resource;
|
||||
struct wl_listener focus_resource_listener;
|
||||
uint32_t focus_serial;
|
||||
|
||||
MetaWaylandKeyboardGrab *grab;
|
||||
|
@ -63,13 +63,25 @@ meta_wayland_pointer_get_seat (MetaWaylandPointer *pointer)
|
||||
return seat;
|
||||
}
|
||||
|
||||
static void
|
||||
release_focus (MetaWaylandPointer *pointer)
|
||||
{
|
||||
pointer->focus_resource = NULL;
|
||||
pointer->focus_surface = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandPointer *pointer = wl_container_of (listener, pointer, focus_surface_listener);
|
||||
release_focus (pointer);
|
||||
}
|
||||
|
||||
pointer->focus_resource = NULL;
|
||||
pointer->focus = NULL;
|
||||
static void
|
||||
pointer_handle_focus_resource_destroy (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandPointer *pointer = wl_container_of (listener, pointer, focus_resource_listener);
|
||||
release_focus (pointer);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -97,7 +109,7 @@ default_grab_motion (MetaWaylandPointerGrab *grab,
|
||||
wl_fixed_t sx, sy;
|
||||
|
||||
meta_wayland_pointer_get_relative_coordinates (grab->pointer,
|
||||
grab->pointer->focus,
|
||||
grab->pointer->focus_surface,
|
||||
&sx, &sy);
|
||||
wl_pointer_send_motion (resource, clutter_event_get_time (event), sx, sy);
|
||||
}
|
||||
@ -265,7 +277,10 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer)
|
||||
|
||||
memset (pointer, 0, sizeof *pointer);
|
||||
wl_list_init (&pointer->resource_list);
|
||||
|
||||
pointer->focus_surface_listener.notify = pointer_handle_focus_surface_destroy;
|
||||
pointer->focus_resource_listener.notify = pointer_handle_focus_resource_destroy;
|
||||
|
||||
pointer->default_grab.interface = &default_pointer_grab_interface;
|
||||
pointer->default_grab.pointer = pointer;
|
||||
pointer->grab = &pointer->default_grab;
|
||||
@ -292,12 +307,7 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer)
|
||||
void
|
||||
meta_wayland_pointer_release (MetaWaylandPointer *pointer)
|
||||
{
|
||||
/* XXX: What about pointer->resource_list? */
|
||||
if (pointer->focus_resource)
|
||||
wl_list_remove (&pointer->focus_surface_listener.link);
|
||||
|
||||
pointer->focus = NULL;
|
||||
pointer->focus_resource = NULL;
|
||||
release_focus (pointer);
|
||||
}
|
||||
|
||||
static struct wl_resource *
|
||||
@ -323,21 +333,25 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
|
||||
struct wl_resource *resource, *kr;
|
||||
uint32_t serial;
|
||||
|
||||
if (pointer->focus == surface && pointer->focus_resource != NULL)
|
||||
if (pointer->focus_surface == surface && pointer->focus_resource != NULL)
|
||||
return;
|
||||
|
||||
resource = pointer->focus_resource;
|
||||
if (resource)
|
||||
{
|
||||
if (pointer->focus->resource)
|
||||
if (pointer->focus_surface->resource)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
serial = wl_display_next_serial (display);
|
||||
wl_pointer_send_leave (resource, serial, pointer->focus->resource);
|
||||
wl_pointer_send_leave (resource, serial, pointer->focus_surface->resource);
|
||||
}
|
||||
|
||||
wl_list_remove (&pointer->focus_surface_listener.link);
|
||||
wl_list_remove (&pointer->focus_resource_listener.link);
|
||||
|
||||
pointer->focus_surface = NULL;
|
||||
pointer->focus_resource = NULL;
|
||||
}
|
||||
|
||||
resource = find_resource_for_surface (&pointer->resource_list, surface);
|
||||
@ -370,12 +384,15 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
|
||||
wl_fixed_to_int (pointer->x),
|
||||
wl_fixed_to_int (pointer->y));
|
||||
wl_pointer_send_enter (resource, serial, surface->resource, sx, sy);
|
||||
wl_resource_add_destroy_listener (surface->resource, &pointer->focus_surface_listener);
|
||||
|
||||
pointer->focus_resource = resource;
|
||||
pointer->focus_surface = surface;
|
||||
|
||||
wl_resource_add_destroy_listener (pointer->focus_resource, &pointer->focus_resource_listener);
|
||||
wl_resource_add_destroy_listener (pointer->focus_surface->resource, &pointer->focus_surface_listener);
|
||||
|
||||
pointer->focus_serial = serial;
|
||||
}
|
||||
|
||||
pointer->focus_resource = resource;
|
||||
pointer->focus = surface;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -46,9 +46,11 @@ struct _MetaWaylandPointerGrab
|
||||
struct _MetaWaylandPointer
|
||||
{
|
||||
struct wl_list resource_list;
|
||||
MetaWaylandSurface *focus;
|
||||
struct wl_resource *focus_resource;
|
||||
|
||||
MetaWaylandSurface *focus_surface;
|
||||
struct wl_listener focus_surface_listener;
|
||||
struct wl_resource *focus_resource;
|
||||
struct wl_listener focus_resource_listener;
|
||||
guint32 focus_serial;
|
||||
guint32 click_serial;
|
||||
|
||||
|
@ -95,9 +95,9 @@ pointer_set_cursor (struct wl_client *client,
|
||||
|
||||
surface = (surface_resource ? wl_resource_get_user_data (surface_resource) : NULL);
|
||||
|
||||
if (seat->pointer.focus == NULL)
|
||||
if (seat->pointer.focus_surface == NULL)
|
||||
return;
|
||||
if (wl_resource_get_client (seat->pointer.focus->resource) != client)
|
||||
if (wl_resource_get_client (seat->pointer.focus_surface->resource) != client)
|
||||
return;
|
||||
if (seat->pointer.focus_serial - serial > G_MAXUINT32 / 2)
|
||||
return;
|
||||
@ -125,9 +125,9 @@ seat_get_pointer (struct wl_client *client,
|
||||
wl_resource_set_implementation (cr, &pointer_interface, seat, unbind_resource);
|
||||
wl_list_insert (&seat->pointer.resource_list, wl_resource_get_link (cr));
|
||||
|
||||
if (seat->pointer.focus &&
|
||||
wl_resource_get_client (seat->pointer.focus->resource) == client)
|
||||
meta_wayland_pointer_set_focus (&seat->pointer, seat->pointer.focus);
|
||||
if (seat->pointer.focus_surface &&
|
||||
wl_resource_get_client (seat->pointer.focus_surface->resource) == client)
|
||||
meta_wayland_pointer_set_focus (&seat->pointer, seat->pointer.focus_surface);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -148,10 +148,10 @@ seat_get_keyboard (struct wl_client *client,
|
||||
seat->keyboard.xkb_info.keymap_fd,
|
||||
seat->keyboard.xkb_info.keymap_size);
|
||||
|
||||
if (seat->keyboard.focus &&
|
||||
wl_resource_get_client (seat->keyboard.focus->resource) == client)
|
||||
if (seat->keyboard.focus_surface &&
|
||||
wl_resource_get_client (seat->keyboard.focus_surface->resource) == client)
|
||||
{
|
||||
meta_wayland_keyboard_set_focus (&seat->keyboard, seat->keyboard.focus);
|
||||
meta_wayland_keyboard_set_focus (&seat->keyboard, seat->keyboard.focus_surface);
|
||||
meta_wayland_data_device_set_keyboard_focus (seat);
|
||||
}
|
||||
}
|
||||
@ -429,7 +429,7 @@ meta_wayland_seat_repick (MetaWaylandSeat *seat,
|
||||
}
|
||||
|
||||
pointer->current = surface;
|
||||
if (surface != pointer->focus)
|
||||
if (surface != pointer->focus_surface)
|
||||
{
|
||||
const MetaWaylandPointerGrabInterface *interface =
|
||||
pointer->grab->interface;
|
||||
|
@ -826,7 +826,7 @@ xdg_surface_move (struct wl_client *client,
|
||||
|
||||
if (seat->pointer.button_count == 0 ||
|
||||
seat->pointer.grab_serial != serial ||
|
||||
seat->pointer.focus != surface)
|
||||
seat->pointer.focus_surface != surface)
|
||||
return;
|
||||
|
||||
begin_grab_op_on_surface (surface, seat, META_GRAB_OP_MOVING);
|
||||
@ -872,7 +872,7 @@ xdg_surface_resize (struct wl_client *client,
|
||||
|
||||
if (seat->pointer.button_count == 0 ||
|
||||
seat->pointer.grab_serial != serial ||
|
||||
seat->pointer.focus != surface)
|
||||
seat->pointer.focus_surface != surface)
|
||||
return;
|
||||
|
||||
begin_grab_op_on_surface (surface, seat, grab_op_for_edge (edges));
|
||||
|
Loading…
Reference in New Issue
Block a user