[PATCH 06/14] tablet-shell: add trash function when dragging launcher icon.

Philipp Brüschweiler blei42 at gmail.com
Tue Aug 21 08:00:34 PDT 2012


On Tue, Aug 21, 2012 at 1:49 PM,  <tecton69 at gmail.com> wrote:
> From: Ning Tang <ning.tang at intel.com>
>
> Determine whether to accpet the data by the allocation of trash area. If
> the icon is in it, then drop event will delete either the icon image as
> well as tag in ini file.
>
>  Signed-off-by: Ning Tang <tecton69 at gmail.com>
>
> ---
>  clients/tablet-shell.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++-
>  weston-tablet.ini      |   1 +
>  2 files changed, 151 insertions(+), 3 deletions(-)
>
> diff --git a/clients/tablet-shell.c b/clients/tablet-shell.c
> index eaaa8d7..860bba8 100644
> --- a/clients/tablet-shell.c
> +++ b/clients/tablet-shell.c
> @@ -103,17 +103,22 @@ 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 char *key_trash_image;
>  /* launcher drag */
>  struct launcher *gl_launcher_drag = NULL;
>  static int launcher_size;
>  static int key_layout_rows;
>  static int key_layout_columns;
>  static int layout_moving;
> +/* trash parameters */
> +static cairo_surface_t *trash_surface = NULL;
> +struct rectangle *trash_allocation = NULL;
>
>  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 },
> +       { "trash-image", CONFIG_KEY_STRING, &key_trash_image },
>         { "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 },
> @@ -175,6 +180,49 @@ paint_background(cairo_t *cr, const char *path, struct rectangle *allocation)
>         }
>  }
>
> +/*simple draw trash function*/
> +static void
> +homescreen_draw_trash(void *data, int x, int y)
> +{
> +       cairo_t *cr;
> +       cairo_surface_t *surface;
> +       struct homescreen *homescreen = data;

Why don't you call this function with a struct homescreen* argument?
AFAICS it's only called by you directly.

> +
> +       if (key_trash_image) {
> +               if (!trash_surface) {
> +                       trash_surface = load_cairo_surface(key_trash_image);
> +               }
> +       } else {
> +               trash_surface = NULL;
> +       }
> +
> +       if (!trash_surface) {
> +               fprintf(stderr, "no trash image.\n");
> +               return;
> +       }
> +
> +       // set up trash allocation
> +       if (!trash_allocation) {
> +               trash_allocation = malloc(sizeof *trash_allocation);
> +               trash_allocation->x = x;
> +               trash_allocation->y = y;
> +               trash_allocation->width =
> +                       cairo_image_surface_get_width(trash_surface);
> +               trash_allocation->height =
> +                       cairo_image_surface_get_height(trash_surface);
> +       }

Could you do this initialization at startup instead on each redraw?

> +       surface = window_get_surface(homescreen->window);
> +       cr = cairo_create(surface);
> +
> +       cairo_set_source_surface(cr, trash_surface,
> +                                trash_allocation->x,
> +                                trash_allocation->y);
> +       cairo_paint(cr);
> +
> +       cairo_destroy(cr);
> +       cairo_surface_destroy(surface);
> +}
> +
>  static void
>  homescreen_draw(struct widget *widget, void *data)
>  {
> @@ -203,6 +251,13 @@ homescreen_draw(struct widget *widget, void *data)
>                 }
>         }
>
> +       /* draw trash if dragging*/
> +       if(gl_launcher_drag && gl_launcher_drag->widget) {
> +               homescreen_draw_trash(homescreen,
> +                                     allocation.width * 0.6,
> +                                     allocation.height * 0.6);
> +       }
> +
>         cairo_destroy(cr);
>         cairo_surface_destroy(surface);
>  }
> @@ -404,17 +459,83 @@ launcher_motion_handler(struct widget *widget, struct input *input,
>         return CURSOR_HAND1;
>  }
>
> +static int
> +layout_delete_launcher(struct launcher *launcher) {
> +       char *config_file = config_file_path("weston-tablet.ini");
> +       FILE *fp;
> +       char line[512];
> +       uint32_t found_pos = 0;
> +       uint32_t next_pos = 0;
> +       uint32_t end_length = 0;
> +       uint32_t layout_num = launcher->layout->index;
> +       uint32_t launcher_num = launcher->index;
> +
> +       fp = fopen(config_file, "r");
> +       if (fp == NULL) {
> +               fprintf(stderr, "couldn't open %s.\n", config_file);
> +               return -1;

You test the return value of this function against 0, so you should
return 0 on error, not -1. But I think this function is generally kind
of hacky... And I think it should be moved to shared/config-parser.c
together with the other config handling functions.

> +       }
> +       while (fgets(line, sizeof line, fp)) {
> +               if (strcmp("[layout]\n", line) == 0)
> +                       layout_num--;
> +               if (layout_num == 0 && strcmp("[launcher]\n", line) == 0) {
> +                       launcher_num--;
> +                       if (launcher_num == 0) {
> +                               found_pos = ftell(fp) - 11;
> +                               break;
> +                       }
> +               }
> +       }
> +       fseek(fp, found_pos, SEEK_SET);
> +       if (!fread(line, 1, 511, fp))
> +       {
> +               fprintf(stderr, "read ini file error.\n");
> +       }
> +       char *next = strchr(line + 10, '[');
> +       next_pos = next - line + found_pos;
> +
> +       char *start_content = malloc(sizeof (char) * (found_pos + 1));
> +       fseek(fp, 0, SEEK_END);
> +       end_length = ftell(fp) - next_pos;
> +       char *end_content = malloc(sizeof (char) * (end_length + 1));
> +       if (!start_content || !end_content) {
> +               fprintf(stderr, "Not enough memory when changing ini file.\n");
> +               return -1;
> +       }
> +       fseek(fp, 0, SEEK_SET);
> +       if (!fread(start_content, 1, found_pos, fp))
> +               fprintf(stderr, "read ini file error.\n");
> +       fseek(fp, next_pos, SEEK_SET);
> +       if (!fread(end_content, 1, end_length, fp))
> +               fprintf(stderr, "read ini file error.\n");
> +       fclose(fp);
> +       fp = fopen(config_file, "w");
> +       fwrite(start_content, found_pos, 1, fp);
> +       fwrite(end_content, end_length, 1, fp);
> +       free(start_content);
> +       free(end_content);
> +       fclose(fp);
> +       printf("launcher deleted.\n");
> +       return 1;
> +}
>  static void
>  launcher_data_handler(struct window *window,
>                       struct input *input,
>                       float x, float y, const char **types, void *data)
>  {
> -       if (!types)
> +       if (!types || !trash_allocation)
>                 return;
>         if (strcmp(types[0], "application/tablet-launcher") != 0) {
>                 return;
>         }
> -       input_accept(input, types[0]);
> +       if (x > trash_allocation->x&&
> +           x < trash_allocation->x + trash_allocation->width &&
> +           y > trash_allocation->y &&
> +           y < trash_allocation->y + trash_allocation->height) {

I think it would be worth it to refactor this comparison into its own
function. Maybe even move it to window.c, as it seems generally
useful.

> +               input_accept(input, NULL);
> +       } else {
> +               input_accept(input, types[0]);
> +       }
>  }
>
>  static void
> @@ -433,7 +554,31 @@ launcher_drop_handler(struct window *window, struct input *input,
>
>         launcher->dragging = 0;
>         launcher->pressed = 0;
> -       gl_launcher_drag = NULL;
> +
> +       if (x > trash_allocation->x &&
> +           x < trash_allocation->x + trash_allocation->width &&
> +           y > trash_allocation->y &&
> +           y < trash_allocation->y + trash_allocation->height) {
> +               if (layout_delete_launcher(launcher)) {
> +                       wl_list_remove(&launcher->link);
> +                       widget_destroy(launcher->widget);
> +                       launcher->widget = NULL;
> +                       free((char*)launcher->path);
> +                       cairo_surface_destroy(launcher->icon);
> +                       wl_data_source_destroy(launcher->data_source);
> +                       wl_surface_destroy(launcher->drag_surface);
> +                       cairo_surface_destroy(launcher->translucent);
> +                       cairo_surface_destroy(launcher->opaque);
> +                       int i = 1;
> +                       wl_list_for_each(temp_launcher,
> +                                        &layout->launcher_list, link) {
> +                               temp_launcher->index = i++;
> +                       }
> +                       window_schedule_redraw(layout->homescreen->window);
> +               }
> +       } else {
> +               gl_launcher_drag = NULL;
> +       }
>         window_schedule_redraw(launcher->layout->homescreen->window);
>  }
>
> @@ -900,6 +1045,7 @@ tablet_shell_add_layout(struct tablet *tablet)
>
>         /* let layout know number of layouts */
>         layout->layout_list = &homescreen->layout_list;
> +       layout->index = wl_list_length(layout->layout_list);
>
>         wl_list_insert(homescreen->layout_list.prev, &layout->link);
>         widget_set_button_handler(layout->widget,
> @@ -937,6 +1083,7 @@ layout_add_launcher(struct tablet *tablet,
>         launcher->layout = layout;
>
>         wl_list_insert(layout->launcher_list.prev, &launcher->link);
> +       launcher->index = wl_list_length(&layout->launcher_list);
>
>         launcher->widget = widget_add_widget(layout->widget, launcher);
>         widget_set_enter_handler(launcher->widget,
> diff --git a/weston-tablet.ini b/weston-tablet.ini
> index b5239a8..58fd688 100644
> --- a/weston-tablet.ini
> +++ b/weston-tablet.ini
> @@ -7,6 +7,7 @@ animation=zoom
>  layout-rows=6
>  layout-columns=8
>  icon-size=64
> +trash-image=/usr/share/weston/trash.png
>
>  [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