Implement a camera/modelview matrix for transforms to simulate camera movement. Ideally, we would want to use <modifier>+Scroll but that will have to wait for axis events. For now we use keyboard grabs. Zoom in/out with Super+Up/Down. Zoom area follows mouse pointer. --- src/compositor.c | 41 +++++++++++++++++++++++- src/compositor.h | 12 +++++++ src/shell.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+), 1 deletions(-)
diff --git a/src/compositor.c b/src/compositor.c index 8339e6c..ccbccd4 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -925,6 +925,7 @@ weston_output_repaint(struct weston_output *output, int msecs) struct weston_surface *es; struct weston_animation *animation, *next; struct weston_frame_callback *cb, *cnext; + struct weston_matrix modelview; pixman_region32_t opaque, new_damage, total_damage, overlap, surface_overlap; int32_t width, height; @@ -937,6 +938,12 @@ weston_output_repaint(struct weston_output *output, int msecs) output->border.top + output->border.bottom; glViewport(0, 0, width, height); + weston_matrix_init(&output->camera_matrix); + weston_matrix_translate(&output->camera_matrix, + output->zoom.trans_x, + output->zoom.trans_y, 0); + weston_matrix_invert(&modelview, &output->camera_matrix); + pixman_region32_init(&new_damage); pixman_region32_init(&opaque); pixman_region32_init(&overlap); @@ -953,6 +960,9 @@ weston_output_repaint(struct weston_output *output, int msecs) pixman_region32_fini(&surface_overlap); pixman_region32_union(&overlap, &overlap, &es->transform.boundingbox); + glUniform1f(es->shader->zoom_uniform, output->zoom.level); + glUniformMatrix4fv(es->shader->modelview_uniform, + 1, GL_FALSE, modelview.d); } weston_output_set_cursor(output, ec->input_device); @@ -1322,6 +1332,9 @@ notify_motion(struct wl_input_device *device, uint32_t time, int x, int y) max_x = output->x + output->current->width; if (output->y + output->current->height > max_y) max_y = output->y + output->current->height; + if (output->zoom.active && + pixman_region32_contains_point(&output->region, x, y, NULL)) + zoom_update(output, x, y); } if (!x_valid) { @@ -1850,12 +1863,14 @@ bind_output(struct wl_client *client, static const char vertex_shader[] = "uniform mat4 proj;\n" + "uniform mat4 modelview;\n" + "uniform float zoom;\n" "attribute vec2 position;\n" "attribute vec2 texcoord;\n" "varying vec2 v_texcoord;\n" "void main()\n" "{\n" - " gl_Position = proj * vec4(position, 0.0, 1.0);\n" + " gl_Position = proj * (modelview * vec4(position, 0.0, zoom));\n" " v_texcoord = texcoord;\n" "}\n"; @@ -1929,6 +1944,8 @@ weston_shader_init(struct weston_shader *shader, } shader->proj_uniform = glGetUniformLocation(shader->program, "proj"); + shader->modelview_uniform = glGetUniformLocation(shader->program, "modelview"); + shader->zoom_uniform = glGetUniformLocation(shader->program, "zoom"); shader->tex_uniform = glGetUniformLocation(shader->program, "tex"); shader->alpha_uniform = glGetUniformLocation(shader->program, "alpha"); shader->color_uniform = glGetUniformLocation(shader->program, "color"); @@ -1946,6 +1963,21 @@ weston_output_destroy(struct weston_output *output) } WL_EXPORT void +zoom_update(struct weston_output *output, int x, int y) +{ + if (output->zoom.level <= 0) + return; + + float ratio = (1 / output->zoom.level) - 1; + + output->zoom.trans_x = (output->mm_width * ratio) * + ((float)x / output->mm_width); + output->zoom.trans_y = (output->mm_height * ratio) * + ((float)y / output->mm_height); + weston_output_damage(output); +} + +WL_EXPORT void weston_output_move(struct weston_output *output, int x, int y) { int flip; @@ -1985,6 +2017,13 @@ weston_output_init(struct weston_output *output, struct weston_compositor *c, output->mm_width = width; output->mm_height = height; + output->zoom.active = 0; + output->zoom.level = 1.0; + output->zoom.trans_x = 0.0; + output->zoom.trans_y = 0.0; + + weston_matrix_init(&output->camera_matrix); + output->flags = flags; weston_output_move(output, x, y); diff --git a/src/compositor.h b/src/compositor.h index 4c82e79..66ec688 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -54,10 +54,17 @@ struct weston_border { int32_t left, right, top, bottom; }; +struct weston_output_zoom { + int active; + float level; + int trans_x, trans_y; +}; + struct weston_output { struct wl_list link; struct weston_compositor *compositor; struct weston_matrix matrix; + struct weston_matrix camera_matrix; struct wl_list frame_callback_list; int32_t x, y, mm_width, mm_height; struct weston_border border; @@ -66,6 +73,7 @@ struct weston_output { uint32_t flags; int repaint_needed; int repaint_scheduled; + struct weston_output_zoom zoom; char *make, *model; uint32_t subpixel; @@ -100,6 +108,8 @@ struct weston_shader { GLuint program; GLuint vertex_shader, fragment_shader; GLint proj_uniform; + GLint modelview_uniform; + GLint zoom_uniform; GLint tex_uniform; GLint alpha_uniform; GLint color_uniform; @@ -414,6 +424,8 @@ weston_compositor_init(struct weston_compositor *ec, struct wl_display *display) void weston_compositor_shutdown(struct weston_compositor *ec); void +zoom_update(struct weston_output *output, int x, int y); +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 fa165e2..ee406f0 100644 --- a/src/shell.c +++ b/src/shell.c @@ -113,6 +113,11 @@ struct shell_surface { struct wl_list link; }; +struct weston_zoom_grab { + struct wl_keyboard_grab grab; + uint32_t key; +}; + struct weston_move_grab { struct wl_pointer_grab grab; struct weston_surface *surface; @@ -1035,6 +1040,88 @@ resize_binding(struct wl_input_device *device, uint32_t time, } static void +zoom_grab_key(struct wl_keyboard_grab *grab, + uint32_t time, uint32_t key, int32_t state) +{ + struct weston_zoom_grab *zoom; + zoom = container_of(grab, struct weston_zoom_grab, grab); + + if (state == 0) { + wl_input_device_end_keyboard_grab(grab->input_device, time); + free(zoom); + } +} + +static const struct wl_keyboard_grab_interface zoom_grab_interface = { + zoom_grab_key, +}; + +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; + struct weston_zoom_grab *zoom; + + zoom = malloc(sizeof *zoom); + if (!zoom) + return; + + zoom->grab.interface = &zoom_grab_interface; + + wl_input_device_start_keyboard_grab(&wd->input_device, &zoom->grab, time); + + 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 -= 0.05; + if (output->zoom.level > 1.0) + output->zoom.level = 1.0; + if (output->zoom.level < 0.0) + output->zoom.level = 0.05; + + zoom_update(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; + struct weston_zoom_grab *zoom; + + zoom = malloc(sizeof *zoom); + if (!zoom) + return; + + zoom->grab.interface = &zoom_grab_interface; + + wl_input_device_start_keyboard_grab(&wd->input_device, &zoom->grab, time); + + wl_list_for_each(output, &compositor->output_list, link) { + if (pixman_region32_contains_point(&output->region, + device->x, device->y, NULL)) { + output->zoom.level += 0.05; + if (output->zoom.level > 1.0) + output->zoom.level = 1.0; + if (output->zoom.level < 0.0) { + output->zoom.active = 0; + output->zoom.level = 0.0; + } + + zoom_update(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) { @@ -1827,6 +1914,10 @@ shell_init(struct weston_compositor *ec) move_binding, shell); weston_compositor_add_binding(ec, 0, BTN_MIDDLE, MODIFIER_SUPER, resize_binding, shell); + 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, KEY_BACKSPACE, 0, MODIFIER_CTRL | MODIFIER_ALT, terminate_binding, ec); -- 1.7.4.1 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel