tinyds: Update seat capabilities properly 68/279468/1
authorSeunghun <chwila927@gmail.com>
Mon, 8 Aug 2022 07:15:58 +0000 (16:15 +0900)
committerTizen Window System <tizen.windowsystem@gmail.com>
Wed, 10 Aug 2022 04:24:16 +0000 (13:24 +0900)
Change-Id: I1c3cee34e5c70bdfc4374f67e56e9d7236b5fda6

examples/tinyds.c

index 1154f0b..010cd25 100644 (file)
@@ -99,6 +99,8 @@ struct tinyds_server
     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;
@@ -109,6 +111,10 @@ struct tinyds_server
     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
@@ -130,6 +136,10 @@ static bool server_init(struct tinyds_server *server,
         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);
@@ -280,6 +290,9 @@ server_handle_display_destroy(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. */
@@ -355,11 +368,45 @@ server_init_protocols(struct tinyds_server *server)
 }
 
 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);
 
@@ -367,21 +414,22 @@ server_handle_new_input(struct wl_listener *listener, void *data)
     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
@@ -804,11 +852,15 @@ 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);
 
@@ -869,11 +921,15 @@ static void
 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);
@@ -904,11 +960,15 @@ static void
 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);