[RFC] compositor: Introduce composite zoom. v1
Scott Moreau
oreaus at gmail.com
Mon Feb 13 14:26:16 PST 2012
Implements a 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 to come. For now we double check for the binding
in notify_key as a quick-n-dirty hack to avoid sending unwanted events.
Zoom in/out with Super+Up/Down. Zoom area follows mouse pointer.
---
src/compositor.c | 43 +++++++++++++++++++++++++++++++++++++++++--
src/compositor.h | 15 +++++++++++++++
src/shell.c | 43 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 99 insertions(+), 2 deletions(-)
diff --git a/src/compositor.c b/src/compositor.c
index ab90ded..de4f9f4 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -307,6 +307,21 @@ surface_compute_bbox(struct weston_surface *surface, int32_t sx, int32_t sy,
ceilf(max_x) - int_x, ceilf(max_y) - int_y);
}
+WL_EXPORT void
+weston_update_zoom(struct weston_output *output, int x, int y)
+{
+ if (output->zoom.level <= 0.0)
+ return;
+
+ GLfloat 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);
+}
+
static void
weston_surface_update_transform_disable(struct weston_surface *surface)
{
@@ -774,7 +789,16 @@ weston_surface_draw(struct weston_surface *es, struct weston_output *output)
glUseProgram(es->shader->program);
ec->current_shader = es->shader;
}
+ glUniform1f(es->shader->zoom_uniform, output->zoom.level);
+ struct weston_matrix modelview_inverse;
+ weston_matrix_init(&output->modelview_matrix);
+ weston_matrix_translate(&output->modelview_matrix,
+ output->zoom.trans_x,
+ output->zoom.trans_y, 0);
+ weston_matrix_invert(&modelview_inverse, &output->modelview_matrix);
+ glUniformMatrix4fv(es->shader->modelview_uniform,
+ 1, GL_FALSE, modelview_inverse.d);
glUniformMatrix4fv(es->shader->proj_uniform,
1, GL_FALSE, output->matrix.d);
glUniform1i(es->shader->tex_uniform, 0);
@@ -1349,6 +1373,8 @@ 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)
+ weston_update_zoom(output, x, y);
}
if (!x_valid) {
@@ -1466,6 +1492,9 @@ notify_key(struct wl_input_device *device,
weston_compositor_run_binding(compositor, wd, time, key, 0, state);
+ if (wd->modifier_state & MODIFIER_SUPER && (key == KEY_UP || key == KEY_DOWN))
+ return;
+
update_modifier_state(wd, key, state);
end = device->keys.data + device->keys.size;
for (k = device->keys.data; k < end; k++) {
@@ -1815,12 +1844,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";
@@ -1894,6 +1925,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");
@@ -1950,6 +1983,12 @@ 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.increment = 0.05;
+ output->zoom.level = 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 966d3f4..0f5827e 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -54,10 +54,19 @@ struct weston_border {
int32_t left, right, top, bottom;
};
+struct weston_composite_zoom {
+ int active;
+ /* 1.0 is no zoom, 0.0 is 100% zoomed in */
+ GLfloat level;
+ float increment;
+ int trans_x, trans_y;
+};
+
struct weston_output {
struct wl_list link;
struct weston_compositor *compositor;
struct weston_matrix matrix;
+ struct weston_matrix modelview_matrix;
struct wl_list frame_callback_list;
int32_t x, y, mm_width, mm_height;
struct weston_border border;
@@ -66,6 +75,7 @@ struct weston_output {
uint32_t flags;
int repaint_needed;
int repaint_scheduled;
+ struct weston_composite_zoom zoom;
char *make, *model;
uint32_t subpixel;
@@ -105,6 +115,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;
@@ -325,6 +337,9 @@ void
weston_surface_draw(struct weston_surface *es, struct weston_output *output);
void
+weston_update_zoom(struct weston_output *output, int x, int y);
+
+void
notify_motion(struct wl_input_device *device,
uint32_t time, int x, int y);
void
diff --git a/src/shell.c b/src/shell.c
index 66c4f01..6b2ffc0 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -964,6 +964,45 @@ 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;
+ output = container_of(compositor->output_list.next,
+ struct weston_output, link);
+
+ output->zoom.active = 1;
+ output->zoom.level -= output->zoom.increment;
+ if (output->zoom.level > 1.0)
+ output->zoom.level = 1.0;
+ if (output->zoom.level <= output->zoom.increment)
+ output->zoom.level = output->zoom.increment;
+
+ weston_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;
+ output = container_of(compositor->output_list.next,
+ struct weston_output, link);
+
+ output->zoom.level += output->zoom.increment;
+ if (output->zoom.level > 1.0) {
+ output->zoom.active = 0;
+ output->zoom.level = 1.0;
+ }
+
+ weston_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)
{
@@ -1618,6 +1657,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
More information about the wayland-devel
mailing list