blob: 8573555dc4cf833f53be061cfcbeba96f534f15d [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øgsberg02bbabb2013-05-06 22:15:05 -040051 struct weston_pointer *pointer = seat->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
293WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400294weston_pointer_init(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400295{
296 memset(pointer, 0, sizeof *pointer);
297 wl_list_init(&pointer->resource_list);
298 pointer->focus_listener.notify = lose_pointer_focus;
299 pointer->default_grab.interface = &default_pointer_grab_interface;
300 pointer->default_grab.pointer = pointer;
301 pointer->grab = &pointer->default_grab;
302 wl_signal_init(&pointer->focus_signal);
303
304 /* FIXME: Pick better co-ords. */
305 pointer->x = wl_fixed_from_int(100);
306 pointer->y = wl_fixed_from_int(100);
307}
308
309WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400310weston_pointer_release(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400311{
312 /* XXX: What about pointer->resource_list? */
313 if (pointer->focus_resource)
314 wl_list_remove(&pointer->focus_listener.link);
315}
316
317WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400318weston_keyboard_init(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400319{
320 memset(keyboard, 0, sizeof *keyboard);
321 wl_list_init(&keyboard->resource_list);
322 wl_array_init(&keyboard->keys);
323 keyboard->focus_listener.notify = lose_keyboard_focus;
324 keyboard->default_grab.interface = &default_keyboard_grab_interface;
325 keyboard->default_grab.keyboard = keyboard;
326 keyboard->grab = &keyboard->default_grab;
327 wl_signal_init(&keyboard->focus_signal);
328}
329
330WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400331weston_keyboard_release(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400332{
333 /* XXX: What about keyboard->resource_list? */
334 if (keyboard->focus_resource)
335 wl_list_remove(&keyboard->focus_listener.link);
336 wl_array_release(&keyboard->keys);
337}
338
339WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -0400340weston_touch_init(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400341{
342 memset(touch, 0, sizeof *touch);
343 wl_list_init(&touch->resource_list);
344 touch->focus_listener.notify = lose_touch_focus;
345 touch->default_grab.interface = &default_touch_grab_interface;
346 touch->default_grab.touch = touch;
347 touch->grab = &touch->default_grab;
348 wl_signal_init(&touch->focus_signal);
349}
350
351WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -0400352weston_touch_release(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400353{
354 /* XXX: What about touch->resource_list? */
355 if (touch->focus_resource)
356 wl_list_remove(&touch->focus_listener.link);
357}
358
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400359static void
360seat_send_updated_caps(struct wl_seat *seat)
361{
362 struct wl_resource *r;
363 enum wl_seat_capability caps = 0;
364
365 if (seat->pointer)
366 caps |= WL_SEAT_CAPABILITY_POINTER;
367 if (seat->keyboard)
368 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
369 if (seat->touch)
370 caps |= WL_SEAT_CAPABILITY_TOUCH;
371
372 wl_list_for_each(r, &seat->base_resource_list, link)
373 wl_seat_send_capabilities(r, caps);
374}
375
376WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400377wl_seat_set_pointer(struct wl_seat *seat, struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400378{
379 if (pointer && (seat->pointer || pointer->seat))
380 return; /* XXX: error? */
381 if (!pointer && !seat->pointer)
382 return;
383
384 seat->pointer = pointer;
385 if (pointer)
386 pointer->seat = seat;
387
388 seat_send_updated_caps(seat);
389}
390
391WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400392wl_seat_set_keyboard(struct wl_seat *seat, struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400393{
394 if (keyboard && (seat->keyboard || keyboard->seat))
395 return; /* XXX: error? */
396 if (!keyboard && !seat->keyboard)
397 return;
398
399 seat->keyboard = keyboard;
400 if (keyboard)
401 keyboard->seat = seat;
402
403 seat_send_updated_caps(seat);
404}
405
406WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -0400407wl_seat_set_touch(struct wl_seat *seat, struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400408{
409 if (touch && (seat->touch || touch->seat))
410 return; /* XXX: error? */
411 if (!touch && !seat->touch)
412 return;
413
414 seat->touch = touch;
415 if (touch)
416 touch->seat = seat;
417
418 seat_send_updated_caps(seat);
419}
420
421WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400422weston_pointer_set_focus(struct weston_pointer *pointer,
423 struct wl_surface *surface,
424 wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400425{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400426 struct weston_keyboard *kbd = pointer->seat->keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400427 struct wl_resource *resource, *kr;
428 struct wl_display *display;
429 uint32_t serial;
430
431 resource = pointer->focus_resource;
432 if (resource && pointer->focus != surface) {
433 display = wl_client_get_display(resource->client);
434 serial = wl_display_next_serial(display);
435 wl_pointer_send_leave(resource, serial,
436 &pointer->focus->resource);
437 wl_list_remove(&pointer->focus_listener.link);
438 }
439
440 resource = find_resource_for_surface(&pointer->resource_list,
441 surface);
442 if (resource &&
443 (pointer->focus != surface ||
444 pointer->focus_resource != resource)) {
445 display = wl_client_get_display(resource->client);
446 serial = wl_display_next_serial(display);
447 if (kbd) {
448 kr = find_resource_for_surface(&kbd->resource_list,
449 surface);
450 if (kr) {
451 wl_keyboard_send_modifiers(kr,
452 serial,
453 kbd->modifiers.mods_depressed,
454 kbd->modifiers.mods_latched,
455 kbd->modifiers.mods_locked,
456 kbd->modifiers.group);
457 }
458 }
459 wl_pointer_send_enter(resource, serial, &surface->resource,
460 sx, sy);
461 wl_signal_add(&resource->destroy_signal,
462 &pointer->focus_listener);
463 pointer->focus_serial = serial;
464 }
465
466 pointer->focus_resource = resource;
467 pointer->focus = surface;
468 pointer->default_grab.focus = surface;
469 wl_signal_emit(&pointer->focus_signal, pointer);
470}
471
472WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400473weston_keyboard_set_focus(struct weston_keyboard *keyboard,
474 struct wl_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400475{
476 struct wl_resource *resource;
477 struct wl_display *display;
478 uint32_t serial;
479
480 if (keyboard->focus_resource && keyboard->focus != surface) {
481 resource = keyboard->focus_resource;
482 display = wl_client_get_display(resource->client);
483 serial = wl_display_next_serial(display);
484 wl_keyboard_send_leave(resource, serial,
485 &keyboard->focus->resource);
486 wl_list_remove(&keyboard->focus_listener.link);
487 }
488
489 resource = find_resource_for_surface(&keyboard->resource_list,
490 surface);
491 if (resource &&
492 (keyboard->focus != surface ||
493 keyboard->focus_resource != resource)) {
494 display = wl_client_get_display(resource->client);
495 serial = wl_display_next_serial(display);
496 wl_keyboard_send_modifiers(resource, serial,
497 keyboard->modifiers.mods_depressed,
498 keyboard->modifiers.mods_latched,
499 keyboard->modifiers.mods_locked,
500 keyboard->modifiers.group);
501 wl_keyboard_send_enter(resource, serial, &surface->resource,
502 &keyboard->keys);
503 wl_signal_add(&resource->destroy_signal,
504 &keyboard->focus_listener);
505 keyboard->focus_serial = serial;
506 }
507
508 keyboard->focus_resource = resource;
509 keyboard->focus = surface;
510 wl_signal_emit(&keyboard->focus_signal, keyboard);
511}
512
513WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400514weston_keyboard_start_grab(struct weston_keyboard *keyboard,
515 struct weston_keyboard_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400516{
517 keyboard->grab = grab;
518 grab->keyboard = keyboard;
519
520 /* XXX focus? */
521}
522
523WL_EXPORT void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400524weston_keyboard_end_grab(struct weston_keyboard *keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400525{
526 keyboard->grab = &keyboard->default_grab;
527}
528
529WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400530weston_pointer_start_grab(struct weston_pointer *pointer,
531 struct weston_pointer_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400532{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400533 const struct weston_pointer_grab_interface *interface;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400534
535 pointer->grab = grab;
536 interface = pointer->grab->interface;
537 grab->pointer = pointer;
538
539 if (pointer->current)
540 interface->focus(pointer->grab, pointer->current,
541 pointer->current_x, pointer->current_y);
542}
543
544WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400545weston_pointer_end_grab(struct weston_pointer *pointer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400546{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400547 const struct weston_pointer_grab_interface *interface;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400548
549 pointer->grab = &pointer->default_grab;
550 interface = pointer->grab->interface;
551 interface->focus(pointer->grab, pointer->current,
552 pointer->current_x, pointer->current_y);
553}
554
555static void
556current_surface_destroy(struct wl_listener *listener, void *data)
557{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400558 struct weston_pointer *pointer =
559 container_of(listener, struct weston_pointer, current_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400560
561 pointer->current = NULL;
562}
563
564WL_EXPORT void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400565weston_pointer_set_current(struct weston_pointer *pointer,
566 struct wl_surface *surface)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400567{
568 if (pointer->current)
569 wl_list_remove(&pointer->current_listener.link);
570
571 pointer->current = surface;
572
573 if (!surface)
574 return;
575
576 wl_signal_add(&surface->resource.destroy_signal,
577 &pointer->current_listener);
578 pointer->current_listener.notify = current_surface_destroy;
579}
580
581WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -0400582weston_touch_start_grab(struct weston_touch *touch, struct weston_touch_grab *grab)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400583{
584 touch->grab = grab;
585 grab->touch = touch;
586}
587
588WL_EXPORT void
Kristian Høgsberge329f362013-05-06 22:19:57 -0400589weston_touch_end_grab(struct weston_touch *touch)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400590{
591 touch->grab = &touch->default_grab;
592}
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400593
594static void
595weston_seat_update_drag_surface(struct weston_seat *seat, int dx, int dy);
596
597static void
598clip_pointer_motion(struct weston_seat *seat, wl_fixed_t *fx, wl_fixed_t *fy)
599{
600 struct weston_compositor *ec = seat->compositor;
601 struct weston_output *output, *prev = NULL;
602 int x, y, old_x, old_y, valid = 0;
603
604 x = wl_fixed_to_int(*fx);
605 y = wl_fixed_to_int(*fy);
606 old_x = wl_fixed_to_int(seat->seat.pointer->x);
607 old_y = wl_fixed_to_int(seat->seat.pointer->y);
608
609 wl_list_for_each(output, &ec->output_list, link) {
610 if (pixman_region32_contains_point(&output->region,
611 x, y, NULL))
612 valid = 1;
613 if (pixman_region32_contains_point(&output->region,
614 old_x, old_y, NULL))
615 prev = output;
616 }
617
618 if (!valid) {
619 if (x < prev->x)
620 *fx = wl_fixed_from_int(prev->x);
621 else if (x >= prev->x + prev->width)
622 *fx = wl_fixed_from_int(prev->x +
623 prev->width - 1);
624 if (y < prev->y)
625 *fy = wl_fixed_from_int(prev->y);
626 else if (y >= prev->y + prev->current->height)
627 *fy = wl_fixed_from_int(prev->y +
628 prev->height - 1);
629 }
630}
631
632/* Takes absolute values */
633static void
634move_pointer(struct weston_seat *seat, wl_fixed_t x, wl_fixed_t y)
635{
636 struct weston_compositor *ec = seat->compositor;
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400637 struct weston_pointer *pointer = seat->seat.pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400638 struct weston_output *output;
639 int32_t ix, iy;
640
641 clip_pointer_motion(seat, &x, &y);
642
643 weston_seat_update_drag_surface(seat, x - pointer->x, y - pointer->y);
644
645 pointer->x = x;
646 pointer->y = y;
647
648 ix = wl_fixed_to_int(x);
649 iy = wl_fixed_to_int(y);
650
651 wl_list_for_each(output, &ec->output_list, link)
652 if (output->zoom.active &&
653 pixman_region32_contains_point(&output->region,
654 ix, iy, NULL))
655 weston_output_update_zoom(output, ZOOM_FOCUS_POINTER);
656
Kristian Høgsberga71e8b22013-05-06 21:51:21 -0400657 weston_seat_repick(seat);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400658
659 if (seat->sprite) {
660 weston_surface_set_position(seat->sprite,
661 ix - seat->hotspot_x,
662 iy - seat->hotspot_y);
663 weston_surface_schedule_repaint(seat->sprite);
664 }
665}
666
667WL_EXPORT void
668notify_motion(struct weston_seat *seat,
669 uint32_t time, wl_fixed_t dx, wl_fixed_t dy)
670{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400671 const struct weston_pointer_grab_interface *interface;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400672 struct weston_compositor *ec = seat->compositor;
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400673 struct weston_pointer *pointer = seat->seat.pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400674
675 weston_compositor_wake(ec);
676
677 move_pointer(seat, pointer->x + dx, pointer->y + dy);
678
679 interface = pointer->grab->interface;
680 interface->motion(pointer->grab, time,
681 pointer->grab->x, pointer->grab->y);
682}
683
684WL_EXPORT void
685notify_motion_absolute(struct weston_seat *seat,
686 uint32_t time, wl_fixed_t x, wl_fixed_t y)
687{
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400688 const struct weston_pointer_grab_interface *interface;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400689 struct weston_compositor *ec = seat->compositor;
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400690 struct weston_pointer *pointer = seat->seat.pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400691
692 weston_compositor_wake(ec);
693
694 move_pointer(seat, x, y);
695
696 interface = pointer->grab->interface;
697 interface->motion(pointer->grab, time,
698 pointer->grab->x, pointer->grab->y);
699}
700
701WL_EXPORT void
702weston_surface_activate(struct weston_surface *surface,
703 struct weston_seat *seat)
704{
705 struct weston_compositor *compositor = seat->compositor;
706
707 if (seat->seat.keyboard) {
708 weston_keyboard_set_focus(seat->seat.keyboard, &surface->surface);
709 wl_data_device_set_keyboard_focus(&seat->seat);
710 }
711
712 wl_signal_emit(&compositor->activate_signal, surface);
713}
714
715WL_EXPORT void
716notify_button(struct weston_seat *seat, uint32_t time, int32_t button,
717 enum wl_pointer_button_state state)
718{
719 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400720 struct weston_pointer *pointer = seat->seat.pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400721 struct weston_surface *focus =
722 (struct weston_surface *) pointer->focus;
723 uint32_t serial = wl_display_next_serial(compositor->wl_display);
724
725 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
726 if (compositor->ping_handler && focus)
727 compositor->ping_handler(focus, serial);
728 weston_compositor_idle_inhibit(compositor);
729 if (pointer->button_count == 0) {
730 pointer->grab_button = button;
731 pointer->grab_time = time;
732 pointer->grab_x = pointer->x;
733 pointer->grab_y = pointer->y;
734 }
735 pointer->button_count++;
736 } else {
737 weston_compositor_idle_release(compositor);
738 pointer->button_count--;
739 }
740
741 weston_compositor_run_button_binding(compositor, seat, time, button,
742 state);
743
744 pointer->grab->interface->button(pointer->grab, time, button, state);
745
746 if (pointer->button_count == 1)
747 pointer->grab_serial =
748 wl_display_get_serial(compositor->wl_display);
749}
750
751WL_EXPORT void
752notify_axis(struct weston_seat *seat, uint32_t time, uint32_t axis,
753 wl_fixed_t value)
754{
755 struct weston_compositor *compositor = seat->compositor;
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400756 struct weston_pointer *pointer = seat->seat.pointer;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400757 struct weston_surface *focus =
758 (struct weston_surface *) pointer->focus;
759 uint32_t serial = wl_display_next_serial(compositor->wl_display);
760
761 if (compositor->ping_handler && focus)
762 compositor->ping_handler(focus, serial);
763
764 weston_compositor_wake(compositor);
765
766 if (!value)
767 return;
768
769 if (weston_compositor_run_axis_binding(compositor, seat,
770 time, axis, value))
771 return;
772
773 if (pointer->focus_resource)
774 wl_pointer_send_axis(pointer->focus_resource, time, axis,
775 value);
776}
777
778WL_EXPORT void
779notify_modifiers(struct weston_seat *seat, uint32_t serial)
780{
781 struct weston_keyboard *keyboard = &seat->keyboard;
782 struct weston_keyboard_grab *grab = keyboard->grab;
783 uint32_t mods_depressed, mods_latched, mods_locked, group;
784 uint32_t mods_lookup;
785 enum weston_led leds = 0;
786 int changed = 0;
787
788 /* Serialize and update our internal state, checking to see if it's
789 * different to the previous state. */
790 mods_depressed = xkb_state_serialize_mods(seat->xkb_state.state,
791 XKB_STATE_DEPRESSED);
792 mods_latched = xkb_state_serialize_mods(seat->xkb_state.state,
793 XKB_STATE_LATCHED);
794 mods_locked = xkb_state_serialize_mods(seat->xkb_state.state,
795 XKB_STATE_LOCKED);
796 group = xkb_state_serialize_group(seat->xkb_state.state,
797 XKB_STATE_EFFECTIVE);
798
799 if (mods_depressed != seat->seat.keyboard->modifiers.mods_depressed ||
800 mods_latched != seat->seat.keyboard->modifiers.mods_latched ||
801 mods_locked != seat->seat.keyboard->modifiers.mods_locked ||
802 group != seat->seat.keyboard->modifiers.group)
803 changed = 1;
804
805 seat->seat.keyboard->modifiers.mods_depressed = mods_depressed;
806 seat->seat.keyboard->modifiers.mods_latched = mods_latched;
807 seat->seat.keyboard->modifiers.mods_locked = mods_locked;
808 seat->seat.keyboard->modifiers.group = group;
809
810 /* And update the modifier_state for bindings. */
811 mods_lookup = mods_depressed | mods_latched;
812 seat->modifier_state = 0;
813 if (mods_lookup & (1 << seat->xkb_info.ctrl_mod))
814 seat->modifier_state |= MODIFIER_CTRL;
815 if (mods_lookup & (1 << seat->xkb_info.alt_mod))
816 seat->modifier_state |= MODIFIER_ALT;
817 if (mods_lookup & (1 << seat->xkb_info.super_mod))
818 seat->modifier_state |= MODIFIER_SUPER;
819 if (mods_lookup & (1 << seat->xkb_info.shift_mod))
820 seat->modifier_state |= MODIFIER_SHIFT;
821
822 /* Finally, notify the compositor that LEDs have changed. */
823 if (xkb_state_led_index_is_active(seat->xkb_state.state,
824 seat->xkb_info.num_led))
825 leds |= LED_NUM_LOCK;
826 if (xkb_state_led_index_is_active(seat->xkb_state.state,
827 seat->xkb_info.caps_led))
828 leds |= LED_CAPS_LOCK;
829 if (xkb_state_led_index_is_active(seat->xkb_state.state,
830 seat->xkb_info.scroll_led))
831 leds |= LED_SCROLL_LOCK;
832 if (leds != seat->xkb_state.leds && seat->led_update)
833 seat->led_update(seat, leds);
834 seat->xkb_state.leds = leds;
835
836 if (changed) {
837 grab->interface->modifiers(grab,
838 serial,
839 keyboard->modifiers.mods_depressed,
840 keyboard->modifiers.mods_latched,
841 keyboard->modifiers.mods_locked,
842 keyboard->modifiers.group);
843 }
844}
845
846static void
847update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key,
848 enum wl_keyboard_key_state state)
849{
850 enum xkb_key_direction direction;
851
852 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
853 direction = XKB_KEY_DOWN;
854 else
855 direction = XKB_KEY_UP;
856
857 /* Offset the keycode by 8, as the evdev XKB rules reflect X's
858 * broken keycode system, which starts at 8. */
859 xkb_state_update_key(seat->xkb_state.state, key + 8, direction);
860
861 notify_modifiers(seat, serial);
862}
863
864WL_EXPORT void
865notify_key(struct weston_seat *seat, uint32_t time, uint32_t key,
866 enum wl_keyboard_key_state state,
867 enum weston_key_state_update update_state)
868{
869 struct weston_compositor *compositor = seat->compositor;
870 struct weston_keyboard *keyboard = &seat->keyboard;
871 struct weston_surface *focus =
872 (struct weston_surface *) keyboard->focus;
873 struct weston_keyboard_grab *grab = keyboard->grab;
874 uint32_t serial = wl_display_next_serial(compositor->wl_display);
875 uint32_t *k, *end;
876
877 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
878 if (compositor->ping_handler && focus)
879 compositor->ping_handler(focus, serial);
880
881 weston_compositor_idle_inhibit(compositor);
882 keyboard->grab_key = key;
883 keyboard->grab_time = time;
884 } else {
885 weston_compositor_idle_release(compositor);
886 }
887
888 end = keyboard->keys.data + keyboard->keys.size;
889 for (k = keyboard->keys.data; k < end; k++) {
890 if (*k == key) {
891 /* Ignore server-generated repeats. */
892 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
893 return;
894 *k = *--end;
895 }
896 }
897 keyboard->keys.size = (void *) end - keyboard->keys.data;
898 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
899 k = wl_array_add(&keyboard->keys, sizeof *k);
900 *k = key;
901 }
902
903 if (grab == &keyboard->default_grab ||
904 grab == &keyboard->input_method_grab) {
905 weston_compositor_run_key_binding(compositor, seat, time, key,
906 state);
907 grab = keyboard->grab;
908 }
909
910 grab->interface->key(grab, time, key, state);
911
912 if (update_state == STATE_UPDATE_AUTOMATIC) {
913 update_modifier_state(seat,
914 wl_display_get_serial(compositor->wl_display),
915 key,
916 state);
917 }
918}
919
920WL_EXPORT void
921notify_pointer_focus(struct weston_seat *seat, struct weston_output *output,
922 wl_fixed_t x, wl_fixed_t y)
923{
924 struct weston_compositor *compositor = seat->compositor;
925
926 if (output) {
927 move_pointer(seat, x, y);
928 compositor->focus = 1;
929 } else {
930 compositor->focus = 0;
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400931 /* FIXME: We should call weston_pointer_set_focus(seat,
Kristian Høgsbergb5e26102013-04-18 15:40:10 -0400932 * NULL) here, but somehow that breaks re-entry... */
933 }
934}
935
936static void
937destroy_device_saved_kbd_focus(struct wl_listener *listener, void *data)
938{
939 struct weston_seat *ws;
940
941 ws = container_of(listener, struct weston_seat,
942 saved_kbd_focus_listener);
943
944 ws->saved_kbd_focus = NULL;
945}
946
947WL_EXPORT void
948notify_keyboard_focus_in(struct weston_seat *seat, struct wl_array *keys,
949 enum weston_key_state_update update_state)
950{
951 struct weston_compositor *compositor = seat->compositor;
952 struct weston_keyboard *keyboard = seat->seat.keyboard;
953 struct wl_surface *surface;
954 uint32_t *k, serial;
955
956 serial = wl_display_next_serial(compositor->wl_display);
957 wl_array_copy(&keyboard->keys, keys);
958 wl_array_for_each(k, &keyboard->keys) {
959 weston_compositor_idle_inhibit(compositor);
960 if (update_state == STATE_UPDATE_AUTOMATIC)
961 update_modifier_state(seat, serial, *k,
962 WL_KEYBOARD_KEY_STATE_PRESSED);
963 }
964
965 /* Run key bindings after we've updated the state. */
966 wl_array_for_each(k, &keyboard->keys) {
967 weston_compositor_run_key_binding(compositor, seat, 0, *k,
968 WL_KEYBOARD_KEY_STATE_PRESSED);
969 }
970
971 surface = seat->saved_kbd_focus;
972
973 if (surface) {
974 wl_list_remove(&seat->saved_kbd_focus_listener.link);
975 weston_keyboard_set_focus(keyboard, surface);
976 seat->saved_kbd_focus = NULL;
977 }
978}
979
980WL_EXPORT void
981notify_keyboard_focus_out(struct weston_seat *seat)
982{
983 struct weston_compositor *compositor = seat->compositor;
984 struct weston_keyboard *keyboard = seat->seat.keyboard;
985 uint32_t *k, serial;
986
987 serial = wl_display_next_serial(compositor->wl_display);
988 wl_array_for_each(k, &keyboard->keys) {
989 weston_compositor_idle_release(compositor);
990 update_modifier_state(seat, serial, *k,
991 WL_KEYBOARD_KEY_STATE_RELEASED);
992 }
993
994 seat->modifier_state = 0;
995
996 if (keyboard->focus) {
997 seat->saved_kbd_focus = keyboard->focus;
998 seat->saved_kbd_focus_listener.notify =
999 destroy_device_saved_kbd_focus;
1000 wl_signal_add(&keyboard->focus->resource.destroy_signal,
1001 &seat->saved_kbd_focus_listener);
1002 }
1003
1004 weston_keyboard_set_focus(keyboard, NULL);
1005 /* FIXME: We really need keyboard grab cancel here to
1006 * let the grab shut down properly. As it is we leak
1007 * the grab data. */
1008 weston_keyboard_end_grab(keyboard);
1009}
1010
1011static void
1012touch_set_focus(struct weston_seat *ws, struct wl_surface *surface)
1013{
1014 struct wl_seat *seat = &ws->seat;
1015 struct wl_resource *resource;
1016
1017 if (seat->touch->focus == surface)
1018 return;
1019
1020 if (seat->touch->focus_resource)
1021 wl_list_remove(&seat->touch->focus_listener.link);
1022 seat->touch->focus = NULL;
1023 seat->touch->focus_resource = NULL;
1024
1025 if (surface) {
1026 resource =
Kristian Høgsberg80fb82d2013-05-06 21:49:55 -04001027 find_resource_for_surface(&seat->touch->resource_list,
1028 surface);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001029 if (!resource) {
1030 weston_log("couldn't find resource\n");
1031 return;
1032 }
1033
1034 seat->touch->focus = surface;
1035 seat->touch->focus_resource = resource;
1036 wl_signal_add(&resource->destroy_signal,
1037 &seat->touch->focus_listener);
1038 }
1039}
1040
1041/**
1042 * notify_touch - emulates button touches and notifies surfaces accordingly.
1043 *
1044 * It assumes always the correct cycle sequence until it gets here: touch_down
1045 * → touch_update → ... → touch_update → touch_end. The driver is responsible
1046 * for sending along such order.
1047 *
1048 */
1049WL_EXPORT void
1050notify_touch(struct weston_seat *seat, uint32_t time, int touch_id,
1051 wl_fixed_t x, wl_fixed_t y, int touch_type)
1052{
1053 struct weston_compositor *ec = seat->compositor;
Kristian Høgsberge329f362013-05-06 22:19:57 -04001054 struct weston_touch *touch = seat->seat.touch;
1055 struct weston_touch_grab *grab = touch->grab;
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001056 struct weston_surface *es;
1057 wl_fixed_t sx, sy;
1058
1059 /* Update grab's global coordinates. */
1060 touch->grab_x = x;
1061 touch->grab_y = y;
1062
1063 switch (touch_type) {
1064 case WL_TOUCH_DOWN:
1065 weston_compositor_idle_inhibit(ec);
1066
1067 seat->num_tp++;
1068
1069 /* the first finger down picks the surface, and all further go
1070 * to that surface for the remainder of the touch session i.e.
1071 * until all touch points are up again. */
1072 if (seat->num_tp == 1) {
1073 es = weston_compositor_pick_surface(ec, x, y, &sx, &sy);
1074 touch_set_focus(seat, &es->surface);
1075 } else if (touch->focus) {
1076 es = (struct weston_surface *) touch->focus;
1077 weston_surface_from_global_fixed(es, x, y, &sx, &sy);
1078 } else {
1079 /* Unexpected condition: We have non-initial touch but
1080 * there is no focused surface.
1081 */
1082 weston_log("touch event received with %d points down"
1083 "but no surface focused\n", seat->num_tp);
1084 return;
1085 }
1086
1087 grab->interface->down(grab, time, touch_id, sx, sy);
1088 break;
1089 case WL_TOUCH_MOTION:
1090 es = (struct weston_surface *) touch->focus;
1091 if (!es)
1092 break;
1093
1094 weston_surface_from_global_fixed(es, x, y, &sx, &sy);
1095 grab->interface->motion(grab, time, touch_id, sx, sy);
1096 break;
1097 case WL_TOUCH_UP:
1098 weston_compositor_idle_release(ec);
1099 seat->num_tp--;
1100
1101 grab->interface->up(grab, time, touch_id);
1102 if (seat->num_tp == 0)
1103 touch_set_focus(seat, NULL);
1104 break;
1105 }
1106}
1107
1108static void
1109pointer_handle_sprite_destroy(struct wl_listener *listener, void *data)
1110{
1111 struct weston_seat *seat = container_of(listener, struct weston_seat,
1112 sprite_destroy_listener);
1113
1114 seat->sprite = NULL;
1115}
1116
1117static void
1118pointer_cursor_surface_configure(struct weston_surface *es,
1119 int32_t dx, int32_t dy, int32_t width, int32_t height)
1120{
1121 struct weston_seat *seat = es->configure_private;
1122 int x, y;
1123
1124 if (width == 0)
1125 return;
1126
1127 assert(es == seat->sprite);
1128
1129 seat->hotspot_x -= dx;
1130 seat->hotspot_y -= dy;
1131
1132 x = wl_fixed_to_int(seat->seat.pointer->x) - seat->hotspot_x;
1133 y = wl_fixed_to_int(seat->seat.pointer->y) - seat->hotspot_y;
1134
1135 weston_surface_configure(seat->sprite, x, y,
1136 width, height);
1137
1138 empty_region(&es->pending.input);
1139
1140 if (!weston_surface_is_mapped(es)) {
1141 wl_list_insert(&es->compositor->cursor_layer.surface_list,
1142 &es->layer_link);
1143 weston_surface_update_transform(es);
1144 }
1145}
1146
1147static void
1148pointer_unmap_sprite(struct weston_seat *seat)
1149{
1150 if (weston_surface_is_mapped(seat->sprite))
1151 weston_surface_unmap(seat->sprite);
1152
1153 wl_list_remove(&seat->sprite_destroy_listener.link);
1154 seat->sprite->configure = NULL;
1155 seat->sprite->configure_private = NULL;
1156 seat->sprite = NULL;
1157}
1158
1159static void
1160pointer_set_cursor(struct wl_client *client, struct wl_resource *resource,
1161 uint32_t serial, struct wl_resource *surface_resource,
1162 int32_t x, int32_t y)
1163{
1164 struct weston_seat *seat = resource->data;
1165 struct weston_surface *surface = NULL;
1166
1167 if (surface_resource)
1168 surface = surface_resource->data;
1169
1170 if (seat->seat.pointer->focus == NULL)
1171 return;
1172 if (seat->seat.pointer->focus->resource.client != client)
1173 return;
1174 if (seat->seat.pointer->focus_serial - serial > UINT32_MAX / 2)
1175 return;
1176
1177 if (surface && surface != seat->sprite) {
1178 if (surface->configure) {
1179 wl_resource_post_error(&surface->surface.resource,
1180 WL_DISPLAY_ERROR_INVALID_OBJECT,
1181 "surface->configure already "
1182 "set");
1183 return;
1184 }
1185 }
1186
1187 if (seat->sprite)
1188 pointer_unmap_sprite(seat);
1189
1190 if (!surface)
1191 return;
1192
1193 wl_signal_add(&surface->surface.resource.destroy_signal,
1194 &seat->sprite_destroy_listener);
1195
1196 surface->configure = pointer_cursor_surface_configure;
1197 surface->configure_private = seat;
1198 seat->sprite = surface;
1199 seat->hotspot_x = x;
1200 seat->hotspot_y = y;
1201
1202 if (surface->buffer_ref.buffer)
1203 pointer_cursor_surface_configure(surface, 0, 0, weston_surface_buffer_width(surface),
1204 weston_surface_buffer_height(surface));
1205}
1206
1207static const struct wl_pointer_interface pointer_interface = {
1208 pointer_set_cursor
1209};
1210
1211static void
1212handle_drag_surface_destroy(struct wl_listener *listener, void *data)
1213{
1214 struct weston_seat *seat;
1215
1216 seat = container_of(listener, struct weston_seat,
1217 drag_surface_destroy_listener);
1218
1219 seat->drag_surface = NULL;
1220}
1221
1222static void
1223seat_get_pointer(struct wl_client *client, struct wl_resource *resource,
1224 uint32_t id)
1225{
1226 struct weston_seat *seat = resource->data;
1227 struct wl_resource *cr;
1228
1229 if (!seat->seat.pointer)
1230 return;
1231
1232 cr = wl_client_add_object(client, &wl_pointer_interface,
1233 &pointer_interface, id, seat);
1234 wl_list_insert(&seat->seat.pointer->resource_list, &cr->link);
1235 cr->destroy = unbind_resource;
1236
1237 if (seat->seat.pointer->focus &&
1238 seat->seat.pointer->focus->resource.client == client) {
1239 struct weston_surface *surface;
1240 wl_fixed_t sx, sy;
1241
1242 surface = (struct weston_surface *) seat->seat.pointer->focus;
1243 weston_surface_from_global_fixed(surface,
1244 seat->seat.pointer->x,
1245 seat->seat.pointer->y,
1246 &sx,
1247 &sy);
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001248 weston_pointer_set_focus(seat->seat.pointer,
1249 seat->seat.pointer->focus,
1250 sx,
1251 sy);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001252 }
1253}
1254
1255static void
1256seat_get_keyboard(struct wl_client *client, struct wl_resource *resource,
1257 uint32_t id)
1258{
1259 struct weston_seat *seat = resource->data;
1260 struct wl_resource *cr;
1261
1262 if (!seat->seat.keyboard)
1263 return;
1264
1265 cr = wl_client_add_object(client, &wl_keyboard_interface, NULL, id,
1266 seat);
1267 wl_list_insert(&seat->seat.keyboard->resource_list, &cr->link);
1268 cr->destroy = unbind_resource;
1269
1270 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
1271 seat->xkb_info.keymap_fd,
1272 seat->xkb_info.keymap_size);
1273
1274 if (seat->seat.keyboard->focus &&
1275 seat->seat.keyboard->focus->resource.client == client) {
1276 weston_keyboard_set_focus(seat->seat.keyboard,
1277 seat->seat.keyboard->focus);
1278 wl_data_device_set_keyboard_focus(&seat->seat);
1279 }
1280}
1281
1282static void
1283seat_get_touch(struct wl_client *client, struct wl_resource *resource,
1284 uint32_t id)
1285{
1286 struct weston_seat *seat = resource->data;
1287 struct wl_resource *cr;
1288
1289 if (!seat->seat.touch)
1290 return;
1291
1292 cr = wl_client_add_object(client, &wl_touch_interface, NULL, id, seat);
1293 wl_list_insert(&seat->seat.touch->resource_list, &cr->link);
1294 cr->destroy = unbind_resource;
1295}
1296
1297static const struct wl_seat_interface seat_interface = {
1298 seat_get_pointer,
1299 seat_get_keyboard,
1300 seat_get_touch,
1301};
1302
1303static void
1304bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
1305{
1306 struct wl_seat *seat = data;
1307 struct wl_resource *resource;
1308 enum wl_seat_capability caps = 0;
1309
1310 resource = wl_client_add_object(client, &wl_seat_interface,
1311 &seat_interface, id, data);
1312 wl_list_insert(&seat->base_resource_list, &resource->link);
1313 resource->destroy = unbind_resource;
1314
1315 if (seat->pointer)
1316 caps |= WL_SEAT_CAPABILITY_POINTER;
1317 if (seat->keyboard)
1318 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
1319 if (seat->touch)
1320 caps |= WL_SEAT_CAPABILITY_TOUCH;
1321
1322 wl_seat_send_capabilities(resource, caps);
1323}
1324
1325static void
1326device_handle_new_drag_icon(struct wl_listener *listener, void *data)
1327{
1328 struct weston_seat *seat;
1329
1330 seat = container_of(listener, struct weston_seat,
1331 new_drag_icon_listener);
1332
1333 weston_seat_update_drag_surface(seat, 0, 0);
1334}
1335
1336int
1337weston_compositor_xkb_init(struct weston_compositor *ec,
1338 struct xkb_rule_names *names)
1339{
1340 if (ec->xkb_context == NULL) {
1341 ec->xkb_context = xkb_context_new(0);
1342 if (ec->xkb_context == NULL) {
1343 weston_log("failed to create XKB context\n");
1344 return -1;
1345 }
1346 }
1347
1348 if (names)
1349 ec->xkb_names = *names;
1350 if (!ec->xkb_names.rules)
1351 ec->xkb_names.rules = strdup("evdev");
1352 if (!ec->xkb_names.model)
1353 ec->xkb_names.model = strdup("pc105");
1354 if (!ec->xkb_names.layout)
1355 ec->xkb_names.layout = strdup("us");
1356
1357 return 0;
1358}
1359
1360static void xkb_info_destroy(struct weston_xkb_info *xkb_info)
1361{
1362 if (xkb_info->keymap)
1363 xkb_map_unref(xkb_info->keymap);
1364
1365 if (xkb_info->keymap_area)
1366 munmap(xkb_info->keymap_area, xkb_info->keymap_size);
1367 if (xkb_info->keymap_fd >= 0)
1368 close(xkb_info->keymap_fd);
1369}
1370
1371void
1372weston_compositor_xkb_destroy(struct weston_compositor *ec)
1373{
1374 free((char *) ec->xkb_names.rules);
1375 free((char *) ec->xkb_names.model);
1376 free((char *) ec->xkb_names.layout);
1377 free((char *) ec->xkb_names.variant);
1378 free((char *) ec->xkb_names.options);
1379
1380 xkb_info_destroy(&ec->xkb_info);
1381 xkb_context_unref(ec->xkb_context);
1382}
1383
1384static int
1385weston_xkb_info_new_keymap(struct weston_xkb_info *xkb_info)
1386{
1387 char *keymap_str;
1388
1389 xkb_info->shift_mod = xkb_map_mod_get_index(xkb_info->keymap,
1390 XKB_MOD_NAME_SHIFT);
1391 xkb_info->caps_mod = xkb_map_mod_get_index(xkb_info->keymap,
1392 XKB_MOD_NAME_CAPS);
1393 xkb_info->ctrl_mod = xkb_map_mod_get_index(xkb_info->keymap,
1394 XKB_MOD_NAME_CTRL);
1395 xkb_info->alt_mod = xkb_map_mod_get_index(xkb_info->keymap,
1396 XKB_MOD_NAME_ALT);
1397 xkb_info->mod2_mod = xkb_map_mod_get_index(xkb_info->keymap, "Mod2");
1398 xkb_info->mod3_mod = xkb_map_mod_get_index(xkb_info->keymap, "Mod3");
1399 xkb_info->super_mod = xkb_map_mod_get_index(xkb_info->keymap,
1400 XKB_MOD_NAME_LOGO);
1401 xkb_info->mod5_mod = xkb_map_mod_get_index(xkb_info->keymap, "Mod5");
1402
1403 xkb_info->num_led = xkb_map_led_get_index(xkb_info->keymap,
1404 XKB_LED_NAME_NUM);
1405 xkb_info->caps_led = xkb_map_led_get_index(xkb_info->keymap,
1406 XKB_LED_NAME_CAPS);
1407 xkb_info->scroll_led = xkb_map_led_get_index(xkb_info->keymap,
1408 XKB_LED_NAME_SCROLL);
1409
1410 keymap_str = xkb_map_get_as_string(xkb_info->keymap);
1411 if (keymap_str == NULL) {
1412 weston_log("failed to get string version of keymap\n");
1413 return -1;
1414 }
1415 xkb_info->keymap_size = strlen(keymap_str) + 1;
1416
1417 xkb_info->keymap_fd = os_create_anonymous_file(xkb_info->keymap_size);
1418 if (xkb_info->keymap_fd < 0) {
1419 weston_log("creating a keymap file for %lu bytes failed: %m\n",
1420 (unsigned long) xkb_info->keymap_size);
1421 goto err_keymap_str;
1422 }
1423
1424 xkb_info->keymap_area = mmap(NULL, xkb_info->keymap_size,
1425 PROT_READ | PROT_WRITE,
1426 MAP_SHARED, xkb_info->keymap_fd, 0);
1427 if (xkb_info->keymap_area == MAP_FAILED) {
1428 weston_log("failed to mmap() %lu bytes\n",
1429 (unsigned long) xkb_info->keymap_size);
1430 goto err_dev_zero;
1431 }
1432 strcpy(xkb_info->keymap_area, keymap_str);
1433 free(keymap_str);
1434
1435 return 0;
1436
1437err_dev_zero:
1438 close(xkb_info->keymap_fd);
1439 xkb_info->keymap_fd = -1;
1440err_keymap_str:
1441 free(keymap_str);
1442 return -1;
1443}
1444
1445static int
1446weston_compositor_build_global_keymap(struct weston_compositor *ec)
1447{
1448 if (ec->xkb_info.keymap != NULL)
1449 return 0;
1450
1451 ec->xkb_info.keymap = xkb_map_new_from_names(ec->xkb_context,
1452 &ec->xkb_names,
1453 0);
1454 if (ec->xkb_info.keymap == NULL) {
1455 weston_log("failed to compile global XKB keymap\n");
1456 weston_log(" tried rules %s, model %s, layout %s, variant %s, "
1457 "options %s\n",
1458 ec->xkb_names.rules, ec->xkb_names.model,
1459 ec->xkb_names.layout, ec->xkb_names.variant,
1460 ec->xkb_names.options);
1461 return -1;
1462 }
1463
1464 if (weston_xkb_info_new_keymap(&ec->xkb_info) < 0)
1465 return -1;
1466
1467 return 0;
1468}
1469
1470WL_EXPORT int
1471weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
1472{
1473 if (seat->has_keyboard)
1474 return 0;
1475
1476 if (keymap != NULL) {
1477 seat->xkb_info.keymap = xkb_map_ref(keymap);
1478 if (weston_xkb_info_new_keymap(&seat->xkb_info) < 0)
1479 return -1;
1480 } else {
1481 if (weston_compositor_build_global_keymap(seat->compositor) < 0)
1482 return -1;
1483 seat->xkb_info = seat->compositor->xkb_info;
1484 seat->xkb_info.keymap = xkb_map_ref(seat->xkb_info.keymap);
1485 }
1486
1487 seat->xkb_state.state = xkb_state_new(seat->xkb_info.keymap);
1488 if (seat->xkb_state.state == NULL) {
1489 weston_log("failed to initialise XKB state\n");
1490 return -1;
1491 }
1492
1493 seat->xkb_state.leds = 0;
1494
1495 weston_keyboard_init(&seat->keyboard);
1496 wl_seat_set_keyboard(&seat->seat, &seat->keyboard);
1497
1498 seat->has_keyboard = 1;
1499
1500 return 0;
1501}
1502
1503WL_EXPORT void
1504weston_seat_init_pointer(struct weston_seat *seat)
1505{
1506 if (seat->has_pointer)
1507 return;
1508
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -04001509 weston_pointer_init(&seat->pointer);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001510 wl_seat_set_pointer(&seat->seat, &seat->pointer);
1511
1512 seat->has_pointer = 1;
1513}
1514
1515WL_EXPORT void
1516weston_seat_init_touch(struct weston_seat *seat)
1517{
1518 if (seat->has_touch)
1519 return;
1520
Kristian Høgsberge329f362013-05-06 22:19:57 -04001521 weston_touch_init(&seat->touch);
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001522 wl_seat_set_touch(&seat->seat, &seat->touch);
1523
1524 seat->has_touch = 1;
1525}
1526
1527WL_EXPORT void
1528weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec)
1529{
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04001530 memset(seat, 0, sizeof *seat);
1531
1532 wl_signal_init(&seat->seat.destroy_signal);
1533
1534 seat->seat.selection_data_source = NULL;
1535 wl_list_init(&seat->seat.base_resource_list);
1536 wl_signal_init(&seat->seat.selection_signal);
1537 wl_list_init(&seat->seat.drag_resource_list);
1538 wl_signal_init(&seat->seat.drag_icon_signal);
1539
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001540 seat->has_pointer = 0;
1541 seat->has_keyboard = 0;
1542 seat->has_touch = 0;
1543
1544 wl_display_add_global(ec->wl_display, &wl_seat_interface, seat,
1545 bind_seat);
1546
1547 seat->sprite = NULL;
1548 seat->sprite_destroy_listener.notify = pointer_handle_sprite_destroy;
1549
1550 seat->compositor = ec;
1551 seat->hotspot_x = 16;
1552 seat->hotspot_y = 16;
1553 seat->modifier_state = 0;
1554 seat->num_tp = 0;
1555
1556 seat->drag_surface_destroy_listener.notify =
1557 handle_drag_surface_destroy;
1558
1559 wl_list_insert(ec->seat_list.prev, &seat->link);
1560
1561 seat->new_drag_icon_listener.notify = device_handle_new_drag_icon;
1562 wl_signal_add(&seat->seat.drag_icon_signal,
1563 &seat->new_drag_icon_listener);
1564
1565 clipboard_create(seat);
1566
1567 wl_signal_init(&seat->destroy_signal);
1568 wl_signal_emit(&ec->seat_created_signal, seat);
1569}
1570
1571WL_EXPORT void
1572weston_seat_release(struct weston_seat *seat)
1573{
1574 wl_list_remove(&seat->link);
1575 /* The global object is destroyed at wl_display_destroy() time. */
1576
1577 if (seat->sprite)
1578 pointer_unmap_sprite(seat);
1579
1580 if (seat->xkb_state.state != NULL)
1581 xkb_state_unref(seat->xkb_state.state);
1582 xkb_info_destroy(&seat->xkb_info);
1583
Kristian Høgsberg4a2a2742013-05-06 22:24:50 -04001584 wl_signal_emit(&seat->seat.destroy_signal, seat);
1585
1586 if (seat->seat.pointer)
1587 weston_pointer_release(seat->seat.pointer);
1588 if (seat->seat.keyboard)
1589 weston_keyboard_release(seat->seat.keyboard);
1590 if (seat->seat.touch)
1591 weston_touch_release(seat->seat.touch);
1592
Kristian Høgsbergb5e26102013-04-18 15:40:10 -04001593 wl_signal_emit(&seat->destroy_signal, seat);
1594}
1595
1596static void
1597drag_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height)
1598{
1599 empty_region(&es->pending.input);
1600
1601 weston_surface_configure(es,
1602 es->geometry.x + sx, es->geometry.y + sy,
1603 width, height);
1604}
1605
1606static int
1607device_setup_new_drag_surface(struct weston_seat *ws,
1608 struct weston_surface *surface)
1609{
1610 struct wl_seat *seat = &ws->seat;
1611
1612 if (surface->configure) {
1613 wl_resource_post_error(&surface->surface.resource,
1614 WL_DISPLAY_ERROR_INVALID_OBJECT,
1615 "surface->configure already set");
1616 return 0;
1617 }
1618
1619 ws->drag_surface = surface;
1620
1621 weston_surface_set_position(ws->drag_surface,
1622 wl_fixed_to_double(seat->pointer->x),
1623 wl_fixed_to_double(seat->pointer->y));
1624
1625 surface->configure = drag_surface_configure;
1626
1627 wl_signal_add(&surface->surface.resource.destroy_signal,
1628 &ws->drag_surface_destroy_listener);
1629
1630 return 1;
1631}
1632
1633static void
1634device_release_drag_surface(struct weston_seat *seat)
1635{
1636 if (weston_surface_is_mapped(seat->drag_surface))
1637 weston_surface_unmap(seat->drag_surface);
1638
1639 seat->drag_surface->configure = NULL;
1640 empty_region(&seat->drag_surface->pending.input);
1641 wl_list_remove(&seat->drag_surface_destroy_listener.link);
1642 seat->drag_surface = NULL;
1643}
1644
1645static void
1646device_map_drag_surface(struct weston_seat *seat)
1647{
1648 struct wl_list *list;
1649
1650 if (weston_surface_is_mapped(seat->drag_surface) ||
1651 !seat->drag_surface->buffer_ref.buffer)
1652 return;
1653
1654 if (seat->sprite && weston_surface_is_mapped(seat->sprite))
1655 list = &seat->sprite->layer_link;
1656 else
1657 list = &seat->compositor->cursor_layer.surface_list;
1658
1659 wl_list_insert(list, &seat->drag_surface->layer_link);
1660 weston_surface_update_transform(seat->drag_surface);
1661 empty_region(&seat->drag_surface->input);
1662}
1663
1664static void
1665weston_seat_update_drag_surface(struct weston_seat *seat,
1666 int dx, int dy)
1667{
1668 int surface_changed = 0;
1669
1670 if (!seat->drag_surface && !seat->seat.drag_surface)
1671 return;
1672
1673 if (seat->drag_surface && seat->seat.drag_surface &&
1674 (&seat->drag_surface->surface.resource !=
1675 &seat->seat.drag_surface->resource))
1676 /* between calls to this funcion we got a new drag_surface */
1677 surface_changed = 1;
1678
1679 if (!seat->seat.drag_surface || surface_changed) {
1680 device_release_drag_surface(seat);
1681 if (!surface_changed)
1682 return;
1683 }
1684
1685 if (!seat->drag_surface || surface_changed) {
1686 struct weston_surface *surface = (struct weston_surface *)
1687 seat->seat.drag_surface;
1688 if (!device_setup_new_drag_surface(seat, surface))
1689 return;
1690 }
1691
1692 /* the client may not have attached a buffer to the drag surface
1693 * when we setup it up, so check if map is needed on every update */
1694 device_map_drag_surface(seat);
1695
1696 if (!dx && !dy)
1697 return;
1698
1699 weston_surface_set_position(seat->drag_surface,
1700 seat->drag_surface->geometry.x + wl_fixed_to_double(dx),
1701 seat->drag_surface->geometry.y + wl_fixed_to_double(dy));
1702}
1703
1704WL_EXPORT void
1705weston_compositor_update_drag_surfaces(struct weston_compositor *compositor)
1706{
1707 struct weston_seat *seat;
1708
1709 wl_list_for_each(seat, &compositor->seat_list, link)
1710 weston_seat_update_drag_surface(seat, 0, 0);
1711}