diff -ur fltk-copy-image/FL/Fl_Copy_Surface.H fltk-devel/FL/Fl_Copy_Surface.H
--- fltk-copy-image/FL/Fl_Copy_Surface.H	2014-02-25 20:04:02.085588613 -0500
+++ fltk-devel/FL/Fl_Copy_Surface.H	2014-02-25 19:29:01.455172156 -0500
@@ -1,13 +1,14 @@
 #include <FL/Fl_Paged_Device.H>
 #include <FL/Fl_Printer.H>
 
-#if defined(__APPLE__) || defined(WIN32) || defined(FL_DOXYGEN)
-
-
 #if defined(__APPLE__)
 #include <ApplicationServices/ApplicationServices.h>
 #endif
 
+#if defined(USE_X11)
+#include <FL/x.H>
+#endif
+
 /** A class that supports copying of graphical data to the clipboard (MSWindows and Mac OS only).
  
  This class is implemented only on the MSWindows and Mac OS platforms.
@@ -34,7 +35,13 @@
  clipboard content is pasted can use the flavor that suits them best.
  
  */
+#if defined(__APPLE__) || defined(WIN32) || defined(FL_DOXYGEN)
 class Fl_Copy_Surface : public Fl_System_Printer {
+  typedef Fl_System_Printer Base;
+#else // Xlib
+class Fl_Copy_Surface : public Fl_Paged_Device {
+  typedef Fl_Paged_Device Base;
+#endif
 private:
   int width;
   int height;
@@ -51,6 +58,10 @@
 #elif defined(WIN32)
   HDC oldgc;
   HDC           gc;
+#else // Xlib
+  Fl_Offscreen xid;
+  Window oldwindow;
+  Fl_Xlib_Graphics_Driver *my_driver;
 #endif
 public:
   static const char *class_id;
@@ -65,4 +76,4 @@
 #endif
 };
 
-#endif
+
diff -ur fltk-copy-image/FL/Fl.H fltk-devel/FL/Fl.H
--- fltk-copy-image/FL/Fl.H	2014-01-31 16:51:53.000000000 -0500
+++ fltk-devel/FL/Fl.H	2014-02-25 19:27:12.830633519 -0500
@@ -765,6 +765,9 @@
   clipboard is used for traditional copy/cut/paste operations.
   */
   static void copy(const char* stuff, int len, int destination = 0); // platform dependent
+#if !(defined(__APPLE__) || defined(WIN32))
+  static void copy_image(const unsigned char* data, int W, int H, int destination = 0); // platform dependent
+#endif
   /**
   Pastes the data from the selection buffer (\p source is 0) or the clipboard 
   (\p source is 1) into \p receiver.  
diff -ur fltk-copy-image/src/Fl_Copy_Surface.cxx fltk-devel/src/Fl_Copy_Surface.cxx
--- fltk-copy-image/src/Fl_Copy_Surface.cxx	2014-02-25 20:04:02.085588613 -0500
+++ fltk-devel/src/Fl_Copy_Surface.cxx	2014-02-25 19:48:16.580900116 -0500
@@ -1,6 +1,5 @@
-
-#if defined(__APPLE__) || defined(WIN32) || defined(FL_DOXYGEN)
 #include <FL/Fl_Copy_Surface.H>
+#include <FL/Fl.H>
 
 const char *Fl_Copy_Surface::class_id = "Fl_Copy_Surface";
 
@@ -8,7 +7,7 @@
  \param w and \param h are the width and height of the clipboard surface
  in points where drawing will occur.
  */
-Fl_Copy_Surface::Fl_Copy_Surface(int w, int h) : Fl_System_Printer()
+Fl_Copy_Surface::Fl_Copy_Surface(int w, int h) : Base()
 {
   width = w;
   height = h;
@@ -39,6 +38,15 @@
   Fl_Graphics_Driver* d = driver();
   delete d;
   driver(new Fl_GDI_Graphics_Driver); // don't use the printer driver
+#else // Xlib
+  oldwindow = fl_window;
+  xid = fl_create_offscreen(w,h);
+  my_driver = new Fl_Xlib_Graphics_Driver();
+  start_job(1,NULL,NULL);
+  start_page();
+  int AW,AH;
+  int res=printable_rect(&AW,&AH);
+  origin(0,0);
 #endif
 }
 
@@ -48,6 +56,7 @@
 {
 #ifdef __APPLE__
   complete_copy_pdf_and_tiff();
+  fl_gc = oldgc;
 #elif defined(WIN32)
   if(oldgc == fl_gc) oldgc = NULL;
   HENHMETAFILE hmf = CloseEnhMetaFile (gc);
@@ -60,15 +69,30 @@
     DeleteEnhMetaFile(hmf);
   }
   DeleteDC(gc);
-#endif
   fl_gc = oldgc;
+#else // Xlib
+  fl_window = xid;
+  unsigned char *data=fl_read_image(NULL,0,0,width,height,0);
+  Fl::copy_image(data,width,height,1);
+  delete[] data;
+  end_page();
+  end_job();
+  fl_delete_offscreen(xid);
+  fl_window = oldwindow;
+#endif
 }
 
 void Fl_Copy_Surface::set_current()
 {
+#if defined(__APPLE__) || defined(WIN32) || defined(FL_DOXYGEN)
   fl_gc = gc;
   fl_window = (Window)1;
   Fl_Surface_Device::set_current();
+#else
+  fl_window = xid;
+  fl_graphics_driver = my_driver;
+  fl_draw_box(FL_UP_BOX,0,0,300,300,FL_RED);
+#endif
 }
 
 
@@ -224,4 +248,4 @@
 }
 #endif //__APPLE__
 
-#endif // defined(__APPLE__) || defined(WIN32)
+
diff -ur fltk-copy-image/src/Fl_x.cxx fltk-devel/src/Fl_x.cxx
--- fltk-copy-image/src/Fl_x.cxx	2014-02-06 19:09:52.000000000 -0500
+++ fltk-devel/src/Fl_x.cxx	2014-02-25 19:47:26.104649822 -0500
@@ -335,6 +336,7 @@
 Atom fl_XaCompoundText;
 Atom fl_XaUtf8String;
 Atom fl_XaTextUriList;
+Atom fl_XaImageBmp;
 Atom fl_NET_WM_NAME;			// utf8 aware window label
 Atom fl_NET_WM_ICON_NAME;		// utf8 aware window icon name
 Atom fl_NET_SUPPORTING_WM_CHECK;
@@ -641,6 +644,7 @@
   fl_XaCompoundText     = XInternAtom(d, "COMPOUND_TEXT",       0);
   fl_XaUtf8String       = XInternAtom(d, "UTF8_STRING",         0);
   fl_XaTextUriList      = XInternAtom(d, "text/uri-list",       0);
+  fl_XaImageBmp         = XInternAtom(d, "image/bmp",           0);
   fl_NET_WM_NAME        = XInternAtom(d, "_NET_WM_NAME",        0);
   fl_NET_WM_ICON_NAME   = XInternAtom(d, "_NET_WM_ICON_NAME",   0);
   fl_NET_SUPPORTING_WM_CHECK = XInternAtom(d, "_NET_SUPPORTING_WM_CHECK", 0);
@@ -773,6 +777,9 @@
 Fl_Widget *fl_selection_requestor;
 char *fl_selection_buffer[2];
 int fl_selection_length[2];
+#define FL_SELECTION_TEXT 0
+#define FL_SELECTION_IMAGE 1
+int fl_selection_type[2];
 int fl_selection_buffer_length[2];
 char fl_i_own_selection[2] = {0,0};
 
@@ -782,6 +789,8 @@
     // 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_SELECTION_TEXT) return;
     Fl::e_text = fl_selection_buffer[clipboard];
     Fl::e_length = fl_selection_length[clipboard];
     if (!Fl::e_text) Fl::e_text = (char *)"";
@@ -870,6 +879,77 @@
   fl_selection_buffer[clipboard][len] = 0; // needed for direct paste
   fl_selection_length[clipboard] = len;
   fl_i_own_selection[clipboard] = 1;
+  fl_selection_type[clipboard] = FL_SELECTION_TEXT;
+  Atom property = clipboard ? CLIPBOARD : XA_PRIMARY;
+  XSetSelectionOwner(fl_display, property, fl_message_window, fl_event_time);
+}
+
+static void write_short(unsigned char **cp,short i){
+  unsigned char *c=*cp;
+  *c++=i&0xFF;i>>=8;
+  *c++=i&0xFF;i>>=8;
+  *cp=c;
+}
+
+static void write_int(unsigned char **cp,int i){
+  unsigned char *c=*cp;
+  *c++=i&0xFF;i>>=8;
+  *c++=i&0xFF;i>>=8;
+  *c++=i&0xFF;i>>=8;
+  *c++=i&0xFF;i>>=8;
+  *cp=c;
+}
+
+static unsigned char *create_bmp(const unsigned char *data, int W, int H, int *return_size){
+  int R=(3*W+3)/4 * 4; // the number of bytes per row, rounded up to multiple of 4
+  int s=H*R;
+  int fs=14+40+s;
+  unsigned char *b=new unsigned char[fs];
+  unsigned char *c=b;
+  // BMP header
+  *c++='B';
+  *c++='M';
+  write_int(&c,fs);
+  write_int(&c,0);
+  write_int(&c,14+40);
+  // DIB header:
+  write_int(&c,40);
+  write_int(&c,W);
+  write_int(&c,H);
+  write_short(&c,1);
+  write_short(&c,24);//bits ber pixel
+  write_int(&c,0);//RGB
+  write_int(&c,s);
+  write_int(&c,0);// horizontal resolution
+  write_int(&c,0);// vertical resolution
+  write_int(&c,0);//number of colors. 0 -> 1<<bits_per_pixel
+  write_int(&c,0);
+  // Pixel data
+  data+=3*W*H;
+  for (int y=0;y<H;++y){
+    data-=3*W;
+    const unsigned char *s=data;
+    unsigned char *p=c;
+    for (int x=0;x<W;++x){
+      *p++=s[0];
+      *p++=s[1];
+      *p++=s[2];
+      s+=3;
+    }
+    c+=R;
+  }
+  *return_size = fs;
+  return b;
+}
+
+void Fl::copy_image(const unsigned char *data, int W, int H, int clipboard){
+  if(!data || W<=0 || H<=0) return;
+  delete[] fl_selection_buffer[clipboard];
+  fl_selection_buffer[clipboard] = (char *) create_bmp(data,W,H,&fl_selection_length[clipboard]);
+  fl_selection_buffer_length[clipboard] = fl_selection_length[clipboard];
+  fl_i_own_selection[clipboard] = 1;
+  fl_selection_type[clipboard] = FL_SELECTION_IMAGE;
+
   Atom property = clipboard ? CLIPBOARD : XA_PRIMARY;
   XSetSelectionOwner(fl_display, property, fl_message_window, fl_event_time);
 }
@@ -1242,32 +1363,54 @@
     e.target = fl_xevent->xselectionrequest.target;
     e.time = fl_xevent->xselectionrequest.time;
     e.property = fl_xevent->xselectionrequest.property;
-    if (e.target == TARGETS) {
-      Atom a[3] = {fl_XaUtf8String, XA_STRING, fl_XaText};
-      XChangeProperty(fl_display, e.requestor, e.property,
-                      XA_ATOM, atom_bits, 0, (unsigned char*)a, 3);
-    } else if (/*e.target == XA_STRING &&*/ fl_selection_length[clipboard]) {
-    if (e.target == fl_XaUtf8String ||
-	     e.target == XA_STRING ||
-	     e.target == fl_XaCompoundText ||
-	     e.target == fl_XaText ||
-	     e.target == fl_Xatextplain ||
-	     e.target == fl_Xatextplainutf ||
-	     e.target == fl_Xatextplainutf2) {
-	// clobber the target type, this seems to make some applications
-	// behave that insist on asking for XA_TEXT instead of UTF8_STRING
-	// Does not change XA_STRING as that breaks xclipboard.
-	if (e.target != XA_STRING) e.target = fl_XaUtf8String;
+    if (fl_selection_type[clipboard] == FL_SELECTION_TEXT){
+      if (e.target == TARGETS) {
+	Atom a[3] = {fl_XaUtf8String, XA_STRING, fl_XaText};
+	XChangeProperty(fl_display, e.requestor, e.property,
+	                XA_ATOM, atom_bits, 0, (unsigned char*)a, 3);
+      } else {
+	if (/*e.target == XA_STRING &&*/ fl_selection_length[clipboard]) {
+	  if (e.target == fl_XaUtf8String ||
+	      e.target == XA_STRING ||
+	      e.target == fl_XaCompoundText ||
+	      e.target == fl_XaText ||
+	      e.target == fl_Xatextplain ||
+	      e.target == fl_Xatextplainutf ||
+	      e.target == fl_Xatextplainutf2) {
+	    // clobber the target type, this seems to make some applications
+	    // behave that insist on asking for XA_TEXT instead of UTF8_STRING
+	    // Does not change XA_STRING as that breaks xclipboard.
+	    if (e.target != XA_STRING) e.target = fl_XaUtf8String;
+	    XChangeProperty(fl_display, e.requestor, e.property,
+		            e.target, 8, 0,
+		            (unsigned char *)fl_selection_buffer[clipboard],
+		            fl_selection_length[clipboard]);
+	  }
+	} else {
+	  //    char* x = XGetAtomName(fl_display,e.target);
+	  //    fprintf(stderr,"selection request of %s\n",x);
+	  //    XFree(x);
+	  e.property = 0;
+	}
+      }
+    } else { // image in clipboard
+      if (e.target == TARGETS) {
+	Atom a[1] = {fl_XaImageBmp};
 	XChangeProperty(fl_display, e.requestor, e.property,
-			 e.target, 8, 0,
-			 (unsigned char *)fl_selection_buffer[clipboard],
-			 fl_selection_length[clipboard]);
+	                XA_ATOM, atom_bits, 0, (unsigned char*)a, 1);
+      } else {
+	if (e.target == fl_XaImageBmp && fl_selection_length[clipboard]) {
+	    XChangeProperty(fl_display, e.requestor, e.property,
+		            e.target, 8, 0,
+		            (unsigned char *)fl_selection_buffer[clipboard],
+		            fl_selection_length[clipboard]);
+	} else {
+	  //    char* x = XGetAtomName(fl_display,e.target);
+	  //    fprintf(stderr,"selection request of %s\n",x);
+	  //    XFree(x);
+	  e.property = 0;
+	}
       }
-    } else {
-//    char* x = XGetAtomName(fl_display,e.target);
-//    fprintf(stderr,"selection request of %s\n",x);
-//    XFree(x);
-      e.property = 0;
     }
     XSendEvent(fl_display, e.requestor, 0, 0, (XEvent *)&e);}
     return 1;
diff -ur fltk-copy-image/test/device.cxx fltk-devel/test/device.cxx
--- fltk-copy-image/test/device.cxx	2014-02-25 20:04:02.085588613 -0500
+++ fltk-devel/test/device.cxx	2014-02-25 19:29:01.455172156 -0500
@@ -564,19 +564,15 @@
   delete p;
 }
 
-#if defined(__APPLE__) || defined(WIN32)
 #include <FL/Fl_Copy_Surface.H>
-#endif
 
 void copy(Fl_Widget *, Fl_Widget *w) {
-#if defined(__APPLE__) || defined(WIN32)
   Fl_Window* g =  w->window();
   Fl_Copy_Surface *copy_surf = new Fl_Copy_Surface(g->w(), g->h());
   copy_surf->set_current();
   copy_surf->print_widget(g);
   delete copy_surf;
   Fl_Display_Device::display_device()->set_current();  
-#endif
 }
 
 /*void print2(Fl_Widget *, void *w) {
