[PATCH v3] shell: moving drag surface refine

juan.j.zhao at linux.intel.com juan.j.zhao at linux.intel.com
Tue Aug 7 21:44:26 PDT 2012


From: Juan Zhao <juan.j.zhao at linux.intel.com>

When applications not directly based on toytoolkit, like simple-egl, efl
applications is grabbed and moved, they may be moved to the place under
the panel. Then they could not be grabbed again.
Don't allow the pointer's bounding box move across the shell's active_regions.
v3: use output_union, and signal to triggle configure active region.

Signed-off-by: Juan Zhao <juan.j.zhao at linux.intel.com>
---
 src/compositor-drm.c |  5 +++
 src/compositor.c     | 23 +++++++++++-
 src/compositor.h     |  6 ++--
 src/shell.c          | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 4 files changed, 127 insertions(+), 5 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 33bffae..ea5947a 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -1522,6 +1522,8 @@ create_output_for_connector(struct drm_compositor *ec,
 				    connector->count_modes == 0 ?
 				    ", built-in" : "");
 
+	weston_compositor_union_output_region(&ec->base);
+	wl_signal_emit(&ec->base.output_signal, ec->base.shell_interface.shell);
 	return 0;
 
 err_surface:
@@ -1751,6 +1753,9 @@ update_outputs(struct drm_compositor *ec, struct udev_device *drm_device)
 	/* FIXME: handle zero outputs, without terminating */	
 	if (ec->connector_allocator == 0)
 		wl_display_terminate(ec->base.wl_display);
+
+	weston_compositor_union_output_region(&ec->base);
+	wl_signal_emit(&ec->base.output_signal, ec->base.shell_interface.shell);
 }
 
 static int
diff --git a/src/compositor.c b/src/compositor.c
index a3273dc..04b3b24 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -91,7 +91,13 @@ weston_output_switch_mode(struct weston_output *output, struct weston_mode *mode
 	if (!output->switch_mode)
 		return -1;
 
-	return output->switch_mode(output, mode);
+	if (output->switch_mode(output, mode) == 0) {
+		weston_compositor_union_output_region(output->compositor);
+		wl_signal_emit(&output->compositor->output_signal,
+				output->compositor->shell_interface.shell);
+		return 0;
+	}
+	return -1;
 }
 
 WL_EXPORT void
@@ -3151,6 +3157,7 @@ weston_compositor_init(struct weston_compositor *ec,
 	wl_signal_init(&ec->activate_signal);
 	wl_signal_init(&ec->lock_signal);
 	wl_signal_init(&ec->unlock_signal);
+	wl_signal_init(&ec->output_signal);
 	wl_signal_init(&ec->show_input_panel_signal);
 	wl_signal_init(&ec->hide_input_panel_signal);
 	ec->launcher_sock = weston_environment_get_fd("WESTON_LAUNCHER_SOCK");
@@ -3274,6 +3281,19 @@ weston_compositor_init_gl(struct weston_compositor *ec)
 }
 
 WL_EXPORT void
+weston_compositor_union_output_region(struct weston_compositor *ec)
+{
+	struct weston_output *output, *next;
+	pixman_region32_init(&ec->union_output_region);
+
+	wl_list_for_each_safe(output, next, &ec->output_list, link) {
+		pixman_region32_union(&ec->union_output_region,
+				      &ec->union_output_region,
+				      &output->region);
+	}
+}
+
+WL_EXPORT void
 weston_compositor_shutdown(struct weston_compositor *ec)
 {
 	struct weston_output *output, *next;
@@ -3285,6 +3305,7 @@ weston_compositor_shutdown(struct weston_compositor *ec)
 	/* Destroy all outputs associated with this compositor */
 	wl_list_for_each_safe(output, next, &ec->output_list, link)
 		output->destroy(output);
+	pixman_region32_fini(&ec->union_output_region);
 
 	weston_binding_list_destroy_all(&ec->key_binding_list);
 	weston_binding_list_destroy_all(&ec->button_binding_list);
diff --git a/src/compositor.h b/src/compositor.h
index 979ce66..e30f8d4 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -88,7 +88,6 @@ struct weston_shell_interface {
 	int (*move)(struct shell_surface *shsurf, struct weston_seat *ws);
 	int (*resize)(struct shell_surface *shsurf,
 		      struct weston_seat *ws, uint32_t edges);
-
 };
 
 struct weston_border {
@@ -284,6 +283,7 @@ struct weston_compositor {
 	struct wl_signal activate_signal;
 	struct wl_signal lock_signal;
 	struct wl_signal unlock_signal;
+	struct wl_signal output_signal;
 
 	struct wl_signal show_input_panel_signal;
 	struct wl_signal hide_input_panel_signal;
@@ -345,6 +345,7 @@ struct weston_compositor {
 	int launcher_sock;
 
 	uint32_t output_id_pool;
+	pixman_region32_t union_output_region;
 
 	struct xkb_rule_names xkb_names;
 	struct xkb_context *xkb_context;
@@ -562,7 +563,8 @@ void
 weston_compositor_activity(struct weston_compositor *compositor);
 void
 weston_compositor_update_drag_surfaces(struct weston_compositor *compositor);
-
+void
+weston_compositor_union_output_region(struct weston_compositor *ec);
 
 struct weston_binding;
 typedef void (*weston_key_binding_handler_t)(struct wl_seat *seat,
diff --git a/src/shell.c b/src/shell.c
index 6c810ff..954682d 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -71,6 +71,7 @@ struct desktop_shell {
 	struct wl_listener destroy_listener;
 	struct wl_listener show_input_panel_listener;
 	struct wl_listener hide_input_panel_listener;
+	struct wl_listener reconf_active_region_listener;
 
 	struct weston_layer fullscreen_layer;
 	struct weston_layer panel_layer;
@@ -124,6 +125,7 @@ struct desktop_shell {
 	uint32_t binding_modifier;
 	enum animation_type win_animation_type;
 	struct weston_surface *debug_repaint_surface;
+	pixman_region32_t active_region;
 };
 
 enum shell_surface_type {
@@ -226,6 +228,17 @@ get_shell_surface(struct weston_surface *surface);
 static struct desktop_shell *
 shell_surface_get_shell(struct shell_surface *shsurf);
 
+static int
+get_output_panel_height(struct desktop_shell *shell,
+                        struct weston_output *output);
+
+static struct weston_output *
+get_default_output(struct weston_compositor *compositor);
+
+static void
+active_region_substract(struct desktop_shell *shell, int32_t x,
+			       int32_t y, int32_t width, int32_t height);
+
 static bool
 shell_surface_is_top_fullscreen(struct shell_surface *shsurf)
 {
@@ -770,13 +783,44 @@ move_grab_motion(struct wl_pointer_grab *grab,
 	struct wl_pointer *pointer = grab->pointer;
 	struct shell_surface *shsurf = move->base.shsurf;
 	struct weston_surface *es;
-	int dx = wl_fixed_to_int(pointer->x + move->dx);
-	int dy = wl_fixed_to_int(pointer->y + move->dy);
+	struct desktop_shell *shell = NULL;
+	pixman_region32_t region;
+	pixman_box32_t *b;
+	int dx, dy, bounding_x, bounding_y, n_rects, i;
+	int updated_x = 0, updated_y = 0;
+	int boxsize = 4;
 
 	if (!shsurf)
 		return;
 
 	es = shsurf->surface;
+	shell = shell_surface_get_shell(shsurf);
+
+	bounding_x = wl_fixed_to_int(pointer->x) - boxsize;
+	bounding_y = wl_fixed_to_int(pointer->y) - boxsize;
+	pixman_region32_init(&region);
+	pixman_region32_init_rect(&region, bounding_x, bounding_y,
+				   boxsize << 1, boxsize << 1);
+	pixman_region32_intersect(&region, &region,
+				  &shell->active_region);
+	b = pixman_region32_rectangles(&region, &n_rects);
+
+	dx = (int)es->geometry.x;
+	dy = (int)es->geometry.y;
+	for ( i = 0; i < n_rects; i++) {
+		if ((!updated_x) && (b[i].x2 - b[i].x1 >= boxsize)) {
+			dx = wl_fixed_to_int(pointer->x + move->dx);
+			updated_x = 1;
+		}
+		if ((!updated_y) && (b[i].y2 - b[i].y1 >= boxsize)) {
+			dy = wl_fixed_to_int(pointer->y + move->dy);
+			updated_y = 1;
+		}
+	}
+	pixman_region32_fini(&region);
+
+	if((!updated_x) && (!updated_y))
+		return;
 
 	weston_surface_configure(es, dx, dy,
 				 es->geometry.width, es->geometry.height);
@@ -1909,11 +1953,23 @@ desktop_shell_set_background(struct wl_client *client,
 }
 
 static void
+active_region_substract(struct desktop_shell *shell, int32_t x,
+			       int32_t y, int32_t width, int32_t height)
+{
+	pixman_region32_t region;
+	pixman_region32_init_rect(&region, x, y, width, height);
+	pixman_region32_subtract(&shell->active_region,
+				  &shell->active_region, &region);
+}
+
+static void
 panel_configure(struct weston_surface *es, int32_t sx, int32_t sy)
 {
 	struct desktop_shell *shell = es->private;
 
 	configure_static_surface(es, &shell->panel_layer);
+	wl_signal_emit(&shell->compositor->output_signal,
+			shell);
 }
 
 static void
@@ -3226,16 +3282,50 @@ shell_destroy(struct wl_listener *listener, void *data)
 	wl_list_remove(&shell->unlock_listener.link);
 	wl_list_remove(&shell->show_input_panel_listener.link);
 	wl_list_remove(&shell->hide_input_panel_listener.link);
+	wl_list_remove(&shell->reconf_active_region_listener.link);
 
 	wl_array_for_each(ws, &shell->workspaces.array)
 		workspace_destroy(*ws);
 	wl_array_release(&shell->workspaces.array);
 
+	pixman_region32_fini(&shell->active_region);
+
 	free(shell->screensaver.path);
 	free(shell);
 }
 
 static void
+init_active_region(struct weston_compositor *ec, struct desktop_shell *shell)
+{
+	pixman_region32_init(&shell->active_region);
+	pixman_region32_union(&shell->active_region, &shell->active_region,
+			      &ec->union_output_region);
+	return;
+}
+
+static void
+reconf_active_region(struct wl_listener *listener, void *data)
+{
+	struct desktop_shell *shell =
+		container_of(listener, struct desktop_shell,
+				reconf_active_region_listener);
+	struct weston_surface *surface;
+
+	init_active_region(shell->compositor, shell);
+
+	/*subtract panel areas*/
+	wl_list_for_each(surface, &shell->panel_layer.surface_list, layer_link) {
+		if (!surface->output)
+			continue;
+		active_region_substract( shell,
+					(int32_t)surface->geometry.x,
+					(int32_t)surface->geometry.y,
+					 surface->geometry.width,
+					 surface->geometry.height);
+	}
+}
+
+static void
 shell_add_bindings(struct weston_compositor *ec, struct desktop_shell *shell)
 {
 	uint32_t mod;
@@ -3325,6 +3415,8 @@ shell_init(struct weston_compositor *ec)
 	wl_signal_add(&ec->show_input_panel_signal, &shell->show_input_panel_listener);
 	shell->hide_input_panel_listener.notify = hide_input_panels;
 	wl_signal_add(&ec->hide_input_panel_signal, &shell->hide_input_panel_listener);
+	shell->reconf_active_region_listener.notify = reconf_active_region;
+	wl_signal_add(&ec->output_signal, &shell->reconf_active_region_listener);
 	ec->ping_handler = ping_handler;
 	ec->shell_interface.shell = shell;
 	ec->shell_interface.create_shell_surface = create_shell_surface;
@@ -3387,5 +3479,7 @@ shell_init(struct weston_compositor *ec)
 
 	shell_add_bindings(ec, shell);
 
+	init_active_region(ec, shell);
+
 	return 0;
 }
-- 
1.7.11



More information about the wayland-devel mailing list