summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2019-07-18 17:46:10 +0200
committerManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2019-07-18 17:46:10 +0200
commitf20c07d757388482ff2f4ca4eb7ceaf52712814a (patch)
tree8bcf24b8a60958e844d38d6543c1c50ced417ce7 /src
parent3679dd5fbdeed711804ebb9eb52abc335440b903 (diff)
X11: support copy/paste of image via clipboard within a single app
X11 requires to process differently paste if both copy and paste are within the same app or are in 2 separate apps. This was implemented for paste of text. It's now also implemented for paste of image.
Diffstat (limited to 'src')
-rw-r--r--src/Fl_x.cxx58
1 files changed, 50 insertions, 8 deletions
diff --git a/src/Fl_x.cxx b/src/Fl_x.cxx
index 36418ffe8..6c1da73a4 100644
--- a/src/Fl_x.cxx
+++ b/src/Fl_x.cxx
@@ -751,18 +751,56 @@ const char * fl_selection_type[2];
int fl_selection_buffer_length[2];
char fl_i_own_selection[2] = {0,0};
+static void read_int(uchar *c, int& i) {
+ i = *c;
+ i |= (*(++c))<<8;
+ i |= (*(++c))<<16;
+ i |= (*(++c))<<24;
+}
+
+// turn BMP image FLTK produced by create_bmp() back to Fl_RGB_Image
+static Fl_RGB_Image *own_bmp_to_RGB(char *bmp) {
+ int w, h;
+ read_int((uchar*)bmp + 18, w);
+ read_int((uchar*)bmp + 22, h);
+ int R=(3*w+3)/4 * 4; // the number of bytes per row, rounded up to multiple of 4
+ bmp += 54;
+ uchar *data = new uchar[w*h*3];
+ uchar *p = data;
+ for (int i = h-1; i >= 0; i--) {
+ char *s = bmp + i * R;
+ for (int j = 0; j < w; j++) {
+ *p++=s[2];
+ *p++=s[1];
+ *p++=s[0];
+ s+=3;
+ }
+ }
+ Fl_RGB_Image *img = new Fl_RGB_Image(data, w, h, 3);
+ img->alloc_array = 1;
+ return img;
+}
+
// Call this when a "paste" operation happens:
void Fl_X11_System_Driver::paste(Fl_Widget &receiver, int clipboard, const char *type) {
if (fl_i_own_selection[clipboard]) {
// We already have it, do it quickly without window server.
- // Notice that the text is clobbered if set_selection is
- // called in response to FL_PASTE!
- // However, for now, we only paste text in this function
- if (fl_selection_type[clipboard] != Fl::clipboard_plain_text) return; //TODO: allow copy/paste of image within same app
- Fl::e_text = fl_selection_buffer[clipboard];
- Fl::e_length = fl_selection_length[clipboard];
- if (!Fl::e_text) Fl::e_text = (char *)"";
- receiver.handle(FL_PASTE);
+ if (type == Fl::clipboard_plain_text && fl_selection_type[clipboard] == type) {
+ // Notice that the text is clobbered if set_selection is
+ // called in response to FL_PASTE!
+ // However, for now, we only paste text in this function
+ Fl::e_text = fl_selection_buffer[clipboard];
+ Fl::e_length = fl_selection_length[clipboard];
+ if (!Fl::e_text) Fl::e_text = (char *)"";
+ } else if (clipboard == 1 && type == Fl::clipboard_image && fl_selection_type[1] == type) {
+ Fl::e_clipboard_data = own_bmp_to_RGB(fl_selection_buffer[1]);
+ Fl::e_clipboard_type = Fl::clipboard_image;
+ } else return;
+ int retval = receiver.handle(FL_PASTE);
+ if (retval == 0 && type == Fl::clipboard_image) {
+ delete (Fl_RGB_Image*)Fl::e_clipboard_data;
+ Fl::e_clipboard_data = NULL;
+ }
return;
}
// otherwise get the window server to return it:
@@ -775,11 +813,15 @@ void Fl_X11_System_Driver::paste(Fl_Widget &receiver, int clipboard, const char
int Fl_X11_System_Driver::clipboard_contains(const char *type)
{
+ if (fl_i_own_selection[1]) {
+ return fl_selection_type[1] == type;
+ }
XEvent event;
Atom actual; int format; unsigned long count, remaining, i = 0;
unsigned char* portion = NULL;
Fl_Window *win = Fl::first_window();
if (!win || !fl_xid(win)) return 0;
+ win->wait_for_expose();
XConvertSelection(fl_display, CLIPBOARD, TARGETS, CLIPBOARD, fl_xid(win), CurrentTime);
XFlush(fl_display);
do {