blob: 220b2b6ed157d997f1dae6aa9a6edc67c74f0049 [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 {
Kristian Høgsberg583a2362012-06-25 17:13:58 -040031 struct weston_compositor *ec;
32 struct wl_global *global;
33 struct wl_listener destroy_listener;
34};
35
36static void
37text_cursor_position_notify(struct wl_client *client,
38 struct wl_resource *resource,
39 struct wl_resource *surface_resource,
40 wl_fixed_t x, wl_fixed_t y)
41{
Jason Ekstrand26ed73c2013-06-06 22:34:41 -050042 struct weston_surface *surface =
43 wl_resource_get_user_data(surface_resource);
44
45 weston_text_cursor_position_notify(surface, x, y);
Kristian Høgsberg583a2362012-06-25 17:13:58 -040046}
47
48struct text_cursor_position_interface text_cursor_position_implementation = {
49 text_cursor_position_notify
50};
51
52static void
53bind_text_cursor_position(struct wl_client *client,
54 void *data, uint32_t version, uint32_t id)
55{
Jason Ekstranda85118c2013-06-27 20:17:02 -050056 struct wl_resource *resource;
57
58 resource = wl_resource_create(client,
59 &text_cursor_position_interface, 1, id);
60 if (resource)
61 wl_resource_set_implementation(resource,
62 &text_cursor_position_implementation,
63 data, NULL);
Kristian Høgsberg583a2362012-06-25 17:13:58 -040064}
65
66static void
67text_cursor_position_notifier_destroy(struct wl_listener *listener, void *data)
68{
69 struct text_cursor_position *text_cursor_position =
70 container_of(listener, struct text_cursor_position, destroy_listener);
71
Kristian Høgsberg919cddb2013-07-08 19:03:57 -040072 wl_global_destroy(text_cursor_position->global);
Kristian Høgsberg583a2362012-06-25 17:13:58 -040073 free(text_cursor_position);
74}
75
76void
77text_cursor_position_notifier_create(struct weston_compositor *ec)
78{
79 struct text_cursor_position *text_cursor_position;
80
81 text_cursor_position = malloc(sizeof *text_cursor_position);
82 if (text_cursor_position == NULL)
83 return;
84
Kristian Høgsberg583a2362012-06-25 17:13:58 -040085 text_cursor_position->ec = ec;
86
Kristian Høgsberg919cddb2013-07-08 19:03:57 -040087 text_cursor_position->global =
88 wl_global_create(ec->wl_display,
89 &text_cursor_position_interface, 1,
90 text_cursor_position,
91 bind_text_cursor_position);
Kristian Høgsberg583a2362012-06-25 17:13:58 -040092
Kristian Høgsberg919cddb2013-07-08 19:03:57 -040093 text_cursor_position->destroy_listener.notify =
94 text_cursor_position_notifier_destroy;
Kristian Høgsberg583a2362012-06-25 17:13:58 -040095 wl_signal_add(&ec->destroy_signal, &text_cursor_position->destroy_listener);
96}
Scott Moreau429490d2012-06-17 18:10:59 -060097
98WL_EXPORT void
99weston_text_cursor_position_notify(struct weston_surface *surface,
100 wl_fixed_t cur_pos_x,
101 wl_fixed_t cur_pos_y)
102{
103 struct weston_output *output;
104 wl_fixed_t global_x, global_y;
105
106 weston_surface_to_global_fixed(surface, cur_pos_x, cur_pos_y,
107 &global_x, &global_y);
108
109 wl_list_for_each(output, &surface->compositor->output_list, link)
110 if (output->zoom.active &&
111 pixman_region32_contains_point(&output->region,
112 wl_fixed_to_int(global_x),
113 wl_fixed_to_int(global_y),
114 NULL)) {
115 output->zoom.text_cursor.x = global_x;
116 output->zoom.text_cursor.y = global_y;
117 weston_output_update_zoom(output, ZOOM_FOCUS_TEXT);
118 }
119}
120
121static void
122weston_zoom_frame_z(struct weston_animation *animation,
123 struct weston_output *output, uint32_t msecs)
124{
125 if (animation->frame_counter <= 1)
126 output->zoom.spring_z.timestamp = msecs;
127
128 weston_spring_update(&output->zoom.spring_z, msecs);
129
130 if (output->zoom.spring_z.current > output->zoom.max_level)
131 output->zoom.spring_z.current = output->zoom.max_level;
132 else if (output->zoom.spring_z.current < 0.0)
133 output->zoom.spring_z.current = 0.0;
134
135 if (weston_spring_done(&output->zoom.spring_z)) {
Ville Syrjäläaa628d02012-11-16 11:48:47 +0200136 if (output->zoom.active && output->zoom.level <= 0.0) {
Scott Moreau429490d2012-06-17 18:10:59 -0600137 output->zoom.active = 0;
Kristian Høgsberg79af73e2012-08-03 15:45:23 -0400138 output->disable_planes--;
139 }
Scott Moreau429490d2012-06-17 18:10:59 -0600140 output->zoom.spring_z.current = output->zoom.level;
141 wl_list_remove(&animation->link);
142 wl_list_init(&animation->link);
143 }
144
145 output->dirty = 1;
146 weston_output_damage(output);
147}
148
Kristian Høgsbergef6f1362012-08-10 10:07:55 -0400149static struct weston_seat *
150weston_zoom_pick_seat(struct weston_compositor *compositor)
151{
152 return container_of(compositor->seat_list.next,
153 struct weston_seat, link);
154}
155
156
Scott Moreau429490d2012-06-17 18:10:59 -0600157static void
158weston_zoom_frame_xy(struct weston_animation *animation,
159 struct weston_output *output, uint32_t msecs)
160{
Kristian Høgsbergef6f1362012-08-10 10:07:55 -0400161 struct weston_seat *seat = weston_zoom_pick_seat(output->compositor);
Scott Moreau429490d2012-06-17 18:10:59 -0600162 wl_fixed_t x, y;
Kristian Høgsbergef6f1362012-08-10 10:07:55 -0400163
Scott Moreau429490d2012-06-17 18:10:59 -0600164 if (animation->frame_counter <= 1)
165 output->zoom.spring_xy.timestamp = msecs;
166
167 weston_spring_update(&output->zoom.spring_xy, msecs);
168
169 x = output->zoom.from.x - ((output->zoom.from.x - output->zoom.to.x) *
170 output->zoom.spring_xy.current);
171 y = output->zoom.from.y - ((output->zoom.from.y - output->zoom.to.y) *
172 output->zoom.spring_xy.current);
173
174 output->zoom.current.x = x;
175 output->zoom.current.y = y;
176
177 if (weston_spring_done(&output->zoom.spring_xy)) {
178 output->zoom.spring_xy.current = output->zoom.spring_xy.target;
179 output->zoom.current.x =
Kristian Høgsbergef6f1362012-08-10 10:07:55 -0400180 output->zoom.type == ZOOM_FOCUS_POINTER ?
Kristian Høgsberge3148752013-05-06 23:19:49 -0400181 seat->pointer->x : output->zoom.text_cursor.x;
Scott Moreau429490d2012-06-17 18:10:59 -0600182 output->zoom.current.y =
Kristian Høgsbergef6f1362012-08-10 10:07:55 -0400183 output->zoom.type == ZOOM_FOCUS_POINTER ?
Kristian Høgsberge3148752013-05-06 23:19:49 -0400184 seat->pointer->y : output->zoom.text_cursor.y;
Scott Moreau429490d2012-06-17 18:10:59 -0600185 wl_list_remove(&animation->link);
186 wl_list_init(&animation->link);
187 }
188
189 output->dirty = 1;
190 weston_output_damage(output);
191}
192
193static void
194zoom_area_center_from_pointer(struct weston_output *output,
195 wl_fixed_t *x, wl_fixed_t *y)
196{
197 float level = output->zoom.spring_z.current;
198 wl_fixed_t offset_x = wl_fixed_from_int(output->x);
199 wl_fixed_t offset_y = wl_fixed_from_int(output->y);
Scott Moreau1bad5db2012-08-18 01:04:05 -0600200 wl_fixed_t w = wl_fixed_from_int(output->width);
201 wl_fixed_t h = wl_fixed_from_int(output->height);
Scott Moreau429490d2012-06-17 18:10:59 -0600202
203 *x -= ((((*x - offset_x) / (float) w) - 0.5) * (w * (1.0 - level)));
204 *y -= ((((*y - offset_y) / (float) h) - 0.5) * (h * (1.0 - level)));
205}
206
207static void
Scott Moreau1bad5db2012-08-18 01:04:05 -0600208weston_zoom_apply_output_transform(struct weston_output *output,
209 float *x, float *y)
210{
211 float tx, ty;
212
213 switch(output->transform) {
214 case WL_OUTPUT_TRANSFORM_NORMAL:
215 default:
216 return;
217 case WL_OUTPUT_TRANSFORM_90:
218 tx = -*y;
219 ty = *x;
220 break;
221 case WL_OUTPUT_TRANSFORM_180:
222 tx = -*x;
223 ty = -*y;
224 break;
225 case WL_OUTPUT_TRANSFORM_270:
226 tx = *y;
227 ty = -*x;
228 break;
229 case WL_OUTPUT_TRANSFORM_FLIPPED:
230 tx = -*x;
231 ty = *y;
232 break;
233 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
234 tx = -*y;
235 ty = -*x;
236 break;
237 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
238 tx = *x;
239 ty = -*y;
240 break;
241 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
242 tx = *y;
243 ty = *x;
244 break;
245 }
246
247 *x = tx;
248 *y = ty;
249}
250
251static void
Scott Moreau429490d2012-06-17 18:10:59 -0600252weston_output_update_zoom_transform(struct weston_output *output)
253{
254 uint32_t type = output->zoom.type;
255 float global_x, global_y;
256 wl_fixed_t x = output->zoom.current.x;
257 wl_fixed_t y = output->zoom.current.y;
258 float trans_min, trans_max;
259 float ratio, level;
260
261 level = output->zoom.spring_z.current;
262 ratio = 1 / level;
263
Ander Conselvan de Oliveira434e8f32012-11-21 15:11:36 +0200264 if (!output->zoom.active || level > output->zoom.max_level ||
265 level == 0.0f)
Scott Moreau429490d2012-06-17 18:10:59 -0600266 return;
267
268 if (type == ZOOM_FOCUS_POINTER &&
269 wl_list_empty(&output->zoom.animation_xy.link))
270 zoom_area_center_from_pointer(output, &x, &y);
271
272 global_x = wl_fixed_to_double(x);
273 global_y = wl_fixed_to_double(y);
274
275 output->zoom.trans_x =
Scott Moreau1bad5db2012-08-18 01:04:05 -0600276 ((((global_x - output->x) / output->width) *
Scott Moreau429490d2012-06-17 18:10:59 -0600277 (level * 2)) - level) * ratio;
278 output->zoom.trans_y =
Scott Moreau1bad5db2012-08-18 01:04:05 -0600279 ((((global_y - output->y) / output->height) *
Scott Moreau429490d2012-06-17 18:10:59 -0600280 (level * 2)) - level) * ratio;
281
Scott Moreau1bad5db2012-08-18 01:04:05 -0600282 weston_zoom_apply_output_transform(output, &output->zoom.trans_x,
283 &output->zoom.trans_y);
284
Scott Moreau429490d2012-06-17 18:10:59 -0600285 trans_max = level * 2 - level;
286 trans_min = -trans_max;
287
288 /* Clip zoom area to output */
289 if (output->zoom.trans_x > trans_max)
290 output->zoom.trans_x = trans_max;
291 else if (output->zoom.trans_x < trans_min)
292 output->zoom.trans_x = trans_min;
293 if (output->zoom.trans_y > trans_max)
294 output->zoom.trans_y = trans_max;
295 else if (output->zoom.trans_y < trans_min)
296 output->zoom.trans_y = trans_min;
297}
298
299static void
300weston_zoom_transition(struct weston_output *output, uint32_t type,
301 wl_fixed_t x, wl_fixed_t y)
302{
303 if (output->zoom.type != type) {
304 /* Set from/to points and start animation */
305 output->zoom.spring_xy.current = 0.0;
306 output->zoom.spring_xy.previous = 0.0;
307 output->zoom.spring_xy.target = 1.0;
308
309 if (wl_list_empty(&output->zoom.animation_xy.link)) {
310 output->zoom.animation_xy.frame_counter = 0;
311 wl_list_insert(output->animation_list.prev,
312 &output->zoom.animation_xy.link);
313
314 output->zoom.from.x = (type == ZOOM_FOCUS_TEXT) ?
315 x : output->zoom.text_cursor.x;
316 output->zoom.from.y = (type == ZOOM_FOCUS_TEXT) ?
317 y : output->zoom.text_cursor.y;
318 } else {
319 output->zoom.from.x = output->zoom.current.x;
320 output->zoom.from.y = output->zoom.current.y;
321 }
322
323 output->zoom.to.x = (type == ZOOM_FOCUS_POINTER) ?
324 x : output->zoom.text_cursor.x;
325 output->zoom.to.y = (type == ZOOM_FOCUS_POINTER) ?
326 y : output->zoom.text_cursor.y;
327 output->zoom.current.x = output->zoom.from.x;
328 output->zoom.current.y = output->zoom.from.y;
329
330 output->zoom.type = type;
331 }
332
333 if (output->zoom.level != output->zoom.spring_z.current) {
334 output->zoom.spring_z.target = output->zoom.level;
335 if (wl_list_empty(&output->zoom.animation_z.link)) {
336 output->zoom.animation_z.frame_counter = 0;
337 wl_list_insert(output->animation_list.prev,
338 &output->zoom.animation_z.link);
339 }
340 }
341
342 output->dirty = 1;
343 weston_output_damage(output);
344}
345
346WL_EXPORT void
347weston_output_update_zoom(struct weston_output *output, uint32_t type)
348{
Kristian Høgsbergef6f1362012-08-10 10:07:55 -0400349 struct weston_seat *seat = weston_zoom_pick_seat(output->compositor);
Kristian Høgsberge3148752013-05-06 23:19:49 -0400350 wl_fixed_t x = seat->pointer->x;
351 wl_fixed_t y = seat->pointer->y;
Scott Moreau429490d2012-06-17 18:10:59 -0600352
353 zoom_area_center_from_pointer(output, &x, &y);
354
355 if (type == ZOOM_FOCUS_POINTER) {
356 if (wl_list_empty(&output->zoom.animation_xy.link)) {
Kristian Høgsberge3148752013-05-06 23:19:49 -0400357 output->zoom.current.x = seat->pointer->x;
358 output->zoom.current.y = seat->pointer->y;
Scott Moreau429490d2012-06-17 18:10:59 -0600359 } else {
360 output->zoom.to.x = x;
361 output->zoom.to.y = y;
362 }
363 }
364
365 if (type == ZOOM_FOCUS_TEXT) {
366 if (wl_list_empty(&output->zoom.animation_xy.link)) {
367 output->zoom.current.x = output->zoom.text_cursor.x;
368 output->zoom.current.y = output->zoom.text_cursor.y;
369 } else {
370 output->zoom.to.x = output->zoom.text_cursor.x;
371 output->zoom.to.y = output->zoom.text_cursor.y;
372 }
373 }
374
375 weston_zoom_transition(output, type, x, y);
376 weston_output_update_zoom_transform(output);
377}
378
379WL_EXPORT void
380weston_output_init_zoom(struct weston_output *output)
381{
382 output->zoom.active = 0;
383 output->zoom.increment = 0.07;
384 output->zoom.max_level = 0.95;
385 output->zoom.level = 0.0;
386 output->zoom.trans_x = 0.0;
387 output->zoom.trans_y = 0.0;
388 output->zoom.type = ZOOM_FOCUS_POINTER;
389 weston_spring_init(&output->zoom.spring_z, 250.0, 0.0, 0.0);
390 output->zoom.spring_z.friction = 1000;
391 output->zoom.animation_z.frame = weston_zoom_frame_z;
392 wl_list_init(&output->zoom.animation_z.link);
393 weston_spring_init(&output->zoom.spring_xy, 250.0, 0.0, 0.0);
394 output->zoom.spring_xy.friction = 1000;
395 output->zoom.animation_xy.frame = weston_zoom_frame_xy;
396 wl_list_init(&output->zoom.animation_xy.link);
397}