[PATCH 04/14] tablet-shell: add sliding effect of layout.

Philipp Brüschweiler blei42 at gmail.com
Tue Aug 21 06:58:58 PDT 2012


On Tue, Aug 21, 2012 at 1:49 PM,  <tecton69 at gmail.com> wrote:
> From: Ning Tang <ning.tang at intel.com>
>
> Use frame callback to enable layout moving, so dragging layout
> will cause layout's offset changes.
> And redraw function will allocate corresponding positions to launchers.
> The allocation of layout won't change until sliding ends.
>
>  Signed-off-by: Ning Tang <tecton69 at gmail.com>
>
> ---
>  clients/tablet-shell.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 224 insertions(+), 1 deletion(-)
>
> diff --git a/clients/tablet-shell.c b/clients/tablet-shell.c
> index 3a0f04c..515d198 100644
> --- a/clients/tablet-shell.c
> +++ b/clients/tablet-shell.c
> @@ -47,6 +47,7 @@ struct homescreen {
>         struct window *window;
>         struct widget *widget;
>         struct wl_list layout_list;
> +       struct input *input;
>  };
>
>  struct lockscreen {
> @@ -60,12 +61,17 @@ struct layout {
>         struct homescreen *homescreen;
>         struct wl_list launcher_list;
>         struct wl_list link;
> +       int index;
>         int pressed;
>         int showing;
>         int offset;
> +       int to_offset;
> +       int last_x;
>         int hmargin;
>         int vmargin;
> -
> +       uint32_t click_time;            /* ms */
> +       int switching;                  /* 0-no 1-right -1-left*/
> +       int s_speed;                    /* switching speed */
>         struct wl_list *layout_list;    /* we need know the number of list */
>  };
>
> @@ -88,6 +94,7 @@ static void layout_section_done(void *data);
>  static int launcher_size;
>  static int key_layout_rows;
>  static int key_layout_columns;
> +static int layout_moving;
>
>  static const struct config_key shell_config_keys[] = {
>         { "lockscreen-icon", CONFIG_KEY_STRING, &key_lockscreen_icon },
> @@ -251,6 +258,7 @@ homescreen_create(struct tablet *tablet)
>         widget_set_redraw_handler(homescreen->widget, homescreen_draw);
>
>         wl_list_init(&homescreen->layout_list);
> +       layout_moving = 1;
>         return homescreen;
>  }
>
> @@ -408,13 +416,54 @@ 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;
> +       struct rectangle allocation;
> +
> +       if (abs(layout->offset - layout->to_offset) < layout->s_speed) {
> +               /* stop switching */
> +               layout->offset = 0;
> +               layout->switching = 0;
> +               widget_get_allocation(layout->homescreen->widget, &allocation);
> +               if (layout->to_offset) {
> +                       layout->showing = 0;
> +                       widget_set_allocation(layout->widget,
> +                                             0, 0, 0, 0);
> +               } else {
> +                       widget_set_allocation(layout->widget,
> +                                             layout->hmargin,
> +                                             layout->vmargin,
> +                                             allocation.width - 2 *
> +                                             layout->hmargin,
> +                                             allocation.height - 2 *
> +                                             layout->vmargin);
> +                       input_ungrab(layout->homescreen->input);

Why is this input_ungrab() necessary here? You don't seem to grab the
input yourself anywhere.

> +               }
> +       } else if (layout_moving) {
> +               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 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;
> @@ -447,6 +496,174 @@ layout_redraw_handler(struct widget *widget, void *data)
>                         i = 0;
>                 }
>         }
> +
> +       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_sliding(struct layout *layout, int offset,
> +              int to_offset, int switching)
> +{
> +       struct rectangle allocation;
> +       widget_get_allocation(layout->widget, &allocation);
> +       layout->showing = 1;
> +       layout->offset = offset;
> +       if (switching) {
> +               layout->switching = switching;
> +               layout->to_offset = to_offset;
> +       }
> +       widget_set_allocation(layout->widget,
> +                             layout->hmargin,
> +                             layout->vmargin,
> +                             allocation.width,
> +                             allocation.height);
> +       widget_schedule_redraw(layout->widget);
> +}
> +
> +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 layout *show_layout = NULL;
> +       int y;
> +       int width;
> +       int fast_slide = 0;
> +       struct rectangle layout_allocation;
> +       struct rectangle screen_allocation;
> +
> +       layout = widget_get_user_data(widget);
> +       layout->homescreen->input = input;
> +       if (state == WL_POINTER_BUTTON_STATE_RELEASED) {
> +               layout_moving = 1;
> +               layout->pressed = 0;
> +
> +               /* do offset check to determine switch direction */
> +               widget_get_allocation(widget, &layout_allocation);
> +               widget_get_allocation(layout->homescreen->widget,
> +                                     &screen_allocation);
> +               width = screen_allocation.width;
> +
> +               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 */
> +                       if (fast_slide)
> +                               layout->offset += (layout->offset > 0) ?
> +                                                 -width / 2:width / 2;
> +                       layout_sliding(layout,
> +                                      layout->offset,
> +                                      layout->offset > 0 ?
> +                                      width: -width,
> +                                      layout->offset > 0 ?
> +                                      1: -1);
> +
> +                       if (layout->offset < 0) {
> +                               /* move to next */
> +                               layout_sliding(next_layout,
> +                                              width + layout->offset,
> +                                              0, -1);
> +                       } else {
> +                               /* move to previous */
> +                               layout_sliding(prev_layout,
> +                                              -width + layout->offset,
> +                                              0, 1);
> +                       }
> +               } else {
> +                       /* back to itself */
> +                       layout->switching = (layout->offset > 0)? -1 : 1;
> +                       layout->showing = 1;
> +                       layout->to_offset = 0;
> +                       if (fast_slide && layout->offset != 0)
> +                               layout->offset += (layout->offset > 0)?
> +                                                 -width / 2 : width / 2;
> +                       show_layout = (layout->offset < 0)? next_layout :
> +                                                           prev_layout;
> +                       if (!show_layout) {
> +                               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);
> +               }
> +               /* update scene */
> +               widget_schedule_redraw(layout->widget);
> +       } else if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
> +               layout_moving = 0;
> +               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;
> +       struct layout *show_layout = NULL;
> +       struct rectangle layout_allocation, screen_allocation;
> +
> +       widget_get_allocation(layout->widget,
> +                             &layout_allocation);
> +       widget_get_allocation(layout->homescreen->widget,
> +                             &screen_allocation);
> +
> +       if (layout->pressed)
> +       {
> +               layout->offset += x - layout->last_x;
> +               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;
> +               } 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;
> +               }
> +               if (show_layout) {
> +                       layout_sliding(show_layout,
> +                                      show_layout->offset,
> +                                      0, 0);
> +               }
> +       }
> +
> +       return CURSOR_LEFT_PTR;
>  }
>
>  static void
> @@ -464,6 +681,8 @@ tablet_shell_add_layout(struct tablet *tablet)
>         layout->homescreen = homescreen;
>         layout->hmargin = 100;
>         layout->vmargin = 50;
> +       layout->switching = 0;
> +       layout->s_speed = 30;
>         if (wl_list_empty(&homescreen->layout_list)) {
>                 layout->showing = 1;
>         }
> @@ -473,6 +692,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.5
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list