<br><br><div class="gmail_quote">On Tue, Feb 14, 2012 at 12:53 AM, Pekka Paalanen <span dir="ltr"><<a href="mailto:ppaalanen@gmail.com">ppaalanen@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="im">On Mon, 13 Feb 2012 15:26:16 -0700<br>
Scott Moreau <<a href="mailto:oreaus@gmail.com">oreaus@gmail.com</a>> wrote:<br>
<br>
> Implements a modelview matrix for transforms to simulate camera movement.<br>
> Ideally, we would want to use <modifier>+Scroll but that will have to<br>
> wait for axis events to come. For now we double check for the binding<br>
> in notify_key as a quick-n-dirty hack to avoid sending unwanted events.<br>
> Zoom in/out with Super+Up/Down. Zoom area follows mouse pointer.<br>
><br>
> ---<br>
> src/compositor.c | 43 +++++++++++++++++++++++++++++++++++++++++--<br>
> src/compositor.h | 15 +++++++++++++++<br>
> src/shell.c | 43 +++++++++++++++++++++++++++++++++++++++++++<br>
> 3 files changed, 99 insertions(+), 2 deletions(-)<br>
><br>
> diff --git a/src/compositor.c b/src/compositor.c<br>
> index ab90ded..de4f9f4 100644<br>
> --- a/src/compositor.c<br>
> +++ b/src/compositor.c<br>
> @@ -307,6 +307,21 @@ surface_compute_bbox(struct weston_surface *surface, int32_t sx, int32_t sy,<br>
> ceilf(max_x) - int_x, ceilf(max_y) - int_y);<br>
> }<br>
><br>
> +WL_EXPORT void<br>
> +weston_update_zoom(struct weston_output *output, int x, int y)<br>
<br>
</div>We already have the name "zoom" in util.c for per-surface scaling<br>
effect. Is there a danger to confuse these?<br></blockquote><div> </div><div>Probably. Which is why I think it may be time to start thinking about how to separate functionalities better.<br></div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
Following the naming conventions I were taught here, this function<br>
should at least be called weston_output_update_zoom(), since it is a<br>
weston_output method.<br></blockquote><div> </div><div>Noted.<br></div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div class="im"><br>
> +{<br>
> + if (output->zoom.level <= 0.0)<br>
> + return;<br>
> +<br>
> + GLfloat ratio = (1 / output->zoom.level) - 1;<br>
> +<br>
> + output->zoom.trans_x = (output->mm_width * ratio) *<br>
> + ((float)x / output->mm_width);<br>
> + output->zoom.trans_y = (output->mm_height * ratio) *<br>
> + ((float)y / output->mm_height);<br>
<br>
</div>That indentation looks funny.<br></blockquote><div> </div><div>Maybe it can be output->zoom.trans_x =\n ... </div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div class="im"><br>
> + weston_output_damage(output);<br>
> +}<br>
> +<br>
> static void<br>
> weston_surface_update_transform_disable(struct weston_surface *surface)<br>
> {<br>
> @@ -774,7 +789,16 @@ weston_surface_draw(struct weston_surface *es, struct weston_output *output)<br>
> glUseProgram(es->shader->program);<br>
> ec->current_shader = es->shader;<br>
> }<br>
> + glUniform1f(es->shader->zoom_uniform, output->zoom.level);<br>
><br>
> + struct weston_matrix modelview_inverse;<br>
> + weston_matrix_init(&output->modelview_matrix);<br>
> + weston_matrix_translate(&output->modelview_matrix,<br>
> + output->zoom.trans_x,<br>
> + output->zoom.trans_y, 0);<br>
> + weston_matrix_invert(&modelview_inverse, &output->modelview_matrix);<br>
<br>
</div>Couldn't these computations be moved to some per-output function?<br>
Repeating the same computation per surface is unnecessary.<br></blockquote><div> </div><div>Didn't notice that, thanks.<br></div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
Also, do you really need to call weston_matrix_invert() for inverting a<br>
pure translation matrix? ;-)<br></blockquote><div><br>For simple translation, it could be made much more compact but I wanted to simulate a camera matrix.<br></div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div class="im"><br>
> + glUniformMatrix4fv(es->shader->modelview_uniform,<br>
> + 1, GL_FALSE, modelview_inverse.d);<br>
<br>
</div>The inverse matrix is going into modelview uniform, one of them needs a<br>
corretion in the name.<br>
<div class="im"><br>
> glUniformMatrix4fv(es->shader->proj_uniform,<br>
> 1, GL_FALSE, output->matrix.d);<br>
> glUniform1i(es->shader->tex_uniform, 0);<br>
> @@ -1349,6 +1373,8 @@ notify_motion(struct wl_input_device *device, uint32_t time, int x, int y)<br>
> max_x = output->x + output->current->width;<br>
> if (output->y + output->current->height > max_y)<br>
> max_y = output->y + output->current->height;<br>
> + if (output->zoom.active)<br>
> + weston_update_zoom(output, x, y);<br>
> }<br>
><br>
> if (!x_valid) {<br>
> @@ -1466,6 +1492,9 @@ notify_key(struct wl_input_device *device,<br>
><br>
> weston_compositor_run_binding(compositor, wd, time, key, 0, state);<br>
><br>
> + if (wd->modifier_state & MODIFIER_SUPER && (key == KEY_UP || key == KEY_DOWN))<br>
> + return;<br>
<br>
</div>This does look a bit suspicious. So the reason for this is, that if we<br>
have keyboard-only bindings, using them will send the key events also to<br>
the client?<br></blockquote><div> </div><div>Yes. <br></div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
Hm, maybe we would need a keyboard grab for the time the binding is<br>
held down, to easily avoid sending both the key press and release, and<br>
getting clients out of sync. Waiting for proper keyboard grabs to be<br>
implemented...<br></blockquote><div><br>Yes, I've been looking into how to do proper keyboard grabs.<br></div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div><div class="h5"><br>
> +<br>
> update_modifier_state(wd, key, state);<br>
> end = device->keys.data + device->keys.size;<br>
> for (k = device->keys.data; k < end; k++) {<br>
> @@ -1815,12 +1844,14 @@ bind_output(struct wl_client *client,<br>
><br>
> static const char vertex_shader[] =<br>
> "uniform mat4 proj;\n"<br>
> + "uniform mat4 modelview;\n"<br>
> + "uniform float zoom;\n"<br>
> "attribute vec2 position;\n"<br>
> "attribute vec2 texcoord;\n"<br>
> "varying vec2 v_texcoord;\n"<br>
> "void main()\n"<br>
> "{\n"<br>
> - " gl_Position = proj * vec4(position, 0.0, 1.0);\n"<br>
> + " gl_Position = proj * (modelview * vec4(position, 0.0, zoom));\n"<br>
> " v_texcoord = texcoord;\n"<br>
> "}\n";<br>
><br>
> @@ -1894,6 +1925,8 @@ weston_shader_init(struct weston_shader *shader,<br>
> }<br>
><br>
> shader->proj_uniform = glGetUniformLocation(shader->program, "proj");<br>
> + shader->modelview_uniform = glGetUniformLocation(shader->program, "modelview");<br>
> + shader->zoom_uniform = glGetUniformLocation(shader->program, "zoom");<br>
> shader->tex_uniform = glGetUniformLocation(shader->program, "tex");<br>
> shader->alpha_uniform = glGetUniformLocation(shader->program, "alpha");<br>
> shader->color_uniform = glGetUniformLocation(shader->program, "color");<br>
> @@ -1950,6 +1983,12 @@ weston_output_init(struct weston_output *output, struct weston_compositor *c,<br>
> output->mm_width = width;<br>
> output->mm_height = height;<br>
><br>
> + output->zoom.active = 0;<br>
> + output->zoom.increment = 0.05;<br>
> + output->zoom.level = 1.0;<br>
> + output->zoom.trans_x = 0.0;<br>
> + output->zoom.trans_y = 0.0;<br>
<br>
</div></div>AFAICT, you are only using trans_x,trans_y for creating an equivalent<br>
translation matrix. You could store the translation matrix here instead<br>
and change the x,y elements.<br></blockquote><div><br>Yes, it certainly could be much simpler strictly for zoom. As you said on irc though, this could potentially be used for screen rotation and possibly other things. I wanted to take steps to show the function without obfuscating much, while trying to make it versatile.<br>
</div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div><div class="h5"><br>
> +<br>
> output->flags = flags;<br>
> weston_output_move(output, x, y);<br>
><br>
> diff --git a/src/compositor.h b/src/compositor.h<br>
> index 966d3f4..0f5827e 100644<br>
> --- a/src/compositor.h<br>
> +++ b/src/compositor.h<br>
> @@ -54,10 +54,19 @@ struct weston_border {<br>
> int32_t left, right, top, bottom;<br>
> };<br>
><br>
> +struct weston_composite_zoom {<br>
> + int active;<br>
> + /* 1.0 is no zoom, 0.0 is 100% zoomed in */<br>
> + GLfloat level;<br>
> + float increment;<br>
> + int trans_x, trans_y;<br>
> +};<br>
> +<br>
> struct weston_output {<br>
> struct wl_list link;<br>
> struct weston_compositor *compositor;<br>
> struct weston_matrix matrix;<br>
> + struct weston_matrix modelview_matrix;<br>
> struct wl_list frame_callback_list;<br>
> int32_t x, y, mm_width, mm_height;<br>
> struct weston_border border;<br>
> @@ -66,6 +75,7 @@ struct weston_output {<br>
> uint32_t flags;<br>
> int repaint_needed;<br>
> int repaint_scheduled;<br>
> + struct weston_composite_zoom zoom;<br>
><br>
> char *make, *model;<br>
> uint32_t subpixel;<br>
> @@ -105,6 +115,8 @@ struct weston_shader {<br>
> GLuint program;<br>
> GLuint vertex_shader, fragment_shader;<br>
> GLint proj_uniform;<br>
> + GLint modelview_uniform;<br>
> + GLint zoom_uniform;<br>
> GLint tex_uniform;<br>
> GLint alpha_uniform;<br>
> GLint color_uniform;<br>
> @@ -325,6 +337,9 @@ void<br>
> weston_surface_draw(struct weston_surface *es, struct weston_output *output);<br>
><br>
> void<br>
> +weston_update_zoom(struct weston_output *output, int x, int y);<br>
> +<br>
> +void<br>
> notify_motion(struct wl_input_device *device,<br>
> uint32_t time, int x, int y);<br>
> void<br>
> diff --git a/src/shell.c b/src/shell.c<br>
> index 66c4f01..6b2ffc0 100644<br>
> --- a/src/shell.c<br>
> +++ b/src/shell.c<br>
> @@ -964,6 +964,45 @@ resize_binding(struct wl_input_device *device, uint32_t time,<br>
> }<br>
><br>
> static void<br>
> +zoom_in_binding(struct wl_input_device *device, uint32_t time,<br>
> + uint32_t key, uint32_t button, uint32_t state, void *data)<br>
> +{<br>
> + struct weston_input_device *wd = (struct weston_input_device *) device;<br>
> + struct weston_compositor *compositor = wd->compositor;<br>
> + struct weston_output *output;<br>
> + output = container_of(compositor->output_list.next,<br>
> + struct weston_output, link);<br>
<br>
</div></div>You always zoom only the first output? How about an output where the<br>
pointer is in, or lacking a pointer, the output of the surface which<br>
has the keyboard focus?<br></blockquote><div> </div><div>Ah, should fix that. Thanks.<br></div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>