Move XDesktop to separate file

Define ledNames in XDesktop.cxx, rename N_LEDS to XDESKTOP_N_LEDS
diff --git a/unix/x0vncserver/x0vncserver.cxx b/unix/x0vncserver/x0vncserver.cxx
index 6fd6bc3..b21daae 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,28 +38,12 @@
 #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>
@@ -71,14 +54,6 @@
 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 "
@@ -157,399 +132,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
 {