[PATCH 03/14] tablet-shell: break the connection between launcher and homescreen.

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


-----Original Message-----
From: Philipp Brüschweiler [mailto:blei42 at gmail.com] 
Sent: Tuesday, August 21, 2012 9:34 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 03/14] tablet-shell: break the connection between launcher and homescreen.

On Tue, Aug 21, 2012 at 1:49 PM,  <tecton69 at gmail.com> wrote:
> From: Ning Tang <ning.tang at intel.com>
>
> Launcher is totally depend on layout and add layout redraw function to 
> manage drawing launchers.
>
>  Signed-off-by: Ning Tang <tecton69 at gmail.com>
>
> ---
>  clients/tablet-shell.c | 133 +++++++++++++++++++++++++++++++++----------------
>  weston-tablet.ini      |   3 ++
>  2 files changed, 94 insertions(+), 42 deletions(-)
>
> diff --git a/clients/tablet-shell.c b/clients/tablet-shell.c index 
> c4ec5e7..3a0f04c 100644
> --- a/clients/tablet-shell.c
> +++ b/clients/tablet-shell.c
> @@ -46,7 +46,6 @@ struct tablet {
>  struct homescreen {
>         struct window *window;
>         struct widget *widget;
> -       struct wl_list launcher_list;
>         struct wl_list layout_list;
>  };
>
> @@ -63,6 +62,7 @@ struct layout {
>         struct wl_list link;
>         int pressed;
>         int showing;
> +       int offset;
>         int hmargin;
>         int vmargin;
>
> @@ -71,7 +71,6 @@ struct layout {
>
>  struct launcher {
>         struct widget *widget;
> -       struct homescreen *homescreen;
>         struct layout *layout;
>         cairo_surface_t *icon;
>         int focused, pressed;
> @@ -86,11 +85,17 @@ static char *key_launcher_icon;  static char 
> *key_launcher_path;  static void launcher_section_done(void *data);  
> static void layout_section_done(void *data);
> +static int launcher_size;
> +static int key_layout_rows;
> +static int key_layout_columns;
>
>  static const struct config_key shell_config_keys[] = {
>         { "lockscreen-icon", CONFIG_KEY_STRING, &key_lockscreen_icon },
>         { "lockscreen", CONFIG_KEY_STRING, &key_lockscreen_background },
>         { "homescreen", CONFIG_KEY_STRING, &key_homescreen_background 
> },
> +       { "layout-rows", CONFIG_KEY_UNSIGNED_INTEGER, &key_layout_rows },
> +       { "layout-columns", CONFIG_KEY_UNSIGNED_INTEGER, &key_layout_columns },
> +       { "icon-size", CONFIG_KEY_UNSIGNED_INTEGER, &launcher_size },
>  };
>
>  static const struct config_key launcher_config_keys[] = { @@ -156,9 
> +161,7 @@ homescreen_draw(struct widget *widget, void *data)
>         cairo_surface_t *surface;
>         struct rectangle allocation;
>         cairo_t *cr;
> -       struct launcher *launcher;
> -       const int rows = 4, columns = 5, icon_width = 128, icon_height = 128;
> -       int x, y, i, width, height, vmargin, hmargin, vpadding, hpadding;
> +       struct layout *layout;
>
>         surface = window_get_surface(homescreen->window);
>         cr = cairo_create(surface);
> @@ -166,29 +169,16 @@ homescreen_draw(struct widget *widget, void *data)
>         widget_get_allocation(widget, &allocation);
>         paint_background(cr, key_homescreen_background, &allocation);
>
> -       cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
> -
> -       width = allocation.width - columns * icon_width;
> -       hpadding = width / (columns + 1);
> -       hmargin = (width - hpadding * (columns - 1)) / 2;
> -
> -       height = allocation.height - rows * icon_height;
> -       vpadding = height / (rows + 1);
> -       vmargin = (height - vpadding * (rows - 1)) / 2;
> -
> -       x = hmargin;
> -       y = vmargin;
> -       i = 0;
> -
> -       wl_list_for_each(launcher, &homescreen->launcher_list, link) {
> -               widget_set_allocation(launcher->widget,
> -                                     x, y, icon_width, icon_height);
> -               x += icon_width + hpadding;
> -               i++;
> -               if (i == columns) {
> -                       x = hmargin;
> -                       y += icon_height + vpadding;
> -                       i = 0;
> +       /* draw current layout */
> +       wl_list_for_each(layout, &homescreen->layout_list, link) {
> +               if (layout->showing) {
> +                       widget_set_allocation(layout->widget,
> +                                             layout->hmargin,
> +                                             layout->vmargin,
> +                                             allocation.width
> +                                             - 2 * layout->hmargin,
> +                                             allocation.height
> +                                             - 2 * layout->vmargin);
>                 }
>         }
>
> @@ -375,7 +365,7 @@ launcher_button_handler(struct widget *widget,
>         if (state == WL_POINTER_BUTTON_STATE_RELEASED) {
>                 launcher_activate(launcher);
>                 launcher->pressed = 0;
> -       } else if (state == WL_POINTER_BUTTON_STATE_PRESSED)
> +       } else if (state == WL_POINTER_BUTTON_STATE_PRESSED)
>                 launcher->pressed = 1;  }
>
> @@ -385,12 +375,20 @@ launcher_redraw_handler(struct widget *widget, void *data)
>         struct launcher *launcher = data;
>         cairo_surface_t *surface;
>         struct rectangle allocation;
> +       struct rectangle layout_allocation;
>         cairo_t *cr;
>
> -       surface = window_get_surface(launcher->homescreen->window);
> -       cr = cairo_create(surface);
> -
>         widget_get_allocation(widget, &allocation);
> +       widget_get_allocation(launcher->layout->homescreen->widget,
> +                             &layout_allocation);
> +
> +       /* avoid drawing out of bounding. */
> +       if (allocation.x <= (0 - allocation.width) ||
> +           allocation.x > layout_allocation.width)
> +               return;
> +
> +       surface = window_get_surface(launcher->layout->homescreen->window);
> +       cr = cairo_create(surface);
>         if (launcher->pressed) {
>                 allocation.x++;
>                 allocation.y++;
> @@ -410,12 +408,53 @@ launcher_redraw_handler(struct widget *widget, 
> void *data)  }
>
>  static void
> +layout_redraw_handler(struct widget *widget, void *data) {
> +       struct layout *layout = 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;
> +
> +       if (layout->showing != 1)
> +               return;
> +
> +       widget_get_allocation(widget, &allocation);
> +       width = allocation.width - key_layout_columns * icon_width;
> +       /* width between icons */
> +       hpadding = width / (key_layout_columns - 1);
> +
> +       height = allocation.height - key_layout_rows * icon_height;
> +       vpadding = height / (key_layout_rows - 1);

It's unlikely, but when rows or columns is set to 1, this results in a division by 0.

Oh, sorry I didn't notice that, I will fix it. Thanks :)

> +
> +       x = allocation.x + layout->offset;
> +       y = allocation.y;
> +       i = 0;
> +
> +       wl_list_for_each(launcher, &layout->launcher_list, link) {
> +               if (x < allocation.width + 2 * layout->hmargin) {
> +                       widget_set_allocation(launcher->widget, x, y,
> +                                             icon_width, icon_height);
> +               } else {
> +                       widget_set_allocation(launcher->widget,
> +                                             0, 0, 0, 0);
> +               }
> +               x += icon_width + hpadding;
> +               i++;
> +               if (i == key_layout_columns) {
> +                       x = allocation.x + layout->offset;
> +                       y += icon_height + vpadding;
> +                       i = 0;
> +               }
> +       }
> +}
> +
> +static void
>  tablet_shell_add_layout(struct tablet *tablet)  {
>         struct layout *layout;
>         struct homescreen *homescreen = tablet->homescreen;
>         struct rectangle allocation;
> -       char *index_image;
>         widget_get_allocation(homescreen->widget, &allocation);
>
>         layout = malloc(sizeof *layout); @@ -428,22 +467,31 @@ 
> tablet_shell_add_layout(struct tablet *tablet)
>         if (wl_list_empty(&homescreen->layout_list)) {
>                 layout->showing = 1;
>         }
> +       layout->offset = 0;
>
>         /* let layout know number of layouts */
>         layout->layout_list = &homescreen->layout_list;
>
>         wl_list_insert(homescreen->layout_list.prev, &layout->link);
> +       widget_set_redraw_handler(layout->widget,
> +                                 layout_redraw_handler);
>  }
>
>  static void
> -tablet_shell_add_launcher(struct tablet *tablet,
> -                         const char *icon, const char *path)
> +layout_add_launcher(struct tablet *tablet,
> +                   const char *icon, const char *path)
>  {
>         struct launcher *launcher;
> +       struct layout *layout = NULL;
>         struct homescreen *homescreen = tablet->homescreen;
>
> +       wl_list_for_each(layout, &homescreen->layout_list, link) {
> +       }
> +       /* find the last layout */
> +       layout = __wl_container_of(layout->link.prev, layout, link);

Wouldn't it be easier to just do this:

       layout = container_of(homescreen->layout_list.prev, struct layout, link);

You are right, it's more efficient, thanks.

> +
>         launcher = malloc(sizeof *launcher);
> -       launcher->path = strdup(path);
> +       memset(launcher, 0, sizeof *launcher);
>         launcher->icon = load_cairo_surface(icon);
>         if ( !launcher->icon ||
>              cairo_surface_status (launcher->icon) != 
> CAIRO_STATUS_SUCCESS) { @@ -451,9 +499,13 @@ tablet_shell_add_launcher(struct tablet *tablet,
>                 free(launcher);
>                 return;
>         }
> +       launcher->path = strdup(path);
>
> -       launcher->homescreen = homescreen;
> -       launcher->widget = widget_add_widget(homescreen->widget, launcher);
> +       launcher->layout = layout;
> +
> +       wl_list_insert(layout->launcher_list.prev, &launcher->link);
> +
> +       launcher->widget = widget_add_widget(layout->widget, 
> + launcher);
>         widget_set_enter_handler(launcher->widget,
>                                  launcher_enter_handler);
>         widget_set_leave_handler(launcher->widget,
> @@ -462,8 +514,6 @@ tablet_shell_add_launcher(struct tablet *tablet,
>                                   launcher_button_handler);
>         widget_set_redraw_handler(launcher->widget,
>                                   launcher_redraw_handler);
> -
> -       wl_list_insert(&homescreen->launcher_list, &launcher->link);
>  }
>
>  static void
> @@ -476,7 +526,7 @@ launcher_section_done(void *data)
>                 return;
>         }
>
> -       tablet_shell_add_launcher(tablet, key_launcher_icon, key_launcher_path);
> +       layout_add_launcher(tablet, key_launcher_icon, 
> + key_launcher_path);
>
>         free(key_launcher_icon);
>         key_launcher_icon = NULL;
> @@ -527,7 +577,6 @@ int main(int argc, char *argv[])
>         tablet.homescreen = homescreen_create(&tablet);
>         tablet_shell_set_homescreen(tablet.tablet_shell,
>                         window_get_wl_surface(tablet.homescreen->window));
> -       wl_list_init(&tablet.homescreen->launcher_list);
>         wl_list_init(&tablet.homescreen->layout_list);
>
>         config_file = config_file_path("weston-tablet.ini");
> diff --git a/weston-tablet.ini b/weston-tablet.ini index 
> d38b87a..b5239a8 100644
> --- a/weston-tablet.ini
> +++ b/weston-tablet.ini
> @@ -4,6 +4,9 @@ 
> lockscreen-icon=/usr/share/weston/org.tizen.gallery.png
>  lockscreen=/usr/share/backgrounds/gnome/Garden.jpg
>  homescreen=/usr/share/backgrounds/gnome/Aqua.jpg
>  animation=zoom
> +layout-rows=6
> +layout-columns=8
> +icon-size=64
>
>  [layout]
>  [launcher]
> --
> 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