if the system doesn't have a pointer device common_surface_resize will crash on accessing seat->pointer->button_count. if the system does have a pointer device, but attempts to resize a window using touchscreen - nothing happens. here we implement separate window resizing path for seat->touch as it is done in common_surface_move --- clients/window.c | 5 +- desktop-shell/shell.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++--- shared/cairo-util.h | 2 +- shared/frame.c | 20 ++++--- 4 files changed, 159 insertions(+), 21 deletions(-)
diff --git a/clients/window.c b/clients/window.c index e770a04..185fe23 100644 --- a/clients/window.c +++ b/clients/window.c @@ -2409,9 +2409,10 @@ frame_touch_down_handler(struct widget *widget, struct input *input, float x, float y, void *data) { struct window_frame *frame = data; + enum theme_location location; - frame_touch_down(frame->frame, input, id, x, y); - frame_handle_status(frame, input, time, THEME_LOCATION_CLIENT_AREA); + location = frame_touch_down(frame->frame, input, id, x, y); + frame_handle_status(frame, input, time, location); } static void diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c index bc4a258..23125af 100644 --- a/desktop-shell/shell.c +++ b/desktop-shell/shell.c @@ -1581,6 +1581,14 @@ struct weston_resize_grab { int32_t width, height; }; +struct weston_touch_resize_grab { + struct shell_touch_grab base; + int active; + uint32_t edges; + int32_t width, height; + wl_fixed_t dx, dy; +}; + static void resize_grab_motion(struct weston_pointer_grab *grab, uint32_t time, wl_fixed_t x, wl_fixed_t y) @@ -1668,6 +1676,84 @@ static const struct weston_pointer_grab_interface resize_grab_interface = { resize_grab_cancel, }; +static void +touch_resize_grab_down(struct weston_touch_grab *grab, uint32_t time, + int touch_id, wl_fixed_t sx, wl_fixed_t sy) +{ +} + +static void +touch_resize_grab_up(struct weston_touch_grab *grab, uint32_t time, int touch_id) +{ + struct weston_touch_resize_grab *resize = + (struct weston_touch_resize_grab *) container_of( + grab, struct shell_touch_grab, grab); + + if (touch_id == 0) + resize->active = 0; + + if (grab->touch->num_tp == 0) { + shell_touch_grab_end(&resize->base); + free(resize); + } +} + +static void +touch_resize_grab_motion(struct weston_touch_grab *grab, uint32_t time, + int touch_id, wl_fixed_t sx, wl_fixed_t sy) +{ + struct weston_touch_resize_grab *resize = (struct weston_touch_resize_grab *) grab; + struct weston_touch *touch = grab->touch; + struct shell_surface *shsurf = resize->base.shsurf; + int32_t width, height; + wl_fixed_t from_x, from_y; + wl_fixed_t to_x, to_y; + + if (!shsurf || !resize->active) + return; + + weston_view_from_global_fixed(shsurf->view, + resize->dx, resize->dy, + &from_x, &from_y); + weston_view_from_global_fixed(shsurf->view, + touch->grab_x, touch->grab_y, &to_x, &to_y); + + width = resize->width; + if (resize->edges & WL_SHELL_SURFACE_RESIZE_LEFT) { + width += wl_fixed_to_int(from_x - to_x); + } else if (resize->edges & WL_SHELL_SURFACE_RESIZE_RIGHT) { + width += wl_fixed_to_int(to_x - from_x); + } + + height = resize->height; + if (resize->edges & WL_SHELL_SURFACE_RESIZE_TOP) { + height += wl_fixed_to_int(from_y - to_y); + } else if (resize->edges & WL_SHELL_SURFACE_RESIZE_BOTTOM) { + height += wl_fixed_to_int(to_y - from_y); + } + + shsurf->client->send_configure(shsurf->surface, + resize->edges, width, height); +} + +static void +touch_resize_grab_cancel(struct weston_touch_grab *grab) +{ + struct weston_touch_resize_grab *resize = + (struct weston_touch_resize_grab *) container_of( + grab, struct shell_touch_grab, grab); + + shell_touch_grab_end(&resize->base); + free(resize); +} + +static const struct weston_touch_grab_interface touch_resize_grab_interface = { + touch_resize_grab_down, + touch_resize_grab_up, + touch_resize_grab_motion, + touch_resize_grab_cancel, +}; + /* * Returns the bounding box of a surface and all its sub-surfaces, * in the surface coordinates system. */ @@ -1731,6 +1817,37 @@ surface_resize(struct shell_surface *shsurf, return 0; } +static int +surface_touch_resize(struct shell_surface *shsurf, + struct weston_seat *seat, uint32_t edges) +{ + struct weston_touch_resize_grab *resize; + + if (shsurf->state.fullscreen || shsurf->state.maximized) + return 0; + + if (edges == 0 || edges > 15 || + (edges & 3) == 3 || (edges & 12) == 12) + return 0; + + resize = malloc(sizeof *resize); + if (!resize) + return -1; + + resize->active = 1; + resize->edges = edges; + surface_subsurfaces_boundingbox(shsurf->surface, NULL, NULL, + &resize->width, &resize->height); + resize->dx = seat->touch->grab_x; + resize->dy = seat->touch->grab_y; + + shsurf->resize_edges = edges; + shell_touch_grab_start(&resize->base, &touch_resize_grab_interface, shsurf, + seat->touch); + + return 0; +} + static void common_surface_resize(struct wl_resource *resource, struct wl_resource *seat_resource, uint32_t serial, @@ -1743,17 +1860,35 @@ common_surface_resize(struct wl_resource *resource, if (shsurf->state.fullscreen) return; - if (seat->pointer->button_count == 0 || - seat->pointer->grab_serial != serial || - seat->pointer->focus == NULL) - return; + if (seat->pointer) { + if (seat->pointer->button_count == 0 || + seat->pointer->grab_serial != serial || + seat->pointer->focus == NULL) + goto out; + + surface = weston_surface_get_main_surface(seat->pointer->focus->surface); + if (surface != shsurf->surface) + goto out; + + if (surface_resize(shsurf, seat, edges) < 0) + wl_resource_post_no_memory(resource); - surface = weston_surface_get_main_surface(seat->pointer->focus->surface); - if (surface != shsurf->surface) return; + } + +out: + if (seat->touch) { + if (seat->touch->grab_serial != serial || + seat->touch->focus == NULL) + return; - if (surface_resize(shsurf, seat, edges) < 0) - wl_resource_post_no_memory(resource); + surface = weston_surface_get_main_surface(seat->touch->focus->surface); + if (surface != shsurf->surface) + return; + + if (surface_touch_resize(shsurf, seat, edges) < 0) + wl_resource_post_no_memory(resource); + } } static void @@ -1877,7 +2012,7 @@ xdg_ping_timeout_handler(void *data) continue; if (seat->pointer->focus->surface->resource == NULL) continue; - + shsurf = get_shell_surface(seat->pointer->focus->surface); if (shsurf && wl_resource_get_client(shsurf->resource) == sc->client) diff --git a/shared/cairo-util.h b/shared/cairo-util.h index 4493b0d..9643023 100644 --- a/shared/cairo-util.h +++ b/shared/cairo-util.h @@ -204,7 +204,7 @@ enum theme_location frame_pointer_button(struct frame *frame, void *pointer, uint32_t button, enum frame_button_state state); -void +enum theme_location frame_touch_down(struct frame *frame, void *data, int32_t id, int x, int y); void diff --git a/shared/frame.c b/shared/frame.c index 35e6b65..833117c 100644 --- a/shared/frame.c +++ b/shared/frame.c @@ -782,27 +782,27 @@ frame_pointer_button(struct frame *frame, void *data, return location; } -void +enum theme_location frame_touch_down(struct frame *frame, void *data, int32_t id, int x, int y) { struct frame_touch *touch = frame_touch_get(frame, data); struct frame_button *button = frame_find_button(frame, x, y); - enum theme_location location; + enum theme_location location = THEME_LOCATION_EXTERIOR; if (id > 0) - return; - - if (touch && button) { - touch->button = button; - frame_button_press(touch->button); - return; - } + return location; location = theme_get_location(frame->theme, x, y, frame->width, frame->height, frame->flags & FRAME_FLAG_MAXIMIZED ? THEME_FRAME_MAXIMIZED : 0); + if (touch && button) { + touch->button = button; + frame_button_press(touch->button); + return location; + } + switch (location) { case THEME_LOCATION_TITLEBAR: frame->status |= FRAME_STATUS_MOVE; @@ -820,6 +820,8 @@ frame_touch_down(struct frame *frame, void *data, int32_t id, int x, int y) default: break; } + + return location; } void -- 1.7.9.5 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel