Index: src/Fl_Copy_Surface.cxx
===================================================================
--- src/Fl_Copy_Surface.cxx	(revision 0)
+++ src/Fl_Copy_Surface.cxx	(revision 0)
@@ -0,0 +1,329 @@
+#include <FL/Fl_Copy_Surface.H>
+#include <FL/Fl.H>
+
+#if defined(__APPLE__) && defined(__ppc__)
+#include <QuickTime/QuickTimeComponents.h>
+#endif
+
+#if defined(__APPLE__)
+
+/* Mac class to reimplement Fl_Paged_Device::printable_rect() */
+class Fl_mac_Printer_With_Size : public Fl_System_Printer {
+  int width;
+  int height;
+public:
+  Fl_mac_Printer_With_Size(int w, int h) : Fl_System_Printer(), width(w), height(h) {};
+  virtual int printable_rect(int *w, int *h) {
+    *w = width;
+    *h = height;
+    return 0;
+    }
+  virtual ~Fl_mac_Printer_With_Size() {};
+};
+
+#elif defined(WIN32)
+
+/* Win class to change the graphics driver of Fl_System_Printer */
+class Fl_win_Helper : public Fl_System_Printer {
+  int width;
+  int height;
+public:
+  Fl_win_Helper() : Fl_System_Printer() {
+    delete driver();
+    driver(new Fl_GDI_Graphics_Driver);
+  };
+  virtual ~Fl_win_Helper() {};
+};
+
+#else
+
+/* When the current graphics driver is an Fl_Xlib_Graphics_Driver, it's not possible to
+ apply a (delta_x,delta_y) translation to drawing coordinates. The print_widget()
+ function is thus re-implemented here. The position of all children of a subwindow
+ is moved by (delta_x,delta_y), then the subwindow is drawn, and children are put
+ back in position. Furthermore, in Fl_Paged_Device::print_widget(), use_xlib_algo is 
+ true when the widget is a subwindow, and allows correct drawing of the subwindow's box.
+*/
+class Fl_Xlib_Paged_Device : public Fl_Paged_Device {
+  int oldx, oldy;
+public:
+  Fl_Xlib_Paged_Device() : Fl_Paged_Device() {};
+  virtual void print_widget(Fl_Widget* w, int delta_x = 0, int delta_y = 0) {
+    Fl_Group *g;
+    Fl_Widget*const* a;
+    bool doit = w->as_window() && w->window() && (delta_x || delta_y);
+    if (doit) { // a subwindow
+      g = w->as_window();
+      a = g->array();
+      for (int i=g->children(); i--;) { // move all its children by delta_x|y
+	Fl_Widget* o = *a++;
+	o->position(o->x()+delta_x, o->y()+delta_y);
+	}
+      }
+    Fl_Paged_Device::print_widget(w);
+    if (doit) {
+      a = g->array();
+      for (int i=g->children(); i--;) { // move all children back to their position
+	Fl_Widget* o = *a++;
+	o->position(o->x()-delta_x, o->y()-delta_y);
+      }
+    }
+  }
+  virtual ~Fl_Xlib_Paged_Device() {};
+};
+
+#endif
+
+
+const char *Fl_Copy_Surface::class_id = "Fl_Copy_Surface";
+
+/** Constructor. 
+ \param w and \param h are the width and height of the clipboard surface
+ in pixels where drawing will occur.
+ */
+Fl_Copy_Surface::Fl_Copy_Surface(int w, int h) :  Fl_Surface_Device(NULL)
+{
+  width = w;
+  height = h;
+#ifdef __APPLE__
+  helper = new Fl_mac_Printer_With_Size(width, height);
+  driver(helper->driver());
+  prepare_copy_pdf_and_tiff(w, h);
+  oldgc = fl_gc;
+#elif defined(WIN32)
+  helper = new Fl_win_Helper();
+  driver(helper->driver());
+  oldgc = fl_gc;
+  // exact computation of factor from screen units to EnhMetaFile units (0.01 mm)
+  HDC hdc = GetDC(NULL);
+  int hmm = GetDeviceCaps(hdc, HORZSIZE);
+  int hdots = GetDeviceCaps(hdc, HORZRES);
+  int vmm = GetDeviceCaps(hdc, VERTSIZE);
+  int vdots = GetDeviceCaps(hdc, VERTRES);
+  ReleaseDC(NULL, hdc);
+  float factorw =  (100. * hmm) / hdots;
+  float factorh =  (100. * vmm) / vdots + 0.5;
+  
+  RECT rect; rect.left = 0; rect.top = 0; rect.right = w * factorw; rect.bottom = h * factorh;
+  gc = CreateEnhMetaFile (NULL, NULL, &rect, NULL);
+  if (gc != NULL) {
+    SetGraphicsMode(gc, GM_ADVANCED); // needed for ModifyWorldTransform()
+    SetTextAlign(gc, TA_BASELINE|TA_LEFT);
+    SetBkMode(gc, TRANSPARENT);
+  } 
+#else // Xlib
+  helper = new Fl_Xlib_Paged_Device();
+  driver(Fl_Display_Device::display_device()->driver());
+  Fl::check();
+  Fl::first_window()->make_current();
+  oldwindow = fl_xid(Fl::first_window());
+  xid = fl_create_offscreen(w,h);
+  Fl_Surface_Device *present_surface = Fl_Surface_Device::surface();
+  set_current();
+  fl_push_no_clip();
+  fl_color(FL_WHITE);
+  fl_rectf(0, 0, w, h);
+  present_surface->set_current();
+#endif
+}
+
+/** Destructor.
+ */
+Fl_Copy_Surface::~Fl_Copy_Surface()
+{
+#ifdef __APPLE__
+  complete_copy_pdf_and_tiff();
+  fl_gc = oldgc;
+  delete (Fl_mac_Printer_With_Size*)helper;
+#elif defined(WIN32)
+  if(oldgc == fl_gc) oldgc = NULL;
+  HENHMETAFILE hmf = CloseEnhMetaFile (gc);
+  if ( hmf != NULL ) {
+    if ( OpenClipboard (NULL) ){
+      EmptyClipboard ();
+      SetClipboardData (CF_ENHMETAFILE, hmf);
+      CloseClipboard ();
+    }
+    DeleteEnhMetaFile(hmf);
+  }
+  DeleteDC(gc);
+  fl_gc = oldgc;
+  delete (Fl_win_Helper*)helper;
+#else // Xlib
+  fl_pop_clip(); 
+  fl_window = xid;
+  unsigned char *data=fl_read_image(NULL,0,0,width,height,0);
+  Fl::copy_image(data,width,height,1);
+  delete[] data;
+  fl_delete_offscreen(xid);
+  fl_window = oldwindow;
+  delete (Fl_Xlib_Paged_Device*)helper;
+#endif
+}
+
+/** To draw any kind of FLTK widget in the clipboard.
+ */
+void Fl_Copy_Surface::draw(Fl_Widget* widget) 
+{
+#if defined(__APPLE__)|| defined(WIN32)
+  helper->print_widget(widget);
+#else
+  /* Here, it's not possible to apply a translation to graphics coordinates,
+   so the widget is temporarily translated before drawing.
+   */
+  int new_x = 0, new_y = 0;
+  if (!widget->as_window()) {
+    new_x = widget->x();
+    new_y = widget->y();
+  }
+  if (new_x || new_y) {
+    widget->position(widget->x() - new_x, widget->y() - new_y );
+  }
+  helper->print_widget(widget);
+  if (new_x || new_y) {
+    widget->position(widget->x() + new_x, widget->y() + new_y );
+  }
+#endif
+}
+
+void Fl_Copy_Surface::set_current()
+{
+#if defined(__APPLE__) || defined(WIN32)
+  fl_gc = gc;
+  fl_window = (Window)1;
+#else
+  fl_window=xid;
+#endif
+  Fl_Surface_Device::set_current();
+}
+
+
+#if defined(__APPLE__)
+
+size_t Fl_Copy_Surface::MyPutBytes(void* info, const void* buffer, size_t count)
+  {
+  CFDataAppendBytes ((CFMutableDataRef) info, (const UInt8 *)buffer, count);
+  return count;
+}
+
+void Fl_Copy_Surface::init_PDF_context(int w, int h)
+{
+  CGRect bounds = CGRectMake(0, 0, w, h );	
+  pdfdata = CFDataCreateMutable(NULL, 0);
+  CGDataConsumerRef myconsumer;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
+  if(CGDataConsumerCreateWithCFData != NULL) {
+    myconsumer = CGDataConsumerCreateWithCFData(pdfdata); // 10.4
+  }
+  else 
+#endif
+  {
+    static CGDataConsumerCallbacks callbacks = { Fl_Copy_Surface::MyPutBytes, NULL };
+    myconsumer = CGDataConsumerCreate ((void*) pdfdata, &callbacks);
+  }
+  gc = CGPDFContextCreate (myconsumer, &bounds, NULL);
+  CGDataConsumerRelease (myconsumer);
+}
+
+void Fl_Copy_Surface::prepare_copy_pdf_and_tiff(int w, int h)
+{
+  init_PDF_context(w, h);
+  if (gc == NULL) return;
+  CGRect bounds = CGRectMake(0, 0, w, h );	
+  CGContextBeginPage (gc, &bounds);
+  CGContextTranslateCTM(gc, 0, h);
+  CGContextScaleCTM(gc, 1.0f, -1.0f);
+  CGContextSaveGState(gc);
+}
+
+static void bitmap_to_tiff_clipboard(CGContextRef c, PasteboardRef clipboard)
+{
+  if (fl_mac_os_version >= 100400) {
+    CFStringRef tiff = CFSTR("public.tiff");
+    CFMutableDataRef data = CFDataCreateMutable(NULL, 0);
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
+    CGImageRef image = CGBitmapContextCreateImage(c); // 10.4
+    CGImageDestinationRef dest = CGImageDestinationCreateWithData(data,tiff, 1, NULL); // 10.4
+    CGImageDestinationAddImage(dest, image, NULL); // 10.4
+    CGImageDestinationFinalize(dest); // 10.4
+    CGImageRelease(image);
+    CFRelease(dest);
+#endif
+    PasteboardPutItemFlavor(clipboard, (PasteboardItemID)1, tiff, data, kPasteboardFlavorNoFlags );
+    CFRelease(data);
+    }
+  else {
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 && defined(__ppc__)
+#warning Compilation with -mmacosx-version-min=10.3 requires -framework QuickTime at link time
+	GraphicsExportComponent exporter;
+   	OSErr err = OpenADefaultComponent(GraphicsExporterComponentType, /*kQTFileTypePicture*/ 'PICT', &exporter);
+   	ComponentResult cerr = GraphicsExportSetInputCGBitmapContext(exporter, c); // 10.3 -framework QuickTime
+   	Handle dataHandle = NewHandle(0);
+   	cerr = GraphicsExportSetOutputHandle(exporter, dataHandle); // -framework QuickTime
+  	unsigned long size;
+   	cerr = GraphicsExportDoExport(exporter, &size); // -framework QuickTime
+   	err = CloseComponent(exporter);
+   	if (GetHandleSize(dataHandle) > 512) {
+     	HLock(dataHandle);
+     	// The clipboard REQUIRES only the image data, not the header.
+     	CFDataRef pictdata = CFDataCreate(NULL, (const UInt8 *)*dataHandle + 512, GetHandleSize(dataHandle) - 512);
+     	HUnlock(dataHandle);
+     	PasteboardPutItemFlavor(clipboard, (PasteboardItemID)1,
+					 	CFSTR("com.apple.pict"),
+					 	pictdata,
+					 	kPasteboardFlavorNoFlags );
+     	CFRelease(pictdata);
+     	}
+   	DisposeHandle(dataHandle);
+#endif
+  }
+}
+
+
+void Fl_Copy_Surface::complete_copy_pdf_and_tiff()
+{
+  CGContextRestoreGState(gc);
+  CGContextEndPage(gc);
+  CGContextRelease(gc);
+  PasteboardRef clipboard = NULL;
+  PasteboardCreate(kPasteboardClipboard, &clipboard);
+  PasteboardClear(clipboard); //	first, copy PDF to clipboard 
+  PasteboardPutItemFlavor (clipboard, (PasteboardItemID)1, 
+			   CFSTR("com.adobe.pdf"), // kUTTypePDF
+			   pdfdata, kPasteboardFlavorNoFlags);
+  //second, transform this PDF to a bitmap image and put it as tiff in clipboard
+  CGDataProviderRef prov;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
+  if(fl_mac_os_version >= 100400)
+    prov = CGDataProviderCreateWithCFData(pdfdata); // 10.4
+  else 
+#endif
+    prov = CGDataProviderCreateWithData(NULL, CFDataGetBytePtr(pdfdata), CFDataGetLength(pdfdata), NULL);
+  CGPDFDocumentRef pdfdoc = CGPDFDocumentCreateWithProvider(prov);
+  CGPDFPageRef pdfpage = CGPDFDocumentGetPage(pdfdoc, 1);
+  CGDataProviderRelease(prov);
+  CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
+  void *mem = ( fl_mac_os_version >= 100600 ? NULL : malloc(width * height * 4) );
+  gc = CGBitmapContextCreate(mem, width, height, 8, width * 4, space, kCGImageAlphaNoneSkipLast);
+  CFRelease(space);
+  if (gc == NULL) { if (mem) free(mem); return; }
+  CGRect rect = CGRectMake(0, 0, width, height);
+  CGContextSetRGBFillColor(gc,  1,1,1,1);//need to clear background
+  CGContextFillRect(gc, rect);
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+  CGContextDrawPDFPage(gc, pdfpage);  // requires 10.3
+#endif
+  CGPDFDocumentRelease(pdfdoc);
+  CFRelease(pdfdata);
+  bitmap_to_tiff_clipboard(gc, clipboard);
+  CFRelease(clipboard);    
+  CGContextRelease(gc);
+  if (mem) free(mem);
+}
+
+#endif  // __APPLE__
+
+
+
+
+
Index: src/Fl_x.cxx
===================================================================
--- src/Fl_x.cxx	(revision 10113)
+++ src/Fl_x.cxx	(working copy)
@@ -335,6 +335,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 +642,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 +775,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 +787,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,10 +877,81 @@
   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[2];
+      *p++=s[1];
+      *p++=s[0];
+      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);
+}
+
 ////////////////////////////////////////////////////////////////
 // Code for tracking clipboard changes:
 
@@ -1242,32 +1320,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,
-			 e.target, 8, 0,
-			 (unsigned char *)fl_selection_buffer[clipboard],
-			 fl_selection_length[clipboard]);
+	                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 {
-//    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,
+	                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;
+	}
+      }
     }
     XSendEvent(fl_display, e.requestor, 0, 0, (XEvent *)&e);}
     return 1;
Index: src/Fl_Paged_Device.cxx
===================================================================
--- src/Fl_Paged_Device.cxx	(revision 10113)
+++ src/Fl_Paged_Device.cxx	(working copy)
@@ -20,12 +20,12 @@
  */
 
 #include <FL/Fl_Paged_Device.H>
+#include <FL/Fl_Box.H>
 #include <FL/Fl.H>
 #include <FL/fl_draw.H>
 
 const char *Fl_Paged_Device::class_id = "Fl_Paged_Device";
 
-
 /**
  @brief Draws the widget on the printed page.
  *
@@ -55,8 +55,16 @@
   if (new_x != old_x || new_y != old_y) {
     translate(new_x - old_x, new_y - old_y );
   }
-  // if widget is a window, clip all drawings to the window area
-  if (is_window) fl_push_clip(0, 0, widget->w(), widget->h() );
+  // if widget is a main window, clip all drawings to the window area
+  if (is_window && !widget->window()) {
+      fl_push_clip(0, 0, widget->w(), widget->h() );
+    }
+#if defined(__APPLE__)|| defined(WIN32)
+  bool use_xlib_algo = false;
+#else
+  bool use_xlib_algo = 
+      (is_window && widget->window() && fl_graphics_driver->class_name() == Fl_Xlib_Graphics_Driver::class_id);
+#endif
   // we do some trickery to recognize OpenGL windows and draw them via a plugin
   int drawn_by_plugin = 0;
   if (widget->as_gl_window()) {
@@ -68,13 +76,27 @@
       int width;
       this->printable_rect(&width, &height);
 #endif
-      drawn_by_plugin = pi->print(widget, 0, 0, height);
+      if (use_xlib_algo) 
+	drawn_by_plugin = pi->print(widget, widget->x(), widget->y(), height);
+      else	
+	drawn_by_plugin = pi->print(widget, 0, 0, height);
     }
   }
   if (!drawn_by_plugin) {
-    widget->draw();
+    if (use_xlib_algo) { // with Xlib, draw separately the subwindow box and its content
+      Fl_Boxtype box_t = widget->box();
+      Fl_Group::current(0);
+      Fl_Box *box = new Fl_Box(box_t, widget->x(), widget->y(), widget->w(), widget->h(), NULL);
+      ((Fl_Widget*)box)->draw(); // draw the box at its right place
+      delete box;
+      widget->box(FL_NO_BOX);
+      widget->draw(); // draw the subwindow content
+      widget->box(box_t);
+      }
+    else
+      widget->draw();
   }
-  if (is_window) fl_pop_clip();
+  if (is_window && !widget->window()) fl_pop_clip();
   // find subwindows of widget and print them
   traverse(widget);
   // reset origin to where it was
Index: FL/Fl.H
===================================================================
--- FL/Fl.H	(revision 10113)
+++ FL/Fl.H	(working copy)
@@ -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.  
Index: FL/Fl_Copy_Surface.H
===================================================================
--- FL/Fl_Copy_Surface.H	(revision 0)
+++ FL/Fl_Copy_Surface.H	(revision 0)
@@ -0,0 +1,66 @@
+#include <FL/Fl_Paged_Device.H>
+#include <FL/Fl_Printer.H>
+
+#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.
+ 
+ <br> After creation of an Fl_Copy_Surface object, call set_current() on it, and all subsequent graphics requests
+ will be recorded in the clipboard. It's possible to draw widgets (using Fl_Copy_Surface::draw(Fl_Widget*)
+ ) or to use any of the \ref fl_drawings or the \ref fl_attributes.
+ Finally, delete the Fl_Copy_Surface object to load the clipboard with the graphical data.
+ <br> Fl_GL_Window's can be copied to the clipboard as well. 
+ <br> Usage example:
+ \code
+ Fl_Widget *g = ...; // a widget you want to copy to the clipboard
+ Fl_Copy_Surface *copy_surf = new Fl_Copy_Surface(g->w(), g->h()); // create an Fl_Copy_Surface object
+ copy_surf->set_current(); // direct graphics requests to the clipboard
+ copy_surf->draw(g); // draw the g widget in the clipboard
+ delete copy_surf; // after this, the clipboard is loaded
+ Fl_Display_Device::display_device()->set_current();  // direct graphics requests back to the display
+ \endcode
+ Platform details:
+ \li MSWindows: Transparent RGB images copy without transparency.
+ The graphical data is copied to the clipboard as an 'enhanced metafile'.
+ \li Mac OS: Mac OS X 10.4 or higher is necessary. The graphical data is copied to the 
+ clipboard (a.k.a. pasteboard) in 2 'flavors': 
+ 1) in vectorial form as PDF data; 2) in bitmap form as a TIFF image. Applications to which the 
+ clipboard content is pasted can use the flavor that suits them best.
+ \li X11: the graphical data is copied to the clipboard as an image in BMP format.
+*/
+class Fl_Copy_Surface : public Fl_Surface_Device {
+private:
+  int width;
+  int height;
+  Fl_Paged_Device *helper;
+#ifdef __APPLE__
+  CFMutableDataRef pdfdata;
+  CGContextRef oldgc;
+  CGContextRef gc;
+  void prepare_copy_pdf_and_tiff(int w, int h);
+  void complete_copy_pdf_and_tiff();
+  void init_PDF_context(int w, int h);
+  static size_t MyPutBytes(void* info, const void* buffer, size_t count);
+#elif defined(WIN32)
+  HDC oldgc;
+  HDC gc;
+#else // Xlib
+  Fl_Offscreen xid;
+  Window oldwindow;
+#endif
+public:
+  static const char *class_id;
+  const char *class_name() {return class_id;};
+  Fl_Copy_Surface(int w, int h);
+  ~Fl_Copy_Surface();
+  void set_current();
+  void draw(Fl_Widget* widget);
+};
+
+
Index: test/device.cxx
===================================================================
--- test/device.cxx	(revision 10113)
+++ test/device.cxx	(working copy)
@@ -30,9 +30,8 @@
 
 
 #include <FL/Fl_Printer.H>
+#include <FL/Fl_Copy_Surface.H>
 
-//#include "fl_printer_chooser.H"
-
 #include <FL/Fl_File_Chooser.H>
 #include <FL/fl_draw.H>
 
@@ -564,6 +563,16 @@
   delete p;
 }
 
+
+void copy(Fl_Widget *, Fl_Widget *w) {
+  Fl_Window* g =  w->window();
+  Fl_Copy_Surface *copy_surf = new Fl_Copy_Surface(g->w(), g->h());
+  copy_surf->set_current();
+  copy_surf->draw(g);
+  delete copy_surf;
+  Fl_Display_Device::display_device()->set_current();  
+}
+
 /*void print2(Fl_Widget *, void *w) {
  Fl_Widget * g = (Fl_Widget *)w;
  Fl_Printer * p = fl_printer_chooser();
@@ -675,6 +684,8 @@
   c2->end();
   Fl_Button *b4 = new Fl_Button(10,5, 150, 25, "Print");
   b4->callback(print,c2);
+  Fl_Button *b6 = new Fl_Button(170,5, 150, 25, "Copy");
+  b6->callback((Fl_Callback*)copy,c2);
   /*Fl_Button *b5 = new Fl_Button(165,5, 90, 25, "Print");
    b5->tooltip("This is a tooltip");
    b5->callback(print2,c2);*/
