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.
This commit is contained in:
ManoloFLTK
2019-07-18 17:46:10 +02:00
parent 3679dd5fbd
commit f20c07d757
+50 -8
View File
@@ -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 {