[PATCH 3/5] tablet-shell: Making the layout draggable and have sliding effect.

tecton69 at gmail.com tecton69 at gmail.com
Tue Jul 17 02:08:15 PDT 2012


From: Ning Tang <tecton69 at gmail.com>

Use frame callback to move layout and thus making layout move
at a speed. Also button and motion function will record the offset.

Signed-off-by: Li Chen	    <cl.zhejiang.china at gmail.com>
Signed-off-by: Yi Yuan	    <harryyuan910702 at gmail.com>
Signed-off-by: Ning Tang    <tecton69 at gmail.com>
---
 clients/tablet-shell.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 165 insertions(+), 2 deletions(-)

diff --git a/clients/tablet-shell.c b/clients/tablet-shell.c
index 54fb5b0..0a9e868 100644
--- a/clients/tablet-shell.c
+++ b/clients/tablet-shell.c
@@ -411,14 +411,39 @@ launcher_redraw_handler(struct widget *widget, void *data)
 }
 
 static void
+layout_frame_callback(void *data, struct wl_callback *callback, uint32_t time)
+{
+	struct layout *layout = data;
+
+	if (abs(layout->offset) < layout->s_speed) {
+		/* stop switching */
+		layout->offset = 0;
+		layout->switching = 0;
+	} else {
+		layout->offset += layout->switching * layout->s_speed;
+	}
+
+	widget_schedule_redraw(layout->widget);
+
+	if (callback)
+		wl_callback_destroy(callback);
+}
+
+static const struct wl_callback_listener layout_listener = {
+	layout_frame_callback
+};
+
+static void
 layout_redraw_handler(struct widget *widget, void *data)
 {
 	struct layout *layout = data;
+	struct layout *current = data;
 	struct launcher *launcher;
 	struct rectangle allocation;
 	const int rows = 3, columns = 4, icon_width = launcher_size,
 	icon_height = launcher_size;
 	int x, y, i, width, height, vpadding, hpadding;
+	struct wl_callback *callback;
 
 	if (layout->showing != 1)
 		return;
@@ -472,7 +497,7 @@ layout_redraw_handler(struct widget *widget, void *data)
 			i++;
 			if (i == columns) {
 				x = allocation.x + layout->offset
-				    + allocation.width + 2 * layout->hmargin;
+				+ allocation.width + 2 * layout->hmargin;
 				y += icon_height + vpadding;
 				i = 0;
 			}
@@ -506,6 +531,140 @@ layout_redraw_handler(struct widget *widget, void *data)
 			}
 		}
 	}
+
+	if (current->switching) {
+		callback = wl_surface_frame(window_get_wl_surface(
+					    current->homescreen->window));
+		wl_callback_add_listener(callback, &layout_listener, current);
+	}
+}
+
+static void
+layout_button_handler(struct widget *widget,
+		      struct input *input, uint32_t time,
+		      uint32_t button,
+		      enum wl_pointer_button_state state, void *data)
+{
+	struct layout *layout;
+	struct layout *prev_layout = NULL, *next_layout = NULL;
+	struct launcher *launcher;
+	int y;
+	int width;
+	int fast_slide = 0;
+	struct rectangle allocation;
+
+	layout = widget_get_user_data(widget);
+
+	if (state == WL_POINTER_BUTTON_STATE_RELEASED) {
+		layout->pressed = 0;
+
+		/* do offset check to determine switch direction */
+		widget_get_allocation(widget, &allocation);
+		width = allocation.width + layout->hmargin * 2;
+
+		if (time - layout->click_time < 700) {
+			fast_slide = 1;
+			/* less than 0.7 second, also slide layout. */
+			if (layout->offset > 0)
+				layout->offset += width / 2;
+			else if (layout->offset < 0)
+				layout->offset -= width / 2;
+		}
+
+		if (layout->link.next != layout->layout_list)
+			next_layout = __wl_container_of(layout->link.next,
+							layout, link);
+		if (layout->link.prev != layout->layout_list)
+			prev_layout = __wl_container_of(layout->link.prev,
+							layout, link);
+
+		if ((layout->offset < -width / 2 && next_layout != NULL) ||
+		    (layout->offset > width / 2 && prev_layout != NULL)) {
+			/* origin hide to show the other */
+			layout->showing = 0;
+			widget_set_allocation(layout->widget, 0, 0, 0, 0);
+			wl_list_for_each(launcher,
+					 &layout->launcher_list, link) {
+				widget_set_allocation(launcher->widget,
+						      0, 0, 0, 0);
+			}
+
+			if (layout->offset < 0) {
+				/* move to next */
+				if (fast_slide)
+					layout->offset += (layout->offset > 0)?
+							  -width / 2:width / 2;
+				next_layout->offset = width + layout->offset;
+				next_layout->showing = 1;
+				/* switch animation */
+				next_layout->switching = -1;
+				widget_set_allocation(next_layout->widget,
+						      layout->hmargin,
+						      layout->vmargin,
+						      allocation.width,
+						      allocation.height);
+			} else {
+				/* move to previous */
+				if (fast_slide)
+					layout->offset += (layout->offset > 0)?
+							  -width / 2:width / 2;
+				prev_layout->offset = layout->offset - width;
+				prev_layout->showing = 1;
+				/* switch animation */
+				prev_layout->switching = 1;
+				widget_set_allocation(prev_layout->widget,
+						      layout->hmargin,
+						      layout->vmargin,
+						      allocation.width,
+						      allocation.height);
+			}
+		} else {
+			/* back to itself */
+			layout->switching = (layout->offset > 0)? -1 : 1;
+			if (fast_slide && layout->offset != 0)
+				layout->offset += (layout->offset > 0)?
+						  -width / 2 : width / 2;
+			if (prev_layout != NULL) {
+				wl_list_for_each(launcher,
+						 &prev_layout->launcher_list,
+						 link) {
+					widget_set_allocation(launcher->widget,
+							      0, 0, 0, 0);
+				}
+			}
+			if (next_layout != NULL) {
+				wl_list_for_each(launcher,
+						 &next_layout->launcher_list,
+						 link) {
+					widget_set_allocation(launcher->widget,
+							      0, 0, 0, 0);
+				}
+			}
+		}
+		/* update scene */
+		widget_schedule_redraw(layout->widget);
+	} else if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
+		layout->pressed = 1;
+		layout->click_time = time;
+		/* record first position */
+		input_get_position(input,&layout->last_x, &y);
+	}
+}
+
+static int
+layout_motion_handler(struct widget *widget, struct input *input,
+		      uint32_t time, float x, float y, void *data)
+{
+	struct layout *layout = data;
+
+	if (layout->pressed)
+	{
+		layout->offset += x - layout->last_x;
+		layout->last_x = x;
+		widget_schedule_redraw(layout->widget);
+	}
+
+	return CURSOR_LEFT_PTR;
 }
 
 static void
@@ -525,7 +684,7 @@ tablet_shell_add_layout(struct tablet *tablet)
 	layout->hmargin = 100;
 	layout->vmargin = 50;
 	layout->switching = 0;
-	layout->s_speed = 20;
+	layout->s_speed = 40;
 	if (wl_list_empty(&homescreen->layout_list))
 		layout->showing = 1;
 	else
@@ -536,6 +695,10 @@ tablet_shell_add_layout(struct tablet *tablet)
 	layout->layout_list = &homescreen->layout_list;
 
 	wl_list_insert(homescreen->layout_list.prev, &layout->link);
+	widget_set_button_handler(layout->widget,
+				  layout_button_handler);
+	widget_set_motion_handler(layout->widget,
+				  layout_motion_handler);
 	widget_set_redraw_handler(layout->widget,
 				  layout_redraw_handler);
 }
-- 
1.7.11.1



More information about the wayland-devel mailing list