shell: Show approprite cursors during move and resize grabs
authorAnder Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Thu, 28 Jun 2012 15:08:05 +0000 (18:08 +0300)
committerKristian Høgsberg <krh@bitplanet.net>
Thu, 28 Jun 2012 18:13:57 +0000 (14:13 -0400)
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
protocol/desktop-shell.xml
src/shell.c

index cc1028f..0605f84 100644 (file)
@@ -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);
+
+       s = window_get_wl_surface(desktop->grab_window);
+       desktop_shell_set_grab_surface(desktop->shell, s);
 
-       desktop->busy_widget =
-               window_add_widget(desktop->busy_window, desktop);
+       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,
index 687f169..2b6afbd 100644 (file)
 
     <request name="unlock"/>
 
-    <request name="set_busy_surface">
+    <request name="set_grab_surface">
+      <description summary="set grab surface">
+       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.
+      </description>
       <arg name="surface" type="object" interface="wl_surface"/>
     </request>
 
         desktop resume.
       </description>
     </event>
+
+    <event name="grab_cursor">
+      <description summary="tell client what cursor to show during a grab">
+       This event will be sent immediately before a fake enter event on the
+       grab surface.
+      </description>
+      <arg name="cursor" type="uint"/>
+    </event>
+
+    <enum name="cursor">
+      <entry name="none" value="0"/>
+
+      <entry name="resize_top" value="1"/>
+      <entry name="resize_bottom" value="2"/>
+
+      <entry name="arrow" value="3"/>
+
+      <entry name="resize_left" value="4"/>
+      <entry name="resize_top_left" value="5"/>
+      <entry name="resize_bottom_left" value="6"/>
+
+      <entry name="move" value="7"/>
+
+      <entry name="resize_right" value="8"/>
+      <entry name="resize_top_right" value="9"/>
+      <entry name="resize_bottom_right" value="10"/>
+
+      <entry name="busy" value="11"/>
+    </enum>
   </interface>
 
   <interface name="screensaver" version="1">
index 2222970..b477bbe 100644 (file)
@@ -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