diff options
| -rw-r--r-- | src/drivers/Wayland/fl_wayland_clipboard_dnd.cxx | 86 |
1 files changed, 56 insertions, 30 deletions
diff --git a/src/drivers/Wayland/fl_wayland_clipboard_dnd.cxx b/src/drivers/Wayland/fl_wayland_clipboard_dnd.cxx index a4b874287..eae25e8e2 100644 --- a/src/drivers/Wayland/fl_wayland_clipboard_dnd.cxx +++ b/src/drivers/Wayland/fl_wayland_clipboard_dnd.cxx @@ -30,6 +30,7 @@ # include <errno.h> # include <stdio.h> # include <stdlib.h> +# include <map> //////////////////////////////////////////////////////////////// @@ -41,7 +42,6 @@ static const char * fl_selection_type[2]; static int fl_selection_buffer_length[2]; static char fl_i_own_selection[2] = {0,0}; static struct wl_data_offer *fl_selection_offer = NULL; -static const char *fl_selection_offer_type = NULL; // The MIME type Wayland uses for text-containing clipboard: static const char wld_plain_text_clipboard[] = "text/plain;charset=utf-8"; @@ -280,30 +280,46 @@ int Fl_Wayland_Screen_Driver::dnd(int use_selection) { } +// map: for each clipboard mime-type FLTK has interest in, give FLTK clipboard type and priority. +// A mime-type with higher priority for same FLTK clipboard type is preferred. +typedef struct two_field_struct_ { const char *fltk_type; int priority; } type_prio_struct; +static std::map<const char *, type_prio_struct> clipboard_mimetypes_map = { +// mime-type FLTK-clipboard-type priority + {"image/png", {Fl::clipboard_image, 1} }, + {"image/bmp", {Fl::clipboard_image, 2} }, + {"text/plain", {Fl::clipboard_plain_text, 1} }, + {"text/uri-list", {Fl::clipboard_plain_text, 2} }, + {"UTF8_STRING", {Fl::clipboard_plain_text, 3} }, + {wld_plain_text_clipboard, {Fl::clipboard_plain_text, 4} }, +}; + +// map: for each FLTK-clipboard-type, give current preferred mime-type and priority +typedef struct mime_prio_struct_ { const char *mime_type; int priority; } mime_prio_struct; +static std::map<const char *, mime_prio_struct> clipboard_kinds_map = { +// FLTK-clipboard-type current mime-type current highest priority + {Fl::clipboard_image, {NULL, 0} }, + {Fl::clipboard_plain_text, {NULL, 0} }, +}; + + static void data_offer_handle_offer(void *data, struct wl_data_offer *offer, const char *mime_type) { - // runs when app becomes active and lists possible clipboard types + // runs when app becomes active once for each offered clipboard type //fprintf(stderr, "Clipboard offer=%p supports MIME type: %s\n", offer, mime_type); - if (strcmp(mime_type, "image/png") == 0) { - fl_selection_type[1] = Fl::clipboard_image; - fl_selection_offer_type = "image/png"; - } else if (strcmp(mime_type, "image/bmp") == 0 && (!fl_selection_offer_type || - strcmp(fl_selection_offer_type, "image/png"))) { - fl_selection_type[1] = Fl::clipboard_image; - fl_selection_offer_type = "image/bmp"; - } else if (strcmp(mime_type, "text/uri-list") == 0 && !fl_selection_type[1]) { - fl_selection_type[1] = Fl::clipboard_plain_text; - fl_selection_offer_type = "text/uri-list"; - } else if (strcmp(mime_type, wld_plain_text_clipboard) == 0 && - (!fl_selection_type[1] || !strcmp(fl_selection_offer_type, "text/plain"))) { - fl_selection_type[1] = Fl::clipboard_plain_text; - fl_selection_offer_type = wld_plain_text_clipboard; - } else if (strcmp(mime_type, "text/plain") == 0 && !fl_selection_type[1]) { - fl_selection_type[1] = Fl::clipboard_plain_text; - fl_selection_offer_type = "text/plain"; - } else if (strcmp(mime_type, "UTF8_STRING") == 0 && !fl_selection_type[1]) { - fl_selection_type[1] = Fl::clipboard_plain_text; - fl_selection_offer_type = "text/plain"; + std::map<const char*, type_prio_struct>::iterator iter_mime = clipboard_mimetypes_map.begin(); + while (strcmp(iter_mime->first, mime_type)) { + iter_mime++; + if (iter_mime == clipboard_mimetypes_map.end()) return; // FLTK doesn't handle this mime_type + } + std::map<const char*, mime_prio_struct>::iterator iter_kind = clipboard_kinds_map.begin(); + while (strcmp(iter_kind->first, iter_mime->second.fltk_type)) { + iter_kind++; + } + if (iter_mime->second.priority > iter_kind->second.priority) { // found mime-type with higher priority + iter_kind->second.priority = iter_mime->second.priority; + iter_kind->second.mime_type = iter_mime->first; + fl_selection_type[1] = iter_kind->first; +//fprintf(stderr,"mime_type=%s priority=%d [%s]\n",iter_kind->second.mime_type, iter_kind->second.priority, fl_selection_type[1]); } } @@ -344,8 +360,14 @@ static void data_device_handle_data_offer(void *data, struct wl_data_device *dat // An application has created a new data source //fprintf(stderr, "data_device_handle_data_offer offer=%p\n", offer); fl_selection_type[1] = NULL; - fl_selection_offer_type = NULL; wl_data_offer_add_listener(offer, &data_offer_listener, NULL); + // reset current best mime-type and priority + std::map<const char*, mime_prio_struct>::iterator iter = clipboard_kinds_map.begin(); + while (iter != clipboard_kinds_map.end()) { + iter->second.mime_type = NULL; + iter->second.priority = 0; + iter++; + } } @@ -365,7 +387,9 @@ static void get_clipboard_or_dragged_text(struct wl_data_offer *offer) { int fds[2]; char *from; if (pipe(fds)) return; - wl_data_offer_receive(offer, fl_selection_offer_type, fds[1]); + // preferred mime-type for the text clipboard type + const char *type = clipboard_kinds_map[Fl::clipboard_plain_text].mime_type; + wl_data_offer_receive(offer, type, fds[1]); close(fds[1]); wl_display_flush(Fl_Wayland_Screen_Driver::wl_display); // read in fl_selection_buffer @@ -397,7 +421,7 @@ static void get_clipboard_or_dragged_text(struct wl_data_offer *offer) { //fprintf(stderr, "get_clipboard_or_dragged_text: size=%ld\n", rest); // read full clipboard data if (pipe(fds)) goto way_out; - wl_data_offer_receive(offer, fl_selection_offer_type, fds[1]); + wl_data_offer_receive(offer, type, fds[1]); close(fds[1]); wl_display_flush(Fl_Wayland_Screen_Driver::wl_display); if (rest+1 > fl_selection_buffer_length[1]) { @@ -418,7 +442,7 @@ static void get_clipboard_or_dragged_text(struct wl_data_offer *offer) { fl_selection_length[1] = from - fl_selection_buffer[1]; fl_selection_buffer[1][fl_selection_length[1]] = 0; way_out: - if (strcmp(fl_selection_offer_type, "text/uri-list") == 0) { + if (strcmp(type, "text/uri-list") == 0) { fl_decode_uri(fl_selection_buffer[1]); // decode encoded bytes char *p = fl_selection_buffer[1]; while (*p) { // remove prefixes @@ -549,13 +573,15 @@ const struct wl_data_device_listener *Fl_Wayland_Screen_Driver::p_data_device_li // Reads from the clipboard an image which can be in image/bmp or image/png MIME type. // Returns 0 if OK, != 0 if error. -static int get_clipboard_image() { +static int get_clipboard_image(struct wl_data_offer *offer) { int fds[2]; if (pipe(fds)) return 1; - wl_data_offer_receive(fl_selection_offer, fl_selection_offer_type, fds[1]); + // preferred mime-type for the image clipboard type + const char *type = clipboard_kinds_map[Fl::clipboard_image].mime_type; + wl_data_offer_receive(offer, type, fds[1]); close(fds[1]); wl_display_roundtrip(Fl_Wayland_Screen_Driver::wl_display); - if (strcmp(fl_selection_offer_type, "image/png") == 0) { + if (strcmp(type, "image/png") == 0) { char tmp_fname[21]; Fl_Shared_Image *shared = 0; strcpy(tmp_fname, "/tmp/clipboardXXXXXX"); @@ -638,7 +664,7 @@ void Fl_Wayland_Screen_Driver::paste(Fl_Widget &receiver, int clipboard, const c Fl::e_length = fl_selection_length[1]; receiver.handle(FL_PASTE); } else if (type == Fl::clipboard_image && clipboard_contains(Fl::clipboard_image)) { - if (get_clipboard_image()) return; + if (get_clipboard_image(fl_selection_offer)) return; struct wld_window * xid = fl_wl_xid(receiver.top_window()); if (xid) { int s = Fl_Wayland_Window_Driver::driver(receiver.top_window())->wld_scale(); |
