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

Tang, Ning ning.tang at intel.com
Tue Aug 21 19:23:47 PDT 2012



> -----Original Message-----
> From: Philipp Brüschweiler [mailto:blei42 at gmail.com]
> Sent: Tuesday, August 21, 2012 9:59 PM
> To: tecton69 at gmail.com
> Cc: wayland-devel at lists.freedesktop.org; juan.j.zhao at linux.intel.com; Tang,
> Ning
> Subject: Re: [PATCH 04/14] tablet-shell: add sliding effect of layout.
> 
> 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.
> 
There was a bug that when I dragged to slide layout, a layout is moved out of screen
and the next layout is shown. But the pointer's focus is still on previous layout, if
click again without moving the mouse will cause bug.
So here I use input_ungrab() to let pointer find correct focus.

Thanks.

> > +               }
> > +       } 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