data_device: Create ds_data_device per seat_client 24/279824/1
authorSeunghun Lee <shiin.lee@samsung.com>
Fri, 12 Aug 2022 02:17:40 +0000 (11:17 +0900)
committerTizen Window System <tizen.windowsystem@gmail.com>
Thu, 18 Aug 2022 07:37:50 +0000 (16:37 +0900)
Change-Id: Ib2c74c3f26ca7bead4d707e7b642a8e8d605be7c

src/data_device/data_device.c
src/data_device/data_device_private.h
src/data_device/data_offer.c
src/data_device/manager.c

index b85a9bf..24f8032 100644 (file)
@@ -5,7 +5,16 @@
 
 static const struct wl_data_device_interface data_device_iface;
 
+static struct ds_data_device *
+data_device_get_or_create(struct ds_data_device_manager *manager,
+        struct ds_seat_client *seat_client);
+static struct ds_data_device *create_data_device(
+        struct ds_data_device_manager *manager,
+        struct ds_seat_client *seat_client);
+static void data_device_destroy(struct ds_data_device *data_device);
 static void data_device_handle_resource_destroy(struct wl_resource *resource);
+static void data_device_handle_manager_destroy(struct wl_listener *listener,
+        void *data);
 static void data_device_handle_seat_client_destroy(
         struct wl_listener *listener, void *data);
 static void data_device_handle_seat_set_selection(struct wl_listener *listener,
@@ -13,32 +22,77 @@ static void data_device_handle_seat_set_selection(struct wl_listener *listener,
 static void data_device_handle_keyboard_focus_change(
         struct wl_listener *listener, void *data);
 static void data_device_update_selection(struct ds_data_device *data_device);
+static void data_device_send_selection(struct ds_data_device *data_device,
+        struct wl_resource *resource);
 
-struct ds_data_device *
-create_data_device(struct ds_data_device_manager *manager,
+void
+create_data_device_resource(struct ds_data_device_manager *manager,
         struct wl_client *client, uint32_t version,
         uint32_t id, struct wl_resource *seat_resource)
 {
     struct ds_data_device *data_device;
+    struct ds_seat_client *seat_client, *focused_client;
+    struct wl_resource *resource;
 
-    data_device = calloc(1, sizeof *data_device);
-    if (!data_device)
-        return NULL;
+    seat_client = ds_seat_client_from_resource(seat_resource);
+    data_device = data_device_get_or_create(manager, seat_client);
+    if (!data_device) {
+        ds_err("Could not create data_device");
+        wl_client_post_no_memory(client);
+        return;
+    }
 
-    data_device->resource = wl_resource_create(client,
-            &wl_data_device_interface, version, id);
-    if (!data_device->resource) {
+    resource = wl_resource_create(client, &wl_data_device_interface,
+            version, id);
+    if (!resource) {
         wl_client_post_no_memory(client);
-        return NULL;
+        return;
     }
 
-    wl_resource_set_implementation(data_device->resource, &data_device_iface, 
+    wl_resource_set_implementation(resource, &data_device_iface,
             data_device, data_device_handle_resource_destroy);
 
+    wl_list_insert(&data_device->resources, wl_resource_get_link(resource));
+
+    focused_client = ds_seat_keyboard_get_focused_client(data_device->seat);
+    if (data_device->seat_client == focused_client)
+        data_device_send_selection(data_device, resource);
+}
+
+static struct ds_data_device *
+data_device_get_or_create(struct ds_data_device_manager *manager,
+        struct ds_seat_client *seat_client)
+{
+    struct ds_data_device *data_device;
+
+    data_device = data_device_for_seat_client(manager, seat_client);
+    if (!data_device)
+        data_device = create_data_device(manager, seat_client);
+
+    return data_device;
+}
+
+static struct ds_data_device *
+create_data_device(struct ds_data_device_manager *manager,
+        struct ds_seat_client *seat_client)
+{
+    struct ds_data_device *data_device;
+
+    data_device = calloc(1, sizeof *data_device);
+    if (!data_device)
+        return NULL;
+
+
+    wl_list_init(&data_device->resources);
+    wl_list_init(&data_device->selection_offers);
+
     data_device->manager = manager;
-    data_device->seat_client = ds_seat_client_from_resource(seat_resource);
+    data_device->seat_client = seat_client;
     data_device->seat = ds_seat_client_get_seat(data_device->seat_client);
 
+    data_device->manager_destroy.notify = data_device_handle_manager_destroy;
+    wl_signal_add(&manager->events.destroy, &data_device->manager_destroy);
+
     data_device->seat_client_destroy.notify =
         data_device_handle_seat_client_destroy;
     ds_seat_client_add_destroy_listener(data_device->seat_client,
@@ -52,28 +106,35 @@ create_data_device(struct ds_data_device_manager *manager,
     data_device->keyboard_focus_change.notify =
         data_device_handle_keyboard_focus_change;
     ds_seat_keyboard_add_focus_change_listener(data_device->seat,
-        &data_device->keyboard_focus_change);
-
-    data_device_update_selection(data_device);
+            &data_device->keyboard_focus_change);
 
     wl_list_insert(&manager->data_devices, &data_device->link);
 
     return data_device;
 }
 
-void
+static void
 data_device_destroy(struct ds_data_device *data_device)
 {
-    wl_list_remove(&data_device->link);
+    struct wl_resource *resource, *resource_tmp;
+    struct ds_data_offer *offer, *offer_tmp;
 
-    if (data_device->seat_client) {
-        wl_list_remove(&data_device->seat_client_destroy.link);
-        wl_list_remove(&data_device->seat_set_selection.link);
-        wl_list_remove(&data_device->keyboard_focus_change.link);
+    wl_list_for_each_safe(offer, offer_tmp, &data_device->selection_offers,
+            link) {
+        data_offer_destroy(offer);
     }
 
-    wl_resource_set_user_data(data_device->resource, NULL);
+    wl_resource_for_each_safe(resource, resource_tmp,
+            &data_device->resources) {
+        wl_list_remove(wl_resource_get_link(resource));
+        wl_resource_set_user_data(resource, NULL);
+    }
 
+    wl_list_remove(&data_device->link);
+    wl_list_remove(&data_device->manager_destroy.link);
+    wl_list_remove(&data_device->seat_client_destroy.link);
+    wl_list_remove(&data_device->seat_set_selection.link);
+    wl_list_remove(&data_device->keyboard_focus_change.link);
     free(data_device);
 }
 
@@ -86,6 +147,19 @@ data_device_handle_resource_destroy(struct wl_resource *resource)
     if (!data_device)
         return;
 
+    wl_list_remove(wl_resource_get_link(resource));
+    if (!wl_list_empty(&data_device->resources))
+        return;
+
+    data_device_destroy(data_device);
+}
+
+static void data_device_handle_manager_destroy(struct wl_listener *listener,
+        void *data)
+{
+    struct ds_data_device *data_device;
+
+    data_device = wl_container_of(listener, data_device, manager_destroy);
     data_device_destroy(data_device);
 }
 
@@ -96,13 +170,7 @@ data_device_handle_seat_client_destroy(struct wl_listener *listener,
     struct ds_data_device *data_device;
 
     data_device = wl_container_of(listener, data_device, seat_client_destroy);
-
-    wl_list_remove(&data_device->seat_client_destroy.link);
-    wl_list_remove(&data_device->seat_set_selection.link);
-    wl_list_remove(&data_device->keyboard_focus_change.link);
-
-    data_device->seat_client = NULL;
-    data_device->seat = NULL;
+    data_device_destroy(data_device);
 }
 
 static void
@@ -137,7 +205,7 @@ data_device_handle_start_drag(struct wl_client *client,
     struct ds_drag *drag;
 
     data_device = wl_resource_get_user_data(resource);
-    if (!data_device || !data_device->seat_client)
+    if (!data_device)
         return;
 
     if (source_resource) {
@@ -173,7 +241,7 @@ data_device_handle_set_selection(struct wl_client *client,
     struct ds_data_source_client *source = NULL;
 
     data_device = wl_resource_get_user_data(resource);
-    if (!data_device || !data_device->seat_client)
+    if (!data_device)
         return;
 
     if (source_resource) {
@@ -208,26 +276,46 @@ static const struct wl_data_device_interface data_device_iface = {
 static void
 data_device_update_selection(struct ds_data_device *data_device)
 {
-    struct ds_seat_client *focused_client;
     struct ds_data_source *source;
-    struct ds_data_offer *offer;
+    struct ds_data_offer *offer, *tmp;
+    struct ds_seat_client *focused_client;
+    struct wl_resource *resource;
+
+    source = ds_seat_get_selection(data_device->seat);
+    if (source)
+        source->accepted = false;
+
+    wl_list_for_each_safe(offer, tmp, &data_device->selection_offers, link)
+        data_offer_destroy(offer);
 
     focused_client = ds_seat_keyboard_get_focused_client(data_device->seat);
-    if (data_device->seat_client != focused_client)
-        return;
+    if (data_device->seat_client == focused_client) {
+        wl_resource_for_each(resource, &data_device->resources)
+            data_device_send_selection(data_device, resource);
+    }
+}
+
+static void
+data_device_send_selection(struct ds_data_device *data_device,
+        struct wl_resource *device_resource)
+{
+    struct ds_data_source *source;
+    struct ds_data_offer *offer;
 
     source = ds_seat_get_selection(data_device->seat);
     if (source) {
-        offer = create_data_offer(data_device, source,
+        offer = create_data_offer(device_resource, source,
                 DS_DATA_OFFER_SELECTION);
         if (!offer) {
-            wl_resource_post_no_memory(data_device->resource);
+            wl_resource_post_no_memory(device_resource);
             return;
         }
 
-        wl_data_device_send_selection(data_device->resource, offer->resource);
+        wl_list_insert(&data_device->selection_offers, &offer->link);
+
+        wl_data_device_send_selection(device_resource, offer->resource);
     }
     else {
-        wl_data_device_send_selection(data_device->resource, NULL);
+        wl_data_device_send_selection(device_resource, NULL);
     }
 }
index e766cd3..e86d5c7 100644 (file)
@@ -34,14 +34,15 @@ struct ds_data_device_manager
 
 struct ds_data_device
 {
-    struct wl_resource *resource;
     struct ds_data_device_manager *manager;
     struct ds_seat_client *seat_client;
     struct ds_seat *seat;
 
+    struct wl_list resources;
     struct wl_list selection_offers; // ds_data_offer.link
     struct wl_list link; // ds_data_device_manager.data_devices
 
+    struct wl_listener manager_destroy;
     struct wl_listener seat_client_destroy;
     struct wl_listener seat_set_selection;
     struct wl_listener keyboard_focus_change;
@@ -110,19 +111,23 @@ struct ds_drag_icon
     bool mapped;
 };
 
-struct ds_data_device *create_data_device(
-        struct ds_data_device_manager *manager, struct wl_client *client,
-        uint32_t version, uint32_t id, struct wl_resource *seat_resource);
+struct ds_data_device *
+data_device_for_seat_client(struct ds_data_device_manager *manager,
+        struct ds_seat_client *seat_client);
 
-void data_device_destroy(struct ds_data_device *data_device);
+void create_data_device_resource(struct ds_data_device_manager *manager,
+        struct wl_client *client, uint32_t version,
+        uint32_t id, struct wl_resource *seat_resource);
 
 struct ds_data_source_client *create_data_source_client(
         struct wl_client *wl_client, uint32_t version, uint32_t id);
 
 struct ds_data_offer *
-create_data_offer(struct ds_data_device *data_device,
+create_data_offer(struct wl_resource *device_resource,
         struct ds_data_source *source, enum ds_data_offer_type type);
 
+void data_offer_destroy(struct ds_data_offer *offer);
+
 struct ds_drag *create_drag(struct ds_seat_client *seat_client,
         struct ds_data_source *source, struct wl_resource *icon_resource);
 
index 23d71c1..46b0ac4 100644 (file)
@@ -21,12 +21,11 @@ ds_data_offer_send(struct ds_data_offer *offer, const char *mime_type,
 }
 
 struct ds_data_offer *
-create_data_offer(struct ds_data_device *data_device,
+create_data_offer(struct wl_resource *device_resource,
         struct ds_data_source *source, enum ds_data_offer_type type)
 {
     struct ds_data_offer *offer;
     struct wl_client *client;
-    uint32_t version;
     char **p;
 
     offer = calloc(1, sizeof *offer);
@@ -34,13 +33,12 @@ create_data_offer(struct ds_data_device *data_device,
         return NULL;
 
     offer->source = source;
-    offer->data_device = data_device;
+    offer->data_device = wl_resource_get_user_data(device_resource);
     offer->type = type;
 
-    client = wl_resource_get_client(data_device->resource);
-    version = wl_resource_get_version(data_device->resource);
+    client = wl_resource_get_client(device_resource);
     offer->resource = wl_resource_create(client, &wl_data_offer_interface,
-            version, 0);
+            wl_resource_get_version(device_resource), 0);
     if (!offer->resource) {
         free(offer);
         return NULL;
@@ -52,7 +50,7 @@ create_data_offer(struct ds_data_device *data_device,
     offer->source_destroy.notify = data_offer_handle_source_destroy;
     wl_signal_add(&source->events.destroy, &offer->source_destroy);
 
-    wl_data_device_send_data_offer(data_device->resource, offer->resource);
+    wl_data_device_send_data_offer(device_resource, offer->resource);
 
     wl_array_for_each(p, &source->mime_types)
         wl_data_offer_send_offer(offer->resource, *p);
@@ -80,9 +78,10 @@ data_offer_update_action(struct ds_data_offer *offer)
         wl_data_offer_send_action(offer->resource, action);
 }
 
-static void
+void
 data_offer_destroy(struct ds_data_offer *offer)
 {
+    wl_list_remove(&offer->link);
     wl_list_remove(&offer->source_destroy.link);
 
     wl_resource_set_user_data(offer->resource, NULL);
index abf6ff8..61300ce 100644 (file)
@@ -69,6 +69,20 @@ ds_data_device_manager_add_request_data_offer_receive_listener(
     wl_signal_add(&manager->events.request_data_offer_receive, listener);
 }
 
+struct ds_data_device *
+data_device_for_seat_client(struct ds_data_device_manager *manager,
+        struct ds_seat_client *seat_client)
+{
+    struct ds_data_device *data_device;
+
+    wl_list_for_each(data_device, &manager->data_devices, link) {
+        if (data_device->seat_client == seat_client)
+            return data_device;
+    }
+
+    return NULL;
+}
+
 static const struct wl_data_device_manager_interface data_device_manager_iface;
 
 static void
@@ -114,12 +128,10 @@ static void data_device_manager_handle_get_data_device(
         uint32_t id, struct wl_resource *seat_resource)
 {
     struct ds_data_device_manager *manager;
-    uint32_t version;
 
     manager = wl_resource_get_user_data(resource);
-    version = wl_resource_get_version(resource);
-
-    create_data_device(manager, client, version, id, seat_resource);
+    create_data_device_resource(manager, client,
+            wl_resource_get_version(resource), id, seat_resource);
 }
 
 static const struct wl_data_device_manager_interface