[PATCH v4] shell: support window resizing using touchscreen

Stanislav Vorobiov s.vorobiov at samsung.com
Mon May 5 05:56:20 PDT 2014


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 f12ce39..be2c0e0 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 a631c62..2aab283 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -395,6 +395,7 @@ shell_touch_grab_end(struct shell_touch_grab *grab)
 	if (grab->shsurf) {
 		wl_list_remove(&grab->shsurf_destroy_listener.link);
 		grab->shsurf->grabbed = 0;
+		grab->shsurf->resize_edges = 0;
 	}
 
 	weston_touch_end_grab(grab->touch);
@@ -1615,6 +1616,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)
@@ -1702,6 +1711,83 @@ 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, 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. */
@@ -1766,6 +1852,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,
@@ -1775,17 +1892,35 @@ common_surface_resize(struct wl_resource *resource,
 	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
 	struct weston_surface *surface;
 
-	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
@@ -1909,7 +2044,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



More information about the wayland-devel mailing list