From 1281a36e3bcd27345bd4a107f282213ecca56f0e Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Fri, 31 Jul 2015 16:55:32 -0500 Subject: [PATCH] input: Don't test keyboard/pointer/touch pointers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Keyboards and pointers aren't freed when devices are removed, so we should really be testing keyboard_device_count and pointer_device_count in most cases, not the actual pointers. Otherwise we end up with different behaviour after removing a device than we had before it was inserted. This commit renames the touch/keyboard/pointer pointers and adds helper functions to get them that hide this complexity and return NULL when *_device_count is 0. Signed-off-by: Derek Foreman Reviewed-by: Jonas Ã…dahl --- desktop-shell/exposay.c | 34 ++-- desktop-shell/input-panel.c | 7 +- desktop-shell/shell.c | 191 ++++++++++++--------- fullscreen-shell/fullscreen-shell.c | 18 +- ivi-shell/hmi-controller.c | 30 ++-- ivi-shell/input-panel-ivi.c | 7 +- src/compositor-drm.c | 10 +- src/compositor-wayland.c | 8 +- src/compositor-x11.c | 18 +- src/compositor.c | 27 +-- src/compositor.h | 15 +- src/data-device.c | 41 +++-- src/input.c | 246 ++++++++++++++++++++-------- src/libinput-seat.c | 15 +- src/main.c | 7 +- src/text-backend.c | 19 ++- src/zoom.c | 9 +- tests/surface-screenshot.c | 7 +- tests/weston-test.c | 9 +- xwayland/dnd.c | 3 +- xwayland/window-manager.c | 23 ++- 21 files changed, 484 insertions(+), 260 deletions(-) diff --git a/desktop-shell/exposay.c b/desktop-shell/exposay.c index 3d5d0c33..109f8e33 100644 --- a/desktop-shell/exposay.c +++ b/desktop-shell/exposay.c @@ -525,14 +525,16 @@ static enum exposay_layout_state exposay_set_inactive(struct desktop_shell *shell) { struct weston_seat *seat = shell->exposay.seat; + struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat); + struct weston_pointer *pointer = weston_seat_get_pointer(seat); - if (seat->pointer_device_count) - weston_pointer_end_grab(seat->pointer); + if (pointer) + weston_pointer_end_grab(pointer); - if (seat->keyboard_device_count) { - weston_keyboard_end_grab(seat->keyboard); - if (seat->keyboard->input_method_resource) - seat->keyboard->grab = &seat->keyboard->input_method_grab; + if (keyboard) { + weston_keyboard_end_grab(keyboard); + if (keyboard->input_method_resource) + keyboard->grab = &keyboard->input_method_grab; } return EXPOSAY_LAYOUT_INACTIVE; @@ -566,28 +568,30 @@ static enum exposay_layout_state exposay_transition_active(struct desktop_shell *shell) { struct weston_seat *seat = shell->exposay.seat; + struct weston_pointer *pointer = weston_seat_get_pointer(seat); + struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat); struct shell_output *shell_output; bool animate = false; shell->exposay.workspace = get_current_workspace(shell); - shell->exposay.focus_prev = get_default_view (seat->keyboard->focus); - shell->exposay.focus_current = get_default_view (seat->keyboard->focus); + 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(seat->keyboard, + weston_keyboard_start_grab(keyboard, &shell->exposay.grab_kbd); - weston_keyboard_set_focus(seat->keyboard, NULL); + weston_keyboard_set_focus(keyboard, NULL); shell->exposay.grab_ptr.interface = &exposay_ptr_grab; - if (seat->pointer_device_count) { - weston_pointer_start_grab(seat->pointer, + if (pointer) { + weston_pointer_start_grab(pointer, &shell->exposay.grab_ptr); - weston_pointer_set_focus(seat->pointer, NULL, - seat->pointer->x, - seat->pointer->y); + weston_pointer_set_focus(pointer, NULL, + pointer->x, + pointer->y); } wl_list_for_each(shell_output, &shell->output_list, link) { enum exposay_layout_state state; diff --git a/desktop-shell/input-panel.c b/desktop-shell/input-panel.c index 1028df13..251d0449 100644 --- a/desktop-shell/input-panel.c +++ b/desktop-shell/input-panel.c @@ -68,9 +68,12 @@ show_input_panel_surface(struct input_panel_surface *ipsurf) float x, y; wl_list_for_each(seat, &shell->compositor->seat_list, link) { - if (!seat->keyboard || !seat->keyboard->focus) + struct weston_keyboard *keyboard = + weston_seat_get_keyboard(seat); + + if (!keyboard || !keyboard->focus) continue; - focus = weston_surface_get_main_surface(seat->keyboard->focus); + focus = weston_surface_get_main_surface(keyboard->focus); ipsurf->output = focus->output; x = ipsurf->output->x + (ipsurf->output->width - ipsurf->surface->width) / 2; y = ipsurf->output->y + ipsurf->output->height - ipsurf->surface->height; diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c index 009e6710..487c3e73 100644 --- a/desktop-shell/shell.c +++ b/desktop-shell/shell.c @@ -378,10 +378,11 @@ shell_grab_start(struct shell_grab *grab, enum desktop_shell_cursor cursor) { struct desktop_shell *shell = shsurf->shell; + struct weston_touch *touch = weston_seat_get_touch(pointer->seat); popup_grab_end(pointer); - if (pointer->seat->touch) - touch_popup_grab_end(pointer->seat->touch); + if (touch) + touch_popup_grab_end(touch); grab->grab.interface = interface; grab->shsurf = shsurf; @@ -546,10 +547,11 @@ shell_touch_grab_start(struct shell_touch_grab *grab, struct weston_touch *touch) { struct desktop_shell *shell = shsurf->shell; + struct weston_pointer *pointer = weston_seat_get_pointer(touch->seat); touch_popup_grab_end(touch); - if (touch->seat->pointer) - popup_grab_end(touch->seat->pointer); + if (pointer) + popup_grab_end(pointer); grab->grab.interface = interface; grab->shsurf = shsurf; @@ -900,27 +902,33 @@ restore_focus_state(struct desktop_shell *shell, struct workspace *ws) wl_list_init(&shell->compositor->seat_list); wl_list_for_each_safe(state, next, &ws->focus_list, link) { + struct weston_keyboard *keyboard = + weston_seat_get_keyboard(state->seat); + wl_list_remove(&state->seat->link); wl_list_insert(&shell->compositor->seat_list, &state->seat->link); - if (state->seat->keyboard == NULL) + if (!keyboard) continue; surface = state->keyboard_focus; - weston_keyboard_set_focus(state->seat->keyboard, surface); + weston_keyboard_set_focus(keyboard, surface); } /* For any remaining seats that we don't have a focus state * for we'll reset the keyboard focus to NULL */ wl_list_for_each_safe(seat, next_seat, &pending_seat_list, link) { + struct weston_keyboard *keyboard = + weston_seat_get_keyboard(seat); + wl_list_insert(&shell->compositor->seat_list, &seat->link); - if (seat->keyboard == NULL) + if (!keyboard) continue; - weston_keyboard_set_focus(seat->keyboard, NULL); + weston_keyboard_set_focus(keyboard, NULL); } } @@ -928,11 +936,12 @@ static void replace_focus_state(struct desktop_shell *shell, struct workspace *ws, struct weston_seat *seat) { + struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat); struct focus_state *state; wl_list_for_each(state, &ws->focus_list, link) { if (state->seat == seat) { - focus_state_set_focus(state, seat->keyboard->focus); + focus_state_set_focus(state, keyboard->focus); return; } } @@ -1431,12 +1440,15 @@ move_surface_to_workspace(struct desktop_shell *shell, drop_focus_state(shell, from, view->surface); wl_list_for_each(seat, &shell->compositor->seat_list, link) { - if (!seat->keyboard) + struct weston_keyboard *keyboard = + weston_seat_get_keyboard(seat); + + if (!keyboard) continue; - focus = weston_surface_get_main_surface(seat->keyboard->focus); + focus = weston_surface_get_main_surface(keyboard->focus); if (focus == view->surface) - weston_keyboard_set_focus(seat->keyboard, NULL); + weston_keyboard_set_focus(keyboard, NULL); } weston_view_damage_below(view); @@ -1447,6 +1459,7 @@ take_surface_to_workspace_by_seat(struct desktop_shell *shell, struct weston_seat *seat, unsigned int index) { + struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat); struct weston_surface *surface; struct weston_view *view; struct shell_surface *shsurf; @@ -1454,7 +1467,7 @@ take_surface_to_workspace_by_seat(struct desktop_shell *shell, struct workspace *to; struct focus_state *state; - surface = weston_surface_get_main_surface(seat->keyboard->focus); + surface = weston_surface_get_main_surface(keyboard->focus); view = get_default_view(surface); if (view == NULL || index == shell->workspaces.current || @@ -1782,23 +1795,25 @@ common_surface_move(struct wl_resource *resource, struct wl_resource *seat_resource, uint32_t serial) { struct weston_seat *seat = wl_resource_get_user_data(seat_resource); + struct weston_pointer *pointer = weston_seat_get_pointer(seat); + struct weston_touch *touch = weston_seat_get_touch(seat); struct shell_surface *shsurf = wl_resource_get_user_data(resource); struct weston_surface *surface; - if (seat->pointer && - seat->pointer->focus && - seat->pointer->button_count > 0 && - seat->pointer->grab_serial == serial) { - surface = weston_surface_get_main_surface(seat->pointer->focus->surface); + if (pointer && + pointer->focus && + pointer->button_count > 0 && + pointer->grab_serial == serial) { + surface = weston_surface_get_main_surface(pointer->focus->surface); if ((surface == shsurf->surface) && - (surface_move(shsurf, seat->pointer, true) < 0)) + (surface_move(shsurf, pointer, true) < 0)) wl_resource_post_no_memory(resource); - } else if (seat->touch && - seat->touch->focus && - seat->touch->grab_serial == serial) { - surface = weston_surface_get_main_surface(seat->touch->focus->surface); + } else if (touch && + touch->focus && + touch->grab_serial == serial) { + surface = weston_surface_get_main_surface(touch->focus->surface); if ((surface == shsurf->surface) && - (surface_touch_move(shsurf, seat->touch) < 0)) + (surface_touch_move(shsurf, touch) < 0)) wl_resource_post_no_memory(resource); } } @@ -1986,20 +2001,21 @@ common_surface_resize(struct wl_resource *resource, uint32_t edges) { struct weston_seat *seat = wl_resource_get_user_data(seat_resource); + struct weston_pointer *pointer = weston_seat_get_pointer(seat); struct shell_surface *shsurf = wl_resource_get_user_data(resource); struct weston_surface *surface; - if (seat->pointer == NULL || - seat->pointer->button_count == 0 || - seat->pointer->grab_serial != serial || - seat->pointer->focus == NULL) + if (!pointer || + pointer->button_count == 0 || + pointer->grab_serial != serial || + pointer->focus == NULL) return; - surface = weston_surface_get_main_surface(seat->pointer->focus->surface); + surface = weston_surface_get_main_surface(pointer->focus->surface); if (surface != shsurf->surface) return; - if (surface_resize(shsurf, seat->pointer, edges) < 0) + if (surface_resize(shsurf, pointer, edges) < 0) wl_resource_post_no_memory(resource); } @@ -2096,10 +2112,12 @@ end_busy_cursor(struct weston_compositor *compositor, struct wl_client *client) struct weston_seat *seat; wl_list_for_each(seat, &compositor->seat_list, link) { - if (seat->pointer == NULL) + struct weston_pointer *pointer = weston_seat_get_pointer(seat); + + if (!pointer) continue; - grab = (struct shell_grab *) seat->pointer->grab; + grab = (struct shell_grab *) pointer->grab; if (grab->grab.interface == &busy_cursor_grab_interface && wl_resource_get_client(grab->shsurf->resource) == client) { shell_grab_end(grab); @@ -2121,15 +2139,17 @@ xdg_ping_timeout_handler(void *data) /* Client is not responding */ sc->unresponsive = 1; wl_list_for_each(seat, &sc->shell->compositor->seat_list, link) { - if (seat->pointer == NULL || seat->pointer->focus == NULL) - continue; - if (seat->pointer->focus->surface->resource == NULL) + struct weston_pointer *pointer = weston_seat_get_pointer(seat); + + if (!pointer || + !pointer->focus || + !pointer->focus->surface->resource) continue; - shsurf = get_shell_surface(seat->pointer->focus->surface); + shsurf = get_shell_surface(pointer->focus->surface); if (shsurf && wl_resource_get_client(shsurf->resource) == sc->client) - set_busy_cursor(shsurf, seat->pointer); + set_busy_cursor(shsurf, pointer); } return 1; @@ -2684,11 +2704,14 @@ set_minimized(struct weston_surface *surface) drop_focus_state(shsurf->shell, current_ws, view->surface); wl_list_for_each(seat, &shsurf->shell->compositor->seat_list, link) { - if (!seat->keyboard) + struct weston_keyboard *keyboard = + weston_seat_get_keyboard(seat); + + if (!keyboard) continue; - focus = weston_surface_get_main_surface(seat->keyboard->focus); + focus = weston_surface_get_main_surface(keyboard->focus); if (focus == view->surface) - weston_keyboard_set_focus(seat->keyboard, NULL); + weston_keyboard_set_focus(keyboard, NULL); } shell_surface_update_child_surface_layers(shsurf); @@ -3020,17 +3043,22 @@ get_focused_output(struct weston_compositor *compositor) struct weston_output *output = NULL; wl_list_for_each(seat, &compositor->seat_list, link) { + struct weston_touch *touch = weston_seat_get_touch(seat); + struct weston_pointer *pointer = weston_seat_get_pointer(seat); + struct weston_keyboard *keyboard = + weston_seat_get_keyboard(seat); + /* Priority has touch focus, then pointer and * then keyboard focus. We should probably have * three for loops and check frist for touch, * then for pointer, etc. but unless somebody has some * objections, I think this is sufficient. */ - if (seat->touch && seat->touch->focus) - output = seat->touch->focus->output; - else if (seat->pointer && seat->pointer->focus) - output = seat->pointer->focus->output; - else if (seat->keyboard && seat->keyboard->focus) - output = seat->keyboard->focus->output; + if (touch && touch->focus) + output = touch->focus->output; + else if (pointer && pointer->focus) + output = pointer->focus->output; + else if (keyboard && keyboard->focus) + output = keyboard->focus->output; if (output) break; @@ -3061,7 +3089,7 @@ shell_interface_set_maximized(struct shell_surface *shsurf) static int shell_interface_move(struct shell_surface *shsurf, struct weston_seat *ws) { - return surface_move(shsurf, ws->pointer, true); + return surface_move(shsurf, weston_seat_get_pointer(ws), true); } static int @@ -3069,7 +3097,7 @@ shell_interface_resize(struct shell_surface *shsurf, struct weston_seat *ws, uint32_t edges) { - return surface_resize(shsurf, ws->pointer, edges); + return surface_resize(shsurf, weston_seat_get_pointer(ws), edges); } static const struct weston_pointer_grab_interface popup_grab_interface; @@ -3101,24 +3129,28 @@ destroy_shell_seat(struct wl_listener *listener, void *data) static void shell_seat_caps_changed(struct wl_listener *listener, void *data) { + struct weston_keyboard *keyboard; + struct weston_pointer *pointer; struct shell_seat *seat; seat = container_of(listener, struct shell_seat, caps_changed_listener); + keyboard = weston_seat_get_keyboard(seat->seat); + pointer = weston_seat_get_pointer(seat->seat); - if (seat->seat->keyboard_device_count && + if (keyboard && wl_list_empty(&seat->keyboard_focus_listener.link)) { - wl_signal_add(&seat->seat->keyboard->focus_signal, + wl_signal_add(&keyboard->focus_signal, &seat->keyboard_focus_listener); - } else if (!seat->seat->keyboard_device_count) { + } else if (!keyboard) { wl_list_remove(&seat->keyboard_focus_listener.link); wl_list_init(&seat->keyboard_focus_listener.link); } - if (seat->seat->pointer_device_count && + if (pointer && wl_list_empty(&seat->pointer_focus_listener.link)) { - wl_signal_add(&seat->seat->pointer->focus_signal, + wl_signal_add(&pointer->focus_signal, &seat->pointer_focus_listener); - } else if (!seat->seat->pointer_device_count) { + } else if (!pointer) { wl_list_remove(&seat->pointer_focus_listener.link); wl_list_init(&seat->pointer_focus_listener.link); } @@ -3415,6 +3447,8 @@ add_popup_grab(struct shell_surface *shsurf, { struct weston_seat *seat = shseat->seat; struct shell_surface *parent, *top_surface; + struct weston_pointer *pointer = weston_seat_get_pointer(seat); + struct weston_touch *touch = weston_seat_get_touch(seat); parent = get_shell_surface(shsurf->parent); top_surface = get_top_popup(shseat); @@ -3441,7 +3475,7 @@ add_popup_grab(struct shell_surface *shsurf, /* We must make sure here that this popup was opened * after a mouse press, and not just by moving around * with other popups already open. */ - if (shseat->seat->pointer->button_count > 0) + if (pointer->button_count > 0) shseat->popup_grab.initial_up = 0; } else if (type == TOUCH) { shseat->popup_grab.touch_grab.interface = @@ -3452,10 +3486,10 @@ add_popup_grab(struct shell_surface *shsurf, &shsurf->popup.grab_link); if (type == POINTER) { - weston_pointer_start_grab(seat->pointer, + weston_pointer_start_grab(pointer, &shseat->popup_grab.grab); } else if (type == TOUCH) { - weston_touch_start_grab(seat->touch, + weston_touch_start_grab(touch, &shseat->popup_grab.touch_grab); } } else { @@ -3498,6 +3532,8 @@ shell_map_popup(struct shell_surface *shsurf) { struct shell_seat *shseat = shsurf->popup.shseat; struct weston_view *parent_view = get_default_view(shsurf->parent); + struct weston_pointer *pointer = weston_seat_get_pointer(shseat->seat); + struct weston_touch *touch = weston_seat_get_touch(shseat->seat); shsurf->surface->output = parent_view->output; shsurf->view->output = parent_view->output; @@ -3506,12 +3542,12 @@ shell_map_popup(struct shell_surface *shsurf) weston_view_set_position(shsurf->view, shsurf->popup.x, shsurf->popup.y); weston_view_update_transform(shsurf->view); - if (shseat->seat->pointer && - shseat->seat->pointer->grab_serial == shsurf->popup.serial) { + if (pointer && + pointer->grab_serial == shsurf->popup.serial) { if (add_popup_grab(shsurf, shseat, POINTER) != 0) return -1; - } else if (shseat->seat->touch && - shseat->seat->touch->grab_serial == shsurf->popup.serial) { + } else if (touch && + touch->grab_serial == shsurf->popup.serial) { if (add_popup_grab(shsurf, shseat, TOUCH) != 0) return -1; } else { @@ -4776,18 +4812,19 @@ do_zoom(struct weston_seat *seat, uint32_t time, uint32_t key, uint32_t axis, wl_fixed_t value) { struct weston_compositor *compositor = seat->compositor; + struct weston_pointer *pointer = weston_seat_get_pointer(seat); struct weston_output *output; float increment; - if (!seat->pointer) { + if (!pointer) { weston_log("Zoom hotkey pressed but seat '%s' contains no pointer.\n", seat->seat_name); return; } wl_list_for_each(output, &compositor->output_list, link) { if (pixman_region32_contains_point(&output->region, - wl_fixed_to_double(seat->pointer->x), - wl_fixed_to_double(seat->pointer->y), + wl_fixed_to_double(pointer->x), + wl_fixed_to_double(pointer->y), NULL)) { if (key == KEY_PAGEUP) increment = output->zoom.increment; @@ -5168,10 +5205,13 @@ unfocus_all_seats(struct desktop_shell *shell) struct weston_seat *seat, *next; wl_list_for_each_safe(seat, next, &shell->compositor->seat_list, link) { - if (seat->keyboard == NULL) + struct weston_keyboard *keyboard = + weston_seat_get_keyboard(seat); + + if (!keyboard) continue; - weston_keyboard_set_focus(seat->keyboard, NULL); + weston_keyboard_set_focus(keyboard, NULL); } } @@ -5405,10 +5445,13 @@ idle_handler(struct wl_listener *listener, void *data) struct weston_seat *seat; wl_list_for_each(seat, &shell->compositor->seat_list, link) { - if (seat->pointer) - popup_grab_end(seat->pointer); - if (seat->touch) - touch_popup_grab_end(seat->touch); + struct weston_touch *touch = weston_seat_get_touch(seat); + struct weston_pointer *pointer = weston_seat_get_pointer(seat); + + if (pointer) + popup_grab_end(pointer); + if (touch) + touch_popup_grab_end(touch); } shell_fade(shell, FADE_OUT); @@ -5456,9 +5499,11 @@ weston_view_set_initial_position(struct weston_view *view, * TODO: Do something clever for touch too? */ wl_list_for_each(seat, &compositor->seat_list, link) { - if (seat->pointer) { - ix = wl_fixed_to_int(seat->pointer->x); - iy = wl_fixed_to_int(seat->pointer->y); + struct weston_pointer *pointer = weston_seat_get_pointer(seat); + + if (pointer) { + ix = wl_fixed_to_int(pointer->x); + iy = wl_fixed_to_int(pointer->y); break; } } diff --git a/fullscreen-shell/fullscreen-shell.c b/fullscreen-shell/fullscreen-shell.c index cae6ed5f..ef9302bc 100644 --- a/fullscreen-shell/fullscreen-shell.c +++ b/fullscreen-shell/fullscreen-shell.c @@ -96,15 +96,17 @@ static void seat_caps_changed(struct wl_listener *l, void *data) { struct weston_seat *seat = data; + struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat); + struct weston_pointer *pointer = weston_seat_get_pointer(seat); struct pointer_focus_listener *listener; struct fs_output *fsout; listener = container_of(l, struct pointer_focus_listener, seat_caps); /* no pointer */ - if (seat->pointer_device_count) { + if (pointer) { if (!listener->pointer_focus.link.prev) { - wl_signal_add(&seat->pointer->focus_signal, + wl_signal_add(&pointer->focus_signal, &listener->pointer_focus); } } else { @@ -113,7 +115,7 @@ seat_caps_changed(struct wl_listener *l, void *data) } } - if (seat->keyboard_device_count && seat->keyboard->focus != NULL) { + if (keyboard && keyboard->focus != NULL) { wl_list_for_each(fsout, &listener->shell->output_list, link) { if (fsout->surface) { weston_surface_activate(fsout->surface, seat); @@ -681,7 +683,10 @@ fullscreen_shell_present_surface(struct wl_client *client, if (surface) { wl_list_for_each(seat, &shell->compositor->seat_list, link) { - if (seat->keyboard && seat->keyboard->focus == NULL) + struct weston_keyboard *keyboard = + weston_seat_get_keyboard(seat); + + if (keyboard && !keyboard->focus) weston_surface_activate(surface, seat); } } @@ -729,7 +734,10 @@ fullscreen_shell_present_surface_for_mode(struct wl_client *client, fsout, mode_feedback_destroyed); wl_list_for_each(seat, &shell->compositor->seat_list, link) { - if (seat->keyboard && seat->keyboard->focus == NULL) + struct weston_keyboard *keyboard = + weston_seat_get_keyboard(seat); + + if (keyboard && !keyboard->focus) weston_surface_activate(surface, seat); } } diff --git a/ivi-shell/hmi-controller.c b/ivi-shell/hmi-controller.c index eae346af..760bf06d 100644 --- a/ivi-shell/hmi-controller.c +++ b/ivi-shell/hmi-controller.c @@ -1469,15 +1469,18 @@ enum HMI_GRAB_DEVICE { static enum HMI_GRAB_DEVICE get_hmi_grab_device(struct weston_seat *seat, uint32_t serial) { - if (seat->pointer && - seat->pointer->focus && - seat->pointer->button_count && - seat->pointer->grab_serial == serial) + struct weston_pointer *pointer = weston_seat_get_pointer(seat); + struct weston_touch *touch = weston_seat_get_touch(seat); + + if (pointer && + pointer->focus && + pointer->button_count && + pointer->grab_serial == serial) return HMI_GRAB_DEVICE_POINTER; - if (seat->touch && - seat->touch->focus && - seat->touch->grab_serial == serial) + if (touch && + touch->focus && + touch->grab_serial == serial) return HMI_GRAB_DEVICE_TOUCH; return HMI_GRAB_DEVICE_NONE; @@ -1568,6 +1571,9 @@ ivi_hmi_controller_workspace_control(struct wl_client *client, struct pointer_move_grab *pnt_move_grab = NULL; struct touch_move_grab *tch_move_grab = NULL; struct weston_seat *seat = NULL; + struct weston_pointer *pointer; + struct weston_touch *touch; + enum HMI_GRAB_DEVICE device; if (hmi_ctrl->workspace_count < 2) @@ -1586,21 +1592,23 @@ ivi_hmi_controller_workspace_control(struct wl_client *client, switch (device) { case HMI_GRAB_DEVICE_POINTER: - pnt_move_grab = create_workspace_pointer_move(seat->pointer, + pointer = weston_seat_get_pointer(seat); + pnt_move_grab = create_workspace_pointer_move(pointer, resource); pointer_grab_start(&pnt_move_grab->base, layer, &pointer_move_grab_workspace_interface, - seat->pointer); + pointer); break; case HMI_GRAB_DEVICE_TOUCH: - tch_move_grab = create_workspace_touch_move(seat->touch, + touch = weston_seat_get_touch(seat); + tch_move_grab = create_workspace_touch_move(touch, resource); touch_grab_start(&tch_move_grab->base, layer, &touch_move_grab_workspace_interface, - seat->touch); + touch); break; default: diff --git a/ivi-shell/input-panel-ivi.c b/ivi-shell/input-panel-ivi.c index c624ef37..ecd497e0 100644 --- a/ivi-shell/input-panel-ivi.c +++ b/ivi-shell/input-panel-ivi.c @@ -70,9 +70,12 @@ show_input_panel_surface(struct input_panel_surface *ipsurf) float x, y; wl_list_for_each(seat, &shell->compositor->seat_list, link) { - if (!seat->keyboard || !seat->keyboard->focus) + struct weston_keyboard *keyboard = + weston_seat_get_keyboard(seat); + + if (!keyboard || !keyboard->focus) continue; - focus = weston_surface_get_main_surface(seat->keyboard->focus); + focus = weston_surface_get_main_surface(keyboard->focus); ipsurf->output = focus->output; x = ipsurf->output->x + (ipsurf->output->width - ipsurf->surface->width) / 2; y = ipsurf->output->y + ipsurf->output->height - ipsurf->surface->height; diff --git a/src/compositor-drm.c b/src/compositor-drm.c index 3cb6b84e..2aab6919 100644 --- a/src/compositor-drm.c +++ b/src/compositor-drm.c @@ -2075,6 +2075,7 @@ setup_output_seat_constraint(struct drm_backend *b, const char *s) { if (strcmp(s, "") != 0) { + struct weston_pointer *pointer; struct udev_seat *seat; seat = udev_seat_get_named(&b->input, s); @@ -2083,10 +2084,11 @@ setup_output_seat_constraint(struct drm_backend *b, seat->base.output = output; - if (seat->base.pointer) - weston_pointer_clamp(seat->base.pointer, - &seat->base.pointer->x, - &seat->base.pointer->y); + pointer = weston_seat_get_pointer(&seat->base); + if (pointer) + weston_pointer_clamp(pointer, + &pointer->x, + &pointer->y); } } diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c index a8e63e14..1b40e468 100644 --- a/src/compositor-wayland.c +++ b/src/compositor-wayland.c @@ -1479,7 +1479,7 @@ input_handle_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format, close(fd); - if (input->base.keyboard) + if (weston_seat_get_keyboard(&input->base)) weston_seat_update_keymap(&input->base, keymap); else weston_seat_init_keyboard(&input->base, keymap); @@ -1569,11 +1569,12 @@ input_handle_key(void *data, struct wl_keyboard *keyboard, } static void -input_handle_modifiers(void *data, struct wl_keyboard *keyboard, +input_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial_in, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) { + struct weston_keyboard *keyboard; struct wayland_input *input = data; struct wayland_backend *b = input->backend; uint32_t serial_out; @@ -1586,7 +1587,8 @@ input_handle_modifiers(void *data, struct wl_keyboard *keyboard, else serial_out = wl_display_next_serial(b->compositor->wl_display); - xkb_state_update_mask(input->base.keyboard->xkb_state.state, + 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); diff --git a/src/compositor-x11.c b/src/compositor-x11.c index 55c85edc..73ba783f 100644 --- a/src/compositor-x11.c +++ b/src/compositor-x11.c @@ -174,7 +174,9 @@ x11_backend_get_keymap(struct x11_backend *b) static uint32_t get_xkb_mod_mask(struct x11_backend *b, uint32_t in) { - struct weston_xkb_info *info = b->core_seat.keyboard->xkb_info; + struct weston_keyboard *keyboard = + weston_seat_get_keyboard(&b->core_seat); + struct weston_xkb_info *info = keyboard->xkb_info; uint32_t ret = 0; if ((in & ShiftMask) && info->shift_mod != XKB_MOD_INVALID) @@ -206,6 +208,7 @@ x11_backend_setup_xkb(struct x11_backend *b) b->xkb_event_base = 0; return; #else + struct weston_keyboard *keyboard; const xcb_query_extension_reply_t *ext; xcb_generic_error_t *error; xcb_void_cookie_t select; @@ -285,7 +288,8 @@ x11_backend_setup_xkb(struct x11_backend *b) return; } - xkb_state_update_mask(b->core_seat.keyboard->xkb_state.state, + keyboard = weston_seat_get_keyboard(&b->core_seat); + xkb_state_update_mask(keyboard->xkb_state.state, get_xkb_mod_mask(b, state_reply->baseMods), get_xkb_mod_mask(b, state_reply->latchedMods), get_xkb_mod_mask(b, state_reply->lockedMods), @@ -975,7 +979,10 @@ static void delete_cb(void *data) static void update_xkb_state(struct x11_backend *b, xcb_xkb_state_notify_event_t *state) { - xkb_state_update_mask(b->core_seat.keyboard->xkb_state.state, + struct weston_keyboard *keyboard = + weston_seat_get_keyboard(&b->core_seat); + + xkb_state_update_mask(keyboard->xkb_state.state, get_xkb_mod_mask(b, state->baseMods), get_xkb_mod_mask(b, state->latchedMods), get_xkb_mod_mask(b, state->lockedMods), @@ -1003,9 +1010,10 @@ static void update_xkb_state_from_core(struct x11_backend *b, uint16_t x11_mask) { uint32_t mask = get_xkb_mod_mask(b, x11_mask); - struct weston_keyboard *keyboard = b->core_seat.keyboard; + struct weston_keyboard *keyboard + = weston_seat_get_keyboard(&b->core_seat); - xkb_state_update_mask(b->core_seat.keyboard->xkb_state.state, + xkb_state_update_mask(keyboard->xkb_state.state, keyboard->modifiers.mods_depressed & mask, keyboard->modifiers.mods_latched & mask, keyboard->modifiers.mods_locked & mask, diff --git a/src/compositor.c b/src/compositor.c index 66c3eeee..541829ca 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -95,7 +95,7 @@ static void weston_mode_switch_finish(struct weston_output *output, /* If a pointer falls outside the outputs new geometry, move it to its * lower-right corner */ wl_list_for_each(seat, &output->compositor->seat_list, link) { - struct weston_pointer *pointer = seat->pointer; + struct weston_pointer *pointer = weston_seat_get_pointer(seat); int32_t x, y; if (!pointer) @@ -1752,15 +1752,20 @@ weston_view_unmap(struct weston_view *view) return; wl_list_for_each(seat, &view->surface->compositor->seat_list, link) { - if (seat->keyboard && seat->keyboard->focus == view->surface) - weston_keyboard_set_focus(seat->keyboard, NULL); - if (seat->pointer && seat->pointer->focus == view) - weston_pointer_set_focus(seat->pointer, + struct weston_touch *touch = weston_seat_get_touch(seat); + struct weston_pointer *pointer = weston_seat_get_pointer(seat); + struct weston_keyboard *keyboard = + weston_seat_get_keyboard(seat); + + if (keyboard && keyboard->focus == view->surface) + weston_keyboard_set_focus(keyboard, NULL); + if (pointer && pointer->focus == view) + weston_pointer_set_focus(pointer, NULL, wl_fixed_from_int(0), wl_fixed_from_int(0)); - if (seat->touch && seat->touch->focus == view) - weston_touch_set_focus(seat->touch, NULL); + if (touch && touch->focus == view) + weston_touch_set_focus(touch, NULL); } } @@ -4587,10 +4592,10 @@ weston_compositor_set_default_pointer_grab(struct weston_compositor *ec, ec->default_pointer_grab = interface; wl_list_for_each(seat, &ec->seat_list, link) { - if (seat->pointer) { - weston_pointer_set_default_grab(seat->pointer, - interface); - } + struct weston_pointer *pointer = weston_seat_get_pointer(seat); + + if (pointer) + weston_pointer_set_default_grab(pointer, interface); } } diff --git a/src/compositor.h b/src/compositor.h index b74f7e8d..2654f8dc 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -503,9 +503,9 @@ struct weston_seat { struct wl_list base_resource_list; struct wl_global *global; - struct weston_pointer *pointer; - struct weston_keyboard *keyboard; - struct weston_touch *touch; + 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; @@ -1587,6 +1587,15 @@ weston_parse_transform(const char *transform, uint32_t *out); const char * weston_transform_to_string(uint32_t output_transform); +struct weston_keyboard * +weston_seat_get_keyboard(struct weston_seat *seat); + +struct weston_pointer * +weston_seat_get_pointer(struct weston_seat *seat); + +struct weston_touch * +weston_seat_get_touch(struct weston_seat *seat); + #ifdef __cplusplus } #endif diff --git a/src/data-device.c b/src/data-device.c index 825b734c..9825bda6 100644 --- a/src/data-device.c +++ b/src/data-device.c @@ -662,23 +662,25 @@ data_device_start_drag(struct wl_client *client, struct wl_resource *resource, struct wl_resource *icon_resource, uint32_t serial) { struct weston_seat *seat = wl_resource_get_user_data(resource); + struct weston_pointer *pointer = weston_seat_get_pointer(seat); + struct weston_touch *touch = weston_seat_get_touch(seat); struct weston_surface *origin = wl_resource_get_user_data(origin_resource); struct weston_data_source *source = NULL; struct weston_surface *icon = NULL; int is_pointer_grab, is_touch_grab; int32_t ret = 0; - is_pointer_grab = seat->pointer && - seat->pointer->button_count == 1 && - seat->pointer->grab_serial == serial && - seat->pointer->focus && - seat->pointer->focus->surface == origin; + is_pointer_grab = pointer && + pointer->button_count == 1 && + pointer->grab_serial == serial && + pointer->focus && + pointer->focus->surface == origin; - is_touch_grab = seat->touch && - seat->touch->num_tp == 1 && - seat->touch->grab_serial == serial && - seat->touch->focus && - seat->touch->focus->surface == origin; + is_touch_grab = touch && + touch->num_tp == 1 && + touch->grab_serial == serial && + touch->focus && + touch->focus->surface == origin; if (!is_pointer_grab && !is_touch_grab) return; @@ -698,9 +700,9 @@ data_device_start_drag(struct wl_client *client, struct wl_resource *resource, } if (is_pointer_grab) - ret = weston_pointer_start_drag(seat->pointer, source, icon, client); + ret = weston_pointer_start_drag(pointer, source, icon, client); else if (is_touch_grab) - ret = weston_touch_start_drag(seat->touch, source, icon, client); + ret = weston_touch_start_drag(touch, source, icon, client); if (ret < 0) wl_resource_post_no_memory(resource); @@ -711,13 +713,14 @@ destroy_selection_data_source(struct wl_listener *listener, void *data) { struct weston_seat *seat = container_of(listener, struct weston_seat, selection_data_source_listener); + struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat); struct wl_resource *data_device; struct weston_surface *focus = NULL; seat->selection_data_source = NULL; - if (seat->keyboard) - focus = seat->keyboard->focus; + if (keyboard) + focus = keyboard->focus; if (focus && focus->resource) { data_device = wl_resource_find_for_client(&seat->drag_resource_list, wl_resource_get_client(focus->resource)); @@ -766,6 +769,7 @@ weston_seat_set_selection(struct weston_seat *seat, struct weston_data_source *source, uint32_t serial) { struct weston_surface *focus = NULL; + struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat); if (seat->selection_data_source && seat->selection_serial - serial < UINT32_MAX / 2) @@ -780,8 +784,8 @@ weston_seat_set_selection(struct weston_seat *seat, seat->selection_data_source = source; seat->selection_serial = serial; - if (seat->keyboard) - focus = seat->keyboard->focus; + if (keyboard) + focus = keyboard->focus; if (focus && focus->resource) { weston_seat_send_selection(seat, wl_resource_get_client(focus->resource)); } @@ -939,11 +943,12 @@ WL_EXPORT void wl_data_device_set_keyboard_focus(struct weston_seat *seat) { struct weston_surface *focus; + struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat); - if (!seat->keyboard) + if (!keyboard) return; - focus = seat->keyboard->focus; + focus = keyboard->focus; if (!focus || !focus->resource) return; diff --git a/src/input.c b/src/input.c index bbcaec5b..8f24ccd5 100644 --- a/src/input.c +++ b/src/input.c @@ -53,7 +53,7 @@ static void unbind_resource(struct wl_resource *resource) WL_EXPORT void weston_seat_repick(struct weston_seat *seat) { - const struct weston_pointer *pointer = seat->pointer; + const struct weston_pointer *pointer = weston_seat_get_pointer(seat); if (!pointer) return; @@ -391,7 +391,8 @@ default_grab_keyboard_modifiers(struct weston_keyboard_grab *grab, uint32_t mods_locked, uint32_t group) { struct weston_keyboard *keyboard = grab->keyboard; - struct weston_pointer *pointer = grab->keyboard->seat->pointer; + struct weston_pointer *pointer = + weston_seat_get_pointer(grab->keyboard->seat); struct wl_resource *resource; struct wl_list *resource_list; @@ -626,7 +627,7 @@ weston_pointer_set_focus(struct weston_pointer *pointer, struct weston_view *view, wl_fixed_t sx, wl_fixed_t sy) { - struct weston_keyboard *kbd = pointer->seat->keyboard; + struct weston_keyboard *kbd = weston_seat_get_keyboard(pointer->seat); struct wl_resource *resource; struct wl_display *display = pointer->seat->compositor->wl_display; uint32_t serial; @@ -946,7 +947,7 @@ notify_motion(struct weston_seat *seat, uint32_t time, wl_fixed_t dx, wl_fixed_t dy) { struct weston_compositor *ec = seat->compositor; - struct weston_pointer *pointer = seat->pointer; + 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); @@ -956,7 +957,7 @@ static void run_modifier_bindings(struct weston_seat *seat, uint32_t old, uint32_t new) { struct weston_compositor *compositor = seat->compositor; - struct weston_keyboard *keyboard = seat->keyboard; + struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat); uint32_t diff; unsigned int i; struct { @@ -993,7 +994,7 @@ notify_motion_absolute(struct weston_seat *seat, uint32_t time, wl_fixed_t x, wl_fixed_t y) { struct weston_compositor *ec = seat->compositor; - struct weston_pointer *pointer = seat->pointer; + struct weston_pointer *pointer = weston_seat_get_pointer(seat); weston_compositor_wake(ec); pointer->grab->interface->motion(pointer->grab, time, x, y); @@ -1004,9 +1005,10 @@ weston_surface_activate(struct weston_surface *surface, struct weston_seat *seat) { struct weston_compositor *compositor = seat->compositor; + struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat); - if (seat->keyboard) { - weston_keyboard_set_focus(seat->keyboard, surface); + if (keyboard) { + weston_keyboard_set_focus(keyboard, surface); wl_data_device_set_keyboard_focus(seat); } @@ -1018,7 +1020,7 @@ notify_button(struct weston_seat *seat, uint32_t time, int32_t button, enum wl_pointer_button_state state) { struct weston_compositor *compositor = seat->compositor; - struct weston_pointer *pointer = seat->pointer; + struct weston_pointer *pointer = weston_seat_get_pointer(seat); if (state == WL_POINTER_BUTTON_STATE_PRESSED) { weston_compositor_idle_inhibit(compositor); @@ -1049,7 +1051,7 @@ notify_axis(struct weston_seat *seat, uint32_t time, uint32_t axis, wl_fixed_t value) { struct weston_compositor *compositor = seat->compositor; - struct weston_pointer *pointer = seat->pointer; + struct weston_pointer *pointer = weston_seat_get_pointer(seat); struct wl_resource *resource; struct wl_list *resource_list; @@ -1124,7 +1126,7 @@ weston_keyboard_set_locks(struct weston_keyboard *keyboard, WL_EXPORT void notify_modifiers(struct weston_seat *seat, uint32_t serial) { - struct weston_keyboard *keyboard = seat->keyboard; + struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat); struct weston_keyboard_grab *grab = keyboard->grab; uint32_t mods_depressed, mods_latched, mods_locked, group; uint32_t mods_lookup; @@ -1196,7 +1198,7 @@ static void update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key, enum wl_keyboard_key_state state) { - struct weston_keyboard *keyboard = seat->keyboard; + struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat); enum xkb_key_direction direction; /* Keyboard modifiers don't exist in raw keyboard mode */ @@ -1240,7 +1242,7 @@ weston_xkb_info_create(struct xkb_keymap *keymap); static void update_keymap(struct weston_seat *seat) { - struct weston_keyboard *keyboard = seat->keyboard; + struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat); struct wl_resource *resource; struct weston_xkb_info *xkb_info; struct xkb_state *state; @@ -1319,7 +1321,7 @@ 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 = seat->keyboard; + struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat); struct weston_keyboard_grab *grab = keyboard->grab; uint32_t *k, *end; @@ -1376,8 +1378,10 @@ WL_EXPORT void notify_pointer_focus(struct weston_seat *seat, struct weston_output *output, wl_fixed_t x, wl_fixed_t y) { + struct weston_pointer *pointer = weston_seat_get_pointer(seat); + if (output) { - weston_pointer_move(seat->pointer, x, y); + weston_pointer_move(pointer, x, y); } else { /* FIXME: We should call weston_pointer_set_focus(seat, * NULL) here, but somehow that breaks re-entry... */ @@ -1400,7 +1404,7 @@ notify_keyboard_focus_in(struct weston_seat *seat, struct wl_array *keys, enum weston_key_state_update update_state) { struct weston_compositor *compositor = seat->compositor; - struct weston_keyboard *keyboard = seat->keyboard; + struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat); struct weston_surface *surface; uint32_t *k, serial; @@ -1426,7 +1430,8 @@ WL_EXPORT void notify_keyboard_focus_out(struct weston_seat *seat) { struct weston_compositor *compositor = seat->compositor; - struct weston_keyboard *keyboard = seat->keyboard; + struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat); + struct weston_pointer *pointer = weston_seat_get_pointer(seat); uint32_t *k, serial; serial = wl_display_next_serial(compositor->wl_display); @@ -1448,8 +1453,8 @@ notify_keyboard_focus_out(struct weston_seat *seat) weston_keyboard_set_focus(keyboard, NULL); weston_keyboard_cancel_grab(keyboard); - if (seat->pointer) - weston_pointer_cancel_grab(seat->pointer); + if (pointer) + weston_pointer_cancel_grab(pointer); } WL_EXPORT void @@ -1507,7 +1512,7 @@ notify_touch(struct weston_seat *seat, uint32_t time, int touch_id, wl_fixed_t x, wl_fixed_t y, int touch_type) { struct weston_compositor *ec = seat->compositor; - struct weston_touch *touch = seat->touch; + struct weston_touch *touch = weston_seat_get_touch(seat); struct weston_touch_grab *grab = touch->grab; struct weston_view *ev; wl_fixed_t sx, sy; @@ -1586,7 +1591,7 @@ notify_touch(struct weston_seat *seat, uint32_t time, int touch_id, WL_EXPORT void notify_touch_frame(struct weston_seat *seat) { - struct weston_touch *touch = seat->touch; + struct weston_touch *touch = weston_seat_get_touch(seat); struct weston_touch_grab *grab = touch->grab; grab->interface->frame(grab); @@ -1706,9 +1711,18 @@ 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 (!seat->pointer) + if (!pointer) return; cr = wl_resource_create(client, &wl_pointer_interface, @@ -1721,25 +1735,25 @@ seat_get_pointer(struct wl_client *client, struct wl_resource *resource, /* May be moved to focused list later by either * weston_pointer_set_focus or directly if this client is already * focused */ - wl_list_insert(&seat->pointer->resource_list, wl_resource_get_link(cr)); - wl_resource_set_implementation(cr, &pointer_interface, seat->pointer, + wl_list_insert(&pointer->resource_list, wl_resource_get_link(cr)); + wl_resource_set_implementation(cr, &pointer_interface, pointer, unbind_resource); - if (seat->pointer->focus && seat->pointer->focus->surface->resource && - wl_resource_get_client(seat->pointer->focus->surface->resource) == client) { + if (pointer->focus && pointer->focus->surface->resource && + wl_resource_get_client(pointer->focus->surface->resource) == client) { wl_fixed_t sx, sy; - weston_view_from_global_fixed(seat->pointer->focus, - seat->pointer->x, - seat->pointer->y, + weston_view_from_global_fixed(pointer->focus, + pointer->x, + pointer->y, &sx, &sy); wl_list_remove(wl_resource_get_link(cr)); - wl_list_insert(&seat->pointer->focus_resource_list, + wl_list_insert(&pointer->focus_resource_list, wl_resource_get_link(cr)); wl_pointer_send_enter(cr, - seat->pointer->focus_serial, - seat->pointer->focus->surface->resource, + pointer->focus_serial, + pointer->focus->surface->resource, sx, sy); } } @@ -1758,16 +1772,19 @@ static bool should_send_modifiers_to_client(struct weston_seat *seat, struct wl_client *client) { - if (seat->keyboard && - seat->keyboard->focus && - seat->keyboard->focus->resource && - wl_resource_get_client(seat->keyboard->focus->resource) == client) + struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat); + struct weston_pointer *pointer = weston_seat_get_pointer(seat); + + if (keyboard && + keyboard->focus && + keyboard->focus->resource && + wl_resource_get_client(keyboard->focus->resource) == client) return true; - if (seat->pointer && - seat->pointer->focus && - seat->pointer->focus->surface->resource && - wl_resource_get_client(seat->pointer->focus->surface->resource) == client) + if (pointer && + pointer->focus && + pointer->focus->surface->resource && + wl_resource_get_client(pointer->focus->surface->resource) == client) return true; return false; @@ -1778,7 +1795,15 @@ seat_get_keyboard(struct wl_client *client, struct wl_resource *resource, uint32_t id) { struct weston_seat *seat = wl_resource_get_user_data(resource); - struct weston_keyboard *keyboard = seat->keyboard; + /* 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) @@ -1858,9 +1883,18 @@ 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 (!seat->touch) + if (!touch) return; cr = wl_resource_create(client, &wl_touch_interface, @@ -1870,12 +1904,12 @@ seat_get_touch(struct wl_client *client, struct wl_resource *resource, return; } - if (seat->touch->focus && - wl_resource_get_client(seat->touch->focus->surface->resource) == client) { - wl_list_insert(&seat->touch->resource_list, + if (touch->focus && + wl_resource_get_client(touch->focus->surface->resource) == client) { + wl_list_insert(&touch->resource_list, wl_resource_get_link(cr)); } else { - wl_list_insert(&seat->touch->focus_resource_list, + wl_list_insert(&touch->focus_resource_list, wl_resource_get_link(cr)); } wl_resource_set_implementation(cr, &touch_interface, @@ -1901,11 +1935,11 @@ bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id) wl_resource_set_implementation(resource, &seat_interface, data, unbind_resource); - if (seat->pointer_device_count) + if (weston_seat_get_pointer(seat)) caps |= WL_SEAT_CAPABILITY_POINTER; - if (seat->keyboard_device_count) + if (weston_seat_get_keyboard(seat)) caps |= WL_SEAT_CAPABILITY_KEYBOARD; - if (seat->touch_device_count) + if (weston_seat_get_touch(seat)) caps |= WL_SEAT_CAPABILITY_TOUCH; wl_seat_send_capabilities(resource, caps); @@ -2095,17 +2129,19 @@ weston_compositor_xkb_destroy(struct weston_compositor *ec) WL_EXPORT void weston_seat_update_keymap(struct weston_seat *seat, struct xkb_keymap *keymap) { - if (!seat->keyboard || !keymap) + struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat); + + if (!keyboard || !keymap) return; #ifdef ENABLE_XKBCOMMON if (!seat->compositor->use_xkbcommon) return; - xkb_keymap_unref(seat->keyboard->pending_keymap); - seat->keyboard->pending_keymap = xkb_keymap_ref(keymap); + xkb_keymap_unref(keyboard->pending_keymap); + keyboard->pending_keymap = xkb_keymap_ref(keymap); - if (seat->keyboard->keys.size == 0) + if (keyboard->keys.size == 0) update_keymap(seat); #endif } @@ -2115,7 +2151,7 @@ weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap) { struct weston_keyboard *keyboard; - if (seat->keyboard) { + if (seat->keyboard_state) { seat->keyboard_device_count += 1; if (seat->keyboard_device_count == 1) seat_send_updated_caps(seat); @@ -2151,7 +2187,7 @@ weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap) } #endif - seat->keyboard = keyboard; + seat->keyboard_state = keyboard; seat->keyboard_device_count = 1; keyboard->seat = seat; @@ -2196,9 +2232,9 @@ weston_seat_release_keyboard(struct weston_seat *seat) seat->keyboard_device_count--; assert(seat->keyboard_device_count >= 0); if (seat->keyboard_device_count == 0) { - weston_keyboard_set_focus(seat->keyboard, NULL); - weston_keyboard_cancel_grab(seat->keyboard); - weston_keyboard_reset_state(seat->keyboard); + weston_keyboard_set_focus(seat->keyboard_state, NULL); + weston_keyboard_cancel_grab(seat->keyboard_state); + weston_keyboard_reset_state(seat->keyboard_state); seat_send_updated_caps(seat); } } @@ -2208,7 +2244,7 @@ weston_seat_init_pointer(struct weston_seat *seat) { struct weston_pointer *pointer; - if (seat->pointer) { + if (seat->pointer_state) { seat->pointer_device_count += 1; if (seat->pointer_device_count == 1) seat_send_updated_caps(seat); @@ -2219,7 +2255,7 @@ weston_seat_init_pointer(struct weston_seat *seat) if (pointer == NULL) return; - seat->pointer = pointer; + seat->pointer_state = pointer; seat->pointer_device_count = 1; pointer->seat = seat; @@ -2229,7 +2265,7 @@ weston_seat_init_pointer(struct weston_seat *seat) WL_EXPORT void weston_seat_release_pointer(struct weston_seat *seat) { - struct weston_pointer *pointer = seat->pointer; + struct weston_pointer *pointer = seat->pointer_state; seat->pointer_device_count--; if (seat->pointer_device_count == 0) { @@ -2256,7 +2292,7 @@ weston_seat_init_touch(struct weston_seat *seat) { struct weston_touch *touch; - if (seat->touch) { + if (seat->touch_state) { seat->touch_device_count += 1; if (seat->touch_device_count == 1) seat_send_updated_caps(seat); @@ -2267,7 +2303,7 @@ weston_seat_init_touch(struct weston_seat *seat) if (touch == NULL) return; - seat->touch = touch; + seat->touch_state = touch; seat->touch_device_count = 1; touch->seat = seat; @@ -2279,9 +2315,9 @@ weston_seat_release_touch(struct weston_seat *seat) { seat->touch_device_count--; if (seat->touch_device_count == 0) { - weston_touch_set_focus(seat->touch, NULL); - weston_touch_cancel_grab(seat->touch); - weston_touch_reset_state(seat->touch); + weston_touch_set_focus(seat->touch_state, NULL); + weston_touch_cancel_grab(seat->touch_state); + weston_touch_reset_state(seat->touch_state); seat_send_updated_caps(seat); } } @@ -2321,12 +2357,12 @@ weston_seat_release(struct weston_seat *seat) if (seat->saved_kbd_focus) wl_list_remove(&seat->saved_kbd_focus_listener.link); - if (seat->pointer) - weston_pointer_destroy(seat->pointer); - if (seat->keyboard) - weston_keyboard_destroy(seat->keyboard); - if (seat->touch) - weston_touch_destroy(seat->touch); + if (seat->pointer_state) + weston_pointer_destroy(seat->pointer_state); + if (seat->keyboard_state) + weston_keyboard_destroy(seat->keyboard_state); + if (seat->touch_state) + weston_touch_destroy(seat->touch_state); free (seat->seat_name); @@ -2334,3 +2370,69 @@ weston_seat_release(struct weston_seat *seat) wl_signal_emit(&seat->destroy_signal, seat); } + +/** Get a seat's keyboard pointer + * + * \param seat The seat to query + * \return The seat's keyboard pointer, or NULL if no keyboard is present + * + * The keyboard pointer for a seat isn't freed when all keyboards are removed, + * so it should only be used when the seat's keyboard_device_count is greater + * than zero. This function does that test and only returns a pointer + * when a keyboard is present. + */ +WL_EXPORT struct weston_keyboard * +weston_seat_get_keyboard(struct weston_seat *seat) +{ + if (!seat) + return NULL; + + if (seat->keyboard_device_count) + return seat->keyboard_state; + + return NULL; +} + +/** Get a seat's pointer pointer + * + * \param seat The seat to query + * \return The seat's pointer pointer, or NULL if no pointer device is present + * + * The pointer pointer for a seat isn't freed when all mice are removed, + * so it should only be used when the seat's pointer_device_count is greater + * than zero. This function does that test and only returns a pointer + * when a pointing device is present. + */ +WL_EXPORT struct weston_pointer * +weston_seat_get_pointer(struct weston_seat *seat) +{ + if (!seat) + return NULL; + + if (seat->pointer_device_count) + return seat->pointer_state; + + return NULL; +} + +/** Get a seat's touch pointer + * + * \param seat The seat to query + * \return The seat's touch pointer, or NULL if no touch device is present + * + * The touch pointer for a seat isn't freed when all touch devices are removed, + * so it should only be used when the seat's touch_device_count is greater + * than zero. This function does that test and only returns a pointer + * when a touch device is present. + */ +WL_EXPORT struct weston_touch * +weston_seat_get_touch(struct weston_seat *seat) +{ + if (!seat) + return NULL; + + if (seat->touch_device_count) + return seat->touch_state; + + return NULL; +} diff --git a/src/libinput-seat.c b/src/libinput-seat.c index 6353667f..e6d44b0f 100644 --- a/src/libinput-seat.c +++ b/src/libinput-seat.c @@ -60,6 +60,7 @@ device_added(struct udev_input *input, struct libinput_device *libinput_device) struct libinput_seat *libinput_seat; struct weston_seat *seat; struct udev_seat *udev_seat; + struct weston_pointer *pointer; c = input->compositor; libinput_seat = libinput_device_get_seat(libinput_device); @@ -77,10 +78,11 @@ device_added(struct udev_input *input, struct libinput_device *libinput_device) udev_seat = (struct udev_seat *) seat; wl_list_insert(udev_seat->devices_list.prev, &device->link); - if (seat->output && seat->pointer) - weston_pointer_clamp(seat->pointer, - &seat->pointer->x, - &seat->pointer->y); + pointer = weston_seat_get_pointer(seat); + if (seat->output && pointer) + weston_pointer_clamp(pointer, + &pointer->x, + &pointer->y); output_name = libinput_device_get_output_name(libinput_device); if (output_name) { @@ -378,8 +380,11 @@ udev_seat_create(struct udev_input *input, const char *seat_name) static void udev_seat_destroy(struct udev_seat *seat) { + struct weston_keyboard *keyboard = + weston_seat_get_keyboard(&seat->base); + udev_seat_remove_devices(seat); - if (seat->base.keyboard) + if (keyboard) notify_keyboard_focus_out(&seat->base); weston_seat_release(&seat->base); wl_list_remove(&seat->output_create_listener.link); diff --git a/src/main.c b/src/main.c index 0017ab5c..4acb913b 100644 --- a/src/main.c +++ b/src/main.c @@ -798,8 +798,11 @@ int main(int argc, char *argv[]) weston_config_section_get_bool(section, "numlock-on", &numlock_on, 0); if (numlock_on) { wl_list_for_each(seat, &ec->seat_list, link) { - if (seat->keyboard) - weston_keyboard_set_locks(seat->keyboard, + struct weston_keyboard *keyboard = + weston_seat_get_keyboard(seat); + + if (keyboard) + weston_keyboard_set_locks(keyboard, WESTON_NUM_LOCK, WESTON_NUM_LOCK); } diff --git a/src/text-backend.c b/src/text-backend.c index 76e4e155..cd6c4d99 100644 --- a/src/text-backend.c +++ b/src/text-backend.c @@ -658,7 +658,7 @@ input_method_context_grab_keyboard(struct wl_client *client, wl_resource_get_user_data(resource); struct wl_resource *cr; struct weston_seat *seat = context->input_method->seat; - struct weston_keyboard *keyboard = seat->keyboard; + struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat); cr = wl_resource_create(client, &wl_keyboard_interface, 1, id); wl_resource_set_implementation(cr, NULL, context, unbind_keyboard); @@ -687,7 +687,7 @@ 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 = seat->keyboard; + struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat); struct weston_keyboard_grab *default_grab = &keyboard->default_grab; default_grab->interface->key(default_grab, time, key, state_w); @@ -706,7 +706,7 @@ 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 = seat->keyboard; + struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat); struct weston_keyboard_grab *default_grab = &keyboard->default_grab; default_grab->interface->modifiers(default_grab, @@ -812,10 +812,11 @@ input_method_context_end_keyboard_grab(struct input_method_context *context) struct weston_keyboard_grab *grab; struct weston_keyboard *keyboard; - if (!context->input_method->seat->keyboard) + keyboard = weston_seat_get_keyboard(context->input_method->seat); + if (!keyboard) return; - grab = &context->input_method->seat->keyboard->input_method_grab; + grab = &keyboard->input_method_grab; keyboard = grab->keyboard; if (!keyboard) return; @@ -907,15 +908,17 @@ handle_keyboard_focus(struct wl_listener *listener, void *data) static void input_method_init_seat(struct weston_seat *seat) { + struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat); + if (seat->input_method->focus_listener_initialized) return; - if (seat->keyboard) { + if (keyboard) { seat->input_method->keyboard_focus_listener.notify = handle_keyboard_focus; - wl_signal_add(&seat->keyboard->focus_signal, + wl_signal_add(&keyboard->focus_signal, &seat->input_method->keyboard_focus_listener); - seat->keyboard->input_method_grab.interface = + keyboard->input_method_grab.interface = &input_method_context_grab; } diff --git a/src/zoom.c b/src/zoom.c index efc658c3..8eb20fe4 100644 --- a/src/zoom.c +++ b/src/zoom.c @@ -129,11 +129,12 @@ WL_EXPORT void weston_output_update_zoom(struct weston_output *output) { struct weston_seat *seat = output->zoom.seat; + struct weston_pointer *pointer = weston_seat_get_pointer(seat); assert(output->zoom.active); - output->zoom.current.x = seat->pointer->x; - output->zoom.current.y = seat->pointer->y; + output->zoom.current.x = pointer->x; + output->zoom.current.y = pointer->y; weston_zoom_transition(output); weston_output_update_zoom_transform(output); @@ -154,13 +155,15 @@ WL_EXPORT void weston_output_activate_zoom(struct weston_output *output, struct weston_seat *seat) { + struct weston_pointer *pointer = weston_seat_get_pointer(seat); + if (output->zoom.active) return; output->zoom.active = true; output->zoom.seat = seat; output->disable_planes++; - wl_signal_add(&seat->pointer->motion_signal, + wl_signal_add(&pointer->motion_signal, &output->zoom.motion_listener); } diff --git a/tests/surface-screenshot.c b/tests/surface-screenshot.c index a54ae22e..703d48b0 100644 --- a/tests/surface-screenshot.c +++ b/tests/surface-screenshot.c @@ -139,6 +139,7 @@ trigger_binding(struct weston_keyboard *keyboard, uint32_t time, uint32_t key, char fname[1024]; struct weston_surface *surface; struct weston_seat *seat = keyboard->seat; + struct weston_pointer *pointer = weston_seat_get_pointer(seat); int width, height; char desc[512]; void *pixels; @@ -147,12 +148,10 @@ trigger_binding(struct weston_keyboard *keyboard, uint32_t time, uint32_t key, int ret; FILE *fp; - if (seat->pointer_device_count == 0 || - !seat->pointer || - !seat->pointer->focus) + if (!pointer || !pointer->focus) return; - surface = seat->pointer->focus->surface; + surface = pointer->focus->surface; weston_surface_get_content_size(surface, &width, &height); diff --git a/tests/weston-test.c b/tests/weston-test.c index df9a1391..b593f1e8 100644 --- a/tests/weston-test.c +++ b/tests/weston-test.c @@ -83,7 +83,7 @@ static void notify_pointer_position(struct weston_test *test, struct wl_resource *resource) { struct weston_seat *seat = get_seat(test); - struct weston_pointer *pointer = seat->pointer; + struct weston_pointer *pointer = weston_seat_get_pointer(seat); weston_test_send_pointer_position(resource, pointer->x, pointer->y); } @@ -144,7 +144,7 @@ move_pointer(struct wl_client *client, struct wl_resource *resource, { struct weston_test *test = wl_resource_get_user_data(resource); struct weston_seat *seat = get_seat(test); - struct weston_pointer *pointer = seat->pointer; + struct weston_pointer *pointer = weston_seat_get_pointer(seat); notify_motion(seat, 100, wl_fixed_from_int(x) - pointer->x, @@ -171,12 +171,13 @@ activate_surface(struct wl_client *client, struct wl_resource *resource, wl_resource_get_user_data(surface_resource) : NULL; struct weston_test *test = wl_resource_get_user_data(resource); struct weston_seat *seat; + struct weston_keyboard *keyboard; seat = get_seat(test); - + keyboard = weston_seat_get_keyboard(seat); if (surface) { weston_surface_activate(surface, seat); - notify_keyboard_focus_in(seat, &seat->keyboard->keys, + notify_keyboard_focus_in(seat, &keyboard->keys, STATE_UPDATE_AUTOMATIC); } else { diff --git a/xwayland/dnd.c b/xwayland/dnd.c index eb9c5dd1..a036b30f 100644 --- a/xwayland/dnd.c +++ b/xwayland/dnd.c @@ -154,6 +154,7 @@ handle_enter(struct weston_wm *wm, xcb_client_message_event_t *client_message) { struct dnd_data_source *source; struct weston_seat *seat = weston_wm_pick_seat(wm); + struct weston_pointer *pointer = weston_seat_get_pointer(seat); char **p; const char *name; uint32_t *types; @@ -213,7 +214,7 @@ handle_enter(struct weston_wm *wm, xcb_client_message_event_t *client_message) } free(reply); - weston_pointer_start_drag(seat->pointer, &source->base, NULL, NULL); + weston_pointer_start_drag(pointer, &source->base, NULL, NULL); } int diff --git a/xwayland/window-manager.c b/xwayland/window-manager.c index c3a57c19..daebf47d 100644 --- a/xwayland/window-manager.c +++ b/xwayland/window-manager.c @@ -1316,12 +1316,16 @@ weston_wm_pick_seat_for_window(struct weston_wm_window *window) seat = NULL; wl_list_for_each(s, &wm->server->compositor->seat_list, link) { - if (s->pointer != NULL && s->pointer->focus && - s->pointer->focus->surface == window->surface && - s->pointer->button_count > 0 && - (seat == NULL || - s->pointer->grab_serial - - seat->pointer->grab_serial < (1 << 30))) + struct weston_pointer *pointer = weston_seat_get_pointer(s); + struct weston_pointer *old_pointer = + weston_seat_get_pointer(seat); + + if (pointer && pointer->focus && + pointer->focus->surface == window->surface && + pointer->button_count > 0 && + (!seat || + pointer->grab_serial - + old_pointer->grab_serial < (1 << 30))) seat = s; } @@ -1345,13 +1349,14 @@ weston_wm_window_handle_moveresize(struct weston_wm_window *window, struct weston_wm *wm = window->wm; struct weston_seat *seat = weston_wm_pick_seat_for_window(window); + struct weston_pointer *pointer = weston_seat_get_pointer(seat); int detail; struct weston_shell_interface *shell_interface = &wm->server->compositor->shell_interface; - if (seat == NULL || seat->pointer->button_count != 1 - || !seat->pointer->focus - || seat->pointer->focus->surface != window->surface) + if (!pointer || pointer->button_count != 1 + || !pointer->focus + || pointer->focus->surface != window->surface) return; detail = client_message->data.data32[2];