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 {
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
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)) {
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++;
}
}
}
}
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
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;
}
}
}
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;
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));
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) {
if (received_data->data != NULL) {
free(received_data->data);
received_data->data = NULL;
+ free(received_data);
}
goto receive_data_done;
}
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);
}
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;
{
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;
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 =
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);
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);
}
info->datafd.fd = -1;
+ LIST_INITHEAD(&info->received_data_list);
ret = cbhm_wayland_init(info);
if (ret) {
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);