[RFC v4] Introduce output zoom.
Scott Moreau
oreaus at gmail.com
Wed Feb 22 13:21:41 PST 2012
Ideally, we would want to use <modifier>+Scroll binding but that will have
to wait for axis events. For now we just use keybindings. Zoom in/out with
Super+Up/Down.
---
src/compositor.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++--------
src/compositor.h | 14 +++++++++++
src/shell.c | 48 ++++++++++++++++++++++++++++++++++++++
3 files changed, 120 insertions(+), 10 deletions(-)
diff --git a/src/compositor.c b/src/compositor.c
index 5a424fa..1566753 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -743,7 +743,7 @@ weston_surface_draw(struct weston_surface *es, struct weston_output *output)
glUniform1f(es->shader->texwidth_uniform,
(GLfloat)es->geometry.width / es->pitch);
- if (es->transform.enabled)
+ if (es->transform.enabled || output->zoom.active)
filter = GL_LINEAR;
else
filter = GL_NEAREST;
@@ -979,6 +979,9 @@ weston_output_repaint(struct weston_output *output, int msecs)
&total_damage, &es->transform.opaque);
}
+ if (output->dirty)
+ weston_output_update_matrix(output);
+
output->repaint(output);
pixman_region32_fini(&total_damage);
@@ -1341,6 +1344,11 @@ notify_motion(struct wl_input_device *device, uint32_t time, int x, int y)
device->x = x;
device->y = y;
+ wl_list_for_each(output, &ec->output_list, link)
+ if (output->zoom.active &&
+ pixman_region32_contains_point(&output->region, x, y, NULL))
+ weston_output_update_zoom(output, x, y);
+
weston_device_repick(device, time);
interface = device->pointer_grab->interface;
interface->motion(device->pointer_grab, time,
@@ -1941,17 +1949,29 @@ weston_output_destroy(struct weston_output *output)
}
WL_EXPORT void
-weston_output_move(struct weston_output *output, int x, int y)
+weston_output_update_zoom(struct weston_output *output, int x, int y)
{
- int flip;
+ if (output->zoom.level <= 0)
+ return;
- output->x = x;
- output->y = y;
+ float ratio;
- pixman_region32_init(&output->previous_damage);
- pixman_region32_init_rect(&output->region, x, y,
- output->current->width,
- output->current->height);
+ output->zoom.magnification = 1 / output->zoom.level;
+ ratio = 1 - (1 / output->zoom.magnification);
+
+ output->zoom.trans_x = (((float)(x - output->x) / output->current->width) * (ratio * 2)) - ratio;
+ output->zoom.trans_y = (((float)(y - output->y) / output->current->height) * (ratio * 2)) - ratio;
+
+ output->dirty = 1;
+ weston_output_damage(output);
+}
+
+WL_EXPORT void
+weston_output_update_matrix(struct weston_output *output)
+{
+ int flip;
+ struct weston_matrix camera;
+ struct weston_matrix modelview;
weston_matrix_init(&output->matrix);
weston_matrix_translate(&output->matrix,
@@ -1962,8 +1982,28 @@ weston_output_move(struct weston_output *output, int x, int y)
weston_matrix_scale(&output->matrix,
2.0 / (output->current->width + output->border.left + output->border.right),
flip * 2.0 / (output->current->height + output->border.top + output->border.bottom), 1);
+ if (output->zoom.active) {
+ weston_matrix_init(&camera);
+ weston_matrix_init(&modelview);
+ weston_matrix_translate(&camera, output->zoom.trans_x, flip * output->zoom.trans_y, 0);
+ weston_matrix_invert(&modelview, &camera);
+ weston_matrix_scale(&modelview, output->zoom.magnification, output->zoom.magnification, 1.0);
+ weston_matrix_multiply(&output->matrix, &modelview);
+ }
- weston_output_damage(output);
+ output->dirty = 0;
+}
+
+WL_EXPORT void
+weston_output_move(struct weston_output *output, int x, int y)
+{
+ output->x = x;
+ output->y = y;
+
+ pixman_region32_init(&output->previous_damage);
+ pixman_region32_init_rect(&output->region, x, y,
+ output->current->width,
+ output->current->height);
}
WL_EXPORT void
@@ -1979,6 +2019,14 @@ weston_output_init(struct weston_output *output, struct weston_compositor *c,
output->border.right = 0;
output->mm_width = width;
output->mm_height = height;
+ output->dirty = 1;
+
+ output->zoom.active = 0;
+ output->zoom.increment = 0.05;
+ output->zoom.level = 1.0;
+ output->zoom.magnification = 1.0;
+ output->zoom.trans_x = 0.0;
+ output->zoom.trans_y = 0.0;
output->flags = flags;
weston_output_move(output, x, y);
diff --git a/src/compositor.h b/src/compositor.h
index 4c82e79..a11ca45 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -54,6 +54,14 @@ struct weston_border {
int32_t left, right, top, bottom;
};
+struct weston_output_zoom {
+ int active;
+ float increment;
+ float level;
+ float magnification;
+ float trans_x, trans_y;
+};
+
struct weston_output {
struct wl_list link;
struct weston_compositor *compositor;
@@ -66,6 +74,8 @@ struct weston_output {
uint32_t flags;
int repaint_needed;
int repaint_scheduled;
+ struct weston_output_zoom zoom;
+ int dirty;
char *make, *model;
uint32_t subpixel;
@@ -414,6 +424,10 @@ weston_compositor_init(struct weston_compositor *ec, struct wl_display *display)
void
weston_compositor_shutdown(struct weston_compositor *ec);
void
+weston_output_update_zoom(struct weston_output *output, int x, int y);
+void
+weston_output_update_matrix(struct weston_output *output);
+void
weston_output_move(struct weston_output *output, int x, int y);
void
weston_output_init(struct weston_output *output, struct weston_compositor *c,
diff --git a/src/shell.c b/src/shell.c
index 3d5dfd9..36b0c9e 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -1035,6 +1035,50 @@ resize_binding(struct wl_input_device *device, uint32_t time,
}
static void
+zoom_in_binding(struct wl_input_device *device, uint32_t time,
+ uint32_t key, uint32_t button, uint32_t state, void *data)
+{
+ struct weston_input_device *wd = (struct weston_input_device *) device;
+ struct weston_compositor *compositor = wd->compositor;
+ struct weston_output *output;
+
+ wl_list_for_each(output, &compositor->output_list, link) {
+ if (pixman_region32_contains_point(&output->region,
+ device->x, device->y, NULL)) {
+ output->zoom.active = 1;
+ output->zoom.level -= output->zoom.increment;
+
+ if (output->zoom.level < output->zoom.increment)
+ output->zoom.level = output->zoom.increment;
+
+ weston_output_update_zoom(output, device->x, device->y);
+ }
+ }
+}
+
+static void
+zoom_out_binding(struct wl_input_device *device, uint32_t time,
+ uint32_t key, uint32_t button, uint32_t state, void *data)
+{
+ struct weston_input_device *wd = (struct weston_input_device *) device;
+ struct weston_compositor *compositor = wd->compositor;
+ struct weston_output *output;
+
+ wl_list_for_each(output, &compositor->output_list, link) {
+ if (pixman_region32_contains_point(&output->region,
+ device->x, device->y, NULL)) {
+ output->zoom.level += output->zoom.increment;
+ if (output->zoom.level >= 1.0) {
+ output->zoom.active = 0;
+ output->zoom.level = 1.0;
+ }
+
+ weston_output_update_zoom(output, device->x, device->y);
+ }
+ }
+}
+
+static void
terminate_binding(struct wl_input_device *device, uint32_t time,
uint32_t key, uint32_t button, uint32_t state, void *data)
{
@@ -1832,6 +1876,10 @@ shell_init(struct weston_compositor *ec)
terminate_binding, ec);
weston_compositor_add_binding(ec, 0, BTN_LEFT, 0,
click_to_activate_binding, ec);
+ weston_compositor_add_binding(ec, KEY_UP, 0, MODIFIER_SUPER,
+ zoom_in_binding, shell);
+ weston_compositor_add_binding(ec, KEY_DOWN, 0, MODIFIER_SUPER,
+ zoom_out_binding, shell);
weston_compositor_add_binding(ec, 0, BTN_LEFT,
MODIFIER_SUPER | MODIFIER_ALT,
rotate_binding, NULL);
--
1.7.4.1
More information about the wayland-devel
mailing list