[RFC] weston: implement inert objects for keyboard/pointer/touch
Hardening
rdp.effort at gmail.com
Fri Oct 16 08:16:52 PDT 2015
Le 16/10/2015 11:53, David FORT a écrit :
> This patch implements inert objects for wl_keyboard, wl_pointer and wl_touch.
> The target case is when the server has just send a capability event about a
> disappearing object, and the client binds the corresponding object. We bind an
> inert object: an object does nothing when it is requested. If the client behave
> correctly, this object should be released when the capability event is received
> and treated (calling the corresponding release request).
> As a consequence, we can rely on seat->[keyboard|pointer|touch]_state to know
> if the seat has the corresponding object.
> Weston doesn't really handle multiple mice for one wl_pointer, so I have removed
> the corresponding code and tests (it was quite a weston_test hack BTW).
> Finally I have fixed a wrong behaviour: the capabilities event's documentation states
> that the capabilities should be sent when a new capability is set on the seat. So
> attaching a second mouse to an existing wl_pointer should not broadcast seat
> capabilities (and the same for keyboard and touch).
> ---
> desktop-shell/exposay.c | 16 ++--
> desktop-shell/shell.c | 21 +++--
> src/compositor-wayland.c | 10 +-
> src/compositor-x11.c | 12 ++-
> src/compositor.h | 3 -
> src/input.c | 235 ++++++++++++++++++++++++++---------------------
> src/libinput-device.c | 2 +-
> src/screen-share.c | 2 +
> src/text-backend.c | 44 +++++----
> src/zoom.c | 7 +-
> tests/devices-test.c | 20 ----
> tests/weston-test.c | 18 ++--
> xwayland/dnd.c | 3 +-
> 13 files changed, 216 insertions(+), 177 deletions(-)
>
> diff --git a/desktop-shell/exposay.c b/desktop-shell/exposay.c
> index 08b86a3..d6919b3 100644
> --- a/desktop-shell/exposay.c
> +++ b/desktop-shell/exposay.c
> @@ -574,21 +574,23 @@ exposay_transition_active(struct desktop_shell *shell)
> bool animate = false;
>
> shell->exposay.workspace = get_current_workspace(shell);
> - shell->exposay.focus_prev = get_default_view(keyboard->focus);
> - shell->exposay.focus_current = get_default_view(keyboard->focus);
> + if (keyboard) {
> + shell->exposay.focus_prev = get_default_view(keyboard->focus);
> + shell->exposay.focus_current = get_default_view(keyboard->focus);
> + }
> shell->exposay.clicked = NULL;
> wl_list_init(&shell->exposay.surface_list);
>
> lower_fullscreen_layer(shell, NULL);
> shell->exposay.grab_kbd.interface = &exposay_kbd_grab;
> - weston_keyboard_start_grab(keyboard,
> - &shell->exposay.grab_kbd);
> - weston_keyboard_set_focus(keyboard, NULL);
> + if (keyboard) {
> + weston_keyboard_start_grab(keyboard, &shell->exposay.grab_kbd);
> + weston_keyboard_set_focus(keyboard, NULL);
> + }
>
> shell->exposay.grab_ptr.interface = &exposay_ptr_grab;
> if (pointer) {
> - weston_pointer_start_grab(pointer,
> - &shell->exposay.grab_ptr);
> + weston_pointer_start_grab(pointer, &shell->exposay.grab_ptr);
> weston_pointer_clear_focus(pointer);
> }
> wl_list_for_each(shell_output, &shell->output_list, link) {
> diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
> index 3eb3f5c..cdddf09 100644
> --- a/desktop-shell/shell.c
> +++ b/desktop-shell/shell.c
> @@ -380,7 +380,8 @@ shell_grab_start(struct shell_grab *grab,
> struct desktop_shell *shell = shsurf->shell;
> struct weston_touch *touch = weston_seat_get_touch(pointer->seat);
>
> - popup_grab_end(pointer);
> + if (pointer)
> + popup_grab_end(pointer);
> if (touch)
> touch_popup_grab_end(touch);
>
> @@ -391,11 +392,13 @@ shell_grab_start(struct shell_grab *grab,
> &grab->shsurf_destroy_listener);
>
> shsurf->grabbed = 1;
> - weston_pointer_start_grab(pointer, &grab->grab);
> + if (pointer)
> + weston_pointer_start_grab(pointer, &grab->grab);
> if (shell->child.desktop_shell) {
> desktop_shell_send_grab_cursor(shell->child.desktop_shell,
> cursor);
> - weston_pointer_set_focus(pointer,
> + if (pointer)
> + weston_pointer_set_focus(pointer,
> get_default_view(shell->grab_surface),
> wl_fixed_from_int(0),
> wl_fixed_from_int(0));
> @@ -925,12 +928,10 @@ restore_focus_state(struct desktop_shell *shell, struct workspace *ws)
> wl_list_insert(&shell->compositor->seat_list,
> &state->seat->link);
>
> - if (!keyboard)
> - continue;
> -
> surface = state->keyboard_focus;
>
> - weston_keyboard_set_focus(keyboard, surface);
> + if (keyboard)
> + weston_keyboard_set_focus(keyboard, surface);
> }
>
> /* For any remaining seats that we don't have a focus state
> @@ -955,6 +956,9 @@ replace_focus_state(struct desktop_shell *shell, struct workspace *ws,
> struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
> struct focus_state *state;
>
> + if (!keyboard)
> + return;
> +
> wl_list_for_each(state, &ws->focus_list, link) {
> if (state->seat == seat) {
> focus_state_set_focus(state, keyboard->focus);
> @@ -1483,6 +1487,9 @@ take_surface_to_workspace_by_seat(struct desktop_shell *shell,
> struct workspace *to;
> struct focus_state *state;
>
> + if (!keyboard)
> + return;
> +
> surface = weston_surface_get_main_surface(keyboard->focus);
> view = get_default_view(surface);
> if (view == NULL ||
> diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c
> index 7b11ae4..2cdf7a5 100644
> --- a/src/compositor-wayland.c
> +++ b/src/compositor-wayland.c
> @@ -1589,10 +1589,12 @@ input_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard,
> serial_out = wl_display_next_serial(b->compositor->wl_display);
>
> keyboard = weston_seat_get_keyboard(&input->base);
> - xkb_state_update_mask(keyboard->xkb_state.state,
> - mods_depressed, mods_latched,
> - mods_locked, 0, 0, group);
> - notify_modifiers(&input->base, serial_out);
> + if (keyboard) {
> + xkb_state_update_mask(keyboard->xkb_state.state,
> + mods_depressed, mods_latched,
> + mods_locked, 0, 0, group);
> + notify_modifiers(&input->base, serial_out);
> + }
> }
>
> static void
> diff --git a/src/compositor-x11.c b/src/compositor-x11.c
> index 9a23996..42356e6 100644
> --- a/src/compositor-x11.c
> +++ b/src/compositor-x11.c
> @@ -189,11 +189,15 @@ x11_backend_get_keymap(struct x11_backend *b)
> static uint32_t
> get_xkb_mod_mask(struct x11_backend *b, uint32_t in)
> {
> - struct weston_keyboard *keyboard =
> - weston_seat_get_keyboard(&b->core_seat);
> - struct weston_xkb_info *info = keyboard->xkb_info;
> + struct weston_keyboard *keyboard = weston_seat_get_keyboard(&b->core_seat);
> + struct weston_xkb_info *info;
> uint32_t ret = 0;
>
> + if (!keyboard)
> + return 0;
> +
> + info = keyboard->xkb_info;
> +
> if ((in & ShiftMask) && info->shift_mod != XKB_MOD_INVALID)
> ret |= (1 << info->shift_mod);
> if ((in & LockMask) && info->caps_mod != XKB_MOD_INVALID)
> @@ -1028,6 +1032,8 @@ update_xkb_state_from_core(struct x11_backend *b, uint16_t x11_mask)
> struct weston_keyboard *keyboard
> = weston_seat_get_keyboard(&b->core_seat);
>
> + if (!keyboard)
> + return;
> xkb_state_update_mask(keyboard->xkb_state.state,
> keyboard->modifiers.mods_depressed & mask,
> keyboard->modifiers.mods_latched & mask,
> diff --git a/src/compositor.h b/src/compositor.h
> index 2e2a185..de38514 100644
> --- a/src/compositor.h
> +++ b/src/compositor.h
> @@ -508,9 +508,6 @@ struct weston_seat {
> struct weston_pointer *pointer_state;
> struct weston_keyboard *keyboard_state;
> struct weston_touch *touch_state;
> - int pointer_device_count;
> - int keyboard_device_count;
> - int touch_device_count;
>
> struct weston_output *output; /* constraint */
>
> diff --git a/src/input.c b/src/input.c
> index 500c39a..6cd2650 100644
> --- a/src/input.c
> +++ b/src/input.c
> @@ -55,10 +55,8 @@ weston_seat_repick(struct weston_seat *seat)
> {
> const struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>
> - if (!pointer)
> - return;
> -
> - pointer->grab->interface->focus(pointer->grab);
> + if (pointer)
> + pointer->grab->interface->focus(pointer->grab);
> }
>
> static void
> @@ -618,11 +616,11 @@ seat_send_updated_caps(struct weston_seat *seat)
> enum wl_seat_capability caps = 0;
> struct wl_resource *resource;
>
> - if (seat->pointer_device_count > 0)
> + if (seat->pointer_state)
> caps |= WL_SEAT_CAPABILITY_POINTER;
> - if (seat->keyboard_device_count > 0)
> + if (seat->keyboard_state)
> caps |= WL_SEAT_CAPABILITY_KEYBOARD;
> - if (seat->touch_device_count > 0)
> + if (seat->touch_state)
> caps |= WL_SEAT_CAPABILITY_TOUCH;
>
> wl_resource_for_each(resource, &seat->base_resource_list) {
> @@ -982,7 +980,8 @@ notify_motion(struct weston_seat *seat,
> struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>
> weston_compositor_wake(ec);
> - pointer->grab->interface->motion(pointer->grab, time, pointer->x + dx, pointer->y + dy);
> + if (pointer)
> + pointer->grab->interface->motion(pointer->grab, time, pointer->x + dx, pointer->y + dy);
> }
>
> static void
> @@ -1029,7 +1028,8 @@ notify_motion_absolute(struct weston_seat *seat,
> struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>
> weston_compositor_wake(ec);
> - pointer->grab->interface->motion(pointer->grab, time, x, y);
> + if (pointer)
> + pointer->grab->interface->motion(pointer->grab, time, x, y);
> }
>
> WL_EXPORT void
> @@ -1054,6 +1054,9 @@ notify_button(struct weston_seat *seat, uint32_t time, int32_t button,
> struct weston_compositor *compositor = seat->compositor;
> struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>
> + if (!pointer)
> + return;
> +
> if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
> weston_compositor_idle_inhibit(compositor);
> if (pointer->button_count == 0) {
> @@ -1092,7 +1095,7 @@ notify_axis(struct weston_seat *seat, uint32_t time, uint32_t axis,
> if (!value)
> return;
>
> - if (weston_compositor_run_axis_binding(compositor, pointer,
> + if (!pointer || weston_compositor_run_axis_binding(compositor, pointer,
> time, axis, value))
> return;
>
> @@ -1159,12 +1162,16 @@ WL_EXPORT void
> notify_modifiers(struct weston_seat *seat, uint32_t serial)
> {
> struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
> - struct weston_keyboard_grab *grab = keyboard->grab;
> + struct weston_keyboard_grab *grab;
> uint32_t mods_depressed, mods_latched, mods_locked, group;
> uint32_t mods_lookup;
> enum weston_led leds = 0;
> int changed = 0;
>
> + if (!keyboard)
> + return;
> +
> + grab = keyboard->grab;
> /* Serialize and update our internal state, checking to see if it's
> * different to the previous state. */
> mods_depressed = xkb_state_serialize_mods(keyboard->xkb_state.state,
> @@ -1233,6 +1240,9 @@ update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key,
> struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
> enum xkb_key_direction direction;
>
> + if (!keyboard)
> + return;
> +
> /* Keyboard modifiers don't exist in raw keyboard mode */
> if (!seat->compositor->use_xkbcommon)
> return;
> @@ -1281,6 +1291,9 @@ update_keymap(struct weston_seat *seat)
> xkb_mod_mask_t latched_mods;
> xkb_mod_mask_t locked_mods;
>
> + if (!keyboard)
> + return;
> +
> xkb_info = weston_xkb_info_create(keyboard->pending_keymap);
>
> xkb_keymap_unref(keyboard->pending_keymap);
> @@ -1353,8 +1366,8 @@ notify_key(struct weston_seat *seat, uint32_t time, uint32_t key,
> enum weston_key_state_update update_state)
> {
> struct weston_compositor *compositor = seat->compositor;
> - struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
> - struct weston_keyboard_grab *grab = keyboard->grab;
> + struct weston_keyboard *keyboard;
> + struct weston_keyboard_grab *grab;
> uint32_t *k, *end;
>
> if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
> @@ -1363,6 +1376,11 @@ notify_key(struct weston_seat *seat, uint32_t time, uint32_t key,
> weston_compositor_idle_release(compositor);
> }
>
> + keyboard = weston_seat_get_keyboard(seat);
> + if (!keyboard)
> + return;
> + grab = keyboard->grab;
> +
> end = keyboard->keys.data + keyboard->keys.size;
> for (k = keyboard->keys.data; k < end; k++) {
> if (*k == key) {
> @@ -1412,7 +1430,7 @@ notify_pointer_focus(struct weston_seat *seat, struct weston_output *output,
> {
> struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>
> - if (output) {
> + if (output && pointer) {
> weston_pointer_move(pointer, x, y);
> } else {
> /* FIXME: We should call weston_pointer_set_focus(seat,
> @@ -1440,6 +1458,9 @@ notify_keyboard_focus_in(struct weston_seat *seat, struct wl_array *keys,
> struct weston_surface *surface;
> uint32_t *k, serial;
>
> + if (!keyboard)
> + return;
> +
> serial = wl_display_next_serial(compositor->wl_display);
> wl_array_copy(&keyboard->keys, keys);
> wl_array_for_each(k, &keyboard->keys) {
> @@ -1466,25 +1487,30 @@ notify_keyboard_focus_out(struct weston_seat *seat)
> struct weston_pointer *pointer = weston_seat_get_pointer(seat);
> uint32_t *k, serial;
>
> - serial = wl_display_next_serial(compositor->wl_display);
> - wl_array_for_each(k, &keyboard->keys) {
> - weston_compositor_idle_release(compositor);
> - update_modifier_state(seat, serial, *k,
> - WL_KEYBOARD_KEY_STATE_RELEASED);
> + if (keyboard) {
> + serial = wl_display_next_serial(compositor->wl_display);
> + wl_array_for_each(k, &keyboard->keys) {
> + weston_compositor_idle_release(compositor);
> + update_modifier_state(seat, serial, *k,
> + WL_KEYBOARD_KEY_STATE_RELEASED);
> + }
> }
>
> seat->modifier_state = 0;
>
> - if (keyboard->focus) {
> - seat->saved_kbd_focus = keyboard->focus;
> - seat->saved_kbd_focus_listener.notify =
> - destroy_device_saved_kbd_focus;
> - wl_signal_add(&keyboard->focus->destroy_signal,
> - &seat->saved_kbd_focus_listener);
> + if (keyboard) {
> + if (keyboard->focus) {
> + seat->saved_kbd_focus = keyboard->focus;
> + seat->saved_kbd_focus_listener.notify =
> + destroy_device_saved_kbd_focus;
> + wl_signal_add(&keyboard->focus->destroy_signal,
> + &seat->saved_kbd_focus_listener);
> + }
> +
> + weston_keyboard_set_focus(keyboard, NULL);
> + weston_keyboard_cancel_grab(keyboard);
> }
>
> - weston_keyboard_set_focus(keyboard, NULL);
> - weston_keyboard_cancel_grab(keyboard);
> if (pointer)
> weston_pointer_cancel_grab(pointer);
> }
> @@ -1545,10 +1571,15 @@ notify_touch(struct weston_seat *seat, uint32_t time, int touch_id,
> {
> struct weston_compositor *ec = seat->compositor;
> struct weston_touch *touch = weston_seat_get_touch(seat);
> - struct weston_touch_grab *grab = touch->grab;
> + struct weston_touch_grab *grab;
> struct weston_view *ev;
> wl_fixed_t sx, sy;
>
> + if (!touch)
> + return;
> +
> + grab = touch->grab;
> +
> /* Update grab's global coordinates. */
> if (touch_id == touch->grab_touch_id && touch_type != WL_TOUCH_UP) {
> touch->grab_x = x;
> @@ -1620,9 +1651,12 @@ WL_EXPORT void
> notify_touch_frame(struct weston_seat *seat)
> {
> struct weston_touch *touch = weston_seat_get_touch(seat);
> - struct weston_touch_grab *grab = touch->grab;
> + struct weston_touch_grab *grab;
>
> - grab->interface->frame(grab);
> + if (touch) {
> + grab = touch->grab;
> + grab->interface->frame(grab);
> + }
> }
>
> static int
> @@ -1735,34 +1769,46 @@ static const struct wl_pointer_interface pointer_interface = {
> };
>
> static void
> +inert_pointer_set_cursor(struct wl_client *client, struct wl_resource *resource,
> + uint32_t serial, struct wl_resource *surface_resource,
> + int32_t x, int32_t y)
> +{
> + /* in the "normal" pointer_set_cursor, we're setting a surface role only
> + * if we have pointer focus. An inert pointer doesn't really have a focus so
> + * we don't do anything on the surface */
> +}
> +
> +static const struct wl_pointer_interface inert_pointer_interface = {
> + inert_pointer_set_cursor,
> + pointer_release
> +};
> +
> +static void
> seat_get_pointer(struct wl_client *client, struct wl_resource *resource,
> uint32_t id)
> {
> struct weston_seat *seat = wl_resource_get_user_data(resource);
> - /* We use the pointer_state directly, which means we'll
> - * give a wl_pointer if the seat has ever had one - even though
> - * the spec explicitly states that this request only takes effect
> - * if the seat has the pointer capability.
> - *
> - * This prevents a race between the compositor sending new
> - * capabilities and the client trying to use the old ones.
> - */
> struct weston_pointer *pointer = seat->pointer_state;
> struct wl_resource *cr;
>
> - if (!pointer)
> - return;
> -
> - cr = wl_resource_create(client, &wl_pointer_interface,
> - wl_resource_get_version(resource), id);
> + cr = wl_resource_create(client, &wl_pointer_interface,
> + wl_resource_get_version(resource), id);
> if (cr == NULL) {
> wl_client_post_no_memory(client);
> return;
> }
>
> + if (!pointer) {
> + /*weston_log("binding inert pointer for seat %p\n", seat);*/
> + wl_resource_set_implementation(cr, &inert_pointer_interface, NULL,
> + NULL);
> + return;
> + }
> +
> /* May be moved to focused list later by either
> * weston_pointer_set_focus or directly if this client is already
> * focused */
> +
> wl_list_insert(&pointer->resource_list, wl_resource_get_link(cr));
> wl_resource_set_implementation(cr, &pointer_interface, pointer,
> unbind_resource);
> @@ -1796,6 +1842,10 @@ static const struct wl_keyboard_interface keyboard_interface = {
> keyboard_release
> };
>
> +static const struct wl_keyboard_interface inert_keyboard_interface = {
> + keyboard_release
> +};
> +
> static bool
> should_send_modifiers_to_client(struct weston_seat *seat,
> struct wl_client *client)
> @@ -1823,27 +1873,23 @@ seat_get_keyboard(struct wl_client *client, struct wl_resource *resource,
> uint32_t id)
> {
> struct weston_seat *seat = wl_resource_get_user_data(resource);
> - /* We use the keyboard_state directly, which means we'll
> - * give a wl_keyboard if the seat has ever had one - even though
> - * the spec explicitly states that this request only takes effect
> - * if the seat has the keyboard capability.
> - *
> - * This prevents a race between the compositor sending new
> - * capabilities and the client trying to use the old ones.
> - */
> struct weston_keyboard *keyboard = seat->keyboard_state;
> struct wl_resource *cr;
>
> - if (!keyboard)
> - return;
> -
> - cr = wl_resource_create(client, &wl_keyboard_interface,
> - wl_resource_get_version(resource), id);
> + cr = wl_resource_create(client, &wl_keyboard_interface,
> + wl_resource_get_version(resource), id);
> if (cr == NULL) {
> wl_client_post_no_memory(client);
> return;
> }
>
> + if (!keyboard) {
> + /*weston_log("binding inert keyboard for seat %p\n", seat);*/
> + wl_resource_set_implementation(cr, &inert_keyboard_interface, NULL,
> + NULL);
> + return;
> + }
> +
> /* May be moved to focused list later by either
> * weston_keyboard_set_focus or directly if this client is already
> * focused */
> @@ -1906,32 +1952,32 @@ static const struct wl_touch_interface touch_interface = {
> touch_release
> };
>
> +static const struct wl_touch_interface inert_touch_interface = {
> + touch_release
> +};
> +
> static void
> seat_get_touch(struct wl_client *client, struct wl_resource *resource,
> uint32_t id)
> {
> struct weston_seat *seat = wl_resource_get_user_data(resource);
> - /* We use the touch_state directly, which means we'll
> - * give a wl_touch if the seat has ever had one - even though
> - * the spec explicitly states that this request only takes effect
> - * if the seat has the touch capability.
> - *
> - * This prevents a race between the compositor sending new
> - * capabilities and the client trying to use the old ones.
> - */
> struct weston_touch *touch = seat->touch_state;
> struct wl_resource *cr;
>
> - if (!touch)
> - return;
> -
> - cr = wl_resource_create(client, &wl_touch_interface,
> - wl_resource_get_version(resource), id);
> + cr = wl_resource_create(client, &wl_touch_interface,
> + wl_resource_get_version(resource), id);
> if (cr == NULL) {
> wl_client_post_no_memory(client);
> return;
> }
>
> + if (!touch) {
> + /*weston_log("binding inert touch for seat %p\n", seat);*/
> + wl_resource_set_implementation(cr, &inert_touch_interface, NULL, NULL);
> + return;
> + }
> +
> +
> if (touch->focus &&
> wl_resource_get_client(touch->focus->surface->resource) == client) {
> wl_list_insert(&touch->focus_resource_list,
> @@ -2180,9 +2226,7 @@ weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
> struct weston_keyboard *keyboard;
>
> if (seat->keyboard_state) {
> - seat->keyboard_device_count += 1;
> - if (seat->keyboard_device_count == 1)
> - seat_send_updated_caps(seat);
> + weston_log("seat %p already has a keyboard device\n", seat);
> return 0;
> }
>
> @@ -2216,7 +2260,6 @@ weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
> #endif
>
> seat->keyboard_state = keyboard;
> - seat->keyboard_device_count = 1;
> keyboard->seat = seat;
>
> seat_send_updated_caps(seat);
> @@ -2257,12 +2300,12 @@ weston_keyboard_reset_state(struct weston_keyboard *keyboard)
> WL_EXPORT void
> weston_seat_release_keyboard(struct weston_seat *seat)
> {
> - seat->keyboard_device_count--;
> - assert(seat->keyboard_device_count >= 0);
> - if (seat->keyboard_device_count == 0) {
> + if (seat->keyboard_state) {
> weston_keyboard_set_focus(seat->keyboard_state, NULL);
> weston_keyboard_cancel_grab(seat->keyboard_state);
> weston_keyboard_reset_state(seat->keyboard_state);
> + seat->keyboard_state = NULL;
> +
> seat_send_updated_caps(seat);
> }
> }
> @@ -2273,9 +2316,7 @@ weston_seat_init_pointer(struct weston_seat *seat)
> struct weston_pointer *pointer;
>
> if (seat->pointer_state) {
> - seat->pointer_device_count += 1;
> - if (seat->pointer_device_count == 1)
> - seat_send_updated_caps(seat);
> + weston_log("seat %p already has a pointer device\n", seat);
> return;
> }
>
> @@ -2284,7 +2325,6 @@ weston_seat_init_pointer(struct weston_seat *seat)
> return;
>
> seat->pointer_state = pointer;
> - seat->pointer_device_count = 1;
> pointer->seat = seat;
>
> seat_send_updated_caps(seat);
> @@ -2295,8 +2335,7 @@ weston_seat_release_pointer(struct weston_seat *seat)
> {
> struct weston_pointer *pointer = seat->pointer_state;
>
> - seat->pointer_device_count--;
> - if (seat->pointer_device_count == 0) {
> + if (seat->pointer_state) {
> weston_pointer_clear_focus(pointer);
> weston_pointer_cancel_grab(pointer);
>
> @@ -2304,12 +2343,9 @@ weston_seat_release_pointer(struct weston_seat *seat)
> pointer_unmap_sprite(pointer);
>
> weston_pointer_reset_state(pointer);
> - seat_send_updated_caps(seat);
> + seat->pointer_state = NULL;
>
> - /* seat->pointer is intentionally not destroyed so that
> - * a newly attached pointer on this seat will retain
> - * the previous cursor co-ordinates.
> - */
> + seat_send_updated_caps(seat);
> }
> }
>
> @@ -2319,9 +2355,7 @@ weston_seat_init_touch(struct weston_seat *seat)
> struct weston_touch *touch;
>
> if (seat->touch_state) {
> - seat->touch_device_count += 1;
> - if (seat->touch_device_count == 1)
> - seat_send_updated_caps(seat);
> + weston_log("seat %p already has a touch device\n", seat);
> return;
> }
>
> @@ -2330,7 +2364,6 @@ weston_seat_init_touch(struct weston_seat *seat)
> return;
>
> seat->touch_state = touch;
> - seat->touch_device_count = 1;
> touch->seat = seat;
>
> seat_send_updated_caps(seat);
> @@ -2339,11 +2372,12 @@ weston_seat_init_touch(struct weston_seat *seat)
> WL_EXPORT void
> weston_seat_release_touch(struct weston_seat *seat)
> {
> - seat->touch_device_count--;
> - if (seat->touch_device_count == 0) {
> + if (seat->touch_state) {
> weston_touch_set_focus(seat->touch_state, NULL);
> weston_touch_cancel_grab(seat->touch_state);
> weston_touch_reset_state(seat->touch_state);
> + seat->touch_state = NULL;
> +
> seat_send_updated_caps(seat);
> }
> }
> @@ -2413,10 +2447,7 @@ weston_seat_get_keyboard(struct weston_seat *seat)
> if (!seat)
> return NULL;
>
> - if (seat->keyboard_device_count)
> - return seat->keyboard_state;
> -
> - return NULL;
> + return seat->keyboard_state;
> }
>
> /** Get a seat's pointer pointer
> @@ -2435,10 +2466,7 @@ weston_seat_get_pointer(struct weston_seat *seat)
> if (!seat)
> return NULL;
>
> - if (seat->pointer_device_count)
> - return seat->pointer_state;
> -
> - return NULL;
> + return seat->pointer_state;
> }
>
> /** Get a seat's touch pointer
> @@ -2457,8 +2485,5 @@ weston_seat_get_touch(struct weston_seat *seat)
> if (!seat)
> return NULL;
>
> - if (seat->touch_device_count)
> - return seat->touch_state;
> -
> - return NULL;
> + return seat->touch_state;
> }
> diff --git a/src/libinput-device.c b/src/libinput-device.c
> index 2cbfb88..ddd8e2c 100644
> --- a/src/libinput-device.c
> +++ b/src/libinput-device.c
> @@ -547,7 +547,7 @@ evdev_notify_keyboard_focus(struct weston_seat *seat,
> {
> struct wl_array keys;
>
> - if (seat->keyboard_device_count == 0)
> + if (!seat->keyboard_state)
> return;
>
> wl_array_init(&keys);
> diff --git a/src/screen-share.c b/src/screen-share.c
> index d961c89..e20aede 100644
> --- a/src/screen-share.c
> +++ b/src/screen-share.c
> @@ -283,6 +283,8 @@ ss_seat_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard,
> serial_out = wl_display_next_serial(c->wl_display);
>
> keyboard = weston_seat_get_keyboard(&seat->base);
> + if (!keyboard)
> + return;
> xkb_state_update_mask(keyboard->xkb_state.state,
> mods_depressed, mods_latched,
> mods_locked, 0, 0, group);
> diff --git a/src/text-backend.c b/src/text-backend.c
> index 8c9e30d..f3f30dc 100644
> --- a/src/text-backend.c
> +++ b/src/text-backend.c
> @@ -664,15 +664,17 @@ input_method_context_grab_keyboard(struct wl_client *client,
>
> context->keyboard = cr;
>
> - wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
> - keyboard->xkb_info->keymap_fd,
> - keyboard->xkb_info->keymap_size);
> -
> - if (keyboard->grab != &keyboard->default_grab) {
> - weston_keyboard_end_grab(keyboard);
> + if (keyboard) {
> + wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
> + keyboard->xkb_info->keymap_fd,
> + keyboard->xkb_info->keymap_size);
> +
> + if (keyboard->grab != &keyboard->default_grab) {
> + weston_keyboard_end_grab(keyboard);
> + }
> + weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
> + keyboard->input_method_resource = cr;
> }
> - weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
> - keyboard->input_method_resource = cr;
> }
>
> static void
> @@ -686,10 +688,14 @@ input_method_context_key(struct wl_client *client,
> struct input_method_context *context =
> wl_resource_get_user_data(resource);
> struct weston_seat *seat = context->input_method->seat;
> - struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
> - struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
> + struct weston_keyboard *keyboard;
> + struct weston_keyboard_grab *default_grab;
>
> - default_grab->interface->key(default_grab, time, key, state_w);
> + keyboard = weston_seat_get_keyboard(seat);
> + if (keyboard) {
> + default_grab = &keyboard->default_grab;
> + default_grab->interface->key(default_grab, time, key, state_w);
> + }
> }
>
> static void
> @@ -705,13 +711,17 @@ input_method_context_modifiers(struct wl_client *client,
> wl_resource_get_user_data(resource);
>
> struct weston_seat *seat = context->input_method->seat;
> - struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
> - struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
> + struct weston_keyboard *keyboard;
> + struct weston_keyboard_grab *default_grab;
>
> - default_grab->interface->modifiers(default_grab,
> - serial, mods_depressed,
> - mods_latched, mods_locked,
> - group);
> + keyboard = weston_seat_get_keyboard(seat);
> + if (keyboard) {
> + default_grab = &keyboard->default_grab;
> + default_grab->interface->modifiers(default_grab,
> + serial, mods_depressed,
> + mods_latched, mods_locked,
> + group);
> + }
> }
>
> static void
> diff --git a/src/zoom.c b/src/zoom.c
> index 08c0693..8658f08 100644
> --- a/src/zoom.c
> +++ b/src/zoom.c
> @@ -124,6 +124,8 @@ weston_output_update_zoom(struct weston_output *output)
> struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>
> assert(output->zoom.active);
> + if (!pointer)
> + return;
>
> output->zoom.current.x = wl_fixed_to_double(pointer->x);
> output->zoom.current.y = wl_fixed_to_double(pointer->y);
> @@ -155,8 +157,9 @@ weston_output_activate_zoom(struct weston_output *output,
> output->zoom.active = true;
> output->zoom.seat = seat;
> output->disable_planes++;
> - wl_signal_add(&pointer->motion_signal,
> - &output->zoom.motion_listener);
> + if (pointer)
> + wl_signal_add(&pointer->motion_signal,
> + &output->zoom.motion_listener);
> }
>
> WL_EXPORT void
> diff --git a/tests/devices-test.c b/tests/devices-test.c
> index 8f9feec..8851c17 100644
> --- a/tests/devices-test.c
> +++ b/tests/devices-test.c
> @@ -74,26 +74,6 @@ TEST(seat_capabilities_test)
> assert(cl->input->pointer);
> assert(cl->input->keyboard);
> assert(cl->input->touch);
> -
> - /* add extra devices */
> - weston_test_device_add(cl->test->weston_test, "keyboard");
> - weston_test_device_add(cl->test->weston_test, "pointer");
> - weston_test_device_add(cl->test->weston_test, "touch");
> - client_roundtrip(cl);
> -
> - /* remove extra devices */
> - weston_test_device_release(cl->test->weston_test, "keyboard");
> - weston_test_device_release(cl->test->weston_test, "pointer");
> - weston_test_device_release(cl->test->weston_test, "touch");
> - client_roundtrip(cl);
> -
> - /* we still should have all the capabilities, since the devices
> - * were doubled */
> - assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
> -
> - assert(cl->input->pointer);
> - assert(cl->input->keyboard);
> - assert(cl->input->touch);
> }
>
> #define COUNT 15
> diff --git a/tests/weston-test.c b/tests/weston-test.c
> index b593f1e..28aefad 100644
> --- a/tests/weston-test.c
> +++ b/tests/weston-test.c
> @@ -85,7 +85,8 @@ notify_pointer_position(struct weston_test *test, struct wl_resource *resource)
> struct weston_seat *seat = get_seat(test);
> struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>
> - weston_test_send_pointer_position(resource, pointer->x, pointer->y);
> + if (pointer)
> + weston_test_send_pointer_position(resource, pointer->x, pointer->y);
> }
>
> static void
> @@ -146,9 +147,10 @@ move_pointer(struct wl_client *client, struct wl_resource *resource,
> struct weston_seat *seat = get_seat(test);
> struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>
> - notify_motion(seat, 100,
> - wl_fixed_from_int(x) - pointer->x,
> - wl_fixed_from_int(y) - pointer->y);
> + if (pointer)
> + notify_motion(seat, 100,
> + wl_fixed_from_int(x) - pointer->x,
> + wl_fixed_from_int(y) - pointer->y);
>
> notify_pointer_position(test, resource);
> }
> @@ -177,11 +179,13 @@ activate_surface(struct wl_client *client, struct wl_resource *resource,
> keyboard = weston_seat_get_keyboard(seat);
> if (surface) {
> weston_surface_activate(surface, seat);
> - notify_keyboard_focus_in(seat, &keyboard->keys,
> - STATE_UPDATE_AUTOMATIC);
> + if (keyboard)
> + notify_keyboard_focus_in(seat, &keyboard->keys,
> + STATE_UPDATE_AUTOMATIC);
> }
> else {
> - notify_keyboard_focus_out(seat);
> + if (keyboard)
> + notify_keyboard_focus_out(seat);
> weston_surface_activate(surface, seat);
> }
> }
> diff --git a/xwayland/dnd.c b/xwayland/dnd.c
> index a036b30..94a9563 100644
> --- a/xwayland/dnd.c
> +++ b/xwayland/dnd.c
> @@ -214,7 +214,8 @@ handle_enter(struct weston_wm *wm, xcb_client_message_event_t *client_message)
> }
>
> free(reply);
> - weston_pointer_start_drag(pointer, &source->base, NULL, NULL);
> + if (pointer)
> + weston_pointer_start_drag(pointer, &source->base, NULL, NULL);
> }
>
> int
>
As Jonas noticed I have missed something with the refcounting of
keyboard/pointer/touch in my patch. I'm sending an updated version.
--
David FORT
website: http://www.hardening-consulting.com/
More information about the wayland-devel
mailing list