FLTK logo

[master] c720aae - Make hybrid Wayland/X11 platform.

FLTK matrix user chat room
(using Element browser app)   FLTK gitter user chat room   GitHub FLTK Project   FLTK News RSS Feed  
  FLTK Apps      FLTK Library      Forums      Links     Login 
 All Forums  |  Back to fltk.commit  ]
 
Previous Message ]Next Message ]

[master] c720aae - Make hybrid Wayland/X11 platform. "ManoloFLTK" Aug 29, 2022  
 
commit c720aae51515907ae82ee02df80bd084f291d4b1
Author:     ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>
AuthorDate: Tue Mar 15 06:42:06 2022 +0100
Commit:     ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>
CommitDate: Mon Aug 29 12:15:32 2022 +0200

    Make hybrid Wayland/X11 platform.

 CMake/options.cmake                                |  48 +++++++-
 CMakeLists.txt                                     |  24 ++--
 FL/Fl_Cairo_Window.H                               |   2 +-
 FL/Fl_Device.H                                     |   2 +
 FL/Fl_Gl_Window.H                                  |   5 +-
 FL/Fl_Image_Surface.H                              |   4 +
 FL/mac.H                                           |  13 ++
 FL/platform.H                                      |   4 +-
 FL/platform_types.h                                | 104 +++++++---------
 FL/wayland.H                                       |  41 +++++--
 FL/win32.H                                         |  27 ++++-
 FL/x11.H                                           |  24 +++-
 README.CMake.txt                                   |  19 ++-
 README.Cairo.txt                                   |  10 +-
 README.Wayland.txt                                 | 135 ++++++++++++++-------
 cairo/Fl_Cairo.cxx                                 |  27 +++--
 configure.ac                                       |  25 +++-
 documentation/src/intro.dox                        |  38 +++++-
 documentation/src/osissues.dox                     |  35 +++---
 fl_config.cmake.in                                 |  10 ++
 fl_config.in                                       |  10 ++
 fluid/Makefile                                     |   1 +
 makeinclude.in                                     |   2 +-
 src/CMakeLists.txt                                 |  78 ++++++++----
 src/Fl.cxx                                         |  32 +++--
 src/Fl_Color_Chooser.cxx                           |   2 +-
 src/Fl_Device.cxx                                  |   4 +
 src/Fl_File_Chooser2.cxx                           |   1 +
 src/Fl_Image_Surface.cxx                           |  11 ++
 src/Fl_Input.cxx                                   |   2 +-
 src/Fl_Message.cxx                                 |   2 +-
 src/Fl_Native_File_Chooser_FLTK.cxx                |   2 +-
 src/Fl_Screen_Driver.H                             |   2 +
 src/Fl_Screen_Driver.cxx                           |   1 +
 src/Fl_System_Driver.H                             |   2 +
 src/Fl_System_Driver.cxx                           |  19 +++
 src/Fl_Window.cxx                                  |   2 +
 src/Fl_Window_Driver.H                             |   2 +
 src/Fl_Window_Driver.cxx                           |  26 ++++
 src/Fl_cocoa.mm                                    |  24 ++--
 src/Fl_win32.cxx                                   |  32 ++---
 src/Fl_x.cxx                                       |  22 +++-
 src/Makefile                                       |  44 +++++--
 .../Cairo/Fl_Display_Cairo_Graphics_Driver.H       |  37 ++++++
 .../Cairo/Fl_Display_Cairo_Graphics_Driver.cxx     |  64 ++++++++++
 src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx    |  30 +++--
 src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm       |   2 +-
 src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.cxx       |   6 +-
 src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx       |  14 ++-
 src/drivers/Darwin/Fl_Darwin_System_Driver.cxx     |   2 +
 src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx     |   4 +-
 src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx         |  14 ++-
 src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx   |   6 +-
 src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx    |  18 +--
 src/drivers/GDI/Fl_GDI_Image_Surface_Driver.H      |   2 +-
 src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx    |   8 +-
 .../Quartz/Fl_Quartz_Copy_Surface_Driver.cxx       |   2 +-
 src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx   |  14 ++-
 .../Quartz/Fl_Quartz_Graphics_Driver_image.cxx     |   2 +-
 .../Quartz/Fl_Quartz_Graphics_Driver_rect.cxx      |  15 +--
 .../Quartz/Fl_Quartz_Image_Surface_Driver.H        |   2 +-
 .../Quartz/Fl_Quartz_Image_Surface_Driver.cxx      |  46 +++----
 .../Wayland/Fl_Wayland_Copy_Surface_Driver.cxx     |   2 +-
 .../Wayland/Fl_Wayland_Gl_Window_Driver.cxx        |  20 +--
 src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx |   3 +-
 .../Wayland/Fl_Wayland_Image_Surface_Driver.cxx    |  37 +++---
 src/drivers/Wayland/Fl_Wayland_Screen_Driver.H     |   4 +
 src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx   |  44 ++++---
 src/drivers/Wayland/Fl_Wayland_System_Driver.cxx   |   3 +-
 src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx   |  86 +++++++------
 src/drivers/Wayland/fl_wayland_clipboard_dnd.cxx   |  17 ++-
 .../Wayland/fl_wayland_gl_platform_init.cxx        |   5 +-
 src/drivers/Wayland/fl_wayland_platform_init.cxx   |  88 ++++++++++++--
 src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.cxx  |  14 ++-
 src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx     |   2 +-
 src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx     |  38 +++---
 src/drivers/X11/Fl_X11_Gl_Window_Driver.cxx        |  18 +--
 src/drivers/X11/Fl_X11_Screen_Driver.cxx           |   4 +-
 src/drivers/X11/Fl_X11_Window_Driver.H             |   8 ++
 src/drivers/X11/Fl_X11_Window_Driver.cxx           |  71 +++++++++--
 src/drivers/X11/fl_X11_platform_init.cxx           |  11 +-
 src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.H     |   6 +
 src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx   |  39 +++++-
 src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H         |   2 +-
 src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx       |  12 +-
 .../Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx      |   6 +-
 src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx |  16 +--
 src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx  |  26 ++--
 src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.H    |   6 +
 src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx  |  41 ++++++-
 src/filename_isdir.cxx                             |   1 +
 src/fl_read_image.cxx                              |   2 +-
 src/fl_utf8.cxx                                    |   1 +
 93 files changed, 1311 insertions(+), 530 deletions(-)

diff --git CMake/options.cmake CMake/options.cmake
index ae77c7c..e91d1c8 100644
--- CMake/options.cmake
+++ CMake/options.cmake
@@ -197,12 +197,20 @@ if (UNIX)
   option (OPTION_USE_WAYLAND "use Wayland" OFF)
   if (OPTION_USE_WAYLAND)
     set (FLTK_USE_WAYLAND 1)
+    set (FLTK_USE_X11 1) # to build a hybrid Wayland/X11 library
+    unset (OPTION_USE_CAIRO CACHE)
+    set (OPTION_USE_CAIRO TRUE CACHE BOOL "all drawing to X11 windows uses Cairo")
     option (OPTION_USE_SYSTEM_LIBDECOR "use libdecor from the system" OFF)
     unset (OPTION_USE_XRENDER CACHE)
     unset (OPTION_USE_XINERAMA CACHE)
     unset (OPTION_USE_XFT CACHE)
     unset (OPTION_USE_XCURSOR CACHE)
     unset (OPTION_USE_XFIXES CACHE)
+      set (HAVE_XFIXES 1)
+      set (HAVE_XRENDER 1)
+      set (USE_XFT 1)
+      set (HAVE_XCURSOR 1)
+      set (HAVE_XINERAMA 1)
     unset (OPTION_USE_PANGO CACHE)
     set (OPTION_USE_PANGO TRUE CACHE BOOL "use lib Pango")
     if (OPTION_USE_SYSTEM_LIBDECOR)
@@ -211,6 +219,9 @@ if (UNIX)
         set (OPTION_USE_SYSTEM_LIBDECOR OFF)
       endif (NOT SYSTEM_LIBDECOR_FOUND)
     endif (OPTION_USE_SYSTEM_LIBDECOR)
+
+    option (OPTION_ALLOW_GTK_PLUGIN "Allow to use libdecor's GTK plugin" ON)
+
   endif (OPTION_USE_WAYLAND)
 endif (UNIX)
 
@@ -311,7 +322,7 @@ endif (OPTION_BUILD_HTML_DOCUMENTATION OR OPTION_BUILD_PDF_DOCUMENTATION)
 # Include optional Cairo support
 #######################################################################
 
-option (OPTION_CAIRO "use lib Cairo" OFF)
+option (OPTION_CAIRO "add support for Fl_Cairo_Window" OFF)
 option (OPTION_CAIROEXT
   "use FLTK code instrumentation for Cairo extended use" OFF
 )
@@ -556,8 +567,17 @@ endif (OPTION_USE_XCURSOR)
 if (X11_Xft_FOUND)
   option (OPTION_USE_XFT "use lib Xft" ON)
   option (OPTION_USE_PANGO "use lib Pango" OFF)
+  if (NOT OPTION_USE_WAYLAND)
+    option (OPTION_USE_CAIRO "all drawing to X11 windows uses Cairo" OFF)
+  endif (NOT OPTION_USE_WAYLAND)
 endif (X11_Xft_FOUND)
 
+# test option compatibility: Cairo for Xlib requires Pango
+if (OPTION_USE_CAIRO)
+    unset (OPTION_USE_PANGO CACHE)
+    set (OPTION_USE_PANGO TRUE CACHE BOOL "use lib Pango")
+endif (OPTION_USE_CAIRO)
+
 # test option compatibility: Pango requires Xft
 if (OPTION_USE_PANGO AND NOT OPTION_USE_WAYLAND)
   if (NOT X11_Xft_FOUND)
@@ -654,14 +674,30 @@ if ((X11_Xft_FOUND OR OPTION_USE_WAYLAND) AND OPTION_USE_PANGO)
     endif (HAVE_LIB_PANGO AND HAVE_LIB_PANGOXFT AND HAVE_LIB_GOBJECT)
   endif (PANGOXFT_FOUND AND PANGOCAIRO_FOUND AND CAIRO_FOUND)
 
+  if (USE_PANGO AND (OPTION_USE_CAIRO OR OPTION_USE_WAYLAND))
+    set (FLTK_USE_CAIRO 1)
+    # fl_debug_var (FLTK_USE_CAIRO)
+  endif (USE_PANGO AND (OPTION_USE_CAIRO OR OPTION_USE_WAYLAND))
+
 endif ((X11_Xft_FOUND OR OPTION_USE_WAYLAND) AND OPTION_USE_PANGO)
 
 if (OPTION_USE_WAYLAND AND NOT OPTION_USE_SYSTEM_LIBDECOR)
-  pkg_check_modules(GTK gtk+-3.0)
-  # set (GTK_FOUND 0) # use this to get cairo titlebars rather than GTK
-  if (GTK_FOUND)
-    include_directories (${GTK_INCLUDE_DIRS})
-  endif (GTK_FOUND)
+
+  # Note: Disable OPTION_ALLOW_GTK_PLUGIN to get cairo titlebars rather than GTK
+  # FIXME: This needs to be redesigned! Forcing GTK_FOUND to 0 (NO) is a bad
+  # FIXME: idea because there could be unwanted side effects. AlbrechtS
+  if (OPTION_ALLOW_GTK_PLUGIN)
+    pkg_check_modules(GTK gtk+-3.0)
+    if (GTK_FOUND)
+      include_directories (${GTK_INCLUDE_DIRS})
+    endif (GTK_FOUND)
+  else ()
+    if (GTK_FOUND)
+      message (STATUS "*** FIXME: Disable GTK plugin by forcing GTK_FOUND to 0 ***")
+      set (GTK_FOUND 0)
+    endif (GTK_FOUND)
+  endif (OPTION_ALLOW_GTK_PLUGIN)
+
 endif (OPTION_USE_WAYLAND AND NOT OPTION_USE_SYSTEM_LIBDECOR)
 
 if (OPTION_USE_XFT)
diff --git CMakeLists.txt CMakeLists.txt
index c871386..9fb8cac 100644
--- CMakeLists.txt
+++ CMakeLists.txt
@@ -241,30 +241,36 @@ endif ()
 if (UNIX)
 
   if (OPTION_USE_WAYLAND)
-    message (STATUS "Use Wayland:     Yes")
+    message (STATUS "Use Wayland:             Yes (when available at run-time)")
   else ()
-    message (STATUS "Use Wayland:     No")
+    message (STATUS "Use Wayland:             No (therefore, X11 is used)")
+  endif ()
+
+  if (FLTK_USE_CAIRO)
+    message (STATUS "All drawing uses Cairo:  Yes")
+  else ()
+    message (STATUS "All drawing uses Cairo:  No")
   endif ()
 
   if (USE_PANGO)
-    message (STATUS "Use Pango:       Yes")
+    message (STATUS "Use Pango:               Yes")
   else (USE_PANGO)
-    message (STATUS "Use Pango:       No")
+    message (STATUS "Use Pango:               No")
     if (USE_XFT)
-      message (STATUS "Use Xft:         Yes")
+      message (STATUS "Use Xft:                 Yes")
     else ()
-      message (STATUS "Use Xft:         No")
+      message (STATUS "Use Xft:                 No")
     endif (USE_XFT)
   endif (USE_PANGO)
 
 endif (UNIX)
 
 if (FLTK_HAVE_CAIROEXT)
-  message (STATUS "Cairo support:   Yes (extended)")
+  message (STATUS "Fl_Cairo_Window support: Yes (extended)")
 elseif (FLTK_HAVE_CAIRO)
-  message (STATUS "Cairo support:   Yes (standard)")
+  message (STATUS "Fl_Cairo_Window support: Yes (standard)")
 else ()
-  message (STATUS "Cairo support:   No")
+  message (STATUS "Fl_Cairo_Window support: No")
 endif ()
 
 message ("")
diff --git FL/Fl_Cairo_Window.H FL/Fl_Cairo_Window.H
index 86f25c9..1111097 100644
--- FL/Fl_Cairo_Window.H
+++ FL/Fl_Cairo_Window.H
@@ -74,7 +74,7 @@
 
    \see examples/cairo-draw-x.cxx
    \see test/cairo_test.cxx
-
+ 
    \note Class Fl_Cairo_Window requires the FLTK library to have been built with
    CMake option OPTION_CAIRO or configure --enable-cairo.
 
diff --git FL/Fl_Device.H FL/Fl_Device.H
index 93b3836..757aa65 100644
--- FL/Fl_Device.H
+++ FL/Fl_Device.H
@@ -28,6 +28,7 @@
 class Fl_Graphics_Driver;
 class Fl_RGB_Image;
 class Fl_Widget;
+class Fl_Image_Surface;
 
 /**
  A drawing surface that's susceptible to receive graphical output.
@@ -91,6 +92,7 @@ public:
   }
   /** \brief The destructor. */
   virtual ~Fl_Surface_Device();
+  virtual Fl_Image_Surface *as_image_surface();
   static void push_current(Fl_Surface_Device *new_current);
   static Fl_Surface_Device *pop_current();
 };
diff --git FL/Fl_Gl_Window.H FL/Fl_Gl_Window.H
index ec9179b..9143d0a 100644
--- FL/Fl_Gl_Window.H
+++ FL/Fl_Gl_Window.H
@@ -187,8 +187,9 @@ public:
    and may be followed by adequate attribute values.
    */
   int mode(const int *a) {return mode(0, a);}
-  /** Returns a pointer to the GLContext that this window is using.
-   \see void context(GLContext c, int destroy_flag) */
+  /** Returns a pointer to the window's OpenGL rendering context.
+   \see void context(GLContext c, int destroy_flag)
+  */
   GLContext context() const {return context_;}
   void context(GLContext, int destroy_flag = 0);
   void make_current();
diff --git FL/Fl_Image_Surface.H FL/Fl_Image_Surface.H
index a22d1d9..b09d7d4 100644
--- FL/Fl_Image_Surface.H
+++ FL/Fl_Image_Surface.H
@@ -82,6 +82,7 @@ public:
   int printable_rect(int *w, int *h);
   Fl_Offscreen offscreen();
   void rescale();
+  Fl_Image_Surface *as_image_surface();
 };
 
 
@@ -98,6 +99,8 @@ public:
  */
 class Fl_Image_Surface_Driver : public Fl_Widget_Surface {
   friend class Fl_Image_Surface;
+private:
+  Fl_Image_Surface *image_surface_;
 protected:
   int width;
   int height;
@@ -110,6 +113,7 @@ protected:
   virtual void untranslate() = 0;
   int printable_rect(int *w, int *h);
   virtual Fl_RGB_Image *image() = 0;
+  virtual Fl_Image_Surface *as_image_surface();
   /** Each platform implements this function its own way.
    It returns an object implementing all virtual functions
    of class Fl_Image_Surface_Driver for the plaform.
diff --git FL/mac.H FL/mac.H
index 0b5d32a..c1748ab 100644
--- FL/mac.H
+++ FL/mac.H
@@ -24,6 +24,13 @@
 #endif // !FL_PLATFORM_H
 
 #ifdef __OBJC__
+  @class NSOpenGLContext;
+#elif defined(__cplusplus)
+  class NSOpenGLContext;
+#endif /* __OBJC__ */
+extern NSOpenGLContext *fl_mac_glcontext(GLContext rc);
+
+#ifdef __OBJC__
 @class FLWindow; // a subclass of the NSWindow Cocoa class
 typedef FLWindow *Window;
 #else
@@ -125,6 +132,12 @@ extern CGContextRef fl_gc;
  */
 void fl_mac_set_about(Fl_Callback *cb, void *user_data, int shortcut = 0);
 
+/** Returns the macOS-specific graphics context for the current window */
+extern CGContextRef fl_mac_gc();
+/** Returns the macOS-specific window reference corresponding to the given Fl_Window object */
+extern FLWindow *fl_mac_xid(const Fl_Window *win);
+/** Returns the Fl_Window corresponding to the given macOS-specific window reference */
+extern Fl_Window *fl_mac_find(FLWindow *);
 
 /** The version number of the running Mac OS X (e.g., 100604 for 10.6.4, 101300 for 10.13).
  FLTK initializes this global variable before main() begins running. If
diff --git FL/platform.H FL/platform.H
index 1ff9cd4..834a323 100644
--- FL/platform.H
+++ FL/platform.H
@@ -51,7 +51,7 @@ class Fl_Window;
 
 class FL_EXPORT Fl_X {
 public:
-  Window xid;
+  fl_uintptr_t xid;
   Fl_Window* w;
   Fl_Region region;
   Fl_X *next;
@@ -64,7 +64,7 @@ public:
 #  endif
 };
 
-inline Window fl_xid(const Fl_Window* w) { Fl_X *xTemp = Fl_X::i(w); return xTemp ? xTemp->xid : 0; }
+inline Window fl_xid(const Fl_Window* w) { Fl_X *xTemp = Fl_X::i(w); return xTemp ? (Window)xTemp->xid : 0; }
 #else
 extern FL_EXPORT Window fl_xid_(const Fl_Window* w);
 #  define fl_xid(w) fl_xid_(w)
diff --git FL/platform_types.h FL/platform_types.h
index f831b8b..b55544d 100644
--- FL/platform_types.h
+++ FL/platform_types.h
@@ -32,15 +32,40 @@ typedef opaque fl_intptr_t;
  A variable of type fl_uintptr_t can also store an unsigned long int value. */
 typedef opaque fl_uintptr_t;
 
-typedef opaque Fl_Offscreen; /**< an offscreen drawing buffer */
-typedef opaque Fl_Region; /**< a region made of several rectangles */
+/**
+ Platform-specific value representing an offscreen drawing buffer.
+  \note This value can be safely cast to these types on each platform:
+  \li X11: Pixmap
+  \li Wayland: struct fl_wld_buffer *
+  \li Windows: HBITMAP
+  \li macOS:  CGContextRef
+ */
+typedef opaque Fl_Offscreen;
+
+/**
+ Pointer to a platform-specific structure representing a collection of rectangles.
+  \note This pointer can be safely cast to these types on each platform:
+  \li X11: Region as defined by X11
+  \li Wayland: struct flCairoRegion *
+  \li Windows: HRGN
+  \li macOS:  struct flCocoaRegion *
+ */
+typedef struct opaque *Fl_Region;
 typedef opaque FL_SOCKET; /**< socket or file descriptor */
-typedef opaque GLContext; /**< an OpenGL graphics context, into which all OpenGL calls are rendered */
+/**
+ Pointer to a platform-specific structure representing the window's OpenGL rendering context.
+  \note This pointer can be safely cast to these types on each platform:
+  \li X11: GLXContext
+  \li Wayland: EGLContext
+  \li Windows: HGLRC
+  \li macOS: NSOpenGLContext *
+ */
+typedef struct opaque *GLContext;
 
 #  define FL_COMMAND  opaque   /**< An alias for FL_CTRL on Windows and X11, or FL_META on MacOS X */
 #  define FL_CONTROL  opaque   /**< An alias for FL_META on Windows and X11, or FL_CTRL on MacOS X */
 
-#else
+#else /* FL_DOXYGEN */
 
 #ifndef FL_PLATFORM_TYPES_H
 #define FL_PLATFORM_TYPES_H
@@ -49,8 +74,7 @@ typedef opaque GLContext; /**< an OpenGL graphics context, into which all OpenGL
 
 /* Platform-dependent types are defined here.
   These types must be defined by any platform:
-  Fl_Offscreen, Fl_Region, FL_SOCKET, GLContext, struct dirent, struct stat,
-  fl_intptr_t, fl_uintptr_t
+  FL_SOCKET, struct dirent, fl_intptr_t, fl_uintptr_t
 
   NOTE: *FIXME* AlbrechtS 13 Apr 2016 (concerning FL_SOCKET)
   ----------------------------------------------------------
@@ -78,65 +102,29 @@ typedef unsigned long fl_uintptr_t;
 
 #endif /* _WIN64 */
 
+typedef void *GLContext;
+typedef void *Fl_Region;
+typedef fl_uintptr_t  Fl_Offscreen;
+
+/* Allows all hybrid combinations except WIN32 + X11 with MSVC */
+#if defined(_WIN32) && !defined(__MINGW32__)
+  struct dirent {char d_name[1];};
+#else
+#  include <dirent.h>
+#endif
 
-#ifdef __APPLE__
-typedef struct CGContext* Fl_Offscreen;
-typedef struct flCocoaRegion* Fl_Region;
-typedef int FL_SOCKET;
-#ifdef __OBJC__
-  @class NSOpenGLContext;
-  typedef NSOpenGLContext* GLContext;
-#elif defined(__cplusplus)
-  typedef class NSOpenGLContext* GLContext;
-#endif /* __OBJC__ */
-
-#include <sys/types.h>
-#include <dirent.h>
-#  define FL_COMMAND    FL_META
-#  define FL_CONTROL    FL_CTRL
-
-#elif defined(_WIN32)
-typedef struct HBITMAP__ *HBITMAP;
-typedef HBITMAP Fl_Offscreen;
-typedef struct HRGN__ *Fl_Region;
 # if defined(_WIN64) && defined(_MSC_VER)
 typedef  unsigned __int64 FL_SOCKET;    /* *FIXME* - FL_SOCKET (see above) */
 # else
 typedef  int FL_SOCKET;
 # endif
-typedef struct HGLRC__ *GLContext;
-#ifdef __MINGW32__
-#  include <dirent.h>
-#else
-   struct dirent {char d_name[1];};
-#endif
-
-#elif defined(FLTK_USE_WAYLAND)
-typedef struct fl_wld_buffer *Fl_Offscreen; /**< an offscreen drawing buffer */
-typedef struct flCairoRegion* Fl_Region;
-typedef int FL_SOCKET; /**< socket or file descriptor */
-typedef void *EGLContext;
-typedef EGLContext GLContext;
-#include <sys/types.h>
-#include <dirent.h>
-
-#elif defined(FLTK_USE_X11)
 
-typedef unsigned long Fl_Offscreen;
-typedef struct _XRegion *Fl_Region;
-typedef int FL_SOCKET;
-typedef struct __GLXcontextRec *GLContext;
-#include <sys/types.h>
-#include <dirent.h>
-
-#endif /* __APPLE__ */
-
-
-#ifndef __APPLE__
-#  define FL_COMMAND    FL_CTRL   /**< An alias for FL_CTRL on Windows and X11, or FL_META on MacOS X */
-#  define FL_CONTROL    FL_META   /**< An alias for FL_META on Windows and X11, or FL_CTRL on MacOS X */
-#endif
+#include <FL/Fl_Export.H>
+extern FL_EXPORT int fl_command_modifier();
+extern FL_EXPORT int fl_control_modifier();
+#  define FL_COMMAND    fl_command_modifier()
+#  define FL_CONTROL    fl_control_modifier()
 
 #endif /* FL_PLATFORM_TYPES_H */
 
-#endif // FL_DOXYGEN
+#endif /* FL_DOXYGEN */
diff --git FL/wayland.H FL/wayland.H
index bd5f8a8..66b6331 100644
--- FL/wayland.H
+++ FL/wayland.H
@@ -1,7 +1,7 @@
 //
-// Wayland platform header file for the Fast Light Tool Kit (FLTK).
+// Wayland/X11 hybrid platform header file for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 1998-2021 by Bill Spitzak and others.
+// Copyright 1998-2022 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
@@ -18,16 +18,35 @@
 #  error "Never use <FL/wayland.H> directly; include <FL/platform.H> instead."
 #endif // !FL_PLATFORM_H
 
-typedef struct wld_window *Window;
+/** \file
+ Definitions of functions specific to the Wayland platform.
+*/
 
-struct flCairoRegion {
-  int count;
-  struct _cairo_rectangle *rects;
-}; // a region is the union of a series of rectangles
+// ***********  for Wayland component ***********
 
-#include <stdint.h>
 typedef struct _cairo cairo_t;
 
-FL_EXPORT struct wl_display *fl_wl_display();
-FL_EXPORT struct wl_surface *fl_wl_surface(Window xid);
-FL_EXPORT cairo_t *fl_wl_cairo();
+/** Returns the Wayland display in use */
+extern FL_EXPORT struct wl_display *fl_wl_display();
+/** Returns the wl_surface associated to a shown window */
+extern FL_EXPORT struct wl_surface *fl_wl_surface(struct wld_window *xid);
+/** Returns a platform-specific reference associated to a shown window */
+extern FL_EXPORT struct wld_window *fl_wl_xid(const Fl_Window *win);
+/** Returns the Fl_Window corresponding to a given the platform-specific window reference */
+extern FL_EXPORT Fl_Window *fl_wl_find(struct wld_window *);
+/** Returns the cairo context associated to the current window*/
+extern FL_EXPORT cairo_t *fl_wl_cairo();
+typedef void *EGLContext;
+/** Returns the EGLContext corresponding to the given GLContext */
+extern FL_EXPORT EGLContext fl_wl_glcontext(GLContext rc);
+/** Prevent the FLTK library from using its wayland backend.
+ Call this early in your main(), before fl_open_display() runs. */
+extern FL_EXPORT void fl_disable_wayland();
+
+
+#ifndef FL_DOXYGEN
+
+//  *********** for X11 component ***********
+#  include "x11.H"
+
+#endif // FL_DOXYGEN
diff --git FL/win32.H FL/win32.H
index 8ff136c..d7bfd5c 100644
--- FL/win32.H
+++ FL/win32.H
@@ -18,7 +18,25 @@
 // include this file if _WIN32 is defined.  This is to encourage
 // portability of even the system-specific code...
 
-#ifndef FL_DOXYGEN
+#ifdef FL_DOXYGEN
+
+/** \file
+ Definitions of functions specific to the Windows platform.
+*/
+
+/** Returns the Windows-specific window reference corresponding to the given Fl_Window object */
+extern HWND fl_win32_xid(const Fl_Window *win);
+/** Returns the Fl_Window corresponding to the given Windows-specific window reference */
+extern Fl_Window *fl_win32_find(HWND);
+/** Returns the Windows-specific GL rendering context corresponding to the given GLContext  */
+extern HGLRC fl_win32_glcontext(GLContext rc);
+/** Returns the Windows-specific graphics context for the current window  */
+extern HDC fl_win32_gc();
+/** Returns the Windows-specific display in use  */
+extern HINSTANCE fl_win32_display();
+
+#else
+
 #ifndef FL_PLATFORM_H
 #  error "Never use <FL/win32.H> directly; include <FL/platform.H> instead."
 #endif // !FL_PLATFORM_H
@@ -26,6 +44,11 @@
 #include <windows.h>
 typedef HWND Window;
 
+typedef struct HGLRC__ *HGLRC;
+extern FL_EXPORT HGLRC fl_win32_glcontext(GLContext rc);
+extern FL_EXPORT HWND fl_win32_xid(const Fl_Window *win);
+extern FL_EXPORT Fl_Window *fl_win32_find(HWND);
+
 // this part is included only when compiling the FLTK library or if requested explicitly
 #if defined(FL_LIBRARY) || defined(FL_INTERNALS)
 
@@ -60,7 +83,9 @@ FL_EXPORT HBRUSH fl_brush(); // allocates a brush if necessary
 FL_EXPORT HBRUSH fl_brush_action(int); // now does the real work
 
 extern FL_EXPORT HINSTANCE fl_display;
+extern FL_EXPORT HINSTANCE fl_win32_display();
 extern FL_EXPORT HDC fl_gc;
+extern FL_EXPORT HDC fl_win32_gc();
 extern FL_EXPORT MSG fl_msg;
 extern FL_EXPORT HDC fl_GetDC(Window);
 extern FL_EXPORT HDC fl_makeDC(HBITMAP);
diff --git FL/x11.H FL/x11.H
index 1168701..56ca43b 100644
--- FL/x11.H
+++ FL/x11.H
@@ -18,7 +18,22 @@
 // include this file if FLTK_USE_X11 is defined.  This is to encourage
 // portability of even the system-specific code...
 
-#ifndef FL_DOXYGEN
+#ifdef FL_DOXYGEN
+
+/** \file
+ Definitions of functions specific to the X11 platform.
+*/
+
+/** Returns the X11 Display in use */
+extern Display *fl_x11_display();
+/** Returns the Window reference for the given Fl_Window, or zero if not \c shown().  */
+extern Window fl_x11_xid(const Fl_Window *win);
+/** Returns the Fl_Window corresponding to the given Window reference.  */
+extern Fl_Window *fl_x11_find(Window xid);
+/** Returns the X11-specific currently active graphics context.  */
+extern GC fl_x11_gc();
+
+#else // ! FL_DOXYGEN
 
 #ifndef FL_PLATFORM_H
 #  error "Never use <FL/x11.H> directly; include <FL/platform.H> instead."
@@ -36,14 +51,21 @@
 #endif
 #include <X11/Xatom.h>
 
+typedef struct __GLXcontextRec *GLXContext;
+extern GLXContext fl_x11_glcontext(GLContext rc);
+
 // constant info about the X server connection:
 extern FL_EXPORT Display *fl_display;
+extern FL_EXPORT Display *fl_x11_display();
+extern FL_EXPORT Window fl_x11_xid(const Fl_Window *win);
+extern FL_EXPORT Fl_Window *fl_x11_find(Window);
 extern FL_EXPORT int fl_screen;
 extern FL_EXPORT XVisualInfo *fl_visual;
 extern FL_EXPORT Colormap fl_colormap;
 
 // drawing functions:
 extern FL_EXPORT GC fl_gc;
+extern FL_EXPORT GC fl_x11_gc();
 FL_EXPORT ulong fl_xpixel(Fl_Color i);
 FL_EXPORT ulong fl_xpixel(uchar r, uchar g, uchar b);
 
diff --git README.CMake.txt README.CMake.txt
index b3d089b..d97b491 100644
--- README.CMake.txt
+++ README.CMake.txt
@@ -126,7 +126,8 @@ FLTK_BUILD_EXAMPLES - default OFF
    Builds the example programs in the 'examples' directory.
 
 OPTION_CAIRO - default OFF
-   Enables libcairo support - see README.Cairo.txt.
+   Enables support of class Fl_Cairo_Window (all platforms, requires the
+   Cairo library) - see README.Cairo.txt.
 
 OPTION_CAIROEXT - default OFF
    Enables extended libcairo support - see README.Cairo.txt.
@@ -148,7 +149,7 @@ OPTION_USE_SYSTEM_ZLIB    - default ON
    any of these options to OFF, then the built in library will be used.
 
 OPTION_USE_SVG - default ON
-   FLTK has a built in SVG library and can create (write) SVG image files.
+   FLTK has a built-in SVG library and can create (write) SVG image files.
    Turning this option off disables SVG (read and write) support.
 
 OPTION_USE_XINERAMA - default ON
@@ -158,14 +159,21 @@ OPTION_USE_XRENDER  - default ON
    These are X11 extended libraries. These libs are used if found on the
    build system unless the respective option is turned off.
 
+OPTION_USE_CAIRO - default OFF
+   Makes all drawing operations use the Cairo library (rather than Xlib)
+   producing antialiased graphics (X11 platform, implies OPTION_USE_PANGO).
+
 OPTION_USE_PANGO - default OFF
    Enables use of the Pango library for drawing text. Pango supports all
    unicode-defined scripts with limited support of right-to-left scripts.
    This option makes sense only under X11, and also requires Xft.
 
 OPTION_USE_WAYLAND - default OFF
-   Enables use of the Wayland system for all window operations.
-   This option requires a Wayland-equipped system, i.e., Linux or FreeBSD.
+   Enables the use of Wayland for all window operations, of Cairo for all
+   graphics and of Pango for text drawing (Linux only). Resulting FLTK
+   apps use Wayland when a Wayland compositor is available at run-time,
+   and use X11 for their window operations otherwise, but keep using
+   Cairo and Pango - see README.Wayland.txt.
 
 OPTION_ABI_VERSION - default EMPTY
    Use a numeric value corresponding to the FLTK ABI version you want to
@@ -182,6 +190,9 @@ OPTION_PRINT_SUPPORT - default ON
    is somewhat smaller. This option makes sense only on the Unix/Linux
    platform or when OPTION_APPLE_X11 is ON.
 
+OPTION_USE_GDIPLUS - default ON
+   Makes FLTK use GDI+ to draw oblique lines and curves resulting in
+   antialiased graphics (Windows platform only).
 
 Documentation options: these options are only available if `doxygen' is
    installed and found by CMake. PDF related options require also `latex'.
diff --git README.Cairo.txt README.Cairo.txt
index b2bfba0..6d70e92 100644
--- README.Cairo.txt
+++ README.Cairo.txt
@@ -61,11 +61,19 @@ variable OPTION_CAIRO:BOOL=ON is set.
     transparently a Cairo context to your custom Fl_Window derived class.
     This function is intended to be used in your overloaded draw() method.
 
-(3) Adding an optional Cairo autolink context mode support which permits
+(3) FLTK instrumentation for cairo extended use :
+    Adding an optional Cairo autolink context mode support which permits
     complete and automatic synchronization of OS dependent graphical context
     and Cairo contexts, thus furthering a valid Cairo context anytime,
     in any current window.
 
+    Usage :
+    - Call Fl::cairo_autolink_context(true); before windows are shown.
+    - In an overridden widget draw method, do
+        cairo_t *cc = Fl::cairo_cc();
+    and obtain the cairo context value adequate to draw with cairo to
+    the current window.
+
     This feature should be only necessary in the following cases:
     - Intensive and almost systematic use of Cairo in an FLTK application
     - Creation of a new Cairo based scheme for FLTK
diff --git README.Wayland.txt README.Wayland.txt
index 840f372..01b7ba1 100644
--- README.Wayland.txt
+++ README.Wayland.txt
@@ -9,12 +9,17 @@ CONTENTS
 
  2   WAYLAND SUPPORT FOR FLTK
    2.1    Configuration
-   2.2    Known limitations
+   2.2    Known Limitations
 
- 3   PLATFORM SPECIFIC NOTES
-   3.1    Debian and Derivatives (like Ubuntu)
-   3.2    Fedora
-   3.3    FreeBSD
+ 3   PREPARING PLATFORM-SPECIFIC CODE FOR THE WAYLAND PLATFORM
+   3.1    Handling X11-specific source code
+   3.2    Handling X11- and Wayland-specific source code in the same app
+   3.3    Forcing an app to always use the X11 mechanism
+
+ 4   PLATFORM SPECIFIC NOTES
+   4.1    Debian and Derivatives (like Ubuntu)
+   4.2    Fedora
+   4.3    FreeBSD
 
 
 1 INTRODUCTION
@@ -33,36 +38,49 @@ CJK text-input methods, as well as dead and compose keys are supported.
 2 WAYLAND SUPPORT FOR FLTK
 ==========================
 
-It is possible to have your FLTK application do all its windowing and drawing
-through the Wayland protocol on Linux or FreeBSD systems.
-All graphics is done via Cairo or EGL. All text-drawing is done via Pango.
+On Linux and FreeBSD systems, and provided a Wayland compositor is available at run-time,
+it is possible to have your FLTK application do all its windowing through the
+Wayland protocol, all its graphics with Cairo or EGL, and all text-drawing with
+Pango. If no Wayland compositor is available at run-time, FLTK falls back to
+using X11 or OpenGL for its windowing. Cairo and Pango remain used for graphics
+and text, respectively.
+
+Environment variable FLTK_BACKEND can be used to control whether Wayland or
+X11 is used at run time as follows:
+- if FLTK_BACKEND is not defined, Wayland is used when possible, otherwise
+  X11 is used;
+- if FLTK_BACKEND equals "wayland", the library stops with error if no
+  Wayland compositor is available;
+- if FLTK_BACKEND equals "x11", the library uses X11 even if a Wayland
+  compositor is available;
+- if FLTK_BACKEND has another value, the library stops with error.
 
  2.1 Configuration
----------------
+------------------
 
 * Configure-based build can be performed as follows:
 Once after "git clone", create the configure file :
-   autoconf -f
+  autoconf -f
 
 Prepare build with :
-   ./configure --enable-wayland [--enable-shared]
+  ./configure --enable-wayland [--enable-shared]
 
 Build with :
-   make
+  make
 
 * CMake-based build can be performed as follows:
-cmake -S <path-to-source> -B <path-to-build> -DCMAKE_BUILD_TYPE=Release -DOPTION_USE_WAYLAND=1
+  cmake -S <path-to-source> -B <path-to-build> -DCMAKE_BUILD_TYPE=Release -DOPTION_USE_WAYLAND=1
 
-cd <path-to-build>; make
+  cd <path-to-build>; make
 
-The FLTK wayland platform uses a library called libdecor which handles window decorations
+The FLTK Wayland platform uses a library called libdecor which handles window decorations
 (i.e., titlebars, shade). Libdecor is bundled in the FLTK source code and FLTK uses by default
 this form of libdecor. Optionally, OPTION_USE_SYSTEM_LIBDECOR can be turned on to have FLTK
 use the system's version of libdecor which is available on recent Linux distributions (e.g.,
-Debian bookworm or more recent in packages libdecor-0-0 and libdecor-0-plugin-1-cairo).
+Debian Bookworm or more recent in packages libdecor-0-0 and libdecor-0-plugin-1-cairo).
 
- 2.2 Known limitations
--------------------------------
+ 2.2 Known Limitations
+----------------------
 
 * A deliberate design trait of Wayland makes application windows ignorant of their exact
 placement on screen. It's possible, though, to position a popup window relatively to
@@ -86,41 +104,72 @@ tested in that situation.
 * Text input methods have been tested without any understanding of the writing systems,
 so feedback on this subject would be helpful.
 
-* While platform-independent source code prepared for FLTK 1.3 is expected to be compatible
-with FLTK 1.4 and the Wayland platform, X11-specific code will not compile.  In particular,
-the common FLTK 1.3 construct :
+
+3 PREPARING PLATFORM-SPECIFIC CODE FOR THE WAYLAND PLATFORM
+===========================================================
+
+While platform-independent source code prepared for FLTK 1.3 is expected
+to be compatible with no change with FLTK 1.4 and the Wayland platform,
+platform-specific code may require some attention.
+
+3.1 Handling X11-specific source code
+-------------------------------------
+
+If an FLTK 1.4 application contains X11-specific code, execution of this code
+in the context of an active Wayland session can produce malfunctions or program crashes.
+To ensure that X11-specific code gets called only when an X11 connection is active,
+check that function fl_x11_display() returns non-NULL before using any X11-specific
+function or variable.
+
+3.2 Handling X11- and Wayland-specific source code in the same app
+------------------------------------------------------------------
+
+The recommended way to prepare and use platform-specific code that would contain
+both X11-specific and Wayland-specific parts is as follows :
+
+a) Organize platform-specific code as follows :
+
+  #include <FL/platform.H>
+
   #ifdef __APPLE__
      *** macOS-specific code ***
   #elif defined(_WIN32)
      *** Windows-specific code ***
   #else
-     *** X11-specific code ***
-  #endif
-will choke at compile time because it exposes X11-specific code to the non-X11, Wayland
-environment. This should be written instead :
-  #include <FL/fl_config.h>
+      *** X11-specific code ***
 
-  #ifdef __APPLE__
-     *** macOS-specific code ***
-  #elif defined(_WIN32)
-     *** Windows-specific code ***
-  #elif defined(FLTK_USE_X11)
-     *** X11-specific code ***
+      *** Wayland-specific code ***
   #endif
-Moreover, the new FLTK_USE_WAYLAND preprocessor variable is available to bracket
-Wayland-specific source code.
 
+b) Make sure to use distinct names for global variables and functions
+in the X11- and the Wayland-specific sections.
 
-3 PLATFORM SPECIFIC NOTES
+c) Check that function fl_x11_display() returns non-NULL before using any X11-specific
+function or variable, and that fl_wl_display() returns non-NULL before using any
+Wayland-specific function or variable. Make sure that fl_open_display() was called
+directly or indirectly before using any such symbol.
+
+3.3 Forcing an app to always use the X11 mechanism
+--------------------------------------------------
+
+Alternatively, it's possible to force an FLTK app to use X11 in all
+situations by calling function fl_disable_wayland() early in main(), before
+fl_open_display() runs. FLTK source code and also platform-specific
+code conceived for FLTK 1.3 should run under 1.4 with that single change only.
+
+
+4 PLATFORM SPECIFIC NOTES
 =========================
 
 The following are notes about building FLTK for the Wayland platform
-on the various supported Linux distributions.
+on the various supported Linux distributions/OS.
+
+4.1 Debian and Derivatives (like Ubuntu)
+----------------------------------------
 
-    3.1 Debian and Derivatives (like Ubuntu)
-    ----------------------------------------
 Under Debian, the Wayland platform requires version 11 (a.k.a. Bullseye) or more recent.
-Under Ubuntu, the Wayland platform is known to work with version 20.04 (focal fossa) or more recent.
+Under Ubuntu, the Wayland platform is known to work with version 20.04 (focal fossa) or
+more recent.
 
 These packages are necessary to build the FLTK library, in addition to those present
 in a basic Debian/Ubuntu distribution :
@@ -148,8 +197,8 @@ These packages allow to run FLTK apps under the KDE/Plasma-Wayland desktop:
 - plasma-workspace-wayland
 
 
-  3.2 Fedora
-  ----------
+4.2 Fedora
+----------
 
 The Wayland platform is known to work with Fedora version 35.
 
@@ -172,8 +221,8 @@ in a Fedora 35 Workstation distribution :
 Package installation command: sudo yum install <package-name ...>
 
 
-  3.3 FreeBSD
-  -----------
+4.3 FreeBSD
+-----------
 
 The Wayland platform is known to work with FreeBSD version 13.1 and the sway compositor.
 
diff --git cairo/Fl_Cairo.cxx cairo/Fl_Cairo.cxx
index dbbf2e5..4833bb3 100644
--- cairo/Fl_Cairo.cxx
+++ cairo/Fl_Cairo.cxx
@@ -21,17 +21,18 @@
 #include <FL/Fl_Window.H>
 
 // Cairo is currently supported for the following platforms:
-// Win32, Apple Quartz, X11
+// Win32, Apple Quartz, X11, Wayland
 
-#if defined(FLTK_USE_X11)         // X11
-#  include <cairo-xlib.h>
-#elif defined(_WIN32)             // Windows
+#if defined(_WIN32)             // Windows
 #  include <cairo-win32.h>
 #elif defined(__APPLE__)   // macOS
 #  include <cairo-quartz.h>
-#elif defined(FLTK_USE_WAYLAND)
+#elif defined(FLTK_USE_WAYLAND)  // Wayland or hybrid
 #  include "../src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H"
 #  include "../src/drivers/Wayland/Fl_Wayland_Window_Driver.H"
+#  include <cairo-xlib.h>
+#elif defined(FLTK_USE_X11)         // X11
+#  include <cairo-xlib.h>
 #else
 #  error Cairo is not supported on this platform.
 #endif
@@ -73,11 +74,14 @@ cairo_t * Fl::cairo_make_current(Fl_Window* wi) {
     if (!wi) return NULL; // Precondition
   cairo_t * cairo_ctxt;
 #if defined(FLTK_USE_WAYLAND)
-  Window xid = fl_xid(wi);
-  if (!xid->buffer) return NULL; // this may happen with GL windows
-  cairo_ctxt = xid->buffer->cairo_;
-  cairo_state_.cc(cairo_ctxt, false);
-#else // !FLTK_USE_WAYLAND
+  if (fl_wl_display()) { // true means using wayland backend
+    struct wld_window *xid = fl_wl_xid(wi);
+    if (!xid->buffer) return NULL; // this may happen with GL windows
+    cairo_ctxt = xid->buffer->cairo_;
+    cairo_state_.cc(cairo_ctxt, false);
+    return cairo_ctxt;
+  }
+#endif
     if (fl_gc==0) { // means remove current cc
         Fl::cairo_cc(0); // destroy any previous cc
         cairo_state_.window(0);
@@ -102,11 +106,9 @@ cairo_t * Fl::cairo_make_current(Fl_Window* wi) {
 #ifndef __APPLE__
   cairo_scale(cairo_ctxt, scale, scale);
 #endif
-#endif // FLTK_USE_WAYLAND
   return cairo_ctxt;
 }
 
-#if !defined(FLTK_USE_WAYLAND)
 /*
     Creates transparently a cairo_surface_t object.
     gc is an HDC context in Windows, a CGContext* in Quartz, and
@@ -194,7 +196,6 @@ cairo_t * Fl::cairo_make_current(void *gc, int W, int H) {
     return c;
 }
 
-#endif // !FLTK_USE_WAYLAND
 
 #else
 // just don't leave the libfltk_cairo lib empty to avoid warnings
diff --git configure.ac configure.ac
index 9826102..3a2240c 100644
--- configure.ac
+++ configure.ac
@@ -85,7 +85,7 @@ AC_SUBST(OPTIM)
 
 
 dnl Other options
-AC_ARG_ENABLE([cairo], AS_HELP_STRING([--enable-cairo], [use Cairo library]))
+AC_ARG_ENABLE([cairo], AS_HELP_STRING([--enable-cairo], [add support for Fl_Cairo_Window]))
 AC_ARG_ENABLE([cairoext], AS_HELP_STRING([--enable-cairoext], [use FLTK code instrumentation for cairo extended use]))
 
 AC_ARG_ENABLE([cp936], AS_HELP_STRING([--enable-cp936], [turn on CP936]))
@@ -112,6 +112,8 @@ AC_ARG_ENABLE([pango], AS_HELP_STRING([--enable-pango], [turn on Pango support])
 
 AC_ARG_ENABLE([wayland], AS_HELP_STRING([--enable-wayland], [turn on Wayland support]))
 
+AC_ARG_ENABLE([usecairo], AS_HELP_STRING([--enable-usecairo], [all drawing to X11 windows uses Cairo]))
+
 AC_ARG_ENABLE([print], AS_HELP_STRING([--disable-print], [turn off print support (X11)]))
 AS_IF([test x$enable_print = xno], [
     AC_DEFINE([FL_NO_PRINT_SUPPORT], [Disable X11 print support?])
@@ -984,13 +986,18 @@ AS_CASE([$host_os_gui], [cygwin* | mingw*], [
           AC_MSG_WARN([--enable-wayland: please install pkg-config.])
           AC_MSG_ERROR([Aborting.])
       ])
+      
+      dnl Turn option usecairo ON
+      AC_DEFINE([FLTK_USE_CAIRO])
+      AC_MSG_NOTICE([Turning on the usecairo option])
 
       BUILD="WAYLAND"
       AC_DEFINE([FLTK_USE_WAYLAND])
+      AC_DEFINE([FLTK_USE_X11]) # to build a hybrid Wayland/X11 library
       CFLAGS="$CFLAGS -DUSE_SYSTEM_LIBDECOR=0"
       CXXFLAGS="$CXXFLAGS -DUSE_SYSTEM_LIBDECOR=0"
-      graphics="Wayland"
-      LIBS="$LIBS $($PKGCONFIG --libs wayland-cursor) $($PKGCONFIG --libs wayland-client) $($PKGCONFIG --libs xkbcommon)"
+      graphics="Wayland or X11 with cairo"
+      LIBS="$LIBS $($PKGCONFIG --libs wayland-cursor) $($PKGCONFIG --libs wayland-client) $($PKGCONFIG --libs xkbcommon) $($PKGCONFIG --libs pangoxft) $($PKGCONFIG --libs x11)"
       LIBS="$LIBS $($PKGCONFIG --libs dbus-1) -ldl"
       CXXFLAGS="$CXXFLAGS -I../libdecor/src"
       DSOFLAGS="$LIBS $DSOFLAGS"
@@ -1174,6 +1181,15 @@ AS_CASE([$host_os_gui], [cygwin* | mingw*], [
         ])
     ])
 
+    dnl Option usecairo
+    AS_IF([test x$enable_usecairo = xyes], [
+      enable_pango=yes
+      BUILD="CAIRO"
+      AC_DEFINE([FLTK_USE_CAIRO])
+      AC_MSG_NOTICE([Processing usecairo option])
+      ]
+    )
+    
     dnl test if Pango is asked but xft was not found
     AS_IF([test x$enable_pango = xyes -a x$xft_found = xno], [
         AC_MSG_WARN([could not find the Xft headers and/or libraries required for Pango.])
@@ -1609,6 +1625,9 @@ AS_CASE([$host_os_gui], [cygwin* | mingw*], [
     AS_IF([test x$xrender_found = xyes], [
         graphics="$graphics + Xrender"
     ])
+    AS_IF([test x$enable_usecairo = xyes], [
+        graphics="$graphics + Cairo"
+    ])
     AS_IF([test x$pango_found = xyes], [
         graphics="$graphics + Pango"
     ])
diff --git documentation/src/intro.dox documentation/src/intro.dox
index 89ac09a..7b827fd 100644
--- documentation/src/intro.dox
+++ documentation/src/intro.dox
@@ -143,7 +143,13 @@ the toolkit, which was already in use by several people, Bill
 came up with "FLTK", including a bogus excuse that it
 stands for "The Fast Light Toolkit".
 
-\section intro_unix Building and Installing FLTK Under UNIX and Apple macOS
+\section intro_cmake Building and Installing FLTK with CMake
+
+Starting with version 1.4, the recommended FLTK building system
+is CMake. See file README.CMake of the FLTK source tree for all information.
+It's also possible to use \p configure and \p make as follows to build and install FLTK.
+
+\section intro_unix Building and Installing FLTK Under UNIX and macOS with make
 
 In most cases you can just type "make". This will run configure with
 the default of no options and then compile everything.
@@ -196,6 +202,9 @@ Enable debugging code & symbols
 \par --disable-gl
 Disable OpenGL support
 
+\par --disable-svg
+Disable support of reading and writing of Support Vector Graphics (.svg) files.
+
 \par --disable-print
 Disable print support for an X11 platform
 
@@ -205,22 +214,39 @@ Enable generation of shared libraries
 \par --enable-threads
 Enable multithreading support
 
-\par --enable-xdbe
-Enable the X double-buffer extension
+\par --enable-wayland
+Enable the use of Wayland for all window operations, of Cairo for all graphics
+and of Pango for text drawing (Linux and FreeBSD only). Resulting FLTK apps
+use Wayland if a Wayland compositor is available at run-time, and use
+the equivalent of "--enable-x11 --enable-usecairo" otherwise.
+
+\par --disable-xft
+Disables the Xft library, resulting in non anti-aliased fonts (X11 platform).
 
-\par --enable-xft
-Enable the Xft library for anti-aliased fonts under X11
+\par --enable-usecairo
+All drawing operations use the Cairo library (rather than Xlib) producing
+antialiased graphics (X11 platform, implies --enable-pango).
 
 \par --enable-pango
-Enable the pango library for drawing any text in any script under X11.
+Enable the Pango library for drawing any text in any script with any font under X11.
 
 \par --enable-x11
+This is the default under Unix and Linux.
 When targeting cygwin, build with X11 GUI instead of windows GDI.
 Also applicable to macOS platforms supplemented with XQuartz.
 
 \par --enable-wayland
 Enable use of the Wayland system for window handling.
 
+\par --enable-cairo
+Enable support of class Fl_Cairo_Window (all platforms, requires the Cairo library).
+
+\par --enable-cairoext
+Enable the FLTK instrumentation for cairo extended use (requires --enable-cairo).
+
+\par --disable-gdiplus
+Don't use GDI+ when drawing curves and oblique lines (Windows platform).
+
 \par --enable-cp936
 Under X11, enable use of the GB2312 locale
 
diff --git documentation/src/osissues.dox documentation/src/osissues.dox
index 999fced..3232884 100644
--- documentation/src/osissues.dox
+++ documentation/src/osissues.dox
@@ -88,6 +88,8 @@ Window fl_xid(const Fl_Window *)
 
 \par
 Returns the XID for a window, or zero if not \c shown().
+\deprecated Kept for compatibility with FLTK versions before 1.4.
+Use preferentially fl_x11_xid(const Fl_Window *) with versions 1.4 and above.
 
 Fl_Window *fl_find(ulong xid)
 
@@ -96,6 +98,8 @@ Returns the Fl_Window that corresponds to the given
 XID, or \c NULL if not found. This function uses a cache
 so it is slightly faster than iterating through the windows
 yourself.
+\deprecated Kept for compatibility with FLTK versions before 1.4.
+Use preferentially fl_x11_find(Window) with versions 1.4 and above.
 
 int fl_handle(const XEvent &)
 
@@ -124,9 +128,11 @@ The following global variables are set before
 Fl_Widget::draw() is called, or by Fl_Window::make_current():
 
 \code
-extern Display *fl_display;
+extern Display *fl_display; // for compatibility with previous FLTK versions
+extern Display *fl_x11_display(); // preferred access starting with FLTK 1.4
 extern Window fl_window;
-extern GC fl_gc;
+extern GC fl_gc; // for compatibility with previous FLTK versions
+extern GC fl_x11_gc(); // preferred access starting with FLTK 1.4
 extern int fl_screen;
 extern XVisualInfo *fl_visual;
 extern Colormap fl_colormap;
@@ -559,9 +565,11 @@ called, FLTK stores all the extra arguments you need to
 make a proper GDI call in some global variables:
 
 \code
-extern HINSTANCE fl_display;
+extern HINSTANCE fl_display; // for compatibility with previous FLTK versions
+extern HINSTANCE fl_win32_display(); // preferred access starting with FLTK 1.4
 extern HWND fl_window;
-extern HDC fl_gc;
+extern HDC fl_gc;  // for compatibility with previous FLTK versions
+extern HDC fl_win32_gc(); // preferred access starting with FLTK 1.4
 COLORREF fl_RGB();
 HPEN fl_pen();
 HBRUSH fl_brush();
@@ -931,17 +939,8 @@ FLTK uses UTF-8-encoded UNIX-style filenames and paths.
 
 \section osissues_wayland The Wayland Interface
 
-Wayland-specific source code can be organized as follows to be distinguished
-from X11-specific source code :
-\code
-#include <FL/platform.H> // defines FLTK_USE_WAYLAND or FLTK_USE_X11 as appropriate
-
-#if defined(FLTK_USE_WAYLAND)
-â?¦ Wayland-specific source code â?¦
-#elif defined(FLTK_USE_X11)
-â?¦ X11-specific source code â?¦
-#endif
-\endcode
+See file README.Wayland.txt for details about how to organize platform-specific
+source code for the Wayland platform.
 
 extern struct wl_display *fl_wl_display();
 \par
@@ -950,16 +949,16 @@ struct wl_display representing the connection between the application and Waylan
 For example, \c wl_display_get_fd(fl_wl_display()) gives the file descriptor one can
 use to communicate with the Wayland compositor according to the Wayland protocol.
 
-Window fl_xid(const Fl_Window *)
+struct wld_window *fl_wl_xid(const Fl_Window *)
 \par
 Returns a pointer to an <u>FLTK-defined</u> structure holding Wayland-related
 data created when a window gets show()'n, or NULL if not show()'n.
 
-Fl_Window *fl_find(Window wld_win)
+Fl_Window *fl_wl_find(struct wld_window * wld_win)
 \par
 Returns the Fl_Window that corresponds to the given Window, or NULL if not found.
 
-struct wl_surface *fl_wl_surface(Window wld_win)
+struct wl_surface *fl_wl_surface(struct wld_window *wld_win)
 \par
 Returns a pointer to the struct wl_surface corresponding to a show()'n
 top-level window or subwindow.
diff --git fl_config.cmake.in fl_config.cmake.in
index c0505e0..0acc7a8 100644
--- fl_config.cmake.in
+++ fl_config.cmake.in
@@ -57,6 +57,16 @@
 
 
 /*
+ * FLTK_USE_CAIRO
+ *
+ * Do we use Cairo to draw to the display?
+ *
+ */
+ 
+#cmakedefine FLTK_USE_CAIRO 1
+
+
+/*
  * FLTK_USE_WAYLAND
  *
  * Do we use Wayland for the current platform?
diff --git fl_config.in fl_config.in
index af4fd35..992c3cd 100644
--- fl_config.in
+++ fl_config.in
@@ -56,6 +56,16 @@
 
 
 /*
+ * FLTK_USE_CAIRO
+ *
+ * Do we use Cairo to draw to the display?
+ *
+ */
+ 
+#undef FLTK_USE_CAIRO
+
+
+/*
  * FLTK_USE_WAYLAND
  *
  * Do we use Wayland for the current platform?
diff --git fluid/Makefile fluid/Makefile
index 3252abc..f8423ce 100644
--- fluid/Makefile
+++ fluid/Makefile
@@ -48,6 +48,7 @@ CPPFILES_WIN = ExternalCodeEditor_WIN32.cxx
 CPPFILES_OSX = ExternalCodeEditor_UNIX.cxx
 CPPFILES_X11 = ExternalCodeEditor_UNIX.cxx
 CPPFILES_XFT = ExternalCodeEditor_UNIX.cxx
+CPPFILES_CAIRO = ExternalCodeEditor_UNIX.cxx
 CPPFILES_WAYLAND = ExternalCodeEditor_UNIX.cxx
 
 CPPFILES += $(CPPFILES_$(BUILD))
diff --git makeinclude.in makeinclude.in
index 8df8eb2..78637ea 100644
--- makeinclude.in
+++ makeinclude.in
@@ -24,7 +24,7 @@ FL_ABI_VERSION		= @FL_ABI_VERSION@
 
 FLTK_VERSION		= @FLTK_VERSION@
 
-# FLTK configuration options: BUILD = { WIN | OSX | X11 | XFT | WAYLAND }
+# FLTK configuration options: BUILD = { WIN | OSX | X11 | XFT | CAIROXLIB | WAYLAND }
 
 BUILD		= @BUILD@
 UNAME            = @UNAME@
diff --git src/CMakeLists.txt src/CMakeLists.txt
index 63b5b83..a9bc917 100644
--- src/CMakeLists.txt
+++ src/CMakeLists.txt
@@ -191,7 +191,7 @@ endif (FLTK_USE_X11 AND NOT OPTION_PRINT_SUPPORT)
 
 set (DRIVER_FILES)
 
-if (FLTK_USE_X11)
+if (FLTK_USE_X11 AND NOT OPTION_USE_WAYLAND)
 
   # X11 (including APPLE with X11)
 
@@ -202,13 +202,6 @@ if (FLTK_USE_X11)
     drivers/Posix/Fl_Posix_System_Driver.cxx
     drivers/Unix/Fl_Unix_System_Driver.cxx
     drivers/X11/Fl_X11_System_Driver.cxx
-    drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx
-    drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.cxx
-    drivers/Xlib/Fl_Xlib_Graphics_Driver_color.cxx
-    drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx
-    drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.cxx
-    drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx
-    drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.cxx
     drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx
     drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx
     drivers/X11/fl_X11_platform_init.cxx
@@ -223,29 +216,56 @@ if (FLTK_USE_X11)
     set (DRIVER_FILES ${DRIVER_FILES} Fl_Native_File_Chooser_Kdialog.cxx)
   endif (OPTION_USE_KDIALOG)
 
-  if (USE_XFT)
+  if (FLTK_USE_CAIRO)
     set (DRIVER_FILES ${DRIVER_FILES}
-      drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx
+      drivers/Cairo/Fl_Cairo_Graphics_Driver.cxx
+      drivers/Cairo/Fl_Display_Cairo_Graphics_Driver.cxx
     )
-    if (USE_PANGO)
-      set (DRIVER_FILES ${DRIVER_FILES} drivers/Cairo/Fl_Cairo_Graphics_Driver.cxx)
-    endif (USE_PANGO)
   else ()
+    if (USE_XFT)
+      set (DRIVER_FILES ${DRIVER_FILES}
+        drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx
+      )
+      if (USE_PANGO)
+        set (DRIVER_FILES ${DRIVER_FILES} drivers/Cairo/Fl_Cairo_Graphics_Driver.cxx)
+      endif (USE_PANGO)
+    else ()
+      set (DRIVER_FILES ${DRIVER_FILES}
+        drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx
+      )
+    endif (USE_XFT)
     set (DRIVER_FILES ${DRIVER_FILES}
-      drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx
+      drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx
+      drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.cxx
+      drivers/Xlib/Fl_Xlib_Graphics_Driver_color.cxx
+      drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx
+      drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.cxx
+      drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx
+      drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.cxx
     )
-  endif (USE_XFT)
+  endif (FLTK_USE_CAIRO)
 
   set (DRIVER_HEADER_FILES
     drivers/Posix/Fl_Posix_System_Driver.H
     drivers/X11/Fl_X11_Screen_Driver.H
     drivers/X11/Fl_X11_Window_Driver.H
     drivers/X11/Fl_X11_System_Driver.H
+    drivers/Xlib/Fl_Xlib_Graphics_Driver.H
     drivers/Xlib/Fl_Font.H
     drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.H
     drivers/Xlib/Fl_Xlib_Image_Surface_Driver.H
     drivers/Unix/Fl_Unix_System_Driver.H
  )
+ if (FLTK_USE_CAIRO)
+   set (DRIVER_HEADER_FILES ${DRIVER_HEADER_FILES}
+     drivers/Cairo/Fl_Cairo_Graphics_Driver.H
+     drivers/Cairo/Fl_Display_Cairo_Graphics_Driver.H
+   )
+ elseif (USE_PANGO)
+   set (DRIVER_HEADER_FILES ${DRIVER_HEADER_FILES}
+     drivers/Cairo/Fl_Cairo_Graphics_Driver.H
+   )
+ endif (FLTK_USE_CAIRO)
 
 elseif (OPTION_USE_WAYLAND)
   set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I${CMAKE_CURRENT_BINARY_DIR}")
@@ -262,9 +282,18 @@ elseif (OPTION_USE_WAYLAND)
     drivers/Wayland/fl_wayland_clipboard_dnd.cxx
     drivers/Wayland/fl_wayland_platform_init.cxx
     drivers/Cairo/Fl_Cairo_Graphics_Driver.cxx
+    drivers/Cairo/Fl_Display_Cairo_Graphics_Driver.cxx
     Fl_Native_File_Chooser_FLTK.cxx
     Fl_Native_File_Chooser_GTK.cxx
     Fl_Native_File_Chooser_Kdialog.cxx
+    drivers/X11/Fl_X11_Screen_Driver.cxx
+    drivers/X11/Fl_X11_Window_Driver.cxx
+    drivers/X11/Fl_X11_System_Driver.cxx
+    drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx
+    drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx
+    Fl_x.cxx
+    fl_dnd_x.cxx
+    Fl_get_key.cxx
   )
   set (DRIVER_HEADER_FILES
     drivers/Posix/Fl_Posix_System_Driver.H
@@ -272,6 +301,8 @@ elseif (OPTION_USE_WAYLAND)
     drivers/Wayland/Fl_Wayland_Screen_Driver.H
     drivers/Wayland/Fl_Wayland_Window_Driver.H
     drivers/Wayland/Fl_Wayland_Graphics_Driver.H
+    drivers/Cairo/Fl_Cairo_Graphics_Driver.H
+    drivers/Cairo/Fl_Display_Cairo_Graphics_Driver.H
     drivers/Wayland/Fl_Wayland_Copy_Surface_Driver.H
     drivers/Wayland/Fl_Wayland_Image_Surface_Driver.H
     drivers/Unix/Fl_Unix_System_Driver.H
@@ -346,7 +377,7 @@ else ()
     drivers/GDI/Fl_GDI_Image_Surface_Driver.H
   )
 
-endif (FLTK_USE_X11)
+endif (FLTK_USE_X11 AND NOT OPTION_USE_WAYLAND)
 
 source_group("Header Files" FILES ${HEADER_FILES})
 source_group("Driver Source Files" FILES ${DRIVER_FILES})
@@ -392,19 +423,22 @@ set (GL_DRIVER_FILES
   drivers/OpenGL/Fl_OpenGL_Graphics_Driver_rect.cxx
   drivers/OpenGL/Fl_OpenGL_Graphics_Driver_vertex.cxx
 )
-if (FLTK_USE_X11)
+if (OPTION_USE_WAYLAND)
+  set (GL_DRIVER_FILES ${GL_DRIVER_FILES}
+    drivers/Wayland/Fl_Wayland_Gl_Window_Driver.cxx
+    drivers/X11/Fl_X11_Gl_Window_Driver.cxx
+    drivers/Wayland/fl_wayland_gl_platform_init.cxx)
+  set (GL_DRIVER_HEADER_FILES drivers/Wayland/Fl_Wayland_Gl_Window_Driver.H drivers/X11/Fl_X11_Gl_Window_Driver.H)
+elseif (FLTK_USE_X11)
   set (GL_DRIVER_FILES ${GL_DRIVER_FILES} drivers/X11/Fl_X11_Gl_Window_Driver.cxx drivers/X11/fl_X11_gl_platform_init.cxx)
   set (GL_DRIVER_HEADER_FILES drivers/X11/Fl_X11_Gl_Window_Driver.H)
-elseif (OPTION_USE_WAYLAND)
-  set (GL_DRIVER_FILES ${GL_DRIVER_FILES} drivers/Wayland/Fl_Wayland_Gl_Window_Driver.cxx drivers/Wayland/fl_wayland_gl_platform_init.cxx)
-  set (GL_DRIVER_HEADER_FILES drivers/Wayland/Fl_Wayland_Gl_Window_Driver.H)
 elseif (APPLE)
   set (GL_DRIVER_FILES ${GL_DRIVER_FILES} drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx drivers/Cocoa/fl_macOS_gl_platform_init.cxx)
   set (GL_DRIVER_HEADER_FILES drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.H)
 elseif (WIN32)
   set (GL_DRIVER_FILES ${GL_DRIVER_FILES} drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.cxx drivers/WinAPI/fl_WinAPI_gl_platform_init.cxx)
   set (GL_DRIVER_HEADER_FILES drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.H)
-endif (FLTK_USE_X11)
+endif (OPTION_USE_WAYLAND)
 
 set (GL_DRIVER_HEADER_FILES ${GL_DRIVER_FILES}
   drivers/OpenGL/Fl_OpenGL_Display_Device.H
@@ -621,7 +655,7 @@ if (OPTION_USE_WAYLAND)
   if (OPTION_USE_SYSTEM_LIBDECOR)
     list (APPEND OPTIONAL_LIBS "-ldecor-0")
   endif (OPTION_USE_SYSTEM_LIBDECOR)
-  list (APPEND OPTIONAL_LIBS "-lwayland-cursor -lwayland-client -lxkbcommon -ldl -ldbus-1")
+  list (APPEND OPTIONAL_LIBS "-lwayland-cursor -lwayland-client -lxkbcommon -ldl -ldbus-1 -lXcursor -lXrender -lXinerama -lXfixes -lXft -lXext -lX11")
   if (GTK_FOUND)
     list (APPEND OPTIONAL_LIBS ${GTK_LDFLAGS} )
   endif (GTK_FOUND)
diff --git src/Fl.cxx src/Fl.cxx
index bac2ffa..7b7cb2b 100644
--- src/Fl.cxx
+++ src/Fl.cxx
@@ -99,8 +99,10 @@ Fl_Screen_Driver *Fl::screen_driver()
 /** Returns a pointer to the unique Fl_System_Driver object of the platform */
 Fl_System_Driver *Fl::system_driver()
 {
-  static  Fl_System_Driver* system_driver_ = Fl_System_Driver::newSystemDriver();
-  return system_driver_;
+  if (!Fl_Screen_Driver::system_driver) {
+    Fl_Screen_Driver::system_driver = Fl_System_Driver::newSystemDriver();
+  }
+  return Fl_Screen_Driver::system_driver;
 }
 
 //
@@ -578,21 +580,15 @@ int Fl::program_should_quit_ = 0;
 Fl_X* Fl_X::first;
 #endif
 
+/** Returns the Fl_Window that corresponds to the given window reference,
+  or \c NULL if not found.
+  \deprecated Kept in the X11, Windows, and macOS platforms for compatibility
+    with FLTK versions before 1.4.
+    Please use fl_x11_find(Window), fl_wl_find(struct wld_window*),
+    fl_win32_find(HWND) or fl_mac_find(FLWindow*) with FLTK 1.4.0 and above.
+*/
 Fl_Window* fl_find(Window xid) {
-  Fl_X *window;
-  for (Fl_X **pp = &Fl_X::first; (window = *pp); pp = &window->next) {
-    if (window->xid == xid) {
-      if (window != Fl_X::first && !Fl::modal()) {
-        // make this window be first to speed up searches
-        // this is not done if modal is true to avoid messing up modal stack
-        *pp = window->next;
-        window->next = Fl_X::first;
-        Fl_X::first = window;
-      }
-      return window->w;
-    }
-  }
-  return 0;
+  return Fl_Window_Driver::find((fl_uintptr_t)xid);
 }
 
 /**
@@ -630,7 +626,7 @@ Fl_Window* Fl::next_window(const Fl_Window* window) {
  */
 void Fl::first_window(Fl_Window* window) {
   if (!window || !window->shown()) return;
-  fl_find( Fl_X::i(window)->xid );
+  Fl_Window_Driver::find( Fl_X::i(window)->xid );
 }
 
 /**
@@ -2021,7 +2017,7 @@ void fl_close_display()
 
 FL_EXPORT Window fl_xid_(const Fl_Window *w) {
   Fl_X *temp = Fl_X::i(w);
-  return temp ? temp->xid : 0;
+  return temp ? (Window)temp->xid : 0;
 }
 /** \addtogroup group_macosx
  \{ */
diff --git src/Fl_Color_Chooser.cxx src/Fl_Color_Chooser.cxx
index 9111dba..643ba4f 100644
--- src/Fl_Color_Chooser.cxx
+++ src/Fl_Color_Chooser.cxx
@@ -506,7 +506,7 @@ static int copy_rgb(double r, double g, double b) {
 
 int Fl_Color_Chooser::handle(int e) {
 
-  unsigned int mods = Fl::event_state() & (FL_META | FL_CTRL | FL_ALT);
+  int mods = Fl::event_state() & (FL_META | FL_CTRL | FL_ALT);
   unsigned int shift = Fl::event_state() & FL_SHIFT;
 
   switch (e) {
diff --git src/Fl_Device.cxx src/Fl_Device.cxx
index c4f1dec..d5e1b27 100644
--- src/Fl_Device.cxx
+++ src/Fl_Device.cxx
@@ -97,6 +97,10 @@ Fl_Surface_Device::~Fl_Surface_Device()
   if (surface_ == this) surface_ = NULL;
 }
 
+/** Returns non-NULL if this surface is an Fl_Image_Surface object
+ \version 1.4.0
+ */
+Fl_Image_Surface *Fl_Surface_Device::as_image_surface() { return NULL; }
 
 /**  A constructor that sets the graphics driver used by the display */
 Fl_Display_Device::Fl_Display_Device(Fl_Graphics_Driver *graphics_driver) : Fl_Surface_Device(graphics_driver) {
diff --git src/Fl_File_Chooser2.cxx src/Fl_File_Chooser2.cxx
index ca17df1..e0192bf 100644
--- src/Fl_File_Chooser2.cxx
+++ src/Fl_File_Chooser2.cxx
@@ -360,6 +360,7 @@
 #include <stdlib.h>
 #include "flstring.h"
 #include <errno.h>
+#include <sys/stat.h>
 
 //
 // File chooser label strings and sort function...
diff --git src/Fl_Image_Surface.cxx src/Fl_Image_Surface.cxx
index e2870e5..1a5f5ec 100644
--- src/Fl_Image_Surface.cxx
+++ src/Fl_Image_Surface.cxx
@@ -37,6 +37,7 @@
  */
 Fl_Image_Surface::Fl_Image_Surface(int w, int h, int high_res, Fl_Offscreen off) : Fl_Widget_Surface(NULL) {
   platform_surface = Fl_Image_Surface_Driver::newImageSurfaceDriver(w, h, high_res, off);
+  platform_surface->image_surface_ = this;
   if (platform_surface) driver(platform_surface->driver());
 }
 
@@ -88,6 +89,10 @@ int Fl_Image_Surface_Driver::printable_rect(int *w, int *h) {
   *w = width; *h = height;
   return 0;
 }
+
+Fl_Image_Surface *Fl_Image_Surface_Driver::as_image_surface() {
+  return image_surface_;
+}
 /**
  \}
  \endcond
@@ -149,6 +154,12 @@ void Fl_Image_Surface::rescale() {
   delete rgb;
 }
 
+
+Fl_Image_Surface *Fl_Image_Surface::as_image_surface() {
+  return this;
+}
+
+
 // implementation of the fl_XXX_offscreen() functions
 
 static Fl_Image_Surface **offscreen_api_surface = NULL;
diff --git src/Fl_Input.cxx src/Fl_Input.cxx
index 880b7c6..bc94a88 100644
--- src/Fl_Input.cxx
+++ src/Fl_Input.cxx
@@ -374,7 +374,7 @@ int Fl_Input::handle_key() {
     return 1;
   }
 
-  unsigned int mods = Fl::event_state() & (FL_META|FL_CTRL|FL_ALT);
+  int mods = Fl::event_state() & (FL_META|FL_CTRL|FL_ALT);
   unsigned int shift = Fl::event_state() & FL_SHIFT;
   unsigned int multiline = (input_type() == FL_MULTILINE_INPUT) ? 1 : 0;
   //
diff --git src/Fl_Message.cxx src/Fl_Message.cxx
index 7047fbf..246835d 100644
--- src/Fl_Message.cxx
+++ src/Fl_Message.cxx
@@ -548,7 +548,7 @@ void Fl_Message::icon_label(const char *str) {
 // handle ctrl-c (command-c on macOS) to copy message text
 
 int Fl_Message_Box::handle(int e) {
-  unsigned int mods = Fl::event_state() & (FL_META|FL_CTRL|FL_ALT);
+  int mods = Fl::event_state() & (FL_META|FL_CTRL|FL_ALT);
   switch (e) {
     case FL_KEYBOARD:
     case FL_SHORTCUT:
diff --git src/Fl_Native_File_Chooser_FLTK.cxx src/Fl_Native_File_Chooser_FLTK.cxx
index 144ca95..178ce1b 100644
--- src/Fl_Native_File_Chooser_FLTK.cxx
+++ src/Fl_Native_File_Chooser_FLTK.cxx
@@ -24,8 +24,8 @@
 #include <FL/Fl_Native_File_Chooser.H>
 #include <FL/Fl_File_Chooser.H>
 #include <FL/Fl_File_Icon.H>
-#include "Fl_System_Driver.H" // for struct stat
 #include <string.h>
+#include <sys/stat.h>
 
 
 
diff --git src/Fl_Screen_Driver.H src/Fl_Screen_Driver.H
index 135a7bf..3047aed 100644
--- src/Fl_Screen_Driver.H
+++ src/Fl_Screen_Driver.H
@@ -43,6 +43,7 @@ class Fl_Window;
 class Fl_RGB_Image;
 class Fl_Group;
 class Fl_Input;
+class Fl_System_Driver;
 
 /**
   A base class describing the interface between FLTK and screen-related operations.
@@ -68,6 +69,7 @@ public:
   static char bg_set;
   static char bg2_set;
   static char fg_set;
+  static Fl_System_Driver *system_driver;
 
   virtual float scale(int) { return 1; }
   virtual void scale(int /*n*/, float /*f*/) {}
diff --git src/Fl_Screen_Driver.cxx src/Fl_Screen_Driver.cxx
index 22008da..3f0d1b4 100644
--- src/Fl_Screen_Driver.cxx
+++ src/Fl_Screen_Driver.cxx
@@ -34,6 +34,7 @@
 char Fl_Screen_Driver::bg_set = 0;
 char Fl_Screen_Driver::bg2_set = 0;
 char Fl_Screen_Driver::fg_set = 0;
+Fl_System_Driver *Fl_Screen_Driver::system_driver = NULL;
 
 int Fl_Screen_Driver::keyboard_screen_scaling = 1;
 
diff --git src/Fl_System_Driver.H src/Fl_System_Driver.H
index e893048..0abab55 100644
--- src/Fl_System_Driver.H
+++ src/Fl_System_Driver.H
@@ -84,6 +84,8 @@ public:
   static const int fl_YValue;
   static const int fl_XNegative;
   static const int fl_YNegative;
+  static int command_key;
+  static int control_key;
 
   // implement if the system adds unwanted program argument(s)
   virtual int single_arg(const char *) { return 0; }
diff --git src/Fl_System_Driver.cxx src/Fl_System_Driver.cxx
index ee5e990..44b47bc 100644
--- src/Fl_System_Driver.cxx
+++ src/Fl_System_Driver.cxx
@@ -83,11 +83,30 @@ static Fl_System_Driver::Keyname default_key_table[] = {
   {FL_Delete,     "Delete"}
 };
 
+
+int Fl_System_Driver::command_key = 0;
+int Fl_System_Driver::control_key = 0;
+
+
+int fl_command_modifier() {
+  if (!Fl_System_Driver::command_key) Fl::system_driver();
+  return Fl_System_Driver::command_key;
+}
+
+
+int fl_control_modifier() {
+  if (!Fl_System_Driver::control_key) Fl::system_driver();
+  return Fl_System_Driver::control_key;
+}
+
+
 Fl_System_Driver::Fl_System_Driver()
 {
   // initialize default key table (used in fl_shortcut.cxx)
   key_table = default_key_table;
   key_table_size = sizeof(default_key_table)/sizeof(*default_key_table);
+  command_key = FL_CTRL;
+  control_key = FL_META;
 }
 
 Fl_System_Driver::~Fl_System_Driver()
diff --git src/Fl_Window.cxx src/Fl_Window.cxx
index 56f672f..2d589f4 100644
--- src/Fl_Window.cxx
+++ src/Fl_Window.cxx
@@ -879,6 +879,8 @@ const Fl_Image* Fl_Window::shape() {return pWindowDriver->shape();}
 bool Fl_Window::is_a_rescale() {return Fl_Window_Driver::is_a_rescale_;}
 
 /** Returns a platform-specific identification of a shown window, or 0 if not shown.
+ \note This identification may differ from the platform-specific reference of an
+ Fl_Window object used by functions fl_x11_xid(), fl_mac_xid(), fl_x11_find(), and fl_mac_find().
  \li X11 platform: the window's XID.
  \li macOS platform: The window number of the windowâ??s window device.
  \li other platforms: 0.
diff --git src/Fl_Window_Driver.H src/Fl_Window_Driver.H
index 24878e7..03333c9 100644
--- src/Fl_Window_Driver.H
+++ src/Fl_Window_Driver.H
@@ -61,6 +61,8 @@ public:
   Fl_Window_Driver(Fl_Window *);
   virtual ~Fl_Window_Driver();
   static Fl_Window_Driver *newWindowDriver(Fl_Window *);
+  static fl_uintptr_t xid(const Fl_Window *win);
+  static Fl_Window *find(fl_uintptr_t xid);
   int wait_for_expose_value;
   Fl_Offscreen other_xid; // offscreen bitmap (overlay and double-buffered windows)
   virtual int screen_num();
diff --git src/Fl_Window_Driver.cxx src/Fl_Window_Driver.cxx
index 23c66be..a9faa32 100644
--- src/Fl_Window_Driver.cxx
+++ src/Fl_Window_Driver.cxx
@@ -258,6 +258,32 @@ void Fl_Window_Driver::menu_window_area(int &X, int &Y, int &W, int &H, int nscr
   scr_driver->screen_work_area(X, Y, W, H, nscreen);
 }
 
+/** Returns  the platform-specific reference of the given window, or NULL if that window isn't shown.
+ \version 1.4.0 */
+fl_uintptr_t Fl_Window_Driver::xid(const Fl_Window *win) {
+  Fl_X *flx = win->i;
+  return flx ? flx->xid : 0;
+}
+
+/** Returns a pointer to the Fl_Window corresponding to the platform-specific reference \p xid of a shown window.
+ \version 1.4.0 */
+Fl_Window *Fl_Window_Driver::find(fl_uintptr_t xid) {
+  Fl_X *window;
+  for (Fl_X **pp = &Fl_X::first; (window = *pp); pp = &window->next) {
+    if (window->xid == xid) {
+      if (window != Fl_X::first && !Fl::modal()) {
+        // make this window be first to speed up searches
+        // this is not done if modal is true to avoid messing up modal stack
+        *pp = window->next;
+        window->next = Fl_X::first;
+        Fl_X::first = window;
+      }
+      return window->w;
+    }
+  }
+  return 0;
+}
+
 /**
  \}
  \endcond
diff --git src/Fl_cocoa.mm src/Fl_cocoa.mm
index 05a748b..663fd29 100644
--- src/Fl_cocoa.mm
+++ src/Fl_cocoa.mm
@@ -81,7 +81,7 @@ int fl_mac_os_version = Fl_Darwin_System_Driver::calc_mac_os_version();
 
 // public variables
 void *fl_capture = 0;                   // (NSWindow*) we need this to compensate for a missing(?) mouse capture
-Window fl_window;
+FLWindow *fl_window;
 
 // forward declarations of variables in this file
 static int main_screen_height; // height of menubar-containing screen used to convert between Cocoa and FLTK global screen coordinates
@@ -803,7 +803,7 @@ static NSInteger max_normal_window_level(void)
 
   for (x = Fl_X::first;x;x = x->next) {
     NSInteger level;
-    FLWindow *cw = x->xid;
+    FLWindow *cw = (FLWindow*)x->xid;
     Fl_Window *win = x->w;
     if (!win || !cw || ![cw isVisible])
       continue;
@@ -868,7 +868,7 @@ static void fixup_window_levels(void)
   prev_non_modal = NULL;
 
   for (x = Fl_X::first;x;x = x->next) {
-    FLWindow *cw = x->xid;
+    FLWindow *cw = (FLWindow*)x->xid;
     Fl_Window *win = x->w;
     if (!win || !cw || ![cw isVisible])
       continue;
@@ -1513,7 +1513,7 @@ static FLWindowDelegate *flwindowdelegate_instance = nil;
   FLWindow *top = 0;
   // sort in all regular windows
   for (x = Fl_X::first;x;x = x->next) {
-    FLWindow *cw = x->xid;
+    FLWindow *cw = (FLWindow*)x->xid;
     Fl_Window *win = x->w;
     if (win && cw) {
       if (win->modal()) {
@@ -1525,7 +1525,7 @@ static FLWindowDelegate *flwindowdelegate_instance = nil;
   }
   // now sort in all modals
   for (x = Fl_X::first;x;x = x->next) {
-    FLWindow *cw = x->xid;
+    FLWindow *cw = (FLWindow*)x->xid;
     Fl_Window *win = x->w;
     if (win && cw && [cw isVisible]) {
       if (win->modal()) {
@@ -1536,7 +1536,7 @@ static FLWindowDelegate *flwindowdelegate_instance = nil;
   }
   // finally all non-modals
   for (x = Fl_X::first;x;x = x->next) {
-    FLWindow *cw = x->xid;
+    FLWindow *cw = (FLWindow*)x->xid;
     Fl_Window *win = x->w;
     if (win && cw && [cw isVisible]) {
       if (win->non_modal()) {
@@ -1600,8 +1600,8 @@ static FLWindowDelegate *flwindowdelegate_instance = nil;
 { // before 10.5, subwindows are lost when application is unhidden
   fl_lock_function();
   for (Fl_X *x = Fl_X::first; x; x = x->next) {
-    if (![x->xid parentWindow]) {
-      orderfront_subwindows(x->xid);
+    if (![(FLWindow*)x->xid parentWindow]) {
+      orderfront_subwindows((FLWindow*)x->xid);
     }
   }
   fl_unlock_function();
@@ -3103,7 +3103,7 @@ Fl_X* Fl_Cocoa_Window_Driver::makeWindow()
     [cw setOpaque:NO]; // shaped windows must be non opaque
     [cw setBackgroundColor:[NSColor clearColor]]; // and with transparent background color
   }
-  x->xid = cw;
+  x->xid = (fl_uintptr_t)cw;
   x->w = w;
   i(x);
   wait_for_expose_value = 1;
@@ -3444,7 +3444,7 @@ void Fl_Cocoa_Window_Driver::make_current()
   q_release_context();
   Fl_X *i = Fl_X::i(pWindow);
   //NSLog(@"region-count=%d damage=%u",i->region?i->region->count:0, pWindow->damage());
-  fl_window = i->xid;
+  fl_window = (FLWindow*)i->xid;
   ((Fl_Quartz_Graphics_Driver&)Fl_Graphics_Driver::default_driver()).high_resolution( mapped_to_retina() );
 
   if (pWindow->as_overlay_window() && other_xid && changed_resolution()) {
@@ -3766,7 +3766,7 @@ void Fl_Cocoa_Window_Driver::destroy(FLWindow *xid) {
 
 
 void Fl_Cocoa_Window_Driver::map() {
-  Window xid = fl_xid(pWindow);
+  FLWindow *xid = fl_xid(pWindow);
   if (pWindow && xid && ![xid parentWindow]) { // 10.2
     // after a subwindow has been unmapped, it has lost its parent window and its frame may be wrong
     [xid setSubwindowFrame];
@@ -3779,7 +3779,7 @@ void Fl_Cocoa_Window_Driver::map() {
 
 
 void Fl_Cocoa_Window_Driver::unmap() {
-  Window xid = fl_xid(pWindow);
+  FLWindow *xid = fl_xid(pWindow);
   if (pWindow && xid) {
     if (parent()) [[xid parentWindow] removeChildWindow:xid]; // necessary with at least 10.5
     [xid orderOut:nil];
diff --git src/Fl_win32.cxx src/Fl_win32.cxx
index 6480aab..da4dddc 100644
--- src/Fl_win32.cxx
+++ src/Fl_win32.cxx
@@ -636,7 +636,7 @@ void Fl_WinAPI_Screen_Driver::enable_im() {
 
   Fl_X *i = Fl_X::first;
   while (i) {
-    flImmAssociateContextEx(i->xid, 0, IACE_DEFAULT);
+    flImmAssociateContextEx((HWND)i->xid, 0, IACE_DEFAULT);
     i = i->next;
   }
 
@@ -648,7 +648,7 @@ void Fl_WinAPI_Screen_Driver::disable_im() {
 
   Fl_X *i = Fl_X::first;
   while (i) {
-    flImmAssociateContextEx(i->xid, 0, 0);
+    flImmAssociateContextEx((HWND)i->xid, 0, 0);
     i = i->next;
   }
 
@@ -1288,7 +1288,7 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
         break;
 
       case WM_PAINT: {
-        Fl_Region R, R2;
+        HRGN R, R2;
         Fl_X *i = Fl_X::i(window);
         Fl_Window_Driver::driver(window)->wait_for_expose_value = 0;
         char redraw_whole_window = false;
@@ -1307,7 +1307,7 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
         }
 
         // convert i->region in FLTK units to R2 in drawing units
-        R2 = Fl_GDI_Graphics_Driver::scale_region(i->region, scale, NULL);
+        R2 = Fl_GDI_Graphics_Driver::scale_region((HRGN)i->region, scale, NULL);
 
         RECT r_box;
         if (scale != 1 && GetRgnBox(R, &r_box) != NULLREGION) {
@@ -1316,10 +1316,10 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
           r_box.right = LONG(r_box.right / scale);
           r_box.top = LONG(r_box.top / scale);
           r_box.bottom = LONG(r_box.bottom / scale);
-          Fl_Region R3 = CreateRectRgn(r_box.left, r_box.top, r_box.right + 1, r_box.bottom + 1);
+          HRGN R3 = CreateRectRgn(r_box.left, r_box.top, r_box.right + 1, r_box.bottom + 1);
           if (!i->region) i->region = R3;
           else {
-            CombineRgn(i->region, i->region, R3, RGN_OR);
+            CombineRgn((HRGN)i->region, (HRGN)i->region, R3, RGN_OR);
             DeleteObject(R3);
           }
         }
@@ -2185,7 +2185,7 @@ Fl_X *Fl_WinAPI_Window_Driver::makeWindow() {
     wlen = fl_utf8toUtf16(w->label(), (unsigned)l, (unsigned short *)lab, wlen);
     lab[wlen] = 0;
   }
-  x->xid = CreateWindowExW(styleEx,
+  x->xid = (fl_uintptr_t)CreateWindowExW(styleEx,
                            class_namew, lab, style,
                            xp, yp, wp, hp,
                            parent,
@@ -2208,14 +2208,14 @@ Fl_X *Fl_WinAPI_Window_Driver::makeWindow() {
        for x and y. We can then use GetWindowRect to determine which
        monitor the window was placed on. */
     RECT rect;
-    GetWindowRect(x->xid, &rect);
+    GetWindowRect((HWND)x->xid, &rect);
     make_fullscreen(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
   }
 
   // Setup clipboard monitor target if there are registered handlers and
   // no window is targeted.
   if (!fl_clipboard_notify_empty() && clipboard_wnd == NULL)
-    fl_clipboard_notify_target(x->xid);
+    fl_clipboard_notify_target((HWND)x->xid);
 
   wait_for_expose_value = 1;
   if (show_iconic()) {
@@ -2239,14 +2239,14 @@ Fl_X *Fl_WinAPI_Window_Driver::makeWindow() {
 
   // If we've captured the mouse, we dont want to activate any
   // other windows from the code, or we lose the capture.
-  ShowWindow(x->xid, !showit ? SW_SHOWMINNOACTIVE :
+  ShowWindow((HWND)x->xid, !showit ? SW_SHOWMINNOACTIVE :
              (Fl::grab() || (styleEx & WS_EX_TOOLWINDOW)) ? SW_SHOWNOACTIVATE : SW_SHOWNORMAL);
 
   // Register all windows for potential drag'n'drop operations
-  RegisterDragDrop(x->xid, flIDropTarget);
+  RegisterDragDrop((HWND)x->xid, flIDropTarget);
 
   if (!im_enabled)
-    flImmAssociateContextEx(x->xid, 0, 0);
+    flImmAssociateContextEx((HWND)x->xid, 0, 0);
 
   return x;
 }
@@ -2256,6 +2256,8 @@ Fl_X *Fl_WinAPI_Window_Driver::makeWindow() {
 
 HINSTANCE fl_display = GetModuleHandle(NULL);
 
+HINSTANCE fl_win32_display() { return fl_display; }
+
 void Fl_WinAPI_Window_Driver::set_minmax(LPMINMAXINFO minmax) {
   int td, wd, hd, dummy_x, dummy_y;
 
@@ -2632,10 +2634,10 @@ void Fl_WinAPI_Window_Driver::show() {
   } else {
     // Once again, we would lose the capture if we activated the window.
     Fl_X *i = Fl_X::i(pWindow);
-    if (IsIconic(i->xid))
-      OpenIcon(i->xid);
+    if (IsIconic((HWND)i->xid))
+      OpenIcon((HWND)i->xid);
     if (!fl_capture)
-      BringWindowToTop(i->xid);
+      BringWindowToTop((HWND)i->xid);
     // ShowWindow(i->xid,fl_capture?SW_SHOWNOACTIVATE:SW_RESTORE);
   }
 }
diff --git src/Fl_x.cxx src/Fl_x.cxx
index d29bf82..b189dc4 100644
--- src/Fl_x.cxx
+++ src/Fl_x.cxx
@@ -41,7 +41,11 @@
 #  include "drivers/X11/Fl_X11_Screen_Driver.H"
 #  include "drivers/X11/Fl_X11_Window_Driver.H"
 #  include "drivers/X11/Fl_X11_System_Driver.H"
+#if FLTK_USE_CAIRO
+#  include "drivers/Cairo/Fl_Display_Cairo_Graphics_Driver.H"
+#else
 #  include "drivers/Xlib/Fl_Xlib_Graphics_Driver.H"
+#endif
 #  include "print_button.h"
 #  include <unistd.h>
 #  include <time.h>
@@ -53,6 +57,11 @@
 #  include <X11/keysym.h>
 #  include "Xutf8.h"
 
+#if FLTK_USE_CAIRO
+#  include <cairo-xlib.h>
+#  include <cairo/cairo.h>
+#endif // FLTK_USE_CAIRO
+
 #define USE_XRANDR (HAVE_DLSYM && HAVE_DLFCN_H) // means attempt to dynamically load libXrandr.so
 #if USE_XRANDR
 #include <dlfcn.h>
@@ -149,6 +158,7 @@ static void convert_crlf(unsigned char *string, long& len) {
 ////////////////////////////////////////////////////////////////
 
 Display *fl_display;
+Display *fl_x11_display() { return fl_display; }
 Window fl_message_window = 0;
 int fl_screen;
 XVisualInfo *fl_visual;
@@ -2117,7 +2127,15 @@ void Fl_X11_Window_Driver::resize(int X,int Y,int W,int H) {
   else if (!is_a_resize && !is_a_move) return;
   if (is_a_resize) {
     pWindow->Fl_Group::resize(X,Y,W,H);
-    if (shown()) {pWindow->redraw();}
+    if (shown()) {
+#if FLTK_USE_CAIRO
+      if (!pWindow->as_gl_window() && cairo_) {
+        float s = Fl::screen_driver()->scale(screen_num());
+        cairo_xlib_surface_set_size(cairo_get_target(cairo_), (W>0 ? int(W*s) : 1), (H>0 ? int(H*s) : 1));
+      }
+#endif
+      pWindow->redraw();
+    }
   } else {
     x(X); y(Y);
     if (Fl_X11_Screen_Driver::xim_win && Fl::focus()) {
@@ -2202,6 +2220,7 @@ static int xrender_supported() {
 }
 #endif
 
+#if ! FLTK_USE_CAIRO
 char Fl_Xlib_Graphics_Driver::can_do_alpha_blending() {
 #if HAVE_XRENDER
   static char result = (char)xrender_supported();
@@ -2210,6 +2229,7 @@ char Fl_Xlib_Graphics_Driver::can_do_alpha_blending() {
   return 0;
 #endif
 }
+#endif
 
 extern Fl_Window *fl_xfocus;
 
diff --git src/Makefile src/Makefile
index 94aaf0b..8be30e3 100644
--- src/Makefile
+++ src/Makefile
@@ -207,9 +207,11 @@ GLCPPFILES_OSX = drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx \
 GLCPPFILES_X11 = drivers/X11/Fl_X11_Gl_Window_Driver.cxx \
 		 drivers/X11/fl_X11_gl_platform_init.cxx
 GLCPPFILES_XFT = $(GLCPPFILES_X11)
+GLCPPFILES_CAIRO = $(GLCPPFILES_X11)
 GLCPPFILES_WIN = drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.cxx \
 		 drivers/WinAPI/fl_WinAPI_gl_platform_init.cxx
 GLCPPFILES_WAYLAND = drivers/Wayland/Fl_Wayland_Gl_Window_Driver.cxx \
+  		     drivers/X11/Fl_X11_Gl_Window_Driver.cxx \
 		     drivers/Wayland/fl_wayland_gl_platform_init.cxx
 
 GLCPPFILES += $(GLCPPFILES_$(BUILD))
@@ -258,13 +260,6 @@ QUARTZCPPFILES = \
 
 # These C++ files are used under condition: BUILD_X11
 XLIBCPPFILES = \
-	drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx \
-	drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.cxx \
-	drivers/Xlib/Fl_Xlib_Graphics_Driver_color.cxx \
-	drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx \
-	drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.cxx \
-	drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx \
-	drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.cxx \
 	drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx \
 	drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx \
 	drivers/X11/Fl_X11_Window_Driver.cxx \
@@ -280,7 +275,21 @@ XLIBCPPFILES = \
 	Fl_Native_File_Chooser_GTK.cxx\
 	Fl_Native_File_Chooser_Kdialog.cxx \
         Fl_get_key.cxx
-        
+
+# These graphics driver files are used under condition: BUILD_CAIRO
+CAIROGDFILES = \
+	drivers/Cairo/Fl_Cairo_Graphics_Driver.cxx \
+	drivers/Cairo/Fl_Display_Cairo_Graphics_Driver.cxx
+
+# These graphics driver files are used under condition: BUILD_X11 AND BUILD_XFT
+XLIBGDFILES = drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx \
+	drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.cxx \
+	drivers/Xlib/Fl_Xlib_Graphics_Driver_color.cxx \
+	drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx \
+	drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.cxx \
+	drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx \
+	drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.cxx
+
 # These C++ files are used under condition: BUILD_WAYLAND
 WLCPPFILES = \
 	drivers/Posix/Fl_Posix_Printer_Driver.cxx \
@@ -296,7 +305,16 @@ WLCPPFILES = \
 	drivers/Wayland/Fl_Wayland_Copy_Surface_Driver.cxx \
 	drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx \
 	drivers/Wayland/fl_wayland_platform_init.cxx \
-	drivers/Wayland/fl_wayland_clipboard_dnd.cxx
+	drivers/Wayland/fl_wayland_clipboard_dnd.cxx \
+	drivers/X11/Fl_X11_Screen_Driver.cxx \
+	drivers/X11/Fl_X11_Window_Driver.cxx \
+	drivers/X11/Fl_X11_System_Driver.cxx \
+	drivers/Cairo/Fl_Display_Cairo_Graphics_Driver.cxx \
+	drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx \
+	drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx \
+	Fl_x.cxx \
+	fl_dnd_x.cxx \
+	Fl_get_key.cxx
 
       
 #   fl_dnd_x.cxx  Fl_Native_File_Chooser_GTK.cxx
@@ -364,7 +382,7 @@ FLTKFLAGS = -DFL_LIBRARY
 include ../makeinclude
 
 # makeinclude has set this variable:
-# BUILD = {WIN|X11|XFT|OSX|WAYLAND}
+# BUILD = {WIN|X11|XFT|CAIRO|OSX|WAYLAND}
 
 MMFILES_OSX = $(OBJCPPFILES)
 MMFILES = $(MMFILES_$(BUILD))
@@ -372,8 +390,9 @@ MMFILES = $(MMFILES_$(BUILD))
 CPPFILES += $(PSCPPFILES)
 CPPFILES_OSX = $(QUARTZCPPFILES)
 
-CPPFILES_XFT = $(XLIBCPPFILES) $(XLIBXFTFILES)
-CPPFILES_X11 = $(XLIBCPPFILES) $(XLIBFONTFILES)
+CPPFILES_XFT = $(XLIBCPPFILES) $(XLIBGDFILES) $(XLIBXFTFILES)
+CPPFILES_X11 = $(XLIBCPPFILES) $(XLIBGDFILES) $(XLIBFONTFILES)
+CPPFILES_CAIRO = $(XLIBCPPFILES) $(CAIROGDFILES)
 
 CPPFILES_WAYLAND = $(WLCPPFILES) $(WLXFTFILES)
 
@@ -383,6 +402,7 @@ CPPFILES += $(CPPFILES_$(BUILD))
 
 
 CFILES_X11 = $(XLIBCFILES) $(XLIBXCFILES)
+CFILES_CAIRO = $(XLIBCFILES)
 CFILES_XFT = $(XLIBCFILES)
 
 CFILES_WAYLAND = $(WLCFILES)
diff --git src/drivers/Cairo/Fl_Display_Cairo_Graphics_Driver.H src/drivers/Cairo/Fl_Display_Cairo_Graphics_Driver.H
new file mode 100644
index 0000000..76986af
--- /dev/null
+++ src/drivers/Cairo/Fl_Display_Cairo_Graphics_Driver.H
@@ -0,0 +1,37 @@
+//
+// Support for using Cairo to draw into X11 windows for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 2022 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
+// file is missing or damaged, see the license at:
+//
+//     https://www.fltk.org/COPYING.php
+//
+// Please see the following page on how to report bugs and issues:
+//
+//     https://www.fltk.org/bugs.php
+//
+
+/* \file
+    Declaration of class Fl_Display_Cairo_Graphics_Driver.
+*/
+
+#ifndef FL_DISPLAY_CAIRO_GRAPHICS_DRIVER_H
+# define FL_DISPLAY_CAIRO_GRAPHICS_DRIVER_H
+
+#include "Fl_Cairo_Graphics_Driver.H"
+
+class Fl_Display_Cairo_Graphics_Driver : public Fl_Cairo_Graphics_Driver {
+private:
+  static void *gc_;
+public:
+  virtual void scale(float f);
+  virtual float scale() {return Fl_Graphics_Driver::scale();}
+  virtual void gc(void *value);
+  virtual void* gc();
+  virtual void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
+ };
+
+#endif // FL_DISPLAY_CAIRO_GRAPHICS_DRIVER_H
diff --git src/drivers/Cairo/Fl_Display_Cairo_Graphics_Driver.cxx src/drivers/Cairo/Fl_Display_Cairo_Graphics_Driver.cxx
new file mode 100644
index 0000000..02df902
--- /dev/null
+++ src/drivers/Cairo/Fl_Display_Cairo_Graphics_Driver.cxx
@@ -0,0 +1,64 @@
+//
+// Support for using Cairo to draw into X11 windows for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 2022 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
+// file is missing or damaged, see the license at:
+//
+//     https://www.fltk.org/COPYING.php
+//
+// Please see the following page on how to report bugs and issues:
+//
+//     https://www.fltk.org/bugs.php
+//
+
+/* \file
+    Implementation of class Fl_Display_Cairo_Graphics_Driver .
+*/
+
+#include "Fl_Display_Cairo_Graphics_Driver.H"
+#include <FL/platform.H>
+#include <cairo/cairo.h>
+#include <pango/pangocairo.h>
+#include <stdlib.h>
+
+
+void *Fl_Display_Cairo_Graphics_Driver::gc_ = NULL;
+GC fl_gc;
+
+
+ulong fl_xpixel(uchar r,uchar g,uchar b) {
+  return 0;
+}
+ulong fl_xpixel(Fl_Color i) {
+    return 0;
+}
+
+
+void Fl_Display_Cairo_Graphics_Driver::scale(float f) {
+  Fl_Graphics_Driver::scale(f);
+  if (cairo_) {
+    cairo_restore(cairo_);
+    cairo_save(cairo_);
+    cairo_scale(cairo_, f, f);
+    cairo_translate(cairo_, 0.5, 0.5);
+  }
+}
+
+
+void Fl_Display_Cairo_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)Fl_Graphics_Driver::default_driver().gc(), int(srcx*scale()), int(srcy*scale()), int(w*scale()), int(h*scale()), int(x*scale()), int(y*scale()));
+}
+
+
+void Fl_Display_Cairo_Graphics_Driver::gc(void *value) {
+  gc_ = value;
+  fl_gc = (GC)gc_;
+}
+
+
+void *Fl_Display_Cairo_Graphics_Driver::gc() {
+  return gc_;
+}
diff --git src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx
index 6491332..d1ed8df 100644
--- src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx
+++ src/drivers/Cocoa/Fl_Cocoa_Gl_Window_Driver.cxx
@@ -1,7 +1,7 @@
 //
 // Class Fl_Cocoa_Gl_Window_Driver for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 2021 by Bill Spitzak and others.
+// Copyright 2021-2022 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
@@ -66,7 +66,7 @@ GLContext Fl_Cocoa_Gl_Window_Driver::create_gl_context(Fl_Window* window, const
   // resets the pile of string textures used to draw strings
   // necessary before the first context is created
   if (!shared_ctx) gl_texture_reset();
-  context = Fl_Cocoa_Window_Driver::create_GLcontext_for_window(((Fl_Cocoa_Gl_Choice*)g)->pixelformat, shared_ctx, window);
+  context = Fl_Cocoa_Window_Driver::create_GLcontext_for_window(((Fl_Cocoa_Gl_Choice*)g)->pixelformat, (NSOpenGLContext*)shared_ctx, window);
   if (!context) return 0;
   add_context(context);
   return (context);
@@ -76,7 +76,7 @@ void Fl_Cocoa_Gl_Window_Driver::set_gl_context(Fl_Window* w, GLContext context)
   if (context != cached_context || w != cached_window) {
     cached_context = context;
     cached_window = w;
-    Fl_Cocoa_Window_Driver::GLcontext_makecurrent(context);
+    Fl_Cocoa_Window_Driver::GLcontext_makecurrent((NSOpenGLContext*)context);
   }
 }
 
@@ -86,7 +86,7 @@ void Fl_Cocoa_Gl_Window_Driver::delete_gl_context(GLContext context) {
     cached_window = 0;
     Fl_Cocoa_Window_Driver::GL_cleardrawable();
   }
-  Fl_Cocoa_Window_Driver::GLcontext_release(context);
+  Fl_Cocoa_Window_Driver::GLcontext_release((NSOpenGLContext*)context);
   del_context(context);
 }
 
@@ -143,7 +143,7 @@ void Fl_Cocoa_Gl_Window_Driver::make_current_before() {
   if (d->changed_resolution()){
     d->changed_resolution(false);
     pWindow->invalidate();
-    Fl_Cocoa_Window_Driver::GLcontext_update(pWindow->context());
+    Fl_Cocoa_Window_Driver::GLcontext_update((NSOpenGLContext*)pWindow->context());
   }
 }
 
@@ -179,13 +179,13 @@ void Fl_Cocoa_Gl_Window_Driver::swap_buffers() {
     glRasterPos3f(pos[0], pos[1], pos[2]);              // restore original glRasterPos
   }
    else
-     Fl_Cocoa_Window_Driver::flush_context(pWindow->context());//aglSwapBuffers((AGLContext)context_);
+     Fl_Cocoa_Window_Driver::flush_context((NSOpenGLContext*)pWindow->context());//aglSwapBuffers((AGLContext)context_);
 }
 
 char Fl_Cocoa_Gl_Window_Driver::swap_type() {return copy;}
 
 void Fl_Cocoa_Gl_Window_Driver::resize(int is_a_resize, int w, int h) {
-  Fl_Cocoa_Window_Driver::GLcontext_update(pWindow->context());
+  Fl_Cocoa_Window_Driver::GLcontext_update((NSOpenGLContext*)pWindow->context());
 }
 
 /* Some old Apple hardware doesn't implement the GL_EXT_texture_rectangle extension.
@@ -202,7 +202,7 @@ char *Fl_Cocoa_Gl_Window_Driver::alpha_mask_for_string(const char *str, int n, i
   fl_draw(str, n, 0, fl_height() - fl_descent());
   // get the alpha channel only of the bitmap
   char *alpha_buf = new char[w*h], *r = alpha_buf, *q;
-  q = (char*)CGBitmapContextGetData(surf->offscreen());
+  q = (char*)CGBitmapContextGetData((CGContextRef)surf->offscreen());
   for (int i = 0; i < h; i++) {
     for (int j = 0; j < w; j++) {
       *r++ = *(q+3);
@@ -215,7 +215,7 @@ char *Fl_Cocoa_Gl_Window_Driver::alpha_mask_for_string(const char *str, int n, i
 }
 
 void Fl_Cocoa_Gl_Window_Driver::gl_start() {
-  Fl_Cocoa_Window_Driver::gl_start(gl_start_context);
+  Fl_Cocoa_Window_Driver::gl_start((NSOpenGLContext*)gl_start_context);
 }
 
 // convert BGRA to RGB and also exchange top and bottom
@@ -247,8 +247,8 @@ Fl_RGB_Image* Fl_Cocoa_Gl_Window_Driver::capture_gl_rectangle(int x, int y, int
   if (factor != 1) {
     w *= factor; h *= factor; x *= factor; y *= factor;
   }
-  Fl_Cocoa_Window_Driver::GLcontext_makecurrent(glw->context());
-  Fl_Cocoa_Window_Driver::flush_context(glw->context()); // to capture also the overlay and for directGL demo
+  Fl_Cocoa_Window_Driver::GLcontext_makecurrent((NSOpenGLContext*)glw->context());
+  Fl_Cocoa_Window_Driver::flush_context((NSOpenGLContext*)glw->context()); // to capture also the overlay and for directGL demo
   // Read OpenGL context pixels directly.
   // For extra safety, save & restore OpenGL states that are changed
   glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
@@ -266,10 +266,16 @@ Fl_RGB_Image* Fl_Cocoa_Gl_Window_Driver::capture_gl_rectangle(int x, int y, int
   baseAddress = convert_BGRA_to_RGB(baseAddress, w, h, mByteWidth);
   Fl_RGB_Image *img = new Fl_RGB_Image(baseAddress, w, h, 3, 3 * w);
   img->alloc_array = 1;
-  Fl_Cocoa_Window_Driver::flush_context(glw->context());
+  Fl_Cocoa_Window_Driver::flush_context((NSOpenGLContext*)glw->context());
   return img;
 }
 
+
+FL_EXPORT NSOpenGLContext *fl_mac_glcontext(GLContext rc) {
+  return (NSOpenGLContext*)rc;
+}
+
+
 class Fl_Gl_Cocoa_Plugin : public Fl_Cocoa_Plugin {
 public:
   Fl_Gl_Cocoa_Plugin() : Fl_Cocoa_Plugin(name()) { }
diff --git src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm
index fd278cf..c587caf 100644
--- src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm
+++ src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm
@@ -347,7 +347,7 @@ int Fl_Cocoa_Printer_Driver::begin_page (void)
   CGContextSaveGState(gc);
   CGContextSaveGState(gc);
   fl_line_style(FL_SOLID);
-  fl_window = (Window)1; // TODO: something better
+  fl_window = (FLWindow*)1; // TODO: something better
   fl_clip_region(0);
   return status != noErr;
 }
diff --git src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.cxx src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.cxx
index 01c3b0f..33b0392 100644
--- src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.cxx
+++ src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.cxx
@@ -140,7 +140,7 @@ void Fl_Cocoa_Screen_Driver::grab(Fl_Window* win)
 {
   if (win) {
     if (!Fl::grab_) {
-      fl_capture = Fl_X::i(Fl::first_window())->xid;
+      fl_capture = (FLWindow*)(Fl_X::i(Fl::first_window())->xid);
       Fl_Cocoa_Window_Driver::driver(Fl::first_window())->set_key_window();
     }
     Fl::grab_ = win;
@@ -315,8 +315,8 @@ int Fl_Cocoa_Screen_Driver::input_widget_handle_key(int key, unsigned mods, unsi
 
 void Fl_Cocoa_Screen_Driver::offscreen_size(Fl_Offscreen off, int &width, int &height)
 {
-  width = CGBitmapContextGetWidth(off);
-  height = CGBitmapContextGetHeight(off);
+  width = CGBitmapContextGetWidth((CGContextRef)off);
+  height = CGBitmapContextGetHeight((CGContextRef)off);
 }
 
 Fl_RGB_Image *Fl_Cocoa_Screen_Driver::read_win_rectangle(int X, int Y, int w, int h, Fl_Window *window,
diff --git src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx
index b7f213d..019e2b7 100644
--- src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx
+++ src/drivers/Cocoa/Fl_Cocoa_Window_Driver.cxx
@@ -224,10 +224,10 @@ void Fl_Cocoa_Window_Driver::hide() {
   if (ip && !parent()) pWindow->cursor(FL_CURSOR_DEFAULT);
   if ( hide_common() ) return;
   q_release_context(this);
-  if ( ip->xid == fl_window )
+  if ( ip->xid == (fl_uintptr_t)fl_window )
     fl_window = 0;
   if (ip->region) Fl_Graphics_Driver::default_driver().XDestroyRegion(ip->region);
-  destroy(ip->xid);
+  destroy((FLWindow*)ip->xid);
   delete subRect();
   delete ip;
 }
@@ -338,3 +338,13 @@ int Fl_Cocoa_Window_Driver::screen_num() {
   if (pWindow->parent()) return pWindow->top_window()->screen_num();
   else return screen_num_;
 }
+
+
+FLWindow *fl_mac_xid(const Fl_Window *win) {
+  return (FLWindow*)Fl_Window_Driver::xid(win);
+}
+
+
+Fl_Window *fl_mac_find(FLWindow *xid) {
+  return Fl_Window_Driver::find((fl_uintptr_t)xid);
+}
diff --git src/drivers/Darwin/Fl_Darwin_System_Driver.cxx src/drivers/Darwin/Fl_Darwin_System_Driver.cxx
index 0c8015d..2c4c5a3 100644
--- src/drivers/Darwin/Fl_Darwin_System_Driver.cxx
+++ src/drivers/Darwin/Fl_Darwin_System_Driver.cxx
@@ -93,6 +93,8 @@ Fl_Darwin_System_Driver::Fl_Darwin_System_Driver() : Fl_Posix_System_Driver() {
   // initialize key table
   key_table = darwin_key_table;
   key_table_size = sizeof(darwin_key_table)/sizeof(*darwin_key_table);
+  command_key = FL_META;
+  control_key = FL_CTRL;
 }
 
 int Fl_Darwin_System_Driver::single_arg(const char *arg) {
diff --git src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx
index 29478a9..c44c0a7 100644
--- src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx
+++ src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx
@@ -64,7 +64,7 @@ Fl_GDI_Copy_Surface_Driver::~Fl_GDI_Copy_Surface_Driver() {
       fl_color(FL_WHITE);    // draw white background
       fl_rectf(0, 0, W, H);
       PlayEnhMetaFile((HDC)surf->driver()->gc(), hmf, &rect); // draw metafile to offscreen buffer
-      SetClipboardData(CF_BITMAP, surf->offscreen());
+      SetClipboardData(CF_BITMAP, (HBITMAP)surf->offscreen());
       Fl_Surface_Device::pop_current();
       delete surf;
 
@@ -80,7 +80,7 @@ Fl_GDI_Copy_Surface_Driver::~Fl_GDI_Copy_Surface_Driver() {
 
 void Fl_GDI_Copy_Surface_Driver::set_current() {
   driver()->gc(gc);
-  fl_window = (Window)1;
+  fl_window = (HWND)1;
   Fl_Surface_Device::set_current();
 }
 
diff --git src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx
index 87adc44..188bd1d 100644
--- src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx
+++ src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx
@@ -75,6 +75,10 @@ static FL_BLENDFUNCTION blendfunc = { 0, 0, 255, 1};
  */
 HDC fl_gc = 0;
 
+
+HDC fl_win32_gc() { return fl_gc; }
+
+
 Fl_GDI_Graphics_Driver::Fl_GDI_Graphics_Driver() {
   mask_bitmap_ = NULL;
   gc_ = NULL;
@@ -157,7 +161,7 @@ void Fl_GDI_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offsc
   if (w <= 0 || h <= 0) return;
   HDC new_gc = CreateCompatibleDC(gc_);
   int save = SaveDC(new_gc);
-  SelectObject(new_gc, bitmap);
+  SelectObject(new_gc, (HBITMAP)bitmap);
   BitBlt(gc_, x, y, w, h, new_gc, srcx, srcy, SRCCOPY);
   RestoreDC(new_gc, save);
   DeleteDC(new_gc);
@@ -211,8 +215,8 @@ void Fl_GDI_Graphics_Driver::untranslate_all() {
 #endif
 
 void Fl_GDI_Graphics_Driver::add_rectangle_to_region(Fl_Region r, int X, int Y, int W, int H) {
-  Fl_Region R = XRectangleRegion(X, Y, W, H);
-  CombineRgn(r, r, R, RGN_OR);
+  HRGN R = (HRGN)XRectangleRegion(X, Y, W, H);
+  CombineRgn((HRGN)r, (HRGN)r, R, RGN_OR);
   XDestroyRegion(R);
 }
 
@@ -241,7 +245,7 @@ Fl_Region Fl_GDI_Graphics_Driver::XRectangleRegion(int x, int y, int w, int h) {
 }
 
 void Fl_GDI_Graphics_Driver::XDestroyRegion(Fl_Region r) {
-  DeleteObject(r);
+  DeleteObject((HRGN)r);
 }
 
 
@@ -287,7 +291,7 @@ HRGN Fl_GDI_Graphics_Driver::scale_region(HRGN r, float f, Fl_GDI_Graphics_Drive
 
 
 Fl_Region Fl_GDI_Graphics_Driver::scale_clip(float f) {
-  HRGN r = rstack[rstackptr];
+  HRGN r = (HRGN)rstack[rstackptr];
   HRGN r2 = scale_region(r, f, this);
   return (r == r2 ? NULL : (rstack[rstackptr] = r2, r));
 }
diff --git src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx
index 4cfc745..9e512d8 100644
--- src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx
+++ src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx
@@ -590,7 +590,7 @@ void Fl_GDI_Graphics_Driver::draw_fixed(Fl_RGB_Image *img, int X, int Y, int W,
     RestoreDC(new_gc,save);
     DeleteDC(new_gc);
   } else if (img->d()==2 || img->d()==4) {
-    copy_offscreen_with_alpha(X, Y, W, H, (Fl_Offscreen)*Fl_Graphics_Driver::id(img), cx, cy);
+    copy_offscreen_with_alpha(X, Y, W, H, (HBITMAP)*Fl_Graphics_Driver::id(img), cx, cy);
   } else {
     copy_offscreen(X, Y, W, H, (Fl_Offscreen)*Fl_Graphics_Driver::id(img), cx, cy);
   }
@@ -653,7 +653,7 @@ void Fl_GDI_Printer_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb, int XP, int YP,
 void Fl_GDI_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uintptr_t &mask_)
 {
   if (id_) {
-    DeleteObject((Fl_Offscreen)id_);
+    DeleteObject((HBITMAP)id_);
     id_ = 0;
   }
 
@@ -817,5 +817,5 @@ void Fl_GDI_Graphics_Driver::cache(Fl_Pixmap *img) {
 }
 
 void Fl_GDI_Graphics_Driver::uncache_pixmap(fl_uintptr_t offscreen) {
-  DeleteObject((Fl_Offscreen)offscreen);
+  DeleteObject((HBITMAP)offscreen);
 }
diff --git src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx
index 76b5460..1b13ff0 100644
--- src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx
+++ src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx
@@ -138,10 +138,10 @@ void Fl_GDI_Graphics_Driver::polygon_unscaled(int x, int y, int x1, int y1, int
 // --- clipping
 
 void Fl_GDI_Graphics_Driver::push_clip(int x, int y, int w, int h) {
-  Fl_Region r;
+  HRGN r;
   if (w > 0 && h > 0) {
-    r = XRectangleRegion(x,y,w,h);
-    Fl_Region current = rstack[rstackptr];
+    r = (HRGN)XRectangleRegion(x,y,w,h);
+    HRGN current = (HRGN)rstack[rstackptr];
     if (current) {
       CombineRgn(r,r,current,RGN_AND);
     }
@@ -155,14 +155,14 @@ void Fl_GDI_Graphics_Driver::push_clip(int x, int y, int w, int h) {
 
 int Fl_GDI_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;
-  Fl_Region r = rstack[rstackptr];
+  HRGN r = (HRGN)rstack[rstackptr];
   if (!r) return 0;
   // The win32 API makes no distinction between partial and complete
   // intersection, so we have to check for partial intersection ourselves.
   // However, given that the regions may be composite, we have to do
   // some voodoo stuff...
-  Fl_Region rr = XRectangleRegion(x,y,w,h);
-  Fl_Region temp = CreateRectRgn(0,0,0,0);
+  HRGN rr = (HRGN)XRectangleRegion(x,y,w,h);
+  HRGN temp = CreateRectRgn(0,0,0,0);
   int ret;
   if (CombineRgn(temp, rr, r, RGN_AND) == NULLREGION) { // disjoint
     W = H = 0;
@@ -189,7 +189,7 @@ int Fl_GDI_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y,
 
 int Fl_GDI_Graphics_Driver::not_clipped(int x, int y, int w, int h) {
   if (x+w <= 0 || y+h <= 0) return 0;
-  Fl_Region r = rstack[rstackptr];
+  HRGN r = (HRGN)rstack[rstackptr];
   if (!r) return 1;
   RECT rect;
   if (Fl_Surface_Device::surface() != Fl_Display_Device::display_device()) { // in case of print context, convert coords from logical to device
@@ -206,8 +206,8 @@ void Fl_GDI_Graphics_Driver::restore_clip() {
   fl_clip_state_number++;
   if (gc_) {
     HRGN r = NULL;
-    if (rstack[rstackptr]) r = scale_clip(scale());
-    SelectClipRgn(gc_, rstack[rstackptr]); // if region is NULL, clip is automatically cleared
+    if (rstack[rstackptr]) r = (HRGN)scale_clip(scale());
+    SelectClipRgn(gc_, (HRGN)rstack[rstackptr]); // if region is NULL, clip is automatically cleared
     if (r) unscale_clip(r);
   }
 }
diff --git src/drivers/GDI/Fl_GDI_Image_Surface_Driver.H src/drivers/GDI/Fl_GDI_Image_Surface_Driver.H
index 979b7bd..a3d8ac6 100644
--- src/drivers/GDI/Fl_GDI_Image_Surface_Driver.H
+++ src/drivers/GDI/Fl_GDI_Image_Surface_Driver.H
@@ -24,7 +24,7 @@
 class Fl_GDI_Image_Surface_Driver : public Fl_Image_Surface_Driver {
   virtual void end_current();
 public:
-  Window pre_window;
+  HWND pre_window;
   int _savedc;
   Fl_GDI_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off);
   ~Fl_GDI_Image_Surface_Driver();
diff --git src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx
index 7f655e2..6795fb0 100644
--- src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx
+++ src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx
@@ -29,8 +29,8 @@ Fl_GDI_Image_Surface_Driver::Fl_GDI_Image_Surface_Driver(int w, int h, int high_
     h = int(h*d);
   }
   HDC gc = (HDC)Fl_Graphics_Driver::default_driver().gc();
-  offscreen = off ? off : CreateCompatibleBitmap( (gc ? gc : fl_GetDC(0) ) , w, h);
-  if (!offscreen) offscreen = CreateCompatibleBitmap(fl_GetDC(0), w, h);
+  offscreen = off ? off : (Fl_Offscreen)CreateCompatibleBitmap( (gc ? gc : fl_GetDC(0) ) , w, h);
+  if (!offscreen) offscreen = (Fl_Offscreen)CreateCompatibleBitmap(fl_GetDC(0), w, h);
   driver(Fl_Graphics_Driver::newMainGraphicsDriver());
   if (d != 1 && high_res) ((Fl_GDI_Graphics_Driver*)driver())->scale(d);
   origin.x = origin.y = 0;
@@ -38,13 +38,13 @@ Fl_GDI_Image_Surface_Driver::Fl_GDI_Image_Surface_Driver(int w, int h, int high_
 
 
 Fl_GDI_Image_Surface_Driver::~Fl_GDI_Image_Surface_Driver() {
-  if (offscreen && !external_offscreen) DeleteObject(offscreen);
+  if (offscreen && !external_offscreen) DeleteObject((HBITMAP)offscreen);
   delete driver();
 }
 
 
 void Fl_GDI_Image_Surface_Driver::set_current() {
-  HDC gc = fl_makeDC(offscreen);
+  HDC gc = fl_makeDC((HBITMAP)offscreen);
   driver()->gc(gc);
   SetWindowOrgEx(gc, origin.x, origin.y, NULL);
   Fl_Surface_Device::set_current();
diff --git src/drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.cxx src/drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.cxx
index 3ededb5..77ecdaa 100644
--- src/drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.cxx
+++ src/drivers/Quartz/Fl_Quartz_Copy_Surface_Driver.cxx
@@ -49,7 +49,7 @@ Fl_Quartz_Copy_Surface_Driver::Fl_Quartz_Copy_Surface_Driver(int w, int h) : Fl_
 
 void Fl_Quartz_Copy_Surface_Driver::set_current() {
   driver()->gc(gc);
-  fl_window = (Window)1;
+  fl_window = (FLWindow*)1;
   Fl_Surface_Device::set_current();
 }
 
diff --git src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx
index b503094..552da03 100644
--- src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx
+++ src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx
@@ -84,6 +84,10 @@ void Fl_Quartz_Graphics_Driver::global_gc()
   fl_gc = (CGContextRef)gc();
 }
 
+
+CGContextRef fl_mac_gc() { return fl_gc; }
+
+
 void Fl_Quartz_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen osrc, int srcx, int srcy) {
   // draw portion srcx,srcy,w,h of osrc to position x,y (top-left) of the graphics driver's surface
   CGContextRef src = (CGContextRef)osrc;
@@ -127,7 +131,8 @@ CGRect Fl_Quartz_Graphics_Driver::fl_cgrectmake_cocoa(int x, int y, int w, int h
   return CGRectMake(x - 0.5, y - 0.5, w, h);
 }
 
-void Fl_Quartz_Graphics_Driver::add_rectangle_to_region(Fl_Region r, int X, int Y, int W, int H) {
+void Fl_Quartz_Graphics_Driver::add_rectangle_to_region(Fl_Region r_, int X, int Y, int W, int H) {
+  struct flCocoaRegion *r = (struct flCocoaRegion*)r_;
   CGRect arg = Fl_Quartz_Graphics_Driver::fl_cgrectmake_cocoa(X, Y, W, H);
   int j; // don't add a rectangle totally inside the Fl_Region
   for(j = 0; j < r->count; j++) {
@@ -140,15 +145,16 @@ void Fl_Quartz_Graphics_Driver::add_rectangle_to_region(Fl_Region r, int X, int
 }
 
 Fl_Region Fl_Quartz_Graphics_Driver::XRectangleRegion(int x, int y, int w, int h) {
-  Fl_Region R = (Fl_Region)malloc(sizeof(*R));
+  struct flCocoaRegion* R = (struct flCocoaRegion*)malloc(sizeof(struct flCocoaRegion));
   R->count = 1;
   R->rects = (CGRect *)malloc(sizeof(CGRect));
   *(R->rects) = Fl_Quartz_Graphics_Driver::fl_cgrectmake_cocoa(x, y, w, h);
   return R;
 }
 
-void Fl_Quartz_Graphics_Driver::XDestroyRegion(Fl_Region r) {
-  if(r) {
+void Fl_Quartz_Graphics_Driver::XDestroyRegion(Fl_Region r_) {
+  if (r_) {
+    struct flCocoaRegion *r = (struct flCocoaRegion*)r_;
     free(r->rects);
     free(r);
   }
diff --git src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx
index 558dc47..b97cfbb 100644
--- src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx
+++ src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx
@@ -250,7 +250,7 @@ void Fl_Quartz_Graphics_Driver::cache(Fl_Pixmap *img) {
   Fl_Surface_Device::push_current(surf);
   fl_draw_pixmap(img->data(), 0, 0, FL_BLACK);
   Fl_Surface_Device::pop_current();
-  CGContextRef src = Fl_Graphics_Driver::get_offscreen_and_delete_image_surface(surf);
+  CGContextRef src = (CGContextRef)Fl_Graphics_Driver::get_offscreen_and_delete_image_surface(surf);
   void *cgdata = CGBitmapContextGetData(src);
   int sw = CGBitmapContextGetWidth(src);
   int sh = CGBitmapContextGetHeight(src);
diff --git src/drivers/Quartz/Fl_Quartz_Graphics_Driver_rect.cxx src/drivers/Quartz/Fl_Quartz_Graphics_Driver_rect.cxx
index 52b8c7f..71daf0e 100644
--- src/drivers/Quartz/Fl_Quartz_Graphics_Driver_rect.cxx
+++ src/drivers/Quartz/Fl_Quartz_Graphics_Driver_rect.cxx
@@ -218,11 +218,12 @@ void Fl_Quartz_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, in
 // --- clipping
 
 // intersects current and x,y,w,h rectangle and returns result as a new Fl_Region
-static Fl_Region intersect_region_and_rect(Fl_Region current, int x,int y,int w, int h)
+static Fl_Region intersect_region_and_rect(Fl_Region current_, int x,int y,int w, int h)
 {
-  if (current == NULL) return Fl_Graphics_Driver::default_driver().XRectangleRegion(x,y,w,h);
+  if (current_ == NULL) return Fl_Graphics_Driver::default_driver().XRectangleRegion(x,y,w,h);
+  struct flCocoaRegion* current = (struct flCocoaRegion*)current_;
   CGRect r = Fl_Quartz_Graphics_Driver::fl_cgrectmake_cocoa(x, y, w, h);
-  Fl_Region outr = (Fl_Region)malloc(sizeof(*outr));
+  struct flCocoaRegion* outr = (struct flCocoaRegion*)malloc(sizeof(struct flCocoaRegion));
   outr->count = current->count;
   outr->rects =(CGRect*)malloc(outr->count * sizeof(CGRect));
   int j = 0;
@@ -236,7 +237,7 @@ static Fl_Region intersect_region_and_rect(Fl_Region current, int x,int y,int w,
   }
   else {
     Fl_Graphics_Driver::default_driver().XDestroyRegion(outr);
-    outr = Fl_Graphics_Driver::default_driver().XRectangleRegion(0,0,0,0);
+    outr = (struct flCocoaRegion*)Fl_Graphics_Driver::default_driver().XRectangleRegion(0,0,0,0);
   }
   return outr;
 }
@@ -261,7 +262,7 @@ void Fl_Quartz_Graphics_Driver::push_clip(int x, int y, int w, int h) {
 
 int Fl_Quartz_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;
-  Fl_Region r = rstack[rstackptr];
+  struct flCocoaRegion* r = (struct flCocoaRegion*)rstack[rstackptr];
   if (!r) return 0;
   CGRect arg = fl_cgrectmake_cocoa(x, y, w, h);
   CGRect u = CGRectMake(0,0,0,0);
@@ -283,7 +284,7 @@ int Fl_Quartz_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int&
 
 int Fl_Quartz_Graphics_Driver::not_clipped(int x, int y, int w, int h) {
   if (x+w <= 0 || y+h <= 0) return 0;
-  Fl_Region r = rstack[rstackptr];
+  struct flCocoaRegion* r = (struct flCocoaRegion*)rstack[rstackptr];
   if (!r) return 1;
   CGRect arg = fl_cgrectmake_cocoa(x, y, w, h);
   for (int i = 0; i < r->count; i++) {
@@ -295,7 +296,7 @@ int Fl_Quartz_Graphics_Driver::not_clipped(int x, int y, int w, int h) {
 
 void Fl_Quartz_Graphics_Driver::restore_clip() {
   fl_clip_state_number++;
-  Fl_Region r = rstack[rstackptr];
+  struct flCocoaRegion* r = (struct flCocoaRegion*)rstack[rstackptr];
   if ( fl_window || gc_ ) { // clipping for a true window or an offscreen buffer
     if (gc_) {
       CGContextRestoreGState(gc_);
diff --git src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.H src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.H
index 4e6f8c7..f70a43e 100644
--- src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.H
+++ src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.H
@@ -23,7 +23,7 @@
 class Fl_Quartz_Image_Surface_Driver : public Fl_Image_Surface_Driver {
   virtual void end_current();
 public:
-  Window pre_window;
+  FLWindow *pre_window;
   Fl_Quartz_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off);
   ~Fl_Quartz_Image_Surface_Driver();
   void set_current();
diff --git src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.cxx src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.cxx
index c638bfb..2f1acc5 100644
--- src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.cxx
+++ src/drivers/Quartz/Fl_Quartz_Image_Surface_Driver.cxx
@@ -32,25 +32,25 @@ Fl_Quartz_Image_Surface_Driver::Fl_Quartz_Image_Surface_Driver(int w, int h, int
     W *= s; H *= s;
   }
   CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB();
-  offscreen = off ? off : CGBitmapContextCreate(calloc(W*H,4), W, H, 8, W*4, lut, kCGImageAlphaPremultipliedLast);
+  offscreen = off ? off : (Fl_Offscreen)CGBitmapContextCreate(calloc(W*H,4), W, H, 8, W*4, lut, kCGImageAlphaPremultipliedLast);
   CGColorSpaceRelease(lut);
   driver(new Fl_Quartz_Graphics_Driver);
-  CGContextTranslateCTM(offscreen, 0.5*s, -0.5*s); // as when drawing to a window
+  CGContextTranslateCTM((CGContextRef)offscreen, 0.5*s, -0.5*s); // as when drawing to a window
   if (high_res) {
-    CGContextScaleCTM(offscreen, s, s);
+    CGContextScaleCTM((CGContextRef)offscreen, s, s);
     driver()->scale(s);
   }
-  CGContextSetShouldAntialias(offscreen, false);
-  CGContextTranslateCTM(offscreen, 0, height);
-  CGContextScaleCTM(offscreen, 1.0f, -1.0f);
-  CGContextSaveGState(offscreen);
-  CGContextSetRGBFillColor(offscreen, 1, 1, 1, 0);
-  CGContextFillRect(offscreen, CGRectMake(0,0,w,h));
+  CGContextSetShouldAntialias((CGContextRef)offscreen, false);
+  CGContextTranslateCTM((CGContextRef)offscreen, 0, height);
+  CGContextScaleCTM((CGContextRef)offscreen, 1.0f, -1.0f);
+  CGContextSaveGState((CGContextRef)offscreen);
+  CGContextSetRGBFillColor((CGContextRef)offscreen, 1, 1, 1, 0);
+  CGContextFillRect((CGContextRef)offscreen, CGRectMake(0,0,w,h));
 }
 
 Fl_Quartz_Image_Surface_Driver::~Fl_Quartz_Image_Surface_Driver() {
   if (offscreen && !external_offscreen) {
-    void *data = CGBitmapContextGetData(offscreen);
+    void *data = CGBitmapContextGetData((CGContextRef)offscreen);
     free(data);
     CGContextRelease((CGContextRef)offscreen);
   }
@@ -60,30 +60,30 @@ Fl_Quartz_Image_Surface_Driver::~Fl_Quartz_Image_Surface_Driver() {
 void Fl_Quartz_Image_Surface_Driver::set_current() {
   Fl_Surface_Device::set_current();
   pre_window = fl_window;
-  driver()->gc(offscreen);
+  driver()->gc((CGContextRef)offscreen);
   fl_window = 0;
-  ((Fl_Quartz_Graphics_Driver*)driver())->high_resolution( CGBitmapContextGetWidth(offscreen) > (size_t)width );
+  ((Fl_Quartz_Graphics_Driver*)driver())->high_resolution( CGBitmapContextGetWidth((CGContextRef)offscreen) > (size_t)width );
 }
 
 void Fl_Quartz_Image_Surface_Driver::translate(int x, int y) {
-  CGContextRestoreGState(offscreen);
-  CGContextSaveGState(offscreen);
-  CGContextTranslateCTM(offscreen, x, y);
-  CGContextSaveGState(offscreen);
+  CGContextRestoreGState((CGContextRef)offscreen);
+  CGContextSaveGState((CGContextRef)offscreen);
+  CGContextTranslateCTM((CGContextRef)offscreen, x, y);
+  CGContextSaveGState((CGContextRef)offscreen);
 }
 
 void Fl_Quartz_Image_Surface_Driver::untranslate() {
-  CGContextRestoreGState(offscreen);
+  CGContextRestoreGState((CGContextRef)offscreen);
 }
 
 Fl_RGB_Image* Fl_Quartz_Image_Surface_Driver::image()
 {
-  CGContextFlush(offscreen);
-  int W = CGBitmapContextGetWidth(offscreen);
-  int H = CGBitmapContextGetHeight(offscreen);
-  int bpr = CGBitmapContextGetBytesPerRow(offscreen);
-  int bpp = CGBitmapContextGetBitsPerPixel(offscreen)/8;
-  uchar *base = (uchar*)CGBitmapContextGetData(offscreen);
+  CGContextFlush((CGContextRef)offscreen);
+  int W = CGBitmapContextGetWidth((CGContextRef)offscreen);
+  int H = CGBitmapContextGetHeight((CGContextRef)offscreen);
+  int bpr = CGBitmapContextGetBytesPerRow((CGContextRef)offscreen);
+  int bpp = CGBitmapContextGetBitsPerPixel((CGContextRef)offscreen)/8;
+  uchar *base = (uchar*)CGBitmapContextGetData((CGContextRef)offscreen);
   int idx, idy;
   uchar *pdst, *psrc;
   unsigned char *data = new uchar[W * H * 3];
diff --git src/drivers/Wayland/Fl_Wayland_Copy_Surface_Driver.cxx src/drivers/Wayland/Fl_Wayland_Copy_Surface_Driver.cxx
index 07b3038..60a0cad 100644
--- src/drivers/Wayland/Fl_Wayland_Copy_Surface_Driver.cxx
+++ src/drivers/Wayland/Fl_Wayland_Copy_Surface_Driver.cxx
@@ -43,7 +43,7 @@ Fl_Wayland_Copy_Surface_Driver::~Fl_Wayland_Copy_Surface_Driver() {
 
 void Fl_Wayland_Copy_Surface_Driver::set_current() {
   Fl_Surface_Device::set_current();
-  ((Fl_Wayland_Graphics_Driver*)driver())->set_buffer(img_surf->offscreen());
+  ((Fl_Wayland_Graphics_Driver*)driver())->set_buffer((struct fl_wld_buffer *)img_surf->offscreen());
 }
 
 
diff --git src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.cxx src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.cxx
index 979cef3..8901482 100644
--- src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.cxx
+++ src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.cxx
@@ -94,7 +94,7 @@ char *Fl_Wayland_Gl_Window_Driver::alpha_mask_for_string(const char *str, int n,
 {
   // write str to a bitmap just big enough
   Fl_Image_Surface *surf = new Fl_Image_Surface(w, h);
-  Fl_Font f=fl_font();
+  Fl_Font f = fl_font();
   Fl_Surface_Device::push_current(surf);
   fl_color(FL_BLACK);
   fl_rectf(0, 0, w, h);
@@ -104,7 +104,8 @@ char *Fl_Wayland_Gl_Window_Driver::alpha_mask_for_string(const char *str, int n,
   // get the R channel only of the bitmap
   char *alpha_buf = new char[w*h], *r = alpha_buf, *q;
   for (int i = 0; i < h; i++) {
-    q = (char*)surf->offscreen()->draw_buffer + i * surf->offscreen()->stride;
+    struct fl_wld_buffer *off = (struct fl_wld_buffer *)surf->offscreen();
+    q = (char*)off->draw_buffer + i * off->stride;
     for (int j = 0; j < w; j++) {
       *r++ = *q;
       q += 4;
@@ -174,7 +175,7 @@ GLContext Fl_Wayland_Gl_Window_Driver::create_gl_context(Fl_Window* window, cons
   if (context_list && nContext) shared_ctx = context_list[0];
 
   static const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
-  GLContext ctx = (GLContext)eglCreateContext(egl_display, ((Fl_Wayland_Gl_Choice*)g)->egl_conf, shared_ctx?shared_ctx:EGL_NO_CONTEXT, context_attribs);
+  GLContext ctx = (GLContext)eglCreateContext(egl_display, ((Fl_Wayland_Gl_Choice*)g)->egl_conf, shared_ctx?(EGLContext)shared_ctx:EGL_NO_CONTEXT, context_attribs);
 //fprintf(stderr, "eglCreateContext=%p shared_ctx=%p\n", ctx, shared_ctx);
   if (ctx)
     add_context(ctx);
@@ -183,7 +184,7 @@ GLContext Fl_Wayland_Gl_Window_Driver::create_gl_context(Fl_Window* window, cons
 
 
 void Fl_Wayland_Gl_Window_Driver::set_gl_context(Fl_Window* w, GLContext context) {
-  struct wld_window *win = fl_xid(w);
+  struct wld_window *win = fl_wl_xid(w);
   if (!win) return;
   Fl_Wayland_Window_Driver *dr = Fl_Wayland_Window_Driver::driver(w);
   EGLSurface target_egl_surface = NULL;
@@ -221,7 +222,7 @@ void Fl_Wayland_Gl_Window_Driver::delete_gl_context(GLContext context) {
     cached_window = 0;
   }
 //EGLBoolean b =
-  eglDestroyContext(egl_display, context);
+  eglDestroyContext(egl_display, (EGLContext)context);
 //fprintf(stderr,"EGL context %p destroyed %s\n", context, b==EGL_TRUE?"successfully":"w/ error");
 //b =
   eglDestroySurface(egl_display, egl_surface);
@@ -246,7 +247,7 @@ void Fl_Wayland_Gl_Window_Driver::redraw_overlay() {
 
 void Fl_Wayland_Gl_Window_Driver::make_current_before() {
   if (!egl_window) {
-    struct wld_window *win = fl_xid(pWindow);
+    struct wld_window *win = fl_wl_xid(pWindow);
     struct wl_surface *surface = win->wl_surface;
     egl_window = wl_egl_window_create(surface, pWindow->pixel_w(), pWindow->pixel_h());
     if (egl_window == EGL_NO_SURFACE) {
@@ -270,7 +271,7 @@ void Fl_Wayland_Gl_Window_Driver::make_current_before() {
 float Fl_Wayland_Gl_Window_Driver::pixels_per_unit()
 {
   int ns = Fl_Window_Driver::driver(pWindow)->screen_num();
-  int wld_scale = pWindow->shown() ? fl_xid(pWindow)->scale : 1;
+  int wld_scale = pWindow->shown() ? fl_wl_xid(pWindow)->scale : 1;
   return wld_scale * Fl::screen_driver()->scale(ns);
 }
 
@@ -360,7 +361,7 @@ static void delayed_flush(Fl_Gl_Window *win) {
 
 void Fl_Wayland_Gl_Window_Driver::resize(int is_a_resize, int W, int H) {
   if (!egl_window) return;
-  struct wld_window *win = fl_xid(pWindow);
+  struct wld_window *win = fl_wl_xid(pWindow);
   float f = Fl::screen_scale(pWindow->screen_num());
   W = (W * win->scale) * f;
   H = (H * win->scale) * f;
@@ -404,4 +405,7 @@ void Fl_Wayland_Gl_Window_Driver::gl_start() {
   glClear(GL_COLOR_BUFFER_BIT);
 }
 
+
+FL_EXPORT EGLContext fl_wl_glcontext(GLContext rc) { return (EGLContext)rc; }
+
 #endif // HAVE_GL
diff --git src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx
index 78586dc..986d25d 100644
--- src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx
+++ src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx
@@ -149,8 +149,9 @@ void Fl_Wayland_Graphics_Driver::set_color(Fl_Color i, unsigned c) {
 }
 
 
-void Fl_Wayland_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen osrc, int srcx, int srcy) {
+void Fl_Wayland_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen src, int srcx, int srcy) {
   // draw portion srcx,srcy,w,h of osrc to position x,y (top-left) of the graphics driver's surface
+  struct fl_wld_buffer *osrc = (struct fl_wld_buffer *)src;
   int height = osrc->data_size / osrc->stride;
   cairo_matrix_t matrix;
   cairo_get_matrix(cairo_, &matrix);
diff --git src/drivers/Wayland/Fl_Wayland_Image_Surface_Driver.cxx src/drivers/Wayland/Fl_Wayland_Image_Surface_Driver.cxx
index 1638cf0..4f64434 100644
--- src/drivers/Wayland/Fl_Wayland_Image_Surface_Driver.cxx
+++ src/drivers/Wayland/Fl_Wayland_Image_Surface_Driver.cxx
@@ -33,12 +33,13 @@ Fl_Wayland_Image_Surface_Driver::Fl_Wayland_Image_Surface_Driver(int w, int h, i
       w = int(w*d);
       h = int(h*d);
     }
-    offscreen = (struct fl_wld_buffer*)calloc(1, sizeof(struct fl_wld_buffer));
-    offscreen->stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, w);
-    offscreen->data_size = offscreen->stride * h;
-    offscreen->draw_buffer = (uchar*)malloc(offscreen->data_size);
-    offscreen->width = w;
-    Fl_Wayland_Graphics_Driver::cairo_init(offscreen, w, h, offscreen->stride, CAIRO_FORMAT_RGB24);
+    struct fl_wld_buffer *off_ = (struct fl_wld_buffer*)calloc(1, sizeof(struct fl_wld_buffer));
+    off_->stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, w);
+    off_->data_size = off_->stride * h;
+    off_->draw_buffer = (uchar*)malloc(off_->data_size);
+    off_->width = w;
+    offscreen = (Fl_Offscreen)off_;
+    Fl_Wayland_Graphics_Driver::cairo_init(off_, w, h, off_->stride, CAIRO_FORMAT_RGB24);
   }
   driver(new Fl_Wayland_Graphics_Driver());
   if (d != 1 && high_res) driver()->scale(d);
@@ -47,24 +48,24 @@ Fl_Wayland_Image_Surface_Driver::Fl_Wayland_Image_Surface_Driver(int w, int h, i
 
 Fl_Wayland_Image_Surface_Driver::~Fl_Wayland_Image_Surface_Driver() {
   if (offscreen && !external_offscreen) {
-    cairo_destroy(offscreen->cairo_);
-    free(offscreen->draw_buffer);
-    free(offscreen);
+    cairo_destroy(((struct fl_wld_buffer *)offscreen)->cairo_);
+    free(((struct fl_wld_buffer *)offscreen)->draw_buffer);
+    free((struct fl_wld_buffer *)offscreen);
   }
   delete driver();
 }
 
 void Fl_Wayland_Image_Surface_Driver::set_current() {
   Fl_Surface_Device::set_current();
-  ((Fl_Wayland_Graphics_Driver*)fl_graphics_driver)->set_buffer(offscreen);
+  ((Fl_Wayland_Graphics_Driver*)fl_graphics_driver)->set_buffer((struct fl_wld_buffer*)offscreen);
   pre_window = Fl_Wayland_Window_Driver::wld_window;
-  fl_window = Fl_Wayland_Window_Driver::wld_window = NULL;
+  Fl_Wayland_Window_Driver::wld_window = NULL;
 }
 
 void Fl_Wayland_Image_Surface_Driver::end_current() {
-  cairo_surface_t *surf = cairo_get_target(offscreen->cairo_);
+  cairo_surface_t *surf = cairo_get_target(((struct fl_wld_buffer *)offscreen)->cairo_);
   cairo_surface_flush(surf);
-  fl_window = Fl_Wayland_Window_Driver::wld_window = pre_window;
+  Fl_Wayland_Window_Driver::wld_window = pre_window;
 }
 
 void Fl_Wayland_Image_Surface_Driver::translate(int x, int y) {
@@ -77,20 +78,20 @@ void Fl_Wayland_Image_Surface_Driver::untranslate() {
 
 Fl_RGB_Image* Fl_Wayland_Image_Surface_Driver::image() {
   // Convert depth-4 image in draw_buffer to a depth-3 image while exchanging R and B colors
-  int height = offscreen->data_size / offscreen->stride;
-  uchar *rgb = new uchar[offscreen->width * height * 3];
+  int height = ((struct fl_wld_buffer *)offscreen)->data_size / ((struct fl_wld_buffer *)offscreen)->stride;
+  uchar *rgb = new uchar[((struct fl_wld_buffer *)offscreen)->width * height * 3];
   uchar *p = rgb;
   uchar *q;
   for (int j = 0; j < height; j++) {
-    q = offscreen->draw_buffer + j*offscreen->stride;
-    for (int i = 0; i < offscreen->width; i++) { // exchange R and B colors, transmit G
+    q = ((struct fl_wld_buffer *)offscreen)->draw_buffer + j*((struct fl_wld_buffer *)offscreen)->stride;
+    for (int i = 0; i < ((struct fl_wld_buffer *)offscreen)->width; i++) { // exchange R and B colors, transmit G
       *p = *(q+2);
       *(p+1) = *(q+1);
       *(p+2) = *q;
       p += 3; q += 4;
     }
   }
-  Fl_RGB_Image *image = new Fl_RGB_Image(rgb, offscreen->width, height, 3);
+  Fl_RGB_Image *image = new Fl_RGB_Image(rgb, ((struct fl_wld_buffer *)offscreen)->width, height, 3);
   image->alloc_array = 1;
   return image;
 }
diff --git src/drivers/Wayland/Fl_Wayland_Screen_Driver.H src/drivers/Wayland/Fl_Wayland_Screen_Driver.H
index 196f07d..a7a3f95 100644
--- src/drivers/Wayland/Fl_Wayland_Screen_Driver.H
+++ src/drivers/Wayland/Fl_Wayland_Screen_Driver.H
@@ -64,6 +64,10 @@ class Fl_Wayland_Screen_Driver : public Fl_Screen_Driver
   static bool insertion_point_location_is_valid;
 public:
   static struct wl_display *wl_display;
+  // use it to make sure the Wayland leg was selected and fl_open_display() has run
+  static struct wl_registry *wl_registry;
+  // true when an app is forbidden to use its Wayland leg
+  static bool wld_disabled;
   static void insertion_point_location(int x, int y, int height);
   static bool insertion_point_location(int *px, int *py, int *pwidth, int *pheight);
   int get_mouse_unscaled(int &xx, int &yy);
diff --git src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx
index 372d08b..821bdd5 100644
--- src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx
+++ src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx
@@ -227,13 +227,16 @@ static inline void checkdouble() {
 
 
 struct wl_display *Fl_Wayland_Screen_Driver::wl_display = NULL;
+struct wl_registry *Fl_Wayland_Screen_Driver::wl_registry = NULL;
 
 
+bool Fl_Wayland_Screen_Driver::wld_disabled = false;
+
 Fl_Window *Fl_Wayland_Screen_Driver::surface_to_window(struct wl_surface *surface) {
   if (surface) {
     Fl_X *xp = Fl_X::first;
     while (xp) {
-      if (xp->xid->wl_surface == surface) return xp->w;
+      if (((struct wld_window*)xp->xid)->wl_surface == surface) return xp->w;
       xp = xp->next;
     }
   }
@@ -335,9 +338,9 @@ static void pointer_button(void *data,
   win = win->top_window();
   wld_event_time = time;
   if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED && seat->pointer_focus == NULL &&
-      fl_xid(win)->kind == Fl_Wayland_Window_Driver::DECORATED) {
+      (fl_wl_xid(win))->kind == Fl_Wayland_Window_Driver::DECORATED) {
     // click on titlebar
-    libdecor_frame_move(fl_xid(win)->frame, seat->wl_seat, serial);
+    libdecor_frame_move(fl_wl_xid(win)->frame, seat->wl_seat, serial);
     return;
   }
   int b = 0;
@@ -907,7 +910,7 @@ static void output_done(void *data, struct wl_output *wl_output)
 //fprintf(stderr, "output_done output=%p\n",output);
   Fl_X *xp = Fl_X::first;
   while (xp) { // all mapped windows
-    struct wld_window *win = xp->xid;
+    struct wld_window *win = (struct wld_window*)xp->xid;
     wl_list_for_each(window_output, &(win->outputs), link) { // all Fl_Wayland_Window_Driver::window_output for this window
       if (window_output->output == output) {
         Fl_Wayland_Window_Driver *win_driver = Fl_Wayland_Window_Driver::driver(win->fl_win);
@@ -1041,7 +1044,7 @@ static void registry_handle_global_remove(void *data, struct wl_registry *regist
     if (output->id == name) { // the screen being removed
       Fl_X *xp = Fl_X::first;
       while (xp) { // all mapped windows
-        struct wld_window *win = xp->xid;
+        struct wld_window *win = (struct wld_window*)xp->xid;
         wl_list_for_each_safe(window_output, tmp, &(win->outputs), link) { // all Fl_Wayland_Window_Driver::window_output for this window
           if (window_output->output == output) {
             wl_list_remove(&window_output->link);
@@ -1086,16 +1089,16 @@ Fl_Wayland_Screen_Driver::Fl_Wayland_Screen_Driver() : Fl_Screen_Driver() {
 }
 
 void Fl_Wayland_Screen_Driver::open_display_platform() {
-  struct wl_registry *wl_registry;
-
   static bool beenHereDoneThat = false;
   if (beenHereDoneThat)
     return;
 
   beenHereDoneThat = true;
-  wl_display = wl_display_connect(NULL);
   if (!wl_display) {
-    Fl::fatal("No Wayland connection\n");
+    wl_display = wl_display_connect(NULL);
+    if (!wl_display) {
+      Fl::fatal("No Wayland connection\n");
+    }
   }
   wl_list_init(&seats);
   wl_list_init(&outputs);
@@ -1121,6 +1124,7 @@ void Fl_Wayland_Screen_Driver::close_display() {
   Fl::remove_fd(wl_display_get_fd(Fl_Wayland_Screen_Driver::wl_display));
   wl_display_disconnect(Fl_Wayland_Screen_Driver::wl_display);
   Fl_Wayland_Screen_Driver::wl_display = NULL;
+  Fl_Wayland_Screen_Driver::wl_registry = NULL;
 }
 
 
@@ -1141,7 +1145,7 @@ void Fl_Wayland_Screen_Driver::init_workarea()
 
 
 int Fl_Wayland_Screen_Driver::x() {
-  if (!Fl_Wayland_Screen_Driver::wl_display) open_display();
+  if (!Fl_Wayland_Screen_Driver::wl_registry) open_display();
   Fl_Wayland_Screen_Driver::output *output;
   wl_list_for_each(output, &outputs, link) {
     break;
@@ -1150,7 +1154,7 @@ int Fl_Wayland_Screen_Driver::x() {
 }
 
 int Fl_Wayland_Screen_Driver::y() {
-  if (!Fl_Wayland_Screen_Driver::wl_display) open_display();
+  if (!Fl_Wayland_Screen_Driver::wl_registry) open_display();
   Fl_Wayland_Screen_Driver::output *output;
   wl_list_for_each(output, &outputs, link) {
     break;
@@ -1159,7 +1163,7 @@ int Fl_Wayland_Screen_Driver::y() {
 }
 
 int Fl_Wayland_Screen_Driver::w() {
-  if (!Fl_Wayland_Screen_Driver::wl_display) open_display();
+  if (!Fl_Wayland_Screen_Driver::wl_registry) open_display();
   Fl_Wayland_Screen_Driver::output *output;
   wl_list_for_each(output, &outputs, link) {
     break;
@@ -1168,7 +1172,7 @@ int Fl_Wayland_Screen_Driver::w() {
 }
 
 int Fl_Wayland_Screen_Driver::h() {
-  if (!Fl_Wayland_Screen_Driver::wl_display) open_display();
+  if (!Fl_Wayland_Screen_Driver::wl_registry) open_display();
   Fl_Wayland_Screen_Driver::output *output;
   wl_list_for_each(output, &outputs, link) {
     break;
@@ -1178,7 +1182,7 @@ int Fl_Wayland_Screen_Driver::h() {
 
 
 void Fl_Wayland_Screen_Driver::init() {
-  if (!Fl_Wayland_Screen_Driver::wl_display) open_display();
+  if (!Fl_Wayland_Screen_Driver::wl_registry) open_display();
 }
 
 
@@ -1315,8 +1319,8 @@ const char *Fl_Wayland_Screen_Driver::get_system_scheme()
 
 Fl_RGB_Image *Fl_Wayland_Screen_Driver::read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win,
                                                            bool ignore, bool *p_ignore) {
-  Window xid = win ? fl_xid(win) : NULL;
-  struct fl_wld_buffer *buffer = win ? xid->buffer : (Fl_Offscreen)Fl_Surface_Device::surface()->driver()->gc();
+  struct wld_window* xid = win ? fl_wl_xid(win) : NULL;
+  struct fl_wld_buffer *buffer = win ? xid->buffer : (struct fl_wld_buffer *)Fl_Surface_Device::surface()->driver()->gc();
   float s = win ? xid->scale * scale(win->screen_num()) :
                   Fl_Surface_Device::surface()->driver()->scale();
   int Xs, Ys, ws, hs;
@@ -1346,8 +1350,9 @@ Fl_RGB_Image *Fl_Wayland_Screen_Driver::read_win_rectangle(int X, int Y, int w,
 }
 
 
-void Fl_Wayland_Screen_Driver::offscreen_size(Fl_Offscreen off, int &width, int &height)
+void Fl_Wayland_Screen_Driver::offscreen_size(Fl_Offscreen off_, int &width, int &height)
 {
+  struct fl_wld_buffer *off = (struct fl_wld_buffer *)off_;
   width = off->width;
   height = off->data_size / off->stride;
 }
@@ -1457,3 +1462,8 @@ void Fl_Wayland_Screen_Driver::reset_spot() {
   Fl_Wayland_Screen_Driver::next_marked_length = 0;
   Fl_Wayland_Screen_Driver::insertion_point_location_is_valid = false;
 }
+
+
+struct wl_display *fl_wl_display() {
+  return Fl_Wayland_Screen_Driver::wl_display;
+}
diff --git src/drivers/Wayland/Fl_Wayland_System_Driver.cxx src/drivers/Wayland/Fl_Wayland_System_Driver.cxx
index a54e2ac..4b26a17 100644
--- src/drivers/Wayland/Fl_Wayland_System_Driver.cxx
+++ src/drivers/Wayland/Fl_Wayland_System_Driver.cxx
@@ -18,6 +18,7 @@
 #include "Fl_Wayland_System_Driver.H"
 #include <FL/Fl.H>
 #include "Fl_Wayland_Window_Driver.H"
+#include "Fl_Wayland_Screen_Driver.H"
 #include <FL/platform.H>
 #include "../../../libdecor/src/libdecor.h"
 
@@ -55,7 +56,7 @@ void *Fl_Wayland_System_Driver::control_maximize_button(void *data) {
     Fl_Window *win = Fl::first_window();
     while (win) {
       if (!win->parent() && win->border() &&
-          !(Fl_X::i(win)->xid->state & LIBDECOR_WINDOW_STATE_MAXIMIZED) ) {
+          !( ((struct wld_window*)Fl_X::i(win)->xid)->state & LIBDECOR_WINDOW_STATE_MAXIMIZED) ) {
         win_dims *dim = new win_dims;
         dim->tracker = new Fl_Widget_Tracker(win);
         Fl_Window_Driver *dr = Fl_Window_Driver::driver(win);
diff --git src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
index 38230b3..96985c1 100644
--- src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
+++ src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
@@ -49,7 +49,7 @@ extern "C" {
 
 #define fl_max(a,b) ((a) > (b) ? (a) : (b))
 
-Window fl_window;
+
 struct wld_window *Fl_Wayland_Window_Driver::wld_window = NULL;
 
 
@@ -112,7 +112,7 @@ void Fl_Wayland_Window_Driver::decorated_win_size(int &w, int &h)
   h = win->h();
   if (!win->shown() || win->parent() || !win->border() || !win->visible()) return;
   int X, titlebar_height;
-  libdecor_frame_translate_coordinate(fl_xid(win)->frame, 0, 0, &X, &titlebar_height);
+  libdecor_frame_translate_coordinate(fl_wl_xid(win)->frame, 0, 0, &X, &titlebar_height);
 //printf("titlebar_height=%d\n",titlebar_height);
   h = win->h() + ceil(titlebar_height / Fl::screen_scale(win->screen_num()));
 }
@@ -135,7 +135,7 @@ int Fl_Wayland_Window_Driver::decorated_w()
 }
 
 struct xdg_toplevel *Fl_Wayland_Window_Driver::xdg_toplevel() {
-  Window w = fl_xid(pWindow);
+  struct wld_window * w = fl_wl_xid(pWindow);
   struct xdg_toplevel *top = NULL;
   if (w->kind == DECORATED) top = libdecor_frame_get_xdg_toplevel(w->frame);
   else if (w->kind == UNFRAMED) top = w->xdg_toplevel;
@@ -144,10 +144,10 @@ struct xdg_toplevel *Fl_Wayland_Window_Driver::xdg_toplevel() {
 
 void Fl_Wayland_Window_Driver::take_focus()
 {
-  Window w = fl_xid(pWindow);
+  struct wld_window *w = fl_wl_xid(pWindow);
   if (w) {
     Fl_Window *old_first = Fl::first_window();
-    Window first_xid = (old_first ? fl_xid(old_first->top_window()) : NULL);
+    struct wld_window *first_xid = (old_first ? fl_wl_xid(old_first->top_window()) : NULL);
     if (first_xid && first_xid != w && xdg_toplevel()) {
       // this will move the target window to the front
       Fl_Wayland_Window_Driver *top_dr = Fl_Wayland_Window_Driver::driver(old_first->top_window());
@@ -157,7 +157,7 @@ void Fl_Wayland_Window_Driver::take_focus()
       xdg_toplevel_set_parent(xdg_toplevel(), NULL);
     }
     // this sets the first window
-    fl_find(w);
+    fl_wl_find(w);
   }
 }
 
@@ -185,7 +185,7 @@ void Fl_Wayland_Window_Driver::flush_overlay()
     fl_copy_offscreen(0, 0, oWindow->w(), oWindow->h(), other_xid, 0, 0);
   }
   if (overlay() == oWindow) oWindow->draw_overlay();
-  Window xid = fl_xid(pWindow);
+  struct wld_window * xid = fl_wl_xid(pWindow);
   wl_surface_damage_buffer(xid->wl_surface, 0, 0, pWindow->w() * xid->scale, pWindow->h() * xid->scale);
 }
 
@@ -295,7 +295,7 @@ void Fl_Wayland_Window_Driver::capture_titlebar_and_borders(Fl_RGB_Image*& top,
   top = left = bottom = right = NULL;
   if (pWindow->decorated_h() == h()) return;
   int htop = pWindow->decorated_h() - pWindow->h();
-  struct wld_window *wwin = fl_xid(pWindow);
+  struct wld_window *wwin = fl_wl_xid(pWindow);
   int width, height, stride;
   uchar *cairo_data = fl_libdecor_titlebar_buffer(wwin->frame, &width, &height, &stride);
   if (!cairo_data) return;
@@ -342,7 +342,7 @@ void Fl_Wayland_Window_Driver::make_current() {
     Fl::fatal(err_message);
   }
 
-  struct wld_window *window = fl_xid(pWindow);
+  struct wld_window *window = fl_wl_xid(pWindow);
   if (window->buffer) {
     ((Fl_Cairo_Graphics_Driver*)fl_graphics_driver)->needs_commit_tag(
                                             &window->buffer->draw_buffer_needs_commit);
@@ -355,7 +355,7 @@ void Fl_Wayland_Window_Driver::make_current() {
   }
 
   fl_graphics_driver->clip_region(0);
-  fl_window = Fl_Wayland_Window_Driver::wld_window = window;
+  Fl_Wayland_Window_Driver::wld_window = window;
   float scale = Fl::screen_scale(pWindow->screen_num()) * window->scale;
   if (!window->buffer) {
     window->buffer = Fl_Wayland_Graphics_Driver::create_shm_buffer(
@@ -385,11 +385,11 @@ void Fl_Wayland_Window_Driver::flush() {
     if (scale != fl_graphics_driver->scale() || W != pWindow->w() || H != pWindow->h()) gl_plugin()->invalidate(pWindow);
     return;
   }
-  struct wld_window *window = fl_xid(pWindow);
+  struct wld_window *window = fl_wl_xid(pWindow);
   if (!window || !window->configured_width) return;
 
   Fl_X *i = Fl_X::i(pWindow);
-  Fl_Region r = i->region;
+  struct flCairoRegion* r = (struct flCairoRegion*)i->region;
   float f = Fl::screen_scale(pWindow->screen_num());
   if (r && window->buffer) {
     for (int i = 0; i < r->count; i++) {
@@ -440,7 +440,7 @@ void Fl_Wayland_Window_Driver::hide() {
     ip->region = 0;
   }
   screen_num_ = -1;
-  struct wld_window *wld_win = ip->xid;
+  struct wld_window *wld_win = (struct wld_window*)ip->xid;
   if (wld_win) { // this test makes sure ip->xid has not been destroyed already
     Fl_Wayland_Graphics_Driver::buffer_release(wld_win);
 //fprintf(stderr, "Before hide: sub=%p frame=%p xdg=%p top=%p pop=%p surf=%p\n", wld_win->subsurface,  wld_win->frame, wld_win->xdg_surface, wld_win->xdg_toplevel, wld_win->xdg_popup, wld_win->wl_surface);
@@ -479,7 +479,7 @@ void Fl_Wayland_Window_Driver::hide() {
   }
   free(wld_win);
   if (pWindow->as_gl_window() && in_flush) {
-    ip->xid = NULL;
+    ip->xid = 0;
     ip->next = NULL; // to end the loop in calling Fl::flush()
     Fl::add_timeout(.01, (Fl_Timeout_Handler)delayed_delete_Fl_X, ip);
   } else {
@@ -490,9 +490,9 @@ void Fl_Wayland_Window_Driver::hide() {
 
 void Fl_Wayland_Window_Driver::map() {
   Fl_X* ip = Fl_X::i(pWindow);
-  struct wld_window *wl_win = ip->xid;
+  struct wld_window *wl_win = (struct wld_window*)ip->xid;
   if (wl_win->kind == SUBWINDOW && !wl_win->subsurface) {
-    struct wld_window *parent = fl_xid(pWindow->window());
+    struct wld_window *parent = fl_wl_xid(pWindow->window());
     if (parent) {
       Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
       wl_win->subsurface = wl_subcompositor_get_subsurface(scr_driver->wl_subcompositor, wl_win->wl_surface, parent->wl_surface);
@@ -512,7 +512,7 @@ void Fl_Wayland_Window_Driver::map() {
 
 void Fl_Wayland_Window_Driver::unmap() {
   Fl_X* ip = Fl_X::i(pWindow);
-  struct wld_window *wl_win = ip->xid;
+  struct wld_window *wl_win = (struct wld_window*)ip->xid;
   if (wl_win->kind == SUBWINDOW && wl_win->wl_surface) {
     wl_surface_attach(wl_win->wl_surface, NULL, 0, 0);
     Fl_Wayland_Graphics_Driver::buffer_release(wl_win);
@@ -525,7 +525,7 @@ void Fl_Wayland_Window_Driver::unmap() {
 void Fl_Wayland_Window_Driver::size_range() {
   if (shown()) {
     Fl_X* ip = Fl_X::i(pWindow);
-    struct wld_window *wl_win = ip->xid;
+    struct wld_window *wl_win = (struct wld_window*)ip->xid;
     float f = Fl::screen_scale(pWindow->screen_num());
     if (wl_win->kind == DECORATED && wl_win->frame) {
       int X,Y,W,H;
@@ -553,7 +553,7 @@ void Fl_Wayland_Window_Driver::size_range() {
 
 void Fl_Wayland_Window_Driver::iconize() {
   Fl_X* ip = Fl_X::i(pWindow);
-  struct wld_window *wl_win = ip->xid;
+  struct wld_window *wl_win = (struct wld_window*)ip->xid;
   if (wl_win->kind == DECORATED) {
     libdecor_frame_set_minimized(wl_win->frame);
     Fl::handle(FL_HIDE, pWindow);
@@ -577,7 +577,7 @@ void Fl_Wayland_Window_Driver::decoration_sizes(int *top, int *left,  int *right
 int Fl_Wayland_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)
 {
-  Window xid = fl_xid(pWindow);
+  struct wld_window * xid = fl_wl_xid(pWindow);
   struct fl_wld_buffer *buffer = xid->buffer;
   float s = xid->scale * fl_graphics_driver->scale();
   if (s != 1) {
@@ -781,7 +781,7 @@ static void handle_configure(struct libdecor_frame *frame,
 void Fl_Wayland_Window_Driver::wait_for_expose()
 {
   Fl_Window_Driver::wait_for_expose();
-  Window xid = fl_xid(pWindow);
+  struct wld_window * xid = fl_wl_xid(pWindow);
   if (pWindow->fullscreen_active()) {
     if (xid->kind == DECORATED) {
       while (!(xid->state & LIBDECOR_WINDOW_STATE_FULLSCREEN) || !(xid->state & LIBDECOR_WINDOW_STATE_ACTIVE)) {
@@ -897,7 +897,7 @@ static void popup_done(void *data, struct xdg_popup *xdg_popup) {
 #if USE_GRAB_POPUP
   if (mem_grabbing_popup == xdg_popup) {
     Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
-    libdecor_frame_popup_ungrab(fl_xid(mem_parent)->frame, scr_driver->get_seat_name());
+    libdecor_frame_popup_ungrab(fl_wl_xid(mem_parent)->frame, scr_driver->get_seat_name());
     mem_grabbing_popup = NULL;
     mem_parent = NULL;
   }
@@ -1003,7 +1003,7 @@ Fl_X *Fl_Wayland_Window_Driver::makeWindow()
     if (!target) target = Fl::first_window();
     Fl_Window *parent_win = target->top_window();
     while (parent_win && parent_win->menu_window()) parent_win = Fl::next_window(parent_win);
-    Window parent_xid = fl_xid(parent_win);
+    struct wld_window * parent_xid = fl_wl_xid(parent_win);
     struct xdg_surface *parent_xdg = parent_xid->xdg_surface;
     float f = Fl::screen_scale(parent_win->screen_num());
 //fprintf(stderr, "menu parent_win=%p pos:%dx%d size:%dx%d\n", parent_win, pWindow->x(), pWindow->y(), pWindow->w(), pWindow->h());
@@ -1029,7 +1029,8 @@ Fl_X *Fl_Wayland_Window_Driver::makeWindow()
 
   } else if ( pWindow->border() && !pWindow->parent() ) { // a decorated window
     new_window->kind = DECORATED;
-    if (!scr_driver->libdecor_context) scr_driver->libdecor_context = libdecor_new(Fl_Wayland_Screen_Driver::wl_display, &libdecor_iface);
+    if (!scr_driver->libdecor_context)
+      scr_driver->libdecor_context = libdecor_new(Fl_Wayland_Screen_Driver::wl_display, &libdecor_iface);
     new_window->frame = libdecor_decorate(scr_driver->libdecor_context, new_window->wl_surface,
                                               &libdecor_frame_iface, new_window);
 //fprintf(stderr, "makeWindow: libdecor_decorate=%p pos:%dx%d\n", new_window->frame, pWindow->x(), pWindow->y());
@@ -1046,7 +1047,7 @@ Fl_X *Fl_Wayland_Window_Driver::makeWindow()
 
   } else if (pWindow->parent()) { // for subwindows (GL or non-GL)
     new_window->kind = SUBWINDOW;
-    struct wld_window *parent = fl_xid(pWindow->window());
+    struct wld_window *parent = fl_wl_xid(pWindow->window());
     new_window->subsurface = wl_subcompositor_get_subsurface(scr_driver->wl_subcompositor, new_window->wl_surface, parent->wl_surface);
 //fprintf(stderr, "makeWindow: subsurface=%p\n", new_window->subsurface);
     float f = Fl::screen_scale(pWindow->top_window()->screen_num());
@@ -1073,9 +1074,9 @@ Fl_X *Fl_Wayland_Window_Driver::makeWindow()
   }
 
   Fl_Window *old_first = Fl::first_window();
-  Window first_xid = (old_first ? fl_xid(old_first) : NULL);
+  struct wld_window * first_xid = (old_first ? fl_wl_xid(old_first) : NULL);
   Fl_X *xp = new Fl_X;
-  xp->xid = new_window;
+  xp->xid = (fl_uintptr_t)new_window;
   other_xid = 0;
   xp->w = pWindow;
   i(xp);
@@ -1244,7 +1245,7 @@ int Fl_Wayland_Window_Driver::set_cursor(Fl_Cursor c) {
 
 void Fl_Wayland_Window_Driver::update_scale()
 {
-  struct wld_window *window = fl_xid(pWindow);
+  struct wld_window *window = fl_wl_xid(pWindow);
   int scale = 0;
   Fl_Wayland_Window_Driver::window_output *window_output;
 
@@ -1265,7 +1266,7 @@ void Fl_Wayland_Window_Driver::update_scale()
 void Fl_Wayland_Window_Driver::use_border() {
   if (!shown() || pWindow->parent()) return;
   pWindow->wait_for_expose(); // useful for border(0) just after show()
-  struct libdecor_frame *frame = fl_xid(pWindow)->frame;
+  struct libdecor_frame *frame = fl_wl_xid(pWindow)->frame;
   if (frame && Fl_Wayland_Screen_Driver::compositor != Fl_Wayland_Screen_Driver::KDE) {
     libdecor_frame_set_visibility(frame, pWindow->border());
     pWindow->redraw();
@@ -1310,10 +1311,10 @@ void Fl_Wayland_Window_Driver::fullscreen_off(int X, int Y, int W, int H) {
 
 
 void Fl_Wayland_Window_Driver::label(const char *name, const char *iname) {
-  if (shown() && !parent() && fl_xid(pWindow)->kind == DECORATED) {
+  if (shown() && !parent() && fl_wl_xid(pWindow)->kind == DECORATED) {
     if (!name) name = "";
     if (!iname) iname = fl_filename_name(name);
-    libdecor_frame_set_title(fl_xid(pWindow)->frame, name);
+    libdecor_frame_set_title(fl_wl_xid(pWindow)->frame, name);
   }
 }
 
@@ -1322,7 +1323,7 @@ int Fl_Wayland_Window_Driver::set_cursor(const Fl_RGB_Image *rgb, int hotx, int
 // build a new wl_cursor and its image
   struct wl_cursor *new_cursor = (struct wl_cursor*)malloc(sizeof(struct wl_cursor));
   struct cursor_image *new_image = (struct cursor_image*)calloc(1, sizeof(struct cursor_image));
-  int scale = fl_xid(pWindow)->scale;
+  int scale = fl_wl_xid(pWindow)->scale;
   new_image->image.width = rgb->w() * scale;
   new_image->image.height = rgb->h() * scale;
   new_image->image.hotspot_x = hotx * scale;
@@ -1338,7 +1339,7 @@ int Fl_Wayland_Window_Driver::set_cursor(const Fl_RGB_Image *rgb, int hotx, int
   new_cursor->images[0] = (struct wl_cursor_image*)new_image;
   new_cursor->name = strdup("custom cursor");
   // draw the rgb image to the cursor's drawing buffer
-  Fl_Image_Surface *img_surf = new Fl_Image_Surface(new_image->image.width, new_image->image.height, 0, offscreen);
+  Fl_Image_Surface *img_surf = new Fl_Image_Surface(new_image->image.width, new_image->image.height, 0, (Fl_Offscreen)offscreen);
   Fl_Surface_Device::push_current(img_surf);
   Fl_Wayland_Graphics_Driver *driver = (Fl_Wayland_Graphics_Driver*)img_surf->driver();
   cairo_scale(driver->cr(), scale, scale);
@@ -1361,7 +1362,7 @@ int Fl_Wayland_Window_Driver::set_cursor(const Fl_RGB_Image *rgb, int hotx, int
 // This is only to fix a bug in libdecor where what libdecor_frame_set_min_content_size()
 // does is often destroyed by libdecor-cairo.
 static void delayed_minsize(Fl_Window *win) {
-  struct wld_window *wl_win = fl_xid(win);
+  struct wld_window *wl_win = fl_wl_xid(win);
   Fl_Window_Driver *driver = Fl_Window_Driver::driver(win);
   if (wl_win->kind == Fl_Wayland_Window_Driver::DECORATED) {
     float f = Fl::screen_scale(win->screen_num());
@@ -1377,7 +1378,7 @@ static void delayed_minsize(Fl_Window *win) {
 
 
 void Fl_Wayland_Window_Driver::resize(int X, int Y, int W, int H) {
-  struct wld_window *fl_win = fl_xid(pWindow);
+  struct wld_window *fl_win = fl_wl_xid(pWindow);
   if (fl_win && fl_win->kind == DECORATED && !xdg_toplevel()) {
     pWindow->wait_for_expose();
   }
@@ -1448,7 +1449,7 @@ void Fl_Wayland_Window_Driver::resize(int X, int Y, int W, int H) {
 }
 
 void Fl_Wayland_Window_Driver::reposition_menu_window(int x, int y) {
-  Window xid_menu = fl_xid(pWindow);
+  struct wld_window * xid_menu = fl_wl_xid(pWindow);
   if (y == pWindow->y() && y >= 0) return;
   int true_y = y;
   int y_offset = 0;
@@ -1468,7 +1469,7 @@ void Fl_Wayland_Window_Driver::reposition_menu_window(int x, int y) {
   xid_menu->xdg_surface = xdg_wm_base_get_xdg_surface(scr_driver->xdg_wm_base, xid_menu->wl_surface);
   xdg_surface_add_listener(xid_menu->xdg_surface, &xdg_surface_listener, xid_menu);
   struct xdg_positioner *positioner = xdg_wm_base_create_positioner(scr_driver->xdg_wm_base);
-  Window parent_xid = fl_xid(Fl_Window_Driver::menu_parent());
+  struct wld_window * parent_xid = fl_wl_xid(Fl_Window_Driver::menu_parent());
   float f = Fl::screen_scale(Fl_Window_Driver::menu_parent()->screen_num());
   int popup_x = x * f, popup_y = y * f;
   if (parent_xid->kind == DECORATED)
@@ -1504,7 +1505,7 @@ void Fl_Wayland_Window_Driver::menu_window_area(int &X, int &Y, int &W, int &H,
 }
 
 
-struct wl_surface *fl_wl_surface(Window xid) {
+FL_EXPORT struct wl_surface *fl_wl_surface(struct wld_window *xid) {
   return xid->wl_surface;
 }
 
@@ -1514,8 +1515,13 @@ cairo_t *fl_wl_cairo() {
 }
 
 
-struct wl_display *fl_wl_display() {
-  return Fl_Wayland_Screen_Driver::wl_display;
+Fl_Window *fl_wl_find(struct wld_window *xid) {
+  return Fl_Window_Driver::find((fl_uintptr_t)xid);
+}
+
+
+struct wld_window *fl_wl_xid(const Fl_Window *win) {
+  return (struct wld_window *)Fl_Window_Driver::xid(win);
 }
 
 
diff --git src/drivers/Wayland/fl_wayland_clipboard_dnd.cxx src/drivers/Wayland/fl_wayland_clipboard_dnd.cxx
index 07bcd3e..2dca849 100644
--- src/drivers/Wayland/fl_wayland_clipboard_dnd.cxx
+++ src/drivers/Wayland/fl_wayland_clipboard_dnd.cxx
@@ -34,7 +34,6 @@
 
 ////////////////////////////////////////////////////////////////
 // Code used for copy and paste and DnD into the program:
-//static Window fl_dnd_source_window;
 
 static char *fl_selection_buffer[2];
 static int fl_selection_length[2];
@@ -99,7 +98,7 @@ static void data_source_handle_cancelled(void *data, struct wl_data_source *sour
   wl_data_source_destroy(source);
   doing_dnd = false;
   if (dnd_icon) {
-    Fl_Offscreen off = (Fl_Offscreen)wl_surface_get_user_data(dnd_icon);
+    struct fl_wld_buffer * off = (struct fl_wld_buffer *)wl_surface_get_user_data(dnd_icon);
     struct wld_window fake_window;
     fake_window.buffer = off;
     Fl_Wayland_Graphics_Driver::buffer_release(&fake_window);
@@ -190,9 +189,9 @@ static Fl_Offscreen offscreen_from_text(const char *text, int scale) {
   if (width > 300*scale) width = 300*scale;
   height = nl * fl_height() + 3;
   width += 6;
-  Fl_Offscreen off = Fl_Wayland_Graphics_Driver::create_shm_buffer(width, height);
+  struct fl_wld_buffer * off = Fl_Wayland_Graphics_Driver::create_shm_buffer(width, height);
   memset(off->draw_buffer, 0, off->data_size);
-  Fl_Image_Surface *surf = new Fl_Image_Surface(width, height, 0, off);
+  Fl_Image_Surface *surf = new Fl_Image_Surface(width, height, 0, (Fl_Offscreen)off);
   Fl_Surface_Device::push_current(surf);
   p = text;
   fl_font(FL_HELVETICA, 10 * scale);
@@ -213,7 +212,7 @@ static Fl_Offscreen offscreen_from_text(const char *text, int scale) {
   delete surf;
   cairo_surface_flush( cairo_get_target(off->cairo_) );
   memcpy(off->data, off->draw_buffer, off->data_size);
-  return off;
+  return (Fl_Offscreen)off;
 }
 
 
@@ -226,13 +225,13 @@ int Fl_Wayland_Screen_Driver::dnd(int use_selection) {
   wl_data_source_add_listener(source, &data_source_listener, (void*)0);
   wl_data_source_offer(source, wld_plain_text_clipboard);
   wl_data_source_set_actions(source, WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY);
-  Fl_Offscreen off = NULL;
+  struct fl_wld_buffer * off = NULL;
   int s = 1;
   if (use_selection) {
     // use the text as dragging icon
     Fl_Widget *current = Fl::pushed() ? Fl::pushed() : Fl::first_window();
-    s = fl_xid(current->top_window())->scale;
-    off = offscreen_from_text(fl_selection_buffer[0], s);
+    s = fl_wl_xid(current->top_window())->scale;
+    off = (struct fl_wld_buffer *)offscreen_from_text(fl_selection_buffer[0], s);
     dnd_icon = wl_compositor_create_surface(scr_driver->wl_compositor);
   } else dnd_icon = NULL;
   doing_dnd = true;
@@ -571,7 +570,7 @@ void Fl_Wayland_Screen_Driver::paste(Fl_Widget &receiver, int clipboard, const c
     receiver.handle(FL_PASTE);
   } else if (type == Fl::clipboard_image && clipboard_contains(Fl::clipboard_image)) {
     if (get_clipboard_image()) return;
-    Window xid = fl_xid(receiver.top_window());
+    struct wld_window * xid = fl_wl_xid(receiver.top_window());
     if (xid && xid->scale > 1) {
       Fl_RGB_Image *rgb = (Fl_RGB_Image*)Fl::e_clipboard_data;
       rgb->scale(rgb->data_w() / xid->scale, rgb->data_h() / xid->scale);
diff --git src/drivers/Wayland/fl_wayland_gl_platform_init.cxx src/drivers/Wayland/fl_wayland_gl_platform_init.cxx
index 5a2a78b..f80ee67 100644
--- src/drivers/Wayland/fl_wayland_gl_platform_init.cxx
+++ src/drivers/Wayland/fl_wayland_gl_platform_init.cxx
@@ -16,9 +16,12 @@
 
 
 #include "Fl_Wayland_Gl_Window_Driver.H"
+#include "Fl_Wayland_Screen_Driver.H"
+#include "../X11/Fl_X11_Gl_Window_Driver.H"
 
 
 Fl_Gl_Window_Driver *Fl_Gl_Window_Driver::newGlWindowDriver(Fl_Gl_Window *w)
 {
-  return new Fl_Wayland_Gl_Window_Driver(w);
+  if (Fl_Wayland_Screen_Driver::wl_display) return new Fl_Wayland_Gl_Window_Driver(w);
+  return new Fl_X11_Gl_Window_Driver(w);
 }
diff --git src/drivers/Wayland/fl_wayland_platform_init.cxx src/drivers/Wayland/fl_wayland_platform_init.cxx
index 4500a0f..8c81ab3 100644
--- src/drivers/Wayland/fl_wayland_platform_init.cxx
+++ src/drivers/Wayland/fl_wayland_platform_init.cxx
@@ -22,10 +22,61 @@
 #include "Fl_Wayland_Window_Driver.H"
 #include "Fl_Wayland_Image_Surface_Driver.H"
 
+#include "../Xlib/Fl_Xlib_Copy_Surface_Driver.H"
+#include <cairo-xlib.h>
+#include "../Cairo/Fl_Display_Cairo_Graphics_Driver.H"
+#include "../X11/Fl_X11_Screen_Driver.H"
+#include "../X11/Fl_X11_System_Driver.H"
+#include "../X11/Fl_X11_Window_Driver.H"
+#include "../Xlib/Fl_Xlib_Image_Surface_Driver.H"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+
+void fl_disable_wayland() {
+  if (Fl_Wayland_Screen_Driver::wl_display) {
+    wl_display_disconnect(Fl_Wayland_Screen_Driver::wl_display);
+    Fl_Wayland_Screen_Driver::wl_display = NULL;
+    delete Fl_Screen_Driver::system_driver;
+    Fl_Screen_Driver::system_driver = NULL;
+  }
+  Fl_Wayland_Screen_Driver::wld_disabled = true;
+  Fl::system_driver();
+}
+
 
-Fl_Copy_Surface_Driver *Fl_Copy_Surface_Driver::newCopySurfaceDriver(int w, int h)
+Fl_System_Driver *Fl_System_Driver::newSystemDriver()
 {
-  return new Fl_Wayland_Copy_Surface_Driver(w, h);
+  const char *backend = ::getenv("FLTK_BACKEND");
+  // fprintf(stderr, "FLTK_BACKEND='%s' XDG_RUNTIME_DIR='%s'\n",backend ? backend : "", xdg ? xdg : "");
+  if (backend && strcmp(backend, "wayland") == 0) {
+    Fl_Wayland_Screen_Driver::wl_display = wl_display_connect(NULL);
+    if (!Fl_Wayland_Screen_Driver::wl_display) {
+      fprintf(stderr, "Error: no Wayland connection available, FLTK_BACKEND = '%s'\n", backend);
+      exit(1);
+    }
+    return new Fl_Wayland_System_Driver();
+  }
+  else if (backend && strcmp(backend, "x11") == 0) {
+    return new Fl_X11_System_Driver();
+  }
+  else if (!backend) {
+    if (!Fl_Wayland_Screen_Driver::wld_disabled && ::getenv("XDG_RUNTIME_DIR")) {
+      // env var XDG_RUNTIME_DIR is necessary for wayland
+      // is a Wayland connection available ?
+      Fl_Wayland_Screen_Driver::wl_display = wl_display_connect(NULL);
+      if (Fl_Wayland_Screen_Driver::wl_display) { // Yes, use Wayland drivers
+        // puts("using wayland");
+        return new Fl_Wayland_System_Driver();
+      }
+    }
+    return new Fl_X11_System_Driver();
+  }
+  fprintf(stderr, "Error: unexpected value of FLTK_BACKEND: '%s'\n", backend);
+  exit(1);
+  return NULL;
 }
 
 
@@ -52,32 +103,43 @@ static Fl_Fontdesc built_in_table[] = {  // Pango font names
 FL_EXPORT Fl_Fontdesc *fl_fonts = built_in_table;
 
 
-Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver()
-{
-  fl_graphics_driver = new Fl_Wayland_Graphics_Driver();
+Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver() {
+  if (Fl_Wayland_Screen_Driver::wl_display) {
+    fl_graphics_driver = new Fl_Wayland_Graphics_Driver();
+puts("using Fl_Wayland_Graphics_Driver");
+  } else {
+    fl_graphics_driver = new Fl_Display_Cairo_Graphics_Driver();
+puts("using Fl_Display_Cairo_Graphics_Driver");
+  }
   return fl_graphics_driver;
 }
 
 
-Fl_Screen_Driver *Fl_Screen_Driver::newScreenDriver()
-{
-  return new Fl_Wayland_Screen_Driver();
+Fl_Copy_Surface_Driver *Fl_Copy_Surface_Driver::newCopySurfaceDriver(int w, int h) {
+  if (Fl_Wayland_Screen_Driver::wl_display) return new Fl_Wayland_Copy_Surface_Driver(w, h);
+  return new Fl_Xlib_Copy_Surface_Driver(w, h);
 }
 
 
-Fl_System_Driver *Fl_System_Driver::newSystemDriver()
-{
-  return new Fl_Wayland_System_Driver();
+Fl_Screen_Driver *Fl_Screen_Driver::newScreenDriver() {
+  if (Fl_Wayland_Screen_Driver::wl_display) return new Fl_Wayland_Screen_Driver();
+
+  Fl_X11_Screen_Driver *d = new Fl_X11_Screen_Driver();
+  for (int i = 0;  i < MAX_SCREENS; i++) d->screens[i].scale = 1;
+  d->current_xft_dpi = 0.; // means the value of the Xft.dpi resource is still unknown
+  return d;
 }
 
 
 Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w)
 {
-  return new Fl_Wayland_Window_Driver(w);
+  if (Fl_Wayland_Screen_Driver::wl_display) return new Fl_Wayland_Window_Driver(w);
+  return new Fl_X11_Window_Driver(w);
 }
 
 
 Fl_Image_Surface_Driver *Fl_Image_Surface_Driver::newImageSurfaceDriver(int w, int h, int high_res, Fl_Offscreen off)
 {
-  return new Fl_Wayland_Image_Surface_Driver(w, h, high_res, off);
+  if (Fl_Wayland_Screen_Driver::wl_display) return new Fl_Wayland_Image_Surface_Driver(w, h, high_res, off);
+  return new Fl_Xlib_Image_Surface_Driver(w, h, high_res, off);
 }
diff --git src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.cxx src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.cxx
index cd6e986..7952dfd 100644
--- src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.cxx
+++ src/drivers/WinAPI/Fl_WinAPI_Gl_Window_Driver.cxx
@@ -1,7 +1,7 @@
 //
 // Class Fl_WinAPI_Gl_Window_Driver for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 2021 by Bill Spitzak and others.
+// Copyright 2021-2022 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
@@ -129,8 +129,8 @@ GLContext Fl_WinAPI_Gl_Window_Driver::create_gl_context(Fl_Window* window, const
   Fl_X* i = Fl_X::i(window);
   HDC hdc = Fl_WinAPI_Window_Driver::driver(window)->private_dc;
   if (!hdc) {
-    hdc = Fl_WinAPI_Window_Driver::driver(window)->private_dc = GetDCEx(i->xid, 0, DCX_CACHE);
-    fl_save_dc(i->xid, hdc);
+    hdc = Fl_WinAPI_Window_Driver::driver(window)->private_dc = GetDCEx((HWND)i->xid, 0, DCX_CACHE);
+    fl_save_dc((HWND)i->xid, hdc);
     SetPixelFormat(hdc, ((Fl_WinAPI_Gl_Choice*)g)->pixelformat, (PIXELFORMATDESCRIPTOR*)(&((Fl_WinAPI_Gl_Choice*)g)->pfd));
 #    if USE_COLORMAP
     if (fl_palette) SelectPalette(hdc, fl_palette, FALSE);
@@ -139,7 +139,7 @@ GLContext Fl_WinAPI_Gl_Window_Driver::create_gl_context(Fl_Window* window, const
   GLContext context = layer ? wglCreateLayerContext(hdc, layer) : wglCreateContext(hdc);
   if (context) {
     if (context_list && nContext)
-      wglShareLists(context_list[0], context);
+      wglShareLists((HGLRC)context_list[0], (HGLRC)context);
     add_context(context);
   }
   return context;
@@ -150,7 +150,7 @@ void Fl_WinAPI_Gl_Window_Driver::set_gl_context(Fl_Window* w, GLContext context)
   if (context != cached_context || w != cached_window) {
     cached_context = context;
     cached_window = w;
-    wglMakeCurrent(Fl_WinAPI_Window_Driver::driver(w)->private_dc, context);
+    wglMakeCurrent(Fl_WinAPI_Window_Driver::driver(w)->private_dc, (HGLRC)context);
   }
 }
 
@@ -160,7 +160,7 @@ void Fl_WinAPI_Gl_Window_Driver::delete_gl_context(GLContext context) {
     cached_window = 0;
     wglMakeCurrent(0, 0);
   }
-  wglDeleteContext(context);
+  wglDeleteContext((HGLRC)context);
   del_context(context);
 }
 
@@ -368,4 +368,6 @@ void Fl_WinAPI_Gl_Window_Driver::get_list(Fl_Font_Descriptor *fd, int r) {
 }
 
 
+FL_EXPORT HGLRC fl_win32_glcontext(GLContext rc) { return (HGLRC)rc; }
+
 #endif // HAVE_GL
diff --git src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx
index be9dac6..92f34b9 100644
--- src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx
+++ src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx
@@ -450,7 +450,7 @@ Fl_RGB_Image *Fl_WinAPI_Screen_Driver::read_win_rectangle_unscaled(int X, int Y,
 void Fl_WinAPI_Screen_Driver::offscreen_size(Fl_Offscreen off, int &width, int &height)
 {
   BITMAP bitmap;
-  if ( GetObject(off, sizeof(BITMAP), &bitmap) ) {
+  if ( GetObject((HBITMAP)off, sizeof(BITMAP), &bitmap) ) {
     width = bitmap.bmWidth;
     height = bitmap.bmHeight;
   }
diff --git src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx
index 459143d..5f8c40d 100644
--- src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx
+++ src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx
@@ -317,7 +317,7 @@ void Fl_WinAPI_Window_Driver::flush_double()
      for an Fl_Double_Window.
      */
     HDC sgc = fl_gc;
-    fl_gc = fl_makeDC(other_xid);
+    fl_gc = fl_makeDC((HBITMAP)other_xid);
     int savedc = SaveDC(fl_gc);
     fl_graphics_driver->gc(fl_gc);
     fl_graphics_driver->restore_clip(); // duplicate clip region into new gc
@@ -462,7 +462,7 @@ void Fl_WinAPI_Window_Driver::hide() {
   int count = 0;
   Fl_Window *win, **doit = NULL;
   for (win = Fl::first_window(); win && ip; win = Fl::next_window(win)) {
-    if (win->non_modal() && GetWindow(fl_xid(win), GW_OWNER) == ip->xid) {
+    if (win->non_modal() && GetWindow(fl_xid(win), GW_OWNER) == (HWND)ip->xid) {
       count++;
     }
   }
@@ -470,7 +470,7 @@ void Fl_WinAPI_Window_Driver::hide() {
     doit = new Fl_Window*[count];
     count = 0;
     for (win = Fl::first_window(); win && ip; win = Fl::next_window(win)) {
-      if (win->non_modal() && GetWindow(fl_xid(win), GW_OWNER) == ip->xid) {
+      if (win->non_modal() && GetWindow(fl_xid(win), GW_OWNER) == (HWND)ip->xid) {
         doit[count++] = win;
       }
     }
@@ -485,14 +485,14 @@ void Fl_WinAPI_Window_Driver::hide() {
   // icons(NULL, 0); // free_icons() is called by the Fl_Window destructor
   // this little trick keeps the current clipboard alive, even if we are about
   // to destroy the window that owns the selection.
-  if (GetClipboardOwner()==ip->xid)
+  if (GetClipboardOwner() == (HWND)ip->xid)
     fl_update_clipboard();
   // Make sure we unlink this window from the clipboard chain
-  fl_clipboard_notify_retarget(ip->xid);
+  fl_clipboard_notify_retarget((HWND)ip->xid);
   // Send a message to myself so that I'll get out of the event loop...
-  PostMessage(ip->xid, WM_APP, 0, 0);
-  if (private_dc) fl_release_dc(ip->xid, private_dc);
-  if (ip->xid == fl_window && fl_graphics_driver->gc()) {
+  PostMessage((HWND)ip->xid, WM_APP, 0, 0);
+  if (private_dc) fl_release_dc((HWND)ip->xid, private_dc);
+  if ((HWND)ip->xid == fl_window && fl_graphics_driver->gc()) {
     fl_release_dc(fl_window, (HDC)fl_graphics_driver->gc());
     fl_window = (HWND)-1;
     fl_graphics_driver->gc(0);
@@ -505,11 +505,11 @@ void Fl_WinAPI_Window_Driver::hide() {
 
   // this little trickery seems to avoid the popup window stacking problem
   HWND p = GetForegroundWindow();
-  if (p==GetParent(ip->xid)) {
-    ShowWindow(ip->xid, SW_HIDE);
+  if (p==GetParent((HWND)ip->xid)) {
+    ShowWindow((HWND)ip->xid, SW_HIDE);
     ShowWindow(p, SW_SHOWNA);
   }
-  DestroyWindow(ip->xid);
+  DestroyWindow((HWND)ip->xid);
   // end of fix for STR#3079
   if (count) {
     int ii;
@@ -541,7 +541,7 @@ void Fl_WinAPI_Window_Driver::unmap() {
 #if !defined(FL_DOXYGEN) // FIXME - silence Doxygen warning
 
 void Fl_WinAPI_Window_Driver::make_fullscreen(int X, int Y, int W, int H) {
-  Window xid = fl_xid(pWindow);
+  HWND xid = fl_xid(pWindow);
   int top, bottom, left, right;
   int sx, sy, sw, sh;
 
@@ -589,7 +589,7 @@ void Fl_WinAPI_Window_Driver::fullscreen_off(int X, int Y, int W, int H) {
   // Remove the xid temporarily so that Fl_WinAPI_Window_Driver::fake_X_wm() behaves like it
   // does in Fl_WinAPI_Window_Driver::makeWindow().
   HWND xid = fl_xid(pWindow);
-  Fl_X::i(pWindow)->xid = NULL;
+  Fl_X::i(pWindow)->xid = 0;
   int wx, wy, bt, bx, by;
   switch (fake_X_wm(wx, wy, bt, bx, by)) {
     case 0:
@@ -603,7 +603,7 @@ void Fl_WinAPI_Window_Driver::fullscreen_off(int X, int Y, int W, int H) {
       }
       break;
   }
-  Fl_X::i(pWindow)->xid = xid;
+  Fl_X::i(pWindow)->xid = (fl_uintptr_t)xid;
   // compute window position and size in scaled units
   float s = Fl::screen_driver()->scale(screen_num());
   int scaledX = int(ceil(X*s)), scaledY= int(ceil(Y*s)), scaledW = int(ceil(W*s)), scaledH = int(ceil(H*s));
@@ -712,3 +712,13 @@ void Fl_WinAPI_Window_Driver::resize_after_screen_change(void *data) {
 const Fl_Image* Fl_WinAPI_Window_Driver::shape() {
   return shape_data_ ? shape_data_->shape_ : NULL;
 }
+
+
+HWND fl_win32_xid(const Fl_Window *win) {
+  return (HWND)Fl_Window_Driver::xid(win);
+}
+
+
+Fl_Window *fl_win32_find(HWND xid) {
+  return Fl_Window_Driver::find((fl_uintptr_t)xid);
+}
diff --git src/drivers/X11/Fl_X11_Gl_Window_Driver.cxx src/drivers/X11/Fl_X11_Gl_Window_Driver.cxx
index 9a09275..b85aadd 100644
--- src/drivers/X11/Fl_X11_Gl_Window_Driver.cxx
+++ src/drivers/X11/Fl_X11_Gl_Window_Driver.cxx
@@ -1,7 +1,7 @@
 //
 // Class Fl_X11_Gl_Window_Driver for the Fast Light Tool Kit (FLTK).
 //
-// Copyright 2021 by Bill Spitzak and others.
+// Copyright 2021-2022 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
@@ -21,8 +21,6 @@
 #include "../../Fl_Screen_Driver.H"
 #include "../../Fl_Window_Driver.H"
 #include "Fl_X11_Gl_Window_Driver.H"
-#include "../Xlib/Fl_Font.H"
-#include "../Xlib/Fl_Xlib_Graphics_Driver.H"
 #  include <GL/glx.h>
 #  if ! defined(GLX_VERSION_1_3)
 #    typedef void *GLXFBConfig;
@@ -61,7 +59,7 @@ void Fl_X11_Gl_Window_Driver::gl_bitmap_font(Fl_Font_Descriptor *fl_fontsize) {
    * is not working on this platform. This code might not reliably render glyphs
    * from higher codepoints. */
   if (!fl_fontsize->listbase) {
-#if USE_XFT
+#if USE_XFT && !FLTK_USE_CAIRO
     /* Ideally, for XFT, we need a glXUseXftFont implementation here... But we
      * do not have such a thing. Instead, we try to find a legacy Xlib font that
      * matches the current XFT font and use that.
@@ -288,7 +286,7 @@ GLContext Fl_X11_Gl_Window_Driver::create_gl_context(Fl_Window* window, const Fl
     XSetErrorHandler(oldHandler);
   }
   if (!ctx) { // use OpenGL 1-style context creation
-    ctx = glXCreateContext(fl_display, ((Fl_X11_Gl_Choice*)g)->vis, shared_ctx, true);
+    ctx = glXCreateContext(fl_display, ((Fl_X11_Gl_Choice*)g)->vis, (GLXContext)shared_ctx, true);
   }
   if (ctx)
     add_context(ctx);
@@ -299,7 +297,7 @@ GLContext Fl_X11_Gl_Window_Driver::create_gl_context(Fl_Window* window, const Fl
 GLContext Fl_X11_Gl_Window_Driver::create_gl_context(XVisualInfo *vis) {
   GLContext shared_ctx = 0;
   if (context_list && nContext) shared_ctx = context_list[0];
-  GLContext context = glXCreateContext(fl_display, vis, shared_ctx, 1);
+  GLContext context = glXCreateContext(fl_display, vis, (GLXContext)shared_ctx, 1);
   if (context)
     add_context(context);
   return context;
@@ -309,7 +307,7 @@ void Fl_X11_Gl_Window_Driver::set_gl_context(Fl_Window* w, GLContext context) {
   if (context != cached_context || w != cached_window) {
     cached_context = context;
     cached_window = w;
-    glXMakeCurrent(fl_display, fl_xid(w), context);
+    glXMakeCurrent(fl_display, fl_xid(w), (GLXContext)context);
   }
 }
 
@@ -319,7 +317,7 @@ void Fl_X11_Gl_Window_Driver::delete_gl_context(GLContext context) {
     cached_window = 0;
     glXMakeCurrent(fl_display, 0, 0);
   }
-  glXDestroyContext(fl_display, context);
+  glXDestroyContext(fl_display, (GLXContext)context);
   del_context(context);
 }
 
@@ -394,4 +392,8 @@ void Fl_X11_Gl_Window_Driver::gl_start() {
   glXWaitX();
 }
 
+
+FL_EXPORT GLXContext fl_x11_glcontext(GLContext rc) { return (GLXContext)rc; }
+
+
 #endif // HAVE_GL
diff --git src/drivers/X11/Fl_X11_Screen_Driver.cxx src/drivers/X11/Fl_X11_Screen_Driver.cxx
index b8fdd20..87a9163 100644
--- src/drivers/X11/Fl_X11_Screen_Driver.cxx
+++ src/drivers/X11/Fl_X11_Screen_Driver.cxx
@@ -17,11 +17,9 @@
 
 #include <config.h>
 #include "Fl_X11_Screen_Driver.H"
-#include "../Xlib/Fl_Font.H"
 #include "Fl_X11_Window_Driver.H"
 #include "Fl_X11_System_Driver.H"
 #include "../Posix/Fl_Posix_System_Driver.H"
-#include "../Xlib/Fl_Xlib_Graphics_Driver.H"
 #include <FL/Fl.H>
 #include <FL/platform.H>
 #include <FL/fl_ask.H>
@@ -986,7 +984,7 @@ void Fl_X11_Screen_Driver::offscreen_size(Fl_Offscreen off, int &width, int &hei
   int px, py;
   unsigned w, h, b, d;
   Window root;
-  XGetGeometry(fl_display, off, &root, &px, &py, &w, &h, &b, &d);
+  XGetGeometry(fl_display, (Pixmap)off, &root, &px, &py, &w, &h, &b, &d);
   width = (int)w;
   height = (int)h;
 }
diff --git src/drivers/X11/Fl_X11_Window_Driver.H src/drivers/X11/Fl_X11_Window_Driver.H
index 84b11ad..13c1cf9 100644
--- src/drivers/X11/Fl_X11_Window_Driver.H
+++ src/drivers/X11/Fl_X11_Window_Driver.H
@@ -26,6 +26,11 @@
 #include "../../Fl_Window_Driver.H"
 #include <config.h>
 #include <FL/platform.H> // for Cursor
+
+#if FLTK_USE_CAIRO
+typedef struct _cairo cairo_t;
+#endif // FLTK_USE_CAIRO
+
 class Fl_Bitmap;
 
 /*
@@ -71,6 +76,9 @@ private:
   int screen_num_;
   void screen_num(int n) { screen_num_ = n; }
 #endif // USE_XFT
+#if FLTK_USE_CAIRO
+  cairo_t *cairo_;
+#endif // FLTK_USE_CAIRO
   void decorated_win_size(int &w, int &h);
   void combine_mask();
   void shape_bitmap_(Fl_Image* b);
diff --git src/drivers/X11/Fl_X11_Window_Driver.cxx src/drivers/X11/Fl_X11_Window_Driver.cxx
index ed9dd8f..a530290 100644
--- src/drivers/X11/Fl_X11_Window_Driver.cxx
+++ src/drivers/X11/Fl_X11_Window_Driver.cxx
@@ -18,9 +18,13 @@
 #include <config.h>
 #include "Fl_X11_Window_Driver.H"
 #include "Fl_X11_Screen_Driver.H"
-#include "../Xlib/Fl_Xlib_Graphics_Driver.H"
+#if FLTK_USE_CAIRO
+#  include <cairo-xlib.h>
+#  include "../Cairo/Fl_Display_Cairo_Graphics_Driver.H"
+#else
+#  include "../Xlib/Fl_Xlib_Graphics_Driver.H"
+#endif // FLTK_USE_CAIRO
 
-#include "../../Fl_Screen_Driver.H"
 #include <FL/Fl_Overlay_Window.H>
 #include <FL/Fl_Menu_Window.H>
 #include <FL/Fl_Tooltip.H>
@@ -53,6 +57,9 @@ Fl_X11_Window_Driver::Fl_X11_Window_Driver(Fl_Window *win)
 #if USE_XFT
   screen_num_ = -1;
 #endif
+#if FLTK_USE_CAIRO
+  cairo_ = NULL;
+#endif
 }
 
 
@@ -151,9 +158,17 @@ void Fl_X11_Window_Driver::flush_double(int erase_overlay)
   pWindow->make_current(); // make sure fl_gc is non-zero
   Fl_X *i = Fl_X::i(pWindow);
   if (!other_xid) {
-      other_xid = fl_create_offscreen(w(), h());
+    other_xid = fl_create_offscreen(w(), h());
+#if FLTK_USE_CAIRO
+    fl_begin_offscreen(other_xid);
+    cairo_ = ((Fl_Cairo_Graphics_Driver*)fl_graphics_driver)->cr();
+    fl_end_offscreen();
+#endif
     pWindow->clear_damage(FL_DAMAGE_ALL);
   }
+#if FLTK_USE_CAIRO
+  ((Fl_Display_Cairo_Graphics_Driver*)fl_graphics_driver)->set_cairo(cairo_);
+#endif
     if (pWindow->damage() & ~FL_DAMAGE_EXPOSE) {
       fl_clip_region(i->region); i->region = 0;
       fl_window = other_xid;
@@ -176,8 +191,21 @@ void Fl_X11_Window_Driver::flush_overlay()
   int erase_overlay = (pWindow->damage()&FL_DAMAGE_OVERLAY) | (overlay() == pWindow);
   pWindow->clear_damage((uchar)(pWindow->damage()&~FL_DAMAGE_OVERLAY));
   flush_double(erase_overlay);
-  Fl_Overlay_Window *oWindow = pWindow->as_overlay_window();
-  if (overlay() == oWindow) oWindow->draw_overlay();
+  if (overlay() == pWindow) {
+#if FLTK_USE_CAIRO
+    float scale = fl_graphics_driver->scale();
+    int W = pWindow->w() * scale, H = pWindow->h() * scale;
+    cairo_surface_t *s = cairo_xlib_surface_create(fl_display, Fl_X::i(pWindow)->xid, fl_visual->visual, W, H);
+    cairo_t *overlay_cairo = cairo_create(s);
+    cairo_surface_destroy(s);
+    cairo_save(overlay_cairo);
+    ((Fl_Display_Cairo_Graphics_Driver*)fl_graphics_driver)->set_cairo(overlay_cairo);
+#endif
+    pWindow->as_overlay_window()->draw_overlay();
+#if FLTK_USE_CAIRO
+    cairo_destroy(overlay_cairo);
+#endif
+  }
 }
 
 
@@ -373,7 +401,21 @@ void Fl_X11_Window_Driver::make_current() {
   }
   fl_window = fl_xid(pWindow);
   fl_graphics_driver->clip_region(0);
-#if USE_XFT
+
+#if FLTK_USE_CAIRO
+  float scale = Fl::screen_scale(screen_num()); // get the screen scaling factor
+  if (!pWindow->as_double_window()) {
+    if (!cairo_) {
+      int W = pWindow->w() * scale, H = pWindow->h() * scale;
+      cairo_surface_t *s = cairo_xlib_surface_create(fl_display, fl_window, fl_visual->visual, W, H);
+      cairo_ = cairo_create(s);
+      cairo_surface_destroy(s);
+      cairo_save(cairo_);
+    }
+    ((Fl_Display_Cairo_Graphics_Driver*)fl_graphics_driver)->set_cairo(cairo_);
+  }
+  fl_graphics_driver->scale(scale);
+#elif USE_XFT
   ((Fl_Xlib_Graphics_Driver*)fl_graphics_driver)->scale(Fl::screen_driver()->scale(screen_num()));
 #endif
 
@@ -388,10 +430,16 @@ void Fl_X11_Window_Driver::hide() {
   Fl_X* ip = Fl_X::i(pWindow);
   if (hide_common()) return;
   if (ip->region) Fl_Graphics_Driver::default_driver().XDestroyRegion(ip->region);
-# if USE_XFT
+# if USE_XFT && ! FLTK_USE_CAIRO
   Fl_Xlib_Graphics_Driver::destroy_xft_draw(ip->xid);
   screen_num_ = -1;
 # endif
+# if FLTK_USE_CAIRO
+  if (cairo_ && !pWindow->as_double_window()) {
+    cairo_destroy(cairo_);
+    cairo_ = NULL;
+  }
+# endif
   // this test makes sure ip->xid has not been destroyed already
   if (ip->xid) XDestroyWindow(fl_display, ip->xid);
   delete ip;
@@ -504,6 +552,15 @@ const Fl_Image* Fl_X11_Window_Driver::shape() {
   return shape_data_ ? shape_data_->shape_ : NULL;
 }
 
+Fl_Window *fl_x11_find(Window xid) {
+  return Fl_Window_Driver::find((fl_uintptr_t)xid);
+}
+
+Window fl_x11_xid(const Fl_Window *win) {
+  return (Window)Fl_Window_Driver::xid(win);
+}
+
+
 #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};
diff --git src/drivers/X11/fl_X11_platform_init.cxx src/drivers/X11/fl_X11_platform_init.cxx
index 3bcf213..b26dfa4 100644
--- src/drivers/X11/fl_X11_platform_init.cxx
+++ src/drivers/X11/fl_X11_platform_init.cxx
@@ -14,9 +14,14 @@
 //     https://www.fltk.org/bugs.php
 //
 
+#include <config.h>
 #include <FL/platform.H>
 #include "../Xlib/Fl_Xlib_Copy_Surface_Driver.H"
-#include "../Xlib/Fl_Xlib_Graphics_Driver.H"
+#if FLTK_USE_CAIRO
+#  include "../Cairo/Fl_Display_Cairo_Graphics_Driver.H"
+#else
+#  include "../Xlib/Fl_Xlib_Graphics_Driver.H"
+#endif
 #include "Fl_X11_Screen_Driver.H"
 #include "Fl_X11_System_Driver.H"
 #include "Fl_X11_Window_Driver.H"
@@ -127,7 +132,11 @@ FL_EXPORT Fl_Fontdesc* fl_fonts = (Fl_Fontdesc*)built_in_table;
 
 Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver()
 {
+#if FLTK_USE_CAIRO
+  return new Fl_Display_Cairo_Graphics_Driver();
+#else
   return new Fl_Xlib_Graphics_Driver();
+#endif
 }
 
 
diff --git src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.H src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.H
index a0b0db1..e67447b 100644
--- src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.H
+++ src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.H
@@ -19,6 +19,9 @@
 
 #include <FL/Fl_Copy_Surface.H>
 #include <FL/platform.H>
+#if FLTK_USE_CAIRO
+#  include <cairo/cairo.h>
+#endif // FLTK_USE_CAIRO
 
 class Fl_Xlib_Copy_Surface_Driver : public Fl_Copy_Surface_Driver {
   friend class Fl_Copy_Surface_Driver;
@@ -31,6 +34,9 @@ protected:
   void set_current();
   void translate(int x, int y);
   void untranslate();
+#if FLTK_USE_CAIRO
+  cairo_t *cairo_;
+#endif
 };
 
 #endif // FL_XLIB_COPY_SURFACE_DRIVER_H
diff --git src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx
index f87ae55..e4bbe29 100644
--- src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx
+++ src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx
@@ -19,16 +19,35 @@
 #include <FL/Fl.H>
 #include <FL/platform.H>
 #include <FL/fl_draw.H>
-#include "Fl_Xlib_Graphics_Driver.H"
 #include "../X11/Fl_X11_Screen_Driver.H"
+#if FLTK_USE_CAIRO
+#  include <cairo-xlib.h>
+#  include "../Cairo/Fl_Display_Cairo_Graphics_Driver.H"
+#  include <cairo/cairo.h>
+#else
+#  include "Fl_Xlib_Graphics_Driver.H"
+#endif // FLTK_USE_CAIRO
+
 
 
 Fl_Xlib_Copy_Surface_Driver::Fl_Xlib_Copy_Surface_Driver(int w, int h) : Fl_Copy_Surface_Driver(w, h) {
+#if FLTK_USE_CAIRO
+  driver(new Fl_Display_Cairo_Graphics_Driver());
+#else
   driver(new Fl_Xlib_Graphics_Driver());
+#endif
   float s = Fl_Graphics_Driver::default_driver().scale();
-  ((Fl_Xlib_Graphics_Driver*)driver())->scale(s);
+  driver()->scale(s);
   oldwindow = fl_window;
   xid = fl_create_offscreen(w,h);
+#if FLTK_USE_CAIRO
+  cairo_surface_t *surf = cairo_xlib_surface_create(fl_display, xid, fl_visual->visual, w * s, h * s);
+  cairo_ = cairo_create(surf);
+  cairo_surface_destroy(surf);
+  cairo_scale(cairo_, 1/s, 1/s);
+  cairo_save(cairo_);
+  ((Fl_Display_Cairo_Graphics_Driver*)driver())->set_cairo(cairo_);
+#endif
   driver()->push_no_clip();
   fl_window = xid;
   driver()->color(FL_WHITE);
@@ -47,6 +66,9 @@ Fl_Xlib_Copy_Surface_Driver::~Fl_Xlib_Copy_Surface_Driver() {
   Fl_X11_Screen_Driver::copy_image(rgb->array, rgb->w(), rgb->h(), 1);
   delete rgb;
   fl_delete_offscreen(xid);
+#if FLTK_USE_CAIRO
+  cairo_destroy(cairo_);
+#endif
   delete driver();
 }
 
@@ -55,6 +77,9 @@ void Fl_Xlib_Copy_Surface_Driver::set_current() {
   Fl_Surface_Device::set_current();
   oldwindow = fl_window;
   fl_window = xid;
+#if FLTK_USE_CAIRO
+  ((Fl_Display_Cairo_Graphics_Driver*)driver())->set_cairo(cairo_);
+#endif
 }
 
 void Fl_Xlib_Copy_Surface_Driver::end_current() {
@@ -63,10 +88,20 @@ void Fl_Xlib_Copy_Surface_Driver::end_current() {
 }
 
 void Fl_Xlib_Copy_Surface_Driver::translate(int x, int y) {
+#if FLTK_USE_CAIRO
+  cairo_save(cairo_);
+  cairo_translate(cairo_, x, y);
+#else
   ((Fl_Xlib_Graphics_Driver*)driver())->translate_all(x, y);
+#endif
+
 }
 
 
 void Fl_Xlib_Copy_Surface_Driver::untranslate() {
+#if FLTK_USE_CAIRO
+  cairo_restore(cairo_);
+#else
   ((Fl_Xlib_Graphics_Driver*)driver())->untranslate_all();
+#endif
 }
diff --git src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H
index 5440b53..cf2fcac 100644
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H
@@ -76,7 +76,7 @@ protected:
 #endif
   virtual int height_unscaled();
   virtual int descent_unscaled();
-  virtual Region scale_clip(float f);
+  virtual Fl_Region scale_clip(float f);
 #if USE_XFT
   void drawUCS4(const void *str, int n, int x, int y);
 #endif
diff --git src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx
index 13a67f4..4c7b64a 100644
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx
@@ -38,6 +38,8 @@ int Fl_Xlib_Graphics_Driver::fl_overlay = 0;
  */
 GC fl_gc = 0;
 
+GC fl_x11_gc() { return fl_gc; }
+
 Fl_Xlib_Graphics_Driver::Fl_Xlib_Graphics_Driver(void) {
   mask_bitmap_ = NULL;
   short_point = NULL;
@@ -71,14 +73,14 @@ void Fl_Xlib_Graphics_Driver::scale(float f) {
 }
 
 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*scale(), srcy*scale(), w*scale(), h*scale(), (x+offset_x_)*scale(), (y+offset_y_)*scale());
+  XCopyArea(fl_display, (Pixmap)pixmap, fl_window, gc_, srcx*scale(), srcy*scale(), w*scale(), h*scale(), (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;
-  XUnionRectWithRegion(&R, r, r);
+  XUnionRectWithRegion(&R, (Region)r, (Region)r);
 }
 
 void Fl_Xlib_Graphics_Driver::transformed_vertex0(float fx, float fy) {
@@ -144,8 +146,8 @@ void Fl_Xlib_Graphics_Driver::font_name(int num, const char *name) {
 }
 
 
-Region Fl_Xlib_Graphics_Driver::scale_clip(float f) {
-  Region r = rstack[rstackptr];
+Fl_Region Fl_Xlib_Graphics_Driver::scale_clip(float f) {
+  Region r = (Region)rstack[rstackptr];
   if (r == 0 || (f == 1 && offset_x_ == 0 && offset_y_ == 0) ) return 0;
   Region r2 = XCreateRegion();
   for (int i = 0; i < r->numRects; i++) {
@@ -153,7 +155,7 @@ Region Fl_Xlib_Graphics_Driver::scale_clip(float f) {
     int y = floor(r->rects[i].y1 + offset_y_, f);
     int w = floor((r->rects[i].x2 + offset_x_) , f) - x;
     int h = floor((r->rects[i].y2 + offset_y_) , f) - y;
-    Region R = XRectangleRegion(x, y, w, h);
+    Region R = (Region)XRectangleRegion(x, y, w, h);
     XUnionRegion(R, r2, r2);
     ::XDestroyRegion(R);
   }
diff --git src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx
index 1771188..3a4817b 100644
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx
@@ -720,7 +720,7 @@ void Fl_Xlib_Graphics_Driver::draw_unscaled(const char *str, int n, int x, int y
   else //if (draw_window != fl_window)
     XftDrawChange(draw_, draw_window = fl_window);
 
-  Region region = fl_clip_region();
+  Region region = (Region)fl_clip_region();
   if (!(region && XEmptyRegion(region))) {
     XftDrawSetClip(draw_, region);
 
@@ -756,7 +756,7 @@ void Fl_Xlib_Graphics_Driver::drawUCS4(const void *str, int n, int x, int y) {
   else //if (draw_window != fl_window)
     XftDrawChange(draw_, draw_window = fl_window);
 
-  Region region = fl_clip_region();
+  Region region = (Region)fl_clip_region();
   if (region && XEmptyRegion(region)) return;
   XftDrawSetClip(draw_, region);
 
@@ -1192,7 +1192,7 @@ static void fl_pango_layout_get_pixel_extents(PangoLayout *layout, int &dx, int
 
 void Fl_Xlib_Graphics_Driver::do_draw(int from_right, const char *str, int n, int x, int y) {
   if (!fl_display || n == 0) return;
-  Region region = clip_region();
+  Region region = (Region)clip_region();
   if (region && XEmptyRegion(region)) return;
   if (!playout_) context();
 
diff --git src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx
index d57e5b0..ba098c3 100644
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx
@@ -718,8 +718,8 @@ void Fl_Xlib_Graphics_Driver::cache(Fl_RGB_Image *img) {
   if (depth == 1 || depth == 3) {
     surface = new Fl_Image_Surface(img->data_w(), img->data_h());
   } else if (fl_can_do_alpha_blending()) {
-    Fl_Offscreen pixmap = XCreatePixmap(fl_display, RootWindow(fl_display, fl_screen), img->data_w(), img->data_h(), 32);
-    surface = new Fl_Image_Surface(img->data_w(), img->data_h(), 0, pixmap);
+    Pixmap pixmap = XCreatePixmap(fl_display, RootWindow(fl_display, fl_screen), img->data_w(), img->data_h(), 32);
+    surface = new Fl_Image_Surface(img->data_w(), img->data_h(), 0, (Fl_Offscreen)pixmap);
     depth |= FL_IMAGE_WITH_ALPHA;
   } else {
     *Fl_Graphics_Driver::id(img) = 0;
@@ -806,14 +806,14 @@ int Fl_Xlib_Graphics_Driver::scale_and_render_pixmap(Fl_Offscreen pixmap, int de
   static XRenderPictFormat *fmt24 = XRenderFindStandardFormat(fl_display, PictStandardRGB24);
   static XRenderPictFormat *fmt32 = XRenderFindStandardFormat(fl_display, PictStandardARGB32);
   static XRenderPictFormat *dstfmt = XRenderFindVisualFormat(fl_display, fl_visual->visual);
-  Picture src = XRenderCreatePicture(fl_display, pixmap, has_alpha ?fmt32:fmt24, 0, &srcattr);
+  Picture src = XRenderCreatePicture(fl_display, (Pixmap)pixmap, has_alpha ?fmt32:fmt24, 0, &srcattr);
   Picture dst = XRenderCreatePicture(fl_display, fl_window, dstfmt, 0, &srcattr);
   if (!src || !dst) {
     fprintf(stderr, "Failed to create Render pictures (%lu %lu)\n", src, dst);
     return 0;
   }
   Fl_Region r = scale_clip(scale());
-  const Fl_Region clipr = clip_region();
+  const Region clipr = (Region)clip_region();
   if (clipr)
     XRenderSetPictureClipRegion(fl_display, dst, clipr);
   unscale_clip(r);
@@ -849,7 +849,7 @@ int Fl_Xlib_Graphics_Driver::scale_and_render_pixmap(Fl_Offscreen pixmap, int de
 void Fl_Xlib_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uintptr_t &mask_)
 {
   if (id_) {
-    XFreePixmap(fl_display, (Fl_Offscreen)id_);
+    XFreePixmap(fl_display, (Pixmap)id_);
     id_ = 0;
   }
 }
@@ -882,8 +882,8 @@ void Fl_Xlib_Graphics_Driver::draw_fixed(Fl_Pixmap *pxm, int X, int Y, int W, in
       // be done in a single Xlib call for a multi-rectangle clip region. Thus, we
       // process each rectangle of the intersection between the clip region and XYWH.
       // See also STR #3206.
-      Region r = XRectangleRegion(X,Y,W,H);
-      XIntersectRegion(r, clip_region(), r);
+      Region r = (Region)XRectangleRegion(X,Y,W,H);
+      XIntersectRegion(r, (Region)clip_region(), r);
       int X1, Y1, W1, H1;
       for (int i = 0; i < r->numRects; i++) {
         X1 = r->rects[i].x1;
@@ -929,5 +929,5 @@ void Fl_Xlib_Graphics_Driver::cache(Fl_Pixmap *pxm) {
 }
 
 void Fl_Xlib_Graphics_Driver::uncache_pixmap(fl_uintptr_t offscreen) {
-  XFreePixmap(fl_display, (Fl_Offscreen)offscreen);
+  XFreePixmap(fl_display, (Pixmap)offscreen);
 }
diff --git src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx
index a72fe9d..ea24eba 100644
--- src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx
+++ src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx
@@ -194,7 +194,7 @@ int Fl_Xlib_Graphics_Driver::clip_rect(int &x, int &y, int &w, int &h) {
 
 Fl_Region Fl_Xlib_Graphics_Driver::XRectangleRegion(int x, int y, int w, int h) {
   XRectangle R;
-  Fl_Region r = XCreateRegion(); // create an empty region
+  Region r = XCreateRegion();    // create an empty region
   if (clip_rect(x, y, w, h))     // outside valid coordinate space
     return r;                    // empty region
   R.x = x; R.y = y; R.width = w; R.height = h;
@@ -203,7 +203,7 @@ Fl_Region Fl_Xlib_Graphics_Driver::XRectangleRegion(int x, int y, int w, int h)
 }
 
 void Fl_Xlib_Graphics_Driver::XDestroyRegion(Fl_Region r) {
-  ::XDestroyRegion(r);
+  ::XDestroyRegion((Region)r);
 }
 
 // --- line and polygon drawing
@@ -312,12 +312,12 @@ void Fl_Xlib_Graphics_Driver::draw_clipped_line(int x1, int y1, int x2, int y2)
 // --- clipping
 
 void Fl_Xlib_Graphics_Driver::push_clip(int x, int y, int w, int h) {
-  Fl_Region r;
+  Region r;
   if (w > 0 && h > 0) {
-    r = XRectangleRegion(x, y, w, h); // does X coordinate clipping
-    Fl_Region current = rstack[rstackptr];
+    r = (Region)XRectangleRegion(x, y, w, h); // does X coordinate clipping
+    Region current = (Region)rstack[rstackptr];
     if (current) {
-      Fl_Region temp = XCreateRegion();
+      Region temp = XCreateRegion();
       XIntersectRegion(current, r, temp);
       XDestroyRegion(r);
       r = temp;
@@ -337,7 +337,7 @@ int Fl_Xlib_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y
     W = H = 0;
     return 2;
   }
-  Fl_Region r = rstack[rstackptr];
+  Region r = (Region)rstack[rstackptr];
   if (!r) { // no clipping region
     if (X != x || Y != y || W != w || H != h) // pre-clipped
       return 1; // partially outside, region differs
@@ -352,8 +352,8 @@ int Fl_Xlib_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y
     default: // partial:
       break;
   }
-  Fl_Region rr = XRectangleRegion(X, Y, W, H);
-  Fl_Region temp = XCreateRegion();
+  Region rr = (Region)XRectangleRegion(X, Y, W, H);
+  Region temp = XCreateRegion();
   XIntersectRegion(r, rr, temp);
   XRectangle rect;
   XClipBox(temp, &rect);
@@ -365,7 +365,7 @@ int Fl_Xlib_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y
 
 int Fl_Xlib_Graphics_Driver::not_clipped(int x, int y, int w, int h) {
   if (x+w <= 0 || y+h <= 0) return 0;
-  Fl_Region r = rstack[rstackptr];
+  Region r = (Region)rstack[rstackptr];
   if (!r) return 1;
   // get rid of coordinates outside the 16-bit range the X calls take.
   if (clip_rect(x,y,w,h)) return 0;     // clipped
@@ -375,10 +375,10 @@ int Fl_Xlib_Graphics_Driver::not_clipped(int x, int y, int w, int h) {
 void Fl_Xlib_Graphics_Driver::restore_clip() {
   fl_clip_state_number++;
   if (gc_) {
-    Region r = rstack[rstackptr];
+    Region r = (Region)rstack[rstackptr];
     if (r) {
-      Region r2 = scale_clip(scale());
-      XSetRegion(fl_display, gc_, rstack[rstackptr]);
+      Region r2 = (Region)scale_clip(scale());
+      XSetRegion(fl_display, gc_, (Region)rstack[rstackptr]);
       unscale_clip(r2);
     }
     else XSetClipMask(fl_display, gc_, 0);
diff --git src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.H src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.H
index b7cb480..3f8ecda 100644
--- src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.H
+++ src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.H
@@ -18,6 +18,9 @@
 #define FL_XLIB_IMAGE_SURFACE_DRIVER_H
 
 #include <FL/Fl_Image_Surface.H>
+#if FLTK_USE_CAIRO
+# include <cairo/cairo.h>
+#endif // FLTK_USE_CAIRO
 
 class Fl_Xlib_Image_Surface_Driver : public Fl_Image_Surface_Driver {
   virtual void end_current();
@@ -29,6 +32,9 @@ public:
   void translate(int x, int y);
   void untranslate();
   Fl_RGB_Image *image();
+#if FLTK_USE_CAIRO
+  cairo_t *cairo_;
+#endif
 };
 
 #endif // FL_XLIB_IMAGE_SURFACE_DRIVER_H
diff --git src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx
index e1a33c7..240ced6 100644
--- src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx
+++ src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx
@@ -14,28 +14,47 @@
 //     https://www.fltk.org/bugs.php
 //
 
-#include "Fl_Xlib_Graphics_Driver.H"
+#include <FL/platform.H>
 #include "Fl_Xlib_Image_Surface_Driver.H"
 #include "../../Fl_Screen_Driver.H"
+#if FLTK_USE_CAIRO
+#  include <cairo-xlib.h>
+#  include "../Cairo/Fl_Display_Cairo_Graphics_Driver.H"
+#else
+#  include "Fl_Xlib_Graphics_Driver.H"
+#endif // FLTK_USE_CAIRO
+
 
 
 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();
+    d =  Fl_Graphics_Driver::default_driver().scale();
     if (d != 1 && high_res) {
       w = int(w*d);
       h = int(h*d);
     }
-    offscreen = XCreatePixmap(fl_display, RootWindow(fl_display, fl_screen), w, h, fl_visual->depth);
+    offscreen = (Fl_Offscreen)XCreatePixmap(fl_display, RootWindow(fl_display, fl_screen), w, h, fl_visual->depth);
   }
+#if FLTK_USE_CAIRO
+  driver(new Fl_Display_Cairo_Graphics_Driver());
+  cairo_surface_t *s = cairo_xlib_surface_create(fl_display, offscreen, fl_visual->visual, w, h);
+  cairo_ = cairo_create(s);
+  cairo_surface_destroy(s);
+  cairo_save(cairo_);
+  ((Fl_Display_Cairo_Graphics_Driver*)driver())->set_cairo(cairo_);
+#else
   driver(new Fl_Xlib_Graphics_Driver());
-  if (d != 1 && high_res) ((Fl_Xlib_Graphics_Driver*)driver())->scale(d);
+#endif
+  if (d != 1 && high_res) driver()->scale(d);
 }
 
 Fl_Xlib_Image_Surface_Driver::~Fl_Xlib_Image_Surface_Driver() {
-  if (offscreen && !external_offscreen) XFreePixmap(fl_display, offscreen);
+#if FLTK_USE_CAIRO
+  cairo_destroy(cairo_);
+#endif
+  if (offscreen && !external_offscreen) XFreePixmap(fl_display, (Pixmap)offscreen);
   delete driver();
 }
 
@@ -43,14 +62,26 @@ void Fl_Xlib_Image_Surface_Driver::set_current() {
   Fl_Surface_Device::set_current();
   pre_window = fl_window;
   fl_window = offscreen;
+#if FLTK_USE_CAIRO
+  ((Fl_Display_Cairo_Graphics_Driver*)driver())->set_cairo(cairo_);
+#endif
 }
 
 void Fl_Xlib_Image_Surface_Driver::translate(int x, int y) {
+#if FLTK_USE_CAIRO
+  cairo_save(cairo_);
+  cairo_translate(cairo_, x, y);
+#else
   ((Fl_Xlib_Graphics_Driver*)driver())->translate_all(x, y);
+#endif
 }
 
 void Fl_Xlib_Image_Surface_Driver::untranslate() {
+#if FLTK_USE_CAIRO
+  cairo_restore(cairo_);
+#else
   ((Fl_Xlib_Graphics_Driver*)driver())->untranslate_all();
+#endif
 }
 
 Fl_RGB_Image* Fl_Xlib_Image_Surface_Driver::image()
diff --git src/filename_isdir.cxx src/filename_isdir.cxx
index 47e1de5..f19e464 100644
--- src/filename_isdir.cxx
+++ src/filename_isdir.cxx
@@ -20,6 +20,7 @@
 #include "Fl_System_Driver.H"
 #include <FL/filename.H>
 #include <FL/Fl.H>
+#include <sys/stat.h>
 
 /**
    Determines if a file exists and is a directory from its filename.
diff --git src/fl_read_image.cxx src/fl_read_image.cxx
index 129aeaa..0d5f7ec 100644
--- src/fl_read_image.cxx
+++ src/fl_read_image.cxx
@@ -40,7 +40,7 @@
 uchar *fl_read_image(uchar *p, int X, int Y, int w, int h, int alpha) {
   uchar *image_data = NULL;
   Fl_RGB_Image *img;
-  if (fl_find(fl_window) == 0) { // read from off_screen buffer
+  if (Fl_Surface_Device::surface()->as_image_surface()) { // read from off_screen buffer
     img = Fl::screen_driver()->read_win_rectangle(X, Y, w, h, 0);
     if (!img) {
       return NULL;
diff --git src/fl_utf8.cxx src/fl_utf8.cxx
index efb7fa5..b780120 100644
--- src/fl_utf8.cxx
+++ src/fl_utf8.cxx
@@ -23,6 +23,7 @@
 #include <FL/fl_utf8.h>
 #include "utf8_internal.h"
 
+#include <sys/stat.h>
 #include <string.h>
 #include <stdlib.h>
 
Direct Link to Message ]
 
     
Previous Message ]Next Message ]
 
 

Comments are owned by the poster. All other content is copyright 1998-2024 by Bill Spitzak and others. This project is hosted by The FLTK Team. Please report site problems to 'erco@seriss.com'.