struct ds_seat *seat;
struct ds_data_device_manager *data_device;
+ struct wl_event_source *idle_task;
+
enum wl_seat_capability seat_caps;
struct wl_list views;
struct wl_listener new_xdg_surface;
struct wl_listener request_set_selection;
struct wl_listener request_data_offer_receive;
+
+ struct {
+ bool seat_caps;
+ } changes;
};
struct tinyds_view
struct wl_display *display);
static bool server_init_backend(struct tinyds_server *server);
static bool server_init_protocols(struct tinyds_server *server);
+static void server_schedule_idle_task(struct tinyds_server *server);
+static void server_update_seat_caps(struct tinyds_server *server,
+ enum wl_seat_capability caps);
+static void server_handle_idle_task(void *data);
static void server_handle_display_destroy(struct wl_listener *listener,
void *data);
static void server_handle_new_input(struct wl_listener *listener, void *data);
if (server->output)
output_destroy(server->output);
+ if (server->idle_task)
+ wl_event_source_remove(server->idle_task);
+
/* It's safe to remove links of all listener here because
* server_handle_display_destroy must be the first to be called
* before other objects such as backend. */
}
static void
+server_schedule_idle_task(struct tinyds_server *server)
+{
+ if (server->idle_task)
+ return;
+
+ server->idle_task =
+ wl_event_loop_add_idle(wl_display_get_event_loop(server->display),
+ server_handle_idle_task, server);
+}
+
+static void
+server_update_seat_caps(struct tinyds_server *server,
+ enum wl_seat_capability caps)
+{
+ server->seat_caps = caps;
+ server->changes.seat_caps = true;
+ server_schedule_idle_task(server);
+}
+
+static void
+server_handle_idle_task(void *data)
+{
+ struct tinyds_server *server = data;
+
+ server->idle_task = NULL;
+
+ if (server->changes.seat_caps) {
+ server->changes.seat_caps = false;
+ ds_seat_set_capabilities(server->seat, server->seat_caps);
+ }
+}
+
+static void
server_handle_new_input(struct wl_listener *listener, void *data)
{
struct tinyds_server *server;
struct ds_input_device *dev = data;
enum ds_input_device_type dev_type;
+ enum wl_seat_capability new_cap;
server = wl_container_of(listener, server, new_input);
switch (dev_type) {
case DS_INPUT_DEVICE_KEYBOARD:
server_add_keyboard(server, dev);
- server->seat_caps |= WL_SEAT_CAPABILITY_KEYBOARD;
+ new_cap = WL_SEAT_CAPABILITY_KEYBOARD;
break;
case DS_INPUT_DEVICE_TOUCH:
server_add_touch(server, dev);
+ new_cap = WL_SEAT_CAPABILITY_TOUCH;
break;
case DS_INPUT_DEVICE_POINTER:
server_add_pointer(server, dev);
- server->seat_caps |= WL_SEAT_CAPABILITY_POINTER;
+ new_cap = WL_SEAT_CAPABILITY_POINTER;
break;
default:
ds_err("Unknown type(%d) of ds_input_device", dev_type);
- break;
+ return;
}
- ds_seat_set_capabilities(server->seat, server->seat_caps);
+ server_update_seat_caps(server, (server->seat_caps | new_cap));
}
static void
keyboard_handle_device_destroy(struct wl_listener *listener, void *data)
{
struct tinyds_keyboard *kbd;
+ enum wl_seat_capability new_caps;
kbd = wl_container_of(listener, kbd, destroy);
ds_inf("Keyboard(%p) destroyed", kbd);
+ new_caps = kbd->server->seat_caps & ~WL_SEAT_CAPABILITY_KEYBOARD;
+ server_update_seat_caps(kbd->server, new_caps);
+
wl_list_remove(&kbd->destroy.link);
wl_list_remove(&kbd->key.link);
touch_handle_device_destroy(struct wl_listener *listener, void *data)
{
struct tinyds_touch *touch;
+ enum wl_seat_capability new_caps;
touch = wl_container_of(listener, touch, destroy);
ds_inf("Touch(%p) destroyed", touch);
+ new_caps = touch->server->seat_caps & ~WL_SEAT_CAPABILITY_TOUCH;
+ server_update_seat_caps(touch->server, new_caps);
+
wl_list_remove(&touch->destroy.link);
wl_list_remove(&touch->down.link);
wl_list_remove(&touch->up.link);
pointer_handle_device_destroy(struct wl_listener *listener, void *data)
{
struct tinyds_pointer *pointer;
+ enum wl_seat_capability new_caps;
pointer = wl_container_of(listener, pointer, destroy);
ds_inf("Pointer(%p) destroyed", pointer);
+ new_caps = pointer->server->seat_caps & ~WL_SEAT_CAPABILITY_POINTER;
+ server_update_seat_caps(pointer->server, new_caps);
+
wl_list_remove(&pointer->destroy.link);
wl_list_remove(&pointer->motion.link);
wl_list_remove(&pointer->motion_absolute.link);