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:
Jasper St. Pierre 2014-02-18 18:00:26 -05:00
parent 414259a7f8
commit a364c2a96b
6 changed files with 96 additions and 52 deletions

View File

@ -225,13 +225,25 @@ err_keymap_str:
return; return;
} }
static void
release_focus (MetaWaylandKeyboard *keyboard)
{
keyboard->focus_resource = NULL;
keyboard->focus_surface = NULL;
}
static void static void
keyboard_handle_focus_surface_destroy (struct wl_listener *listener, void *data) keyboard_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
{ {
MetaWaylandKeyboard *keyboard = wl_container_of (listener, keyboard, focus_surface_listener); MetaWaylandKeyboard *keyboard = wl_container_of (listener, keyboard, focus_surface_listener);
release_focus (keyboard);
}
keyboard->focus_resource = NULL; static void
keyboard->focus = NULL; 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 static gboolean
@ -287,10 +299,9 @@ default_grab_modifiers (MetaWaylandKeyboardGrab *grab, uint32_t serial,
wl_keyboard_send_modifiers (resource, serial, mods_depressed, wl_keyboard_send_modifiers (resource, serial, mods_depressed,
mods_latched, mods_locked, group); 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, pr = find_resource_for_surface (&keyboard->resource_list, pointer->focus_surface);
pointer->focus);
if (pr) if (pr)
{ {
wl_keyboard_send_modifiers (pr, serial, wl_keyboard_send_modifiers (pr, serial,
@ -342,7 +353,10 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
wl_list_init (&keyboard->resource_list); wl_list_init (&keyboard->resource_list);
wl_array_init (&keyboard->keys); wl_array_init (&keyboard->keys);
keyboard->focus_surface_listener.notify = keyboard_handle_focus_surface_destroy; 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.interface = &default_keyboard_grab_interface;
keyboard->default_grab.keyboard = keyboard; keyboard->default_grab.keyboard = keyboard;
keyboard->grab = &keyboard->default_grab; keyboard->grab = &keyboard->default_grab;
@ -513,19 +527,27 @@ meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard,
struct wl_resource *resource; struct wl_resource *resource;
uint32_t serial; uint32_t serial;
if (keyboard->focus == surface && keyboard->focus_resource != NULL) if (keyboard->focus_surface == surface && keyboard->focus_resource != NULL)
return; return;
resource = keyboard->focus_resource; resource = keyboard->focus_resource;
if (keyboard->focus_resource && keyboard->focus->resource) if (resource)
{ {
struct wl_client *client = wl_resource_get_client (resource); if (keyboard->focus_surface->resource)
struct wl_display *display = wl_client_get_display (client); {
serial = wl_display_next_serial (display); struct wl_client *client = wl_resource_get_client (resource);
wl_keyboard_send_leave (resource, serial, keyboard->focus->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); 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); 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, wl_keyboard_send_enter (resource, serial, surface->resource,
&keyboard->keys); &keyboard->keys);
} }
wl_resource_add_destroy_listener (surface->resource, &keyboard->focus_surface_listener);
keyboard->focus_serial = serial;
meta_wayland_surface_focused_set (surface); meta_wayland_surface_focused_set (surface);
}
keyboard->focus_resource = resource; keyboard->focus_resource = resource;
keyboard->focus = surface; 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 void
@ -591,8 +616,6 @@ meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard)
xkb_context_unref (keyboard->xkb_context); xkb_context_unref (keyboard->xkb_context);
/* XXX: What about keyboard->resource_list? */ /* XXX: What about keyboard->resource_list? */
if (keyboard->focus_resource)
wl_list_remove (&keyboard->focus_surface_listener.link);
wl_array_release (&keyboard->keys); wl_array_release (&keyboard->keys);
} }
@ -611,7 +634,7 @@ meta_wayland_keyboard_begin_modal (MetaWaylandKeyboard *keyboard,
if (keyboard->grab != &keyboard->default_grab) if (keyboard->grab != &keyboard->default_grab)
return FALSE; return FALSE;
if (keyboard->focus) if (keyboard->focus_surface)
{ {
/* Fake key release events for the focused app */ /* Fake key release events for the focused app */
serial = wl_display_next_serial (keyboard->display); serial = wl_display_next_serial (keyboard->display);
@ -653,7 +676,7 @@ meta_wayland_keyboard_end_modal (MetaWaylandKeyboard *keyboard,
meta_wayland_keyboard_end_grab (keyboard); meta_wayland_keyboard_end_grab (keyboard);
g_slice_free (MetaWaylandKeyboardGrab, grab); g_slice_free (MetaWaylandKeyboardGrab, grab);
if (keyboard->focus) if (keyboard->focus_surface)
{ {
/* Fake key press events for the focused app */ /* Fake key press events for the focused app */
serial = wl_display_next_serial (keyboard->display); serial = wl_display_next_serial (keyboard->display);

View File

@ -92,9 +92,11 @@ typedef struct
struct _MetaWaylandKeyboard struct _MetaWaylandKeyboard
{ {
struct wl_list resource_list; struct wl_list resource_list;
MetaWaylandSurface *focus;
struct wl_resource *focus_resource; MetaWaylandSurface *focus_surface;
struct wl_listener focus_surface_listener; struct wl_listener focus_surface_listener;
struct wl_resource *focus_resource;
struct wl_listener focus_resource_listener;
uint32_t focus_serial; uint32_t focus_serial;
MetaWaylandKeyboardGrab *grab; MetaWaylandKeyboardGrab *grab;

View File

@ -63,13 +63,25 @@ meta_wayland_pointer_get_seat (MetaWaylandPointer *pointer)
return seat; return seat;
} }
static void
release_focus (MetaWaylandPointer *pointer)
{
pointer->focus_resource = NULL;
pointer->focus_surface = NULL;
}
static void static void
pointer_handle_focus_surface_destroy (struct wl_listener *listener, void *data) pointer_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
{ {
MetaWaylandPointer *pointer = wl_container_of (listener, pointer, focus_surface_listener); MetaWaylandPointer *pointer = wl_container_of (listener, pointer, focus_surface_listener);
release_focus (pointer);
}
pointer->focus_resource = NULL; static void
pointer->focus = NULL; 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 static void
@ -97,7 +109,7 @@ default_grab_motion (MetaWaylandPointerGrab *grab,
wl_fixed_t sx, sy; wl_fixed_t sx, sy;
meta_wayland_pointer_get_relative_coordinates (grab->pointer, meta_wayland_pointer_get_relative_coordinates (grab->pointer,
grab->pointer->focus, grab->pointer->focus_surface,
&sx, &sy); &sx, &sy);
wl_pointer_send_motion (resource, clutter_event_get_time (event), 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); memset (pointer, 0, sizeof *pointer);
wl_list_init (&pointer->resource_list); wl_list_init (&pointer->resource_list);
pointer->focus_surface_listener.notify = pointer_handle_focus_surface_destroy; 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.interface = &default_pointer_grab_interface;
pointer->default_grab.pointer = pointer; pointer->default_grab.pointer = pointer;
pointer->grab = &pointer->default_grab; pointer->grab = &pointer->default_grab;
@ -292,12 +307,7 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer)
void void
meta_wayland_pointer_release (MetaWaylandPointer *pointer) meta_wayland_pointer_release (MetaWaylandPointer *pointer)
{ {
/* XXX: What about pointer->resource_list? */ release_focus (pointer);
if (pointer->focus_resource)
wl_list_remove (&pointer->focus_surface_listener.link);
pointer->focus = NULL;
pointer->focus_resource = NULL;
} }
static struct wl_resource * static struct wl_resource *
@ -323,21 +333,25 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
struct wl_resource *resource, *kr; struct wl_resource *resource, *kr;
uint32_t serial; uint32_t serial;
if (pointer->focus == surface && pointer->focus_resource != NULL) if (pointer->focus_surface == surface && pointer->focus_resource != NULL)
return; return;
resource = pointer->focus_resource; resource = pointer->focus_resource;
if (resource) if (resource)
{ {
if (pointer->focus->resource) if (pointer->focus_surface->resource)
{ {
struct wl_client *client = wl_resource_get_client (resource); struct wl_client *client = wl_resource_get_client (resource);
struct wl_display *display = wl_client_get_display (client); struct wl_display *display = wl_client_get_display (client);
serial = wl_display_next_serial (display); 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_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); 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->x),
wl_fixed_to_int (pointer->y)); wl_fixed_to_int (pointer->y));
wl_pointer_send_enter (resource, serial, surface->resource, sx, sy); 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_serial = serial;
} }
pointer->focus_resource = resource;
pointer->focus = surface;
} }
void void

View File

@ -46,9 +46,11 @@ struct _MetaWaylandPointerGrab
struct _MetaWaylandPointer struct _MetaWaylandPointer
{ {
struct wl_list resource_list; struct wl_list resource_list;
MetaWaylandSurface *focus;
struct wl_resource *focus_resource; MetaWaylandSurface *focus_surface;
struct wl_listener focus_surface_listener; struct wl_listener focus_surface_listener;
struct wl_resource *focus_resource;
struct wl_listener focus_resource_listener;
guint32 focus_serial; guint32 focus_serial;
guint32 click_serial; guint32 click_serial;

View File

@ -95,9 +95,9 @@ pointer_set_cursor (struct wl_client *client,
surface = (surface_resource ? wl_resource_get_user_data (surface_resource) : NULL); surface = (surface_resource ? wl_resource_get_user_data (surface_resource) : NULL);
if (seat->pointer.focus == NULL) if (seat->pointer.focus_surface == NULL)
return; return;
if (wl_resource_get_client (seat->pointer.focus->resource) != client) if (wl_resource_get_client (seat->pointer.focus_surface->resource) != client)
return; return;
if (seat->pointer.focus_serial - serial > G_MAXUINT32 / 2) if (seat->pointer.focus_serial - serial > G_MAXUINT32 / 2)
return; return;
@ -125,9 +125,9 @@ seat_get_pointer (struct wl_client *client,
wl_resource_set_implementation (cr, &pointer_interface, seat, unbind_resource); wl_resource_set_implementation (cr, &pointer_interface, seat, unbind_resource);
wl_list_insert (&seat->pointer.resource_list, wl_resource_get_link (cr)); wl_list_insert (&seat->pointer.resource_list, wl_resource_get_link (cr));
if (seat->pointer.focus && if (seat->pointer.focus_surface &&
wl_resource_get_client (seat->pointer.focus->resource) == client) wl_resource_get_client (seat->pointer.focus_surface->resource) == client)
meta_wayland_pointer_set_focus (&seat->pointer, seat->pointer.focus); meta_wayland_pointer_set_focus (&seat->pointer, seat->pointer.focus_surface);
} }
static void static void
@ -148,10 +148,10 @@ seat_get_keyboard (struct wl_client *client,
seat->keyboard.xkb_info.keymap_fd, seat->keyboard.xkb_info.keymap_fd,
seat->keyboard.xkb_info.keymap_size); seat->keyboard.xkb_info.keymap_size);
if (seat->keyboard.focus && if (seat->keyboard.focus_surface &&
wl_resource_get_client (seat->keyboard.focus->resource) == client) 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); meta_wayland_data_device_set_keyboard_focus (seat);
} }
} }
@ -429,7 +429,7 @@ meta_wayland_seat_repick (MetaWaylandSeat *seat,
} }
pointer->current = surface; pointer->current = surface;
if (surface != pointer->focus) if (surface != pointer->focus_surface)
{ {
const MetaWaylandPointerGrabInterface *interface = const MetaWaylandPointerGrabInterface *interface =
pointer->grab->interface; pointer->grab->interface;

View File

@ -826,7 +826,7 @@ xdg_surface_move (struct wl_client *client,
if (seat->pointer.button_count == 0 || if (seat->pointer.button_count == 0 ||
seat->pointer.grab_serial != serial || seat->pointer.grab_serial != serial ||
seat->pointer.focus != surface) seat->pointer.focus_surface != surface)
return; return;
begin_grab_op_on_surface (surface, seat, META_GRAB_OP_MOVING); 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 || if (seat->pointer.button_count == 0 ||
seat->pointer.grab_serial != serial || seat->pointer.grab_serial != serial ||
seat->pointer.focus != surface) seat->pointer.focus_surface != surface)
return; return;
begin_grab_op_on_surface (surface, seat, grab_op_for_edge (edges)); begin_grab_op_on_surface (surface, seat, grab_op_for_edge (edges));