[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