Introduce output zoom.
authorScott Moreau <oreaus@gmail.com>
Wed, 22 Feb 2012 21:21:41 +0000 (14:21 -0700)
committerKristian Høgsberg <krh@bitplanet.net>
Thu, 23 Feb 2012 22:45:49 +0000 (17:45 -0500)
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
src/compositor.h
src/shell.c

index ef1c6ae..a84ac08 100644 (file)
@@ -774,7 +774,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;
@@ -1010,6 +1010,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);
@@ -1497,6 +1500,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,
@@ -2096,17 +2104,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;
+       float ratio;
 
-       output->x = x;
-       output->y = y;
+       if (output->zoom.level <= 0)
+               return;
 
-       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,
@@ -2117,8 +2137,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
@@ -2134,6 +2174,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);
index ac87f89..1888ea6 100644 (file)
@@ -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;
@@ -420,6 +430,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,
index 8628462..ee71dcc 100644 (file)
@@ -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)
 {
@@ -1833,6 +1877,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);