diff --git a/src/compositor.c b/src/compositor.c index ef1c6ae2..a84ac081 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -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); diff --git a/src/compositor.h b/src/compositor.h index ac87f89d..1888ea64 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; @@ -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, diff --git a/src/shell.c b/src/shell.c index 86284627..ee71dcc1 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1034,6 +1034,50 @@ resize_binding(struct wl_input_device *device, uint32_t time, time, edges); } +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);