Support multi mime types 09/312209/1
authorJunkyeong Kim <jk0430.kim@samsung.com>
Wed, 5 Jun 2024 06:01:22 +0000 (15:01 +0900)
committerJunkyeong Kim <jk0430.kim@samsung.com>
Wed, 5 Jun 2024 06:01:31 +0000 (15:01 +0900)
AS-IS : support only first mime type for selection.
TO-BE : support all selection offered mime types.

Change-Id: I678e3e3edd866bc8e9287510ba73490770fe4b62
Signed-off-by: Junkyeong Kim <jk0430.kim@samsung.com>
src/cbhm.c

index a1e8568..4e46a60 100644 (file)
@@ -42,12 +42,17 @@ typedef struct {
 
 typedef struct {
        struct wl_data_offer *data_offer;
+       int type_count;
        struct list_head offer_mimetype_list;
 } Cbhm_Data_Offer;
 
 typedef struct {
+       char *mimetype;
        void *data;
        uint32_t len;
+
+       /* link of data */
+       struct list_head item_link;
 } Cbhm_Received_Data;
 
 typedef struct {
@@ -70,9 +75,11 @@ typedef struct {
        struct wl_array types;
        uint32_t serial;
 
-       Cbhm_Received_Data *received_data;
+       struct list_head received_data_list;
        Cbhm_Data_Offer *cbhm_data_offer;
+       char *temp_mime_type;
        bool data_receive;
+       int data_received_count;
 } Cbhm_Glib_Info;
 
 static void
@@ -112,6 +119,7 @@ _cbhm_add_mime_type(Cbhm_Data_Offer *cbhm_data_offer, const char *type)
        if (LIST_IS_EMPTY(&cbhm_data_offer->offer_mimetype_list)) {
                DBG("[CBHM]_cbhm_add_mime_type: %s\n", type);
                LIST_ADDTAIL(&mime->item_link, &cbhm_data_offer->offer_mimetype_list);
+               cbhm_data_offer->type_count++;
        } else {
                LIST_FOR_EACH_ENTRY(temp, &cbhm_data_offer->offer_mimetype_list, item_link) {
                        if (!strcmp(temp->mimetype, type)) {
@@ -125,6 +133,7 @@ _cbhm_add_mime_type(Cbhm_Data_Offer *cbhm_data_offer, const char *type)
                if (type_match == false) {
                        DBG("[CBHM]_cbhm_add_mime_type: %s\n", type);
                        LIST_ADDTAIL(&mime->item_link, &cbhm_data_offer->offer_mimetype_list);
+                       cbhm_data_offer->type_count++;
                }
        }
 }
@@ -168,13 +177,21 @@ _cbhm_free_mime_type_list(Cbhm_Data_Offer *cbhm_data_offer)
 }
 
 static void
-_cbhm_free_received_data(Cbhm_Received_Data *received_data)
+_cbhm_free_received_data(Cbhm_Glib_Info *info)
 {
-       if (!received_data) return;
+       Cbhm_Received_Data *data;
+       Cbhm_Received_Data *temp;
+
+       if (LIST_IS_EMPTY(&info->received_data_list)) return;
 
-       if (received_data->data)
-               free(received_data->data);
-       free(received_data);
+       LIST_FOR_EACH_ENTRY_SAFE(data, temp, &info->received_data_list, item_link) {
+               free(data->data);
+               free(data->mimetype);
+               LIST_DEL(&data->item_link);
+               free(data);
+       }
+       LIST_DELINIT(&info->received_data_list);
+       info->data_received_count = 0;
 }
 
 static void
@@ -189,20 +206,23 @@ _data_source_send(void *data, struct wl_data_source *source, const char *mime_ty
        Cbhm_Data_Offer *cbhm_data_offer;
        char *buf = NULL, *cur_buf;
        int ret, len_remained, size_ret, len_written = 0;
-       Cbhm_Mime_Type *mime;
+       Cbhm_Received_Data *received_data;
 
        if (!info) return;
        if (!info->cbhm_data_offer) return;
        cbhm_data_offer = info->cbhm_data_offer;
 
-       if (!info->received_data) {
+       if (info->data_source != source) {
+               WRN("[CBHM]_data_source_send: source changed\n");
+               buf = strdup("CLIPBOARD_EMPTY");
+       } else if (LIST_IS_EMPTY(&info->received_data_list)) {
                WRN("[CBHM]_data_source_send: no saved data\n");
                buf = strdup("CLIPBOARD_EMPTY");
        } else {
-               LIST_FOR_EACH_ENTRY(mime, &cbhm_data_offer->offer_mimetype_list, item_link) {
-                       if (!strcmp(mime->mimetype, mime_type)) {
-                               buf = calloc(info->received_data->len, sizeof(char));
-                               strncpy(buf, info->received_data->data, info->received_data->len);
+               LIST_FOR_EACH_ENTRY(received_data, &info->received_data_list, item_link) {
+                       if (!strcmp(received_data->mimetype, mime_type)) {
+                               buf = calloc(received_data->len, sizeof(char));
+                               strncpy(buf, received_data->data, received_data->len);
                                break;
                        }
                }
@@ -330,6 +350,52 @@ _cbhm_set_selection(Cbhm_Glib_Info *info)
 }
 
 static void
+_cbhm_offer_receive(Cbhm_Glib_Info *info)
+{
+       Cbhm_Data_Offer *cbhm_data_offer;
+       Cbhm_Mime_Type *mime = NULL;
+       int pipe[2];
+       int count = 0;
+
+       cbhm_data_offer = info->cbhm_data_offer;
+
+       if (info->data_received_count == cbhm_data_offer->type_count) {
+               DBG("[CBHM]_cbhm_offer_receive: already received all type data : %d", cbhm_data_offer->type_count);
+               return;
+       }
+
+       LIST_FOR_EACH_ENTRY(mime, &cbhm_data_offer->offer_mimetype_list, item_link) {
+               if (count != info->data_received_count) {
+                       count++;
+                       continue;
+               }
+               info->temp_mime_type = strdup(mime->mimetype);
+               break;
+       }
+       DBG("[CBHM]_cbhm_offer_receive: selected mime type : %s", info->temp_mime_type);
+
+       if (pipe2(pipe, O_CLOEXEC) == -1) {
+               ERR("[CBHM]_cbhm_offer_receive: pipe2 fail\n");
+               free(info->temp_mime_type);
+               info->temp_mime_type = NULL;
+               return;
+       }
+
+       wl_data_offer_receive(cbhm_data_offer->data_offer, (const char *)info->temp_mime_type, pipe[1]);
+       close(pipe[1]);
+
+       wl_display_flush(info->wl_disp);
+
+       info->datafd.fd = pipe[0];
+
+       info->datafd.events = G_IO_IN | G_IO_ERR;
+       info->datafd.revents = 0;
+
+       g_source_add_poll(&info->gsource, &info->datafd);
+       DBG("[CBHM]_cbhm_offer_receive: set datafd(%d, %d)\n", pipe[0], pipe[1]);
+}
+
+static void
 _cbhm_receive_data(Cbhm_Glib_Info *info)
 {
        Cbhm_Received_Data *received_data;
@@ -343,9 +409,10 @@ _cbhm_receive_data(Cbhm_Glib_Info *info)
        received_data = calloc(1, sizeof(Cbhm_Received_Data));
        if (!received_data) {
                ERR("[CBHM]_cbhm_receive_data: alloc fail \n");
+               free(info->temp_mime_type);
+               info->temp_mime_type = NULL;
                return;
        }
-       info->received_data = received_data;
 
        while (1) {
                len = read(info->datafd.fd, buffer, sizeof(buffer));
@@ -354,8 +421,7 @@ _cbhm_receive_data(Cbhm_Glib_Info *info)
                                continue;
                        } else {
                                ERR("[CBHM]_cbhm_receive_data: read fail.(%d) %m\n", errno);
-                               _cbhm_free_received_data(received_data);
-                               info->received_data = NULL;
+                               free(received_data);
                                goto receive_data_done;
                        }
                } else if (len == 0) {
@@ -380,6 +446,7 @@ _cbhm_receive_data(Cbhm_Glib_Info *info)
                        if (received_data->data != NULL) {
                                free(received_data->data);
                                received_data->data = NULL;
+                               free(received_data);
                        }
                        goto receive_data_done;
                }
@@ -401,15 +468,29 @@ _cbhm_receive_data(Cbhm_Glib_Info *info)
                        ERR("[CBHM]_cbhm_receive_data: realloc fail\n");
                        free(received_data->data);
                        received_data->data = NULL;
+                       free(received_data);
                        goto receive_data_done;
                }
        }
-       INF("[CBHM]_cbhm_receive_data: (%d) %s\n", received_data->len, (char *)received_data->data);
+       received_data->mimetype = strdup(info->temp_mime_type);
+       LIST_ADDTAIL(&received_data->item_link, &info->received_data_list);
+       info->data_received_count++;
+       INF("[CBHM]_cbhm_receive_data:(%d:%d) len:%d, %s\n",
+               info->data_received_count, info->cbhm_data_offer->type_count, received_data->len, (char *)received_data->data);
 
 receive_data_done:
        g_source_remove_poll(&info->gsource, &info->datafd);
        close(info->datafd.fd);
        info->datafd.fd = -1;
+
+       free(info->temp_mime_type);
+       info->temp_mime_type = NULL;
+
+       if (info->data_received_count != info->cbhm_data_offer->type_count) {
+               _cbhm_offer_receive(info);
+               return;
+       }
+
        info->data_receive = false;
 
        _cbhm_set_selection(info);
@@ -485,6 +566,9 @@ _data_device_cb_offer(void *data, struct wl_data_device *data_device, struct wl_
        }
        DBG("[CBHM]_data_device_cb_offer : %p\n", offer);
 
+       _cbhm_free_received_data(info);
+       LIST_INITHEAD(&info->received_data_list);
+
        LIST_INITHEAD(&cbhm_data_offer->offer_mimetype_list);
        cbhm_data_offer->data_offer = offer;
        info->cbhm_data_offer = cbhm_data_offer;
@@ -517,9 +601,6 @@ _data_device_cb_selection(void *data, struct wl_data_device *data_device, struct
 {
        Cbhm_Glib_Info *info;
        Cbhm_Data_Offer *cbhm_data_offer;
-       Cbhm_Mime_Type *mime = NULL;
-       char *mime_type;
-       int pipe[2];
 
        info = data;
        if (!info) return;
@@ -551,36 +632,9 @@ _data_device_cb_selection(void *data, struct wl_data_device *data_device, struct
                return;
        }
 
-       LIST_FOR_EACH_ENTRY(mime, &cbhm_data_offer->offer_mimetype_list, item_link) {
-               mime_type = strdup(mime->mimetype);
-               break;
-       }
-       DBG("[CBHM]_data_device_cb_selection: selected mime type : %s", mime_type);
-
-       if (pipe2(pipe, O_CLOEXEC) == -1) {
-               ERR("[CBHM]_data_device_cb_selection: pipe2 fail\n");
-               free(mime_type);
-               return;
-       }
-
        info->data_receive = true;
-       _cbhm_free_received_data(info->received_data);
-       info->received_data = NULL;
-
-       wl_data_offer_receive(offer, (const char *)mime_type, pipe[1]);
-       close(pipe[1]);
 
-       wl_display_flush(info->wl_disp);
-
-       free(mime_type);
-
-       info->datafd.fd = pipe[0];
-
-       info->datafd.events = G_IO_IN | G_IO_ERR;
-       info->datafd.revents = 0;
-
-       g_source_add_poll(&info->gsource, &info->datafd);
-       DBG("[CBHM]_data_device_cb_selection: set datafd(%d, %d)\n", pipe[0], pipe[1]);
+       _cbhm_offer_receive(info);
 }
 
 static const struct wl_data_device_listener _data_device_listener =
@@ -864,9 +918,7 @@ cbhm_gsource_finalize(GSource *source)
        Cbhm_Glib_Info *info = (Cbhm_Glib_Info *)source;
 
        INF("[CBHM]cbhm_gsource_finalize: revent:0x%x\n", info->gfd.revents);
-       if (info->received_data)
-               _cbhm_free_received_data(info->received_data);
-       info->received_data = NULL;
+       _cbhm_free_received_data(info);
        if (info->cbhm_data_offer) {
                wl_data_offer_destroy(info->cbhm_data_offer->data_offer);
                _cbhm_free_mime_type_list(info->cbhm_data_offer);
@@ -877,6 +929,8 @@ cbhm_gsource_finalize(GSource *source)
                close(info->datafd.fd);
                info->datafd.fd = -1;
        }
+       if (info->temp_mime_type)
+               free(info->temp_mime_type);
        cbhm_wayland_shutdown(info);
        g_source_destroy(source);
 
@@ -903,6 +957,7 @@ cbhm_init(void)
        }
 
        info->datafd.fd = -1;
+       LIST_INITHEAD(&info->received_data_list);
 
        ret = cbhm_wayland_init(info);
        if (ret) {
@@ -943,9 +998,7 @@ cbhm_shutdown(GSource *gsource)
 
        info = (Cbhm_Glib_Info *)gsource;
 
-       if (info->received_data)
-               _cbhm_free_received_data(info->received_data);
-       info->received_data = NULL;
+       _cbhm_free_received_data(info);
        if (info->cbhm_data_offer) {
                wl_data_offer_destroy(info->cbhm_data_offer->data_offer);
                _cbhm_free_mime_type_list(info->cbhm_data_offer);