3 #define _POSIX_C_SOURCE 200809L
9 #include "seat_private.h"
11 #define SEAT_VERSION 7
13 static void seat_handle_bind(struct wl_client *wl_client, void *data,
14 uint32_t version, uint32_t id);
15 static void seat_handle_display_destroy(struct wl_listener *listener,
17 static void seat_destroy(struct ds_seat *seat);
18 static struct ds_seat_client *seat_client_create(struct ds_seat *seat,
19 struct wl_client *wl_client);
20 static void seat_client_destroy(struct ds_seat_client *seat_client);
22 seat_client_send_capabilities(struct ds_seat_client *seat_client);
23 static void seat_client_send_name(struct ds_seat_client *seat_client);
25 WL_EXPORT struct ds_seat *
26 ds_seat_create(struct wl_display *display, const char *name)
30 seat = calloc(1, sizeof *seat);
34 if (!seat_pointer_init(seat)) {
35 ds_err("Failed to initialize pointer for seat(%s)", name);
39 if (!seat_keyboard_init(seat)) {
40 ds_err("Failed to initialize keyboard for seat(%s)", name);
44 if (!seat_touch_init(seat)) {
45 ds_err("Failed to initialize touch for seat(%s)", name);
49 seat->global = wl_global_create(display, &wl_seat_interface,
50 SEAT_VERSION, seat, seat_handle_bind);
52 ds_err("Failed to create wl_global for seat(%s)", name);
56 seat->display = display;
57 seat->name = strdup(name);
59 wl_list_init(&seat->clients);
61 wl_signal_init(&seat->events.destroy);
62 wl_signal_init(&seat->events.pointer_grab_begin);
63 wl_signal_init(&seat->events.pointer_grab_end);
64 wl_signal_init(&seat->events.keyboard_grab_begin);
65 wl_signal_init(&seat->events.keyboard_grab_end);
66 wl_signal_init(&seat->events.touch_grab_begin);
67 wl_signal_init(&seat->events.touch_grab_end);
69 seat->display_destroy.notify = seat_handle_display_destroy;
70 wl_display_add_destroy_listener(display, &seat->display_destroy);
75 seat_touch_finish(seat);
77 seat_keyboard_finish(seat);
79 seat_pointer_finish(seat);
87 ds_seat_destroy(struct ds_seat *seat)
93 ds_seat_set_capabilities(struct ds_seat *seat,
94 enum wl_seat_capability capabilities)
96 struct ds_seat_client *seat_client;
98 if (capabilities == seat->capabilities)
101 seat->capabilities = capabilities;
102 seat->accumulated_capabilities |= capabilities;
104 wl_list_for_each(seat_client, &seat->clients, link) {
105 if (!(capabilities & WL_SEAT_CAPABILITY_POINTER)) {
106 seat_client_remove_all_pointer_resources(seat_client);
108 if (!(capabilities & WL_SEAT_CAPABILITY_KEYBOARD)) {
109 seat_client_remove_all_keyboard_resources(seat_client);
111 if (!(capabilities & WL_SEAT_CAPABILITY_TOUCH)) {
112 seat_client_remove_all_touch_resources(seat_client);
115 seat_client_send_capabilities(seat_client);
120 ds_seat_set_name(struct ds_seat *seat, const char *name)
122 struct ds_seat_client *seat_client;
125 seat->name = strdup(name);
127 wl_list_for_each(seat_client, &seat->clients, link) {
128 seat_client_send_name(seat_client);
133 ds_seat_add_destroy_listener(struct ds_seat *seat,
134 struct wl_listener *listener)
136 wl_signal_add(&seat->events.destroy, listener);
139 struct ds_seat_client *
140 seat_client_for_wl_client(struct ds_seat *seat, struct wl_client *wl_client)
142 struct ds_seat_client *seat_client;
144 wl_list_for_each(seat_client, &seat->clients, link) {
145 if (seat_client->wl_client == wl_client)
152 static struct ds_seat_client *
153 ds_seat_client_get_or_create(struct ds_seat *seat, struct wl_client *wl_client)
155 struct ds_seat_client *seat_client;
157 seat_client = seat_client_for_wl_client(seat, wl_client);
159 seat_client = seat_client_create(seat, wl_client);
163 wl_list_insert(&seat->clients, &seat_client->link);
170 seat_handle_get_pointer(struct wl_client *wl_client,
171 struct wl_resource *resource, uint32_t id)
173 struct ds_seat_client *seat_client;
175 seat_client = wl_resource_get_user_data(resource);
179 if (!(seat_client->seat->accumulated_capabilities &
180 WL_SEAT_CAPABILITY_POINTER)) {
181 #ifdef HAVE_WL_SEAT_ERROR_MISSING_CAPABILITY
182 wl_resource_post_error(resource, WL_SEAT_ERROR_MISSING_CAPABILITY,
183 "wl_seat.get_pointer called when no "
184 "pointer capability has existed");
189 seat_client_add_pointer_resource(seat_client,
190 wl_resource_get_version(resource), id);
194 seat_handle_get_keyboard(struct wl_client *wl_client,
195 struct wl_resource *resource, uint32_t id)
197 struct ds_seat_client *seat_client;
199 seat_client = wl_resource_get_user_data(resource);
203 if (!(seat_client->seat->accumulated_capabilities &
204 WL_SEAT_CAPABILITY_KEYBOARD)) {
205 #ifdef HAVE_WL_SEAT_ERROR_MISSING_CAPABILITY
206 wl_resource_post_error(resource, WL_SEAT_ERROR_MISSING_CAPABILITY,
207 "wl_seat.get_keyboard called when no "
208 "keyboard capability has existed");
213 seat_client_add_keyboard_resource(seat_client,
214 wl_resource_get_version(resource), id);
218 seat_handle_get_touch(struct wl_client *wl_client,
219 struct wl_resource *resource, uint32_t id)
221 struct ds_seat_client *seat_client;
223 seat_client = wl_resource_get_user_data(resource);
227 if (!(seat_client->seat->accumulated_capabilities &
228 WL_SEAT_CAPABILITY_TOUCH)) {
229 #ifdef HAVE_WL_SEAT_ERROR_MISSING_CAPABILITY
230 wl_resource_post_error(resource, WL_SEAT_ERROR_MISSING_CAPABILITY,
231 "wl_seat.get_touch called when no "
232 "touch capability has existed");
237 seat_client_add_touch_resource(seat_client,
238 wl_resource_get_version(resource), id);
242 seat_handle_release(struct wl_client *wl_client, struct wl_resource *resource)
244 wl_resource_destroy(resource);
247 static const struct wl_seat_interface seat_impl =
249 .get_pointer = seat_handle_get_pointer,
250 .get_keyboard = seat_handle_get_keyboard,
251 .get_touch = seat_handle_get_touch,
252 .release = seat_handle_release,
256 seat_client_handle_resource_destroy(struct wl_resource *resource)
258 struct ds_seat_client *seat_client;
260 seat_client = wl_resource_get_user_data(resource);
264 wl_list_remove(wl_resource_get_link(resource));
265 if (!wl_list_empty(&seat_client->resources))
268 seat_client_destroy(seat_client);
272 seat_handle_bind(struct wl_client *wl_client, void *data, uint32_t version,
275 struct ds_seat *seat = data;
276 struct ds_seat_client *seat_client;
277 struct wl_resource *resource;
279 resource = wl_resource_create(wl_client, &wl_seat_interface, version, id);
281 wl_client_post_no_memory(wl_client);
285 seat_client = ds_seat_client_get_or_create(seat, wl_client);
287 wl_resource_destroy(resource);
288 wl_client_post_no_memory(wl_client);
292 wl_resource_set_implementation(resource, &seat_impl,
293 seat_client, seat_client_handle_resource_destroy);
295 wl_list_insert(&seat_client->resources, wl_resource_get_link(resource));
297 wl_seat_send_capabilities(resource, seat->capabilities);
299 if (version >= WL_SEAT_NAME_SINCE_VERSION)
300 wl_seat_send_name(resource, seat->name);
304 seat_handle_display_destroy(struct wl_listener *listener, void *data)
306 struct ds_seat *seat;
308 seat = wl_container_of(listener, seat, display_destroy);
313 seat_destroy(struct ds_seat *seat)
315 struct ds_seat_client *seat_client, *tmp;
316 struct wl_resource *resource, *next;
318 wl_signal_emit(&seat->events.destroy, seat);
320 wl_list_remove(&seat->display_destroy.link);
322 wl_list_for_each_safe(seat_client, tmp, &seat->clients, link) {
323 wl_resource_for_each_safe(resource, next, &seat_client->resources) {
324 wl_list_remove(wl_resource_get_link(resource));
325 wl_resource_set_user_data(resource, NULL);
327 seat_client_destroy(seat_client);
330 seat_pointer_finish(seat);
331 seat_keyboard_finish(seat);
332 seat_touch_finish(seat);
334 wl_global_destroy(seat->global);
339 static struct ds_seat_client *
340 seat_client_create(struct ds_seat *seat, struct wl_client *wl_client)
342 struct ds_seat_client *seat_client;
344 seat_client = calloc(1, sizeof *seat_client);
345 seat_client->seat = seat;
346 seat_client->wl_client = wl_client;
348 wl_list_init(&seat_client->resources);
349 wl_list_init(&seat_client->pointers);
350 wl_list_init(&seat_client->keyboards);
351 wl_list_init(&seat_client->touches);
353 wl_signal_init(&seat_client->events.destroy);
359 seat_client_destroy(struct ds_seat_client *seat_client)
361 wl_signal_emit(&seat_client->events.destroy, seat_client);
363 seat_client_remove_all_pointer_resources(seat_client);
364 seat_client_remove_all_keyboard_resources(seat_client);
365 seat_client_remove_all_touch_resources(seat_client);
367 wl_list_remove(&seat_client->link);
373 seat_client_send_capabilities(struct ds_seat_client *seat_client)
375 struct wl_resource *resource;
377 wl_resource_for_each(resource, &seat_client->resources) {
378 wl_seat_send_capabilities(resource, seat_client->seat->capabilities);
383 seat_client_send_name(struct ds_seat_client *seat_client)
385 struct wl_resource *resource;
387 wl_resource_for_each(resource, &seat_client->resources) {
388 wl_seat_send_name(resource, seat_client->seat->name);