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

ning.tang at intel.com ning.tang at intel.com
Mon Sep 24 19:39:52 PDT 2012


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 <ning.tang at intel.com>
---
 clients/tablet-shell.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++-
 weston-tablet.ini      |   1 +
 2 files changed, 154 insertions(+), 3 deletions(-)

diff --git a/clients/tablet-shell.c b/clients/tablet-shell.c
index 37166a8..b593331 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,32 @@ paint_background(cairo_t *cr, const char *path, struct rectangle *allocation)
 	}
 }
 
+/*simple draw trash function*/
+static void
+homescreen_draw_trash(struct homescreen *homescreen)
+{
+	cairo_t *cr;
+	cairo_surface_t *surface;
+
+	if (!trash_surface) {
+		fprintf(stderr, "no trash image.\n");
+		return;
+	}
+	if (!trash_allocation)
+		return;
+
+	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 +234,11 @@ homescreen_draw(struct widget *widget, void *data)
 		}
 	}
 
+	/* draw trash if dragging*/
+	if(gl_launcher_drag && gl_launcher_drag->widget) {
+		homescreen_draw_trash(homescreen);
+	}
+
 	cairo_destroy(cr);
 	cairo_surface_destroy(surface);
 }
@@ -404,17 +440,86 @@ 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 + 1;
+	uint32_t launcher_num = launcher->index;
+
+	fp = fopen(config_file, "r");
+	if (fp == NULL) {
+		fprintf(stderr, "couldn't open %s.\n", config_file);
+		return 0;
+	}
+	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");
+		return 0;
+	}
+	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");
+		return 0;
+	}
+	fseek(fp, next_pos, SEEK_SET);
+	if (!fread(end_content, 1, end_length, fp)) {
+		fprintf(stderr, "read ini file error.\n");
+		return 0;
+	}
+	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);
+	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 (input_in_allocation(*trash_allocation, x, y)) {
+		input_accept(input, NULL);
+	} else {
+		input_accept(input, types[0]);
+	}
 }
 
 static void
@@ -433,7 +538,28 @@ launcher_drop_handler(struct window *window, struct input *input,
 
 	launcher->dragging = 0;
 	launcher->pressed = 0;
-	gl_launcher_drag = NULL;
+
+	if (input_in_allocation(*trash_allocation, x, y)) {
+		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);
 }
 
@@ -457,9 +583,30 @@ homescreen_create(struct tablet *tablet)
 
 	wl_list_init(&homescreen->layout_list);
 	layout_moving = 1;
+
 	return homescreen;
 }
 
+static void trash_set_allocation(struct rectangle allocation)
+{
+	if (key_trash_image) {
+		if (!trash_surface) {
+			trash_surface = load_cairo_surface(key_trash_image);
+		}
+	} else {
+		trash_surface = NULL;
+	}
+	if (!trash_allocation) {
+		trash_allocation = malloc(sizeof *trash_allocation);
+		trash_allocation->x = allocation.width * 0.6;
+		trash_allocation->y = allocation.height * 0.6;
+		trash_allocation->width =
+			cairo_image_surface_get_width(trash_surface);
+		trash_allocation->height =
+			cairo_image_surface_get_height(trash_surface);
+	}
+}
+
 static struct lockscreen *
 lockscreen_create(struct tablet *tablet)
 {
@@ -905,6 +1052,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,
@@ -941,6 +1089,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,
@@ -1031,6 +1180,7 @@ int main(int argc, char *argv[])
 	widget_schedule_resize(tablet.homescreen->widget,
 			tablet.allocation.width,
 			tablet.allocation.height);
+	trash_set_allocation(tablet.allocation);
 	display_run(display);
 
 	return 0;
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.12.1



More information about the wayland-devel mailing list