[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