[PATCH weston 6/6] zoom: Change how we select a zoom location

Derek Foreman derekf at osg.samsung.com
Fri Jan 9 10:45:19 PST 2015


Any time the zoom is updated the best zoom target will be calculated
with the following priority:

1) The current pointer location.

2) The last known location of the pointer that initiated the zoom.

3) The center of the current keyboard focus.  If the focus is split across
heads, multiple heads may zoom.

4) The center of the first output.

It should be possible in all cases to zoom out with a keyboard binding,
even if the previous target is no longer available.  Once zoomed out
completely the zoom deactivates and it may no longer be possible to
zoom back in at that location.

If a seat that initiated a zoom no longer has a keyboard (so is unable
to change the zoom) then other seats will control that zoom.

The zoom may jump when the target changes.

Signed-off-by: Derek Foreman <derekf at osg.samsung.com>
---
 desktop-shell/shell.c | 18 +++++++++----
 src/compositor.c      | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/compositor.h      |  6 +++++
 src/zoom.c            | 20 +++++++++------
 4 files changed, 101 insertions(+), 13 deletions(-)

diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index 973b5b3..8ae9834 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -4666,16 +4666,23 @@ static void
 do_zoom(struct weston_seat *seat, uint32_t time, uint32_t key, uint32_t axis,
 	wl_fixed_t value)
 {
+	bool zoomed = false;
 	struct weston_seat *ws = (struct weston_seat *) seat;
 	struct weston_compositor *compositor = ws->compositor;
 	struct weston_output *output;
 	float increment;
 
-	wl_list_for_each(output, &compositor->output_list, link) {
-		if (pixman_region32_contains_point(&output->region,
-						   wl_fixed_to_double(seat->pointer->x),
-						   wl_fixed_to_double(seat->pointer->y),
-						   NULL)) {
+	wl_list_for_each_reverse(output, &compositor->output_list, link) {
+		/* Don't mess with another seat's zoom unless it
+		 * can't unzoom itself.
+		 */
+		if (output->zoom.active &&
+		    output->zoom.seat != seat &&
+		    output->zoom.seat->keyboard_device_count > 0)
+			continue;
+
+		if (weston_get_zoom_target(output, seat, NULL, NULL) == 0 ||
+		    (zoomed == false && output->id == 0)) {
 			if (key == KEY_PAGEUP)
 				increment = output->zoom.increment;
 			else if (key == KEY_PAGEDOWN)
@@ -4703,6 +4710,7 @@ do_zoom(struct weston_seat *seat, uint32_t time, uint32_t key, uint32_t axis,
 			output->zoom.spring_z.target = output->zoom.level;
 
 			weston_output_update_zoom(output);
+			zoomed = true;
 		}
 	}
 }
diff --git a/src/compositor.c b/src/compositor.c
index b84658a..3c74e50 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -4738,6 +4738,76 @@ weston_parse_transform(const char *transform, uint32_t *out)
 	return -1;
 }
 
+
+/** Get zoom target (x and y co-ordinates) for the output and seat.
+ *
+ * \param output The output to be zoomed
+ * \param seat The seat that initiated the zoom request - may be NULL if
+ * an active zoom already exists.
+ * \return 0 for success
+ *         1 if the target isn't on the output but exists (x, y are updated)
+ *        -1 if no target could be found
+ */
+WL_EXPORT int
+weston_get_zoom_target(struct weston_output *output,
+		       struct weston_seat *seat,
+		       wl_fixed_t *x,
+		       wl_fixed_t *y)
+{
+	uint32_t mask_bit;
+	struct weston_surface *focus = NULL;
+	double tmp_x, tmp_y;
+
+	if (seat == NULL && output->zoom.active)
+		seat = output->zoom.seat;
+
+	assert(seat);
+
+	if (seat->pointer_device_count > 0) {
+		if (x)
+			*x = seat->pointer->x;
+		if (y)
+			*y = seat->pointer->y;
+		tmp_x = wl_fixed_to_double(seat->pointer->x);
+		tmp_y = wl_fixed_to_double(seat->pointer->y);
+		if (pixman_region32_contains_point(&output->region,
+						   tmp_x, tmp_y, NULL))
+			return 0;
+		return 1;
+	}
+
+	if (seat->keyboard_device_count > 0)
+		focus = weston_surface_get_main_surface(seat->keyboard->focus);
+
+	mask_bit = 1 << output->id;
+	if (focus && (mask_bit & focus->output_mask)) {
+		struct weston_view *view;
+		wl_list_for_each(view, &focus->views, surface_link) {
+			if (!(mask_bit & view->output_mask))
+				continue;
+			if (x) {
+				double cx = view->geometry.x + focus->width / 2.0;
+				*x = wl_fixed_from_double(cx);
+			}
+			if (y) {
+				double cy = view->geometry.y + focus->height / 2.0;
+				*y = wl_fixed_from_double(cy);
+			}
+			return 0;
+		}
+	}
+
+	if (output->zoom.active) {
+		if (x)
+			*x = wl_fixed_from_double(output->x + output->width / 2.0);
+		if (y)
+			*y = wl_fixed_from_double(output->y + output->height / 2.0);
+		return 0;
+	}
+	return -1;
+
+}
+
 WL_EXPORT const char *
 weston_transform_to_string(uint32_t output_transform)
 {
diff --git a/src/compositor.h b/src/compositor.h
index fafdf95..e41b1ff 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -1493,6 +1493,12 @@ weston_load_module(const char *name, const char *entrypoint);
 int
 weston_parse_transform(const char *transform, uint32_t *out);
 
+int
+weston_get_zoom_target(struct weston_output *output,
+		       struct weston_seat *seat,
+		       wl_fixed_t *x,
+		       wl_fixed_t *y);
+
 const char *
 weston_transform_to_string(uint32_t output_transform);
 
diff --git a/src/zoom.c b/src/zoom.c
index 70afb7c..d6a2274 100644
--- a/src/zoom.c
+++ b/src/zoom.c
@@ -66,7 +66,6 @@ static void
 weston_zoom_frame_xy(struct weston_animation *animation,
 		struct weston_output *output, uint32_t msecs)
 {
-	struct weston_seat *seat = output->zoom.seat;
 	wl_fixed_t x, y;
 
 	if (animation->frame_counter <= 1)
@@ -84,8 +83,9 @@ weston_zoom_frame_xy(struct weston_animation *animation,
 
 	if (weston_spring_done(&output->zoom.spring_xy)) {
 		output->zoom.spring_xy.current = output->zoom.spring_xy.target;
-		output->zoom.current.x = seat->pointer->x;
-		output->zoom.current.y = seat->pointer->y;
+		weston_get_zoom_target(output, NULL,
+				       &output->zoom.current.x,
+				       &output->zoom.current.y);
 		wl_list_remove(&animation->link);
 		wl_list_init(&animation->link);
 	}
@@ -170,16 +170,20 @@ weston_zoom_transition(struct weston_output *output, wl_fixed_t x, wl_fixed_t y)
 WL_EXPORT void
 weston_output_update_zoom(struct weston_output *output)
 {
-	struct weston_seat *seat = output->zoom.seat;
-	wl_fixed_t x = seat->pointer->x;
-	wl_fixed_t y = seat->pointer->y;
+	wl_fixed_t target_x, target_y, x, y;
 
 	assert(output->zoom.active);
 
+	if (weston_get_zoom_target(output, NULL, &target_x, &target_y) < 0)
+		return;
+
+	x = target_x;
+	y = target_y;
 	zoom_area_center_from_point(output, &x, &y);
+
 	if (wl_list_empty(&output->zoom.animation_xy.link)) {
-		output->zoom.current.x = seat->pointer->x;
-		output->zoom.current.y = seat->pointer->y;
+		output->zoom.current.x = target_x;
+		output->zoom.current.y = target_y;
 	} else {
 		output->zoom.to.x = x;
 		output->zoom.to.y = y;
-- 
2.1.4



More information about the wayland-devel mailing list