blob: d0ccc6215d04c7c310ad234b51e0024c85ce8d98 [file] [log] [blame]
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001/*
2 * Copyright © 2013 Intel Corporation
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
23#include <stdlib.h>
24#include <stdint.h>
25#include <string.h>
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040026#include <sys/mman.h>
27#include <assert.h>
28#include <unistd.h>
Kristian Høgsberg2158a882013-04-18 15:07:39 -040029
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040030#include "../shared/os-compatibility.h"
Kristian Høgsberg2158a882013-04-18 15:07:39 -040031#include "compositor.h"
32
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040033static void
34empty_region(pixman_region32_t *region)
35{
36 pixman_region32_fini(region);
37 pixman_region32_init(region);
38}
39
40static void unbind_resource(struct wl_resource *resource)
41{
42 wl_list_remove(&resource->link);
43 free(resource);
44}
45
46void
Kristian Høgsberga71e8b22013-05-06 21:51:21 -040047weston_seat_repick(struct weston_seat *seat)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040048{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -040049 const struct weston_pointer_grab_interface *interface;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040050 struct weston_surface *surface, *focus;
Kristian Høgsberge3148752013-05-06 23:19:49 -040051 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040052
53 if (!pointer)
54 return;
55
56 surface = weston_compositor_pick_surface(seat->compositor,
57 pointer->x,
58 pointer->y,
59 &pointer->current_x,
60 &pointer->current_y);
61
62 if (&surface->surface != pointer->current) {
63 interface = pointer->grab->interface;
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -040064 weston_pointer_set_current(pointer, &surface->surface);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -040065 interface->focus(pointer->grab, &surface->surface,
66 pointer->current_x,
67 pointer->current_y);
68 }
69
70 focus = (struct weston_surface *) pointer->grab->focus;
71 if (focus)
72 weston_surface_from_global_fixed(focus,
73 pointer->x,
74 pointer->y,
75 &pointer->grab->x,
76 &pointer->grab->y);
77}
78
79static void
80weston_compositor_idle_inhibit(struct weston_compositor *compositor)
81{
82 weston_compositor_wake(compositor);
83 compositor->idle_inhibit++;
84}
85
86static void
87weston_compositor_idle_release(struct weston_compositor *compositor)
88{
89 compositor->idle_inhibit--;
90 weston_compositor_wake(compositor);
91}
92
Kristian Høgsberg2158a882013-04-18 15:07:39 -040093static void
94lose_pointer_focus(struct wl_listener *listener, void *data)
95{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -040096 struct weston_pointer *pointer =
97 container_of(listener, struct weston_pointer, focus_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -040098
99 pointer->focus_resource = NULL;
100}
101
102static void
103lose_keyboard_focus(struct wl_listener *listener, void *data)
104{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400105 struct weston_keyboard *keyboard =
106 container_of(listener, struct weston_keyboard, focus_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400107
108 keyboard->focus_resource = NULL;
109}
110
111static void
112lose_touch_focus(struct wl_listener *listener, void *data)
113{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400114 struct weston_touch *touch =
115 container_of(listener, struct weston_touch, focus_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400116
117 touch->focus_resource = NULL;
118}
119
120static void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400121default_grab_focus(struct weston_pointer_grab *grab,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400122 struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y)
123{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400124 struct weston_pointer *pointer = grab->pointer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400125
126 if (pointer->button_count > 0)
127 return;
128
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400129 weston_pointer_set_focus(pointer, surface, x, y);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400130}
131
132static void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400133default_grab_motion(struct weston_pointer_grab *grab,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400134 uint32_t time, wl_fixed_t x, wl_fixed_t y)
135{
136 struct wl_resource *resource;
137
138 resource = grab->pointer->focus_resource;
139 if (resource)
140 wl_pointer_send_motion(resource, time, x, y);
141}
142
143static void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400144default_grab_button(struct weston_pointer_grab *grab,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400145 uint32_t time, uint32_t button, uint32_t state_w)
146{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400147 struct weston_pointer *pointer = grab->pointer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400148 struct wl_resource *resource;
149 uint32_t serial;
150 enum wl_pointer_button_state state = state_w;
151 struct wl_display *display;
152
153 resource = pointer->focus_resource;
154 if (resource) {
155 display = wl_client_get_display(resource->client);
156 serial = wl_display_next_serial(display);
157 wl_pointer_send_button(resource, serial, time, button, state_w);
158 }
159
160 if (pointer->button_count == 0 &&
161 state == WL_POINTER_BUTTON_STATE_RELEASED)
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400162 weston_pointer_set_focus(pointer, pointer->current,
163 pointer->current_x,
164 pointer->current_y);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400165}
166
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400167static const struct weston_pointer_grab_interface
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400168 default_pointer_grab_interface = {
169 default_grab_focus,
170 default_grab_motion,
171 default_grab_button
172};
173
Kristian Høgsberge329f362013-05-06 22:19:57 -0400174static void
175default_grab_touch_down(struct weston_touch_grab *grab, uint32_t time,
176 int touch_id, wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400177{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400178 struct weston_touch *touch = grab->touch;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400179 struct wl_display *display;
180 uint32_t serial;
181
182 if (touch->focus_resource && touch->focus) {
183 display = wl_client_get_display(touch->focus_resource->client);
184 serial = wl_display_next_serial(display);
185 wl_touch_send_down(touch->focus_resource, serial, time,
Kristian Høgsberge329f362013-05-06 22:19:57 -0400186 &touch->focus->resource,
187 touch_id, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400188 }
189}
190
Kristian Høgsberge329f362013-05-06 22:19:57 -0400191static void
192default_grab_touch_up(struct weston_touch_grab *grab,
193 uint32_t time, int touch_id)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400194{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400195 struct weston_touch *touch = grab->touch;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400196 struct wl_display *display;
197 uint32_t serial;
198
199 if (touch->focus_resource) {
200 display = wl_client_get_display(touch->focus_resource->client);
201 serial = wl_display_next_serial(display);
202 wl_touch_send_up(touch->focus_resource, serial, time, touch_id);
203 }
204}
205
Kristian Høgsberge329f362013-05-06 22:19:57 -0400206static void
207default_grab_touch_motion(struct weston_touch_grab *grab, uint32_t time,
208 int touch_id, wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400209{
Kristian Høgsberge329f362013-05-06 22:19:57 -0400210 struct weston_touch *touch = grab->touch;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400211
212 if (touch->focus_resource) {
213 wl_touch_send_motion(touch->focus_resource, time,
Kristian Høgsberge329f362013-05-06 22:19:57 -0400214 touch_id, sx, sy);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400215 }
216}
217
Kristian Høgsberge329f362013-05-06 22:19:57 -0400218static const struct weston_touch_grab_interface default_touch_grab_interface = {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400219 default_grab_touch_down,
220 default_grab_touch_up,
221 default_grab_touch_motion
222};
223
224static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400225default_grab_key(struct weston_keyboard_grab *grab,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400226 uint32_t time, uint32_t key, uint32_t state)
227{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400228 struct weston_keyboard *keyboard = grab->keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400229 struct wl_resource *resource;
230 struct wl_display *display;
231 uint32_t serial;
232
233 resource = keyboard->focus_resource;
234 if (resource) {
235 display = wl_client_get_display(resource->client);
236 serial = wl_display_next_serial(display);
237 wl_keyboard_send_key(resource, serial, time, key, state);
238 }
239}
240
241static struct wl_resource *
242find_resource_for_surface(struct wl_list *list, struct wl_surface *surface)
243{
244 struct wl_resource *r;
245
246 if (!surface)
247 return NULL;
248
249 wl_list_for_each(r, list, link) {
250 if (r->client == surface->resource.client)
251 return r;
252 }
253
254 return NULL;
255}
256
257static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400258default_grab_modifiers(struct weston_keyboard_grab *grab, uint32_t serial,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400259 uint32_t mods_depressed, uint32_t mods_latched,
260 uint32_t mods_locked, uint32_t group)
261{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400262 struct weston_keyboard *keyboard = grab->keyboard;
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400263 struct weston_pointer *pointer = keyboard->seat->pointer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400264 struct wl_resource *resource, *pr;
265
266 resource = keyboard->focus_resource;
267 if (!resource)
268 return;
269
270 wl_keyboard_send_modifiers(resource, serial, mods_depressed,
271 mods_latched, mods_locked, group);
272
273 if (pointer && pointer->focus && pointer->focus != keyboard->focus) {
274 pr = find_resource_for_surface(&keyboard->resource_list,
275 pointer->focus);
276 if (pr) {
277 wl_keyboard_send_modifiers(pr,
278 serial,
279 keyboard->modifiers.mods_depressed,
280 keyboard->modifiers.mods_latched,
281 keyboard->modifiers.mods_locked,
282 keyboard->modifiers.group);
283 }
284 }
285}
286
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400287static const struct weston_keyboard_grab_interface
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400288 default_keyboard_grab_interface = {
289 default_grab_key,
290 default_grab_modifiers,
291};
292
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400293WL_EXPORT struct weston_pointer *
294weston_pointer_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400295{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400296 struct weston_pointer *pointer;
297
298 pointer = malloc(sizeof *pointer);
299 if (pointer == NULL)
300 return NULL;
301
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400302 memset(pointer, 0, sizeof *pointer);
303 wl_list_init(&pointer->resource_list);
304 pointer->focus_listener.notify = lose_pointer_focus;
305 pointer->default_grab.interface = &default_pointer_grab_interface;
306 pointer->default_grab.pointer = pointer;
307 pointer->grab = &pointer->default_grab;
308 wl_signal_init(&pointer->focus_signal);
309
310 /* FIXME: Pick better co-ords. */
311 pointer->x = wl_fixed_from_int(100);
312 pointer->y = wl_fixed_from_int(100);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400313
314 return pointer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400315}
316
317WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400318weston_pointer_destroy(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400319{
320 /* XXX: What about pointer->resource_list? */
321 if (pointer->focus_resource)
322 wl_list_remove(&pointer->focus_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400323 free(pointer);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400324}
325
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400326WL_EXPORT struct weston_keyboard *
327weston_keyboard_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400328{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400329 struct weston_keyboard *keyboard;
330
331 keyboard = malloc(sizeof *keyboard);
332 if (keyboard == NULL)
333 return NULL;
334
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400335 memset(keyboard, 0, sizeof *keyboard);
336 wl_list_init(&keyboard->resource_list);
337 wl_array_init(&keyboard->keys);
338 keyboard->focus_listener.notify = lose_keyboard_focus;
339 keyboard->default_grab.interface = &default_keyboard_grab_interface;
340 keyboard->default_grab.keyboard = keyboard;
341 keyboard->grab = &keyboard->default_grab;
342 wl_signal_init(&keyboard->focus_signal);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400343
344 return keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400345}
346
347WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400348weston_keyboard_destroy(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400349{
350 /* XXX: What about keyboard->resource_list? */
351 if (keyboard->focus_resource)
352 wl_list_remove(&keyboard->focus_listener.link);
353 wl_array_release(&keyboard->keys);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400354 free(keyboard);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400355}
356
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400357WL_EXPORT struct weston_touch *
358weston_touch_create(void)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400359{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400360 struct weston_touch *touch;
361
362 touch = malloc(sizeof *touch);
363 if (touch == NULL)
364 return NULL;
365
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400366 memset(touch, 0, sizeof *touch);
367 wl_list_init(&touch->resource_list);
368 touch->focus_listener.notify = lose_touch_focus;
369 touch->default_grab.interface = &default_touch_grab_interface;
370 touch->default_grab.touch = touch;
371 touch->grab = &touch->default_grab;
372 wl_signal_init(&touch->focus_signal);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400373
374 return touch;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400375}
376
377WL_EXPORT void
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400378weston_touch_destroy(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400379{
380 /* XXX: What about touch->resource_list? */
381 if (touch->focus_resource)
382 wl_list_remove(&touch->focus_listener.link);
Kristian Høgsberga4036bb2013-05-07 23:52:07 -0400383 free(touch);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400384}
385
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400386static void
Kristian Høgsberge3148752013-05-06 23:19:49 -0400387seat_send_updated_caps(struct weston_seat *seat)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400388{
389 struct wl_resource *r;
390 enum wl_seat_capability caps = 0;
391
392 if (seat->pointer)
393 caps |= WL_SEAT_CAPABILITY_POINTER;
394 if (seat->keyboard)
395 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
396 if (seat->touch)
397 caps |= WL_SEAT_CAPABILITY_TOUCH;
398
399 wl_list_for_each(r, &seat->base_resource_list, link)
400 wl_seat_send_capabilities(r, caps);
401}
402
403WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400404weston_pointer_set_focus(struct weston_pointer *pointer,
405 struct wl_surface *surface,
406 wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400407{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400408 struct weston_keyboard *kbd = pointer->seat->keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400409 struct wl_resource *resource, *kr;
410 struct wl_display *display;
411 uint32_t serial;
412
413 resource = pointer->focus_resource;
414 if (resource && pointer->focus != surface) {
415 display = wl_client_get_display(resource->client);
416 serial = wl_display_next_serial(display);
417 wl_pointer_send_leave(resource, serial,
418 &pointer->focus->resource);
419 wl_list_remove(&pointer->focus_listener.link);
420 }
421
422 resource = find_resource_for_surface(&pointer->resource_list,
423 surface);
424 if (resource &&
425 (pointer->focus != surface ||
426 pointer->focus_resource != resource)) {
427 display = wl_client_get_display(resource->client);
428 serial = wl_display_next_serial(display);
429 if (kbd) {
430 kr = find_resource_for_surface(&kbd->resource_list,
431 surface);
432 if (kr) {
433 wl_keyboard_send_modifiers(kr,
434 serial,
435 kbd->modifiers.mods_depressed,
436 kbd->modifiers.mods_latched,
437 kbd->modifiers.mods_locked,
438 kbd->modifiers.group);
439 }
440 }
441 wl_pointer_send_enter(resource, serial, &surface->resource,
442 sx, sy);
443 wl_signal_add(&resource->destroy_signal,
444 &pointer->focus_listener);
445 pointer->focus_serial = serial;
446 }
447
448 pointer->focus_resource = resource;
449 pointer->focus = surface;
450 pointer->default_grab.focus = surface;
451 wl_signal_emit(&pointer->focus_signal, pointer);
452}
453
454WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400455weston_keyboard_set_focus(struct weston_keyboard *keyboard,
456 struct wl_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400457{
458 struct wl_resource *resource;
459 struct wl_display *display;
460 uint32_t serial;
461
462 if (keyboard->focus_resource && keyboard->focus != surface) {
463 resource = keyboard->focus_resource;
464 display = wl_client_get_display(resource->client);
465 serial = wl_display_next_serial(display);
466 wl_keyboard_send_leave(resource, serial,
467 &keyboard->focus->resource);
468 wl_list_remove(&keyboard->focus_listener.link);
469 }
470
471 resource = find_resource_for_surface(&keyboard->resource_list,
472 surface);
473 if (resource &&
474 (keyboard->focus != surface ||
475 keyboard->focus_resource != resource)) {
476 display = wl_client_get_display(resource->client);
477 serial = wl_display_next_serial(display);
478 wl_keyboard_send_modifiers(resource, serial,
479 keyboard->modifiers.mods_depressed,
480 keyboard->modifiers.mods_latched,
481 keyboard->modifiers.mods_locked,
482 keyboard->modifiers.group);
483 wl_keyboard_send_enter(resource, serial, &surface->resource,
484 &keyboard->keys);
485 wl_signal_add(&resource->destroy_signal,
486 &keyboard->focus_listener);
487 keyboard->focus_serial = serial;
488 }
489
490 keyboard->focus_resource = resource;
491 keyboard->focus = surface;
492 wl_signal_emit(&keyboard->focus_signal, keyboard);
493}
494
495WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400496weston_keyboard_start_grab(struct weston_keyboard *keyboard,
497 struct weston_keyboard_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400498{
499 keyboard->grab = grab;
500 grab->keyboard = keyboard;
501
502 /* XXX focus? */
503}
504
505WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400506weston_keyboard_end_grab(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400507{
508 keyboard->grab = &keyboard->default_grab;
509}
510
511WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400512weston_pointer_start_grab(struct weston_pointer *pointer,
513 struct weston_pointer_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400514{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400515 const struct weston_pointer_grab_interface *interface;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400516
517 pointer->grab = grab;
518 interface = pointer->grab->interface;
519 grab->pointer = pointer;
520
521 if (pointer->current)
522 interface->focus(pointer->grab, pointer->current,
523 pointer->current_x, pointer->current_y);
524}
525
526WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400527weston_pointer_end_grab(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400528{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400529 const struct weston_pointer_grab_interface *interface;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400530
531 pointer->grab = &pointer->default_grab;
532 interface = pointer->grab->interface;
533 interface->focus(pointer->grab, pointer->current,
534 pointer->current_x, pointer->current_y);
535}
536
537static void
538current_surface_destroy(struct wl_listener *listener, void *data)
539{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400540 struct weston_pointer *pointer =
541 container_of(listener, struct weston_pointer, current_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400542
543 pointer->current = NULL;
544}
545
546WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400547weston_pointer_set_current(struct weston_pointer *pointer,
548 struct wl_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400549{
550 if (pointer->current)
551 wl_list_remove(&pointer->current_listener.link);
552
553 pointer->current = surface;
554
555 if (!surface)
556 return;
557
558 wl_signal_add(&surface->resource.destroy_signal,
559 &pointer->current_listener);
560 pointer->current_listener.notify = current_surface_destroy;
561}
562
563WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -0400564weston_touch_start_grab(struct weston_touch *touch, struct weston_touch_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400565{
566 touch->grab = grab;
567 grab->touch = touch;
568}
569
570WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -0400571weston_touch_end_grab(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400572{
573 touch->grab = &touch->default_grab;
574}
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400575
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400576static void
577clip_pointer_motion(struct weston_seat *seat, wl_fixed_t *fx, wl_fixed_t *fy)
578{
579 struct weston_compositor *ec = seat->compositor;
580 struct weston_output *output, *prev = NULL;
581 int x, y, old_x, old_y, valid = 0;
582
583 x = wl_fixed_to_int(*fx);
584 y = wl_fixed_to_int(*fy);
Kristian Høgsberge3148752013-05-06 23:19:49 -0400585 old_x = wl_fixed_to_int(seat->pointer->x);
586 old_y = wl_fixed_to_int(seat->pointer->y);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400587
588 wl_list_for_each(output, &ec->output_list, link) {
589 if (pixman_region32_contains_point(&output->region,
590 x, y, NULL))
591 valid = 1;
592 if (pixman_region32_contains_point(&output->region,
593 old_x, old_y, NULL))
594 prev = output;
595 }
596
597 if (!valid) {
598 if (x < prev->x)
599 *fx = wl_fixed_from_int(prev->x);
600 else if (x >= prev->x + prev->width)
601 *fx = wl_fixed_from_int(prev->x +
602 prev->width - 1);
603 if (y < prev->y)
604 *fy = wl_fixed_from_int(prev->y);
605 else if (y >= prev->y + prev->current->height)
606 *fy = wl_fixed_from_int(prev->y +
607 prev->height - 1);
608 }
609}
610
611/* Takes absolute values */
612static void
613move_pointer(struct weston_seat *seat, wl_fixed_t x, wl_fixed_t y)
614{
615 struct weston_compositor *ec = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400616 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400617 struct weston_output *output;
618 int32_t ix, iy;
619
620 clip_pointer_motion(seat, &x, &y);
621
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400622 pointer->x = x;
623 pointer->y = y;
624
625 ix = wl_fixed_to_int(x);
626 iy = wl_fixed_to_int(y);
627
628 wl_list_for_each(output, &ec->output_list, link)
629 if (output->zoom.active &&
630 pixman_region32_contains_point(&output->region,
631 ix, iy, NULL))
632 weston_output_update_zoom(output, ZOOM_FOCUS_POINTER);
633
Kristian Høgsberga71e8b22013-05-06 21:51:21 -0400634 weston_seat_repick(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400635
636 if (seat->sprite) {
637 weston_surface_set_position(seat->sprite,
638 ix - seat->hotspot_x,
639 iy - seat->hotspot_y);
640 weston_surface_schedule_repaint(seat->sprite);
641 }
642}
643
644WL_EXPORT void
645notify_motion(struct weston_seat *seat,
646 uint32_t time, wl_fixed_t dx, wl_fixed_t dy)
647{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400648 const struct weston_pointer_grab_interface *interface;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400649 struct weston_compositor *ec = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400650 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400651
652 weston_compositor_wake(ec);
653
654 move_pointer(seat, pointer->x + dx, pointer->y + dy);
655
656 interface = pointer->grab->interface;
657 interface->motion(pointer->grab, time,
658 pointer->grab->x, pointer->grab->y);
659}
660
661WL_EXPORT void
662notify_motion_absolute(struct weston_seat *seat,
663 uint32_t time, wl_fixed_t x, wl_fixed_t y)
664{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400665 const struct weston_pointer_grab_interface *interface;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400666 struct weston_compositor *ec = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400667 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400668
669 weston_compositor_wake(ec);
670
671 move_pointer(seat, x, y);
672
673 interface = pointer->grab->interface;
674 interface->motion(pointer->grab, time,
675 pointer->grab->x, pointer->grab->y);
676}
677
678WL_EXPORT void
679weston_surface_activate(struct weston_surface *surface,
680 struct weston_seat *seat)
681{
682 struct weston_compositor *compositor = seat->compositor;
683
Kristian Høgsberge3148752013-05-06 23:19:49 -0400684 if (seat->keyboard) {
685 weston_keyboard_set_focus(seat->keyboard, &surface->surface);
686 wl_data_device_set_keyboard_focus(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400687 }
688
689 wl_signal_emit(&compositor->activate_signal, surface);
690}
691
692WL_EXPORT void
693notify_button(struct weston_seat *seat, uint32_t time, int32_t button,
694 enum wl_pointer_button_state state)
695{
696 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400697 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400698 struct weston_surface *focus =
699 (struct weston_surface *) pointer->focus;
700 uint32_t serial = wl_display_next_serial(compositor->wl_display);
701
702 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
703 if (compositor->ping_handler && focus)
704 compositor->ping_handler(focus, serial);
705 weston_compositor_idle_inhibit(compositor);
706 if (pointer->button_count == 0) {
707 pointer->grab_button = button;
708 pointer->grab_time = time;
709 pointer->grab_x = pointer->x;
710 pointer->grab_y = pointer->y;
711 }
712 pointer->button_count++;
713 } else {
714 weston_compositor_idle_release(compositor);
715 pointer->button_count--;
716 }
717
718 weston_compositor_run_button_binding(compositor, seat, time, button,
719 state);
720
721 pointer->grab->interface->button(pointer->grab, time, button, state);
722
723 if (pointer->button_count == 1)
724 pointer->grab_serial =
725 wl_display_get_serial(compositor->wl_display);
726}
727
728WL_EXPORT void
729notify_axis(struct weston_seat *seat, uint32_t time, uint32_t axis,
730 wl_fixed_t value)
731{
732 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400733 struct weston_pointer *pointer = seat->pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400734 struct weston_surface *focus =
735 (struct weston_surface *) pointer->focus;
736 uint32_t serial = wl_display_next_serial(compositor->wl_display);
737
738 if (compositor->ping_handler && focus)
739 compositor->ping_handler(focus, serial);
740
741 weston_compositor_wake(compositor);
742
743 if (!value)
744 return;
745
746 if (weston_compositor_run_axis_binding(compositor, seat,
747 time, axis, value))
748 return;
749
750 if (pointer->focus_resource)
751 wl_pointer_send_axis(pointer->focus_resource, time, axis,
752 value);
753}
754
755WL_EXPORT void
756notify_modifiers(struct weston_seat *seat, uint32_t serial)
757{
Kristian Høgsberge3148752013-05-06 23:19:49 -0400758 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400759 struct weston_keyboard_grab *grab = keyboard->grab;
760 uint32_t mods_depressed, mods_latched, mods_locked, group;
761 uint32_t mods_lookup;
762 enum weston_led leds = 0;
763 int changed = 0;
764
765 /* Serialize and update our internal state, checking to see if it's
766 * different to the previous state. */
767 mods_depressed = xkb_state_serialize_mods(seat->xkb_state.state,
768 XKB_STATE_DEPRESSED);
769 mods_latched = xkb_state_serialize_mods(seat->xkb_state.state,
770 XKB_STATE_LATCHED);
771 mods_locked = xkb_state_serialize_mods(seat->xkb_state.state,
772 XKB_STATE_LOCKED);
773 group = xkb_state_serialize_group(seat->xkb_state.state,
774 XKB_STATE_EFFECTIVE);
775
Kristian Høgsberge3148752013-05-06 23:19:49 -0400776 if (mods_depressed != seat->keyboard->modifiers.mods_depressed ||
777 mods_latched != seat->keyboard->modifiers.mods_latched ||
778 mods_locked != seat->keyboard->modifiers.mods_locked ||
779 group != seat->keyboard->modifiers.group)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400780 changed = 1;
781
Kristian Høgsberge3148752013-05-06 23:19:49 -0400782 seat->keyboard->modifiers.mods_depressed = mods_depressed;
783 seat->keyboard->modifiers.mods_latched = mods_latched;
784 seat->keyboard->modifiers.mods_locked = mods_locked;
785 seat->keyboard->modifiers.group = group;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400786
787 /* And update the modifier_state for bindings. */
788 mods_lookup = mods_depressed | mods_latched;
789 seat->modifier_state = 0;
790 if (mods_lookup & (1 << seat->xkb_info.ctrl_mod))
791 seat->modifier_state |= MODIFIER_CTRL;
792 if (mods_lookup & (1 << seat->xkb_info.alt_mod))
793 seat->modifier_state |= MODIFIER_ALT;
794 if (mods_lookup & (1 << seat->xkb_info.super_mod))
795 seat->modifier_state |= MODIFIER_SUPER;
796 if (mods_lookup & (1 << seat->xkb_info.shift_mod))
797 seat->modifier_state |= MODIFIER_SHIFT;
798
799 /* Finally, notify the compositor that LEDs have changed. */
800 if (xkb_state_led_index_is_active(seat->xkb_state.state,
801 seat->xkb_info.num_led))
802 leds |= LED_NUM_LOCK;
803 if (xkb_state_led_index_is_active(seat->xkb_state.state,
804 seat->xkb_info.caps_led))
805 leds |= LED_CAPS_LOCK;
806 if (xkb_state_led_index_is_active(seat->xkb_state.state,
807 seat->xkb_info.scroll_led))
808 leds |= LED_SCROLL_LOCK;
809 if (leds != seat->xkb_state.leds && seat->led_update)
810 seat->led_update(seat, leds);
811 seat->xkb_state.leds = leds;
812
813 if (changed) {
814 grab->interface->modifiers(grab,
815 serial,
816 keyboard->modifiers.mods_depressed,
817 keyboard->modifiers.mods_latched,
818 keyboard->modifiers.mods_locked,
819 keyboard->modifiers.group);
820 }
821}
822
823static void
824update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key,
825 enum wl_keyboard_key_state state)
826{
827 enum xkb_key_direction direction;
828
829 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
830 direction = XKB_KEY_DOWN;
831 else
832 direction = XKB_KEY_UP;
833
834 /* Offset the keycode by 8, as the evdev XKB rules reflect X's
835 * broken keycode system, which starts at 8. */
836 xkb_state_update_key(seat->xkb_state.state, key + 8, direction);
837
838 notify_modifiers(seat, serial);
839}
840
841WL_EXPORT void
842notify_key(struct weston_seat *seat, uint32_t time, uint32_t key,
843 enum wl_keyboard_key_state state,
844 enum weston_key_state_update update_state)
845{
846 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400847 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400848 struct weston_surface *focus =
849 (struct weston_surface *) keyboard->focus;
850 struct weston_keyboard_grab *grab = keyboard->grab;
851 uint32_t serial = wl_display_next_serial(compositor->wl_display);
852 uint32_t *k, *end;
853
854 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
855 if (compositor->ping_handler && focus)
856 compositor->ping_handler(focus, serial);
857
858 weston_compositor_idle_inhibit(compositor);
859 keyboard->grab_key = key;
860 keyboard->grab_time = time;
861 } else {
862 weston_compositor_idle_release(compositor);
863 }
864
865 end = keyboard->keys.data + keyboard->keys.size;
866 for (k = keyboard->keys.data; k < end; k++) {
867 if (*k == key) {
868 /* Ignore server-generated repeats. */
869 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
870 return;
871 *k = *--end;
872 }
873 }
874 keyboard->keys.size = (void *) end - keyboard->keys.data;
875 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
876 k = wl_array_add(&keyboard->keys, sizeof *k);
877 *k = key;
878 }
879
880 if (grab == &keyboard->default_grab ||
881 grab == &keyboard->input_method_grab) {
882 weston_compositor_run_key_binding(compositor, seat, time, key,
883 state);
884 grab = keyboard->grab;
885 }
886
887 grab->interface->key(grab, time, key, state);
888
889 if (update_state == STATE_UPDATE_AUTOMATIC) {
890 update_modifier_state(seat,
891 wl_display_get_serial(compositor->wl_display),
892 key,
893 state);
894 }
895}
896
897WL_EXPORT void
898notify_pointer_focus(struct weston_seat *seat, struct weston_output *output,
899 wl_fixed_t x, wl_fixed_t y)
900{
901 struct weston_compositor *compositor = seat->compositor;
902
903 if (output) {
904 move_pointer(seat, x, y);
905 compositor->focus = 1;
906 } else {
907 compositor->focus = 0;
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400908 /* FIXME: We should call weston_pointer_set_focus(seat,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400909 * NULL) here, but somehow that breaks re-entry... */
910 }
911}
912
913static void
914destroy_device_saved_kbd_focus(struct wl_listener *listener, void *data)
915{
916 struct weston_seat *ws;
917
918 ws = container_of(listener, struct weston_seat,
919 saved_kbd_focus_listener);
920
921 ws->saved_kbd_focus = NULL;
922}
923
924WL_EXPORT void
925notify_keyboard_focus_in(struct weston_seat *seat, struct wl_array *keys,
926 enum weston_key_state_update update_state)
927{
928 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400929 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400930 struct wl_surface *surface;
931 uint32_t *k, serial;
932
933 serial = wl_display_next_serial(compositor->wl_display);
934 wl_array_copy(&keyboard->keys, keys);
935 wl_array_for_each(k, &keyboard->keys) {
936 weston_compositor_idle_inhibit(compositor);
937 if (update_state == STATE_UPDATE_AUTOMATIC)
938 update_modifier_state(seat, serial, *k,
939 WL_KEYBOARD_KEY_STATE_PRESSED);
940 }
941
942 /* Run key bindings after we've updated the state. */
943 wl_array_for_each(k, &keyboard->keys) {
944 weston_compositor_run_key_binding(compositor, seat, 0, *k,
945 WL_KEYBOARD_KEY_STATE_PRESSED);
946 }
947
948 surface = seat->saved_kbd_focus;
949
950 if (surface) {
951 wl_list_remove(&seat->saved_kbd_focus_listener.link);
952 weston_keyboard_set_focus(keyboard, surface);
953 seat->saved_kbd_focus = NULL;
954 }
955}
956
957WL_EXPORT void
958notify_keyboard_focus_out(struct weston_seat *seat)
959{
960 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400961 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400962 uint32_t *k, serial;
963
964 serial = wl_display_next_serial(compositor->wl_display);
965 wl_array_for_each(k, &keyboard->keys) {
966 weston_compositor_idle_release(compositor);
967 update_modifier_state(seat, serial, *k,
968 WL_KEYBOARD_KEY_STATE_RELEASED);
969 }
970
971 seat->modifier_state = 0;
972
973 if (keyboard->focus) {
974 seat->saved_kbd_focus = keyboard->focus;
975 seat->saved_kbd_focus_listener.notify =
976 destroy_device_saved_kbd_focus;
977 wl_signal_add(&keyboard->focus->resource.destroy_signal,
978 &seat->saved_kbd_focus_listener);
979 }
980
981 weston_keyboard_set_focus(keyboard, NULL);
982 /* FIXME: We really need keyboard grab cancel here to
983 * let the grab shut down properly. As it is we leak
984 * the grab data. */
985 weston_keyboard_end_grab(keyboard);
986}
987
988static void
Kristian Høgsberge3148752013-05-06 23:19:49 -0400989touch_set_focus(struct weston_seat *seat, struct wl_surface *surface)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400990{
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400991 struct wl_resource *resource;
992
993 if (seat->touch->focus == surface)
994 return;
995
996 if (seat->touch->focus_resource)
997 wl_list_remove(&seat->touch->focus_listener.link);
998 seat->touch->focus = NULL;
999 seat->touch->focus_resource = NULL;
1000
1001 if (surface) {
1002 resource =
Kristian Høgsberg80fb82d2013-05-06 21:49:55 -04001003 find_resource_for_surface(&seat->touch->resource_list,
1004 surface);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001005 if (!resource) {
1006 weston_log("couldn't find resource\n");
1007 return;
1008 }
1009
1010 seat->touch->focus = surface;
1011 seat->touch->focus_resource = resource;
1012 wl_signal_add(&resource->destroy_signal,
1013 &seat->touch->focus_listener);
1014 }
1015}
1016
1017/**
1018 * notify_touch - emulates button touches and notifies surfaces accordingly.
1019 *
1020 * It assumes always the correct cycle sequence until it gets here: touch_down
1021 * → touch_update → ... → touch_update → touch_end. The driver is responsible
1022 * for sending along such order.
1023 *
1024 */
1025WL_EXPORT void
1026notify_touch(struct weston_seat *seat, uint32_t time, int touch_id,
1027 wl_fixed_t x, wl_fixed_t y, int touch_type)
1028{
1029 struct weston_compositor *ec = seat->compositor;
Kristian Høgsberge3148752013-05-06 23:19:49 -04001030 struct weston_touch *touch = seat->touch;
Kristian Høgsberge329f362013-05-06 22:19:57 -04001031 struct weston_touch_grab *grab = touch->grab;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001032 struct weston_surface *es;
1033 wl_fixed_t sx, sy;
1034
1035 /* Update grab's global coordinates. */
1036 touch->grab_x = x;
1037 touch->grab_y = y;
1038
1039 switch (touch_type) {
1040 case WL_TOUCH_DOWN:
1041 weston_compositor_idle_inhibit(ec);
1042
1043 seat->num_tp++;
1044
1045 /* the first finger down picks the surface, and all further go
1046 * to that surface for the remainder of the touch session i.e.
1047 * until all touch points are up again. */
1048 if (seat->num_tp == 1) {
1049 es = weston_compositor_pick_surface(ec, x, y, &sx, &sy);
1050 touch_set_focus(seat, &es->surface);
1051 } else if (touch->focus) {
1052 es = (struct weston_surface *) touch->focus;
1053 weston_surface_from_global_fixed(es, x, y, &sx, &sy);
1054 } else {
1055 /* Unexpected condition: We have non-initial touch but
1056 * there is no focused surface.
1057 */
1058 weston_log("touch event received with %d points down"
1059 "but no surface focused\n", seat->num_tp);
1060 return;
1061 }
1062
1063 grab->interface->down(grab, time, touch_id, sx, sy);
1064 break;
1065 case WL_TOUCH_MOTION:
1066 es = (struct weston_surface *) touch->focus;
1067 if (!es)
1068 break;
1069
1070 weston_surface_from_global_fixed(es, x, y, &sx, &sy);
1071 grab->interface->motion(grab, time, touch_id, sx, sy);
1072 break;
1073 case WL_TOUCH_UP:
1074 weston_compositor_idle_release(ec);
1075 seat->num_tp--;
1076
1077 grab->interface->up(grab, time, touch_id);
1078 if (seat->num_tp == 0)
1079 touch_set_focus(seat, NULL);
1080 break;
1081 }
1082}
1083
1084static void
1085pointer_handle_sprite_destroy(struct wl_listener *listener, void *data)
1086{
1087 struct weston_seat *seat = container_of(listener, struct weston_seat,
1088 sprite_destroy_listener);
1089
1090 seat->sprite = NULL;
1091}
1092
1093static void
1094pointer_cursor_surface_configure(struct weston_surface *es,
1095 int32_t dx, int32_t dy, int32_t width, int32_t height)
1096{
1097 struct weston_seat *seat = es->configure_private;
1098 int x, y;
1099
1100 if (width == 0)
1101 return;
1102
1103 assert(es == seat->sprite);
1104
1105 seat->hotspot_x -= dx;
1106 seat->hotspot_y -= dy;
1107
Kristian Høgsberge3148752013-05-06 23:19:49 -04001108 x = wl_fixed_to_int(seat->pointer->x) - seat->hotspot_x;
1109 y = wl_fixed_to_int(seat->pointer->y) - seat->hotspot_y;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001110
1111 weston_surface_configure(seat->sprite, x, y,
1112 width, height);
1113
1114 empty_region(&es->pending.input);
1115
1116 if (!weston_surface_is_mapped(es)) {
1117 wl_list_insert(&es->compositor->cursor_layer.surface_list,
1118 &es->layer_link);
1119 weston_surface_update_transform(es);
1120 }
1121}
1122
1123static void
1124pointer_unmap_sprite(struct weston_seat *seat)
1125{
1126 if (weston_surface_is_mapped(seat->sprite))
1127 weston_surface_unmap(seat->sprite);
1128
1129 wl_list_remove(&seat->sprite_destroy_listener.link);
1130 seat->sprite->configure = NULL;
1131 seat->sprite->configure_private = NULL;
1132 seat->sprite = NULL;
1133}
1134
1135static void
1136pointer_set_cursor(struct wl_client *client, struct wl_resource *resource,
1137 uint32_t serial, struct wl_resource *surface_resource,
1138 int32_t x, int32_t y)
1139{
1140 struct weston_seat *seat = resource->data;
1141 struct weston_surface *surface = NULL;
1142
1143 if (surface_resource)
1144 surface = surface_resource->data;
1145
Kristian Høgsberge3148752013-05-06 23:19:49 -04001146 if (seat->pointer->focus == NULL)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001147 return;
Kristian Høgsberge3148752013-05-06 23:19:49 -04001148 if (seat->pointer->focus->resource.client != client)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001149 return;
Kristian Høgsberge3148752013-05-06 23:19:49 -04001150 if (seat->pointer->focus_serial - serial > UINT32_MAX / 2)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001151 return;
1152
1153 if (surface && surface != seat->sprite) {
1154 if (surface->configure) {
1155 wl_resource_post_error(&surface->surface.resource,
1156 WL_DISPLAY_ERROR_INVALID_OBJECT,
1157 "surface->configure already "
1158 "set");
1159 return;
1160 }
1161 }
1162
1163 if (seat->sprite)
1164 pointer_unmap_sprite(seat);
1165
1166 if (!surface)
1167 return;
1168
1169 wl_signal_add(&surface->surface.resource.destroy_signal,
1170 &seat->sprite_destroy_listener);
1171
1172 surface->configure = pointer_cursor_surface_configure;
1173 surface->configure_private = seat;
1174 seat->sprite = surface;
1175 seat->hotspot_x = x;
1176 seat->hotspot_y = y;
1177
1178 if (surface->buffer_ref.buffer)
1179 pointer_cursor_surface_configure(surface, 0, 0, weston_surface_buffer_width(surface),
1180 weston_surface_buffer_height(surface));
1181}
1182
1183static const struct wl_pointer_interface pointer_interface = {
1184 pointer_set_cursor
1185};
1186
1187static void
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001188seat_get_pointer(struct wl_client *client, struct wl_resource *resource,
1189 uint32_t id)
1190{
1191 struct weston_seat *seat = resource->data;
1192 struct wl_resource *cr;
1193
Kristian Høgsberge3148752013-05-06 23:19:49 -04001194 if (!seat->pointer)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001195 return;
1196
1197 cr = wl_client_add_object(client, &wl_pointer_interface,
1198 &pointer_interface, id, seat);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001199 wl_list_insert(&seat->pointer->resource_list, &cr->link);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001200 cr->destroy = unbind_resource;
1201
Kristian Høgsberge3148752013-05-06 23:19:49 -04001202 if (seat->pointer->focus &&
1203 seat->pointer->focus->resource.client == client) {
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001204 struct weston_surface *surface;
1205 wl_fixed_t sx, sy;
1206
Kristian Høgsberge3148752013-05-06 23:19:49 -04001207 surface = (struct weston_surface *) seat->pointer->focus;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001208 weston_surface_from_global_fixed(surface,
Kristian Høgsberge3148752013-05-06 23:19:49 -04001209 seat->pointer->x,
1210 seat->pointer->y,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001211 &sx,
1212 &sy);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001213 weston_pointer_set_focus(seat->pointer,
1214 seat->pointer->focus,
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001215 sx,
1216 sy);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001217 }
1218}
1219
1220static void
1221seat_get_keyboard(struct wl_client *client, struct wl_resource *resource,
1222 uint32_t id)
1223{
1224 struct weston_seat *seat = resource->data;
1225 struct wl_resource *cr;
1226
Kristian Høgsberge3148752013-05-06 23:19:49 -04001227 if (!seat->keyboard)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001228 return;
1229
1230 cr = wl_client_add_object(client, &wl_keyboard_interface, NULL, id,
1231 seat);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001232 wl_list_insert(&seat->keyboard->resource_list, &cr->link);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001233 cr->destroy = unbind_resource;
1234
1235 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
1236 seat->xkb_info.keymap_fd,
1237 seat->xkb_info.keymap_size);
1238
Kristian Høgsberge3148752013-05-06 23:19:49 -04001239 if (seat->keyboard->focus &&
1240 seat->keyboard->focus->resource.client == client) {
1241 weston_keyboard_set_focus(seat->keyboard,
1242 seat->keyboard->focus);
1243 wl_data_device_set_keyboard_focus(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001244 }
1245}
1246
1247static void
1248seat_get_touch(struct wl_client *client, struct wl_resource *resource,
1249 uint32_t id)
1250{
1251 struct weston_seat *seat = resource->data;
1252 struct wl_resource *cr;
1253
Kristian Høgsberge3148752013-05-06 23:19:49 -04001254 if (!seat->touch)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001255 return;
1256
1257 cr = wl_client_add_object(client, &wl_touch_interface, NULL, id, seat);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001258 wl_list_insert(&seat->touch->resource_list, &cr->link);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001259 cr->destroy = unbind_resource;
1260}
1261
1262static const struct wl_seat_interface seat_interface = {
1263 seat_get_pointer,
1264 seat_get_keyboard,
1265 seat_get_touch,
1266};
1267
1268static void
1269bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
1270{
Kristian Høgsberge3148752013-05-06 23:19:49 -04001271 struct weston_seat *seat = data;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001272 struct wl_resource *resource;
1273 enum wl_seat_capability caps = 0;
1274
1275 resource = wl_client_add_object(client, &wl_seat_interface,
1276 &seat_interface, id, data);
1277 wl_list_insert(&seat->base_resource_list, &resource->link);
1278 resource->destroy = unbind_resource;
1279
1280 if (seat->pointer)
1281 caps |= WL_SEAT_CAPABILITY_POINTER;
1282 if (seat->keyboard)
1283 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
1284 if (seat->touch)
1285 caps |= WL_SEAT_CAPABILITY_TOUCH;
1286
1287 wl_seat_send_capabilities(resource, caps);
1288}
1289
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001290int
1291weston_compositor_xkb_init(struct weston_compositor *ec,
1292 struct xkb_rule_names *names)
1293{
1294 if (ec->xkb_context == NULL) {
1295 ec->xkb_context = xkb_context_new(0);
1296 if (ec->xkb_context == NULL) {
1297 weston_log("failed to create XKB context\n");
1298 return -1;
1299 }
1300 }
1301
1302 if (names)
1303 ec->xkb_names = *names;
1304 if (!ec->xkb_names.rules)
1305 ec->xkb_names.rules = strdup("evdev");
1306 if (!ec->xkb_names.model)
1307 ec->xkb_names.model = strdup("pc105");
1308 if (!ec->xkb_names.layout)
1309 ec->xkb_names.layout = strdup("us");
1310
1311 return 0;
1312}
1313
1314static void xkb_info_destroy(struct weston_xkb_info *xkb_info)
1315{
1316 if (xkb_info->keymap)
1317 xkb_map_unref(xkb_info->keymap);
1318
1319 if (xkb_info->keymap_area)
1320 munmap(xkb_info->keymap_area, xkb_info->keymap_size);
1321 if (xkb_info->keymap_fd >= 0)
1322 close(xkb_info->keymap_fd);
1323}
1324
1325void
1326weston_compositor_xkb_destroy(struct weston_compositor *ec)
1327{
1328 free((char *) ec->xkb_names.rules);
1329 free((char *) ec->xkb_names.model);
1330 free((char *) ec->xkb_names.layout);
1331 free((char *) ec->xkb_names.variant);
1332 free((char *) ec->xkb_names.options);
1333
1334 xkb_info_destroy(&ec->xkb_info);
1335 xkb_context_unref(ec->xkb_context);
1336}
1337
1338static int
1339weston_xkb_info_new_keymap(struct weston_xkb_info *xkb_info)
1340{
1341 char *keymap_str;
1342
1343 xkb_info->shift_mod = xkb_map_mod_get_index(xkb_info->keymap,
1344 XKB_MOD_NAME_SHIFT);
1345 xkb_info->caps_mod = xkb_map_mod_get_index(xkb_info->keymap,
1346 XKB_MOD_NAME_CAPS);
1347 xkb_info->ctrl_mod = xkb_map_mod_get_index(xkb_info->keymap,
1348 XKB_MOD_NAME_CTRL);
1349 xkb_info->alt_mod = xkb_map_mod_get_index(xkb_info->keymap,
1350 XKB_MOD_NAME_ALT);
1351 xkb_info->mod2_mod = xkb_map_mod_get_index(xkb_info->keymap, "Mod2");
1352 xkb_info->mod3_mod = xkb_map_mod_get_index(xkb_info->keymap, "Mod3");
1353 xkb_info->super_mod = xkb_map_mod_get_index(xkb_info->keymap,
1354 XKB_MOD_NAME_LOGO);
1355 xkb_info->mod5_mod = xkb_map_mod_get_index(xkb_info->keymap, "Mod5");
1356
1357 xkb_info->num_led = xkb_map_led_get_index(xkb_info->keymap,
1358 XKB_LED_NAME_NUM);
1359 xkb_info->caps_led = xkb_map_led_get_index(xkb_info->keymap,
1360 XKB_LED_NAME_CAPS);
1361 xkb_info->scroll_led = xkb_map_led_get_index(xkb_info->keymap,
1362 XKB_LED_NAME_SCROLL);
1363
1364 keymap_str = xkb_map_get_as_string(xkb_info->keymap);
1365 if (keymap_str == NULL) {
1366 weston_log("failed to get string version of keymap\n");
1367 return -1;
1368 }
1369 xkb_info->keymap_size = strlen(keymap_str) + 1;
1370
1371 xkb_info->keymap_fd = os_create_anonymous_file(xkb_info->keymap_size);
1372 if (xkb_info->keymap_fd < 0) {
1373 weston_log("creating a keymap file for %lu bytes failed: %m\n",
1374 (unsigned long) xkb_info->keymap_size);
1375 goto err_keymap_str;
1376 }
1377
1378 xkb_info->keymap_area = mmap(NULL, xkb_info->keymap_size,
1379 PROT_READ | PROT_WRITE,
1380 MAP_SHARED, xkb_info->keymap_fd, 0);
1381 if (xkb_info->keymap_area == MAP_FAILED) {
1382 weston_log("failed to mmap() %lu bytes\n",
1383 (unsigned long) xkb_info->keymap_size);
1384 goto err_dev_zero;
1385 }
1386 strcpy(xkb_info->keymap_area, keymap_str);
1387 free(keymap_str);
1388
1389 return 0;
1390
1391err_dev_zero:
1392 close(xkb_info->keymap_fd);
1393 xkb_info->keymap_fd = -1;
1394err_keymap_str:
1395 free(keymap_str);
1396 return -1;
1397}
1398
1399static int
1400weston_compositor_build_global_keymap(struct weston_compositor *ec)
1401{
1402 if (ec->xkb_info.keymap != NULL)
1403 return 0;
1404
1405 ec->xkb_info.keymap = xkb_map_new_from_names(ec->xkb_context,
1406 &ec->xkb_names,
1407 0);
1408 if (ec->xkb_info.keymap == NULL) {
1409 weston_log("failed to compile global XKB keymap\n");
1410 weston_log(" tried rules %s, model %s, layout %s, variant %s, "
1411 "options %s\n",
1412 ec->xkb_names.rules, ec->xkb_names.model,
1413 ec->xkb_names.layout, ec->xkb_names.variant,
1414 ec->xkb_names.options);
1415 return -1;
1416 }
1417
1418 if (weston_xkb_info_new_keymap(&ec->xkb_info) < 0)
1419 return -1;
1420
1421 return 0;
1422}
1423
1424WL_EXPORT int
1425weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
1426{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001427 struct weston_keyboard *keyboard;
1428
Kristian Høgsberg2bf87622013-05-07 23:17:41 -04001429 if (seat->keyboard)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001430 return 0;
1431
1432 if (keymap != NULL) {
1433 seat->xkb_info.keymap = xkb_map_ref(keymap);
1434 if (weston_xkb_info_new_keymap(&seat->xkb_info) < 0)
1435 return -1;
1436 } else {
1437 if (weston_compositor_build_global_keymap(seat->compositor) < 0)
1438 return -1;
1439 seat->xkb_info = seat->compositor->xkb_info;
1440 seat->xkb_info.keymap = xkb_map_ref(seat->xkb_info.keymap);
1441 }
1442
1443 seat->xkb_state.state = xkb_state_new(seat->xkb_info.keymap);
1444 if (seat->xkb_state.state == NULL) {
1445 weston_log("failed to initialise XKB state\n");
1446 return -1;
1447 }
1448
1449 seat->xkb_state.leds = 0;
1450
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001451 keyboard = weston_keyboard_create();
1452 if (keyboard == NULL) {
1453 weston_log("failed to allocate weston keyboard struct\n");
1454 return -1;
1455 }
1456
1457 seat->keyboard = keyboard;
1458 keyboard->seat = seat;
1459
1460 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001461
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001462 return 0;
1463}
1464
1465WL_EXPORT void
1466weston_seat_init_pointer(struct weston_seat *seat)
1467{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001468 struct weston_pointer *pointer;
1469
Kristian Høgsberg2bf87622013-05-07 23:17:41 -04001470 if (seat->pointer)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001471 return;
1472
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001473 pointer = weston_pointer_create();
1474 if (pointer == NULL)
1475 return;
1476
1477 seat->pointer = pointer;
1478 pointer->seat = seat;
1479
1480 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001481}
1482
1483WL_EXPORT void
1484weston_seat_init_touch(struct weston_seat *seat)
1485{
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001486 struct weston_touch *touch;
1487
Kristian Høgsberg2bf87622013-05-07 23:17:41 -04001488 if (seat->touch)
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001489 return;
1490
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001491 touch = weston_touch_create();
1492 if (touch == NULL)
1493 return;
1494
1495 seat->touch = touch;
1496 touch->seat = seat;
1497
1498 seat_send_updated_caps(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001499}
1500
1501WL_EXPORT void
1502weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec)
1503{
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04001504 memset(seat, 0, sizeof *seat);
1505
Kristian Høgsberge3148752013-05-06 23:19:49 -04001506 seat->selection_data_source = NULL;
1507 wl_list_init(&seat->base_resource_list);
1508 wl_signal_init(&seat->selection_signal);
1509 wl_list_init(&seat->drag_resource_list);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001510 wl_signal_init(&seat->destroy_signal);
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04001511
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001512 wl_display_add_global(ec->wl_display, &wl_seat_interface, seat,
1513 bind_seat);
1514
1515 seat->sprite = NULL;
1516 seat->sprite_destroy_listener.notify = pointer_handle_sprite_destroy;
1517
1518 seat->compositor = ec;
1519 seat->hotspot_x = 16;
1520 seat->hotspot_y = 16;
1521 seat->modifier_state = 0;
1522 seat->num_tp = 0;
1523
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001524 wl_list_insert(ec->seat_list.prev, &seat->link);
1525
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001526 clipboard_create(seat);
1527
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001528 wl_signal_emit(&ec->seat_created_signal, seat);
1529}
1530
1531WL_EXPORT void
1532weston_seat_release(struct weston_seat *seat)
1533{
1534 wl_list_remove(&seat->link);
1535 /* The global object is destroyed at wl_display_destroy() time. */
1536
1537 if (seat->sprite)
1538 pointer_unmap_sprite(seat);
1539
1540 if (seat->xkb_state.state != NULL)
1541 xkb_state_unref(seat->xkb_state.state);
1542 xkb_info_destroy(&seat->xkb_info);
1543
Kristian Høgsberge3148752013-05-06 23:19:49 -04001544 if (seat->pointer)
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001545 weston_pointer_destroy(seat->pointer);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001546 if (seat->keyboard)
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001547 weston_keyboard_destroy(seat->keyboard);
Kristian Høgsberge3148752013-05-06 23:19:49 -04001548 if (seat->touch)
Kristian Høgsberga4036bb2013-05-07 23:52:07 -04001549 weston_touch_destroy(seat->touch);
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04001550
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001551 wl_signal_emit(&seat->destroy_signal, seat);
1552}