From: Ning Tang <[email protected]> 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 <[email protected]> Signed-off-by: Yi Yuan <[email protected]> Signed-off-by: Ning Tang <[email protected]> --- 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 _______________________________________________ wayland-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/wayland-devel
