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

Reply via email to