6 #include "seat_private.h"
8 static const struct ds_touch_grab_interface default_touch_grab_iface;
9 static const struct wl_touch_interface touch_impl;
11 static void touch_handle_resource_destroy(struct wl_resource *resource);
12 static struct ds_touch_point *touch_point_create(struct ds_seat *seat,
13 int32_t touch_id, struct ds_surface *surface, double sx, double sy);
14 static void touch_point_destroy(struct ds_touch_point *point);
15 static void touch_point_clear_focus(struct ds_touch_point *point);
16 static struct ds_touch_point *seat_find_touch_point(struct ds_seat *seat,
18 static int seat_touch_num_points(struct ds_seat *seat);
21 ds_seat_touch_notify_down(struct ds_seat *seat, struct ds_surface *surface,
22 uint32_t time_msec, int32_t touch_id, double sx, double sy)
24 struct ds_seat_touch_grab *grab = seat->touch.grab;
25 struct ds_touch_point *point;
29 // What if ds_touch_point is already exist associated with given touch_id?
30 point = touch_point_create(seat, touch_id, surface, sx, sy);
32 ds_err("Could not create touch point");
36 serial = grab->iface->down(grab, time_msec, point);
38 touch_point_destroy(point);
42 if (serial && seat_touch_num_points(seat) == 1) {
43 seat->touch.grab_serial = serial;
44 seat->touch.grab_id = touch_id;
51 ds_seat_touch_notify_up(struct ds_seat *seat, uint32_t time_msec,
54 struct ds_seat_touch_grab *grab = seat->touch.grab;
55 struct ds_touch_point *point;
57 clock_gettime(CLOCK_MONOTONIC, &seat->last_event);
59 point = seat_find_touch_point(seat, touch_id);
63 grab->iface->up(grab, time_msec, point);
65 touch_point_destroy(point);
69 ds_seat_touch_notify_motion(struct ds_seat *seat, uint32_t time_msec,
70 int32_t touch_id, double sx, double sy)
72 struct ds_seat_touch_grab *grab = seat->touch.grab;
73 struct ds_touch_point *point;
75 clock_gettime(CLOCK_MONOTONIC, &seat->last_event);
77 point = seat_find_touch_point(seat, touch_id);
84 grab->iface->motion(grab, time_msec, point);
88 ds_seat_touch_notify_frame(struct ds_seat *seat)
90 struct ds_seat_touch_grab *grab = seat->touch.grab;
92 if (grab->iface->frame)
93 grab->iface->frame(grab);
97 ds_seat_touch_add_grab_start_listener(struct ds_seat *seat,
98 struct wl_listener *listener)
100 wl_signal_add(&seat->events.touch_grab_begin, listener);
104 ds_seat_touch_end_grab_start_listener(struct ds_seat *seat,
105 struct wl_listener *listener)
107 wl_signal_add(&seat->events.touch_grab_end, listener);
111 ds_seat_touch_send_down(struct ds_seat *seat, struct ds_surface *surface,
112 uint32_t time_msec, int32_t touch_id, double sx, double sy)
114 struct ds_touch_point *point;
115 struct wl_resource *resource;
118 point = seat_find_touch_point(seat, touch_id);
120 ds_err("Got touch down for unknown touch point");
124 serial = wl_display_next_serial(seat->display);
125 wl_resource_for_each(resource, &point->seat_client->touches) {
126 wl_touch_send_down(resource, serial, time_msec,
127 ds_surface_get_wl_resource(surface), touch_id,
128 wl_fixed_from_double(sx), wl_fixed_from_double(sy));
131 point->seat_client->needs_touch_frame = true;
137 ds_seat_touch_send_up(struct ds_seat *seat, uint32_t time_msec,
140 struct ds_touch_point *point;
141 struct wl_resource *resource;
144 point = seat_find_touch_point(seat, touch_id);
146 ds_err("Got touch up for unknown touch point");
150 serial = wl_display_next_serial(seat->display);
151 wl_resource_for_each(resource, &point->seat_client->touches)
152 wl_touch_send_up(resource, serial, time_msec, touch_id);
154 point->seat_client->needs_touch_frame = true;
158 ds_seat_touch_send_motion(struct ds_seat *seat, uint32_t time_msec,
159 int32_t touch_id, double sx, double sy)
161 struct ds_touch_point *point;
162 struct wl_resource *resource;
164 point = seat_find_touch_point(seat, touch_id);
166 ds_err("Got touch motion for unknown touch point");
170 wl_resource_for_each(resource, &point->seat_client->touches) {
171 wl_touch_send_motion(resource, time_msec, touch_id,
172 wl_fixed_from_double(sx), wl_fixed_from_double(sy));
175 point->seat_client->needs_touch_frame = true;
179 ds_seat_touch_send_frame(struct ds_seat *seat)
181 struct ds_seat_client *seat_client;
182 struct wl_resource *resource;
184 wl_list_for_each(seat_client, &seat->clients, link) {
185 if (!seat_client->needs_touch_frame)
188 wl_resource_for_each(resource, &seat_client->touches)
189 wl_touch_send_frame(resource);
191 seat_client->needs_touch_frame = false;
196 seat_touch_init(struct ds_seat *seat)
198 struct ds_seat_touch *touch = &seat->touch;
199 struct ds_seat_touch_grab *grab;
201 grab = calloc(1, sizeof *grab);
205 grab->iface = &default_touch_grab_iface;
208 touch->default_grab = grab;
212 wl_list_init(&touch->touch_points);
218 seat_touch_finish(struct ds_seat *seat)
220 struct ds_seat_touch *touch = &seat->touch;
221 struct ds_touch_point *point;
223 wl_list_for_each(point, &touch->touch_points, link)
224 touch_point_clear_focus(point);
226 free(touch->default_grab);
230 seat_client_add_touch_resource(struct ds_seat_client *seat_client,
231 uint32_t version, uint32_t id)
233 struct wl_resource *resource;
235 resource = wl_resource_create(seat_client->wl_client,
236 &wl_touch_interface, version, id);
238 wl_client_post_no_memory(seat_client->wl_client);
242 wl_resource_set_implementation(resource, &touch_impl, seat_client,
243 touch_handle_resource_destroy);
245 wl_list_insert(&seat_client->touches, wl_resource_get_link(resource));
247 if (!(seat_client->seat->capabilities & WL_SEAT_CAPABILITY_TOUCH))
248 wl_resource_set_user_data(resource, NULL);
252 seat_client_remove_all_touch_resources(struct ds_seat_client *seat_client)
254 struct wl_resource *resource, *tmp;
256 wl_resource_for_each_safe(resource, tmp, &seat_client->touches) {
257 wl_list_remove(wl_resource_get_link(resource));
258 wl_resource_set_user_data(resource, NULL);
263 default_touch_grab_iface_down(struct ds_seat_touch_grab *grab,
264 uint32_t time_msec, struct ds_touch_point *point)
266 return ds_seat_touch_send_down(grab->seat, point->surface, time_msec,
267 point->touch_id, point->sx, point->sy);
271 default_touch_grab_iface_up(struct ds_seat_touch_grab *grab,
272 uint32_t time_msec, struct ds_touch_point *point)
274 ds_seat_touch_send_up(grab->seat, time_msec, point->touch_id);
278 default_touch_grab_iface_motion(struct ds_seat_touch_grab *grab,
279 uint32_t time_msec, struct ds_touch_point *point)
281 if (!point->focused_surface || point->focused_surface == point->surface) {
282 ds_seat_touch_send_motion(grab->seat, time_msec, point->touch_id,
283 point->sx, point->sy);
288 default_touch_grab_iface_enter(struct ds_seat_touch_grab *grab,
289 uint32_t time_msec, struct ds_touch_point *point)
291 // not handled by default
295 default_touch_grab_iface_frame(struct ds_seat_touch_grab *grab)
297 ds_seat_touch_send_frame(grab->seat);
301 default_touch_grab_iface_cancel(struct ds_seat_touch_grab *grab)
303 // cannot be cancelled
306 static const struct ds_touch_grab_interface default_touch_grab_iface = {
307 .down = default_touch_grab_iface_down,
308 .up = default_touch_grab_iface_up,
309 .motion = default_touch_grab_iface_motion,
310 .enter = default_touch_grab_iface_enter,
311 .frame = default_touch_grab_iface_frame,
312 .cancel = default_touch_grab_iface_cancel,
316 touch_handle_release(struct wl_client *client, struct wl_resource *resource)
318 wl_resource_destroy(resource);
321 static const struct wl_touch_interface touch_impl =
323 .release = touch_handle_release,
327 touch_handle_resource_destroy(struct wl_resource *resource)
329 if (!wl_resource_get_user_data(resource))
332 wl_list_remove(wl_resource_get_link(resource));
336 touch_point_handle_surface_destroy(struct wl_listener *listener, void *data)
338 struct ds_touch_point *point;
340 point = wl_container_of(listener, point, surface_destroy);
341 point->surface = NULL;
342 wl_list_remove(&point->surface_destroy.link);
343 wl_list_init(&point->surface_destroy.link);
347 touch_point_handle_client_destroy(struct wl_listener *listener, void *data)
349 struct ds_touch_point *point;
351 point = wl_container_of(listener, point, surface_destroy);
352 touch_point_destroy(point);
355 static struct ds_touch_point *
356 touch_point_create(struct ds_seat *seat, int32_t touch_id,
357 struct ds_surface *surface, double sx, double sy)
359 struct ds_touch_point *point;
360 struct ds_seat_client *seat_client;
361 struct wl_client *wl_client;
363 wl_client = wl_resource_get_client(ds_surface_get_wl_resource(surface));
364 seat_client = seat_client_for_wl_client(seat, wl_client);
365 if (!seat_client || wl_list_empty(&seat_client->touches))
368 point = calloc(1, sizeof *point);
372 point->touch_id = touch_id;
373 point->surface = surface;
374 point->seat_client = seat_client;
378 wl_signal_init(&point->events.destroy);
380 point->surface_destroy.notify = touch_point_handle_surface_destroy;
381 ds_surface_add_destroy_listener(surface, &point->surface_destroy);
383 point->client_destroy.notify = touch_point_handle_client_destroy;
384 wl_signal_add(&seat_client->events.destroy, &point->client_destroy);
386 wl_list_insert(&seat->touch.touch_points, &point->link);
392 touch_point_destroy(struct ds_touch_point *point)
394 wl_signal_emit(&point->events.destroy, point);
396 touch_point_clear_focus(point);
398 wl_list_remove(&point->surface_destroy.link);
399 wl_list_remove(&point->client_destroy.link);
400 wl_list_remove(&point->link);
405 touch_point_clear_focus(struct ds_touch_point *point)
407 if (!point->focused_surface)
410 wl_list_remove(&point->focused_surface_destroy.link);
411 point->focused_client = NULL;
412 point->focused_surface = NULL;
415 static struct ds_touch_point *seat_find_touch_point(struct ds_seat *seat,
418 struct ds_touch_point *point;
420 wl_list_for_each(point, &seat->touch.touch_points, link) {
421 if (point->touch_id == touch_id)
429 seat_touch_num_points(struct ds_seat *seat)
431 return wl_list_length(&seat->touch.touch_points);