From b9d2a0fc0a16f470c48851bd52d33c91ea791296 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Thu, 28 Jun 2012 18:08:05 +0300 Subject: [PATCH] shell: Show approprite cursors during move and resize grabs This patch expands the busy cursor mechanism so that it is possible for the desktop-shell client to show the appropriate cursor during grabs. --- clients/desktop-shell.c | 81 +++++++++++++++++++++++++++++++------- protocol/desktop-shell.xml | 37 ++++++++++++++++- src/shell.c | 79 +++++++++++++++++-------------------- 3 files changed, 138 insertions(+), 59 deletions(-) diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c index cc1028f6..0605f844 100644 --- a/clients/desktop-shell.c +++ b/clients/desktop-shell.c @@ -50,8 +50,10 @@ struct desktop { struct task unlock_task; struct wl_list outputs; - struct window *busy_window; - struct widget *busy_widget; + struct window *grab_window; + struct widget *grab_widget; + + enum desktop_shell_cursor grab_cursor; }; struct surface { @@ -742,9 +744,54 @@ desktop_shell_prepare_lock_surface(void *data, } } +static void +desktop_shell_grab_cursor(void *data, + struct desktop_shell *desktop_shell, + uint32_t cursor) +{ + struct desktop *desktop = data; + + switch (cursor) { + case DESKTOP_SHELL_CURSOR_BUSY: + desktop->grab_cursor = CURSOR_WATCH; + break; + case DESKTOP_SHELL_CURSOR_MOVE: + desktop->grab_cursor = CURSOR_DRAGGING; + break; + case DESKTOP_SHELL_CURSOR_RESIZE_TOP: + desktop->grab_cursor = CURSOR_TOP; + break; + case DESKTOP_SHELL_CURSOR_RESIZE_BOTTOM: + desktop->grab_cursor = CURSOR_BOTTOM; + break; + case DESKTOP_SHELL_CURSOR_RESIZE_LEFT: + desktop->grab_cursor = CURSOR_LEFT; + break; + case DESKTOP_SHELL_CURSOR_RESIZE_RIGHT: + desktop->grab_cursor = CURSOR_RIGHT; + break; + case DESKTOP_SHELL_CURSOR_RESIZE_TOP_LEFT: + desktop->grab_cursor = CURSOR_TOP_LEFT; + break; + case DESKTOP_SHELL_CURSOR_RESIZE_TOP_RIGHT: + desktop->grab_cursor = CURSOR_TOP_RIGHT; + break; + case DESKTOP_SHELL_CURSOR_RESIZE_BOTTOM_LEFT: + desktop->grab_cursor = CURSOR_BOTTOM_LEFT; + break; + case DESKTOP_SHELL_CURSOR_RESIZE_BOTTOM_RIGHT: + desktop->grab_cursor = CURSOR_BOTTOM_RIGHT; + break; + case DESKTOP_SHELL_CURSOR_ARROW: + default: + desktop->grab_cursor = CURSOR_LEFT_PTR; + } +} + static const struct desktop_shell_listener listener = { desktop_shell_configure, - desktop_shell_prepare_lock_surface + desktop_shell_prepare_lock_surface, + desktop_shell_grab_cursor }; static struct background * @@ -765,29 +812,33 @@ background_create(struct desktop *desktop) } static int -busy_surface_enter_handler(struct widget *widget, struct input *input, +grab_surface_enter_handler(struct widget *widget, struct input *input, float x, float y, void *data) { - return CURSOR_WATCH; + struct desktop *desktop = data; + + return desktop->grab_cursor; } static void -busy_surface_create(struct desktop *desktop) +grab_surface_create(struct desktop *desktop) { struct wl_surface *s; - desktop->busy_window = window_create(desktop->display); - s = window_get_wl_surface(desktop->busy_window); - desktop_shell_set_busy_surface(desktop->shell, s); + desktop->grab_window = window_create(desktop->display); + window_set_user_data(desktop->grab_window, desktop); - desktop->busy_widget = - window_add_widget(desktop->busy_window, desktop); + s = window_get_wl_surface(desktop->grab_window); + desktop_shell_set_grab_surface(desktop->shell, s); + + desktop->grab_widget = + window_add_widget(desktop->grab_window, desktop); /* We set the allocation to 1x1 at 0,0 so the fake enter event * at 0,0 will go to this widget. */ - widget_set_allocation(desktop->busy_widget, 0, 0, 1, 1); + widget_set_allocation(desktop->grab_widget, 0, 0, 1, 1); - widget_set_enter_handler(desktop->busy_widget, - busy_surface_enter_handler); + widget_set_enter_handler(desktop->grab_widget, + grab_surface_enter_handler); } static void @@ -887,7 +938,7 @@ int main(int argc, char *argv[]) output->output, surface); } - busy_surface_create(&desktop); + grab_surface_create(&desktop); config_file = config_file_path("weston.ini"); ret = parse_config_file(config_file, diff --git a/protocol/desktop-shell.xml b/protocol/desktop-shell.xml index 687f169e..2b6afbd2 100644 --- a/protocol/desktop-shell.xml +++ b/protocol/desktop-shell.xml @@ -23,7 +23,13 @@ - + + + The surface set by this request will receive a fake + pointer.enter event during grabs at position 0, 0 and is + expected to set an appropriate cursor image as described by + the grab_cursor event sent just before the enter event. + @@ -45,6 +51,35 @@ desktop resume. + + + + This event will be sent immediately before a fake enter event on the + grab surface. + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/shell.c b/src/shell.c index 22229701..b477bbe6 100644 --- a/src/shell.c +++ b/src/shell.c @@ -78,7 +78,7 @@ struct desktop_shell { struct weston_layer lock_layer; struct wl_listener pointer_focus_listener; - struct weston_surface *busy_surface; + struct weston_surface *grab_surface; struct { struct weston_process process; @@ -198,6 +198,7 @@ struct shell_grab { struct wl_pointer_grab grab; struct shell_surface *shsurf; struct wl_listener shsurf_destroy_listener; + struct wl_pointer *pointer; }; struct weston_move_grab { @@ -249,23 +250,36 @@ destroy_shell_grab_shsurf(struct wl_listener *listener, void *data) } static void -shell_grab_init(struct shell_grab *grab, - const struct wl_pointer_grab_interface *interface, - struct shell_surface *shsurf) +shell_grab_start(struct shell_grab *grab, + const struct wl_pointer_grab_interface *interface, + struct shell_surface *shsurf, + struct wl_pointer *pointer, + enum desktop_shell_cursor cursor) { + struct desktop_shell *shell = shsurf->shell; + grab->grab.interface = interface; grab->shsurf = shsurf; grab->shsurf_destroy_listener.notify = destroy_shell_grab_shsurf; wl_signal_add(&shsurf->resource.destroy_signal, &grab->shsurf_destroy_listener); + grab->pointer = pointer; + grab->grab.focus = &shsurf->surface->surface; + + wl_pointer_start_grab(pointer, &grab->grab); + desktop_shell_send_grab_cursor(shell->child.desktop_shell, cursor); + wl_pointer_set_focus(pointer, &shell->grab_surface->surface, + wl_fixed_from_int(0), wl_fixed_from_int(0)); } static void -shell_grab_finish(struct shell_grab *grab) +shell_grab_end(struct shell_grab *grab) { if (grab->shsurf) wl_list_remove(&grab->shsurf_destroy_listener.link); + + wl_pointer_end_grab(grab->pointer); } static void @@ -795,7 +809,7 @@ move_grab_button(struct wl_pointer_grab *grab, if (pointer->button_count == 0 && state == WL_POINTER_BUTTON_STATE_RELEASED) { - shell_grab_finish(shell_grab); + shell_grab_end(shell_grab); wl_pointer_end_grab(pointer); free(grab); } @@ -815,7 +829,7 @@ busy_cursor_grab_focus(struct wl_pointer_grab *base, struct wl_pointer *pointer = base->pointer; if (grab->grab.focus != surface) { - shell_grab_finish(grab); + shell_grab_end(grab); wl_pointer_end_grab(pointer); free(grab); } @@ -843,16 +857,13 @@ static void set_busy_cursor(struct shell_surface *shsurf, struct wl_pointer *pointer) { struct shell_grab *grab; - struct desktop_shell *shell = shsurf->shell; grab = malloc(sizeof *grab); if (!grab) return; - shell_grab_init(grab, &busy_cursor_grab_interface, shsurf); - grab->grab.focus = &shsurf->surface->surface; - wl_pointer_start_grab(pointer, &grab->grab); - wl_pointer_set_focus(pointer, &shell->busy_surface->surface, 0, 0); + shell_grab_start(grab, &busy_cursor_grab_interface, shsurf, pointer, + DESKTOP_SHELL_CURSOR_BUSY); } static void @@ -861,8 +872,7 @@ end_busy_cursor(struct shell_surface *shsurf, struct wl_pointer *pointer) struct shell_grab *grab = (struct shell_grab *) pointer->grab; if (grab->grab.interface == &busy_cursor_grab_interface) { - shell_grab_finish(grab); - wl_pointer_end_grab(pointer); + shell_grab_end(grab); free(grab); } } @@ -966,7 +976,7 @@ shell_surface_pong(struct wl_client *client, struct wl_resource *resource, wl_list_for_each(seat, &ec->seat_list, link) { pointer = seat->seat.pointer; if (pointer->focus == - &shell->busy_surface->surface && + &shell->grab_surface->surface && pointer->current == &shsurf->surface->surface) end_busy_cursor(shsurf, pointer); @@ -1008,18 +1018,13 @@ surface_move(struct shell_surface *shsurf, struct weston_seat *ws) if (!move) return -1; - shell_grab_init(&move->base, &move_grab_interface, shsurf); - move->dx = wl_fixed_from_double(shsurf->surface->geometry.x) - ws->seat.pointer->grab_x; move->dy = wl_fixed_from_double(shsurf->surface->geometry.y) - ws->seat.pointer->grab_y; - wl_pointer_start_grab(ws->seat.pointer, &move->base.grab); - - wl_pointer_set_focus(ws->seat.pointer, NULL, - wl_fixed_from_int(0), - wl_fixed_from_int(0)); + shell_grab_start(&move->base, &move_grab_interface, shsurf, + ws->seat.pointer, DESKTOP_SHELL_CURSOR_MOVE); return 0; } @@ -1108,8 +1113,7 @@ resize_grab_button(struct wl_pointer_grab *grab, if (pointer->button_count == 0 && state == WL_POINTER_BUTTON_STATE_RELEASED) { - shell_grab_finish(&resize->base); - wl_pointer_end_grab(pointer); + shell_grab_end(&resize->base); free(grab); } } @@ -1137,17 +1141,12 @@ surface_resize(struct shell_surface *shsurf, if (!resize) return -1; - shell_grab_init(&resize->base, &resize_grab_interface, shsurf); - resize->edges = edges; resize->width = shsurf->surface->geometry.width; resize->height = shsurf->surface->geometry.height; - wl_pointer_start_grab(ws->seat.pointer, &resize->base.grab); - - wl_pointer_set_focus(ws->seat.pointer, NULL, - wl_fixed_from_int(0), - wl_fixed_from_int(0)); + shell_grab_start(&resize->base, &resize_grab_interface, shsurf, + ws->seat.pointer, edges); return 0; } @@ -2009,13 +2008,13 @@ desktop_shell_unlock(struct wl_client *client, } static void -desktop_shell_set_busy_surface(struct wl_client *client, +desktop_shell_set_grab_surface(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface_resource) { struct desktop_shell *shell = resource->data; - shell->busy_surface = surface_resource->data; + shell->grab_surface = surface_resource->data; } static const struct desktop_shell_interface desktop_shell_implementation = { @@ -2023,7 +2022,7 @@ static const struct desktop_shell_interface desktop_shell_implementation = { desktop_shell_set_panel, desktop_shell_set_lock_surface, desktop_shell_unlock, - desktop_shell_set_busy_surface + desktop_shell_set_grab_surface }; static enum shell_surface_type @@ -2266,8 +2265,7 @@ rotate_grab_button(struct wl_pointer_grab *grab, if (shsurf) weston_matrix_multiply(&shsurf->rotation.rotation, &rotate->rotation); - shell_grab_finish(&rotate->base); - wl_pointer_end_grab(pointer); + shell_grab_end(&rotate->base); free(rotate); } } @@ -2300,15 +2298,11 @@ rotate_binding(struct wl_seat *seat, uint32_t time, uint32_t button, if (!rotate) return; - shell_grab_init(&rotate->base, &rotate_grab_interface, surface); - weston_surface_to_global_float(surface->surface, surface->surface->geometry.width / 2, surface->surface->geometry.height / 2, &rotate->center.x, &rotate->center.y); - wl_pointer_start_grab(seat->pointer, &rotate->base.grab); - dx = wl_fixed_to_double(seat->pointer->x) - rotate->center.x; dy = wl_fixed_to_double(seat->pointer->y) - rotate->center.y; r = sqrtf(dx * dx + dy * dy); @@ -2332,9 +2326,8 @@ rotate_binding(struct wl_seat *seat, uint32_t time, uint32_t button, weston_matrix_init(&rotate->rotation); } - wl_pointer_set_focus(seat->pointer, NULL, - wl_fixed_from_int(0), - wl_fixed_from_int(0)); + shell_grab_start(&rotate->base, &rotate_grab_interface, surface, + seat->pointer, DESKTOP_SHELL_CURSOR_ARROW); } static void