[PATCH 16/19] tablet-shell: Improve the sliding effect.

ning.tang at intel.com ning.tang at intel.com
Mon Sep 24 19:40:01 PDT 2012


From: Ning Tang <ning.tang at intel.com>

 Use spring effect so that layout smoothly slides now.
 When layout motion or sliding automatically, it will use a spring
 effect to follow cursor. Set the new to_offset when mouse drags or
 layout need to sliding switch. So when frame callback it will change
 allocation. It is aimed to reduce the trailing.
 
 Signed-off-by: Ning Tang <ning.tang at intel.com>
---
 clients/tablet-shell.c | 169 ++++++++++++++++++++++++++++++++-----------------
 1 file changed, 111 insertions(+), 58 deletions(-)

diff --git a/clients/tablet-shell.c b/clients/tablet-shell.c
index 477b1df..f5dec79 100644
--- a/clients/tablet-shell.c
+++ b/clients/tablet-shell.c
@@ -228,6 +228,7 @@ homescreen_draw(struct widget *widget, void *data)
 	struct homescreen *homescreen = data;
 	cairo_surface_t *surface;
 	struct rectangle allocation;
+	struct rectangle layout_rect;
 	cairo_t *cr;
 	struct layout *layout;
 
@@ -244,13 +245,15 @@ homescreen_draw(struct widget *widget, void *data)
 	/* draw current layout */
 	wl_list_for_each(layout, &homescreen->layout_list, link) {
 		if (layout->showing) {
-			widget_set_allocation(layout->widget,
-					      layout->hmargin,
-					      layout->vmargin,
-					      allocation.width
-					      - 2 * layout->hmargin,
-					      allocation.height
-					      - 2 * layout->vmargin);
+			widget_get_allocation(layout->widget, &layout_rect);
+			if (layout_rect.width == 0)
+				widget_set_allocation(layout->widget,
+						      layout->hmargin,
+						      layout->vmargin,
+						      allocation.width
+						      - 2 * layout->hmargin,
+						      allocation.height
+						      - 2 * layout->vmargin);
 		}
 		layout_draw_indicator(layout,
 				      allocation.height - layout->vmargin,
@@ -355,13 +358,10 @@ launcher_motion_handler(struct widget *widget, struct input *input,
 	uint32_t serial;
 
 	widget_get_allocation(widget, &allocation);
-	widget_set_tooltip(widget, basename(launcher->path),
-			   x, allocation.y + allocation.height);
 
 	if (!launcher->dragging && launcher->pressed == 1 &&
 	    time - launcher->click_time > 600)
 	{
-		widget_destroy_tooltip(widget);
 		// draging mode
 		launcher->focused = 0;
 		if (gl_launcher_drag)
@@ -725,7 +725,7 @@ launcher_redraw_handler(struct widget *widget, void *data)
 		if (launcher->focused) {
 			cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.4);
 			cairo_mask_surface(cr, launcher->icon,
-					allocation.x, allocation.y);
+					   allocation.x, allocation.y);
 		}
 	}
 	cairo_destroy(cr);
@@ -735,18 +735,24 @@ launcher_redraw_handler(struct widget *widget, void *data)
 static void
 layout_frame_callback(void *data, struct wl_callback *callback, uint32_t time)
 {
+	int end = 0;
+	int increament = 0;
 	struct layout *layout = data;
 	struct rectangle allocation;
 
-	if (abs(layout->offset - layout->to_offset) < layout->s_speed) {
-		/* stop switching */
-		layout->offset = 0;
-		layout->switching = 0;
+	if (callback)
+		wl_callback_destroy(callback);
+	if (layout_moving == 2 &&
+	    abs(layout->to_offset - layout->offset) <= 1) {
+		end = 1;
+	} else if ((layout_moving == 1 || layout_moving == -1) &&
+		   abs(layout->offset - layout->to_offset) <= 5) {
+		end = 1;
 		widget_get_allocation(layout->homescreen->widget, &allocation);
 		if (layout->to_offset) {
 			layout->showing = 0;
 			widget_set_allocation(layout->widget,
-					      0, 0, 0, 0);
+					      0, layout->vmargin, 1, 1);
 			layout->active = 0;
 		} else {
 			layout->active = 1;
@@ -759,14 +765,25 @@ layout_frame_callback(void *data, struct wl_callback *callback, uint32_t time)
 					      layout->vmargin);
 			input_ungrab(layout->homescreen->input);
 		}
-	} else if (layout_moving) {
-		layout->offset += layout->switching * layout->s_speed;
+	}
+	if (end) {
+		/* stop switching */
+		layout->offset = layout->to_offset;
+		layout->switching = 0;
+	} else if (layout_moving == 1 || layout_moving == -1) {
+		layout->offset += (layout->to_offset - layout->offset)
+				  / layout->s_speed;
+		layout->offset += layout->switching * 4;
+	} else if (layout_moving == 2) {
+		increament = layout->to_offset - layout->offset;
+		if (abs(increament) < 10)
+			layout->offset += increament;
+		else
+			layout->offset += (increament > 0? 8: -8)
+					  + increament / 4;
 	}
 
 	widget_schedule_redraw(layout->widget);
-
-	if (callback)
-		wl_callback_destroy(callback);
 }
 
 static const struct wl_callback_listener layout_listener = {
@@ -780,6 +797,7 @@ layout_redraw_handler(struct widget *widget, void *data)
 	struct layout *current = data;
 	struct launcher *launcher;
 	struct rectangle allocation;
+	struct rectangle screen_allocation;
 	const int icon_width = launcher_size, icon_height = launcher_size;
 	int x, y, i, width, height, vpadding, hpadding;
 	struct wl_callback *callback;
@@ -788,13 +806,16 @@ layout_redraw_handler(struct widget *widget, void *data)
 		return;
 
 	widget_get_allocation(widget, &allocation);
-	width = allocation.width - key_layout_columns * icon_width;
+	widget_get_allocation(layout->homescreen->widget, &screen_allocation);
+	width = screen_allocation.width - 2 * layout->hmargin
+		- key_layout_columns * icon_width;
 	/* width between icons */
 	if (key_layout_columns > 1)
 		hpadding = width / (key_layout_columns - 1);
 	else
 		hpadding = 0;
-	height = allocation.height - key_layout_rows * icon_height;
+	height = screen_allocation.height - 2 * layout->vmargin
+		 - key_layout_rows * icon_height;
 	if (key_layout_rows > 1)
 		vpadding = height / (key_layout_rows - 1);
 	else
@@ -805,7 +826,7 @@ layout_redraw_handler(struct widget *widget, void *data)
 	i = 0;
 
 	wl_list_for_each(launcher, &layout->launcher_list, link) {
-		if (x < allocation.width + 2 * layout->hmargin) {
+		if (x < screen_allocation.width) {
 			widget_set_allocation(launcher->widget, x, y,
 					      icon_width, icon_height);
 		} else {
@@ -830,21 +851,25 @@ layout_redraw_handler(struct widget *widget, void *data)
 
 static void
 layout_sliding(struct layout *layout, int offset,
-	       int to_offset, int switching)
+	       int to_offset, int switching, int hide)
 {
 	struct rectangle allocation;
-	widget_get_allocation(layout->widget, &allocation);
+	widget_get_allocation(layout->homescreen->widget, &allocation);
 	layout->showing = 1;
-	layout->offset = offset;
+	if (offset != -1)
+		layout->offset = offset;
 	if (switching) {
-		layout->switching = switching;
 		layout->to_offset = to_offset;
+		layout->switching = layout->to_offset - layout->offset > 0?
+				    1: -1;
 	}
 	widget_set_allocation(layout->widget,
 			      layout->hmargin,
 			      layout->vmargin,
-			      allocation.width,
-			      allocation.height);
+			      hide? 1: allocation.width
+			      - 2 * layout->hmargin,
+			      hide? 1: allocation.height
+			      - 2 * layout->vmargin);
 	widget_schedule_redraw(layout->widget);
 }
 
@@ -856,7 +881,7 @@ layout_button_handler(struct widget *widget,
 {
 	struct layout *layout;
 	struct layout *prev_layout = NULL, *next_layout = NULL;
-	struct layout *show_layout = NULL;
+	struct layout *show_layout = NULL, *backup_layout = NULL;
 	int y;
 	int width;
 	int fast_slide = 0;
@@ -896,24 +921,32 @@ layout_button_handler(struct widget *widget,
 			/* origin hide to show the other */
 			if (fast_slide)
 				layout->offset += (layout->offset > 0) ?
-						  -width / 2:width / 2;
+						  -width / 2: width / 2;
 			layout_sliding(layout,
-				       layout->offset,
+				       -1,
 				       layout->offset > 0 ?
 				       width: -width,
 				       layout->offset > 0 ?
-				       1: -1);
+				       1: -1, 0);
 
 			if (layout->offset < 0) {
 				/* move to next */
 				layout_sliding(next_layout,
 					       width + layout->offset,
-					       0, -1);
+					       0, -1, 1);
+				if (prev_layout && prev_layout->switching)
+					layout_sliding(prev_layout,
+						       -1,
+						       -width, -1, 1);
 			} else {
 				/* move to previous */
 				layout_sliding(prev_layout,
 					       -width + layout->offset,
-					       0, 1);
+					       0, 1, 1);
+				if (next_layout && next_layout->switching)
+					layout_sliding(next_layout,
+						       -1,
+						       width, 1, 1);
 			}
 		} else {
 			/* back to itself */
@@ -922,21 +955,28 @@ layout_button_handler(struct widget *widget,
 			layout->to_offset = 0;
 			if (fast_slide && layout->offset != 0)
 				layout->offset += (layout->offset > 0)?
-						  -width / 2 : width / 2;
+						  -width / 2: width / 2;
 			show_layout = (layout->offset < 0)? next_layout :
 							    prev_layout;
 			if (!show_layout) {
+				backup_layout = (layout->offset < 0)?
+						prev_layout : next_layout;
+				if (backup_layout && backup_layout->switching)
+					layout_sliding(backup_layout,
+						       -1,
+						       layout->offset > 0 ?
+						       width : -width,
+						       layout->offset > 0 ?
+						       -1: 1, 1);
 				widget_schedule_redraw(layout->widget);
 				return;
 			}
 			layout_sliding(show_layout,
 				       layout->offset > 0 ?
-				       layout->offset - screen_allocation.width:
-				       layout->offset + screen_allocation.width,
-				       layout->offset > 0 ?
-				       -screen_allocation.width :
-				       screen_allocation.width,
-				       layout->offset > 0 ? -1: 1);
+				       layout->offset - width:
+				       layout->offset + width,
+				       layout->offset > 0 ? -width : width,
+				       layout->offset > 0 ? -1: 1, 1);
 		}
 		/* update scene */
 		widget_schedule_redraw(layout->widget);
@@ -964,26 +1004,40 @@ layout_motion_handler(struct widget *widget, struct input *input,
 
 	if (layout->pressed)
 	{
-		layout->offset += x - layout->last_x;
+		layout_moving = 2;
+		if (layout->switching) {
+			layout->to_offset += (int)x - layout->last_x;
+			layout->switching = layout->to_offset - layout->offset >
+					    0? 1: -1;
+		} else
+			layout_sliding(layout, -1,
+				       layout->to_offset + (int)x -
+				       layout->last_x,
+				       layout->to_offset - layout->offset > 0?
+				       1: -1, 0);
 		layout->last_x = x;
-		widget_schedule_redraw(layout->widget);
 		if (layout->offset < 0 &&
 		    layout->link.next != layout->layout_list) {
 			show_layout = __wl_container_of(layout->link.next,
 							layout, link);
-			show_layout->offset = layout->offset +
-					      screen_allocation.width;
+			show_layout->to_offset = layout->to_offset +
+						 screen_allocation.width;
 		} else if (layout->offset > 0 &&
 			   layout->link.prev != layout->layout_list) {
 			show_layout = __wl_container_of(layout->link.prev,
 							layout, link);
-			show_layout->offset = layout->offset -
-					      screen_allocation.width;
+			show_layout->to_offset = layout->to_offset -
+						 screen_allocation.width;
 		}
 		if (show_layout) {
-			layout_sliding(show_layout,
-				       show_layout->offset,
-				       0, 0);
+			if (show_layout->switching)
+				show_layout->switching = layout->switching;
+			else
+				layout_sliding(show_layout,
+					       -1,
+					       show_layout->to_offset,
+					       layout->to_offset -
+					       layout->offset > 0? 1: -1, 1);
 		}
 	}
 
@@ -997,8 +1051,9 @@ tablet_shell_add_layout(struct tablet *tablet)
 	struct homescreen *homescreen = tablet->homescreen;
 	struct rectangle allocation;
 	char *index_image;
-	widget_get_allocation(homescreen->widget, &allocation);
 
+	output_get_allocation(display_get_output(tablet->display),
+			      &allocation);
 	layout = malloc(sizeof *layout);
 	memset(layout, 0, sizeof *layout);
 	wl_list_init(&layout->launcher_list);
@@ -1006,14 +1061,12 @@ tablet_shell_add_layout(struct tablet *tablet)
 	layout->homescreen = homescreen;
 	layout->hmargin = 100;
 	layout->vmargin = 50;
-	layout->switching = 0;
-	layout->s_speed = 30;
+	layout->s_speed = 13;
 	if (wl_list_empty(&homescreen->layout_list)) {
 		layout->active = 1;
 		layout->showing = 1;
-	}
-	layout->offset = 0;
-
+	} else
+		layout->offset = allocation.width;
 	/* let layout know number of layouts */
 	layout->layout_list = &homescreen->layout_list;
 	layout->index = wl_list_length(layout->layout_list);
-- 
1.7.12.1



More information about the wayland-devel mailing list