Merge branch 'x0-xdesktop-initial-cursor' of https://github.com/x11clone/x11clone
diff --git a/README.txt b/README.txt
index 46dac3a..167a940 100644
--- a/README.txt
+++ b/README.txt
@@ -34,6 +34,7 @@
         Copyright (C) 2009-2011 D. R. Commander
         Copyright (C) 2009-2011 Pierre Ossman for Cendio AB
         Copyright (C) 2004, 2009-2011 Red Hat, Inc.
+        Copyright (C) 2017 Peter Astrand for Cendio AB
         Copyright (C) 2009-2017 TigerVNC Team
         All Rights Reserved.
 
diff --git a/common/network/Socket.h b/common/network/Socket.h
index 874a59c..7a30cac 100644
--- a/common/network/Socket.h
+++ b/common/network/Socket.h
@@ -50,6 +50,7 @@
     // if shutdown() is overridden then the override MUST call on to here
     virtual void shutdown() {isShutdown_ = true;}
     bool isShutdown() const {return isShutdown_;}
+    virtual bool cork(bool enable) = 0;
 
     // information about this end of the socket
     virtual int getMyPort() = 0;
diff --git a/common/network/TcpSocket.cxx b/common/network/TcpSocket.cxx
index cf03c10..9603c38 100644
--- a/common/network/TcpSocket.cxx
+++ b/common/network/TcpSocket.cxx
@@ -349,12 +349,12 @@
   return true;
 }
 
-bool TcpSocket::cork(int sock, bool enable) {
+bool TcpSocket::cork(bool enable) {
 #ifndef TCP_CORK
   return false;
 #else
   int one = enable ? 1 : 0;
-  if (setsockopt(sock, IPPROTO_TCP, TCP_CORK, (char *)&one, sizeof(one)) < 0)
+  if (setsockopt(getFd(), IPPROTO_TCP, TCP_CORK, (char *)&one, sizeof(one)) < 0)
     return false;
   return true;
 #endif
diff --git a/common/network/TcpSocket.h b/common/network/TcpSocket.h
index a97e683..c1b142f 100644
--- a/common/network/TcpSocket.h
+++ b/common/network/TcpSocket.h
@@ -62,9 +62,9 @@
     virtual bool sameMachine();
 
     virtual void shutdown();
+    virtual bool cork(bool enable);
 
     static bool enableNagles(int sock, bool enable);
-    static bool cork(int sock, bool enable);
     static bool isListening(int sock);
     static int getSockPort(int sock);
   private:
diff --git a/common/rdr/FdOutStream.cxx b/common/rdr/FdOutStream.cxx
index 29e864f..8fe9df9 100644
--- a/common/rdr/FdOutStream.cxx
+++ b/common/rdr/FdOutStream.cxx
@@ -1,5 +1,6 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
  * Copyright 2011 Pierre Ossman for Cendio AB
+ * Copyright 2017 Peter Astrand <astrand@cendio.se> for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -34,6 +35,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 #include <sys/time.h>
+#include <sys/socket.h>
 #endif
 
 /* Old systems have select() in sys/time.h */
@@ -193,7 +195,14 @@
     return 0;
 
   do {
-    n = ::write(fd, data, length);
+    // select only guarantees that you can write SO_SNDLOWAT without
+    // blocking, which is normally 1. Use MSG_DONTWAIT to avoid
+    // blocking, when possible.
+#ifndef MSG_DONTWAIT
+    n = ::send(fd, (const char*)data, length, 0);
+#else
+    n = ::send(fd, (const char*)data, length, MSG_DONTWAIT);
+#endif
   } while (n < 0 && (errno == EINTR));
 
   if (n < 0)
diff --git a/common/rfb/Configuration.cxx b/common/rfb/Configuration.cxx
index a5c2302..418a0c9 100644
--- a/common/rfb/Configuration.cxx
+++ b/common/rfb/Configuration.cxx
@@ -1,5 +1,6 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
  * Copyright 2004-2005 Cendio AB.
+ * Copyright 2017 Peter Astrand <astrand@cendio.se> for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -166,6 +167,23 @@
 }
 
 
+bool Configuration::remove(const char* param) {
+  VoidParameter *current = head;
+  VoidParameter **prevnext = &head;
+
+  while (current) {
+    if (strcasecmp(current->getName(), param) == 0) {
+      *prevnext = current->_next;
+      return true;
+    }
+    prevnext = &current->_next;
+    current = current->_next;
+  }
+
+  return false;
+}
+
+
 // -=- VoidParameter
 
 VoidParameter::VoidParameter(const char* name_, const char* desc_,
diff --git a/common/rfb/Configuration.h b/common/rfb/Configuration.h
index d319915..6197317 100644
--- a/common/rfb/Configuration.h
+++ b/common/rfb/Configuration.h
@@ -80,6 +80,9 @@
     // - List the parameters of this Configuration group
     void list(int width=79, int nameWidth=10);
 
+    // - Remove a parameter from this Configuration group
+    bool remove(const char* param);
+
     // - readFromFile
     //   Read configuration parameters from the specified file.
     void readFromFile(const char* filename);
@@ -116,6 +119,9 @@
     static void listParams(int width=79, int nameWidth=10) {
       global()->list(width, nameWidth);
     }
+    static bool removeParam(const char* param) {
+      return global()->remove(param);
+    }
 
   private:
     friend class VoidParameter;
diff --git a/common/rfb/Timer.cxx b/common/rfb/Timer.cxx
index efae36e..71887a0 100644
--- a/common/rfb/Timer.cxx
+++ b/common/rfb/Timer.cxx
@@ -26,11 +26,6 @@
 #include <rfb/util.h>
 #include <rfb/LogWriter.h>
 
-// XXX Lynx/OS 2.3: proto for gettimeofday()
-#ifdef Lynx
-#include <sys/proto.h>
-#endif
-
 using namespace rfb;
 
 #ifndef __NO_DEFINE_VLOG__
diff --git a/common/rfb/VNCSConnectionST.cxx b/common/rfb/VNCSConnectionST.cxx
index 9e58657..0e97a78 100644
--- a/common/rfb/VNCSConnectionST.cxx
+++ b/common/rfb/VNCSConnectionST.cxx
@@ -168,7 +168,7 @@
 
     // Get the underlying TCP layer to build large packets if we send
     // multiple small responses.
-    network::TcpSocket::cork(sock->getFd(), true);
+    sock->cork(true);
 
     while (getInStream()->checkNoWait(1)) {
       if (pendingSyncFence) {
@@ -185,7 +185,7 @@
     }
 
     // Flush out everything in case we go idle after this.
-    network::TcpSocket::cork(sock->getFd(), false);
+    sock->cork(false);
 
     inProcessMessages = false;
 
@@ -1094,7 +1094,7 @@
   // mode, we will also have small fence messages around the update. We
   // need to aggregate these in order to not clog up TCP's congestion
   // window.
-  network::TcpSocket::cork(sock->getFd(), true);
+  sock->cork(true);
 
   // First take care of any updates that cannot contain framebuffer data
   // changes.
@@ -1103,7 +1103,7 @@
   // Then real data (if possible)
   writeDataUpdate();
 
-  network::TcpSocket::cork(sock->getFd(), false);
+  sock->cork(false);
 }
 
 void VNCSConnectionST::writeNoDataUpdate()
diff --git a/unix/tx/TXDialog.h b/unix/tx/TXDialog.h
index 7a52f92..28876e7 100644
--- a/unix/tx/TXDialog.h
+++ b/unix/tx/TXDialog.h
@@ -31,11 +31,6 @@
 #include "TXWindow.h"
 #include <errno.h>
 
-// XXX Lynx/OS 2.3: protos for bzero(), select()
-#ifdef Lynx
-#include <sys/proto.h>
-#endif
-
 class TXDialog : public TXWindow, public TXDeleteWindowCallback {
 public:
   TXDialog(Display* dpy, int width, int height, const char* name,
diff --git a/unix/x0vncserver/CMakeLists.txt b/unix/x0vncserver/CMakeLists.txt
index 5831c4d..5930e32 100644
--- a/unix/x0vncserver/CMakeLists.txt
+++ b/unix/x0vncserver/CMakeLists.txt
@@ -14,6 +14,7 @@
   qnum_to_xorgkbd.c
   x0vncserver.cxx
   XPixelBuffer.cxx
+  XDesktop.cxx
   ../vncconfig/QueryConnectDialog.cxx
 )
 
diff --git a/unix/x0vncserver/Geometry.cxx b/unix/x0vncserver/Geometry.cxx
index adc72c3..48c1842 100644
--- a/unix/x0vncserver/Geometry.cxx
+++ b/unix/x0vncserver/Geometry.cxx
@@ -23,6 +23,8 @@
 #include <rfb/LogWriter.h>
 #include <x0vncserver/Geometry.h>
 
+using namespace rfb;
+
 static LogWriter vlog("Geometry");
 
 StringParameter Geometry::m_geometryParam("Geometry",
diff --git a/unix/x0vncserver/Geometry.h b/unix/x0vncserver/Geometry.h
index 9caeeba..98bafb2 100644
--- a/unix/x0vncserver/Geometry.h
+++ b/unix/x0vncserver/Geometry.h
@@ -26,8 +26,6 @@
 #include <rfb/Rect.h>
 #include <rfb/Configuration.h>
 
-using namespace rfb;
-
 class Geometry
 {
 public:
@@ -43,18 +41,18 @@
   int offsetTop() const { return m_rect.tl.y; }
 
   // Return the same information as a Rect structure.
-  const Rect& getRect() const { return m_rect; }
+  const rfb::Rect& getRect() const { return m_rect; }
 
 protected:
   // Parse a string, extract size and coordinates,
   // and return that rectangle clipped to m_rect.
-  Rect parseString(const char *arg) const;
+  rfb::Rect parseString(const char *arg) const;
 
-  static StringParameter m_geometryParam;
+  static rfb::StringParameter m_geometryParam;
 
   int m_fullWidth;
   int m_fullHeight;
-  Rect m_rect;
+  rfb::Rect m_rect;
 };
 
 #endif // __GEOMETRY_H__
diff --git a/unix/x0vncserver/Image.cxx b/unix/x0vncserver/Image.cxx
index f998c6a..ca3d642 100644
--- a/unix/x0vncserver/Image.cxx
+++ b/unix/x0vncserver/Image.cxx
@@ -24,10 +24,8 @@
 #include <stdlib.h>
 #include <sys/types.h>
 
-#ifdef HAVE_MITSHM
 #include <sys/ipc.h>
 #include <sys/shm.h>
-#endif
 
 #include <rfb/LogWriter.h>
 #include <x0vncserver/Image.h>
@@ -196,8 +194,6 @@
   updateRect(src->xim, dst_x, dst_y, src_x, src_y, w, h);
 }
 
-#ifdef HAVE_MITSHM
-
 //
 // ShmImage class implementation.
 //
@@ -323,182 +319,14 @@
   XGetSubImage(dpy, wnd, x, y, w, h, AllPlanes, ZPixmap, xim, dst_x, dst_y);
 }
 
-#ifdef HAVE_READDISPLAY
-
-//
-// IrixOverlayShmImage class implementation.
-//
-
-IrixOverlayShmImage::IrixOverlayShmImage(Display *d)
-  : ShmImage(d), readDisplayBuf(NULL)
-{
-}
-
-IrixOverlayShmImage::IrixOverlayShmImage(Display *d, int width, int height)
-  : ShmImage(d), readDisplayBuf(NULL)
-{
-  Init(width, height);
-}
-
-void IrixOverlayShmImage::Init(int width, int height)
-{
-  // First determine the pixel format used by XReadDisplay.
-  XVisualInfo vinfo;
-  if (!getOverlayVisualInfo(&vinfo))
-    return;
-
-  // Create an SHM image of the same format.
-  ShmImage::Init(width, height, &vinfo);
-  if (xim == NULL)
-    return;
-
-  // FIXME: Check if the extension is available at run time.
-  readDisplayBuf = XShmCreateReadDisplayBuf(dpy, NULL, shminfo, width, height);
-}
-
-bool IrixOverlayShmImage::getOverlayVisualInfo(XVisualInfo *vinfo_ret)
-{
-  // First, get an image in the format returned by XReadDisplay.
-  unsigned long hints = 0, hints_ret;
-  XImage *testImage = XReadDisplay(dpy, DefaultRootWindow(dpy),
-				   0, 0, 8, 8, hints, &hints_ret);
-  if (testImage == NULL)
-    return false;
-
-  // Fill in a template for matching visuals.
-  XVisualInfo tmpl;
-  tmpl.c_class = TrueColor;
-  tmpl.depth = 24;
-  tmpl.red_mask = testImage->red_mask;
-  tmpl.green_mask = testImage->green_mask;
-  tmpl.blue_mask = testImage->blue_mask;
-
-  // List fields in template that make sense.
-  long mask = (VisualClassMask |
-	       VisualRedMaskMask |
-	       VisualGreenMaskMask |
-	       VisualBlueMaskMask);
-
-  // We don't need that image any more.
-  XDestroyImage(testImage);
-
-  // Now, get a list of matching visuals available.
-  int nVisuals;
-  XVisualInfo *vinfo = XGetVisualInfo(dpy, mask, &tmpl, &nVisuals);
-  if (vinfo == NULL || nVisuals <= 0) {
-    if (vinfo != NULL) {
-      XFree(vinfo);
-    }
-    return false;
-  }
-
-  // Use first visual from the list.
-  *vinfo_ret = vinfo[0];
-
-  XFree(vinfo);
-
-  return true;
-}
-
-IrixOverlayShmImage::~IrixOverlayShmImage()
-{
-  if (readDisplayBuf != NULL)
-    XShmDestroyReadDisplayBuf(readDisplayBuf);
-}
-
-void IrixOverlayShmImage::get(Window wnd, int x, int y)
-{
-  get(wnd, x, y, xim->width, xim->height);
-}
-
-void IrixOverlayShmImage::get(Window wnd, int x, int y, int w, int h,
-                              int dst_x, int dst_y)
-{
-  XRectangle rect;
-  unsigned long hints = XRD_TRANSPARENT | XRD_READ_POINTER;
-
-  rect.x = x;
-  rect.y = y;
-  rect.width = w;
-  rect.height = h;
-
-  XShmReadDisplayRects(dpy, wnd,
-                       &rect, 1, readDisplayBuf,
-                       dst_x - x, dst_y - y,
-                       hints, &hints);
-}
-
-#endif // HAVE_READDISPLAY
-#endif // HAVE_MITSHM
-
-#ifdef HAVE_SUN_OVL
-
-//
-// SolarisOverlayImage class implementation
-//
-
-SolarisOverlayImage::SolarisOverlayImage(Display *d)
-  : Image(d)
-{
-}
-
-SolarisOverlayImage::SolarisOverlayImage(Display *d, int width, int height)
-  : Image(d)
-{
-  Init(width, height);
-}
-
-void SolarisOverlayImage::Init(int width, int height)
-{
-  // FIXME: Check if the extension is available at run time.
-  // FIXME: Maybe just read a small (e.g. 8x8) screen area then
-  //        reallocate xim->data[] and correct width and height?
-  xim = XReadScreen(dpy, DefaultRootWindow(dpy), 0, 0, width, height, True);
-  if (xim == NULL) {
-    vlog.error("XReadScreen() failed");
-    return;
-  }
-}
-
-SolarisOverlayImage::~SolarisOverlayImage()
-{
-}
-
-void SolarisOverlayImage::get(Window wnd, int x, int y)
-{
-  get(wnd, x, y, xim->width, xim->height);
-}
-
-void SolarisOverlayImage::get(Window wnd, int x, int y, int w, int h,
-                              int dst_x, int dst_y)
-{
-  XImage *tmp_xim = XReadScreen(dpy, wnd, x, y, w, h, True);
-  if (tmp_xim == NULL)
-    return;
-
-  updateRect(tmp_xim, dst_x, dst_y);
-
-  XDestroyImage(tmp_xim);
-}
-
-#endif // HAVE_SUN_OVL
-
 //
 // ImageFactory class implementation
 //
 // FIXME: Make ImageFactory always create images of the same class?
 //
 
-// Prepare useful shortcuts for compile-time options.
-#if defined(HAVE_READDISPLAY) && defined(HAVE_MITSHM)
-#define HAVE_SHM_READDISPLAY
-#endif
-#if defined(HAVE_SHM_READDISPLAY) || defined(HAVE_SUN_OVL)
-#define HAVE_OVERLAY_EXT
-#endif
-
-ImageFactory::ImageFactory(bool allowShm, bool allowOverlay)
-  : mayUseShm(allowShm), mayUseOverlay(allowOverlay)
+ImageFactory::ImageFactory(bool allowShm)
+  : mayUseShm(allowShm)
 {
 }
 
@@ -510,33 +338,8 @@
 {
   Image *image = NULL;
 
-  // First, try to create an image with overlay support.
-
-#ifdef HAVE_OVERLAY_EXT
-  if (mayUseOverlay) {
-#if defined(HAVE_SHM_READDISPLAY)
-    if (mayUseShm) {
-      image = new IrixOverlayShmImage(d, width, height);
-      if (image->xim != NULL) {
-        return image;
-      }
-    }
-#elif defined(HAVE_SUN_OVL)
-    image = new SolarisOverlayImage(d, width, height);
-    if (image->xim != NULL) {
-      return image;
-    }
-#endif
-    if (image != NULL) {
-      delete image;
-      vlog.error("Failed to create overlay image, trying other options");
-    }
-  }
-#endif // HAVE_OVERLAY_EXT
-
   // Now, try to use shared memory image.
 
-#ifdef HAVE_MITSHM
   if (mayUseShm) {
     image = new ShmImage(d, width, height);
     if (image->xim != NULL) {
@@ -546,7 +349,6 @@
     delete image;
     vlog.error("Failed to create SHM image, falling back to Xlib image");
   }
-#endif // HAVE_MITSHM
 
   // Fall back to Xlib image.
 
diff --git a/unix/x0vncserver/Image.h b/unix/x0vncserver/Image.h
index 4cac8b4..23502eb 100644
--- a/unix/x0vncserver/Image.h
+++ b/unix/x0vncserver/Image.h
@@ -92,8 +92,6 @@
 // ShmImage uses MIT-SHM extension of an X server to get image data.
 //
 
-#ifdef HAVE_MITSHM
-
 #include <X11/extensions/XShm.h>
 
 class ShmImage : public Image {
@@ -124,89 +122,6 @@
 };
 
 //
-// IrixOverlayShmImage uses ReadDisplay extension of an X server to
-// get truecolor image data, regardless of the default X visual type. 
-// This method is available on Irix only.
-//
-
-#ifdef HAVE_READDISPLAY
-
-#include <X11/extensions/readdisplay.h>
-
-class IrixOverlayShmImage : public ShmImage {
-
-public:
-
-  IrixOverlayShmImage(Display *d);
-  IrixOverlayShmImage(Display *d, int width, int height);
-  virtual ~IrixOverlayShmImage();
-
-  virtual const char *className() const {
-    return "IrixOverlayShmImage";
-  }
-  virtual const char *classDesc() const {
-    return "IRIX-specific SHM-aware overlay image";
-  }
-
-  virtual void get(Window wnd, int x = 0, int y = 0);
-  virtual void get(Window wnd, int x, int y, int w, int h,
-                   int dst_x = 0, int dst_y = 0);
-
-protected:
-
-  void Init(int width, int height);
-
-  // This method searches available X visuals for one that matches
-  // actual pixel format returned by XReadDisplay(). Returns true on
-  // success, false if there is no matching visual. On success, visual
-  // information is placed into the structure pointed by vinfo_ret.
-  bool getOverlayVisualInfo(XVisualInfo *vinfo_ret);
-
-  ShmReadDisplayBuf *readDisplayBuf;
-
-};
-
-#endif // HAVE_READDISPLAY
-#endif // HAVE_MITSHM
-
-//
-// SolarisOverlayImage uses SUN_OVL extension of an X server to get
-// truecolor image data, regardless of the default X visual type. This
-// method is available on Solaris only.
-//
-
-#ifdef HAVE_SUN_OVL
-
-#include <X11/extensions/transovl.h>
-
-class SolarisOverlayImage : public Image {
-
-public:
-
-  SolarisOverlayImage(Display *d);
-  SolarisOverlayImage(Display *d, int width, int height);
-  virtual ~SolarisOverlayImage();
-
-  virtual const char *className() const {
-    return "SolarisOverlayImage";
-  }
-  virtual const char *classDesc() const {
-    return "Solaris-specific non-SHM overlay image";
-  }
-
-  virtual void get(Window wnd, int x = 0, int y = 0);
-  virtual void get(Window wnd, int x, int y, int w, int h,
-                   int dst_x = 0, int dst_y = 0);
-
-protected:
-
-  void Init(int width, int height);
-
-};
-
-#endif // HAVE_SUN_OVL
-
-//
 // ImageFactory class is used to produce instances of Image-derived
 // objects that are most appropriate for current X server and user
 // settings.
@@ -216,18 +131,16 @@
 
 public:
 
-  ImageFactory(bool allowShm, bool allowOverlay);
+  ImageFactory(bool allowShm);
   virtual ~ImageFactory();
 
   bool isShmAllowed()     { return mayUseShm; }
-  bool isOverlayAllowed() { return mayUseOverlay; }
 
   virtual Image *newImage(Display *d, int width, int height);
 
 protected:
 
   bool mayUseShm;
-  bool mayUseOverlay;
 
 };
 
diff --git a/unix/x0vncserver/PollingManager.cxx b/unix/x0vncserver/PollingManager.cxx
index 3a040e2..d7f6f46 100644
--- a/unix/x0vncserver/PollingManager.cxx
+++ b/unix/x0vncserver/PollingManager.cxx
@@ -31,6 +31,8 @@
 
 #include <x0vncserver/PollingManager.h>
 
+using namespace rfb;
+
 static LogWriter vlog("PollingMgr");
 
 const int PollingManager::m_pollingOrder[32] = {
diff --git a/unix/x0vncserver/PollingManager.h b/unix/x0vncserver/PollingManager.h
index e106f79..5025fa5 100644
--- a/unix/x0vncserver/PollingManager.h
+++ b/unix/x0vncserver/PollingManager.h
@@ -32,8 +32,6 @@
 #include <x0vncserver/TimeMillis.h>
 #endif
 
-using namespace rfb;
-
 class PollingManager {
 
 public:
@@ -42,12 +40,12 @@
                  int offsetLeft = 0, int offsetTop = 0);
   virtual ~PollingManager();
 
-  void poll(VNCServer *server);
+  void poll(rfb::VNCServer *server);
 
 protected:
 
   // Screen polling. Returns true if some changes were detected.
-  bool pollScreen(VNCServer *server);
+  bool pollScreen(rfb::VNCServer *server);
 
   Display *m_dpy;
 
@@ -85,7 +83,7 @@
 
   int checkRow(int x, int y, int w);
   int checkColumn(int x, int y, int h, bool *pChangeFlags);
-  int sendChanges(VNCServer *server) const;
+  int sendChanges(rfb::VNCServer *server) const;
 
   // Check neighboring tiles and update m_changeFlags[].
   void checkNeighbors();
diff --git a/unix/x0vncserver/TimeMillis.cxx b/unix/x0vncserver/TimeMillis.cxx
index 059c043..b5054c9 100644
--- a/unix/x0vncserver/TimeMillis.cxx
+++ b/unix/x0vncserver/TimeMillis.cxx
@@ -22,11 +22,6 @@
 
 #include <x0vncserver/TimeMillis.h>
 
-// XXX Lynx/OS 2.3: get proto for gettimeofday()
-#ifdef Lynx
-#include <sys/proto.h>
-#endif
-
 TimeMillis::TimeMillis()
 {
   update();
diff --git a/unix/x0vncserver/XDesktop.cxx b/unix/x0vncserver/XDesktop.cxx
new file mode 100644
index 0000000..07b3a9c
--- /dev/null
+++ b/unix/x0vncserver/XDesktop.cxx
@@ -0,0 +1,427 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * Copyright (C) 2004-2008 Constantin Kaplinsky.  All Rights Reserved.
+ * Copyright 2017 Peter Astrand <astrand@cendio.se> for Cendio AB
+ *    
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+
+#include <x0vncserver/XDesktop.h>
+
+#include <X11/XKBlib.h>
+#ifdef HAVE_XTEST
+#include <X11/extensions/XTest.h>
+#endif
+#ifdef HAVE_XDAMAGE
+#include <X11/extensions/Xdamage.h>
+#endif
+#ifdef HAVE_XFIXES
+#include <X11/extensions/Xfixes.h>
+#endif
+
+#include <x0vncserver/Geometry.h>
+#include <x0vncserver/XPixelBuffer.h>
+
+using namespace rfb;
+
+extern const unsigned short code_map_qnum_to_xorgevdev[];
+extern const unsigned int code_map_qnum_to_xorgevdev_len;
+
+extern const unsigned short code_map_qnum_to_xorgkbd[];
+extern const unsigned int code_map_qnum_to_xorgkbd_len;
+
+extern rfb::BoolParameter useShm;
+extern rfb::BoolParameter rawKeyboard;
+
+static rfb::LogWriter vlog("XDesktop");
+
+// order is important as it must match RFB extension
+static const char * ledNames[XDESKTOP_N_LEDS] = {
+  "Scroll Lock", "Num Lock", "Caps Lock"
+};
+
+XDesktop::XDesktop(Display* dpy_, Geometry *geometry_)
+    : dpy(dpy_), geometry(geometry_), pb(0), server(0),
+      oldButtonMask(0), haveXtest(false), haveDamage(false),
+      maxButtons(0), running(false), ledMasks(), ledState(0),
+      codeMap(0), codeMapLen(0)
+{
+    int major, minor;
+
+    int xkbOpcode, xkbErrorBase;
+
+    major = XkbMajorVersion;
+    minor = XkbMinorVersion;
+    if (!XkbQueryExtension(dpy, &xkbOpcode, &xkbEventBase,
+                           &xkbErrorBase, &major, &minor)) {
+      vlog.error("XKEYBOARD extension not present");
+      throw Exception();
+    }
+
+    XkbSelectEvents(dpy, XkbUseCoreKbd, XkbIndicatorStateNotifyMask,
+                    XkbIndicatorStateNotifyMask);
+
+    // figure out bit masks for the indicators we are interested in
+    for (int i = 0; i < XDESKTOP_N_LEDS; i++) {
+      Atom a;
+      int shift;
+      Bool on;
+
+      a = XInternAtom(dpy, ledNames[i], True);
+      if (!a || !XkbGetNamedIndicator(dpy, a, &shift, &on, NULL, NULL))
+        continue;
+
+      ledMasks[i] = 1u << shift;
+      vlog.debug("Mask for '%s' is 0x%x", ledNames[i], ledMasks[i]);
+      if (on)
+        ledState |= 1u << i;
+    }
+
+    // X11 unfortunately uses keyboard driver specific keycodes and provides no
+    // direct way to query this, so guess based on the keyboard mapping
+    XkbDescPtr desc = XkbGetKeyboard(dpy, XkbAllComponentsMask, XkbUseCoreKbd);
+    if (desc && desc->names) {
+      char *keycodes = XGetAtomName(dpy, desc->names->keycodes);
+
+      if (keycodes) {
+        if (strncmp("evdev", keycodes, strlen("evdev")) == 0) {
+          codeMap = code_map_qnum_to_xorgevdev;
+          codeMapLen = code_map_qnum_to_xorgevdev_len;
+          vlog.info("Using evdev codemap\n");
+        } else if (strncmp("xfree86", keycodes, strlen("xfree86")) == 0) {
+          codeMap = code_map_qnum_to_xorgkbd;
+          codeMapLen = code_map_qnum_to_xorgkbd_len;
+          vlog.info("Using xorgkbd codemap\n");
+        } else {
+          vlog.info("Unknown keycode '%s', no codemap\n", keycodes);
+        }
+        XFree(keycodes);
+      } else {
+        vlog.debug("Unable to get keycode map\n");
+      }
+
+      XkbFreeKeyboard(desc, XkbAllComponentsMask, True);
+    }
+
+#ifdef HAVE_XTEST
+    int xtestEventBase;
+    int xtestErrorBase;
+
+    if (XTestQueryExtension(dpy, &xtestEventBase,
+                            &xtestErrorBase, &major, &minor)) {
+      XTestGrabControl(dpy, True);
+      vlog.info("XTest extension present - version %d.%d",major,minor);
+      haveXtest = true;
+    } else {
+#endif
+      vlog.info("XTest extension not present");
+      vlog.info("Unable to inject events or display while server is grabbed");
+#ifdef HAVE_XTEST
+    }
+#endif
+
+#ifdef HAVE_XDAMAGE
+    int xdamageErrorBase;
+
+    if (XDamageQueryExtension(dpy, &xdamageEventBase, &xdamageErrorBase)) {
+      haveDamage = true;
+    } else {
+#endif
+      vlog.info("DAMAGE extension not present");
+      vlog.info("Will have to poll screen for changes");
+#ifdef HAVE_XDAMAGE
+    }
+#endif
+
+#ifdef HAVE_XFIXES
+    int xfixesErrorBase;
+
+    if (XFixesQueryExtension(dpy, &xfixesEventBase, &xfixesErrorBase)) {
+      XFixesSelectCursorInput(dpy, DefaultRootWindow(dpy),
+                              XFixesDisplayCursorNotifyMask);
+    } else {
+#endif
+      vlog.info("XFIXES extension not present");
+      vlog.info("Will not be able to display cursors");
+#ifdef HAVE_XFIXES
+    }
+#endif
+
+    TXWindow::setGlobalEventHandler(this);
+}
+
+XDesktop::~XDesktop() {
+    stop();
+}
+
+
+void XDesktop::poll() {
+    if (pb and not haveDamage)
+      pb->poll(server);
+    if (running) {
+      Window root, child;
+      int x, y, wx, wy;
+      unsigned int mask;
+      XQueryPointer(dpy, DefaultRootWindow(dpy), &root, &child,
+                    &x, &y, &wx, &wy, &mask);
+      server->setCursorPos(rfb::Point(x, y));
+    }
+  }
+
+
+void XDesktop::start(VNCServer* vs) {
+
+    // Determine actual number of buttons of the X pointer device.
+    unsigned char btnMap[8];
+    int numButtons = XGetPointerMapping(dpy, btnMap, 8);
+    maxButtons = (numButtons > 8) ? 8 : numButtons;
+    vlog.info("Enabling %d button%s of X pointer device",
+              maxButtons, (maxButtons != 1) ? "s" : "");
+
+    // Create an ImageFactory instance for producing Image objects.
+    ImageFactory factory((bool)useShm);
+
+    // Create pixel buffer and provide it to the server object.
+    pb = new XPixelBuffer(dpy, factory, geometry->getRect());
+    vlog.info("Allocated %s", pb->getImage()->classDesc());
+
+    server = (VNCServerST *)vs;
+    server->setPixelBuffer(pb);
+
+#ifdef HAVE_XDAMAGE
+    if (haveDamage) {
+      damage = XDamageCreate(dpy, DefaultRootWindow(dpy),
+                             XDamageReportRawRectangles);
+    }
+#endif
+
+#ifdef HAVE_XFIXES
+    setCursor();
+#endif
+
+    server->setLEDState(ledState);
+
+    running = true;
+}
+
+void XDesktop::stop() {
+    running = false;
+
+#ifdef HAVE_XDAMAGE
+    if (haveDamage)
+      XDamageDestroy(dpy, damage);
+#endif
+
+    delete pb;
+    pb = 0;
+}
+
+bool XDesktop::isRunning() {
+    return running;
+}
+
+void XDesktop::pointerEvent(const Point& pos, int buttonMask) {
+#ifdef HAVE_XTEST
+    if (!haveXtest) return;
+    XTestFakeMotionEvent(dpy, DefaultScreen(dpy),
+                         geometry->offsetLeft() + pos.x,
+                         geometry->offsetTop() + pos.y,
+                         CurrentTime);
+    if (buttonMask != oldButtonMask) {
+      for (int i = 0; i < maxButtons; i++) {
+	if ((buttonMask ^ oldButtonMask) & (1<<i)) {
+          if (buttonMask & (1<<i)) {
+            XTestFakeButtonEvent(dpy, i+1, True, CurrentTime);
+          } else {
+            XTestFakeButtonEvent(dpy, i+1, False, CurrentTime);
+          }
+        }
+      }
+    }
+    oldButtonMask = buttonMask;
+#endif
+}
+
+#ifdef HAVE_XTEST
+KeyCode XDesktop::XkbKeysymToKeycode(Display* dpy, KeySym keysym) {
+    XkbDescPtr xkb;
+    XkbStateRec state;
+    unsigned keycode;
+
+    xkb = XkbGetMap(dpy, XkbAllComponentsMask, XkbUseCoreKbd);
+    if (!xkb)
+      return 0;
+
+    XkbGetState(dpy, XkbUseCoreKbd, &state);
+
+    for (keycode = xkb->min_key_code;
+         keycode <= xkb->max_key_code;
+         keycode++) {
+      KeySym cursym;
+      unsigned int mods, out_mods;
+      // XkbStateFieldFromRec() doesn't work properly because
+      // state.lookup_mods isn't properly updated, so we do this manually
+      mods = XkbBuildCoreState(XkbStateMods(&state), state.group);
+      XkbTranslateKeyCode(xkb, keycode, mods, &out_mods, &cursym);
+      if (cursym == keysym)
+        break;
+    }
+
+    if (keycode > xkb->max_key_code)
+      keycode = 0;
+
+    XkbFreeKeyboard(xkb, XkbAllComponentsMask, True);
+
+    return keycode;
+}
+#endif
+
+void XDesktop::keyEvent(rdr::U32 keysym, rdr::U32 xtcode, bool down) {
+#ifdef HAVE_XTEST
+    int keycode = 0;
+
+    if (!haveXtest)
+      return;
+
+    // Use scan code if provided and mapping exists
+    if (codeMap && rawKeyboard && xtcode < codeMapLen)
+        keycode = codeMap[xtcode];
+
+    if (!keycode) {
+      if (pressedKeys.find(keysym) != pressedKeys.end())
+        keycode = pressedKeys[keysym];
+      else {
+        // XKeysymToKeycode() doesn't respect state, so we have to use
+        // something slightly more complex
+        keycode = XkbKeysymToKeycode(dpy, keysym);
+      }
+    }
+
+    if (!keycode)
+      return;
+
+    if (down)
+      pressedKeys[keysym] = keycode;
+    else
+      pressedKeys.erase(keysym);
+
+    XTestFakeKeyEvent(dpy, keycode, down, CurrentTime);
+#endif
+}
+
+void XDesktop::clientCutText(const char* str, int len) {
+}
+
+
+bool XDesktop::handleGlobalEvent(XEvent* ev) {
+    if (ev->type == xkbEventBase + XkbEventCode) {
+      XkbEvent *kb = (XkbEvent *)ev;
+
+      if (kb->any.xkb_type != XkbIndicatorStateNotify)
+        return false;
+
+      vlog.debug("Got indicator update, mask is now 0x%x", kb->indicators.state);
+
+      ledState = 0;
+      for (int i = 0; i < XDESKTOP_N_LEDS; i++) {
+        if (kb->indicators.state & ledMasks[i])
+          ledState |= 1u << i;
+      }
+
+      if (running)
+        server->setLEDState(ledState);
+
+      return true;
+#ifdef HAVE_XDAMAGE
+    } else if (ev->type == xdamageEventBase) {
+      XDamageNotifyEvent* dev;
+      Rect rect;
+
+      if (!running)
+        return true;
+
+      dev = (XDamageNotifyEvent*)ev;
+      rect.setXYWH(dev->area.x, dev->area.y, dev->area.width, dev->area.height);
+      server->add_changed(rect);
+
+      return true;
+#endif
+#ifdef HAVE_XFIXES
+    } else if (ev->type == xfixesEventBase + XFixesCursorNotify) {
+      XFixesCursorNotifyEvent* cev;
+
+      if (!running)
+        return true;
+
+      cev = (XFixesCursorNotifyEvent*)ev;
+
+      if (cev->subtype != XFixesDisplayCursorNotify)
+        return false;
+
+      return setCursor();
+#endif
+    }
+
+    return false;
+}
+
+bool XDesktop::setCursor()
+{
+      XFixesCursorImage *cim;
+
+      cim = XFixesGetCursorImage(dpy);
+      if (cim == NULL)
+        return false;
+
+      // Copied from XserverDesktop::setCursor() in
+      // unix/xserver/hw/vnc/XserverDesktop.cc and adapted to
+      // handle long -> U32 conversion for 64-bit Xlib
+      rdr::U8* cursorData;
+      rdr::U8 *out;
+      const unsigned long *pixels;
+
+      cursorData = new rdr::U8[cim->width * cim->height * 4];
+
+      // Un-premultiply alpha
+      pixels = cim->pixels;
+      out = cursorData;
+      for (int y = 0; y < cim->height; y++) {
+        for (int x = 0; x < cim->width; x++) {
+          rdr::U8 alpha;
+          rdr::U32 pixel = *pixels++;
+          rdr::U8 *in = (rdr::U8 *) &pixel;
+
+          alpha = in[3];
+          if (alpha == 0)
+            alpha = 1; // Avoid division by zero
+
+          *out++ = (unsigned)*in++ * 255/alpha;
+          *out++ = (unsigned)*in++ * 255/alpha;
+          *out++ = (unsigned)*in++ * 255/alpha;
+          *out++ = *in++;
+        }
+      }
+
+      try {
+        server->setCursor(cim->width, cim->height, Point(cim->xhot, cim->yhot),
+                          cursorData);
+      } catch (rdr::Exception& e) {
+        vlog.error("XserverDesktop::setCursor: %s",e.str());
+      }
+
+      delete [] cursorData;
+      XFree(cim);
+      return true;
+}
diff --git a/unix/x0vncserver/XDesktop.h b/unix/x0vncserver/XDesktop.h
new file mode 100644
index 0000000..c9106f8
--- /dev/null
+++ b/unix/x0vncserver/XDesktop.h
@@ -0,0 +1,81 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * Copyright (C) 2004-2008 Constantin Kaplinsky.  All Rights Reserved.
+ * Copyright 2017 Peter Astrand <astrand@cendio.se> for Cendio AB
+ *    
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+
+#ifndef __XDESKTOP_H__
+#define __XDESKTOP_H__
+
+#include <rfb/VNCServerST.h>
+#include <tx/TXWindow.h>
+
+#include <X11/XKBlib.h>
+#ifdef HAVE_XDAMAGE
+#include <X11/extensions/Xdamage.h>
+#endif
+
+class Geometry;
+class XPixelBuffer;
+
+// number of XKb indicator leds to handle
+#define XDESKTOP_N_LEDS 3
+
+class XDesktop : public rfb::SDesktop, public TXGlobalEventHandler
+{
+public:
+  XDesktop(Display* dpy_, Geometry *geometry);
+  virtual ~XDesktop();
+  void poll();
+  // -=- SDesktop interface
+  virtual void start(rfb::VNCServer* vs);
+  virtual void stop();
+  bool isRunning();
+  virtual void pointerEvent(const rfb::Point& pos, int buttonMask);
+  KeyCode XkbKeysymToKeycode(Display* dpy, KeySym keysym);
+  virtual void keyEvent(rdr::U32 keysym, rdr::U32 xtcode, bool down);
+  virtual void clientCutText(const char* str, int len);
+  // -=- TXGlobalEventHandler interface
+  virtual bool handleGlobalEvent(XEvent* ev);
+
+protected:
+  Display* dpy;
+  Geometry* geometry;
+  XPixelBuffer* pb;
+  rfb::VNCServerST* server;
+  int oldButtonMask;
+  bool haveXtest;
+  bool haveDamage;
+  int maxButtons;
+  std::map<KeySym, KeyCode> pressedKeys;
+  bool running;
+#ifdef HAVE_XDAMAGE
+  Damage damage;
+  int xdamageEventBase;
+#endif
+  int xkbEventBase;
+#ifdef HAVE_XFIXES
+  int xfixesEventBase;
+#endif
+  int ledMasks[XDESKTOP_N_LEDS];
+  unsigned ledState;
+  const unsigned short *codeMap;
+  unsigned codeMapLen;
+  bool setCursor();
+};
+
+#endif // __XDESKTOP_H__
diff --git a/unix/x0vncserver/XPixelBuffer.h b/unix/x0vncserver/XPixelBuffer.h
index da03161..18c85fe 100644
--- a/unix/x0vncserver/XPixelBuffer.h
+++ b/unix/x0vncserver/XPixelBuffer.h
@@ -28,23 +28,21 @@
 #include <x0vncserver/Image.h>
 #include <x0vncserver/PollingManager.h>
 
-using namespace rfb;
-
 //
 // XPixelBuffer is an Image-based implementation of FullFramePixelBuffer.
 //
 
-class XPixelBuffer : public FullFramePixelBuffer
+class XPixelBuffer : public rfb::FullFramePixelBuffer
 {
 public:
-  XPixelBuffer(Display *dpy, ImageFactory &factory, const Rect &rect);
+  XPixelBuffer(Display *dpy, ImageFactory &factory, const rfb::Rect &rect);
   virtual ~XPixelBuffer();
 
   // Provide access to the underlying Image object.
   const Image *getImage() const { return m_image; }
 
   // Detect changed pixels, notify the server.
-  inline void poll(VNCServer *server) { m_poller->poll(server); }
+  inline void poll(rfb::VNCServer *server) { m_poller->poll(server); }
 
   // Override PixelBuffer::grabRegion().
   virtual void grabRegion(const rfb::Region& region);
@@ -59,7 +57,7 @@
 
   // Copy pixels from the screen to the pixel buffer,
   // for the specified rectangular area of the buffer.
-  inline void grabRect(const Rect &r) {
+  inline void grabRect(const rfb::Rect &r) {
     m_image->get(DefaultRootWindow(m_dpy),
 		 m_offsetLeft + r.tl.x, m_offsetTop + r.tl.y,
 		 r.width(), r.height(), r.tl.x, r.tl.y);
diff --git a/unix/x0vncserver/x0vncserver.cxx b/unix/x0vncserver/x0vncserver.cxx
index 6fd6bc3..22525d5 100644
--- a/unix/x0vncserver/x0vncserver.cxx
+++ b/unix/x0vncserver/x0vncserver.cxx
@@ -31,7 +31,6 @@
 #include <rfb/Configuration.h>
 #include <rfb/Timer.h>
 #include <network/TcpSocket.h>
-#include <tx/TXWindow.h>
 
 #include <vncconfig/QueryConnectDialog.h>
 
@@ -39,46 +38,17 @@
 #include <X11/X.h>
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
-#include <X11/XKBlib.h>
-#ifdef HAVE_XTEST
-#include <X11/extensions/XTest.h>
-#endif
-#ifdef HAVE_XDAMAGE
-#include <X11/extensions/Xdamage.h>
-#endif
-#ifdef HAVE_XFIXES
-#include <X11/extensions/Xfixes.h>
-#endif
 
+#include <x0vncserver/XDesktop.h>
 #include <x0vncserver/Geometry.h>
 #include <x0vncserver/Image.h>
-#include <x0vncserver/XPixelBuffer.h>
 #include <x0vncserver/PollingScheduler.h>
 
-extern const unsigned short code_map_qnum_to_xorgevdev[];
-extern const unsigned int code_map_qnum_to_xorgevdev_len;
-
-extern const unsigned short code_map_qnum_to_xorgkbd[];
-extern const unsigned int code_map_qnum_to_xorgkbd_len;
-
-// XXX Lynx/OS 2.3: protos for select(), bzero()
-#ifdef Lynx
-#include <sys/proto.h>
-#endif
-
 extern char buildtime[];
 
 using namespace rfb;
 using namespace network;
 
-// number of XKb indicator leds to handle
-static const int N_LEDS = 3;
-
-// order is important as it must match RFB extension
-static const char * ledNames[N_LEDS] = {
-  "Scroll Lock", "Num Lock", "Caps Lock"
-};
-
 static LogWriter vlog("Main");
 
 IntParameter pollingCycle("PollingCycle", "Milliseconds per one polling "
@@ -87,8 +57,6 @@
 IntParameter maxProcessorUsage("MaxProcessorUsage", "Maximum percentage of "
                                "CPU time to be consumed", 35);
 BoolParameter useShm("UseSHM", "Use MIT-SHM extension if available", true);
-BoolParameter useOverlay("OverlayMode", "Use overlay mode under "
-                         "IRIX or Solaris", true);
 StringParameter displayname("display", "The X display", "");
 IntParameter rfbport("rfbport", "TCP port to listen for RFB protocol",5900);
 IntParameter queryConnectTimeout("QueryConnectTimeout",
@@ -157,399 +125,6 @@
 };
 
 
-class XDesktop : public SDesktop, public TXGlobalEventHandler
-{
-public:
-  XDesktop(Display* dpy_, Geometry *geometry_)
-    : dpy(dpy_), geometry(geometry_), pb(0), server(0),
-      oldButtonMask(0), haveXtest(false), haveDamage(false),
-      maxButtons(0), running(false), ledMasks(), ledState(0),
-      codeMap(0), codeMapLen(0)
-  {
-    int major, minor;
-
-    int xkbOpcode, xkbErrorBase;
-
-    major = XkbMajorVersion;
-    minor = XkbMinorVersion;
-    if (!XkbQueryExtension(dpy, &xkbOpcode, &xkbEventBase,
-                           &xkbErrorBase, &major, &minor)) {
-      vlog.error("XKEYBOARD extension not present");
-      throw Exception();
-    }
-
-    XkbSelectEvents(dpy, XkbUseCoreKbd, XkbIndicatorStateNotifyMask,
-                    XkbIndicatorStateNotifyMask);
-
-    // figure out bit masks for the indicators we are interested in
-    for (int i = 0; i < N_LEDS; i++) {
-      Atom a;
-      int shift;
-      Bool on;
-
-      a = XInternAtom(dpy, ledNames[i], True);
-      if (!a || !XkbGetNamedIndicator(dpy, a, &shift, &on, NULL, NULL))
-        continue;
-
-      ledMasks[i] = 1u << shift;
-      vlog.debug("Mask for '%s' is 0x%x", ledNames[i], ledMasks[i]);
-      if (on)
-        ledState |= 1u << i;
-    }
-
-    // X11 unfortunately uses keyboard driver specific keycodes and provides no
-    // direct way to query this, so guess based on the keyboard mapping
-    XkbDescPtr desc = XkbGetKeyboard(dpy, XkbAllComponentsMask, XkbUseCoreKbd);
-    if (desc && desc->names) {
-      char *keycodes = XGetAtomName(dpy, desc->names->keycodes);
-
-      if (keycodes) {
-        if (strncmp("evdev", keycodes, strlen("evdev")) == 0) {
-          codeMap = code_map_qnum_to_xorgevdev;
-          codeMapLen = code_map_qnum_to_xorgevdev_len;
-          vlog.info("Using evdev codemap\n");
-        } else if (strncmp("xfree86", keycodes, strlen("xfree86")) == 0) {
-          codeMap = code_map_qnum_to_xorgkbd;
-          codeMapLen = code_map_qnum_to_xorgkbd_len;
-          vlog.info("Using xorgkbd codemap\n");
-        } else {
-          vlog.info("Unknown keycode '%s', no codemap\n", keycodes);
-        }
-        XFree(keycodes);
-      } else {
-        vlog.debug("Unable to get keycode map\n");
-      }
-
-      XkbFreeKeyboard(desc, XkbAllComponentsMask, True);
-    }
-
-#ifdef HAVE_XTEST
-    int xtestEventBase;
-    int xtestErrorBase;
-
-    if (XTestQueryExtension(dpy, &xtestEventBase,
-                            &xtestErrorBase, &major, &minor)) {
-      XTestGrabControl(dpy, True);
-      vlog.info("XTest extension present - version %d.%d",major,minor);
-      haveXtest = true;
-    } else {
-#endif
-      vlog.info("XTest extension not present");
-      vlog.info("Unable to inject events or display while server is grabbed");
-#ifdef HAVE_XTEST
-    }
-#endif
-
-#ifdef HAVE_XDAMAGE
-    int xdamageErrorBase;
-
-    if (XDamageQueryExtension(dpy, &xdamageEventBase, &xdamageErrorBase)) {
-      haveDamage = true;
-    } else {
-#endif
-      vlog.info("DAMAGE extension not present");
-      vlog.info("Will have to poll screen for changes");
-#ifdef HAVE_XDAMAGE
-    }
-#endif
-
-#ifdef HAVE_XFIXES
-    int xfixesErrorBase;
-
-    if (XFixesQueryExtension(dpy, &xfixesEventBase, &xfixesErrorBase)) {
-      XFixesSelectCursorInput(dpy, DefaultRootWindow(dpy),
-                              XFixesDisplayCursorNotifyMask);
-    } else {
-#endif
-      vlog.info("XFIXES extension not present");
-      vlog.info("Will not be able to display cursors");
-#ifdef HAVE_XFIXES
-    }
-#endif
-
-    TXWindow::setGlobalEventHandler(this);
-  }
-  virtual ~XDesktop() {
-    stop();
-  }
-
-  inline void poll() {
-    if (pb and not haveDamage)
-      pb->poll(server);
-    if (running) {
-      Window root, child;
-      int x, y, wx, wy;
-      unsigned int mask;
-      XQueryPointer(dpy, DefaultRootWindow(dpy), &root, &child,
-                    &x, &y, &wx, &wy, &mask);
-      server->setCursorPos(rfb::Point(x, y));
-    }
-  }
-
-  // -=- SDesktop interface
-
-  virtual void start(VNCServer* vs) {
-
-    // Determine actual number of buttons of the X pointer device.
-    unsigned char btnMap[8];
-    int numButtons = XGetPointerMapping(dpy, btnMap, 8);
-    maxButtons = (numButtons > 8) ? 8 : numButtons;
-    vlog.info("Enabling %d button%s of X pointer device",
-              maxButtons, (maxButtons != 1) ? "s" : "");
-
-    // Create an ImageFactory instance for producing Image objects.
-    ImageFactory factory((bool)useShm, (bool)useOverlay);
-
-    // Create pixel buffer and provide it to the server object.
-    pb = new XPixelBuffer(dpy, factory, geometry->getRect());
-    vlog.info("Allocated %s", pb->getImage()->classDesc());
-
-    server = (VNCServerST *)vs;
-    server->setPixelBuffer(pb);
-
-#ifdef HAVE_XDAMAGE
-    if (haveDamage) {
-      damage = XDamageCreate(dpy, DefaultRootWindow(dpy),
-                             XDamageReportRawRectangles);
-    }
-#endif
-
-    server->setLEDState(ledState);
-
-    running = true;
-  }
-
-  virtual void stop() {
-    running = false;
-
-#ifdef HAVE_XDAMAGE
-    if (haveDamage)
-      XDamageDestroy(dpy, damage);
-#endif
-
-    delete pb;
-    pb = 0;
-  }
-
-  inline bool isRunning() {
-    return running;
-  }
-
-  virtual void pointerEvent(const Point& pos, int buttonMask) {
-#ifdef HAVE_XTEST
-    if (!haveXtest) return;
-    XTestFakeMotionEvent(dpy, DefaultScreen(dpy),
-                         geometry->offsetLeft() + pos.x,
-                         geometry->offsetTop() + pos.y,
-                         CurrentTime);
-    if (buttonMask != oldButtonMask) {
-      for (int i = 0; i < maxButtons; i++) {
-	if ((buttonMask ^ oldButtonMask) & (1<<i)) {
-          if (buttonMask & (1<<i)) {
-            XTestFakeButtonEvent(dpy, i+1, True, CurrentTime);
-          } else {
-            XTestFakeButtonEvent(dpy, i+1, False, CurrentTime);
-          }
-        }
-      }
-    }
-    oldButtonMask = buttonMask;
-#endif
-  }
-
-#ifdef HAVE_XTEST
-  KeyCode XkbKeysymToKeycode(Display* dpy, KeySym keysym) {
-    XkbDescPtr xkb;
-    XkbStateRec state;
-    unsigned keycode;
-
-    xkb = XkbGetMap(dpy, XkbAllComponentsMask, XkbUseCoreKbd);
-    if (!xkb)
-      return 0;
-
-    XkbGetState(dpy, XkbUseCoreKbd, &state);
-
-    for (keycode = xkb->min_key_code;
-         keycode <= xkb->max_key_code;
-         keycode++) {
-      KeySym cursym;
-      unsigned int mods, out_mods;
-      // XkbStateFieldFromRec() doesn't work properly because
-      // state.lookup_mods isn't properly updated, so we do this manually
-      mods = XkbBuildCoreState(XkbStateMods(&state), state.group);
-      XkbTranslateKeyCode(xkb, keycode, mods, &out_mods, &cursym);
-      if (cursym == keysym)
-        break;
-    }
-
-    if (keycode > xkb->max_key_code)
-      keycode = 0;
-
-    XkbFreeKeyboard(xkb, XkbAllComponentsMask, True);
-
-    return keycode;
-  }
-#endif
-
-  virtual void keyEvent(rdr::U32 keysym, rdr::U32 xtcode, bool down) {
-#ifdef HAVE_XTEST
-    int keycode = 0;
-
-    if (!haveXtest)
-      return;
-
-    // Use scan code if provided and mapping exists
-    if (codeMap && rawKeyboard && xtcode < codeMapLen)
-        keycode = codeMap[xtcode];
-
-    if (!keycode) {
-      if (pressedKeys.find(keysym) != pressedKeys.end())
-        keycode = pressedKeys[keysym];
-      else {
-        // XKeysymToKeycode() doesn't respect state, so we have to use
-        // something slightly more complex
-        keycode = XkbKeysymToKeycode(dpy, keysym);
-      }
-    }
-
-    if (!keycode)
-      return;
-
-    if (down)
-      pressedKeys[keysym] = keycode;
-    else
-      pressedKeys.erase(keysym);
-
-    XTestFakeKeyEvent(dpy, keycode, down, CurrentTime);
-#endif
-  }
-
-  virtual void clientCutText(const char* str, int len) {
-  }
-
-  // -=- TXGlobalEventHandler interface
-
-  virtual bool handleGlobalEvent(XEvent* ev) {
-    if (ev->type == xkbEventBase + XkbEventCode) {
-      XkbEvent *kb = (XkbEvent *)ev;
-
-      if (kb->any.xkb_type != XkbIndicatorStateNotify)
-        return false;
-
-      vlog.debug("Got indicator update, mask is now 0x%x", kb->indicators.state);
-
-      ledState = 0;
-      for (int i = 0; i < N_LEDS; i++) {
-        if (kb->indicators.state & ledMasks[i])
-          ledState |= 1u << i;
-      }
-
-      if (running)
-        server->setLEDState(ledState);
-
-      return true;
-#ifdef HAVE_XDAMAGE
-    } else if (ev->type == xdamageEventBase) {
-      XDamageNotifyEvent* dev;
-      Rect rect;
-
-      if (!running)
-        return true;
-
-      dev = (XDamageNotifyEvent*)ev;
-      rect.setXYWH(dev->area.x, dev->area.y, dev->area.width, dev->area.height);
-      server->add_changed(rect);
-
-      return true;
-#endif
-#ifdef HAVE_XFIXES
-    } else if (ev->type == xfixesEventBase + XFixesCursorNotify) {
-      XFixesCursorNotifyEvent* cev;
-      XFixesCursorImage *cim;
-
-      if (!running)
-        return true;
-
-      cev = (XFixesCursorNotifyEvent*)ev;
-
-      if (cev->subtype != XFixesDisplayCursorNotify)
-        return false;
-
-      cim = XFixesGetCursorImage(dpy);
-      if (cim == NULL)
-        return false;
-
-      // Copied from XserverDesktop::setCursor() in
-      // unix/xserver/hw/vnc/XserverDesktop.cc and adapted to
-      // handle long -> U32 conversion for 64-bit Xlib
-      rdr::U8* cursorData;
-      rdr::U8 *out;
-      const unsigned long *pixels;
-
-      cursorData = new rdr::U8[cim->width * cim->height * 4];
-
-      // Un-premultiply alpha
-      pixels = cim->pixels;
-      out = cursorData;
-      for (int y = 0; y < cim->height; y++) {
-        for (int x = 0; x < cim->width; x++) {
-          rdr::U8 alpha;
-          rdr::U32 pixel = *pixels++;
-          rdr::U8 *in = (rdr::U8 *) &pixel;
-
-          alpha = in[3];
-          if (alpha == 0)
-            alpha = 1; // Avoid division by zero
-
-          *out++ = (unsigned)*in++ * 255/alpha;
-          *out++ = (unsigned)*in++ * 255/alpha;
-          *out++ = (unsigned)*in++ * 255/alpha;
-          *out++ = *in++;
-        }
-      }
-
-      try {
-        server->setCursor(cim->width, cim->height, Point(cim->xhot, cim->yhot),
-                          cursorData);
-      } catch (rdr::Exception& e) {
-        vlog.error("XserverDesktop::setCursor: %s",e.str());
-      }
-
-      delete [] cursorData;
-      XFree(cim);
-      return true;
-#endif
-    }
-
-    return false;
-  }
-
-protected:
-  Display* dpy;
-  Geometry* geometry;
-  XPixelBuffer* pb;
-  VNCServerST* server;
-  int oldButtonMask;
-  bool haveXtest;
-  bool haveDamage;
-  int maxButtons;
-  std::map<KeySym, KeyCode> pressedKeys;
-  bool running;
-#ifdef HAVE_XDAMAGE
-  Damage damage;
-  int xdamageEventBase;
-#endif
-  int xkbEventBase;
-#ifdef HAVE_XFIXES
-  int xfixesEventBase;
-#endif
-  int ledMasks[N_LEDS];
-  unsigned ledState;
-  const unsigned short *codeMap;
-  unsigned codeMapLen;
-};
-
-
 class FileTcpFilter : public TcpFilter
 {
 
@@ -683,6 +258,9 @@
 
   Configuration::enableServerParams();
 
+  // Disable configuration parameters which we do not support
+  Configuration::removeParam("AcceptSetDesktopSize");
+
   for (int i = 1; i < argc; i++) {
     if (Configuration::setParam(argv[i]))
       continue;
diff --git a/unix/x0vncserver/x0vncserver.man b/unix/x0vncserver/x0vncserver.man
index 804a70f..4f47e59 100644
--- a/unix/x0vncserver/x0vncserver.man
+++ b/unix/x0vncserver/x0vncserver.man
@@ -227,13 +227,6 @@
 the screen.  Default is on.
 .
 .TP
-.B OverlayMode
-Use overlay mode in IRIX or Solaris (does not have effect in other systems).
-This enables system-specific access to complete full-color version of the
-screen (the default X visual often provides 256 colors).  Also, in overlay
-mode, \fBx0vncserver\fP can show correct mouse cursor.  Default is on.
-.
-.TP
 .B ZlibLevel
 Zlib compression level for ZRLE encoding (it does not affect Tight encoding).
 Acceptable values are between 0 and 9.  Default is to use the standard
diff --git a/win/winvnc/winvnc.cxx b/win/winvnc/winvnc.cxx
index aa41bcb..5623421 100644
--- a/win/winvnc/winvnc.cxx
+++ b/win/winvnc/winvnc.cxx
@@ -78,7 +78,7 @@
   printf("\nLog destinations:\n");
   Logger::listLoggers();
   printf("\nAvailable configuration parameters:\n");
-  Configuration::listParams(ConfServer);
+  Configuration::listParams(79, 14);
 }
 
 static void MsgBoxOrLog(const char* msg, bool isError=false) {