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

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


> -----Original Message-----
> From: Philipp Brüschweiler [mailto:blei42 at gmail.com]
> Sent: Tuesday, August 21, 2012 11:01 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 06/14] tablet-shell: add trash function when dragging
> launcher icon.
> 
> 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.
> 
I will change that, thank you. :)

> > +
> > +       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?
> 
Yeah, that would be better.

> > +       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.
> 
Yes a little hacky and not a decent way...I thought it wasn't so common to add
In shared/config-parser.c. I would fix it.

> > +       }
> > +       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.
> 
OK, I'll refactor it. Thanks. In window.c widget_find_widget() has similar usage.
It may be reused. :)

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