[RFC PATCH 05/12] tablet-shell: Add trash function when dragging launchers.

juan.j.zhao at linux.intel.com juan.j.zhao at linux.intel.com
Fri Aug 3 04:21:22 PDT 2012


From: Ning Tang <tecton69 at gmail.com>

Show a trash image when dragging the launcher.
If launcher is upon trash, it will be translucent and release it
will cause the icon as well as tag in weston.ini be deleted.

Signed-off-by: Li Chen	    <cl.zhejiang.china at gmail.com>
Signed-off-by: Yi Yuan	    <harryyuan910702 at gmail.com>
Signed-off-by: Ning Tang    <tecton69 at gmail.com>
---
 clients/tablet-shell.c | 179 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 178 insertions(+), 1 deletion(-)

diff --git a/clients/tablet-shell.c b/clients/tablet-shell.c
index 1b0ef0d..651aa67 100644
--- a/clients/tablet-shell.c
+++ b/clients/tablet-shell.c
@@ -101,15 +101,23 @@ static char *key_launcher_icon;
 static char *key_launcher_path;
 static void launcher_section_done(void *data);
 static void layout_section_done(void *data);
+/* trash image string */
+static char *key_trash_image;
 /* launcher drag */
 struct launcher *gl_launcher_drag = NULL;
 /* launcher size */
 static int launcher_size = 146;
+/* trash parameters */
+static cairo_surface_t *trash_surface = NULL;
+static int trash_x, trash_y;
+static int trash_w, trash_h;
+static int trash_highlight = 0;
 
 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 },
 };
 
 static const struct config_key launcher_config_keys[] = {
@@ -168,6 +176,53 @@ 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){
+	int w, h;
+	cairo_t *cr;
+	cairo_surface_t *surface;
+	struct homescreen *homescreen = data;
+
+	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;
+	}
+
+	// get image size
+	w = cairo_image_surface_get_width(trash_surface);
+	h = cairo_image_surface_get_height(trash_surface);
+
+	// set up trash allocation
+	trash_x = x;
+	trash_y = y;
+	trash_w = w;
+	trash_h = h;
+
+	surface = window_get_surface(homescreen->window);
+	cr = cairo_create(surface);
+
+	cairo_set_source_surface(cr, trash_surface,
+				 x - w / 2, y - h / 2);
+	cairo_paint(cr);
+
+	// highlight trash
+	if (trash_highlight) {
+		cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.4);
+		cairo_mask_surface(cr, trash_surface,
+				   x - w / 2, y - h / 2);
+	}
+	cairo_destroy(cr);
+	cairo_surface_destroy(surface);
+}
+
 static void
 homescreen_draw(struct widget *widget, void *data)
 {
@@ -197,6 +252,12 @@ 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.75,
+				      allocation.height * 0.75);
+	}
 
 	cairo_destroy(cr);
 	cairo_surface_destroy(surface);
@@ -398,6 +459,65 @@ 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.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;
+	}
+	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);
+	fclose(fp);
+	printf("launcher deleted.\n");
+	return 1;
+}
+
 static void
 launcher_data_handler(struct window *window,
 		      struct input *input,
@@ -408,8 +528,62 @@ launcher_data_handler(struct window *window,
 	if (strcmp(types[0], "application/tablet-launcher") != 0) {
 		return;
 	}
-	input_accept(input, types[0]);
+	if (x > trash_x - trash_w / 2 && x < trash_x + trash_w / 2 &&
+	    y > trash_y - trash_h / 2 && y < trash_y + trash_h / 2) {
+		input_accept(input, NULL);
+	} else {
+		input_accept(input, types[0]);
+	}
+}
+
+static void
+launcher_drop_handler(struct window *window, struct input *input,
+		      int32_t x, int32_t y, void *data)
+{
+	if (gl_launcher_drag == NULL ||
+	    gl_launcher_drag->widget == NULL) {
+		fprintf(stderr, "ignoring drop from another client\n");
+		return;
+	}
+
+	struct launcher *launcher = gl_launcher_drag;
+	struct layout *layout = launcher->layout;
+	struct launcher *temp_launcher;
+	int left, right, top, bottom;
+
+	// set bounds
+	left = trash_x - trash_w / 2;
+	right = trash_x + trash_w / 2;
+	top = trash_y - trash_h / 2;
+	bottom = trash_y + trash_h / 2;
+
+	launcher->dragging = 0;
+	launcher->pressed = 0;
+
+	if (x > left && x < right && y > top && y < bottom) {
+		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);
 }
+
 static struct homescreen *
 homescreen_create(struct tablet *tablet)
 {
@@ -426,6 +600,7 @@ homescreen_create(struct tablet *tablet)
 	widget_set_redraw_handler(homescreen->widget, homescreen_draw);
 
 	window_set_data_handler(homescreen->window, launcher_data_handler);
+	window_set_drop_handler(homescreen->window, launcher_drop_handler);
 
 	wl_list_init(&homescreen->layout_list);
 	return homescreen;
@@ -917,6 +1092,8 @@ layout_add_launcher(struct tablet *tablet,
 	launcher->layout = layout;
 
 	wl_list_insert(layout->launcher_list.prev, &launcher->link);
+	launcher->layout_index = wl_list_length(layout->layout_list);
+	launcher->index = wl_list_length(&layout->launcher_list);
 
 	launcher->widget = widget_add_widget(layout->widget, launcher);
 	widget_set_enter_handler(launcher->widget,
-- 
1.7.11



More information about the wayland-devel mailing list