blob: 292aed6c1ee888b964d4d3c6363e1d46839b7e10 [file] [log] [blame]
Scott Moreau429490d2012-06-17 18:10:59 -06001/*
2 * Copyright © 2012 Scott Moreau
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
Daniel Stonec228e232013-05-22 18:03:19 +030023#include "config.h"
24
Kristian Høgsberg583a2362012-06-25 17:13:58 -040025#include <stdlib.h>
26
Scott Moreau429490d2012-06-17 18:10:59 -060027#include "compositor.h"
Kristian Høgsberg583a2362012-06-25 17:13:58 -040028#include "text-cursor-position-server-protocol.h"
29
30struct text_cursor_position {
31 struct wl_object base;
32 struct weston_compositor *ec;
33 struct wl_global *global;
34 struct wl_listener destroy_listener;
35};
36
37static void
38text_cursor_position_notify(struct wl_client *client,
39 struct wl_resource *resource,
40 struct wl_resource *surface_resource,
41 wl_fixed_t x, wl_fixed_t y)
42{
43 weston_text_cursor_position_notify((struct weston_surface *) surface_resource, x, y);
44}
45
46struct text_cursor_position_interface text_cursor_position_implementation = {
47 text_cursor_position_notify
48};
49
50static void
51bind_text_cursor_position(struct wl_client *client,
52 void *data, uint32_t version, uint32_t id)
53{
54 wl_client_add_object(client, &text_cursor_position_interface,
55 &text_cursor_position_implementation, id, data);
56}
57
58static void
59text_cursor_position_notifier_destroy(struct wl_listener *listener, void *data)
60{
61 struct text_cursor_position *text_cursor_position =
62 container_of(listener, struct text_cursor_position, destroy_listener);
63
64 wl_display_remove_global(text_cursor_position->ec->wl_display, text_cursor_position->global);
65 free(text_cursor_position);
66}
67
68void
69text_cursor_position_notifier_create(struct weston_compositor *ec)
70{
71 struct text_cursor_position *text_cursor_position;
72
73 text_cursor_position = malloc(sizeof *text_cursor_position);
74 if (text_cursor_position == NULL)
75 return;
76
77 text_cursor_position->base.interface = &text_cursor_position_interface;
78 text_cursor_position->base.implementation =
79 (void(**)(void)) &text_cursor_position_implementation;
80 text_cursor_position->ec = ec;
81
82 text_cursor_position->global = wl_display_add_global(ec->wl_display,
83 &text_cursor_position_interface,
84 text_cursor_position, bind_text_cursor_position);
85
86 text_cursor_position->destroy_listener.notify = text_cursor_position_notifier_destroy;
87 wl_signal_add(&ec->destroy_signal, &text_cursor_position->destroy_listener);
88}
Scott Moreau429490d2012-06-17 18:10:59 -060089
90WL_EXPORT void
91weston_text_cursor_position_notify(struct weston_surface *surface,
92 wl_fixed_t cur_pos_x,
93 wl_fixed_t cur_pos_y)
94{
95 struct weston_output *output;
96 wl_fixed_t global_x, global_y;
97
98 weston_surface_to_global_fixed(surface, cur_pos_x, cur_pos_y,
99 &global_x, &global_y);
100
101 wl_list_for_each(output, &surface->compositor->output_list, link)
102 if (output->zoom.active &&
103 pixman_region32_contains_point(&output->region,
104 wl_fixed_to_int(global_x),
105 wl_fixed_to_int(global_y),
106 NULL)) {
107 output->zoom.text_cursor.x = global_x;
108 output->zoom.text_cursor.y = global_y;
109 weston_output_update_zoom(output, ZOOM_FOCUS_TEXT);
110 }
111}
112
113static void
114weston_zoom_frame_z(struct weston_animation *animation,
115 struct weston_output *output, uint32_t msecs)
116{
117 if (animation->frame_counter <= 1)
118 output->zoom.spring_z.timestamp = msecs;
119
120 weston_spring_update(&output->zoom.spring_z, msecs);
121
122 if (output->zoom.spring_z.current > output->zoom.max_level)
123 output->zoom.spring_z.current = output->zoom.max_level;
124 else if (output->zoom.spring_z.current < 0.0)
125 output->zoom.spring_z.current = 0.0;
126
127 if (weston_spring_done(&output->zoom.spring_z)) {
Ville Syrjäläaa628d02012-11-16 11:48:47 +0200128 if (output->zoom.active && output->zoom.level <= 0.0) {
Scott Moreau429490d2012-06-17 18:10:59 -0600129 output->zoom.active = 0;
Kristian Høgsberg79af73e2012-08-03 15:45:23 -0400130 output->disable_planes--;
131 }
Scott Moreau429490d2012-06-17 18:10:59 -0600132 output->zoom.spring_z.current = output->zoom.level;
133 wl_list_remove(&animation->link);
134 wl_list_init(&animation->link);
135 }
136
137 output->dirty = 1;
138 weston_output_damage(output);
139}
140
Kristian Høgsbergef6f1362012-08-10 10:07:55 -0400141static struct weston_seat *
142weston_zoom_pick_seat(struct weston_compositor *compositor)
143{
144 return container_of(compositor->seat_list.next,
145 struct weston_seat, link);
146}
147
148
Scott Moreau429490d2012-06-17 18:10:59 -0600149static void
150weston_zoom_frame_xy(struct weston_animation *animation,
151 struct weston_output *output, uint32_t msecs)
152{
Kristian Høgsbergef6f1362012-08-10 10:07:55 -0400153 struct weston_seat *seat = weston_zoom_pick_seat(output->compositor);
Scott Moreau429490d2012-06-17 18:10:59 -0600154 wl_fixed_t x, y;
Kristian Høgsbergef6f1362012-08-10 10:07:55 -0400155
Scott Moreau429490d2012-06-17 18:10:59 -0600156 if (animation->frame_counter <= 1)
157 output->zoom.spring_xy.timestamp = msecs;
158
159 weston_spring_update(&output->zoom.spring_xy, msecs);
160
161 x = output->zoom.from.x - ((output->zoom.from.x - output->zoom.to.x) *
162 output->zoom.spring_xy.current);
163 y = output->zoom.from.y - ((output->zoom.from.y - output->zoom.to.y) *
164 output->zoom.spring_xy.current);
165
166 output->zoom.current.x = x;
167 output->zoom.current.y = y;
168
169 if (weston_spring_done(&output->zoom.spring_xy)) {
170 output->zoom.spring_xy.current = output->zoom.spring_xy.target;
171 output->zoom.current.x =
Kristian Høgsbergef6f1362012-08-10 10:07:55 -0400172 output->zoom.type == ZOOM_FOCUS_POINTER ?
Kristian Høgsberge3148752013-05-06 23:19:49 -0400173 seat->pointer->x : output->zoom.text_cursor.x;
Scott Moreau429490d2012-06-17 18:10:59 -0600174 output->zoom.current.y =
Kristian Høgsbergef6f1362012-08-10 10:07:55 -0400175 output->zoom.type == ZOOM_FOCUS_POINTER ?
Kristian Høgsberge3148752013-05-06 23:19:49 -0400176 seat->pointer->y : output->zoom.text_cursor.y;
Scott Moreau429490d2012-06-17 18:10:59 -0600177 wl_list_remove(&animation->link);
178 wl_list_init(&animation->link);
179 }
180
181 output->dirty = 1;
182 weston_output_damage(output);
183}
184
185static void
186zoom_area_center_from_pointer(struct weston_output *output,
187 wl_fixed_t *x, wl_fixed_t *y)
188{
189 float level = output->zoom.spring_z.current;
190 wl_fixed_t offset_x = wl_fixed_from_int(output->x);
191 wl_fixed_t offset_y = wl_fixed_from_int(output->y);
Scott Moreau1bad5db2012-08-18 01:04:05 -0600192 wl_fixed_t w = wl_fixed_from_int(output->width);
193 wl_fixed_t h = wl_fixed_from_int(output->height);
Scott Moreau429490d2012-06-17 18:10:59 -0600194
195 *x -= ((((*x - offset_x) / (float) w) - 0.5) * (w * (1.0 - level)));
196 *y -= ((((*y - offset_y) / (float) h) - 0.5) * (h * (1.0 - level)));
197}
198
199static void
Scott Moreau1bad5db2012-08-18 01:04:05 -0600200weston_zoom_apply_output_transform(struct weston_output *output,
201 float *x, float *y)
202{
203 float tx, ty;
204
205 switch(output->transform) {
206 case WL_OUTPUT_TRANSFORM_NORMAL:
207 default:
208 return;
209 case WL_OUTPUT_TRANSFORM_90:
210 tx = -*y;
211 ty = *x;
212 break;
213 case WL_OUTPUT_TRANSFORM_180:
214 tx = -*x;
215 ty = -*y;
216 break;
217 case WL_OUTPUT_TRANSFORM_270:
218 tx = *y;
219 ty = -*x;
220 break;
221 case WL_OUTPUT_TRANSFORM_FLIPPED:
222 tx = -*x;
223 ty = *y;
224 break;
225 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
226 tx = -*y;
227 ty = -*x;
228 break;
229 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
230 tx = *x;
231 ty = -*y;
232 break;
233 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
234 tx = *y;
235 ty = *x;
236 break;
237 }
238
239 *x = tx;
240 *y = ty;
241}
242
243static void
Scott Moreau429490d2012-06-17 18:10:59 -0600244weston_output_update_zoom_transform(struct weston_output *output)
245{
246 uint32_t type = output->zoom.type;
247 float global_x, global_y;
248 wl_fixed_t x = output->zoom.current.x;
249 wl_fixed_t y = output->zoom.current.y;
250 float trans_min, trans_max;
251 float ratio, level;
252
253 level = output->zoom.spring_z.current;
254 ratio = 1 / level;
255
Ander Conselvan de Oliveira434e8f32012-11-21 15:11:36 +0200256 if (!output->zoom.active || level > output->zoom.max_level ||
257 level == 0.0f)
Scott Moreau429490d2012-06-17 18:10:59 -0600258 return;
259
260 if (type == ZOOM_FOCUS_POINTER &&
261 wl_list_empty(&output->zoom.animation_xy.link))
262 zoom_area_center_from_pointer(output, &x, &y);
263
264 global_x = wl_fixed_to_double(x);
265 global_y = wl_fixed_to_double(y);
266
267 output->zoom.trans_x =
Scott Moreau1bad5db2012-08-18 01:04:05 -0600268 ((((global_x - output->x) / output->width) *
Scott Moreau429490d2012-06-17 18:10:59 -0600269 (level * 2)) - level) * ratio;
270 output->zoom.trans_y =
Scott Moreau1bad5db2012-08-18 01:04:05 -0600271 ((((global_y - output->y) / output->height) *
Scott Moreau429490d2012-06-17 18:10:59 -0600272 (level * 2)) - level) * ratio;
273
Scott Moreau1bad5db2012-08-18 01:04:05 -0600274 weston_zoom_apply_output_transform(output, &output->zoom.trans_x,
275 &output->zoom.trans_y);
276
Scott Moreau429490d2012-06-17 18:10:59 -0600277 trans_max = level * 2 - level;
278 trans_min = -trans_max;
279
280 /* Clip zoom area to output */
281 if (output->zoom.trans_x > trans_max)
282 output->zoom.trans_x = trans_max;
283 else if (output->zoom.trans_x < trans_min)
284 output->zoom.trans_x = trans_min;
285 if (output->zoom.trans_y > trans_max)
286 output->zoom.trans_y = trans_max;
287 else if (output->zoom.trans_y < trans_min)
288 output->zoom.trans_y = trans_min;
289}
290
291static void
292weston_zoom_transition(struct weston_output *output, uint32_t type,
293 wl_fixed_t x, wl_fixed_t y)
294{
295 if (output->zoom.type != type) {
296 /* Set from/to points and start animation */
297 output->zoom.spring_xy.current = 0.0;
298 output->zoom.spring_xy.previous = 0.0;
299 output->zoom.spring_xy.target = 1.0;
300
301 if (wl_list_empty(&output->zoom.animation_xy.link)) {
302 output->zoom.animation_xy.frame_counter = 0;
303 wl_list_insert(output->animation_list.prev,
304 &output->zoom.animation_xy.link);
305
306 output->zoom.from.x = (type == ZOOM_FOCUS_TEXT) ?
307 x : output->zoom.text_cursor.x;
308 output->zoom.from.y = (type == ZOOM_FOCUS_TEXT) ?
309 y : output->zoom.text_cursor.y;
310 } else {
311 output->zoom.from.x = output->zoom.current.x;
312 output->zoom.from.y = output->zoom.current.y;
313 }
314
315 output->zoom.to.x = (type == ZOOM_FOCUS_POINTER) ?
316 x : output->zoom.text_cursor.x;
317 output->zoom.to.y = (type == ZOOM_FOCUS_POINTER) ?
318 y : output->zoom.text_cursor.y;
319 output->zoom.current.x = output->zoom.from.x;
320 output->zoom.current.y = output->zoom.from.y;
321
322 output->zoom.type = type;
323 }
324
325 if (output->zoom.level != output->zoom.spring_z.current) {
326 output->zoom.spring_z.target = output->zoom.level;
327 if (wl_list_empty(&output->zoom.animation_z.link)) {
328 output->zoom.animation_z.frame_counter = 0;
329 wl_list_insert(output->animation_list.prev,
330 &output->zoom.animation_z.link);
331 }
332 }
333
334 output->dirty = 1;
335 weston_output_damage(output);
336}
337
338WL_EXPORT void
339weston_output_update_zoom(struct weston_output *output, uint32_t type)
340{
Kristian Høgsbergef6f1362012-08-10 10:07:55 -0400341 struct weston_seat *seat = weston_zoom_pick_seat(output->compositor);
Kristian Høgsberge3148752013-05-06 23:19:49 -0400342 wl_fixed_t x = seat->pointer->x;
343 wl_fixed_t y = seat->pointer->y;
Scott Moreau429490d2012-06-17 18:10:59 -0600344
345 zoom_area_center_from_pointer(output, &x, &y);
346
347 if (type == ZOOM_FOCUS_POINTER) {
348 if (wl_list_empty(&output->zoom.animation_xy.link)) {
Kristian Høgsberge3148752013-05-06 23:19:49 -0400349 output->zoom.current.x = seat->pointer->x;
350 output->zoom.current.y = seat->pointer->y;
Scott Moreau429490d2012-06-17 18:10:59 -0600351 } else {
352 output->zoom.to.x = x;
353 output->zoom.to.y = y;
354 }
355 }
356
357 if (type == ZOOM_FOCUS_TEXT) {
358 if (wl_list_empty(&output->zoom.animation_xy.link)) {
359 output->zoom.current.x = output->zoom.text_cursor.x;
360 output->zoom.current.y = output->zoom.text_cursor.y;
361 } else {
362 output->zoom.to.x = output->zoom.text_cursor.x;
363 output->zoom.to.y = output->zoom.text_cursor.y;
364 }
365 }
366
367 weston_zoom_transition(output, type, x, y);
368 weston_output_update_zoom_transform(output);
369}
370
371WL_EXPORT void
372weston_output_init_zoom(struct weston_output *output)
373{
374 output->zoom.active = 0;
375 output->zoom.increment = 0.07;
376 output->zoom.max_level = 0.95;
377 output->zoom.level = 0.0;
378 output->zoom.trans_x = 0.0;
379 output->zoom.trans_y = 0.0;
380 output->zoom.type = ZOOM_FOCUS_POINTER;
381 weston_spring_init(&output->zoom.spring_z, 250.0, 0.0, 0.0);
382 output->zoom.spring_z.friction = 1000;
383 output->zoom.animation_z.frame = weston_zoom_frame_z;
384 wl_list_init(&output->zoom.animation_z.link);
385 weston_spring_init(&output->zoom.spring_xy, 250.0, 0.0, 0.0);
386 output->zoom.spring_xy.friction = 1000;
387 output->zoom.animation_xy.frame = weston_zoom_frame_xy;
388 wl_list_init(&output->zoom.animation_xy.link);
389}