Index: FL/Fl_Bitmap.H
===================================================================
--- FL/Fl_Bitmap.H	(revision 12216)
+++ FL/Fl_Bitmap.H	(working copy)
@@ -3,7 +3,7 @@
 //
 // Bitmap header file for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2010 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -45,15 +45,16 @@
 	    int &X, int &Y, int &W, int &H);
   /** for internal use */
   fl_uintptr_t id_;
+  float cache_scale_; // graphics scaling value when id_ was computed
 
 public:
 
   /** The constructors create a new bitmap from the specified bitmap data */
   Fl_Bitmap(const uchar *bits, int W, int H) :
-    Fl_Image(W,H,0), array(bits), alloc_array(0), id_(0) {data((const char **)&array, 1);}
+    Fl_Image(W,H,0), array(bits), alloc_array(0), id_(0), cache_scale_(1) {data((const char **)&array, 1);}
   /** The constructors create a new bitmap from the specified bitmap data */
   Fl_Bitmap(const char *bits, int W, int H) :
-    Fl_Image(W,H,0), array((const uchar *)bits), alloc_array(0), id_(0) {data((const char **)&array, 1);}
+    Fl_Image(W,H,0), array((const uchar *)bits), alloc_array(0), id_(0), cache_scale_(1) {data((const char **)&array, 1);}
   virtual ~Fl_Bitmap();
   virtual Fl_Image *copy(int W, int H);
   Fl_Image *copy() { return copy(w(), h()); }
Index: FL/Fl_Gl_Window_Driver.H
===================================================================
--- FL/Fl_Gl_Window_Driver.H	(revision 12216)
+++ FL/Fl_Gl_Window_Driver.H	(working copy)
@@ -4,7 +4,7 @@
 // Definition of classes  Fl_Graphics_Driver, Fl_Surface_Device, Fl_Display_Device
 // for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 2016 by Bill Spitzak and others.
+// Copyright 2016-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -156,6 +156,7 @@
 class Fl_X11_Gl_Window_Driver : public Fl_Gl_Window_Driver {
   friend class Fl_Gl_Window_Driver;
   Fl_X11_Gl_Window_Driver(Fl_Gl_Window *win) : Fl_Gl_Window_Driver(win) {}
+  virtual float pixels_per_unit();
   virtual void before_show(int& need_redraw);
   virtual int mode_(int m, const int *a);
   virtual void swap_buffers();
Index: FL/Fl_Graphics_Driver.H
===================================================================
--- FL/Fl_Graphics_Driver.H	(revision 12216)
+++ FL/Fl_Graphics_Driver.H	(working copy)
@@ -167,6 +167,10 @@
   virtual Fl_Bitmask create_bitmask(int w, int h, const uchar *array) {return 0; }
   /** Support function for image drawing */
   virtual void delete_bitmask(Fl_Bitmask bm) {}
+  static void change_image_size(Fl_Image *img, int W, int H) {
+    img->w(W);
+    img->h(H);
+  }
   // Support function for image drawing
   virtual void uncache_pixmap(fl_uintptr_t p);
   // accessor functions to protected image members
@@ -177,6 +181,9 @@
   static fl_uintptr_t* id(Fl_Bitmap *bm) {return &(bm->id_);}
   static fl_uintptr_t* mask(Fl_RGB_Image *rgb) {return &(rgb->mask_);}
   static fl_uintptr_t* mask(Fl_Pixmap *pm) {return &(pm->mask_);}
+  static float* cache_scale(Fl_Pixmap *pm) {return &(pm->cache_scale_);}
+  static float* cache_scale(Fl_Bitmap *bm) {return &(bm->cache_scale_);}
+  static float* cache_scale(Fl_RGB_Image *rgb) {return &(rgb->cache_scale_);}
   static Fl_Color* pixmap_bg_color(Fl_Pixmap *pm) {return &(pm->pixmap_bg_color);}
   static void draw_empty(Fl_Image* img, int X, int Y) {img->draw_empty(X, Y);}
   static int prepare(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int &cx, int &cy,
@@ -245,8 +252,6 @@
   virtual void pop_matrix();
   virtual void mult_matrix(double a, double b, double c, double d, double x, double y);
   virtual void rotate(double d);
-  virtual void scale(double x, double y);
-  virtual void scale(double x);
   virtual void translate(double x,double y);
   virtual void begin_points();
   virtual void begin_line();
@@ -346,6 +351,7 @@
   virtual void add_rectangle_to_region(Fl_Region r, int x, int y, int w, int h);
   virtual Fl_Region XRectangleRegion(int x, int y, int w, int h);
   virtual void XDestroyRegion(Fl_Region r);
+  virtual float scale() {return 1;}
   // font support
   virtual const char* get_font_name(Fl_Font fnum, int* ap) {return NULL;}
   virtual int get_font_sizes(Fl_Font fnum, int*& sizep) {return 0;}
@@ -357,6 +363,116 @@
   virtual void font_name(int num, const char *name) {}
 };
 
+#ifndef FL_DOXYGEN
+/* Abstract class Fl_Scalable_Graphics_Driver is platform-independent.
+ It supports the scaling of all graphics coordinates by a
+ float factor helpful to support HiDPI displays.
+ This class does :
+ - compute scaled coordinates
+ - scale the cached offscreen of image objects
+ - scale the pixel arrays used when performing direct image draws
+ - call the member functions of a platform-specific,
+ Fl_Scalable_Graphics_Driver-derived class that do the drawings with adequately 
+ scaled coordinates. The member functions are named with the _unscaled suffix.
+ - scale and unscale the clipping region with member functions of the
+ same derived class called scale_clip() and unscale_clip().
+ 
+ This class is presently used on the X11 platform to support HiDPI.
+ It could also be used on the WIN32 platform.
+ */
+class Fl_Scalable_Graphics_Driver : public Fl_Graphics_Driver {
+public:
+  Fl_Scalable_Graphics_Driver();
+  float scale() { return scale_; }
+  virtual void scale(float f)=0;
+protected:
+  float scale_; // scale between user and graphical coordinates: graphical = user * scale_
+  void cache_size(Fl_Image *img, int &width, int &height);
+  virtual Fl_Region scale_clip(float f)=0;
+  virtual void unscale_clip(Fl_Region)=0;
+  virtual void draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
+  virtual void draw_unscaled(Fl_Pixmap *pxm, float s, int XP, int YP, int WP, int HP, int cx, int cy)=0;
+  virtual void draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy);
+  virtual void draw_unscaled(Fl_Bitmap *bm, float s, int XP, int YP, int WP, int HP, int cx, int cy)=0;
+  virtual void draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy);
+  virtual void draw_unscaled(Fl_RGB_Image *img, float s, int XP, int YP, int WP, int HP, int cx, int cy)=0;
+  void draw(Fl_Shared_Image *shared, int X, int Y);
+  virtual void point(int x, int y);
+  virtual void point_unscaled(float x, float y) = 0;
+  virtual void rect(int x, int y, int w, int h);
+  virtual void rect_unscaled(float x, float y, float w, float h) = 0;
+  virtual void rectf(int x, int y, int w, int h);
+  virtual void rectf_unscaled(float x, float y, float w, float h) = 0;
+  virtual void line(int x, int y, int x1, int y1);
+  virtual void line_unscaled(float x, float y, float x1, float y1) = 0;
+  virtual void line(int x, int y, int x1, int y1, int x2, int y2);
+  virtual void line_unscaled(float x, float y, float x1, float y1, float x2, float y2) = 0;
+  virtual void xyline(int x, int y, int x1);
+  virtual void xyline(int x, int y, int x1, int y2);
+  virtual void xyline(int x, int y, int x1, int y2, int x3);
+  virtual void xyline_unscaled(float x, float y, float x1)=0;
+  virtual void xyline_unscaled(float x, float y, float x1, float y2)=0;
+  virtual void xyline_unscaled(float x, float y, float x1, float y2, float x3)=0;
+  virtual void yxline(int x, int y, int y1);
+  virtual void yxline(int x, int y, int y1, int x2);
+  virtual void yxline(int x, int y, int y1, int x2, int y3);
+  virtual void yxline_unscaled(float x, float y, float y1)=0;
+  virtual void yxline_unscaled(float x, float y, float y1, float x2)=0;
+  virtual void yxline_unscaled(float x, float y, float y1, float x2, float y3)=0;
+  virtual void loop(int x0, int y0, int x1, int y1, int x2, int y2);
+  virtual void loop_unscaled(float x0, float y0, float x1, float y1, float x2, float y2)=0;
+  virtual void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
+  virtual void loop_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)=0;
+  virtual void polygon(int x0, int y0, int x1, int y1, int x2, int y2);
+  virtual void polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2)=0;
+  virtual void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
+  virtual void polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)=0;
+  virtual void circle(double x, double y, double r);
+  virtual void ellipse_unscaled(double xt, double yt, double rx, double ry)=0;
+  virtual void font(Fl_Font face, Fl_Fontsize size);
+  virtual void font_unscaled(Fl_Font face, Fl_Fontsize size)=0;
+  virtual double width(const char *str, int n);
+  virtual double width(unsigned int c);
+  virtual double width_unscaled(const char *str, int n)=0;
+  virtual double width_unscaled(unsigned int c)=0;
+  virtual Fl_Fontsize size();
+  virtual Fl_Fontsize size_unscaled()=0;
+  virtual void text_extents(const char *str, int n, int &dx, int &dy, int &w, int &h);
+  virtual void text_extents_unscaled(const char *str, int n, int &dx, int &dy, int &w, int &h)=0;
+  virtual int height();
+  virtual int descent();
+  virtual int height_unscaled()=0;
+  virtual int descent_unscaled()=0;
+  virtual void draw(const char *str, int n, int x, int y);
+  virtual void draw_unscaled(const char *str, int n, int x, int y)=0;
+  virtual void draw(int angle, const char *str, int n, int x, int y);
+  virtual void draw_unscaled(int angle, const char *str, int n, int x, int y)=0;
+  virtual void rtl_draw(const char* str, int n, int x, int y);
+  virtual void rtl_draw_unscaled(const char* str, int n, int x, int y)=0;
+  virtual void arc(int x, int y, int w, int h, double a1, double a2);
+  virtual void arc_unscaled(float x, float y, float w, float h, double a1, double a2)=0;
+  virtual void pie(int x, int y, int w, int h, double a1, double a2);
+  virtual void pie_unscaled(float x, float y, float w, float h, double a1, double a2)=0;
+  virtual void line_style(int style, int width=0, char* dashes=0);
+  virtual void line_style_unscaled(int style, float width, char* dashes)=0;
+  virtual void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
+  virtual void copy_offscreen_unscaled(float x, float y, float w, float h, Fl_Offscreen pixmap, float srcx, float srcy)=0;
+  void draw_image_rescale(void *buf, Fl_Draw_Image_Cb cb, int X, int Y, int W, int H, int D, int L, bool mono, float s);
+  virtual void draw_image_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0)=0;
+  virtual void draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3)=0;
+  void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0);
+  void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3);
+  virtual void draw_image_mono_unscaled(const uchar* buf, int x, int y, int w, int h, int d, int l)=0;
+  void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0);
+  virtual void draw_image_mono_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1)=0;
+  void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1);
+
+  void transformed_vertex(double xf, double yf);
+  virtual void transformed_vertex0(float x, float y)=0;
+  void vertex(double x, double y);
+};
+#endif // FL_DOXYGEN
+
 #endif // FL_GRAPHICS_DRIVER_H
 
 //
Index: FL/Fl_Image.H
===================================================================
--- FL/Fl_Image.H	(revision 12216)
+++ FL/Fl_Image.H	(working copy)
@@ -3,7 +3,7 @@
 //
 // Image header file for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -223,6 +223,7 @@
   // These two variables are used to cache the image and mask for the main display graphics driver
   fl_uintptr_t id_;
   fl_uintptr_t mask_;
+  float cache_scale_; // graphics scaling value when id_ was computed
 
 public:
 
Index: FL/Fl_Pixmap.H
===================================================================
--- FL/Fl_Pixmap.H	(revision 12216)
+++ FL/Fl_Pixmap.H	(working copy)
@@ -3,7 +3,7 @@
 //
 // Pixmap header file for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2012 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -56,6 +56,7 @@
   fl_uintptr_t id_;
   fl_uintptr_t mask_;
   Fl_Color pixmap_bg_color;
+  float cache_scale_; // graphics scaling value when id_ was computed
 
 public:
 
Index: FL/Fl_Screen_Driver.H
===================================================================
--- FL/Fl_Screen_Driver.H	(revision 12216)
+++ FL/Fl_Screen_Driver.H	(working copy)
@@ -3,7 +3,7 @@
 //
 // All screen related calls in a driver style class.
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -54,6 +54,8 @@
   static const int MAX_SCREENS = 16;
 
   int num_screens;
+  static  float fl_intersection(int x1, int y1, int w1, int h1,
+                                      int x2, int y2, int w2, int h2);
 
 public:
   static char bg_set;
@@ -61,6 +63,7 @@
   static char fg_set;
 
 public:
+  virtual float scale(int n) {return 1;}
   static Fl_Screen_Driver *newScreenDriver();
   // --- display management
   virtual void display(const char *disp);
Index: FL/Fl_Window_Driver.H
===================================================================
--- FL/Fl_Window_Driver.H	(revision 12216)
+++ FL/Fl_Window_Driver.H	(working copy)
@@ -4,7 +4,7 @@
 // A base class for platform specific window handling code
 // for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 2010-2016 by Bill Spitzak and others.
+// Copyright 2010-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -56,6 +56,7 @@
   static Fl_Window_Driver *newWindowDriver(Fl_Window *);
   int wait_for_expose_value;
   Fl_Offscreen other_xid; // offscreen bitmap (overlay and double-buffered windows)
+  virtual int screen_num();
 
   // --- frequently used accessors to public window data
   /** returns the x coordinate of the window. */
Index: FL/fl_draw.H
===================================================================
--- FL/fl_draw.H	(revision 12216)
+++ FL/fl_draw.H	(working copy)
@@ -3,7 +3,7 @@
 //
 // Portable drawing function header file for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -335,12 +335,16 @@
  Concatenates scaling transformation onto the current one.
  \param[in] x,y scale factors in x-direction and y-direction
  */
-inline void fl_scale(double x, double y) { fl_graphics_driver->scale(x, y); }
+inline void fl_scale(double x, double y) {
+  fl_graphics_driver->mult_matrix(x,0,0,y,0,0);
+}
 /**
  Concatenates scaling transformation onto the current one.
  \param[in] x scale factor in both x-direction and y-direction
  */
-inline void fl_scale(double x) { fl_graphics_driver->scale(x, x); }
+inline void fl_scale(double x) {
+  fl_graphics_driver->mult_matrix(x,0,0,x,0,0);
+}
 /**
  Concatenates translation transformation onto the current one.
  \param[in] x,y translation factor in x-direction and y-direction
Index: src/Fl_Gl_Window.cxx
===================================================================
--- src/Fl_Gl_Window.cxx	(revision 12216)
+++ src/Fl_Gl_Window.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // OpenGL window code for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -647,6 +647,8 @@
 #if defined(FL_CFG_GFX_XLIB)
 #include <FL/x.H>
 #include "Fl_Gl_Choice.H"
+#include <FL/Fl_Screen_Driver.H>
+#include "src/drivers/X11/Fl_X11_Window_Driver.H"
 
 Fl_Gl_Window_Driver *Fl_Gl_Window_Driver::newGlWindowDriver(Fl_Gl_Window *w)
 {
@@ -658,6 +660,12 @@
   if (overlay() && overlay() != pWindow) ((Fl_Gl_Window*)overlay())->show();
 }
 
+float Fl_X11_Gl_Window_Driver::pixels_per_unit()
+{
+  int ns = pWindow->driver()->screen_num();
+  return Fl::screen_driver()->scale(ns);
+}
+
 int Fl_X11_Gl_Window_Driver::mode_(int m, const int *a) {
   int oldmode = mode();
   if (a) { // when the mode is set using the a array of system-dependent values, and if asking for double buffer,
Index: src/Fl_Graphics_Driver.cxx
===================================================================
--- src/Fl_Graphics_Driver.cxx	(revision 12216)
+++ src/Fl_Graphics_Driver.cxx	(working copy)
@@ -23,6 +23,7 @@
 #include <FL/Fl_Image.H>
 #include <FL/fl_draw.H>
 #include <FL/Fl_Image_Surface.H>
+#include <FL/math.h>
 
 FL_EXPORT Fl_Graphics_Driver *fl_graphics_driver; // the current driver of graphics operations
 
@@ -181,6 +182,347 @@
   fl_delete_offscreen((Fl_Offscreen)p);
 }
 
+
+#ifndef FL_DOXYGEN
+Fl_Scalable_Graphics_Driver::Fl_Scalable_Graphics_Driver() : Fl_Graphics_Driver() {
+  scale_ = 1;
+}
+
+void Fl_Scalable_Graphics_Driver::rect(int x, int y, int w, int h)
+{
+  rect_unscaled(x * scale_, y * scale_, w * scale_, h * scale_);
+}
+
+void Fl_Scalable_Graphics_Driver::rectf(int x, int y, int w, int h)
+{
+  rectf_unscaled(x * scale_, y * scale_, w * scale_, h * scale_);
+}
+
+void Fl_Scalable_Graphics_Driver::point(int x, int y) {
+  point_unscaled(x * scale_, y * scale_);
+}
+
+void Fl_Scalable_Graphics_Driver::line(int x, int y, int x1, int y1) {
+  line_unscaled( x*scale_, y*scale_, x1*scale_, y1*scale_);
+}
+
+void Fl_Scalable_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) {
+  line_unscaled( x*scale_, y*scale_, x1*scale_, y1*scale_, x2*scale_, y2*scale_);
+}
+
+void Fl_Scalable_Graphics_Driver::xyline(int x, int y, int x1) {
+  xyline_unscaled(x*scale_, y*scale_, x1*scale_);
+}
+void Fl_Scalable_Graphics_Driver::xyline(int x, int y, int x1, int y2) {
+  xyline_unscaled(x*scale_, y*scale_, x1*scale_, y2*scale_);
+}
+void Fl_Scalable_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) {
+  xyline_unscaled(x*scale_, y*scale_, x1*scale_, y2*scale_, x3*scale_);
+}
+
+void Fl_Scalable_Graphics_Driver::yxline(int x, int y, int y1) {
+  yxline_unscaled(x*scale_, y*scale_, y1*scale_);
+}
+void Fl_Scalable_Graphics_Driver::yxline(int x, int y, int y1, int x2) {
+  yxline_unscaled(x*scale_, y*scale_, y1*scale_, x2*scale_);
+}
+void Fl_Scalable_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) {
+  yxline_unscaled(x*scale_, y*scale_, y1*scale_, x2*scale_, y3*scale_);
+}
+
+void Fl_Scalable_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2) {
+  loop_unscaled(x0*scale_, y0*scale_, x1*scale_, y1*scale_, x2*scale_, y2*scale_);
+}
+
+void Fl_Scalable_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
+  loop_unscaled(x0*scale_, y0*scale_, x1*scale_, y1*scale_, x2*scale_, y2*scale_, x3*scale_, y3*scale_);
+}
+
+void Fl_Scalable_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2) {
+  polygon_unscaled(x0*scale_, y0*scale_, x1*scale_, y1*scale_, x2*scale_, y2*scale_);
+}
+
+void Fl_Scalable_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
+  polygon_unscaled(x0*scale_, y0*scale_, x1*scale_, y1*scale_, x2*scale_, y2*scale_, x3*scale_, y3*scale_);
+}
+
+void Fl_Scalable_Graphics_Driver::circle(double x, double y, double r) {
+  double xt = transform_x(x,y);
+  double yt = transform_y(x,y);
+  double rx = r * (m.c ? sqrt(m.a*m.a+m.c*m.c) : fabs(m.a));
+  double ry = r * (m.b ? sqrt(m.b*m.b+m.d*m.d) : fabs(m.d));
+  ellipse_unscaled(xt*scale_, yt*scale_, rx*scale_, ry*scale_);
+}
+
+// compute width & height of cached image so it can be tiled without undrawn gaps when scaling output
+void Fl_Scalable_Graphics_Driver::cache_size(Fl_Image *img, int &width, int &height)
+{
+  if ( int(scale_) == scale_ ) {
+    width  = width * scale_;
+    height = height * scale_;
+  } else {
+    width  = (width+1) * scale_;
+    height = (height+1) * scale_;
+  }
+}
+
+
+void Fl_Scalable_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) {
+  int X, Y, W, H;
+  if (Fl_Graphics_Driver::start_image(pxm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) {
+    return;
+  }
+  // to allow rescale at runtime
+  if (*id(pxm)) {
+    if (*cache_scale(pxm) != scale_) {
+      pxm->uncache();
+    }
+  }
+  if (!*id(pxm)) {
+    if (scale_ != 1) { // build a scaled id_ & pixmap_ for pxm
+      int w2=pxm->w(), h2=pxm->h();
+      cache_size(pxm, w2, h2);
+      Fl_Pixmap *pxm2 = (Fl_Pixmap*)pxm->copy(w2, h2);
+      float s = scale_; scale_ = 1;
+      *id(pxm) = cache(pxm2, pxm2->w(), pxm2->h(), pxm2->data());
+      scale_ = s;
+      *cache_scale(pxm) = scale_;
+      *mask(pxm) = *mask(pxm2);
+      *mask(pxm2) = 0;
+      delete pxm2;
+    } else *id(pxm) = cache(pxm, pxm->w(), pxm->h(), pxm->data());
+  }
+  // draw pxm using its scaled id_ & pixmap_
+  draw_unscaled(pxm, scale_, X, Y, W, H, cx, cy);
+}
+
+
+void Fl_Scalable_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) {
+  int X, Y, W, H;
+  if (Fl_Graphics_Driver::start_image(bm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) {
+    return;
+  }
+  if (*id(bm)) {
+    if (*cache_scale(bm) != scale_) {
+      bm->uncache();
+    }
+  }
+  if (!*id(bm)) {
+    if (scale_ != 1) { // build a scaled id_ for bm
+      int w2 = bm->w(), h2 = bm->h();
+      cache_size(bm, w2, h2);
+      Fl_Bitmap *bm2 = (Fl_Bitmap*)bm->copy(w2, h2);
+      *id(bm) = cache(bm2, bm2->w(), bm2->h(), bm2->array);
+      *cache_scale(bm) =  scale_;
+      delete bm2;
+    } else *id(bm) = cache(bm, bm->w(), bm->h(), bm->array);
+  }
+  // draw bm using its scaled id_
+  draw_unscaled(bm, scale_, X, Y, W, H, cx, cy);
+}
+
+
+void Fl_Scalable_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) {
+  // Don't draw an empty image...
+  if (!img->d() || !img->array) {
+    Fl_Graphics_Driver::draw_empty(img, XP, YP);
+    return;
+  }
+  if (start_image(img, XP, YP, WP, HP, cx, cy, XP, YP, WP, HP)) {
+    return;
+  }
+  if (scale() != 1 && can_do_alpha_blending()) { // try and use the system's scaled image drawing
+    push_clip(XP, YP, WP, HP);
+    Fl_Region r = scale_clip(scale_);
+    int w2=img->w(), h2=img->h();
+    cache_size(img, w2, h2);
+    int done = draw_scaled(img, (XP-cx)*scale_, (YP-cy)*scale_, w2, h2);
+    unscale_clip(r);
+    pop_clip();
+    if (done) return;
+  }
+  // to allow rescale at runtime
+  if (*id(img) && *cache_scale(img) != scale_) {
+      img->uncache();
+  }
+  if (scale_ == 1) {
+    draw_unscaled(img, 1, XP, YP, WP, HP, cx, cy);
+    return;
+  }
+  if (!*id(img)) { // build and draw a scaled id_ for img
+    int w2=img->w(), h2=img->h();
+    cache_size(img, w2, h2);
+    Fl_RGB_Image *img2 = (Fl_RGB_Image*)img->copy(w2, h2);
+    draw_unscaled(img2, scale_, XP, YP, WP, HP, cx, cy);
+    *id(img) = *id(img2);
+    *id(img2) = 0;
+    *cache_scale(img) = scale_;
+    delete img2;
+  }
+  else { // draw img using its scaled id_
+    draw_unscaled(img, scale_, XP, YP, WP, HP, cx, cy);
+  }
+}
+
+
+void Fl_Scalable_Graphics_Driver::draw(Fl_Shared_Image *shared, int X, int Y) {
+  if (scale_ == 1) {
+    Fl_Graphics_Driver::draw(shared, X, Y);
+    return;
+  }
+  float s = scale_; scale_ = 1;
+  Fl_Region r2 = scale_clip(s);
+  int oldw=shared->w();
+  int oldh=shared->h();
+  change_image_size(shared, (oldw*s < 1 ? 1: int(oldw*s)), (oldh*s < 1 ? 1: int(oldh*s)));
+  Fl_Graphics_Driver::draw(shared, X*s, Y*s);
+  change_image_size(shared, oldw, oldh);
+  unscale_clip(r2);
+  scale_ = s;
+}
+
+
+void Fl_Scalable_Graphics_Driver::font(Fl_Font face, Fl_Fontsize size) {
+  font_unscaled(face, size * scale_);
+}
+
+double Fl_Scalable_Graphics_Driver::width(const char *str, int n) {
+  return width_unscaled(str, n)/scale_;
+}
+
+double Fl_Scalable_Graphics_Driver::width(unsigned int c) {
+  return width_unscaled(c)/scale_;
+}
+
+Fl_Fontsize Fl_Scalable_Graphics_Driver::size() {
+  if (!font_descriptor() ) return -1;
+  return size_unscaled()/scale_;
+}
+
+void Fl_Scalable_Graphics_Driver::text_extents(const char *str, int n, int &dx, int &dy, int &w, int &h) {
+  text_extents_unscaled(str, n, dx, dy, w, h);
+  dx /= scale_;
+  dy /= scale_;
+  w /= scale_;
+  h /= scale_;
+}
+
+int Fl_Scalable_Graphics_Driver::height() {
+  return int(height_unscaled()/scale_);
+}
+
+int Fl_Scalable_Graphics_Driver::descent() {
+  return descent_unscaled()/scale_;
+}
+
+void Fl_Scalable_Graphics_Driver::draw(const char *str, int n, int x, int y) {
+  if (!size_ || !font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE);
+  Fl_Region r2 = scale_clip(scale_);
+  draw_unscaled(str, n, x*scale_, y*scale_);
+  unscale_clip(r2);
+}
+
+void Fl_Scalable_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) {
+  if (!size_ || !font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE);
+  Fl_Region r2 = scale_clip(scale_);
+  draw_unscaled(angle, str, n, x*scale_, y*scale_);
+  unscale_clip(r2);
+}
+
+void Fl_Scalable_Graphics_Driver::rtl_draw(const char* str, int n, int x, int y) {
+  rtl_draw_unscaled(str, n, x * scale_, y * scale_);
+}
+
+void Fl_Scalable_Graphics_Driver::arc(int x,int y,int w,int h,double a1,double a2) {
+  arc_unscaled(x * scale_, y * scale_, w * scale_, h * scale_, a1, a2);
+}
+
+void Fl_Scalable_Graphics_Driver::pie(int x,int y,int w,int h,double a1,double a2) {
+  pie_unscaled(x * scale_, y * scale_, w * scale_, h * scale_, a1, a2);
+}
+
+void Fl_Scalable_Graphics_Driver::line_style(int style, int width, char* dashes) {
+  line_style_unscaled(style, width * scale_, dashes);
+}
+
+void Fl_Scalable_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy) {
+  copy_offscreen_unscaled(x * scale_, y * scale_, w * scale_, h * scale_, pixmap, srcx * scale_, srcy * scale_);
+}
+
+/* read the image data from a pointer or with a callback, scale it, and draw it */
+void Fl_Scalable_Graphics_Driver::draw_image_rescale(void *buf, Fl_Draw_Image_Cb cb,
+                                                     int X, int Y, int W, int H, int D, int L, bool mono, float s) {
+  int aD = abs(D);
+  if (L == 0) L = W*aD;
+  int depth = mono ? (aD%2==0?2:1) : aD;
+  uchar *tmp_buf = new uchar[W*H*depth];
+  if (cb) {
+    for (int i = 0; i < H; i++) {
+      cb(buf, 0, i, W, tmp_buf + i * W * depth);
+    }
+  } else {
+    uchar *q, *p = tmp_buf;
+    for (int i = 0; i < H; i++) {
+      q = (uchar*)buf + i * L;
+      for (int j = 0; j < W; j++) {
+        memcpy(p, q, depth);
+        p += depth; q += D;
+      }
+    }
+  }
+  Fl_RGB_Image *rgb = new Fl_RGB_Image(tmp_buf, W, H, depth);
+  rgb->alloc_array = 1;
+  Fl_RGB_Image *scaled_rgb = (Fl_RGB_Image*)rgb->copy(ceil(W * s), ceil(H * s));
+  delete rgb;
+  if (scaled_rgb) {
+    Fl_Region r2 = scale_clip(s);
+    draw_image_unscaled(scaled_rgb->array, X * s, Y * s, scaled_rgb->w(), scaled_rgb->h(), depth);
+    unscale_clip(r2);
+    delete scaled_rgb;
+  }
+}
+
+void Fl_Scalable_Graphics_Driver::draw_image(const uchar* buf, int X,int Y,int W,int H, int D, int L) {
+  if (scale_ == 1) {
+    draw_image_unscaled(buf, X,Y,W,H,D,L);
+  } else {
+    draw_image_rescale((void*)buf, NULL, X, Y, W, H, D, L, false, scale_);
+  }
+}
+
+void Fl_Scalable_Graphics_Driver::draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D) {
+  if (scale_ == 1) {
+    draw_image_unscaled(cb, data, X,Y,W,H,D);
+  } else {
+    draw_image_rescale(data, cb, X, Y, W, H, D, 0, false, scale_);
+  }
+}
+
+void Fl_Scalable_Graphics_Driver::draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D, int L) {
+  if (scale_ == 1) {
+    draw_image_mono_unscaled(buf, X,Y,W,H,D,L);
+  } else {
+    draw_image_rescale((void*)buf, NULL, X, Y, W, H, D, L, true, scale_);
+  }
+}
+
+void Fl_Scalable_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D) {
+  if (scale_ == 1) {
+    draw_image_mono_unscaled(cb, data, X,Y,W,H,D);
+  } else {
+    draw_image_rescale(data, cb, X, Y, W, H, D, 0, true, scale_);
+  }
+}
+
+void Fl_Scalable_Graphics_Driver::transformed_vertex(double xf, double yf) {
+  transformed_vertex0(xf * scale_, yf * scale_);
+}
+
+void Fl_Scalable_Graphics_Driver::vertex(double x,double y) {
+  transformed_vertex0((x*m.a + y*m.c + m.x) * scale_, (x*m.b + y*m.d + m.y) * scale_);
+}
+#endif // !FL_DOXYGEN
+
 //
 // End of "$Id$".
 //
Index: src/Fl_Image.cxx
===================================================================
--- src/Fl_Image.cxx	(revision 12216)
+++ src/Fl_Image.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // Image drawing code for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2015 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -271,7 +271,8 @@
   array(bits),
   alloc_array(0),
   id_(0),
-  mask_(0)
+  mask_(0),
+  cache_scale_(1)
 {
     data((const char **)&array, 1);
     ld(LD);
@@ -293,7 +294,8 @@
   array(0),
   alloc_array(0),
   id_(0),
-  mask_(0)
+  mask_(0),
+  cache_scale_(1)
 {
   if (pxm && pxm->w() > 0 && pxm->h() > 0) {
     array = new uchar[w() * h() * d()];
Index: src/Fl_Image_Surface.cxx
===================================================================
--- src/Fl_Image_Surface.cxx	(revision 12216)
+++ src/Fl_Image_Surface.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // Draw-to-image code for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -17,6 +17,7 @@
 //
 
 #include <FL/Fl_Image_Surface.H>
+#include <FL/Fl_Device.H>
 
 #if defined(FL_PORTING)
 # pragma message "FL_PORTING: optionally implement class Fl_XXX_Image_Surface_Driver for your platform"
@@ -91,7 +92,7 @@
   Fl_Shared_Image *s_img = Fl_Shared_Image::get(platform_surface->image());
   int width, height;
   platform_surface->printable_rect(&width, &height);
-  s_img->scale(width, height);
+  s_img->scale(width, height, 1, 1);
   return s_img;
 }
 
@@ -132,7 +133,9 @@
    */
 Fl_Offscreen fl_create_offscreen(int w, int h) {
   int rank = find_slot();
-  offscreen_api_surface[rank] = new Fl_Image_Surface(w, h, 0);
+  float d = Fl_Graphics_Driver::default_driver().scale();
+  int high_res = d != 1;
+  offscreen_api_surface[rank] = new Fl_Image_Surface(w, h, high_res);
   return offscreen_api_surface[rank]->offscreen();
 }
 
Index: src/Fl_Pixmap.cxx
===================================================================
--- src/Fl_Pixmap.cxx	(revision 12216)
+++ src/Fl_Pixmap.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // Pixmap drawing code for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2015 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -42,6 +42,7 @@
   if (w()<0 && data()) {
     fl_measure_pixmap(data(), W, H);
     w(W); h(H);
+    cache_scale_ = 1;
   }
 }
 
Index: src/Fl_Screen_Driver.cxx
===================================================================
--- src/Fl_Screen_Driver.cxx	(revision 12216)
+++ src/Fl_Screen_Driver.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // All screen related calls in a driver style class.
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -24,6 +24,7 @@
 #include <FL/Fl_Group.H>
 #include <FL/Fl_Window.H>
 #include <FL/Fl_Input.H>
+#include <FL/Fl_Window_Driver.H>
 
 char Fl_Screen_Driver::bg_set = 0;
 char Fl_Screen_Driver::bg2_set = 0;
@@ -110,7 +111,7 @@
 
 
 // Return the number of pixels common to the two rectangular areas
-static inline float fl_intersection(int x1, int y1, int w1, int h1,
+float Fl_Screen_Driver::fl_intersection(int x1, int y1, int w1, int h1,
                                     int x2, int y2, int w2, int h2)
 {
   if(x1+w1 < x2 || x2+w2 < x1 || y1+h1 < y2 || y2+h2 < y1)
@@ -154,7 +155,7 @@
 }
 
 uchar *Fl_Screen_Driver::read_image(uchar *p, int X, int Y, int w, int h, int alpha) {
-  uchar *image_data;
+  uchar *image_data = NULL;
   Fl_RGB_Image *img;
   if (fl_find(fl_window) == 0) { // read from off_screen buffer
     img = read_win_rectangle(p, X, Y, w, h, alpha);
@@ -165,14 +166,16 @@
   } else {
     img = traverse_to_gl_subwindows(Fl_Window::current(), p, X, Y, w, h, alpha, NULL);
   }
-  if (img->w() > w) {
-    Fl_RGB_Image *img2 = (Fl_RGB_Image*)img->copy(w, h);
+  if (img) {
+    if (img->w() > w) {
+      Fl_RGB_Image *img2 = (Fl_RGB_Image*)img->copy(w, h);
+      delete img;
+      img = img2;
+    }
+    img->alloc_array = 0;
+    image_data = (uchar*)img->array;
     delete img;
-    img = img2;
   }
-  img->alloc_array = 0;
-  image_data = (uchar*)img->array;
-  delete img;
   return image_data;
 }
 
@@ -268,7 +271,9 @@
         } else {
           top = full_img->h() - (origin_y - y + img->h());
         }
-        write_image_inside(full_img, img, origin_x - x, top);
+        int nscreen = c->as_window()->driver()->screen_num();
+        float s = Fl::screen_driver()->scale(nscreen);
+        write_image_inside(full_img, img, (origin_x - x) * s, top * s);
         delete img;
       }
     }
Index: src/Fl_Scroll.cxx
===================================================================
--- src/Fl_Scroll.cxx	(revision 12216)
+++ src/Fl_Scroll.cxx	(working copy)
@@ -50,6 +50,7 @@
 //    So widget can just redraw damaged parts.
 //
 void Fl_Scroll::draw_clip(void* v,int X, int Y, int W, int H) {
+printf("draw_clip X=%d Y=%d W=%d H=%d\n",X,Y,W,H);
   fl_push_clip(X,Y,W,H);
   Fl_Scroll* s = (Fl_Scroll*)v;
   // erase background as needed...
Index: src/Fl_Shared_Image.cxx
===================================================================
--- src/Fl_Shared_Image.cxx	(revision 12216)
+++ src/Fl_Shared_Image.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // Shared image code for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -366,9 +366,10 @@
     Fl_Image::draw(X, Y, W, H, cx, cy);
     return;
   }
-  fl_push_clip(X, Y, W, H);
+  bool need_clip = (W != w() || H != h() || cx || cy);
+  if (need_clip) fl_push_clip(X, Y, W, H);
   fl_graphics_driver->draw(this, X-cx, Y-cy);
-  fl_pop_clip();
+  if (need_clip) fl_pop_clip();
 }
 
 /** Draws the shared image to the current surface with its top-left at X,Y */
@@ -379,7 +380,7 @@
   }
   // don't call Fl_Graphics_Driver::draw_scaled(Fl_Image*,...) for an enlarged Fl_Bitmap or Fl_Pixmap
   if (shared->image_->as_rgb_image() || (shared->w() <= shared->image_->w() && shared->h() <= shared->image_->h())) {
-    int done = fl_graphics_driver->draw_scaled(shared->image_, X, Y, shared->w(), shared->h());
+    int done = draw_scaled(shared->image_, X, Y, shared->w(), shared->h());
     if (done) return;
   }
   if (shared->scaled_image_ && (shared->scaled_image_->w() != shared->w() || shared->scaled_image_->h() != shared->h())) {
@@ -401,7 +402,7 @@
  This can be useful to draw a shared image on a drawing surface whose resolution is higher
  than the drawing unit for this surface: all pixels of the original image become available to fill
  an area of the drawing surface sized at <tt>width,height</tt>.
- Examples of such drawing surfaces: laser printers, PostScript files, PDF printers, retina displays on Apple hardware.
+ Examples of such drawing surfaces: laser printers, PostScript files, PDF printers, HiDPI displays.
 
  \param width,height   maximum width and height (in drawing units) to use when drawing the shared image
  \param proportional   if not null, keep the width and height of the shared image proportional to those of its original image
@@ -413,7 +414,7 @@
  \code
  Fl_Box *b = ...  // a box
  Fl_Shared_Image *shared = Fl_Shared_Image::get("/path/to/picture.jpeg"); // read a picture file
- shared->scale(b->w(), b->h(), 1); // set the drawing size of the shared image to the size of the box
+ shared->scale(b->w(), b->h()); // set the drawing size of the shared image to the size of the box
  b->image(shared); // use the shared image as the box image
  b->align(FL_ALIGN_INSIDE | FL_ALIGN_CENTER | FL_ALIGN_CLIP); // the image is to be drawn centered in the box
  \endcode
Index: src/Fl_Widget_Surface.cxx
===================================================================
--- src/Fl_Widget_Surface.cxx	(revision 12216)
+++ src/Fl_Widget_Surface.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // Drivers code for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -22,6 +22,7 @@
 #include <FL/x.H>
 #include <FL/Fl_Shared_Image.H>
 #include <FL/Fl_Window_Driver.H>
+#include <FL/Fl_Screen_Driver.H>
 
 
 /** The constructor.
@@ -153,13 +154,19 @@
   Fl_Window *save_front = Fl::first_window();
   win->show();
   Fl::check();
-  win->driver()->flush(); // makes the window current necessary for fl_read_image
-  uchar *image_data;
-  image_data = fl_read_image(NULL, x, y, w, h);
+  win->driver()->flush(); // makes the window current
+  const uchar *image_data;
+  Fl_RGB_Image *img = Fl_Screen_Driver::traverse_to_gl_subwindows(win, NULL, x, y, w, h, 0, NULL);
+  if (img->w() > w) {
+    Fl_RGB_Image *img2 = (Fl_RGB_Image*)img->copy(w, h);
+    delete img;
+    img = img2;
+  }
+  image_data = img->array;
   if (save_front != win) save_front->show();
   set_current();
   fl_draw_image(image_data, delta_x, delta_y, w, h, 3);
-  delete[] image_data;
+  delete img;
 }
 
 /**
Index: src/Fl_Window_Driver.cxx
===================================================================
--- src/Fl_Window_Driver.cxx	(revision 12216)
+++ src/Fl_Window_Driver.cxx	(working copy)
@@ -4,7 +4,7 @@
 // A base class for platform specific window handling code
 // for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -247,6 +247,11 @@
   }
 }
 
+int Fl_Window_Driver::screen_num() {
+  if (pWindow->parent()) return pWindow->top_window()->driver()->screen_num();
+  return Fl::screen_num(x(), y(), w(), h());
+}
+
 //
 // End of "$Id$".
 //
Index: src/Fl_x.cxx
===================================================================
--- src/Fl_x.cxx	(revision 12216)
+++ src/Fl_x.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // X specific code for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -601,6 +601,49 @@
   fl_xim_deactivate();
 }
 
+
+#if USE_XFT
+
+// respond to Ctrl-'+' and Ctrl-'-' and Ctrl-'0' (Ctrl-'=' is same as Ctrl-'+') by rescaling all windows
+int Fl_X11_Screen_Driver::scale_handler(int event)
+{
+  if ( event != FL_SHORTCUT || (!Fl::event_ctrl()) ) return 0;
+  int key = Fl::event_key() & ~(FL_SHIFT+FL_CTRL);
+  if (key == '=' || key == '-' || key == '+' || key == '0' || key == 0xE0/* for '0' on Fr keyboard */) {
+    int i, count;
+    if (Fl::grab()) return 0; // don't rescale when menu windows are on
+    Fl_Widget *wid = Fl::focus();
+    if (!wid) return 0;
+    int screen = wid->top_window()->driver()->screen_num();
+    Fl_X11_Screen_Driver *screen_dr = (Fl_X11_Screen_Driver*)Fl::screen_driver();
+    static float initial_scale = screen_dr->scale(screen);
+    static float scaling_values[] = {0.5, 2.f/3, 0.8, 0.9, 1, 1.1, 1.2, 4.f/3, 1.5, 1.7, 2, 2.4, 3,
+      4, 5.5, 6.5, 7.5, 9.75 };
+    float f, old_f = screen_dr->scale(screen)/initial_scale;
+    if (key == '0' || key == 0xE0) f = 1;
+    else {
+      count = sizeof(scaling_values)/sizeof(float);
+      for (i = 0; i < count; i++) {
+        if (old_f >= scaling_values[i] - 1e-4 && (i+1 >= count || old_f < scaling_values[i+1] - 1e-4)) {
+          break;
+        }
+      }
+      if (key == '-') i--; else i++;
+      if (i < 0) i = 0; if (i >= count) i = count - 1;
+      f = scaling_values[i];
+    }
+    if (f == old_f) return 1;
+    screen_dr->rescale_all_windows_from_screen(screen, f*initial_scale);
+    Fl_X11_Screen_Driver::transient_scale_display(f, screen);
+    screen_dr->init_workarea();
+    return 1;
+  }
+  return 0;
+}
+
+#endif // USE_XFT
+
+
 void Fl_X11_Screen_Driver::open_display() {
   if (fl_display) return;
 
@@ -617,6 +660,12 @@
   // the unique GC used by all X windows
   GC gc = XCreateGC(fl_display, RootWindow(fl_display, fl_screen), 0, 0);
   Fl_Graphics_Driver::default_driver().gc(gc);
+  
+#if USE_XFT // scaling does not work without Xft
+  float factor = default_scale_factor();
+  for (int i = 0; i < screen_count(); i++) this->scale(i, factor);
+  Fl::add_handler(scale_handler);
+#endif // USE_XFT
 }
 
 
@@ -719,16 +768,25 @@
   XCloseDisplay(fl_display);
 }
 
-
-void Fl_X11_Screen_Driver::get_mouse(int &xx, int &yy) {
+int Fl_X11_Screen_Driver::get_mouse_unscaled(int &mx, int &my) {
   open_display();
   Window root = RootWindow(fl_display, fl_screen);
-  Window c; int mx,my,cx,cy; unsigned int mask;
-  XQueryPointer(fl_display,root,&root,&c,&mx,&my,&cx,&cy,&mask);
-  xx = mx;
-  yy = my;
+  Window c; int cx,cy; unsigned int mask;
+  XQueryPointer(fl_display, root, &root, &c, &mx, &my, &cx, &cy, &mask);
+#if USE_XFT
+  return screen_num_unscaled(mx, my);
+#else
+  return screen_num(mx, my);
+#endif
 }
 
+
+void Fl_X11_Screen_Driver::get_mouse(int &xx, int &yy) {
+  float s = scale(get_mouse_unscaled(xx, yy));
+  xx = xx/s;
+  yy = yy/s;
+}
+
 ////////////////////////////////////////////////////////////////
 // Code used for paste and DnD into the program:
 
@@ -1079,14 +1137,19 @@
 static int px, py;
 static ulong ptime;
 
-static void set_event_xy() {
+static void set_event_xy(Fl_Window *win) {
 #  if CONSOLIDATE_MOTION
   send_motion = 0;
 #  endif
-  Fl::e_x_root  = fl_xevent->xbutton.x_root;
-  Fl::e_x       = fl_xevent->xbutton.x;
-  Fl::e_y_root  = fl_xevent->xbutton.y_root;
-  Fl::e_y       = fl_xevent->xbutton.y;
+  float s = 1;
+#if USE_XFT
+  Fl_X11_Screen_Driver *d =  (Fl_X11_Screen_Driver*)Fl::screen_driver();
+  s = d->scale(win->driver()->screen_num());
+#endif
+  Fl::e_x_root  = fl_xevent->xbutton.x_root/s;
+  Fl::e_x       = fl_xevent->xbutton.x/s;
+  Fl::e_y_root  = fl_xevent->xbutton.y_root/s;
+  Fl::e_y       = fl_xevent->xbutton.y/s;
   Fl::e_state   = fl_xevent->xbutton.state << 16;
   fl_event_time = fl_xevent->xbutton.time;
 #  ifdef __sgi
@@ -1203,12 +1266,6 @@
   return XKeycodeToKeysym(d, k, i);
 }
 
-static void fl_init_workarea()
-{
-  Fl_X11_Screen_Driver *drv = (Fl_X11_Screen_Driver*)Fl::screen_driver();
-  drv->init_workarea();
-}
-
 int fl_handle(const XEvent& thisevent)
 {
   XEvent xevent = thisevent;
@@ -1236,18 +1293,23 @@
 
   if (fl_xim_ic && XFilterEvent((XEvent *)&xevent, 0))
       return(1);
+  Fl_X11_Screen_Driver *x11_screen_driver = (Fl_X11_Screen_Driver*)Fl::screen_driver();
   
 #if USE_XRANDR  
   if( XRRUpdateConfiguration_f && xevent.type == randrEventBase + RRScreenChangeNotify) {
     XRRUpdateConfiguration_f(&xevent);
     Fl::call_screen_init();
-    fl_init_workarea();
+#if USE_XFT
+    float factor = x11_screen_driver->default_scale_factor();
+    for (int screen = 0; screen <= Fl::screen_count(); screen++)
+      x11_screen_driver->rescale_all_windows_from_screen(screen, factor);
+#endif // USE_XFT
     Fl::handle(FL_SCREEN_CONFIGURATION_CHANGED, NULL);
   }
-#endif
+#endif // USE_XRANDR
 
   if (xevent.type == PropertyNotify && xevent.xproperty.atom == fl_NET_WORKAREA) {
-    fl_init_workarea();
+    x11_screen_driver->init_workarea();
   }
   
   switch (xevent.type) {
@@ -1647,8 +1709,17 @@
 #  endif
 
   case GraphicsExpose:
-    window->damage(FL_DAMAGE_EXPOSE, xevent.xexpose.x, xevent.xexpose.y,
-                   xevent.xexpose.width, xevent.xexpose.height);
+    {
+#if USE_XFT
+      int ns = window->driver()->screen_num();
+      float s = Fl::screen_driver()->scale(ns);
+      window->damage(FL_DAMAGE_EXPOSE, xevent.xexpose.x/s, xevent.xexpose.y/s,
+                     xevent.xexpose.width/s + 2, xevent.xexpose.height/s + 2);
+#else
+      window->damage(FL_DAMAGE_EXPOSE, xevent.xexpose.x, xevent.xexpose.y,
+                     xevent.xexpose.width, xevent.xexpose.height);
+#endif
+     }
     return 1;
 
   case FocusIn:
@@ -1867,13 +1938,13 @@
     // replace XK_ISO_Left_Tab (Shift-TAB) with FL_Tab (modifier flags are set correctly by X11)
     if (Fl::e_keysym == 0xfe20) Fl::e_keysym = FL_Tab;
 
-    set_event_xy();
+    set_event_xy(window);
     Fl::e_is_click = 0; }
     break;
   
   case ButtonPress:
     Fl::e_keysym = FL_Button + xevent.xbutton.button;
-    set_event_xy();
+    set_event_xy(window);
     Fl::e_dx = Fl::e_dy = 0;
     if (xevent.xbutton.button == Button4) {
       Fl::e_dy = -1; // Up
@@ -1924,7 +1995,7 @@
     break;
 
   case MotionNotify:
-    set_event_xy();
+    set_event_xy(window);
 #  if CONSOLIDATE_MOTION
     send_motion = fl_xmousewin = window;
     in_a_window = true;
@@ -1938,7 +2009,7 @@
 
   case ButtonRelease:
     Fl::e_keysym = FL_Button + xevent.xbutton.button;
-    set_event_xy();
+    set_event_xy(window);
     Fl::e_state &= ~(FL_BUTTON1 << (xevent.xbutton.button-1));
     if (xevent.xbutton.button == Button4 ||
         xevent.xbutton.button == Button5) return 0;
@@ -1951,7 +2022,7 @@
   case EnterNotify:
     if (xevent.xcrossing.detail == NotifyInferior) break;
     // XInstallColormap(fl_display, Fl_X::i(window)->colormap);
-    set_event_xy();
+    set_event_xy(window);
     Fl::e_state = xevent.xcrossing.state << 16;
     event = FL_ENTER;
 
@@ -1967,7 +2038,7 @@
 
   case LeaveNotify:
     if (xevent.xcrossing.detail == NotifyInferior) break;
-    set_event_xy();
+    set_event_xy(window);
     Fl::e_state = xevent.xcrossing.state << 16;
     fl_xmousewin = 0;
     in_a_window = false; // make do_queued_events produce FL_LEAVE event
@@ -1992,10 +2063,39 @@
     Window cr; int X, Y, W = actual.width, H = actual.height;
     XTranslateCoordinates(fl_display, fl_xid(window), actual.root,
                           0, 0, &X, &Y, &cr);
+#if USE_XFT // detect when window changes screen
+    int num = 0;
+    Fl_X11_Screen_Driver *d = (Fl_X11_Screen_Driver*)Fl::screen_driver();
+    num = d->screen_num_unscaled(X, Y, actual.width, actual.height);
+    Fl_X11_Window_Driver *wd = Fl_X11_Window_Driver::driver(window);
+    int olds = wd->screen_num();
+    float s = d->scale(num);
+    if (num != olds) {
+      if (s != d->scale(olds) &&
+          !Fl_X11_Window_Driver::data_for_resize_window_between_screens_.busy &&
+          window->user_data() != &Fl_X11_Screen_Driver::transient_scale_display) {
+        Fl_X11_Window_Driver::data_for_resize_window_between_screens_.busy = true;
+        Fl_X11_Window_Driver::data_for_resize_window_between_screens_.screen = num;
+        // resize_after_screen_change() works also if called here, but calling it
+        // a second later gives a more pleasant user experience when moving windows between distinct screens
+        Fl::add_timeout(1, Fl_X11_Window_Driver::resize_after_screen_change, window);
+      }
+      wd->screen_num(num);
+    }
+#endif // USE_XFT
 
     // tell Fl_Window about it and set flag to prevent echoing:
     resize_bug_fix = window;
+#if USE_XFT    
+    if (!Fl_X11_Window_Driver::data_for_resize_window_between_screens_.busy &&
+       ( W != int(window->w()*s) || H != int(window->h()*s) ) ) {
+        window->resize(X/s, Y/s, W/s, H/s);
+    } else {
+      window->position(X/s, Y/s);
+    }
+#else
     window->resize(X, Y, W, H);
+#endif
     break; // allow add_handler to do something too
     }
 
@@ -2017,7 +2117,13 @@
     // tell Fl_Window about it and set flag to prevent echoing:
     if ( !wasXExceptionRaised() ) {
       resize_bug_fix = window;
-      window->position(xpos, ypos);
+#if USE_XFT
+      int ns = window->driver()->screen_num();
+      float s = Fl::screen_driver()->scale(ns);
+#else
+      float s = 1;
+#endif
+      window->position(xpos/s, ypos/s);
     }
     break;
     }
@@ -2066,15 +2172,16 @@
   }
 
   if (resize_from_program && shown()) {
+    float s = Fl::screen_driver()->scale(screen_num());
     if (is_a_resize) {
       if (!pWindow->resizable()) pWindow->size_range(w(), h(), w(), h());
       if (is_a_move) {
-        XMoveResizeWindow(fl_display, fl_xid(pWindow), X, Y, W>0 ? W : 1, H>0 ? H : 1);
+        XMoveResizeWindow(fl_display, fl_xid(pWindow), X*s, Y*s, W>0 ? W*s : 1, H>0 ? H*s : 1);
       } else {
-        XResizeWindow(fl_display, fl_xid(pWindow), W>0 ? W : 1, H>0 ? H : 1);
+        XResizeWindow(fl_display, fl_xid(pWindow), W>0 ? W*s : 1, H>0 ? H*s : 1);
       }
     } else
-      XMoveWindow(fl_display, fl_xid(pWindow), X, Y);
+      XMoveWindow(fl_display, fl_xid(pWindow), X*s, Y*s);
   }
 }
 
@@ -2179,7 +2286,7 @@
     right = fullscreen_screen_right();
     
     if ((top < 0) || (bottom < 0) || (left < 0) || (right < 0)) {
-      top = Fl::screen_num(x(), y(), w(), h());
+      top = screen_num();
       bottom = top;
       left = top;
       right = top;
@@ -2361,11 +2468,31 @@
     fl_background_pixel = -1;
     mask |= CWBackPixel;
   }
-
+  // reproduce the window cursor if a window is hidden and then recreated (e.g., rescaled)
+  attr.cursor = Fl_X11_Window_Driver::driver(win)->current_cursor_;
+  mask |= CWCursor;
+  float s = 1;
+#if USE_XFT
+  //compute adequate screen where to put the window
+  int nscreen = 0;
+  if (win->parent()) {
+    nscreen = win->top_window()->driver()->screen_num();
+  } else if (win->force_position() && Fl_X11_Window_Driver::driver(win)->screen_num_ >= 0) {
+    nscreen = win->driver()->screen_num();
+  } else {
+    Fl_Window *hint = Fl::first_window();
+    if (hint) {
+      nscreen = hint->top_window()->driver()->screen_num();
+    }
+  }
+  Fl_X11_Window_Driver::driver(win)->screen_num(nscreen);
+  s = Fl::screen_driver()->scale(nscreen);
+//if (!win->parent()) printf("win creation on screen #%d\n", nscreen);
+#endif
   Fl_X* xp =
     set_xid(win, XCreateWindow(fl_display,
                                root,
-                               X, Y, W, H,
+                               X*s, Y*s, W*s, H*s,
                                0, // borderwidth
                                visual->depth,
                                InputOutput,
@@ -2525,12 +2652,20 @@
 
   XSizeHints *hints = XAllocSizeHints();
   // memset(&hints, 0, sizeof(hints)); jreiser suggestion to fix purify?
-  hints->min_width = minw();
-  hints->min_height = minh();
-  hints->max_width = maxw();
-  hints->max_height = maxh();
-  hints->width_inc = dw();
-  hints->height_inc = dh();
+  float s = Fl::screen_driver()->scale(screen_num());
+
+  hints->min_width = s*minw();
+  hints->min_height = s*minh();
+  hints->max_width = s*maxw();
+  hints->max_height = s*maxh();
+  if (int(s) == s) { // use win size increment value only if scale is an integer. Is it possible to do better?
+    hints->width_inc = s*dw();
+    hints->height_inc = s*dh();
+  } else {
+    hints->width_inc = 0;
+    hints->height_inc = 0;
+  }
+  
   hints->win_gravity = StaticGravity;
 
   // see the file /usr/include/X11/Xm/MwmUtil.h:
@@ -2547,8 +2682,8 @@
       // unfortunately we can't set just one maximum size.  Guess a
       // value for the other one.  Some window managers will make the
       // window fit on screen when maximized, others will put it off screen:
-      if (hints->max_width < hints->min_width) hints->max_width = Fl::w();
-      if (hints->max_height < hints->min_height) hints->max_height = Fl::h();
+      if (hints->max_width < hints->min_width) hints->max_width = Fl::w()*s;
+      if (hints->max_height < hints->min_height) hints->max_height = Fl::h()*s;
     }
     if (hints->width_inc && hints->height_inc) hints->flags |= PResizeInc;
     if (aspect()) {
@@ -2566,8 +2701,8 @@
 
   if (force_position()) {
     hints->flags |= USPosition;
-    hints->x = w->x();
-    hints->y = w->y();
+    hints->x = s*w->x();
+    hints->y = s*w->y();
   }
 
   if (!w->border()) {
@@ -2730,6 +2865,7 @@
 #undef cache_cursor
 
   XDefineCursor(fl_display, fl_xid(pWindow), xc);
+  current_cursor_ = xc;
 
   return 1;
 }
@@ -2895,6 +3031,7 @@
   //printer.print_window_part( win, 0,0, win->w(), win->h(), - win->w()/2, - win->h()/2 );
 #else  
   printer.print_window(win);
+  //printer.print_window_part( win, 0,0, win->w(), win->h(), 0,0 );
 #endif
 
   printer.end_page();
@@ -2909,8 +3046,9 @@
   Fl_Window *win = Fl::first_window();
   if (!win) return;
   Fl_Copy_Surface *surf = new Fl_Copy_Surface(win->decorated_w(), win->decorated_h());
-  surf->set_current();
+  Fl_Surface_Device::push_current(surf);
   surf->draw_decorated_window(win); // draw the window content
+  Fl_Surface_Device::pop_current();
   delete surf; // put the window on the clipboard
   o->window()->show();
 }
Index: src/drivers/OpenGL/Fl_OpenGL_Display_Device.cxx
===================================================================
--- src/drivers/OpenGL/Fl_OpenGL_Display_Device.cxx	(revision 12216)
+++ src/drivers/OpenGL/Fl_OpenGL_Display_Device.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // implementation of class Fl_Gl_Device_Plugin for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 2010-2014 by Bill Spitzak and others.
+// Copyright 2010-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -93,7 +93,8 @@
 #if defined(FL_PORTING)
 #  pragma message "FL_PORTING: check whether the default Fl_OpenGL_Display_Device::capture_gl_rectangle() works for your platform"
 #endif
-
+#include <FL/Fl_Screen_Driver.H>
+#include <FL/Fl_Window_Driver.H>
 Fl_RGB_Image* Fl_OpenGL_Display_Device::capture_gl_rectangle(Fl_Gl_Window *glw, int x, int y, int w, int h)
 /* captures a rectangle of a Fl_Gl_Window window, and returns it as a RGB image
  */
@@ -106,6 +107,12 @@
   glPixelStorei(GL_PACK_ROW_LENGTH, 0);
   glPixelStorei(GL_PACK_SKIP_ROWS, 0);
   glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
+  //
+  int ns = glw->driver()->screen_num();
+  float s = Fl::screen_driver()->scale(ns);
+  if (s != 1) {
+    x *= s; y *= s; w *= s; h *= s;
+  }
   // Read a block of pixels from the frame buffer
   int mByteWidth = w * 3;
   mByteWidth = (mByteWidth + 3) & ~3;    // Align to 4 bytes
Index: src/drivers/X11/Fl_X11_Screen_Driver.H
===================================================================
--- src/drivers/X11/Fl_X11_Screen_Driver.H	(revision 12216)
+++ src/drivers/X11/Fl_X11_Screen_Driver.H	(working copy)
@@ -4,7 +4,7 @@
 // Definition of X11 Screen interface
 // for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 2010-2016 by Bill Spitzak and others.
+// Copyright 2010-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -39,13 +39,29 @@
     short y_org;
     short width;
     short height;
+#if USE_XFT
+    float scale;
+#endif
   } FLScreenInfo;
   FLScreenInfo screens[MAX_SCREENS];
   float dpi[MAX_SCREENS][2];
   int poll_or_select();
   int poll_or_select_with_delay(double time_to_wait);
+  int get_mouse_unscaled(int &xx, int &yy);
 
 public:
+#if USE_XFT // scaling does not work without Xft
+  virtual float scale(int n) {return screens[n].scale;}
+  void scale(int n, float f) { screens[n].scale = f;}
+  float default_scale_factor();
+  int screen_num_unscaled(int x, int y);
+  int screen_num_unscaled(int x, int y, int w, int h);
+  void rescale_all_windows_from_screen(int screen, float old_f);
+  static void transient_scale_display(float f, int nscreen);
+  static int scale_handler(int event);
+  virtual void screen_xywh(int &X, int &Y, int &W, int &H);
+#endif
+  
   static int ewmh_supported();
   static void copy_image(const unsigned char* data, int W, int H, int destination);
   // --- display management
@@ -91,7 +107,6 @@
   virtual void offscreen_size(Fl_Offscreen o, int &width, int &height);
 };
 
-
 #endif // FL_X11_SCREEN_DRIVER_H
 
 //
Index: src/drivers/X11/Fl_X11_Screen_Driver.cxx
===================================================================
--- src/drivers/X11/Fl_X11_Screen_Driver.cxx	(revision 12216)
+++ src/drivers/X11/Fl_X11_Screen_Driver.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // Definition of X11 Screen interface
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -20,9 +20,13 @@
 #include "../../config_lib.h"
 #include "Fl_X11_Screen_Driver.H"
 #include "../Xlib/Fl_Font.H"
+#include "Fl_X11_Window_Driver.H"
 #include <FL/Fl.H>
 #include <FL/x.H>
 #include <FL/fl_ask.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Image_Surface.H>
+#include <FL/Fl_Tooltip.H>
 
 #include <sys/time.h>
 
@@ -229,10 +233,15 @@
   }
   else
   {
-    fl_workarea_xywh[0] = (int)xywh[0];
-    fl_workarea_xywh[1] = (int)xywh[1];
-    fl_workarea_xywh[2] = (int)xywh[2];
-    fl_workarea_xywh[3] = (int)xywh[3];
+#if USE_XFT
+    float s = screens[0].scale;
+#else
+    float s = 1;
+#endif
+    fl_workarea_xywh[0] = xywh[0] / s;
+    fl_workarea_xywh[1] = xywh[1] / s;
+    fl_workarea_xywh[2] = xywh[2] / s;
+    fl_workarea_xywh[3] = xywh[3] / s;
   }
   if ( xywh ) { XFree(xywh); xywh = 0; }
 }
@@ -316,7 +325,9 @@
       screens[i].y_org = xsi[i].y_org;
       screens[i].width = xsi[i].width;
       screens[i].height = xsi[i].height;
-
+#if USE_XFT
+      screens[i].scale = 1;
+#endif
       if (dpi_by_randr) {
 	dpi[i][0] = dpih;
 	dpi[i][1] = dpiv;
@@ -341,7 +352,9 @@
       screens[i].y_org = 0;
       screens[i].width = DisplayWidth(fl_display, i);
       screens[i].height = DisplayHeight(fl_display, i);
-
+#if USE_XFT
+      screens[i].scale = 1;
+#endif
       if (dpi_by_randr) {
 	dpi[i][0] = dpih;
 	dpi[i][1] = dpiv;
@@ -353,6 +366,17 @@
       }
     }
   }
+#if __APPLE_CC__ && USE_XFT // TMP simulate 2 screens under XQuartz
+  if (strstr(getenv("DISPLAY"), "xquartz")) {
+    num_screens = 2;
+    screens[1].x_org = screens[0].width/2;;
+    screens[1].y_org = screens[0].y_org;
+    screens[1].width = screens[0].width = screens[0].width/2;
+    screens[1].height = screens[0].height;
+    screens[1].scale = screens[0].scale = 1;
+  }
+#endif
+  init_workarea();
 }
 
 
@@ -379,10 +403,15 @@
     n = 0;
 
   if (num_screens > 0) {
-    X = screens[n].x_org;
-    Y = screens[n].y_org;
-    W = screens[n].width;
-    H = screens[n].height;
+#if USE_XFT
+    float s = screens[n].scale;
+#else
+    float s = 1;
+#endif
+    X = screens[n].x_org / s;
+    Y = screens[n].y_org / s;
+    W = screens[n].width / s;
+    H = screens[n].height / s;
   }
 }
 
@@ -765,6 +794,8 @@
     image = 0;
 #  endif // __sgi
   
+  float s = Fl_Surface_Device::surface()->driver()->scale();
+
   if (!image) {
     // fetch absolute coordinates
     int dx, dy, sx, sy, sw, sh;
@@ -771,13 +802,14 @@
     Window child_win;
     
     Fl_Window *win;
-    if (allow_outside) win = (Fl_Window*)1;
+    if (allow_outside) win = Fl_Window::current();
     else win = fl_find(fl_window);
     if (win) {
       XTranslateCoordinates(fl_display, fl_window,
-                            RootWindow(fl_display, fl_screen), X, Y, &dx, &dy, &child_win);
+                            RootWindow(fl_display, fl_screen), X*s, Y*s, &dx, &dy, &child_win);
+      dx /= s; dy /= s;
       // screen dimensions
-      Fl::screen_xywh(sx, sy, sw, sh, fl_screen);
+      Fl::screen_xywh(sx, sy, sw, sh, win->driver()->screen_num());
     }
     if (!win || (dx >= sx && dy >= sy && dx + w <= sx+sw && dy + h <= sy+sh)) {
       // the image is fully contained, we can use the traditional method
@@ -784,7 +816,7 @@
       // however, if the window is obscured etc. the function will still fail. Make sure we
       // catch the error and continue, otherwise an exception will be thrown.
       XErrorHandler old_handler = XSetErrorHandler(xgetimageerrhandler);
-      image = XGetImage(fl_display, fl_window, X, Y, w, h, AllPlanes, ZPixmap);
+      image = XGetImage(fl_display, fl_window, int(X*s), int(Y*s), w*s < 1 ? 1 : int(w*s), h*s < 1 ? 1 : int(h*s), AllPlanes, ZPixmap);
       XSetErrorHandler(old_handler);
     } else {
       // image is crossing borders, determine visible region
@@ -795,9 +827,9 @@
       
       // allocate the image
       int bpp = fl_visual->depth + ((fl_visual->depth / 8) % 2) * 8;
-      char* buf = (char*)malloc(bpp / 8 * w * h);
+      char* buf = (char*)malloc(bpp / 8 * int(w*s) * int(h*s));
       image = XCreateImage(fl_display, fl_visual->visual,
-                           fl_visual->depth, ZPixmap, 0, buf, w, h, bpp, 0);
+                           fl_visual->depth, ZPixmap, 0, buf, w*s, h*s, bpp, 0);
       if (!image) {
         if (buf) free(buf);
         return 0;
@@ -804,8 +836,8 @@
       }
       
       XErrorHandler old_handler = XSetErrorHandler(xgetimageerrhandler);
-      XImage *subimg = XGetSubImage(fl_display, fl_window, X + noffx, Y + noffy,
-                                    nw, nh, AllPlanes, ZPixmap, image, noffx, noffy);
+      XImage *subimg = XGetSubImage(fl_display, fl_window, (X + noffx)*s, (Y + noffy)*s,
+                                    nw*s, nh*s, AllPlanes, ZPixmap, image, noffx*s, noffy*s);
       XSetErrorHandler(old_handler);
       if (!subimg) {
         XDestroyImage(image);
@@ -815,6 +847,10 @@
   }
   
   if (!image) return 0;
+  if (s != 1) {
+    w = w*s < 1 ? 1 : int(w*s);
+    h = h*s < 1 ? 1 : int(h*s);
+  }
   
 #ifdef DEBUG
   printf("width            = %d\n", image->width);
@@ -1154,6 +1190,333 @@
   height = (int)h;
 }
 
+#if USE_XFT
+int Fl_X11_Screen_Driver::screen_num_unscaled(int x, int y)
+{
+  int screen = 0;
+  if (num_screens < 0) init();
+  
+  for (int i = 0; i < num_screens; i ++) {
+    int sx = screens[i].x_org, sy = screens[i].y_org, sw = screens[i].width, sh = screens[i].height;
+    if ((x >= sx) && (x < (sx+sw)) && (y >= sy) && (y < (sy+sh))) {
+      screen = i;
+      break;
+    }
+  }
+  return screen;
+}
+
+int Fl_X11_Screen_Driver::screen_num_unscaled(int x, int y, int w, int h)
+{
+  int best_screen = 0;
+  float best_intersection = 0.;
+  if (num_screens < 0) init();
+  for (int i = 0; i < num_screens; i++) {
+    float sintersection = fl_intersection(x, y, w, h, screens[i].x_org, screens[i].y_org,
+                                          screens[i].width, screens[i].height);
+    if (sintersection > best_intersection) {
+      best_screen = i;
+      best_intersection = sintersection;
+    }
+  }
+  return best_screen;
+}
+#endif
+
+#if USE_XFT
+void Fl_X11_Screen_Driver::screen_xywh(int &X, int &Y, int &W, int &H)
+{
+  int xx, yy;
+  int ns = get_mouse_unscaled(xx,yy);
+  float s = screens[ns].scale;
+  X = screens[ns].x_org / s;
+  Y = screens[ns].y_org / s;
+  W = screens[ns].width / s;
+  H = screens[ns].height / s;
+}
+
+
+void Fl_X11_Screen_Driver::rescale_all_windows_from_screen(int screen, float f)
+{
+  float old_f = this->scale(screen);
+  this->scale(screen, f);
+  int i = 0, count = 0; // count top-level windows, except transient scale-displaying window
+  Fl_Window *win = Fl::first_window();
+  while (win) {
+    if (!win->parent() && win->driver()->screen_num() == screen &&
+        win->user_data() != &Fl_X11_Screen_Driver::transient_scale_display) count++;
+    win = Fl::next_window(win);
+  }
+  Fl_Window **win_array = new Fl_Window*[count];
+  win = Fl::first_window(); // memorize all top-level windows
+  while (win) {
+    if (!win->parent() && win->user_data() != &Fl_X11_Screen_Driver::transient_scale_display &&
+        win->driver()->screen_num() == screen) {
+      win_array[i++] = win;
+    }
+    win = Fl::next_window(win);
+  }
+  for (i = count - 1; i >= 0; i--) { // rescale all top-level windows, finishing with front one
+    win = win_array[i];
+    int oldx = win->x(), oldy = win->y();
+    win->hide();
+    Fl_X11_Window_Driver::driver(win)->screen_num(screen);
+    win->position(oldx*old_f/f, oldy*old_f/f);
+    win->driver()->force_position(1);
+    if (win->fullscreen_active()) {
+      win->size(win->w() * old_f/f, win->h() * old_f/f);
+    }
+    win->show();
+    win->wait_for_expose();
+  }
+  delete[] win_array;
+}
+
+#if HAVE_DLSYM && HAVE_DLFCN_H
+
+// returns true when schema is among the list of available schemas
+static bool is_schema_valid(const char *schema, const char **known) {
+  int i = 0;
+  while (known[i]) {
+    if (strcmp(known[i++], schema) == 0) return true;
+  }
+  return false;
+}
+
+
+/*
+ returns true under Ubuntu or Debian or FreeBSD and when the gnome scaling value has been found
+ 
+ Ubuntu:
+ Change the gnome scaling factor with:
+ System Settings ==> Displays ==> Scale for menu and title bars
+ Read the current gnome scaling factor with:
+ gsettings get com.ubuntu.user-interface scale-factor
+ Example value: {'VGA-0': 10}
+ Its type is "a{si}". This value should be divided by 8 to get the correct scaling factor.
+ 
+ Debian or FreeBSD :
+ Change the gnome scaling factor with:
+ Tweak tools ==> Windows ==> Window scaling
+ Read the current gnome scaling factor with:
+ gsettings get org.gnome.settings-daemon.plugins.xsettings overrides
+ Example value: {'Gdk/WindowScalingFactor': <2>}
+ Its type is "a{sv}" and v itself is of type i
+ 
+ It's also possible to use 'Tweak tools' under Ubuntu. With the standard Ubuntu desktop,
+ the modified value goes to "org.gnome.settings-daemon.plugins.xsettings" as above.
+ 
+ With Gnome session flashback under Ubuntu  'Tweak tools' puts the scaling value (1 or 2)
+ in "org.gnome.desktop.interface scaling-factor".
+ Read the current gnome scaling factor with:
+ gsettings get org.gnome.desktop.interface scaling-factor
+ Its type is "u"
+ 
+ Thus, under Ubuntu, we read the 3 possible factor values and 
+ return the first value different from 1 to get the scaling factor.
+ 
+ =================================================================================================
+ Ubuntu | default ubuntu desktop | System Settings => Displays => Scale for menu and title bars
+                                              com.ubuntu.user-interface scale-factor
+                                   -----------------------
+                                   Tweak tools => Windows => Window scaling
+                                              org.gnome.settings-daemon.plugins.xsettings overrides
+                                   -----------------------
+          Gnome session flashback | System Settings => Displays => Scale for menu and title bars
+                                              no effect
+                                   -----------------------
+                                   Tweak tools => Windows => Window scaling
+                                              org.gnome.desktop.interface scaling-factor
+ =================================================================================================
+ Debian or FreeBSD | gnome | Tweak tools => Windows => Window scaling
+                                            org.gnome.settings-daemon.plugins.xsettings overrides
+ =================================================================================================
+ */
+static bool gnome_scale_factor(float& factor) {
+  // define types needed for dynamic lib functions
+  typedef const char** (*g_settings_list_schemas_ftype)(void);
+  typedef void* (*g_settings_new_ftype)(const char *);
+  typedef void* (*g_settings_get_value_ftype)(void *settings, const char *key);
+  typedef void (*g_variant_get_ftype)(void *value, const char *format_string, ...);
+  typedef bool (*g_variant_iter_loop_ftype)(void *iter, const char *format_string, ...);
+  typedef void (*pter_ftype)(void*);
+  //typedef void* (*g_variant_get_type_ftype)(void *variant);
+  
+  // open dynamic libs
+  void *glib = dlopen("libglib-2.0.so", RTLD_LAZY);
+  void *gio = dlopen("libgio-2.0.so", RTLD_LAZY);
+  void *gobj = dlopen("libgobject-2.0.so", RTLD_LAZY);
+  //fprintf(stderr,"glib=%p gio=%p gobj=%p\n",glib,gio,gobj);
+  if (!glib || !gio || !gobj) return false;
+  
+  bool ubuntu = false;
+  // determine whether we run Ubuntu
+  char line[400] = "";
+  FILE *in = fopen("/proc/version", "r");
+  if (in) {
+    fgets(line, sizeof(line), in);
+    fclose(in);
+    if (strstr(line, "Ubuntu")) ubuntu = true;
+  }
+  
+  // define pters to used functions
+  g_settings_list_schemas_ftype g_settings_list_schemas_f = (g_settings_list_schemas_ftype)dlsym(gio, "g_settings_list_schemas"); // 2.26
+  g_settings_new_ftype g_settings_new_f = (g_settings_new_ftype)dlsym(gio, "g_settings_new"); // 2.26
+  g_settings_get_value_ftype g_settings_get_value_f =
+		(g_settings_get_value_ftype)dlsym(gio, "g_settings_get_value"); // 2.26
+  if (!g_settings_list_schemas_f || !g_settings_new_f || !g_settings_get_value_f) return false;
+  g_variant_get_ftype g_variant_get_f = (g_variant_get_ftype)dlsym(glib, "g_variant_get"); //2.24
+  g_variant_iter_loop_ftype g_variant_iter_loop_f = (g_variant_iter_loop_ftype)dlsym(glib, "g_variant_iter_loop"); // 2.24
+  pter_ftype g_variant_iter_free_f = (pter_ftype)dlsym(glib, "g_variant_iter_free"); // 2.24
+  pter_ftype g_object_unref_f = (pter_ftype)dlsym(gobj, "g_object_unref");
+  pter_ftype g_variant_unref_f = (pter_ftype)dlsym(glib, "g_variant_unref"); // 2.24
+  //g_variant_get_type_ftype g_variant_get_type_f = (g_variant_get_type_ftype)dlsym(glib, "g_variant_get_type"); // 2.24
+  
+  // call dynamic lib functions
+  const char **known = g_settings_list_schemas_f(); // list of available GSettings schemas
+  const char *schema;
+  float ubuntu_f = 1, ubuntu_desktop_f = 1, gnome_f = 1;
+  bool found = false;
+  
+  if (ubuntu) {
+    schema = "com.ubuntu.user-interface";
+    if (is_schema_valid(schema, known)) {
+      found = true;
+      void *gset = g_settings_new_f(schema);
+      void *gvar = g_settings_get_value_f(gset, "scale-factor");
+      void *iter;
+      char str[10], *str2; int v, v2;
+      g_variant_get_f(gvar, "a{si}", &iter);
+      while (g_variant_iter_loop_f(iter, "{si}", &str2, &v2)) { // read the last couple of values
+        strcpy(str, str2);  v = v2;
+      }
+      ubuntu_f = v/8.;
+      printf("com.ubuntu.user-interface  scale-factor name=%s value=%d factor=%g\n", str, v, ubuntu_f);
+      g_variant_iter_free_f(iter);
+      g_variant_unref_f(gvar);
+      g_object_unref_f(gset);
+      if (ubuntu_f != 1) {
+        factor = ubuntu_f;
+        return true;
+      }
+    }
+    schema = "org.gnome.desktop.interface";
+    if (is_schema_valid(schema, known)) {
+      found = true;
+      void *gset = g_settings_new_f(schema);
+      void *gvar = g_settings_get_value_f(gset, "scaling-factor");
+      unsigned v;
+      g_variant_get_f(gvar, "u", &v);
+      ubuntu_desktop_f = v;
+      printf("org.gnome.desktop.interface  scaling-factor value=%u factor=%g\n", v, ubuntu_desktop_f);
+      g_variant_unref_f(gvar);
+      g_object_unref_f(gset);
+      if (ubuntu_desktop_f != 1) {
+        factor = ubuntu_desktop_f;
+        return true;
+      }
+    }
+  }
+  schema = "org.gnome.settings-daemon.plugins.xsettings";
+  if (is_schema_valid(schema, known)) {
+    void *gset = g_settings_new_f(schema);
+    void *gvar = g_settings_get_value_f(gset, "overrides");
+    void *iter;
+    char *str; int v;
+    //str = (char*)g_variant_get_type_f(gvar); // -> "a{sv}"
+    g_variant_get_f(gvar, "a{sv}", &iter);
+    g_variant_unref_f(gvar);
+    gvar = NULL;
+    while (g_variant_iter_loop_f(iter, "{sv}", &str, &gvar)) {
+      if (strstr(str, "WindowScalingFactor") == NULL) continue;
+      found = true;
+      //str = (char*)g_variant_get_type_f(gvar); // -> "i"
+      g_variant_get_f(gvar, "i", &v);
+      gnome_f = v;
+      printf("org.gnome.settings-daemon.plugins.xsettings  overrides name=%s value=%d factor=%g\n", str, v, gnome_f);
+      free(str);
+      break;
+    }
+    g_variant_iter_free_f(iter);
+    if (gvar) g_variant_unref_f(gvar);
+    g_object_unref_f(gset);
+  }
+  if (!found) return false;
+  //factor = ubuntu_f * ubuntu_desktop_f * gnome_f;
+  factor = gnome_f;
+  return true;
+}
+#endif // HAVE_DLSYM && HAVE_DLFCN_H
+
+
+// determine the adequate scaling to support HiDPI displays and assign it to all screens
+float Fl_X11_Screen_Driver::default_scale_factor()
+{
+  float factor = 1;
+  char *p = 0;
+  if ((p = getenv("FLTK_SCALING_FACTOR"))) {
+    sscanf(p, "%f", &factor);
+  }
+#if HAVE_DLSYM && HAVE_DLFCN_H
+    else if (gnome_scale_factor(factor)){
+      ; // try to read the current gnome scaling value
+    }
+#endif
+  return factor;
+}
+
+
+static void del_transient_window(void *data) {
+  Fl_Window *win = (Fl_Window*)data;
+  delete (Fl_RGB_Image*)win->child(0)->user_data();
+  Fl::delete_widget(win);
+}
+
+void Fl_X11_Screen_Driver::transient_scale_display(float f, int nscreen)
+{ // transiently show the new scaling value using a shaped window
+  int w = 150;
+  // draw a white rounded box on black background
+  Fl_Screen_Driver *d = Fl::screen_driver();
+  float s = d->scale(nscreen);
+  if (s > 3) s = 3; // limit the growth of the transient window
+  Fl_Image_Surface *surf = new Fl_Image_Surface(w*s, w*s/2);
+  Fl_Surface_Device::push_current(surf);
+  fl_color(FL_BLACK);
+  fl_rectf(-1, -1, w*s+2, w*s+2);
+  Fl_Box *b = new Fl_Box(FL_RFLAT_BOX, 0, 0, w*s, w*s/2, "");
+  b->color(FL_WHITE);
+  surf->draw(b);
+  delete b;
+  Fl_RGB_Image* img = surf->image(); // img will be the window's shape
+  delete surf;
+  Fl_Surface_Device::pop_current();
+  //create a window shaped with the rounded box
+  int X, Y, W, H;
+  Fl::screen_xywh(X, Y, W, H, nscreen);
+  w /= d->scale(nscreen)/s;
+  Fl_Window *win = new Fl_Window((X + W/2) -w/2, (Y + H/2) -w/4, w, w/2, 0);
+  b = new Fl_Box(FL_FLAT_BOX, 0, 0, w, w/2, NULL);
+  char str[10];
+  sprintf(str, "%d %%", int(f * 100 + 0.5));
+  b->copy_label(str);
+  b->labelfont(FL_TIMES_BOLD);
+  b->labelsize(30 * s / d->scale(nscreen));
+  b->labelcolor(FL_BLACK);
+  b->color(Fl_Tooltip::color());
+  win->end();
+  win->shape(img);
+  b->user_data(img);
+  win->user_data((void*)&transient_scale_display); // prevent this window from being rescaled later
+  win->set_output();
+  Fl_X11_Window_Driver::driver(win)->screen_num(nscreen);
+  win->driver()->force_position(1);
+  win->show();
+  Fl::add_timeout(1, del_transient_window, win); // delete after 1 sec
+}
+
+
+#endif // USE_XFT
+
 //
 // End of "$Id$".
 //
Index: src/drivers/X11/Fl_X11_Window_Driver.H
===================================================================
--- src/drivers/X11/Fl_X11_Window_Driver.H	(revision 12216)
+++ src/drivers/X11/Fl_X11_Window_Driver.H	(working copy)
@@ -4,7 +4,7 @@
 // Definition of X11 window driver
 // for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 2010-2016 by Bill Spitzak and others.
+// Copyright 2010-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -27,6 +27,7 @@
 
 #include <FL/Fl_Window_Driver.H>
 #include <config.h> // for USE_XDBE
+#include <FL/x.H> // for Cursor
 class Fl_Bitmap;
 
 /*
@@ -56,6 +57,8 @@
 class FL_EXPORT Fl_X11_Window_Driver : public Fl_Window_Driver
 {
   friend class Fl_X;
+  friend class Fl_X11_Screen_Driver;
+  friend int fl_handle(const XEvent&);
 
 private:
   struct icon_data {
@@ -63,6 +66,17 @@
     Fl_RGB_Image **icons;
     int count;
   } *icon_;
+  Cursor current_cursor_;
+#if  USE_XFT
+  // --- support for screen-specific scaling factors
+  struct type_for_resize_window_between_screens {
+    int screen;
+    bool busy;
+  };
+  static type_for_resize_window_between_screens data_for_resize_window_between_screens_;
+  int screen_num_;
+  inline void screen_num(int n) { screen_num_ = n; }
+#endif // USE_XFT
   void decorated_win_size(int &w, int &h);
   void combine_mask();
   void shape_bitmap_(Fl_Image* b);
@@ -79,7 +93,11 @@
   Fl_X11_Window_Driver(Fl_Window*);
   virtual ~Fl_X11_Window_Driver();
   static inline Fl_X11_Window_Driver* driver(Fl_Window *w) {return (Fl_X11_Window_Driver*)w->driver();}
-
+#if  USE_XFT
+  virtual int screen_num();
+  static void resize_after_screen_change(void *data);
+#endif // USE_XFT
+  
   // --- window data
   virtual int decorated_w();
   virtual int decorated_h();
Index: src/drivers/X11/Fl_X11_Window_Driver.cxx
===================================================================
--- src/drivers/X11/Fl_X11_Window_Driver.cxx	(revision 12216)
+++ src/drivers/X11/Fl_X11_Window_Driver.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // Definition of X11 window driver.
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -112,11 +112,11 @@
 #if USE_XDBE
   if (can_xdbe()) {
     XdbeDeallocateBackBufferName(fl_display, other_xid);
-    other_xid = 0;
   }
   else
 #endif // USE_XDBE
-    Fl_Window_Driver::destroy_double_buffer();
+    fl_delete_offscreen(other_xid);
+  other_xid = 0;
 }
 
 Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w)
@@ -130,6 +130,10 @@
 {
   icon_ = new icon_data;
   memset(icon_, 0, sizeof(icon_data));
+  current_cursor_ = None;
+#if USE_XFT
+  screen_num_ = -1;
+#endif
 }
 
 
@@ -160,8 +164,10 @@
   if (status == 0 || root == parent) return;
   XWindowAttributes attributes;
   XGetWindowAttributes(fl_display, parent, &attributes);
-  w = attributes.width;
-  h = attributes.height;
+  int nscreen = screen_num();
+  float s = Fl::screen_driver()->scale(nscreen);
+  w = attributes.width / s;
+  h = attributes.height / s;
 }
 
 
@@ -196,7 +202,9 @@
 void Fl_X11_Window_Driver::draw_begin()
 {
   if (shape_data_) {
-    if (( shape_data_->lw_ != w() || shape_data_->lh_ != h() ) && shape_data_->shape_) {
+    int nscreen = screen_num();
+    float s = Fl::screen_driver()->scale(nscreen);
+    if (( shape_data_->lw_ != int(s*w()) || shape_data_->lh_ != int(s*h()) ) && shape_data_->shape_) {
       // size of window has changed since last time
       combine_mask();
     }
@@ -324,8 +332,9 @@
 #endif
   }
   if (!XShapeCombineMask_f) return;
-  shape_data_->lw_ = w();
-  shape_data_->lh_ = h();
+  float s = Fl::screen_driver()->scale(screen_num());
+  shape_data_->lw_ = w()*s;
+  shape_data_->lh_ = h()*s;
   Fl_Image* temp = shape_data_->shape_->copy(shape_data_->lw_, shape_data_->lh_);
   Pixmap pbitmap = XCreateBitmapFromData(fl_display, fl_xid(pWindow),
                                          (const char*)*temp->data(),
@@ -400,25 +409,30 @@
   if (n) XFree(children);
   if (!do_it) wsides = htop = 0;
   int hbottom = wsides;
+  float s = Fl::screen_driver()->scale(screen_num());
+  htop /= s; wsides /= s;
   fl_window = parent;
   if (htop) {
     r_top = Fl::screen_driver()->read_win_rectangle(NULL, 0, 0, - (w() + 2 * wsides), htop, 0);
     top = Fl_Shared_Image::get(r_top);
+    top->scale(w() + 2 * wsides, htop, 0, 1);
   }
   if (wsides) {
     r_left = Fl::screen_driver()->read_win_rectangle(NULL, 0, htop, -wsides, h(), 0);
     if (r_left) {
       left =  Fl_Shared_Image::get(r_left);
+      left->scale(wsides, h(), 0, 1);
     }
     r_right = Fl::screen_driver()->read_win_rectangle(NULL, w() + wsides, htop, -wsides, h(), 0);
     if (r_right) {
       right = Fl_Shared_Image::get(r_right);
+      right->scale(wsides, h(), 0, 1);
     }
     r_bottom = Fl::screen_driver()->read_win_rectangle(NULL, 0, htop + h(), -(w() + 2*wsides), hbottom, 0);
     if (r_bottom) {
       bottom = Fl_Shared_Image::get(r_bottom);
-    }
-  }
+      bottom->scale(w() + 2*wsides, wsides, 0, 1);
+    }  }
   fl_window = from;
   Fl_Surface_Device::pop_current();
 }
@@ -432,6 +446,11 @@
   }
   fl_window = fl_xid(pWindow);
   fl_graphics_driver->clip_region(0);
+#if USE_XFT
+  int nscreen = screen_num();
+  Fl_X11_Screen_Driver *d = (Fl_X11_Screen_Driver*)Fl::screen_driver();
+  ((Fl_Xlib_Graphics_Driver*)fl_graphics_driver)->scale(d->scale(nscreen));
+#endif
   
 #ifdef FLTK_USE_CAIRO
   // update the cairo_t context
@@ -460,6 +479,7 @@
   if (ip->region) Fl_Graphics_Driver::default_driver().XDestroyRegion(ip->region);
 # if USE_XFT
   Fl_Xlib_Graphics_Driver::destroy_xft_draw(ip->xid);
+  screen_num_ = -1;
 # endif
   // this test makes sure ip->xid has not been destroyed already
   if (ip->xid) XDestroyWindow(fl_display, ip->xid);
@@ -650,8 +670,10 @@
 int Fl_X11_Window_Driver::scroll(int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y,
                                  void (*draw_area)(void*, int,int,int,int), void* data)
 {
+  float s = Fl::screen_driver()->scale(screen_num());
+printf("%.2f src_y=%d src_h=%d dest_y=%d scl_y=%d scl_h=%d scl_dst_y=%d\n",s, src_y,src_h,dest_y, int(src_y*s), int((src_y+src_h)*s)-int(src_y*s), int(dest_y*s));
   XCopyArea(fl_display, fl_window, fl_window, (GC)fl_graphics_driver->gc(),
-            src_x, src_y, src_w, src_h, dest_x, dest_y);
+            int(src_x*s), int(src_y*s), int((src_x+src_w)*s)-int(src_x*s), int((src_y+src_h)*s)-int(src_y*s), int(dest_x*s), int(dest_y*s));
   // we have to sync the display and get the GraphicsExpose events! (sigh)
   for (;;) {
     XEvent e; XWindowEvent(fl_display, fl_window, ExposureMask, &e);
@@ -670,6 +692,38 @@
   return Fl_X::i(pWindow);
 }
 
+
+#if USE_XFT
+
+Fl_X11_Window_Driver::type_for_resize_window_between_screens Fl_X11_Window_Driver::data_for_resize_window_between_screens_ = {0, false};
+
+void Fl_X11_Window_Driver::resize_after_screen_change(void *data) {
+  Fl_Window *win = (Fl_Window*)data;
+  int oldx, oldy;
+  XWindowAttributes actual;
+  XGetWindowAttributes(fl_display, fl_xid(win), &actual);
+  Window cr;
+  XTranslateCoordinates(fl_display, fl_xid(win), actual.root, 0, 0, &oldx, &oldy, &cr);
+  win->hide();
+  float f = Fl::screen_driver()->scale(data_for_resize_window_between_screens_.screen);
+  Fl_X11_Window_Driver::driver(win)->screen_num(data_for_resize_window_between_screens_.screen);
+  win->position(oldx/f, oldy/f);
+  win->driver()->force_position(1);
+  win->show();
+  win->wait_for_expose();
+  data_for_resize_window_between_screens_.busy = false;
+}
+
+
+int Fl_X11_Window_Driver::screen_num() {
+  if (pWindow->parent()) {
+    screen_num_ = pWindow->top_window()->driver()->screen_num();
+  }
+  return screen_num_ >= 0 ? screen_num_ : 0;
+}
+#endif // USE_XFT
+
+
 //
 // End of "$Id$".
 //
Index: src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx	(revision 12216)
+++ src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // Copy-to-clipboard code for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -31,6 +31,7 @@
   virtual void end_current_();
 protected:
   Fl_Offscreen xid;
+  int pixmap_w, pixmap_h;
   Window oldwindow;
   Fl_Xlib_Copy_Surface_Driver(int w, int h);
   ~Fl_Xlib_Copy_Surface_Driver();
@@ -51,8 +52,12 @@
 
 Fl_Xlib_Copy_Surface_Driver::Fl_Xlib_Copy_Surface_Driver(int w, int h) : Fl_Copy_Surface_Driver(w, h) {
   driver(new Fl_Xlib_Graphics_Driver());
+  float s = Fl_Graphics_Driver::default_driver().scale();
+  ((Fl_Xlib_Graphics_Driver*)driver())->scale(s);
   oldwindow = fl_window;
   xid = fl_create_offscreen(w,h);
+  pixmap_w = w * s;
+  pixmap_h = h * s;
   driver()->push_no_clip();
   fl_window = xid;
   driver()->color(FL_WHITE);
@@ -65,10 +70,10 @@
   driver()->pop_clip();
   bool need_push = (Fl_Surface_Device::surface() != this);
   if (need_push) Fl_Surface_Device::push_current(this);
-  unsigned char *data = fl_read_image(NULL,0,0,width,height,0);
+  Fl_RGB_Image *rgb = Fl::screen_driver()->read_win_rectangle(NULL, 0, 0, width, height, 0);
   if (need_push) Fl_Surface_Device::pop_current();
-  Fl_X11_Screen_Driver::copy_image(data, width, height, 1);
-  delete[] data;
+  Fl_X11_Screen_Driver::copy_image(rgb->array, rgb->w(), rgb->h(), 1);
+  delete rgb;
   fl_delete_offscreen(xid);
   delete driver();
 }
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H	(revision 12216)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H	(working copy)
@@ -43,7 +43,7 @@
 #endif // HAVE_X11_XREGION_H
 
 #if USE_PANGO
-#include <pango/pangoxft.h>
+#include <pango/pango.h>
 #endif
 
 
@@ -52,11 +52,28 @@
  *
  This class is implemented only on the Xlib platform.
  */
-class FL_EXPORT Fl_Xlib_Graphics_Driver : public Fl_Graphics_Driver {
+class FL_EXPORT Fl_Xlib_Graphics_Driver : public Fl_Scalable_Graphics_Driver {
 private:
   int offset_x_, offset_y_; // translation between user and graphical coordinates: graphical = user + offset
   unsigned depth_; // depth of translation stack
   int stack_x_[20], stack_y_[20]; // translation stack allowing cumulative translations
+  int line_delta_;
+protected:
+  virtual void draw_unscaled(Fl_Pixmap *pxm, float s, int XP, int YP, int WP, int HP, int cx, int cy);
+  virtual void draw_unscaled(Fl_Bitmap *pxm, float s, int XP, int YP, int WP, int HP, int cx, int cy);
+  virtual void draw_unscaled(Fl_RGB_Image *img, float s, int XP, int YP, int WP, int HP, int cx, int cy);
+  virtual void draw_image_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0);
+  virtual void draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3);
+  virtual void draw_image_mono_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0);
+  virtual void draw_image_mono_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1);
+#if HAVE_XRENDER
+  virtual int draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP);
+  int scale_and_render_pixmap(Fl_Offscreen pixmap, int depth, double scale_x, double scale_y, int srcx, int srcy, int XP, int YP, int WP, int HP);
+#endif
+  virtual int height_unscaled();
+  virtual int descent_unscaled();
+  virtual Region scale_clip(float f);
+  virtual void unscale_clip(Region r2);
 #if USE_XFT
   void drawUCS4(const void *str, int n, int x, int y);
 #endif
@@ -65,16 +82,11 @@
   static PangoContext *pctxt_;
   static PangoFontMap *pfmap_;
   static PangoLayout *playout_;
-protected:
   PangoFontDescription *pfd_;
   void do_draw(int from_right, const char *str, int n, int x, int y);
   static PangoContext *context();
   static void init_built_in_fonts();
 #endif
-#if HAVE_XRENDER
-  int scale_and_render_pixmap(Fl_Offscreen pixmap, int depth, double scale_x, double scale_y, int srcx, int srcy, int XP, int YP, int WP, int HP);
-#endif
-protected:
   static GC gc_;
   uchar **mask_bitmap_;
   uchar **mask_bitmap() {return mask_bitmap_;}
@@ -93,6 +105,7 @@
   virtual ~Fl_Xlib_Graphics_Driver();
   void translate_all(int dx, int dy);
   void untranslate_all();
+  virtual void scale(float f);
   virtual int has_feature(driver_feature mask) { return mask & NATIVE; }
   virtual void *gc() { return gc_; }
   virtual void gc(void *value);
@@ -104,51 +117,43 @@
   // --- bitmap stuff
   Fl_Bitmask create_bitmask(int w, int h, const uchar *array);
   void delete_bitmask(Fl_Bitmask bm);
-  void draw(const char* str, int n, int x, int y);
-  void draw(int angle, const char *str, int n, int x, int y);
-  void rtl_draw(const char* str, int n, int x, int y);
-  void font(Fl_Font face, Fl_Fontsize size);
-  void draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
-  void draw(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
-  void draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy);
-  void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0);
-  void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3);
-  void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0);
-  void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1);
-#if HAVE_XRENDER
-  int draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP);
-#endif
+  virtual void draw_unscaled(const char* str, int n, int x, int y);
+  virtual void draw_unscaled(int angle, const char *str, int n, int x, int y);
+  virtual void rtl_draw_unscaled(const char* str, int n, int x, int y);
+  virtual void font_unscaled(Fl_Font face, Fl_Fontsize size);
   fl_uintptr_t cache(Fl_Pixmap *img, int w, int h, const char *const*array);
   fl_uintptr_t cache(Fl_Bitmap *img, int w, int h, const uchar *array);
   void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_);
-  double width(const char *str, int n);
-  double width(unsigned int c);
-  void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h);
-  int height();
-  int descent();
-  void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
+  virtual double width_unscaled(const char *str, int n);
+  virtual double width_unscaled(unsigned int c);
+  virtual void text_extents_unscaled(const char*, int n, int& dx, int& dy, int& w, int& h);
+  virtual Fl_Fontsize size_unscaled();
+  virtual void copy_offscreen_unscaled(float x, float y, float w, float h, Fl_Offscreen pixmap, float srcx, float srcy);
+#if ! defined(FL_DOXYGEN)
+  void copy_offscreen_with_alpha(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
+#endif
   void add_rectangle_to_region(Fl_Region r, int x, int y, int w, int h);
   Fl_Region XRectangleRegion(int x, int y, int w, int h);
   void XDestroyRegion(Fl_Region r);
 protected:
-  virtual void transformed_vertex0(short x, short y);
+  virtual void transformed_vertex0(float x, float y);
   void fixloop();
   // --- implementation is in src/fl_rect.cxx which includes src/cfg_gfx/xlib_rect.cxx
-  void point(int x, int y);
-  void rect(int x, int y, int w, int h);
-  void rectf(int x, int y, int w, int h);
-  void line(int x, int y, int x1, int y1);
-  void line(int x, int y, int x1, int y1, int x2, int y2);
-  void xyline(int x, int y, int x1);
-  void xyline(int x, int y, int x1, int y2);
-  void xyline(int x, int y, int x1, int y2, int x3);
-  void yxline(int x, int y, int y1);
-  void yxline(int x, int y, int y1, int x2);
-  void yxline(int x, int y, int y1, int x2, int y3);
-  void loop(int x0, int y0, int x1, int y1, int x2, int y2);
-  void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
-  void polygon(int x0, int y0, int x1, int y1, int x2, int y2);
-  void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
+  virtual void point_unscaled(float x, float y);
+  virtual void rect_unscaled(float x, float y, float w, float h);
+  virtual void rectf_unscaled(float x, float y, float w, float h);
+  virtual void line_unscaled(float x, float y, float x1, float y1);
+  virtual void line_unscaled(float x, float y, float x1, float y1, float x2, float y2);
+  virtual void xyline_unscaled(float x, float y, float x1);
+  virtual void xyline_unscaled(float x, float y, float x1, float y2);
+  virtual void xyline_unscaled(float x, float y, float x1, float y2, float x3);
+  virtual void yxline_unscaled(float x, float y, float y1);
+  virtual void yxline_unscaled(float x, float y, float y1, float x2);
+  virtual void yxline_unscaled(float x, float y, float y1, float x2, float y3);
+  virtual void loop_unscaled(float x0, float y0, float x1, float y1, float x2, float y2);
+  virtual void loop_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
+  virtual void polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2);
+  virtual void polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
   // --- clipping
   void push_clip(int x, int y, int w, int h);
   int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H);
@@ -156,10 +161,7 @@
   void push_no_clip();
   void pop_clip();
   void restore_clip();
-  // --- implementation is in src/fl_vertex.cxx which includes src/cfg_gfx/xxx_rect.cxx
   void begin_complex_polygon();
-  void transformed_vertex(double xf, double yf);
-  void vertex(double x, double y);
   void end_points();
   void end_line();
   void end_loop();
@@ -166,15 +168,11 @@
   void end_polygon();
   void end_complex_polygon();
   void gap();
-  void circle(double x, double y, double r);
-  // --- implementation is in src/fl_arc.cxx which includes src/cfg_gfx/xxx_arc.cxx if needed
-  // using void Fl_Graphics_Driver::arc(double x, double y, double r, double start, double end);
+  virtual void ellipse_unscaled(double xt, double yt, double rx, double ry);
   // --- implementation is in src/fl_arci.cxx which includes src/cfg_gfx/xxx_arci.cxx
-  void arc(int x, int y, int w, int h, double a1, double a2);
-  void pie(int x, int y, int w, int h, double a1, double a2);
-  // --- implementation is in src/fl_line_style.cxx which includes src/cfg_gfx/xxx_line_style.cxx
-  void line_style(int style, int width=0, char* dashes=0);
-  // --- implementation is in src/fl_color.cxx which includes src/cfg_gfx/xxx_color.cxx
+  virtual void arc_unscaled(float x, float y, float w, float h, double a1, double a2);
+  virtual void pie_unscaled(float x, float y, float w, float h, double a1, double a2);
+  virtual void line_style_unscaled(int style, float width, char* dashes);
   void color(Fl_Color c);
   void set_color(Fl_Color i, unsigned int c);
   void free_color(Fl_Color i, int overlay);
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx	(revision 12216)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // Rectangle drawing routines for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -57,6 +57,7 @@
   p_size = 0;
   p = NULL;
   line_width_ = 0;
+  line_delta_ = 0;
 #if USE_PANGO
   pfd_ = pango_font_description_new();
   Fl_Graphics_Driver::font(0, 0);
@@ -78,10 +79,30 @@
   fl_gc = gc_;
 }
 
-void Fl_Xlib_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy) {
-  XCopyArea(fl_display, pixmap, fl_window, gc_, srcx, srcy, w, h, x+offset_x_, y+offset_y_);
+void Fl_Xlib_Graphics_Driver::scale(float f) {
+  if (f != scale_) {
+    size_ = 0;
+    scale_ = f;
+    //fprintf(stderr, "scale=%.2f\n", scale_);
+    line_style(FL_SOLID); // scale also default line width
+    /* Scaling >= 2 transforms 1-pixel wide lines into wider lines.
+     X11 draws 2-pixel wide lines so that half of the line width is above or at left
+     of a 1-pixel wide line that would be drawn with the same coordinates.
+     Thus, if the line starts at coordinates (0,0) half of the line width is invisible.
+     Similarly, if the line ends at w()-1 the last pixel of the window is not drawn.
+     What is wanted when scale_ == 2 is a visible 2-pixel wide line in the first case,
+     and a line at the window's edge in the 2nd case.
+     Setting line_delta_ to 1 and offsetting all line, rectangle, text and clip
+     coordinates by line_delta_ achieves what is wanted until scale_ <= 3.5.
+     */
+    line_delta_ =  (scale_ > 1.75 ? 1 : 0);
+  }
 }
 
+void Fl_Xlib_Graphics_Driver::copy_offscreen_unscaled(float x, float y, float w, float h, Fl_Offscreen pixmap, float srcx, float srcy) {
+  XCopyArea(fl_display, pixmap, fl_window, gc_, srcx, srcy, w, h, x+offset_x_*scale_, y+offset_y_*scale_);
+}
+
 void Fl_Xlib_Graphics_Driver::add_rectangle_to_region(Fl_Region r, int X, int Y, int W, int H) {
   XRectangle R;
   R.x = X; R.y = Y; R.width = W; R.height = H;
@@ -88,7 +109,8 @@
   XUnionRectWithRegion(&R, r, r);
 }
 
-void Fl_Xlib_Graphics_Driver::transformed_vertex0(short x, short y) {
+void Fl_Xlib_Graphics_Driver::transformed_vertex0(float fx, float fy) {
+  short x = short(fx), y = short(fy);
   if (!n || x != p[n-1].x || y != p[n-1].y) {
     if (n >= p_size) {
       p_size = p ? 2*p_size : 16;
@@ -202,6 +224,32 @@
   s->first = 0;
 }
 
+
+Region Fl_Xlib_Graphics_Driver::scale_clip(float f) {
+  Region r = rstack[rstackptr];
+  if (r == 0 || (f == 1 && offset_x_ == 0 && offset_y_ == 0) ) return 0;
+  float delta = (f >= 2 ? f/3 : 0);
+  Region r2 = XCreateRegion();
+  XRectangle R;
+  for (int i = 0; i < r->numRects; i++) {
+    R.x = short((r->rects[i].x1 + offset_x_)*f-delta + line_delta_);
+    R.y = short((r->rects[i].y1 + offset_y_)*f-delta + line_delta_);
+    R.width = short(r->rects[i].x2*f) - short(r->rects[i].x1*f);
+    R.height = short(r->rects[i].y2*f) - short(r->rects[i].y1*f);
+    XUnionRectWithRegion(&R, r2, r2);
+  }
+  rstack[rstackptr] = r2;
+  return r;
+}
+
+void Fl_Xlib_Graphics_Driver::unscale_clip(Region r2) {
+  if (r2) {
+    if (rstack[rstackptr]) ::XDestroyRegion(rstack[rstackptr]);
+    rstack[rstackptr] = r2;
+  }
+}
+
+
 void Fl_Xlib_Graphics_Driver::translate_all(int dx, int dy) { // reversibly adds dx,dy to the offset between user and graphical coordinates
   stack_x_[depth_] = offset_x_;
   stack_y_[depth_] = offset_y_;
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.cxx	(revision 12216)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // Arc (integer) drawing functions for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -26,15 +26,15 @@
   \brief Utility functions for drawing circles using integers
 */
 
-void Fl_Xlib_Graphics_Driver::arc(int x,int y,int w,int h,double a1,double a2) {
+void Fl_Xlib_Graphics_Driver::arc_unscaled(float x,float y,float w,float h,double a1,double a2) {
   if (w <= 0 || h <= 0) return;
-  XDrawArc(fl_display, fl_window, gc_, x+offset_x_,y+offset_y_,w-1,h-1, int(a1*64),int((a2-a1)*64));
+  XDrawArc(fl_display, fl_window, gc_, int(x+offset_x_*scale_), int(y+offset_y_*scale_), int(w-1), int(h-1), int(a1*64),int((a2-a1)*64));
 }
 
-void Fl_Xlib_Graphics_Driver::pie(int x,int y,int w,int h,double a1,double a2) {
+void Fl_Xlib_Graphics_Driver::pie_unscaled(float x,float y,float w,float h,double a1,double a2) {
   if (w <= 0 || h <= 0) return;
-  x += offset_x_;
-  y += offset_y_;
+  x += offset_x_*scale_;
+  y += offset_y_*scale_;
   XDrawArc(fl_display, fl_window, gc_, x,y,w-1,h-1, int(a1*64),int((a2-a1)*64));
   XFillArc(fl_display, fl_window, gc_, x,y,w-1,h-1, int(a1*64),int((a2-a1)*64));
 }
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx	(revision 12216)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // X11 font utilities for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -596,7 +596,7 @@
   return ptr;
 }
 
-void Fl_Xlib_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) {
+void Fl_Xlib_Graphics_Driver::font_unscaled(Fl_Font fnum, Fl_Fontsize size) {
   if (fnum==-1) {
     Fl_Graphics_Driver::font(0, 0);
     return;
@@ -611,27 +611,32 @@
   }
 }
 
-int Fl_Xlib_Graphics_Driver::height() {
+int Fl_Xlib_Graphics_Driver::height_unscaled() {
   if (font_descriptor()) return font_descriptor()->font->ascent + font_descriptor()->font->descent;
   else return -1;
 }
 
-int Fl_Xlib_Graphics_Driver::descent() {
+int Fl_Xlib_Graphics_Driver::descent_unscaled() {
   if (font_descriptor()) return font_descriptor()->font->descent;
   else return -1;
 }
 
-double Fl_Xlib_Graphics_Driver::width(const char* c, int n) {
+Fl_Fontsize Fl_Xlib_Graphics_Driver::size_unscaled() {
+  if (font_descriptor()) return size_;
+  return -1;
+}
+
+double Fl_Xlib_Graphics_Driver::width_unscaled(const char* c, int n) {
   if (font_descriptor()) return (double) XUtf8TextWidth(font_descriptor()->font, c, n);
   else return -1;
 }
 
-double Fl_Xlib_Graphics_Driver::width(unsigned int c) {
+double Fl_Xlib_Graphics_Driver::width_unscaled(unsigned int c) {
   if (font_descriptor()) return (double) XUtf8UcsWidth(font_descriptor()->font, c);
   else return -1;
 }
 
-void Fl_Xlib_Graphics_Driver::text_extents(const char *c, int n, int &dx, int &dy, int &W, int &H) {
+void Fl_Xlib_Graphics_Driver::text_extents_unscaled(const char *c, int n, int &dx, int &dy, int &W, int &H) {
   if (font_gc != gc_) {
     if (!font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE);
     font_gc = gc_;
@@ -649,16 +654,16 @@
 //  dy = fl_descent() - H;
 }
 
-void Fl_Xlib_Graphics_Driver::draw(const char* c, int n, int x, int y) {
+void Fl_Xlib_Graphics_Driver::draw_unscaled(const char* c, int n, int x, int y) {
   if (font_gc != gc_) {
     if (!font_descriptor()) this->font(FL_HELVETICA, FL_NORMAL_SIZE);
     font_gc = gc_;
     XSetFont(fl_display, gc_, font_descriptor()->font->fid);
   }
-  if (gc_) XUtf8DrawString(fl_display, fl_window, font_descriptor()->font, gc_, x+offset_x_, y+offset_y_, c, n);
+  if (gc_) XUtf8DrawString(fl_display, fl_window, font_descriptor()->font, gc_, x+offset_x_*scale_, y+offset_y_*scale_, c, n);
 }
 
-void Fl_Xlib_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) {
+void Fl_Xlib_Graphics_Driver::draw_unscaled(int angle, const char *str, int n, int x, int y) {
   static char warning = 0; // issue warning only once
   if (!warning && angle != 0) {
     warning = 1;
@@ -669,12 +674,12 @@
   this->draw(str, n, (int)x, (int)y);
 }
 
-void Fl_Xlib_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) {
+void Fl_Xlib_Graphics_Driver::rtl_draw_unscaled(const char* c, int n, int x, int y) {
   if (font_gc != gc_) {
     if (!font_descriptor()) this->font(FL_HELVETICA, FL_NORMAL_SIZE);
     font_gc = gc_;
   }
-  if (gc_) XUtf8DrawRtlString(fl_display, fl_window, font_descriptor()->font, gc_, x+offset_x_, y+offset_y_, c, n);
+  if (gc_) XUtf8DrawRtlString(fl_display, fl_window, font_descriptor()->font, gc_, x+offset_x_*scale_, y+offset_y_*scale_, c, n);
 }
 
 float Fl_Xlib_Graphics_Driver::scale_font_for_PostScript(Fl_Font_Descriptor *desc, int s) {
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx	(revision 12216)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // More font utilities for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -125,7 +125,31 @@
 
 Fl_Fontdesc* fl_fonts = built_in_table;
 
+Fl_Fontsize Fl_Xlib_Graphics_Driver::size_unscaled() {
+  return (Fl_Fontsize)(size_);
+}
 
+static void correct_extents (float scale_, int &dx, int &dy, int &w, int &h) {
+  if (int(scale_) == scale_) { // correct for extents non divisible by integral scale_
+    int delta = dx - int(dx/scale_)*scale_;
+    if (delta) {
+      dx -= delta; w += delta;
+    }
+    delta = -dy - int((-dy)/scale_)*scale_;
+    if (delta) {
+      dy -= delta; h += delta;
+    }
+    delta = h - int(h/scale_)*scale_;
+    if (delta) {
+      h += delta;
+    }
+    delta = w - int(w/scale_)*scale_;
+    if (delta) {
+      w += delta;
+    }
+  }
+}
+
 #if ! USE_PANGO
 
 ///////////////////////////////////////////////////////////
@@ -455,8 +479,8 @@
 static const char* fl_encoding_ = "iso10646-1";
 
 
-void Fl_Xlib_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) {
-  fl_xft_font(this,fnum,size,0);
+void Fl_Xlib_Graphics_Driver::font_unscaled(Fl_Font fnum, Fl_Fontsize size) {
+  fl_xft_font(this, fnum, size, 0);
 }
 
 static XftFont* fontopen(const char* name, /*Fl_Fontsize*/double size, bool core, int angle) {
@@ -691,17 +715,17 @@
 #endif
 }
 
-int Fl_Xlib_Graphics_Driver::height() {
+int Fl_Xlib_Graphics_Driver::height_unscaled() {
   if (font_descriptor()) return font_descriptor()->font->ascent + font_descriptor()->font->descent;
   else return -1;
 }
 
-int Fl_Xlib_Graphics_Driver::descent() {
+int Fl_Xlib_Graphics_Driver::descent_unscaled() {
   if (font_descriptor()) return font_descriptor()->font->descent;
   else return -1;
 }
 
-double Fl_Xlib_Graphics_Driver::width(const char* str, int n) {
+double Fl_Xlib_Graphics_Driver::width_unscaled(const char* str, int n) {
   if (!font_descriptor()) return -1.0;
   XGlyphInfo i;
   utf8extents(font_descriptor(), str, n, &i);
@@ -715,11 +739,12 @@
   return i.xOff;
 }
 
-double Fl_Xlib_Graphics_Driver::width(unsigned int c) {
+double Fl_Xlib_Graphics_Driver::width_unscaled(unsigned int c) {
+  if (!font_descriptor()) return -1.0;
   return fl_xft_width(font_descriptor(), (FcChar32 *)(&c), 1);
 }
 
-void Fl_Xlib_Graphics_Driver::text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h) {
+void Fl_Xlib_Graphics_Driver::text_extents_unscaled(const char *c, int n, int &dx, int &dy, int &w, int &h) {
   if (!font_descriptor()) {
     w = h = 0;
     dx = dy = 0;
@@ -730,15 +755,12 @@
 
   w = gi.width;
   h = gi.height;
-  dx = -gi.x;
-  dy = -gi.y;
-} // fl_text_extents
+  dx = -gi.x + line_delta_;
+  dy = -gi.y + line_delta_;
+  correct_extents(scale_, dx, dy, w, h);
+}
 
-
-void Fl_Xlib_Graphics_Driver::draw(const char *str, int n, int x, int y) {
-  if ( !this->font_descriptor() ) {
-    this->font(FL_HELVETICA, FL_NORMAL_SIZE);
-  }
+void Fl_Xlib_Graphics_Driver::draw_unscaled(const char *str, int n, int x, int y) {
 #if USE_OVERLAY
   XftDraw*& draw_ = fl_overlay ? draw_overlay : ::draw_;
   if (fl_overlay) {
@@ -756,31 +778,32 @@
     XftDrawChange(draw_, draw_window = fl_window);
 
   Region region = fl_clip_region();
-  if (region && XEmptyRegion(region)) return;
-  XftDrawSetClip(draw_, region);
-
-  // Use fltk's color allocator, copy the results to match what
-  // XftCollorAllocValue returns:
-  XftColor color;
-  color.pixel = fl_xpixel(Fl_Graphics_Driver::color());
-  uchar r,g,b; Fl::get_color(Fl_Graphics_Driver::color(), r,g,b);
-  color.color.red   = ((int)r)*0x101;
-  color.color.green = ((int)g)*0x101;
-  color.color.blue  = ((int)b)*0x101;
-  color.color.alpha = 0xffff;
-
-  const wchar_t *buffer = utf8reformat(str, n);
+  if (!(region && XEmptyRegion(region))) {
+    XftDrawSetClip(draw_, region);
+    
+    // Use fltk's color allocator, copy the results to match what
+    // XftCollorAllocValue returns:
+    XftColor color;
+    color.pixel = fl_xpixel(Fl_Graphics_Driver::color());
+    uchar r,g,b; Fl::get_color(Fl_Graphics_Driver::color(), r,g,b);
+    color.color.red   = ((int)r)*0x101;
+    color.color.green = ((int)g)*0x101;
+    color.color.blue  = ((int)b)*0x101;
+    color.color.alpha = 0xffff;
+    
+    const wchar_t *buffer = utf8reformat(str, n);
 #ifdef __CYGWIN__
-  XftDrawString16(draw_, &color, font_descriptor()->font, x+offset_x_, y+offset_y_, (XftChar16 *)buffer, n);
+    XftDrawString16(draw_, &color, font_descriptor()->font, x+offset_x_*scale_+line_delta_, y+offset_y_*scale_+line_delta_, (XftChar16 *)buffer, n);
 #else
-  XftDrawString32(draw_, &color, font_descriptor()->font, x+offset_x_, y+offset_y_, (XftChar32 *)buffer, n);
+    XftDrawString32(draw_, &color, font_descriptor()->font, x+offset_x_*scale_+line_delta_, y+offset_y_*scale_+line_delta_, (XftChar32 *)buffer, n);
 #endif
+  }
 }
 
-void Fl_Xlib_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) {
-  fl_xft_font(this, this->Fl_Graphics_Driver::font(), this->size(), angle);
-  this->draw(str, n, (int)x, (int)y);
-  fl_xft_font(this, this->Fl_Graphics_Driver::font(), this->size(), 0);
+void Fl_Xlib_Graphics_Driver::draw_unscaled(int angle, const char *str, int n, int x, int y) {
+  fl_xft_font(this, this->Fl_Graphics_Driver::font(), this->size_unscaled(), angle);
+  this->draw_unscaled(str, n, x, y);
+  fl_xft_font(this, this->Fl_Graphics_Driver::font(), this->size_unscaled(), 0);
 }
 
 void Fl_Xlib_Graphics_Driver::drawUCS4(const void *str, int n, int x, int y) {
@@ -814,11 +837,11 @@
   color.color.blue  = ((int)b)*0x101;
   color.color.alpha = 0xffff;
 
-  XftDrawString32(draw_, &color, font_descriptor()->font, x+offset_x_, y+offset_x_, (FcChar32 *)str, n);
+  XftDrawString32(draw_, &color, font_descriptor()->font, x+offset_x_*scale_+line_delta_, y+offset_y_*scale_+line_delta_, (FcChar32 *)str, n);
 }
 
 
-void Fl_Xlib_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) {
+void Fl_Xlib_Graphics_Driver::rtl_draw_unscaled(const char* c, int n, int x, int y) {
 
 #if defined(__GNUC__)
 // FIXME: warning Need to improve this XFT right to left draw function
@@ -902,7 +925,7 @@
 float Fl_Xlib_Graphics_Driver::scale_font_for_PostScript(Fl_Font_Descriptor *desc, int s) {
   // Xft font height is sometimes larger than the required size (see STR 2566).
   // Increase the PostScript font size by 15% without exceeding the display font height
-  int max = height();
+  int max = height_unscaled();
   float ps_size = s * 1.15;
   if (ps_size > max) ps_size = max;
   return ps_size;
@@ -972,7 +995,7 @@
     return;
   }
   Fl_Font_Descriptor* f = driver->font_descriptor();
-  if (fnum == driver->Fl_Graphics_Driver::font() && size == driver->size() && f && f->angle == angle)
+  if (fnum == driver->Fl_Graphics_Driver::font() && size == driver->size_unscaled() && f && f->angle == angle)
     return;
   driver->Fl_Graphics_Driver::font(fnum, size);
   Fl_Fontdesc *font = fl_fonts + fnum;
@@ -1021,7 +1044,7 @@
 //       well for the fltk "built-in" font names.
 static XFontStruct* load_xfont_for_xft2(Fl_Graphics_Driver *driver) {
   XFontStruct* xgl_font = 0;
-  int size = driver->size();
+  int size = ((Fl_Xlib_Graphics_Driver*)driver)->size_unscaled();
   int fnum = driver->font();
   const char *wt_med = "medium";
   const char *wt_bold = "bold";
@@ -1112,10 +1135,10 @@
   static int glsize = 0;
   static int glfont = -1;
   // Do we need to load a new font?
-  if ((!xgl_font) || (glsize != driver->size()) || (glfont != driver->font())) {
+  if ((!xgl_font) || (glsize != ((Fl_Xlib_Graphics_Driver*)driver)->size_unscaled()) || (glfont != driver->font())) {
     // create a dummy XLFD for some font of the appropriate size...
     if (xgl_font) XFreeFont(fl_display, xgl_font); // font already loaded, free it - this *might* be a Bad Idea
-    glsize = driver->size(); // record current font size
+    glsize = ((Fl_Xlib_Graphics_Driver*)driver)->size_unscaled(); // record current font size
     glfont = driver->font(); // and face
     xgl_font = load_xfont_for_xft2(driver);
   }
@@ -1126,7 +1149,7 @@
   }
   static XftFont* xftfont;
   if (xftfont) XftFontClose (fl_display, xftfont);
-  xftfont = fontopen(fl_fonts[driver->font()].name, driver->size(), true, 0); // else request XFT to load a suitable "core" font instead.
+  xftfont = fontopen(fl_fonts[driver->font()].name, ((Fl_Xlib_Graphics_Driver*)driver)->size_unscaled(), true, 0); // else request XFT to load a suitable "core" font instead.
   return xftfont->u.core.font;
 #  endif // XFT_MAJOR > 1
 }
@@ -1161,9 +1184,13 @@
   return pctxt_;
 }
 
-void Fl_Xlib_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) {
+void Fl_Xlib_Graphics_Driver::font_unscaled(Fl_Font fnum, Fl_Fontsize size) {
   if (!size) return;
-  if (this->Fl_Graphics_Driver::font() == fnum && this->size() == size) return;
+  if (size < 0) {
+    Fl_Graphics_Driver::font(0, 0);
+    return;
+  }
+  if (this->Fl_Graphics_Driver::font() == fnum && this->size_unscaled() == size) return;
   fl_xft_font(this, fnum, size, 0);
   init_built_in_fonts();
   if (pfd_) pango_font_description_free(pfd_);
@@ -1180,13 +1207,13 @@
   }
 }
 
-void Fl_Xlib_Graphics_Driver::draw(const char *str, int n, int x, int y) {
-  do_draw(0, str, n, x+offset_x_, y+offset_y_);
+void Fl_Xlib_Graphics_Driver::draw_unscaled(const char *str, int n, int x, int y) {
+  do_draw(0, str, n, x+offset_x_*scale_, y+offset_y_*scale_);
 }
 
-void Fl_Xlib_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) {
+void Fl_Xlib_Graphics_Driver::draw_unscaled(int angle, const char *str, int n, int x, int y) {
   PangoMatrix mat = PANGO_MATRIX_INIT; // 1.6
-  pango_matrix_translate(&mat, x+offset_x_, y+offset_y_); // 1.6
+  pango_matrix_translate(&mat, x+offset_x_*scale_, y+offset_y_*scale_); // 1.6
   pango_matrix_rotate(&mat, angle); // 1.6
   pango_context_set_matrix(pctxt_, &mat); // 1.6
   do_draw(0, str, n, 0, 0);
@@ -1193,8 +1220,8 @@
   pango_context_set_matrix(pctxt_, NULL); // 1.6
 }
 
-void Fl_Xlib_Graphics_Driver::rtl_draw(const char* str, int n, int x, int y) {
-  do_draw(1, str, n, x+offset_x_, y+offset_y_);
+void Fl_Xlib_Graphics_Driver::rtl_draw_unscaled(const char* str, int n, int x, int y) {
+  do_draw(1, str, n, x+offset_x_*scale_, y+offset_y_*scale_);
 }
 
 void Fl_Xlib_Graphics_Driver::do_draw(int from_right, const char *str, int n, int x, int y) {
@@ -1245,12 +1272,13 @@
   else
     XftDrawChange(draw_, draw_window = fl_window);
   XftDrawSetClip(draw_, region);
-  pango_xft_render_layout(draw_, &color, playout_, x*PANGO_SCALE, (y-height()+descent())*PANGO_SCALE ); // 1.8
-}
+  pango_xft_render_layout(draw_, &color, playout_, (x + line_delta_)*PANGO_SCALE,
+                          (y+line_delta_-height_unscaled()+descent_unscaled())*PANGO_SCALE ); // 1.8
+  }
 
-double Fl_Xlib_Graphics_Driver::width(const char* str, int n) {
+double Fl_Xlib_Graphics_Driver::width_unscaled(const char* str, int n) {
   if (!n) return 0;
-  if (!fl_display || fl_size() == 0) return -1;
+  if (!fl_display || size_ == 0) return -1;
   if (!playout_) context();
   int width, height;
   pango_layout_set_font_description(playout_, pfd_);
@@ -1259,30 +1287,32 @@
   return (double)width;
 }
 
-void Fl_Xlib_Graphics_Driver::text_extents(const char *str, int n, int &dx, int &dy, int &w, int &h) {
+void Fl_Xlib_Graphics_Driver::text_extents_unscaled(const char *str, int n, int &dx, int &dy, int &w, int &h) {
   if (!playout_) context();
   pango_layout_set_font_description(playout_, pfd_);
   pango_layout_set_text(playout_, str, n);
   PangoRectangle ink_rect, logical_rect;
   pango_layout_get_pixel_extents(playout_, &ink_rect, &logical_rect);
-  dx = ink_rect.x;
-  dy = ink_rect.y - height() + descent();
+  dx = ink_rect.x + line_delta_;
+  dy = ink_rect.y + line_delta_ - height_unscaled() + descent_unscaled();
   w = ink_rect.width;
   h = ink_rect.height;
+  correct_extents(scale_, dx, dy, w, h);
 }
 
-int Fl_Xlib_Graphics_Driver::height() {
+int Fl_Xlib_Graphics_Driver::height_unscaled() {
   return font_descriptor()->height_;
 }
 
-double Fl_Xlib_Graphics_Driver::width(unsigned int c) {
+double Fl_Xlib_Graphics_Driver::width_unscaled(unsigned int c) {
   char buf4[4];
   int n = fl_utf8encode(c, buf4);
-  return width(buf4, n);
+  return width_unscaled(buf4, n);
 }
 
-int Fl_Xlib_Graphics_Driver::descent() {
-  return font_descriptor()->descent_;
+int Fl_Xlib_Graphics_Driver::descent_unscaled() {
+  if (font_descriptor()) return font_descriptor()->descent_;
+  else return -1;
 }
 
 typedef int (*sort_f_type)(const void *aa, const void *bb);
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx	(revision 12216)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx	(working copy)
@@ -47,10 +47,13 @@
 
 #include <config.h>
 #include "Fl_Xlib_Graphics_Driver.H"
+#include "../X11/Fl_X11_Screen_Driver.H"
+#include "../X11/Fl_X11_Window_Driver.H"
 #  include <FL/Fl.H>
 #  include <FL/fl_draw.H>
 #  include <FL/x.H>
 #  include <FL/Fl_Image_Surface.H>
+#  include <FL/Fl_Screen_Driver.H>
 #  include "../../Fl_XColor.H"
 #  include "../../flstring.h"
 #if HAVE_XRENDER
@@ -476,7 +479,6 @@
   if (w<=0 || h<=0) return;
   dx -= X;
   dy -= Y;
-
   if (!bytes_per_pixel) figure_out_visual();
   const unsigned oldbpp = bytes_per_pixel;
   static GC gc32 = None;
@@ -574,16 +576,16 @@
   }
 }
 
-void Fl_Xlib_Graphics_Driver::draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l){
+void Fl_Xlib_Graphics_Driver::draw_image_unscaled(const uchar* buf, int x, int y, int w, int h, int d, int l){
 
   const bool alpha = !!(abs(d) & FL_IMAGE_WITH_ALPHA);
   if (alpha) d ^= FL_IMAGE_WITH_ALPHA;
   const int mono = (d>-3 && d<3);
 
-  innards(buf,x+offset_x_,y+offset_y_,w,h,d,l,mono,0,0,alpha,gc_);
+  innards(buf,x+offset_x_*scale_,y+offset_y_*scale_,w,h,d,l,mono,0,0,alpha,gc_);
 }
 
-void Fl_Xlib_Graphics_Driver::draw_image(Fl_Draw_Image_Cb cb, void* data,
+void Fl_Xlib_Graphics_Driver::draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data,
 		   int x, int y, int w, int h,int d) {
 
   const bool alpha = !!(abs(d) & FL_IMAGE_WITH_ALPHA);
@@ -590,16 +592,16 @@
   if (alpha) d ^= FL_IMAGE_WITH_ALPHA;
   const int mono = (d>-3 && d<3);
 
-  innards(0,x+offset_x_,y+offset_y_,w,h,d,0,mono,cb,data,alpha,gc_);
+  innards(0,x+offset_x_*scale_,y+offset_y_*scale_,w,h,d,0,mono,cb,data,alpha,gc_);
 }
 
-void Fl_Xlib_Graphics_Driver::draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){
-  innards(buf,x+offset_x_,y+offset_y_,w,h,d,l,1,0,0,0,gc_);
+void Fl_Xlib_Graphics_Driver::draw_image_mono_unscaled(const uchar* buf, int x, int y, int w, int h, int d, int l){
+  innards(buf,x+offset_x_*scale_,y+offset_y_*scale_,w,h,d,l,1,0,0,0,gc_);
 }
 
-void Fl_Xlib_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb cb, void* data,
+void Fl_Xlib_Graphics_Driver::draw_image_mono_unscaled(Fl_Draw_Image_Cb cb, void* data,
 		   int x, int y, int w, int h,int d) {
-  innards(0,x+offset_x_,y+offset_y_,w,h,d,0,1,cb,data,0,gc_);
+  innards(0,x+offset_x_*scale_,y+offset_y_*scale_,w,h,d,0,1,cb,data,0,gc_);
 }
 
 void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) {
@@ -622,15 +624,14 @@
   XFreePixmap(fl_display, bm);
 }
 
-void Fl_Xlib_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) {
-  int X, Y, W, H;
-  if (Fl_Graphics_Driver::prepare(bm, XP+offset_x_, YP+offset_y_, WP, HP, cx, cy, X, Y, W, H)) {
-    return;
-  }
-
+void Fl_Xlib_Graphics_Driver::draw_unscaled(Fl_Bitmap *bm, float s, int X, int Y, int W, int H, int cx, int cy) {
+  X = (X+offset_x_)*s;
+  Y = (Y+offset_y_)*s;
+  cache_size(bm, W, H);
+  cx *= s; cy *= s;
   XSetStipple(fl_display, gc_, *Fl_Graphics_Driver::id(bm));
-  int ox = X-cx; if (ox < 0) ox += bm->w();
-  int oy = Y-cy; if (oy < 0) oy += bm->h();
+  int ox = X-cx; if (ox < 0) ox += bm->w()*s;
+  int oy = Y-cy; if (oy < 0) oy += bm->h()*s;
   XSetTSOrigin(fl_display, gc_, ox, oy);
   XSetFillStyle(fl_display, gc_, FillStippled);
   XFillRectangle(fl_display, fl_window, gc_, X, Y, W, H);
@@ -715,33 +716,39 @@
   return off;
 }
 
-void Fl_Xlib_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) {
-  int X, Y, W, H;
-  XP += offset_x_;
-  YP += offset_y_;
-  // Don't draw an empty image...
-  if (!img->d() || !img->array) {
-    Fl_Graphics_Driver::draw_empty(img, XP, YP);
-    return;
-  }
-  if (start_image(img, XP, YP, WP, HP, cx, cy, X, Y, W, H)) {
-    return;
-  }
+void Fl_Xlib_Graphics_Driver::draw_unscaled(Fl_RGB_Image *img, float s, int X, int Y, int W, int H, int cx, int cy) {
+  X = (X+offset_x_)*s;
+  Y = (Y+offset_y_)*s;
+  cache_size(img, W, H);
+  cx *= s; cy *= s;
   if (!*Fl_Graphics_Driver::id(img)) {
     *Fl_Graphics_Driver::id(img) = cache_rgb(img);
+    *cache_scale(img) = 1;
   }
+  Fl_Region r2 = scale_clip(scale_);
   if (*Fl_Graphics_Driver::id(img)) {
     if (img->d() == 4 || img->d() == 2) {
 #if HAVE_XRENDER
-      scale_and_render_pixmap(*Fl_Graphics_Driver::id(img), 4, 1, 1, cx, cy, X - offset_x_, Y - offset_y_, W, H);
+      scale_and_render_pixmap(*Fl_Graphics_Driver::id(img), img->d(), 1, 1, cx, cy, X, Y, W, H);
 #endif
     } else {
-      copy_offscreen(X - offset_x_, Y - offset_y_, W, H, *Fl_Graphics_Driver::id(img), cx, cy);
+      XCopyArea(fl_display, *Fl_Graphics_Driver::id(img), fl_window, gc_, cx, cy, W, H, X, Y);
     }
   } else {
     // Composite image with alpha manually each time...
+    scale_ = 1;
+    int ox = offset_x_, oy = offset_y_;
+    offset_x_ = offset_y_ = 0;
+    Fl_X11_Screen_Driver *d = (Fl_X11_Screen_Driver*)Fl::screen_driver();
+    int nscreen = Fl_Window::current()->driver()->screen_num();
+    float keep = d->scale(nscreen);
+    d->scale(nscreen, 1);
     alpha_blend(img, X, Y, W, H, cx, cy);
+    d->scale(nscreen, keep);
+    scale_ = s;
+    offset_x_ = ox; offset_y_ = oy;
   }
+  unscale_clip(r2);
 }
 
 void Fl_Xlib_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uintptr_t &mask_)
@@ -752,13 +759,17 @@
   }
 }
 
-fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Bitmap*, int w, int h, const uchar *array) {
+fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Bitmap *bm, int w, int h, const uchar *array) {
+  *cache_scale(bm) =  Fl_Scalable_Graphics_Driver::scale();
   return (fl_uintptr_t)create_bitmask(w, h, array);
 }
 
-void Fl_Xlib_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) {
-  int X, Y, W, H;
-  if (Fl_Graphics_Driver::prepare(pxm, XP+offset_x_, YP+offset_y_, WP, HP, cx, cy, X, Y, W, H)) return;
+void Fl_Xlib_Graphics_Driver::draw_unscaled(Fl_Pixmap *pxm, float s, int X, int Y, int W, int H, int cx, int cy) {
+  X = (X+offset_x_)*s;
+  Y = (Y+offset_y_)*s;
+  cache_size(pxm, W, H);
+  cx *= s; cy *= s;
+  Fl_Region r2 = scale_clip(s);
   if (*Fl_Graphics_Driver::mask(pxm)) {
     // make X use the bitmap as a mask:
     XSetClipMask(fl_display, gc_, *Fl_Graphics_Driver::mask(pxm));
@@ -781,21 +792,24 @@
         Y1 = r->rects[i].y1;
         W1 = r->rects[i].x2 - r->rects[i].x1;
         H1 = r->rects[i].y2 - r->rects[i].y1;
-        copy_offscreen(X1-offset_x_, Y1-offset_y_, W1, H1, *Fl_Graphics_Driver::id(pxm), cx + (X1 - X), cy + (Y1 - Y));
+        XCopyArea(fl_display, *Fl_Graphics_Driver::id(pxm), fl_window, gc_, cx + (X1 - X), cy + (Y1 - Y), W1, H1, X1, Y1);
       }
       XDestroyRegion(r);
     } else {
-      copy_offscreen(X-offset_x_, Y-offset_y_, W, H, *Fl_Graphics_Driver::id(pxm), cx, cy);
+      XCopyArea(fl_display, *Fl_Graphics_Driver::id(pxm), fl_window, gc_, cx, cy, W, H, X, Y);
     }
     // put the old clip region back
     XSetClipOrigin(fl_display, gc_, 0, 0);
+    s = scale_; scale_ = 1;
     restore_clip();
+    scale_ = s;
   }
-  else copy_offscreen(X-offset_x_, Y-offset_y_, W, H, *Fl_Graphics_Driver::id(pxm), cx, cy);
+  else XCopyArea(fl_display, *Fl_Graphics_Driver::id(pxm), fl_window, gc_, cx, cy, W, H, X, Y);
+  unscale_clip(r2);
 }
 
 
-fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Pixmap *img, int w, int h, const char *const*data) {
+fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Pixmap *pxm, int w, int h, const char *const*data) {
   Fl_Offscreen id;
   id = fl_create_offscreen(w, h);
   fl_begin_offscreen(id);
@@ -804,22 +818,25 @@
   fl_draw_pixmap(data, 0, 0, FL_BLACK);
   Fl_Surface_Device::surface()->driver()->mask_bitmap(0);
   if (bitmap) {
-    *Fl_Graphics_Driver::mask(img) = (fl_uintptr_t)fl_create_bitmask(w, h, bitmap);
+    *Fl_Graphics_Driver::mask(pxm) = (fl_uintptr_t)create_bitmask(w * scale_, h * scale_, bitmap);
     delete[] bitmap;
   }
   fl_end_offscreen();
+  *cache_scale(pxm) =  Fl_Scalable_Graphics_Driver::scale();
   return (fl_uintptr_t)id;
 }
 
 
 #if HAVE_XRENDER
+/* Draws with Xrender an Fl_Offscreen with optional scaling and accounting for transparency if necessary.
+ */
 int Fl_Xlib_Graphics_Driver::scale_and_render_pixmap(Fl_Offscreen pixmap, int depth, double scale_x, double scale_y, int srcx, int srcy, int XP, int YP, int WP, int HP) {
+  bool has_alpha = (depth == 2 || depth == 4);
   XRenderPictureAttributes srcattr;
   memset(&srcattr, 0, sizeof(XRenderPictureAttributes));
   static XRenderPictFormat *fmt32 = XRenderFindStandardFormat(fl_display, PictStandardARGB32);
   static XRenderPictFormat *fmt24 = XRenderFindStandardFormat(fl_display, PictStandardRGB24);
-  Picture src = XRenderCreatePicture(fl_display, pixmap,
-                                     depth%2 == 0 ?fmt32:fmt24, 0, &srcattr);
+  Picture src = XRenderCreatePicture(fl_display, pixmap, has_alpha ?fmt32:fmt24, 0, &srcattr);
   Picture dst = XRenderCreatePicture(fl_display, fl_window, fmt24, 0, &srcattr);
   if (!src || !dst) {
     fprintf(stderr, "Failed to create Render pictures (%lu %lu)\n", src, dst);
@@ -836,8 +853,8 @@
     }};
     XRenderSetPictureTransform(fl_display, src, &mat);
   }
-  XRenderComposite(fl_display, (depth%2 == 0 ? PictOpOver : PictOpSrc), src, None, dst, srcx, srcy, 0, 0,
-                   XP + offset_x_, YP + offset_y_, WP, HP);
+  XRenderComposite(fl_display, (has_alpha ? PictOpOver : PictOpSrc), src, None, dst, srcx, srcy, 0, 0,
+                   XP, YP, WP, HP);
   XRenderFreePicture(fl_display, src);
   XRenderFreePicture(fl_display, dst);
   return 1;
@@ -845,13 +862,15 @@
 
 
 int Fl_Xlib_Graphics_Driver::draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP) {
+//return 0;//see what is best
   Fl_RGB_Image *rgb = img->as_rgb_image();
   if (!rgb || !can_do_alpha_blending()) return 0;
   if (!*Fl_Graphics_Driver::id(rgb)) {
     *Fl_Graphics_Driver::id(rgb) = cache_rgb(rgb);
+    *cache_scale(rgb) = 1;
   }
-  return scale_and_render_pixmap(*Fl_Graphics_Driver::id(rgb), rgb->d(), rgb->w()/double(WP), rgb->h()/double(HP),
-                          0, 0, XP, YP, WP, HP);
+  return scale_and_render_pixmap( *Fl_Graphics_Driver::id(rgb), rgb->d(),
+                                 rgb->w() / double(WP), rgb->h() / double(HP), 0, 0, XP + offset_x_*scale_, YP + offset_y_*scale_, WP, HP);
 }
 #endif // HAVE_XRENDER
 
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.cxx	(revision 12216)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // Line style code for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -34,10 +34,9 @@
 
 #include "Fl_Xlib_Graphics_Driver.H"
 
-void Fl_Xlib_Graphics_Driver::line_style(int style, int width, char* dashes) {
-
+void Fl_Xlib_Graphics_Driver::line_style_unscaled(int style, float width, char* dashes) {
   // save line width for X11 clipping
-  if (width == 0) line_width_ = 1;
+  if (width == 0) line_width_ = scale_ < 2 ? 0 : scale_;
   else line_width_ = width>0 ? width : -width;
 
   int ndashes = dashes ? strlen(dashes) : 0;
@@ -63,10 +62,12 @@
     case FL_DASHDOTDOT: *p++ = dash; *p++ = gap; *p++ = dot; *p++ = gap; *p++ = dot; *p++ = gap; break;
     }
     ndashes = p-buf;
+if (*dashes == 0) ndashes = 0;//against error with very small scaling
   }
   static int Cap[4] = {CapButt, CapButt, CapRound, CapProjecting};
   static int Join[4] = {JoinMiter, JoinMiter, JoinRound, JoinBevel};
-  XSetLineAttributes(fl_display, gc_, width,
+  XSetLineAttributes(fl_display, gc_,
+                     line_width_,
 		     ndashes ? LineOnOffDash : LineSolid,
 		     Cap[(style>>8)&3], Join[(style>>12)&3]);
   if (ndashes) XSetDashes(fl_display, gc_, 0, dashes, ndashes);
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx	(revision 12216)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // Rectangle drawing routines for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -161,112 +161,167 @@
   ::XDestroyRegion(r);
 }
 
-// --- line and polygon drawing with integer coordinates
+// --- line and polygon drawing
 
-void Fl_Xlib_Graphics_Driver::point(int x, int y) {
-  XDrawPoint(fl_display, fl_window, gc_, clip_x(x+offset_x_), clip_x(y+offset_y_));
-}
 
-void Fl_Xlib_Graphics_Driver::rect(int x, int y, int w, int h) {
-  if (w<=0 || h<=0) return;
-  x+=offset_x_; y+=offset_y_;
+void Fl_Xlib_Graphics_Driver::rect_unscaled(float fx, float fy, float fw, float fh) {
+  if (fw<=0 || fh<=0) return;
+  int deltaf = scale_ >= 2 ? scale_-1 : 0;
+  fx += offset_x_*scale_; fy += offset_y_*scale_;
+  int x = fx; int y = fy;
+  int w = int(int(fx/scale_+fw/scale_+0.5)*scale_) - x - 1 - deltaf;
+  int h = int(int(fy/scale_+fh/scale_+0.5)*scale_) - y - 1 - deltaf;
   if (!clip_to_short(x, y, w, h, line_width_))
-    XDrawRectangle(fl_display, fl_window, gc_, x, y, w-1, h-1);
+    XDrawRectangle(fl_display, fl_window, gc_, x+line_delta_, y+line_delta_, w, h);
 }
 
-void Fl_Xlib_Graphics_Driver::rectf(int x, int y, int w, int h) {
-  if (w<=0 || h<=0) return;
-  x+=offset_x_; y+=offset_y_;
+void Fl_Xlib_Graphics_Driver::rectf_unscaled(float fx, float fy, float fw, float fh) {
+  if (fw<=0 || fh<=0) return;
+  int deltaf = scale_ >= 2 ? scale_/2 : 0;
+  fx += offset_x_*scale_; fy += offset_y_*scale_;
+  int x = fx-deltaf; int y = fy-deltaf;
+  // make sure no unfilled area lies between rectf(x,y,w,h) and  rectf(x+w,y,1,h) or rectf(x,y+w,w,1)
+  int w = int(int(fx/scale_+fw/scale_+0.5)*scale_) - int(fx);
+  int h = int(int(fy/scale_+fh/scale_+0.5)*scale_) - int(fy);
   if (!clip_to_short(x, y, w, h, line_width_))
-    XFillRectangle(fl_display, fl_window, gc_, x, y, w, h);
+    XFillRectangle(fl_display, fl_window, gc_, x+line_delta_, y+line_delta_, w, h);
 }
 
-void Fl_Xlib_Graphics_Driver::line(int x, int y, int x1, int y1) {
-  XDrawLine(fl_display, fl_window, gc_, x+offset_x_, y+offset_y_, x1+offset_x_, y1+offset_y_);
+void Fl_Xlib_Graphics_Driver::point_unscaled(float fx, float fy) {
+  int deltaf = scale_ >= 2 ? scale_/2 : 0;
+  int x = fx+offset_x_*scale_-deltaf; int y = fy+offset_y_*scale_-deltaf;
+  int width = scale_ >= 1 ? scale_ : 1;
+  XFillRectangle(fl_display, fl_window, gc_, x+line_delta_, y+line_delta_, width, width);
 }
 
-void Fl_Xlib_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) {
+void Fl_Xlib_Graphics_Driver::line_unscaled(float x, float y, float x1, float y1) {
+  if (x == x1) yxline_unscaled(x, y, y1);
+  else if (y == y1) xyline_unscaled(x, y, x1);
+  else XDrawLine(fl_display, fl_window, gc_, x+offset_x_*scale_+line_delta_, y+offset_y_*scale_+line_delta_, x1+offset_x_*scale_+line_delta_, y1+offset_y_*scale_+line_delta_);
+}
+
+void Fl_Xlib_Graphics_Driver::line_unscaled(float x, float y, float x1, float y1, float x2, float y2) {
   XPoint p[3];
-  p[0].x = x+offset_x_;  p[0].y = y+offset_y_;
-  p[1].x = x1+offset_x_; p[1].y = y1+offset_y_;
-  p[2].x = x2+offset_x_; p[2].y = y2+offset_y_;
+  p[0].x = x+offset_x_*scale_+line_delta_;  p[0].y = y+offset_y_*scale_+line_delta_;
+  p[1].x = x1+offset_x_*scale_+line_delta_; p[1].y = y1+offset_y_*scale_+line_delta_;
+  p[2].x = x2+offset_x_*scale_+line_delta_; p[2].y = y2+offset_y_*scale_+line_delta_;
   XDrawLines(fl_display, fl_window, gc_, p, 3, 0);
 }
 
-void Fl_Xlib_Graphics_Driver::xyline(int x, int y, int x1) {
-  XDrawLine(fl_display, fl_window, gc_, clip_x(x+offset_x_), clip_x(y+offset_y_), clip_x(x1+offset_x_), clip_x(y+offset_y_));
+void Fl_Xlib_Graphics_Driver::xyline_unscaled(float x, float y, float x1) {//OK
+  x+=offset_x_*scale_; y+=offset_y_*scale_; x1 += offset_x_*scale_;
+  int tw = line_width_ ? line_width_ : 1; // true line width
+  if (x > x1) { float exch = x; x = x1; x1 = exch; }
+  int ix = clip_x(x+line_delta_); if (scale_ >= 2) ix -= int(scale_/2);
+  int iy = clip_x(y+line_delta_);
+  int ix1 = int(x1/scale_+1.5)*scale_-1; if (scale_ >= 2) ix1 += int(scale_/2); if (scale_ >= 4) ix1 -= scale_/2;
+  XDrawLine(fl_display, fl_window, gc_, ix, iy, ix1, iy);
+  // try and make sure no unfilled area lies between xyline(x,y,x1) and xyline(x,y+1,x1)
+  if (y+line_delta_ + scale_ >= iy + tw+1 - 0.001 ) XDrawLine(fl_display, fl_window, gc_, ix, iy+1, ix1, iy+1);
 }
 
-void Fl_Xlib_Graphics_Driver::xyline(int x, int y, int x1, int y2) {
+void Fl_Xlib_Graphics_Driver::xyline_unscaled(float x, float y, float x1, float y2) {//OK
+  x+=offset_x_*scale_; y+=offset_y_*scale_; x1 += offset_x_*scale_; y2+=offset_y_*scale_;
+  if (scale_ >= 2) {
+    int delta = int(scale_/2 + 0.5);
+    if (x > x1) x += delta; else x -= delta;
+    if (y2 > y) y2 += delta; else y2 -= delta;
+  }
   XPoint p[3];
-  p[0].x = clip_x(x+offset_x_);  p[0].y = p[1].y = clip_x(y+offset_y_);
-  p[1].x = p[2].x = clip_x(x1+offset_x_); p[2].y = clip_x(y2+offset_y_);
+  p[0].x = clip_x(x+line_delta_);  p[0].y = p[1].y = clip_x(y+line_delta_);
+  p[1].x = p[2].x = clip_x(x1+line_delta_); p[2].y = clip_x(y2+line_delta_);
   XDrawLines(fl_display, fl_window, gc_, p, 3, 0);
 }
 
-void Fl_Xlib_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) {
+void Fl_Xlib_Graphics_Driver::xyline_unscaled(float x, float y, float x1, float y2, float x3) {
+  x+=offset_x_*scale_; y+=offset_y_*scale_; x1 += offset_x_*scale_; y2+=offset_y_*scale_; x3 += offset_x_*scale_;
+  if (scale_ >= 2) {
+    int delta = int(scale_/2 + 0.5);
+    if (x > x1) x += delta; else x -= delta;
+    if (x3 > x1) x3 += delta; else x3 -= delta;
+  }
   XPoint p[4];
-  p[0].x = clip_x(x+offset_x_);  p[0].y = p[1].y = clip_x(y+offset_y_);
-  p[1].x = p[2].x = clip_x(x1+offset_x_); p[2].y = p[3].y = clip_x(y2+offset_y_);
-  p[3].x = clip_x(x3+offset_x_);
+  p[0].x = clip_x(x+line_delta_);  p[0].y = p[1].y = clip_x(y+line_delta_);
+  p[1].x = p[2].x = clip_x(x1+line_delta_); p[2].y = p[3].y = clip_x(y2+line_delta_);
+  p[3].x = clip_x(x3+line_delta_);
   XDrawLines(fl_display, fl_window, gc_, p, 4, 0);
 }
 
-void Fl_Xlib_Graphics_Driver::yxline(int x, int y, int y1) {
-  XDrawLine(fl_display, fl_window, gc_, clip_x(x+offset_x_), clip_x(y+offset_y_), clip_x(x+offset_x_), clip_x(y1+offset_y_));
+void Fl_Xlib_Graphics_Driver::yxline_unscaled(float x, float y, float y1) {//OK
+  x+=offset_x_*scale_; y+=offset_y_*scale_; y1 += offset_y_*scale_;
+  int tw = line_width_ ? line_width_ : 1; // true line width
+  if (y > y1) { float exch = y; y = y1; y1 = exch; }
+  int ix = clip_x(x+line_delta_);
+  int iy = clip_x(y+line_delta_); if (scale_ >= 2) iy -= int(scale_/2);
+  int iy1 = int(y1/scale_+1.5)*scale_-1; if (scale_ >= 2) iy1 += int(scale_/2); if (scale_ >= 4) iy1 -= scale_/2;
+  XDrawLine(fl_display, fl_window, gc_, ix, iy, ix, iy1);
+  // try and make sure no unfilled area lies between yxline(x,y,y1) and yxline(x+1,y,y1)
+  if (x+line_delta_+scale_ >= ix + tw+1 -0.001) XDrawLine(fl_display, fl_window, gc_, ix+1, iy, ix+1, iy1);
 }
 
-void Fl_Xlib_Graphics_Driver::yxline(int x, int y, int y1, int x2) {
+void Fl_Xlib_Graphics_Driver::yxline_unscaled(float x, float y, float y1, float x2) {
+  x+=offset_x_*scale_; y+=offset_y_*scale_; y1 += offset_y_*scale_; x2+=offset_x_*scale_;
+  if (scale_ >= 2) {
+    int delta = int(scale_/2 + 0.5);
+    if (y > y1) y += delta; else y -= delta;
+    if (x2 > x) x2 += delta; else x2 -= delta;
+  }
   XPoint p[3];
-  p[0].x = p[1].x = clip_x(x+offset_x_);  p[0].y = clip_x(y+offset_y_);
-  p[1].y = p[2].y = clip_x(y1+offset_y_); p[2].x = clip_x(x2+offset_x_);
+  p[0].x = p[1].x = clip_x(x+line_delta_);  p[0].y = clip_x(y+line_delta_);
+  p[1].y = p[2].y = clip_x(y1+line_delta_); p[2].x = clip_x(x2+line_delta_);
   XDrawLines(fl_display, fl_window, gc_, p, 3, 0);
 }
 
-void Fl_Xlib_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) {
+void Fl_Xlib_Graphics_Driver::yxline_unscaled(float x, float y, float y1, float x2, float y3) {
+  x+=offset_x_*scale_; y+=offset_y_*scale_; y1 += offset_y_*scale_; x2+=offset_x_*scale_; y3 += offset_y_*scale_;
+  if (scale_ >= 2) {
+    int delta = int(scale_/2 + 0.5);
+    if (y > y1) y += delta; else y -= delta;
+    if (y3 > y1) y3 += delta; else y3 -= delta;
+  }
   XPoint p[4];
-  p[0].x = p[1].x = clip_x(x+offset_x_);  p[0].y = clip_x(y+offset_y_);
-  p[1].y = p[2].y = clip_x(y1+offset_y_); p[2].x = p[3].x = clip_x(x2+offset_x_);
-  p[3].y = clip_x(y3+offset_y_);
+  p[0].x = p[1].x = clip_x(x+line_delta_);  p[0].y = clip_x(y+line_delta_);
+  p[1].y = p[2].y = clip_x(y1+line_delta_); p[2].x = p[3].x = clip_x(x2+line_delta_);
+  p[3].y = clip_x(y3+line_delta_);
   XDrawLines(fl_display, fl_window, gc_, p, 4, 0);
 }
 
-void Fl_Xlib_Graphics_Driver::loop(int x, int y, int x1, int y1, int x2, int y2) {
+void Fl_Xlib_Graphics_Driver::loop_unscaled(float x, float y, float x1, float y1, float x2, float y2) {
   XPoint p[4];
-  p[0].x = x+offset_x_;  p[0].y = y+offset_y_;
-  p[1].x = x1+offset_x_; p[1].y = y1+offset_y_;
-  p[2].x = x2+offset_x_; p[2].y = y2+offset_y_;
-  p[3].x = x+offset_x_;  p[3].y = y+offset_y_;
+  p[0].x = x +offset_x_*scale_+line_delta_;  p[0].y = y +offset_y_*scale_+line_delta_;
+  p[1].x = x1 +offset_x_*scale_+line_delta_; p[1].y = y1 +offset_y_*scale_+line_delta_;
+  p[2].x = x2 +offset_x_*scale_+line_delta_; p[2].y = y2 +offset_y_*scale_+line_delta_;
+  p[3].x = x +offset_x_*scale_+line_delta_;  p[3].y = y +offset_y_*scale_+line_delta_;
   XDrawLines(fl_display, fl_window, gc_, p, 4, 0);
 }
 
-void Fl_Xlib_Graphics_Driver::loop(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
+void Fl_Xlib_Graphics_Driver::loop_unscaled(float x, float y, float x1, float y1, float x2, float y2, float x3, float y3) {
   XPoint p[5];
-  p[0].x = x+offset_x_;  p[0].y = y+offset_y_;
-  p[1].x = x1+offset_x_; p[1].y = y1+offset_y_;
-  p[2].x = x2+offset_x_; p[2].y = y2+offset_y_;
-  p[3].x = x3+offset_x_; p[3].y = y3+offset_y_;
-  p[4].x = x+offset_x_;  p[4].y = y+offset_y_;
+  p[0].x = x+offset_x_*scale_+line_delta_;  p[0].y = y+offset_y_*scale_+line_delta_;
+  p[1].x = x1 +offset_x_*scale_+line_delta_; p[1].y = y1+offset_y_*scale_+line_delta_;
+  p[2].x = x2+offset_x_*scale_+line_delta_; p[2].y = y2+offset_y_*scale_+line_delta_;
+  p[3].x = x3+offset_x_*scale_+line_delta_; p[3].y = y3+offset_y_*scale_+line_delta_;
+  p[4].x = x+offset_x_*scale_+line_delta_;  p[4].y = y+offset_y_*scale_+line_delta_;
   XDrawLines(fl_display, fl_window, gc_, p, 5, 0);
 }
 
-void Fl_Xlib_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2) {
+void Fl_Xlib_Graphics_Driver::polygon_unscaled(float x, float y, float x1, float y1, float x2, float y2) {
   XPoint p[4];
-  p[0].x = x+offset_x_;  p[0].y = y+offset_y_;
-  p[1].x = x1+offset_x_; p[1].y = y1+offset_y_;
-  p[2].x = x2+offset_x_; p[2].y = y2+offset_y_;
-  p[3].x = x+offset_x_;  p[3].y = y+offset_y_;
+  p[0].x = x+offset_x_*scale_+line_delta_;  p[0].y = y+offset_y_*scale_+line_delta_;
+  p[1].x = x1+offset_x_*scale_+line_delta_; p[1].y = y1+offset_y_*scale_+line_delta_;
+  p[2].x = x2+offset_x_*scale_+line_delta_; p[2].y = y2+offset_y_*scale_+line_delta_;
+  p[3].x = x+offset_x_*scale_+line_delta_;  p[3].y = y+offset_y_*scale_+line_delta_;
   XFillPolygon(fl_display, fl_window, gc_, p, 3, Convex, 0);
   XDrawLines(fl_display, fl_window, gc_, p, 4, 0);
 }
 
-void Fl_Xlib_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
+void Fl_Xlib_Graphics_Driver::polygon_unscaled(float x, float y, float x1, float y1, float x2, float y2, float x3, float y3) {
   XPoint p[5];
-  p[0].x = x+offset_x_;  p[0].y = y+offset_y_;
-  p[1].x = x1+offset_x_; p[1].y = y1+offset_y_;
-  p[2].x = x2+offset_x_; p[2].y = y2+offset_y_;
-  p[3].x = x3+offset_x_; p[3].y = y3+offset_y_;
-  p[4].x = x+offset_x_;  p[4].y = y+offset_y_;
+  p[0].x = x+offset_x_*scale_+line_delta_;  p[0].y = y+offset_y_*scale_+line_delta_;
+  p[1].x = x1+offset_x_*scale_+line_delta_; p[1].y = y1+offset_y_*scale_+line_delta_;
+  p[2].x = x2+offset_x_*scale_+line_delta_; p[2].y = y2+offset_y_*scale_+line_delta_;
+  p[3].x = x3+offset_x_*scale_+line_delta_; p[3].y = y3+offset_y_*scale_+line_delta_;
+  p[4].x = x+offset_x_*scale_+line_delta_;  p[4].y = y+offset_y_*scale_+line_delta_;
   XFillPolygon(fl_display, fl_window, gc_, p, 4, Convex, 0);
   XDrawLines(fl_display, fl_window, gc_, p, 5, 0);
 }
@@ -276,7 +331,7 @@
 void Fl_Xlib_Graphics_Driver::push_clip(int x, int y, int w, int h) {
   Fl_Region r;
   if (w > 0 && h > 0) {
-    r = XRectangleRegion(x+offset_x_,y+offset_y_,w,h);
+    r = XRectangleRegion(x,y,w,h);
     Fl_Region current = rstack[rstackptr];
     if (current) {
       Fl_Region temp = XCreateRegion();
@@ -294,8 +349,6 @@
 
 int Fl_Xlib_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H){
   X = x; Y = y; W = w; H = h;
-  x += offset_x_;
-  y += offset_y_;
   Fl_Region r = rstack[rstackptr];
   if (!r) return 0;
   switch (XRectInRegion(r, x, y, w, h)) {
@@ -312,7 +365,7 @@
   XIntersectRegion(r, rr, temp);
   XRectangle rect;
   XClipBox(temp, &rect);
-  X = rect.x - offset_x_; Y = rect.y - offset_y_; W = rect.width; H = rect.height;
+  X = rect.x; Y = rect.y; W = rect.width; H = rect.height;
   XDestroyRegion(temp);
   XDestroyRegion(rr);
   return 1;
@@ -319,8 +372,6 @@
 }
 
 int Fl_Xlib_Graphics_Driver::not_clipped(int x, int y, int w, int h) {
-  x += offset_x_;
-  y += offset_y_;
   if (x+w <= 0 || y+h <= 0) return 0;
   Fl_Region r = rstack[rstackptr];
   if (!r) return 1;
@@ -348,8 +399,12 @@
 void Fl_Xlib_Graphics_Driver::restore_clip() {
   fl_clip_state_number++;
   if (gc_) {
-    Fl_Region r = rstack[rstackptr];
-    if (r) XSetRegion(fl_display, gc_, r);
+    Region r = rstack[rstackptr];
+    if (r) {
+      Region r2 = scale_clip(scale_);
+      XSetRegion(fl_display, gc_, rstack[rstackptr]);
+      unscale_clip(r2);
+    }
     else XSetClipMask(fl_display, gc_, 0);
   }
 }
Index: src/drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.cxx	(revision 12216)
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // Portable drawing routines for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -30,14 +30,6 @@
 #include <FL/math.h>
 
 
-void Fl_Xlib_Graphics_Driver::transformed_vertex(double xf, double yf) {
-  transformed_vertex0(short(rint(xf)), short(rint(yf)));
-}
-
-void Fl_Xlib_Graphics_Driver::vertex(double x,double y) {
-  transformed_vertex0(short(x*m.a + y*m.c + m.x), short(x*m.b + y*m.d + m.y));
-}
-
 void Fl_Xlib_Graphics_Driver::end_points() {
   if (n>1) XDrawPoints(fl_display, fl_window, gc_, (XPoint*)p, n, 0);
 }
@@ -52,7 +44,9 @@
 
 void Fl_Xlib_Graphics_Driver::end_loop() {
   fixloop();
-  if (n>2) transformed_vertex((short)p[0].x, (short)p[0].y);
+  if (n>2) {
+    transformed_vertex0(p[0].x, p[0].y);
+  }
   end_line();
 }
 
@@ -73,7 +67,7 @@
 void Fl_Xlib_Graphics_Driver::gap() {
   while (n>gap_+2 && p[n-1].x == p[gap_].x && p[n-1].y == p[gap_].y) n--;
   if (n > gap_+2) {
-    transformed_vertex((short)p[gap_].x, (short)p[gap_].y);
+    transformed_vertex0(p[gap_].x, p[gap_].y);
     gap_ = n;
   } else {
     n = gap_;
@@ -92,12 +86,7 @@
 // shortcut the closed circles so they use XDrawArc:
 // warning: these do not draw rotated ellipses correctly!
 // See fl_arc.c for portable version.
-
-void Fl_Xlib_Graphics_Driver::circle(double x, double y,double r) {
-  double xt = transform_x(x,y);
-  double yt = transform_y(x,y);
-  double rx = r * (m.c ? sqrt(m.a*m.a+m.c*m.c) : fabs(m.a));
-  double ry = r * (m.b ? sqrt(m.b*m.b+m.d*m.d) : fabs(m.d));
+void Fl_Xlib_Graphics_Driver::ellipse_unscaled(double xt, double yt, double rx, double ry) {
   int llx = (int)rint(xt-rx);
   int w = (int)rint(xt+rx)-llx;
   int lly = (int)rint(yt-ry);
Index: src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx
===================================================================
--- src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx	(revision 12216)
+++ src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // Draw-to-image code for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -24,10 +24,13 @@
 #include "Fl_Xlib_Graphics_Driver.H"
 #include <FL/Fl_Image_Surface.H>
 #include "Fl_Xlib_Graphics_Driver.H"
+#include <FL/Fl_Screen_Driver.H>
 
 class Fl_Xlib_Image_Surface_Driver : public Fl_Image_Surface_Driver {
   friend class Fl_Image_Surface;
   virtual void end_current_();
+protected:
+  int pixmap_w, pixmap_h;
 public:
   Window pre_window;
   int was_high;
@@ -45,11 +48,20 @@
 }
 
 Fl_Xlib_Image_Surface_Driver::Fl_Xlib_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off) : Fl_Image_Surface_Driver(w, h, high_res, off) {
+  float d = 1;
   if (!off) {
     fl_open_display();
+    d =  fl_graphics_driver->scale();
+    if (d != 1 && high_res) {
+      w = int(w*d);
+      h = int(h*d);
+    }
+    pixmap_w = w;
+    pixmap_h = h;
     offscreen = XCreatePixmap(fl_display, RootWindow(fl_display, fl_screen), w, h, fl_visual->depth);
   }
   driver(new Fl_Xlib_Graphics_Driver());
+  if (d != 1 && high_res) ((Fl_Xlib_Graphics_Driver*)driver())->scale(d);
 }
 
 Fl_Xlib_Image_Surface_Driver::~Fl_Xlib_Image_Surface_Driver() {
@@ -74,9 +86,7 @@
 
 Fl_RGB_Image* Fl_Xlib_Image_Surface_Driver::image()
 {
-  unsigned char *data = fl_read_image(NULL, 0, 0, width, height, 0);
-  Fl_RGB_Image *image = new Fl_RGB_Image(data, width, height);
-  image->alloc_array = 1;
+  Fl_RGB_Image *image = Fl::screen_driver()->read_win_rectangle(NULL, 0, 0, width, height, 0);
   return image;
 }
 
Index: src/fl_gleam.cxx
===================================================================
--- src/fl_gleam.cxx	(revision 12216)
+++ src/fl_gleam.cxx	(working copy)
@@ -18,7 +18,7 @@
 // These box types provide a sort of Clearlooks Glossy scheme
 // for FLTK.
 //
-// Copyright 2001-2005 by Colin Jones.
+// Copyright 2001-2017 by Colin Jones.
 //
 // Modified 2012-2013 by Edmanuel Torres
 // This is a new version of the fl_gleam. The gradients are on the top
@@ -48,7 +48,7 @@
     j++;
   }
   gleam_color(fg1);
-  fl_rectf(x, y+h_top, w+1, h_flat);
+  fl_rectf(x, y+j/*h_top*/, w+1, h_flat);
   // This loop generates the gradient at the bottom of the widget
   for (float k = 1; k >= 0; k -= step_size_bottom){
     gleam_color(fl_color_average(fg1,fl_color_average(fg1, fg2, th), k));
Index: src/fl_overlay.cxx
===================================================================
--- src/fl_overlay.cxx	(revision 12216)
+++ src/fl_overlay.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // Overlay support for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -36,6 +36,12 @@
 #ifndef USE_XOR
 #include <stdlib.h>
 static uchar *bgN = 0L, *bgS = 0L, *bgE = 0L, *bgW = 0L;
+
+#include <FL/Fl_Screen_Driver.H>
+#include <FL/Fl_RGB_Image.H>
+#include <FL/Fl_Shared_Image.H>
+static Fl_Shared_Image *s_bgN = 0, *s_bgS = 0, *s_bgE = 0, *s_bgW = 0;
+
 static int bgx, bgy, bgw, bgh;
 #endif
 
@@ -60,24 +66,58 @@
 #  error unsupported platform
 # endif
 #else
-  if (bgN) { free(bgN); bgN = 0L; }
-  if (bgS) { free(bgS); bgS = 0L; }
-  if (bgE) { free(bgE); bgE = 0L; }
-  if (bgW) { free(bgW); bgW = 0L; }
+  float s = fl_graphics_driver->scale();
+  if (s == int(s)) {
+    if (bgN) { free(bgN); bgN = 0L; }
+    if (bgS) { free(bgS); bgS = 0L; }
+    if (bgE) { free(bgE); bgE = 0L; }
+    if (bgW) { free(bgW); bgW = 0L; }
+  } else {
+    if (s_bgN) { s_bgN->release(); s_bgN = 0; }
+    if (s_bgS) { s_bgS->release(); s_bgS = 0; }
+    if (s_bgE) { s_bgE->release(); s_bgE = 0; }
+    if (s_bgW) { s_bgW->release(); s_bgW = 0; }
+  }
   if (pw>0 && ph>0) {
-    bgE = fl_read_image(0L, px+pw-1, py, 1, ph);
-    bgW = fl_read_image(0L, px, py, 1, ph);
-    bgS = fl_read_image(0L, px, py+ph-1, pw, 1);
-    bgN = fl_read_image(0L, px, py, pw, 1);
+    if (s == int(s)) {
+      bgE = fl_read_image(0L, px+pw-1, py, 1, ph);
+      bgW = fl_read_image(0L, px, py, 1, ph);
+      bgS = fl_read_image(0L, px, py+ph-1, pw, 1);
+      bgN = fl_read_image(0L, px, py, pw, 1);
+    } else {
+      Fl_RGB_Image *tmp;
+      tmp = Fl::screen_driver()->read_win_rectangle(NULL, px+pw-1, py, 1, ph, 0);
+      if(tmp && tmp->w() && tmp->h()) {
+        s_bgE = Fl_Shared_Image::get(tmp);
+        s_bgE->scale(1, ph,0,1);
+      }
+      tmp = Fl::screen_driver()->read_win_rectangle(NULL, px, py, 1, ph, 0);
+      if(tmp && tmp->w() && tmp->h()) {
+        s_bgW = Fl_Shared_Image::get(tmp);
+        s_bgW->scale(1, ph,0,1);
+      }
+      tmp = Fl::screen_driver()->read_win_rectangle(NULL, px, py+ph-1, pw, 1, 0);
+      if(tmp && tmp->w() && tmp->h()) {
+        s_bgS = Fl_Shared_Image::get(tmp);
+        s_bgS->scale(pw, 1,0,1);
+      }
+      tmp = Fl::screen_driver()->read_win_rectangle(NULL, px, py, pw, 1, 0);
+      if(tmp && tmp->w() && tmp->h()) {
+        s_bgN = Fl_Shared_Image::get(tmp);
+        s_bgN->scale(pw, 1,0,1);
+      }
+    }
     bgx = px; bgy = py;
     bgw = pw; bgh = ph;
   }
   fl_color(FL_WHITE);
   fl_line_style(FL_SOLID);
-  fl_rect(px, py, pw, ph);
+  if (s == int(s)) fl_rect(px, py, pw, ph);
+  else fl_loop(px, py, px+pw-1, py, px+pw-1, py+ph-1, px, py+ph-1);
   fl_color(FL_BLACK);
   fl_line_style(FL_DOT);
-  fl_rect(px, py, pw, ph);
+  if (s == int(s)) fl_rect(px, py, pw, ph);
+  else fl_loop(px, py, px+pw-1, py, px+pw-1, py+ph-1, px, py+ph-1);
   fl_line_style(FL_SOLID);
 #endif // USE_XOR
 }
@@ -90,10 +130,18 @@
   draw_current_rect();
 # endif
 #else
-  if (bgN) fl_draw_image(bgN, bgx, bgy, bgw, 1);
-  if (bgS) fl_draw_image(bgS, bgx, bgy+bgh-1, bgw, 1);
-  if (bgW) fl_draw_image(bgW, bgx, bgy, 1, bgh);
-  if (bgE) fl_draw_image(bgE, bgx+bgw-1, bgy, 1, bgh);
+  float s = fl_graphics_driver->scale();
+  if (s == int(s)) {
+    if (bgN) fl_draw_image(bgN, bgx, bgy, bgw, 1);
+    if (bgS) fl_draw_image(bgS, bgx, bgy+bgh-1, bgw, 1);
+    if (bgW) fl_draw_image(bgW, bgx, bgy, 1, bgh);
+    if (bgE) fl_draw_image(bgE, bgx+bgw-1, bgy, 1, bgh);
+  } else {
+    if (s_bgN) s_bgN->draw(bgx, bgy);
+    if (s_bgS) s_bgS->draw(bgx, (bgy+bgh-1));
+    if (s_bgW) s_bgW->draw(bgx, bgy);
+    if (s_bgE) s_bgE->draw((bgx+bgw-1), bgy);
+  }
 #endif
 }
 
Index: src/fl_vertex.cxx
===================================================================
--- src/fl_vertex.cxx	(revision 12216)
+++ src/fl_vertex.cxx	(working copy)
@@ -3,7 +3,7 @@
 //
 // Portable drawing routines for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2011 by Bill Spitzak and others.
+// Copyright 1998-2017 by Bill Spitzak and others.
 //
 // This library is free software. Distribution and use rights are outlined in
 // the file "COPYING" which should have been included with this file.  If this
@@ -78,16 +78,6 @@
   }
 }
 
-/** see fl_scale(double, double) */
-void Fl_Graphics_Driver::scale(double x, double y) {
-  mult_matrix(x,0,0,y,0,0);
-}
-
-/** see fl_scale(double) */
-void Fl_Graphics_Driver::scale(double x) {
-  mult_matrix(x,0,0,x,0,0);
-}
-
 /** see fl_translate() */
 void Fl_Graphics_Driver::translate(double x,double y) {
   mult_matrix(1,0,0,1,x,y);
