open-src/xserver/xvnc/upstream-input-refactor.patch
changeset 1124 7bc7e624f965
parent 1123 4678f8c1d429
child 1125 0776474068be
--- a/open-src/xserver/xvnc/upstream-input-refactor.patch	Mon May 09 10:12:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1896 +0,0 @@
-From 2f97d8a75e7371ac7f3a9a1338db55888754d7c0 Mon Sep 17 00:00:00 2001
-From: atkac <atkac@3789f03b-4d11-0410-bbf8-ca57d06f2519>
-Date: Fri, 28 Aug 2009 12:03:11 +0000
-Subject: [PATCH] Initialize eventq in all cases.
-
-git-svn-id: https://tigervnc.svn.sourceforge.net/svnroot/tigervnc/trunk@3885 3789f03b-4d11-0410-bbf8-ca57d06f2519
----
- unix/xserver/hw/vnc/XserverDesktop.cc |    2 ++
- 1 files changed, 2 insertions(+), 0 deletions(-)
-
-diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc
-index d6fe993..533f31b 100644
---- a/unix/xserver/hw/vnc/XserverDesktop.cc
-+++ b/unix/xserver/hw/vnc/XserverDesktop.cc
-@@ -203,6 +203,8 @@ XserverDesktop::XserverDesktop(ScreenPtr pScreen_,
-     eventq = (xEvent *) xcalloc(sizeof(xEvent), GetMaximumEventsNum());
-   if (!eventq)
-     FatalError("Couldn't allocate eventq\n");
-+#else
-+  GetEventList(&eventq);
- #endif
- 
-   /*
--- 
-1.5.6.5
-
-From 1093aa3149c24b362781ab7f19c4c63a6eb19990 Mon Sep 17 00:00:00 2001
-From: atkac <atkac@3789f03b-4d11-0410-bbf8-ca57d06f2519>
-Date: Fri, 28 Aug 2009 12:04:20 +0000
-Subject: [PATCH] Add Input.h and Input.cc and move all mouse input related code there.
-
-git-svn-id: https://tigervnc.svn.sourceforge.net/svnroot/tigervnc/trunk@3886 3789f03b-4d11-0410-bbf8-ca57d06f2519
----
- unix/xserver/hw/vnc/Input.cc          |  167 +++++++++++++++++++++++++++++++++
- unix/xserver/hw/vnc/Input.h           |   61 ++++++++++++
- unix/xserver/hw/vnc/Makefile.am       |    6 +-
- unix/xserver/hw/vnc/XserverDesktop.cc |  142 +---------------------------
- unix/xserver/hw/vnc/XserverDesktop.h  |    5 +-
- 5 files changed, 240 insertions(+), 141 deletions(-)
- create mode 100644 unix/xserver/hw/vnc/Input.cc
- create mode 100644 unix/xserver/hw/vnc/Input.h
-
-diff --git a/unix/xserver/hw/vnc/Input.cc b/unix/xserver/hw/vnc/Input.cc
-new file mode 100644
-index 0000000..ca279f0
---- /dev/null
-+++ b/unix/xserver/hw/vnc/Input.cc
-@@ -0,0 +1,167 @@
-+/* Copyright (C) 2009 TightVNC Team
-+ * Copyright (C) 2009 Red Hat, Inc.
-+ *
-+ * 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.
-+ */
-+
-+#ifdef HAVE_DIX_CONFIG_H
-+#include <dix-config.h>
-+#endif
-+
-+#include "Input.h"
-+#include "xorg-version.h"
-+
-+extern "C" {
-+#include "mi.h"
-+}
-+
-+/* Event queue is shared between all devices. */
-+#if XORG == 15
-+static xEvent *eventq = NULL;
-+#else
-+static EventList *eventq = NULL;
-+#endif
-+
-+static void initEventq(void)
-+{
-+	/* eventq is never free()-ed because it exists during server life. */
-+	if (eventq == NULL) {
-+#if XORG == 15
-+		eventq = (xEvent *)xcalloc(sizeof(xEvent),
-+					   GetMaximumEventsNum());
-+		if (!eventq)
-+			FatalError("Couldn't allocate eventq\n");
-+#else
-+		GetEventList(&eventq);
-+#endif
-+	}
-+}
-+
-+static void enqueueEvents(DeviceIntPtr dev, int n)
-+{
-+	int i;
-+
-+	for (i = 0; i < n; i++) {
-+		/*
-+		 * Passing arguments in global variable eventq is probably not
-+		 * good programming practise but in this case it is safe and
-+		 * clear.
-+		 */
-+		mieqEnqueue(dev,
-+#if XORG == 15
-+			    eventq + i
-+#else
-+			    (eventq + i)->event
-+#endif
-+			   );
-+	}
-+}
-+
-+/* Pointer device pre-declarations */
-+#define BUTTONS 5
-+static int pointerProc(DeviceIntPtr pDevice, int onoff);
-+
-+/* Pointer device methods */
-+
-+PointerDevice::PointerDevice(rfb::VNCServerST *_server)
-+	: server(_server), oldButtonMask(0)
-+{
-+	dev = AddInputDevice(
-+#if XORG >= 16
-+			     serverClient,
-+#endif
-+			     pointerProc, TRUE);
-+	RegisterPointerDevice(dev);
-+	initEventq();
-+}
-+
-+void PointerDevice::ButtonAction(int buttonMask)
-+{
-+	int i, n;
-+
-+	for (i = 0; i < BUTTONS; i++) {
-+		if ((buttonMask ^ oldButtonMask) & (1 << i)) {
-+			int action = (buttonMask & (1<<i)) ?
-+				     ButtonPress : ButtonRelease;
-+			n = GetPointerEvents(eventq, dev, action, i + 1,
-+					     POINTER_RELATIVE, 0, 0, NULL);
-+			enqueueEvents(dev, n);
-+
-+		}
-+	}
-+
-+	oldButtonMask = buttonMask;
-+}
-+
-+void PointerDevice::Move(const rfb::Point &pos)
-+{
-+	int n, valuators[2];
-+
-+	if (pos.equals(cursorPos))
-+		return;
-+
-+	valuators[0] = pos.x;
-+	valuators[1] = pos.y;
-+	n = GetPointerEvents(eventq, dev, MotionNotify, 0, POINTER_ABSOLUTE, 0,
-+			     2, valuators);
-+	enqueueEvents(dev, n);
-+
-+	cursorPos = pos;
-+}
-+
-+void PointerDevice::Sync(void)
-+{
-+	if (cursorPos.equals(oldCursorPos))
-+		return;
-+
-+	oldCursorPos = cursorPos;
-+	server->setCursorPos(cursorPos);
-+	server->tryUpdate();
-+}
-+
-+static int pointerProc(DeviceIntPtr pDevice, int onoff)
-+{
-+	BYTE map[BUTTONS + 1];
-+	DevicePtr pDev = (DevicePtr)pDevice;
-+	int i;
-+
-+	switch (onoff) {
-+	case DEVICE_INIT:
-+		for (i = 0; i < BUTTONS + 1; i++)
-+			map[i] = i;
-+
-+		InitPointerDeviceStruct(pDev, map, BUTTONS,
-+#if XORG == 15
-+					GetMotionHistory,
-+#endif
-+					(PtrCtrlProcPtr)NoopDDA,
-+					GetMotionHistorySize(), 2);
-+		break;
-+	case DEVICE_ON:
-+		pDev->on = TRUE;
-+		break;
-+	case DEVICE_OFF:
-+		pDev->on = FALSE;
-+		break;
-+#if 0
-+	case DEVICE_CLOSE:
-+		break;
-+#endif
-+	}
-+
-+	return Success;
-+}
-+
-diff --git a/unix/xserver/hw/vnc/Input.h b/unix/xserver/hw/vnc/Input.h
-new file mode 100644
-index 0000000..49cedf2
---- /dev/null
-+++ b/unix/xserver/hw/vnc/Input.h
-@@ -0,0 +1,61 @@
-+/* Copyright (C) 2009 TightVNC Team
-+ * Copyright (C) 2009 Red Hat, Inc.
-+ *
-+ * 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.
-+ */
-+
-+/* Make sure macro doesn't conflict with macro in include/input.h. */
-+#ifndef INPUT_H_
-+#define INPUT_H_
-+
-+#ifdef HAVE_DIX_CONFIG_H
-+#include <dix-config.h>
-+#endif
-+
-+#include <rfb/VNCServerST.h>
-+
-+extern "C" {
-+#include "input.h"
-+};
-+
-+/* Represents pointer device. */
-+class PointerDevice {
-+public:
-+	/* Create new PointerDevice instance. */
-+	PointerDevice(rfb::VNCServerST *_server);
-+
-+	/*
-+	 * Press or release buttons. Relationship between buttonMask and
-+	 * buttons is specified in RFB protocol.
-+	 */
-+	void ButtonAction(int buttonMask);
-+
-+	/* Move pointer to target location (point coords are absolute). */
-+	void Move(const rfb::Point &point);
-+
-+	/*
-+	 * Send pointer position to clients. If not called then Move() calls
-+	 * won't be visible to clients.
-+	 */
-+	void Sync(void);
-+private:
-+	rfb::VNCServerST *server;
-+	DeviceIntPtr dev;
-+	int oldButtonMask;
-+	rfb::Point cursorPos, oldCursorPos;
-+};
-+
-+#endif
-diff --git a/unix/xserver/hw/vnc/Makefile.am b/unix/xserver/hw/vnc/Makefile.am
-index a39a10d..c2e78df 100644
---- a/unix/xserver/hw/vnc/Makefile.am
-+++ b/unix/xserver/hw/vnc/Makefile.am
-@@ -9,9 +9,11 @@ COMMON_LIBS=$(NETWORK_LIB) $(RFB_LIB) $(RDR_LIB) $(XREGION_LIB)
- 
- noinst_LTLIBRARIES = libvnccommon.la
- 
--HDRS = RegionHelper.h vncExtInit.h vncHooks.h XserverDesktop.h xorg-version.h
-+HDRS = RegionHelper.h vncExtInit.h vncHooks.h XserverDesktop.h xorg-version.h \
-+	Input.h
- 
--libvnccommon_la_SOURCES = $(HDRS) vncExtInit.cc vncHooks.cc XserverDesktop.cc
-+libvnccommon_la_SOURCES = $(HDRS) vncExtInit.cc vncHooks.cc XserverDesktop.cc \
-+	Input.cc
- 
- libvnccommon_la_CPPFLAGS = -DVENDOR_RELEASE="$(VENDOR_RELEASE)" \
- 	-DVENDOR_STRING="\"$(VENDOR_STRING)\"" -I$(LIB_DIR) \
-diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc
-index 533f31b..58f70d9 100644
---- a/unix/xserver/hw/vnc/XserverDesktop.cc
-+++ b/unix/xserver/hw/vnc/XserverDesktop.cc
-@@ -42,6 +42,7 @@
- #include "XserverDesktop.h"
- #include "vncExtInit.h"
- #include "xorg-version.h"
-+#include "Input.h"
- 
- extern "C" {
- #define public c_public
-@@ -77,7 +78,6 @@ CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master);
- }
- 
- static DeviceIntPtr vncKeyboardDevice = NULL;
--static DeviceIntPtr vncPointerDevice = NULL;
- #if XORG == 15
- static xEvent *eventq = NULL;
- #else
-@@ -85,7 +85,6 @@ static EventList *eventq = NULL;
- #endif
- 
- static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff);
--static int vfbMouseProc(DeviceIntPtr pDevice, int onoff);
- 
- using namespace rfb;
- using namespace network;
-@@ -180,7 +179,6 @@ XserverDesktop::XserverDesktop(ScreenPtr pScreen_,
-     listener(listener_), httpListener(httpListener_),
-     cmap(0), deferredUpdateTimerSet(false),
-     grabbing(false), ignoreHooks_(false), directFbptr(true),
--    oldButtonMask(0),
-     queryConnectId(0)
- {
-   format = pf;
-@@ -221,14 +219,7 @@ XserverDesktop::XserverDesktop(ScreenPtr pScreen_,
-     RegisterKeyboardDevice(vncKeyboardDevice);
-   }
- 
--  if (vncPointerDevice == NULL) {
--    vncPointerDevice = AddInputDevice(
--#if XORG >= 16
--				      serverClient,
--#endif
--				      vfbMouseProc, TRUE);
--    RegisterPointerDevice(vncPointerDevice);
--  }
-+  pointerDevice = new PointerDevice(server);
- }
- 
- XserverDesktop::~XserverDesktop()
-@@ -237,6 +228,7 @@ XserverDesktop::~XserverDesktop()
-     delete [] data;
-   TimerFree(deferredUpdateTimer);
-   TimerFree(dummyTimer);
-+  delete pointerDevice;
-   delete httpServer;
-   delete server;
- }
-@@ -555,43 +547,9 @@ void XserverDesktop::add_copied(RegionPtr dst, int dx, int dy)
-   }
- }
- 
--void XserverDesktop::positionCursor()
--{
--  if (!cursorPos.equals(oldCursorPos)) {
--    oldCursorPos = cursorPos;
--    (*pScreen->SetCursorPosition) (
--#if XORG >= 16
--				   vncPointerDevice,
--#endif
--				   pScreen, cursorPos.x, cursorPos.y, FALSE);
--    server->setCursorPos(cursorPos);
--    server->tryUpdate();
--  }
--}
--
- void XserverDesktop::blockHandler(fd_set* fds)
- {
-   try {
--#if XORG == 15
--    ScreenPtr screenWithCursor = GetCurrentRootWindow()->drawable.pScreen;
--#else
--    ScreenPtr screenWithCursor =
--	GetCurrentRootWindow(vncPointerDevice)->drawable.pScreen;
--#endif
--    if (screenWithCursor == pScreen) {
--      int x, y;
--      GetSpritePosition(
--#if XORG >= 16
--			vncPointerDevice,
--#endif
--			&x, &y);
--      if (x != cursorPos.x || y != cursorPos.y) {
--        cursorPos = oldCursorPos = Point(x, y);
--        server->setCursorPos(cursorPos);
--        server->tryUpdate();
--      }
--    }
--
-     if (listener)
-       FD_SET(listener->getFd(), fds);
-     if (httpListener)
-@@ -678,7 +636,7 @@ void XserverDesktop::wakeupHandler(fd_set* fds, int nfds)
-         }
-       }
- 
--      positionCursor();
-+      pointerDevice->Sync();
-     }
- 
-     int timeout = server->checkTimeouts();
-@@ -737,63 +695,8 @@ void XserverDesktop::approveConnection(void* opaqueId, bool accept,
- 
- void XserverDesktop::pointerEvent(const Point& pos, int buttonMask)
- {
--  int i, j, n, valuators[2];
--
--  // SetCursorPosition seems to be very expensive (at least on XFree86 3.3.6
--  // for S3), so we delay calling it until positionCursor() is called at the
--  // end of processing a load of RFB.
--  //(*pScreen->SetCursorPosition) (pScreen, pos.x, pos.y, FALSE);
--
--  NewCurrentScreen(
--#if XORG >= 16
--		   vncPointerDevice,
--#endif
--		   pScreen, pos.x, pos.y);
--
--  if (!pos.equals(cursorPos)) {
--    valuators[0] = pos.x;
--    valuators[1] = pos.y;
--
--#if XORG >= 16
--    GetEventList(&eventq);
--#endif
--    n = GetPointerEvents (eventq, vncPointerDevice, MotionNotify, 0,
--			  POINTER_ABSOLUTE, 0, 2, valuators);
--
--    for (i = 0; i < n; i++) {
--      mieqEnqueue (vncPointerDevice,
--#if XORG == 15
--		   eventq + i
--#else
--		   (eventq + i)->event
--#endif
--      );
--    }
--  }
--
--  for (i = 0; i < 5; i++) {
--    if ((buttonMask ^ oldButtonMask) & (1<<i)) {
--      // Do not use the pointer mapping. Treat VNC buttons as logical
--      // buttons.
--      n = GetPointerEvents (eventq, vncPointerDevice,
--			    (buttonMask & (1<<i)) ?
--			     ButtonPress : ButtonRelease,
--			    i + 1, POINTER_RELATIVE, 0, 0, NULL);
--
--      for (j = 0; j < n; j++) {
--	mieqEnqueue (vncPointerDevice,
--#if XORG == 15
--		     eventq + j
--#else
--		     (eventq + j)->event
--#endif
--	);
--      }
--    }
--  }
--
--  cursorPos = pos;
--  oldButtonMask = buttonMask;
-+  pointerDevice->Move(pos);
-+  pointerDevice->ButtonAction(buttonMask);
- }
- 
- void XserverDesktop::clientCutText(const char* str, int len)
-@@ -1481,36 +1384,3 @@ static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff)
-   return Success;
- }
- 
--static int vfbMouseProc(DeviceIntPtr pDevice, int onoff)
--{
--  BYTE map[6];
--  DevicePtr pDev = (DevicePtr)pDevice;
--
--  switch (onoff)
--  {
--  case DEVICE_INIT:
--    map[1] = 1;
--    map[2] = 2;
--    map[3] = 3;
--    map[4] = 4;
--    map[5] = 5;
--    InitPointerDeviceStruct(pDev, map, 5,
--#if XORG == 15
--			    GetMotionHistory,
--#endif
--			    (PtrCtrlProcPtr)NoopDDA, GetMotionHistorySize(), 2);
--    break;
--
--  case DEVICE_ON:
--    pDev->on = TRUE;
--    break;
--
--  case DEVICE_OFF:
--    pDev->on = FALSE;
--    break;
--
--  case DEVICE_CLOSE:
--    break;
--  }
--  return Success;
--}
-diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h
-index 7729d3f..9f300f5 100644
---- a/unix/xserver/hw/vnc/XserverDesktop.h
-+++ b/unix/xserver/hw/vnc/XserverDesktop.h
-@@ -32,6 +32,7 @@
- #include <rfb/Configuration.h>
- #include <rfb/VNCServerST.h>
- #include <rdr/SubstitutingInStream.h>
-+#include "Input.h"
- 
- extern "C" {
- #define class c_class
-@@ -68,7 +69,6 @@ public:
-   void setCursor(CursorPtr cursor);
-   void add_changed(RegionPtr reg);
-   void add_copied(RegionPtr dst, int dx, int dy);
--  void positionCursor();
-   void ignoreHooks(bool b) { ignoreHooks_ = b; }
-   void blockHandler(fd_set* fds);
-   void wakeupHandler(fd_set* fds, int nfds);
-@@ -122,6 +122,7 @@ private:
-                                             pointer arg);
-   void deferUpdate();
-   ScreenPtr pScreen;
-+  PointerDevice *pointerDevice;
-   OsTimerPtr deferredUpdateTimer, dummyTimer;
-   rfb::VNCServerST* server;
-   rfb::HTTPServer* httpServer;
-@@ -133,8 +134,6 @@ private:
-   bool grabbing;
-   bool ignoreHooks_;
-   bool directFbptr;
--  int oldButtonMask;
--  rfb::Point cursorPos, oldCursorPos;
- 
-   void* queryConnectId;
-   rfb::CharArray queryConnectAddress;
--- 
-1.5.6.5
-
-From 845dbbfbb6a2c0e1a4981920121935febe7c0a50 Mon Sep 17 00:00:00 2001
-From: atkac <atkac@3789f03b-4d11-0410-bbf8-ca57d06f2519>
-Date: Fri, 28 Aug 2009 12:05:24 +0000
-Subject: [PATCH] Move keyboard input related code to Input.h and Input.cc.
-
-git-svn-id: https://tigervnc.svn.sourceforge.net/svnroot/tigervnc/trunk@3887 3789f03b-4d11-0410-bbf8-ca57d06f2519
----
- unix/xserver/hw/vnc/Input.cc          |  606 ++++++++++++++++++++++++++++++++-
- unix/xserver/hw/vnc/Input.h           |   13 +
- unix/xserver/hw/vnc/XserverDesktop.cc |  589 +-------------------------------
- unix/xserver/hw/vnc/XserverDesktop.h  |    1 +
- 4 files changed, 622 insertions(+), 587 deletions(-)
-
-diff --git a/unix/xserver/hw/vnc/Input.cc b/unix/xserver/hw/vnc/Input.cc
-index ca279f0..478240c 100644
---- a/unix/xserver/hw/vnc/Input.cc
-+++ b/unix/xserver/hw/vnc/Input.cc
-@@ -21,13 +21,49 @@
- #include <dix-config.h>
- #endif
- 
-+#include <rfb/LogWriter.h>
- #include "Input.h"
- #include "xorg-version.h"
-+#include "vncExtInit.h"
- 
- extern "C" {
-+#define public c_public
-+#define class c_class
-+#include "inputstr.h"
- #include "mi.h"
-+#ifndef XKB_IN_SERVER
-+#define XKB_IN_SERVER
-+#endif
-+#ifdef XKB
-+/*
-+ * This include is needed to use XkbConvertCase instead of XConvertCase even if
-+ * we don't use XKB extension.
-+ */
-+#include <xkbsrv.h>
-+#endif
-+#if XORG >= 16
-+#include "exevents.h"
-+extern void
-+CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master);
-+#endif
-+#include <X11/keysym.h>
-+#include <X11/Xutil.h>
-+#undef public
-+#undef class
- }
- 
-+using namespace rdr;
-+using namespace rfb;
-+
-+static LogWriter vlog("Input");
-+
-+#define BUTTONS 5
-+static int pointerProc(DeviceIntPtr pDevice, int onoff);
-+
-+static int keyboardProc(DeviceIntPtr pDevice, int onoff);
-+static KeySym KeyCodetoKeySym(KeySymsPtr keymap, int keycode, int col);
-+static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col);
-+
- /* Event queue is shared between all devices. */
- #if XORG == 15
- static xEvent *eventq = NULL;
-@@ -70,10 +106,6 @@ static void enqueueEvents(DeviceIntPtr dev, int n)
- 	}
- }
- 
--/* Pointer device pre-declarations */
--#define BUTTONS 5
--static int pointerProc(DeviceIntPtr pDevice, int onoff);
--
- /* Pointer device methods */
- 
- PointerDevice::PointerDevice(rfb::VNCServerST *_server)
-@@ -165,3 +197,569 @@ static int pointerProc(DeviceIntPtr pDevice, int onoff)
- 	return Success;
- }
- 
-+/* KeyboardDevice methods */
-+
-+KeyboardDevice::KeyboardDevice(void)
-+{
-+	dev = AddInputDevice(
-+#if XORG >= 16
-+			     serverClient,
-+#endif
-+			     keyboardProc, TRUE);
-+	RegisterKeyboardDevice(dev);
-+	initEventq();
-+}
-+
-+#define IS_PRESSED(keyc, keycode) \
-+	((keyc)->down[(keycode) >> 3] & (1 << ((keycode) & 7)))
-+
-+/*
-+ * ModifierState is a class which helps simplify generating a "fake" press or
-+ * release of shift, ctrl, alt, etc.  An instance of the class is created for
-+ * every modifier which may need to be pressed or released.  Then either
-+ * press() or release() may be called to make sure that the corresponding keys
-+ * are in the right state.  The destructor of the class automatically reverts
-+ * to the previous state.  Each modifier may have multiple keys associated with
-+ * it, so in the case of a fake release, this may involve releasing more than
-+ * one key.
-+ */
-+
-+class ModifierState {
-+public:
-+	ModifierState(DeviceIntPtr _dev, int _modIndex)
-+		: modIndex(_modIndex), nKeys(0), keys(0), pressed(false),
-+		  dev(_dev) {}
-+
-+	~ModifierState()
-+	{
-+		for (int i = 0; i < nKeys; i++)
-+			generateXKeyEvent(keys[i], !pressed);
-+		delete [] keys;
-+	}
-+
-+	void press()
-+	{
-+		KeyClassPtr keyc = dev->key;
-+		if (!(keyc->state & (1 << modIndex))) {
-+			int index = modIndex * keyc->maxKeysPerModifier;
-+			tempKeyEvent(keyc->modifierKeyMap[index], true);
-+			pressed = true;
-+		}
-+	}
-+
-+	void release()
-+	{
-+		KeyClassPtr keyc = dev->key;
-+		if ((keyc->state & (1 << modIndex)) == 0)
-+			return;
-+
-+		for (int k = 0; k < keyc->maxKeysPerModifier; k++) {
-+			int index = modIndex * keyc->maxKeysPerModifier + k;
-+			int keycode = keyc->modifierKeyMap[index];
-+			if (keycode && IS_PRESSED(keyc, keycode))
-+				tempKeyEvent(keycode, false);
-+		}
-+	}
-+
-+private:
-+	void tempKeyEvent(int keycode, bool down)
-+	{
-+		if (keycode) {
-+			if (!keys) keys = new int[dev->key->maxKeysPerModifier];
-+			keys[nKeys++] = keycode;
-+			generateXKeyEvent(keycode, down);
-+		}
-+	}
-+
-+	void generateXKeyEvent(int keycode, bool down)
-+	{
-+		int n, action;
-+
-+		action = down ? KeyPress : KeyRelease;
-+		n = GetKeyboardEvents(eventq, dev, action, keycode);
-+		enqueueEvents(dev, n);
-+
-+		vlog.debug("fake keycode %d %s", keycode,
-+			   down ? "down" : "up");
-+	}
-+
-+	int modIndex;
-+	int nKeys;
-+	int *keys;
-+	bool pressed;
-+	DeviceIntPtr dev;
-+};
-+
-+
-+/* altKeysym is a table of alternative keysyms which have the same meaning. */
-+
-+static struct altKeysym_t {
-+	KeySym a, b;
-+} altKeysym[] = {
-+	{ XK_Shift_L,		XK_Shift_R },
-+	{ XK_Control_L,		XK_Control_R },
-+	{ XK_Meta_L,		XK_Meta_R },
-+	{ XK_Alt_L,		XK_Alt_R },
-+	{ XK_Super_L,		XK_Super_R },
-+	{ XK_Hyper_L,		XK_Hyper_R },
-+	{ XK_KP_Space,		XK_space },
-+	{ XK_KP_Tab,		XK_Tab },
-+	{ XK_KP_Enter,		XK_Return },
-+	{ XK_KP_F1,		XK_F1 },
-+	{ XK_KP_F2,		XK_F2 },
-+	{ XK_KP_F3,		XK_F3 },
-+	{ XK_KP_F4,		XK_F4 },
-+	{ XK_KP_Home,		XK_Home },
-+	{ XK_KP_Left,		XK_Left },
-+	{ XK_KP_Up,		XK_Up },
-+	{ XK_KP_Right,		XK_Right },
-+	{ XK_KP_Down,		XK_Down },
-+	{ XK_KP_Page_Up,	XK_Page_Up },
-+	{ XK_KP_Page_Down,	XK_Page_Down },
-+	{ XK_KP_End,		XK_End },
-+	{ XK_KP_Begin,		XK_Begin },
-+	{ XK_KP_Insert,		XK_Insert },
-+	{ XK_KP_Delete,		XK_Delete },
-+	{ XK_KP_Equal,		XK_equal },
-+	{ XK_KP_Multiply,	XK_asterisk },
-+	{ XK_KP_Add,		XK_plus },
-+	{ XK_KP_Separator,	XK_comma },
-+	{ XK_KP_Subtract,	XK_minus },
-+	{ XK_KP_Decimal,	XK_period },
-+	{ XK_KP_Divide,		XK_slash },
-+	{ XK_KP_0,		XK_0 },
-+	{ XK_KP_1,		XK_1 },
-+	{ XK_KP_2,		XK_2 },
-+	{ XK_KP_3,		XK_3 },
-+	{ XK_KP_4,		XK_4 },
-+	{ XK_KP_5,		XK_5 },
-+	{ XK_KP_6,		XK_6 },
-+	{ XK_KP_7,		XK_7 },
-+	{ XK_KP_8,		XK_8 },
-+	{ XK_KP_9,		XK_9 },
-+};
-+
-+/*
-+ * keyEvent() - work out the best keycode corresponding to the keysym sent by
-+ * the viewer.  This is non-trivial because we can't assume much about the
-+ * local keyboard layout.  We must also find out which column of the keyboard
-+ * mapping the keysym is in, and alter the shift state appropriately.  Column 0
-+ * means both shift and "mode_switch" (AltGr) must be released, column 1 means
-+ * shift must be pressed and mode_switch released, column 2 means shift must be
-+ * released and mode_switch pressed, and column 3 means both shift and
-+ * mode_switch must be pressed.
-+ *
-+ * Magic, which dynamically adds keysym<->keycode mapping depends on X.Org
-+ * version. Quick explanation of that "magic":
-+ * 
-+ * 1.5
-+ * - has only one core keyboard so we have to keep core keyboard mapping
-+ *   synchronized with vncKeyboardDevice. Do it via SwitchCoreKeyboard()
-+ *
-+ * 1.6 (aka MPX - Multi pointer X)
-+ * - multiple master devices (= core devices) exists, keep vncKeyboardDevice
-+ *   synchronized with proper master device
-+ */
-+
-+void KeyboardDevice::keyEvent(rdr::U32 keysym, bool down)
-+{
-+	DeviceIntPtr master;
-+	KeyClassPtr keyc = dev->key;
-+	KeySymsPtr keymap = &keyc->curKeySyms;
-+	KeySym *map = keymap->map;
-+	KeyCode minKeyCode = keymap->minKeyCode;
-+	KeyCode maxKeyCode = keymap->maxKeyCode;
-+	int mapWidth = keymap->mapWidth;
-+	unsigned int i, n;
-+	int j, k, action;
-+
-+	if (keysym == XK_Caps_Lock) {
-+		vlog.debug("Ignoring caps lock");
-+		return;
-+	}
-+
-+	/* find which modifier Mode_switch is on. */
-+	int modeSwitchMapIndex = 0;
-+	for (i = 3; i < 8; i++) {
-+		for (k = 0; k < keyc->maxKeysPerModifier; k++) {
-+			int index = i * keyc->maxKeysPerModifier + k;
-+			int keycode = keyc->modifierKeyMap[index];
-+
-+			if (keycode == 0)
-+				continue;
-+
-+			for (j = 0; j < mapWidth; j++) {
-+				if (map[(keycode - minKeyCode) * mapWidth + j]
-+				    == XK_Mode_switch) {
-+					modeSwitchMapIndex = i;
-+					goto ModeSwitchFound;
-+				}
-+			}
-+		}
-+	}
-+ModeSwitchFound:
-+
-+	int col = 0;
-+	if ((keyc->state & (1 << ShiftMapIndex)) != 0)
-+		col |= 1;
-+	if (modeSwitchMapIndex != 0 &&
-+	    ((keyc->state & (1 << modeSwitchMapIndex))) != 0)
-+		col |= 2;
-+
-+	int kc = KeysymToKeycode(keymap, keysym, &col);
-+
-+	/*
-+	 * Sort out the "shifted Tab" mess.  If we are sent a shifted Tab,
-+	 * generate a local shifted Tab regardless of what the "shifted Tab"
-+	 * keysym is on the local keyboard (it might be Tab, ISO_Left_Tab or
-+	 * HP's private BackTab keysym, and quite possibly some others too).
-+	 * We never get ISO_Left_Tab here because it's already been translated
-+	 * in VNCSConnectionST.
-+	 */
-+	if (keysym == XK_Tab && ((keyc->state & (1 << ShiftMapIndex))) != 0)
-+		col |= 1;
-+
-+	if (kc == 0) {
-+		/*
-+		 * Not a direct match in the local keyboard mapping.  Check for
-+		 * alternative keysyms with the same meaning.
-+		 */
-+		for (i = 0; i < sizeof(altKeysym) / sizeof(altKeysym_t); i++) {
-+			if (keysym == altKeysym[i].a)
-+				kc = KeysymToKeycode(keymap, altKeysym[i].b,
-+						     &col);
-+			else if (keysym == altKeysym[i].b)
-+				kc = KeysymToKeycode(keymap, altKeysym[i].a,
-+						     &col);
-+			if (kc)
-+				break;
-+		}
-+	}
-+
-+	if (kc == 0) {
-+		/* Dynamically add a new key to the keyboard mapping. */
-+		for (kc = maxKeyCode; kc >= minKeyCode; kc--) {
-+			if (map[(kc - minKeyCode) * mapWidth] != 0)
-+				continue;
-+
-+			map[(kc - minKeyCode) * mapWidth] = keysym;
-+			col = 0;
-+
-+			vlog.info("Added unknown keysym 0x%x to keycode %d",
-+				  keysym, kc);
-+#if XORG == 15
-+			master = inputInfo.keyboard;
-+#else
-+			master = dev->u.master;
-+#endif
-+			void *slave = dixLookupPrivate(&master->devPrivates,
-+						       CoreDevicePrivateKey);
-+			if (dev == slave) {
-+				dixSetPrivate(&master->devPrivates,
-+					      CoreDevicePrivateKey, NULL);
-+#if XORG == 15
-+				SwitchCoreKeyboard(dev);
-+#else
-+				CopyKeyClass(dev, master);
-+#endif
-+			}
-+			break;
-+		}
-+	}
-+
-+	if (kc < minKeyCode) {
-+		vlog.info("Keyboard mapping full - ignoring unknown keysym "
-+			  "0x%x",keysym);
-+		return;
-+	}
-+
-+	/*
-+	 * See if it's a modifier key.  If so, then don't do any auto-repeat,
-+	 * because the X server will translate each press into a release
-+	 * followed by a press.
-+	 */
-+	for (i = 0; i < 8; i++) {
-+		for (k = 0; k < keyc->maxKeysPerModifier; k++) {
-+			int index = i * keyc->maxKeysPerModifier + k;
-+			if (kc == keyc->modifierKeyMap[index] &&
-+			    IS_PRESSED(keyc,kc) && down)
-+				return;
-+		}
-+	}
-+
-+	ModifierState shift(dev, ShiftMapIndex);
-+	ModifierState modeSwitch(dev, modeSwitchMapIndex);
-+	if (down) {
-+		if (col & 1)
-+			shift.press();
-+		else
-+			shift.release();
-+		if (modeSwitchMapIndex) {
-+			if (col & 2)
-+				modeSwitch.press();
-+			else
-+				modeSwitch.release();
-+		}
-+	}
-+
-+	vlog.debug("keycode %d %s", kc, down ? "down" : "up");
-+	action = down ? KeyPress : KeyRelease;
-+	n = GetKeyboardEvents(eventq, dev, action, kc);
-+	enqueueEvents(dev, n);
-+}
-+
-+static KeySym KeyCodetoKeySym(KeySymsPtr keymap, int keycode, int col)
-+{
-+	int per = keymap->mapWidth;
-+	KeySym *syms;
-+	KeySym lsym, usym;
-+
-+	if ((col < 0) || ((col >= per) && (col > 3)) ||
-+	    (keycode < keymap->minKeyCode) || (keycode > keymap->maxKeyCode))
-+		return NoSymbol;
-+
-+	syms = &keymap->map[(keycode - keymap->minKeyCode) * per];
-+	if (col >= 4)
-+		return syms[col];
-+
-+	if (col > 1) {
-+		while ((per > 2) && (syms[per - 1] == NoSymbol))
-+			per--;
-+		if (per < 3)
-+			col -= 2;
-+	}
-+
-+	if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) {
-+		XConvertCase(syms[col&~1], &lsym, &usym);
-+		if (!(col & 1))
-+			return lsym;
-+		/*
-+		 * I'm commenting out this logic because it's incorrect even
-+		 * though it was copied from the Xlib sources.  The X protocol
-+		 * book quite clearly states that where a group consists of
-+		 * element 1 being a non-alphabetic keysym and element 2 being
-+		 * NoSymbol that you treat the second element as being the
-+		 * same as the first.  This also tallies with the behaviour
-+		 * produced by the installed Xlib on my linux box (I believe
-+		 * this is because it uses some XKB code rather than the
-+		 * original Xlib code - compare XKBBind.c with KeyBind.c in
-+		 * lib/X11).
-+		 */
-+#if 0
-+		else if (usym == lsym)
-+			return NoSymbol;
-+#endif
-+		else
-+			return usym;
-+	}
-+
-+	return syms[col];
-+}
-+
-+/*
-+ * KeysymToKeycode() - find the keycode and column corresponding to the given
-+ * keysym.  The value of col passed in should be the column determined from the
-+ * current shift state.  If the keysym can be found in that column we prefer
-+ * that to finding it in a different column (which would require fake events to
-+ * alter the shift state).
-+ */
-+static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col)
-+{
-+	int i, j;
-+
-+	j = *col;
-+	for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) {
-+		if (KeyCodetoKeySym(keymap, i, j) == ks)
-+			return i;
-+	}
-+
-+	for (j = 0; j < keymap->mapWidth; j++) {
-+		for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) {
-+			if (KeyCodetoKeySym(keymap, i, j) == ks) {
-+				*col = j;
-+				return i;
-+			}
-+		}
-+	}
-+
-+	return 0;
-+}
-+
-+/* Fairly standard US PC Keyboard */
-+
-+#define MIN_KEY 8
-+#define MAX_KEY 255
-+#define MAP_LEN (MAX_KEY - MIN_KEY + 1)
-+#define KEYSYMS_PER_KEY 2
-+KeySym keyboardMap[MAP_LEN * KEYSYMS_PER_KEY] = {
-+	NoSymbol, NoSymbol,
-+	XK_Escape, NoSymbol,
-+	XK_1, XK_exclam,
-+	XK_2, XK_at,
-+	XK_3, XK_numbersign,
-+	XK_4, XK_dollar,
-+	XK_5, XK_percent,
-+	XK_6, XK_asciicircum,
-+	XK_7, XK_ampersand,
-+	XK_8, XK_asterisk,
-+	XK_9, XK_parenleft,
-+	XK_0, XK_parenright,
-+	XK_minus, XK_underscore,
-+	XK_equal, XK_plus,
-+	XK_BackSpace, NoSymbol,
-+	XK_Tab, NoSymbol,
-+	XK_q, XK_Q,
-+	XK_w, XK_W,
-+	XK_e, XK_E,
-+	XK_r, XK_R,
-+	XK_t, XK_T,
-+	XK_y, XK_Y,
-+	XK_u, XK_U,
-+	XK_i, XK_I,
-+	XK_o, XK_O,
-+	XK_p, XK_P,
-+	XK_bracketleft, XK_braceleft,
-+	XK_bracketright, XK_braceright,
-+	XK_Return, NoSymbol,
-+	XK_Control_L, NoSymbol,
-+	XK_a, XK_A,
-+	XK_s, XK_S,
-+	XK_d, XK_D,
-+	XK_f, XK_F,
-+	XK_g, XK_G,
-+	XK_h, XK_H,
-+	XK_j, XK_J,
-+	XK_k, XK_K,
-+	XK_l, XK_L,
-+	XK_semicolon, XK_colon,
-+	XK_apostrophe, XK_quotedbl,
-+	XK_grave, XK_asciitilde,
-+	XK_Shift_L, NoSymbol,
-+	XK_backslash, XK_bar,
-+	XK_z, XK_Z,
-+	XK_x, XK_X,
-+	XK_c, XK_C,
-+	XK_v, XK_V,
-+	XK_b, XK_B,
-+	XK_n, XK_N,
-+	XK_m, XK_M,
-+	XK_comma, XK_less,
-+	XK_period, XK_greater,
-+	XK_slash, XK_question,
-+	XK_Shift_R, NoSymbol,
-+	XK_KP_Multiply, NoSymbol,
-+	XK_Alt_L, XK_Meta_L,
-+	XK_space, NoSymbol,
-+	/* XK_Caps_Lock */ NoSymbol, NoSymbol,
-+	XK_F1, NoSymbol,
-+	XK_F2, NoSymbol,
-+	XK_F3, NoSymbol,
-+	XK_F4, NoSymbol,
-+	XK_F5, NoSymbol,
-+	XK_F6, NoSymbol,
-+	XK_F7, NoSymbol,
-+	XK_F8, NoSymbol,
-+	XK_F9, NoSymbol,
-+	XK_F10, NoSymbol,
-+	XK_Num_Lock, XK_Pointer_EnableKeys,
-+	XK_Scroll_Lock, NoSymbol,
-+	XK_KP_Home, XK_KP_7,
-+	XK_KP_Up, XK_KP_8,
-+	XK_KP_Prior, XK_KP_9,
-+	XK_KP_Subtract, NoSymbol,
-+	XK_KP_Left, XK_KP_4,
-+	XK_KP_Begin, XK_KP_5,
-+	XK_KP_Right, XK_KP_6,
-+	XK_KP_Add, NoSymbol,
-+	XK_KP_End, XK_KP_1,
-+	XK_KP_Down, XK_KP_2,
-+	XK_KP_Next, XK_KP_3,
-+	XK_KP_Insert, XK_KP_0,
-+	XK_KP_Delete, XK_KP_Decimal,
-+	NoSymbol, NoSymbol,
-+	NoSymbol, NoSymbol,
-+	NoSymbol, NoSymbol,
-+	XK_F11, NoSymbol,
-+	XK_F12, NoSymbol,
-+	XK_Home, NoSymbol,
-+	XK_Up, NoSymbol,
-+	XK_Prior, NoSymbol,
-+	XK_Left, NoSymbol,
-+	NoSymbol, NoSymbol,
-+	XK_Right, NoSymbol,
-+	XK_End, NoSymbol,
-+	XK_Down, NoSymbol,
-+	XK_Next, NoSymbol,
-+	XK_Insert, NoSymbol,
-+	XK_Delete, NoSymbol,
-+	XK_KP_Enter, NoSymbol,
-+	XK_Control_R, NoSymbol,
-+	XK_Pause, XK_Break,
-+	XK_Print, XK_Execute,
-+	XK_KP_Divide, NoSymbol,
-+	XK_Alt_R, XK_Meta_R,
-+};
-+
-+static Bool GetMappings(KeySymsPtr pKeySyms, CARD8 *pModMap)
-+{
-+	int i;
-+
-+	for (i = 0; i < MAP_LENGTH; i++)
-+		pModMap[i] = NoSymbol;
-+
-+	for (i = 0; i < MAP_LEN; i++) {
-+		if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Caps_Lock)
-+			pModMap[i + MIN_KEY] = LockMask;
-+		else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_L ||
-+			 keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_R)
-+			pModMap[i + MIN_KEY] = ShiftMask;
-+		else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_L ||
-+			 keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_R)
-+			pModMap[i + MIN_KEY] = ControlMask;
-+		else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_L ||
-+			 keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_R)
-+			pModMap[i + MIN_KEY] = Mod1Mask;
-+	}
-+
-+	pKeySyms->minKeyCode = MIN_KEY;
-+	pKeySyms->maxKeyCode = MAX_KEY;
-+	pKeySyms->mapWidth = KEYSYMS_PER_KEY;
-+	pKeySyms->map = keyboardMap;
-+
-+	return TRUE;
-+}
-+
-+static void keyboardBell(int percent, DeviceIntPtr device, pointer ctrl,
-+			 int class_)
-+{
-+	if (percent > 0)
-+		vncBell();
-+}
-+
-+static int keyboardProc(DeviceIntPtr pDevice, int onoff)
-+{
-+	KeySymsRec keySyms;
-+	CARD8 modMap[MAP_LENGTH];
-+	DevicePtr pDev = (DevicePtr)pDevice;
-+
-+	switch (onoff) {
-+	case DEVICE_INIT:
-+		GetMappings(&keySyms, modMap);
-+		InitKeyboardDeviceStruct(pDev, &keySyms, modMap, keyboardBell,
-+					 (KbdCtrlProcPtr)NoopDDA);
-+		break;
-+	case DEVICE_ON:
-+		pDev->on = TRUE;
-+		break;
-+	case DEVICE_OFF:
-+		pDev->on = FALSE;
-+		break;
-+#if 0
-+	case DEVICE_CLOSE:
-+		break;
-+#endif
-+	}
-+
-+	return Success;
-+}
-+
-diff --git a/unix/xserver/hw/vnc/Input.h b/unix/xserver/hw/vnc/Input.h
-index 49cedf2..1bfec92 100644
---- a/unix/xserver/hw/vnc/Input.h
-+++ b/unix/xserver/hw/vnc/Input.h
-@@ -58,4 +58,17 @@ private:
- 	rfb::Point cursorPos, oldCursorPos;
- };
- 
-+/* Represents keyboard device. */
-+class KeyboardDevice {
-+public:
-+	/* Create new Keyboard device instance. */
-+	KeyboardDevice(void);
-+
-+	void Press(rdr::U32 keysym) { keyEvent(keysym, true); }
-+	void Release(rdr::U32 keysym) { keyEvent(keysym, false); }
-+private:
-+	void keyEvent(rdr::U32 keysym, bool down);
-+	DeviceIntPtr dev;
-+};
-+
- #endif
-diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc
-index 58f70d9..66c92d2 100644
---- a/unix/xserver/hw/vnc/XserverDesktop.cc
-+++ b/unix/xserver/hw/vnc/XserverDesktop.cc
-@@ -50,26 +50,7 @@ extern "C" {
- 
- extern char *display;
- 
--#include "inputstr.h"
--#include "servermd.h"
- #include "colormapst.h"
--#include "resource.h"
--#include "cursorstr.h"
--#include "windowstr.h"
--#include "mi.h"
--#define XK_CYRILLIC
--#include <X11/keysym.h>
--#ifndef XKB_IN_SERVER
--#define XKB_IN_SERVER
--#endif
--#ifdef XKB
--#include <xkbsrv.h>
--#endif
--#if XORG >= 16
--#include "exevents.h"
--extern void
--CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master);
--#endif
- #ifdef RANDR
- #include "randrstr.h"
- #endif
-@@ -77,15 +58,6 @@ CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master);
- #undef class
- }
- 
--static DeviceIntPtr vncKeyboardDevice = NULL;
--#if XORG == 15
--static xEvent *eventq = NULL;
--#else
--static EventList *eventq = NULL;
--#endif
--
--static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff);
--
- using namespace rfb;
- using namespace network;
- 
-@@ -102,8 +74,6 @@ IntParameter queryConnectTimeout("QueryConnectTimeout",
-                                  "rejecting the connection",
-                                  10);
- 
--static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col);
--
- static rdr::U8 reverseBits[] = {
-   0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0,
-   0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
-@@ -193,33 +163,8 @@ XserverDesktop::XserverDesktop(ScreenPtr pScreen_,
-   if (httpListener)
-     httpServer = new FileHTTPServer(this);
- 
--#if XORG == 15
--  /*
--   * XXX eventq is never free()-ed because it has to exist during server life
--   * */
--  if (!eventq)
--    eventq = (xEvent *) xcalloc(sizeof(xEvent), GetMaximumEventsNum());
--  if (!eventq)
--    FatalError("Couldn't allocate eventq\n");
--#else
--  GetEventList(&eventq);
--#endif
--
--  /*
--   * NOTE:
--   * We _might_ have to call ActivateDevice function for both keyboard and
--   * mouse. For Xvnc it's not needed but I have to check libvnc.so module.
--   */
--  if (vncKeyboardDevice == NULL) {
--    vncKeyboardDevice = AddInputDevice(
--#if XORG >= 16
--				       serverClient,
--#endif
--				       vfbKeybdProc, TRUE);
--    RegisterKeyboardDevice(vncKeyboardDevice);
--  }
--
-   pointerDevice = new PointerDevice(server);
-+  keyboardDevice = new KeyboardDevice();
- }
- 
- XserverDesktop::~XserverDesktop()
-@@ -229,6 +174,7 @@ XserverDesktop::~XserverDesktop()
-   TimerFree(deferredUpdateTimer);
-   TimerFree(dummyTimer);
-   delete pointerDevice;
-+  delete keyboardDevice;
-   delete httpServer;
-   delete server;
- }
-@@ -854,550 +800,10 @@
-   }
- }
- 
--//
--// Keyboard handling
--//
--
--#define IS_PRESSED(keyc, keycode) \
--  ((keyc)->down[(keycode) >> 3] & (1 << ((keycode) & 7)))
--
--// ModifierState is a class which helps simplify generating a "fake" press
--// or release of shift, ctrl, alt, etc.  An instance of the class is created
--// for every modifier which may need to be pressed or released.  Then either
--// press() or release() may be called to make sure that the corresponding keys
--// are in the right state.  The destructor of the class automatically reverts
--// to the previous state.  Each modifier may have multiple keys associated with
--// it, so in the case of a fake release, this may involve releasing more than
--// one key.
--
--class ModifierState {
--public:
--  ModifierState(int modIndex_)
--    : modIndex(modIndex_), nKeys(0), keys(0), pressed(false)
--  {
--  }
--  ~ModifierState() {
--    for (int i = 0; i < nKeys; i++)
--      generateXKeyEvent(keys[i], !pressed);
--    delete [] keys;
--  }
--  void press() {
--    KeyClassPtr keyc = vncKeyboardDevice->key;
--    if (!(keyc->state & (1<<modIndex))) {
--      tempKeyEvent(keyc->modifierKeyMap[modIndex * keyc->maxKeysPerModifier],
--                   true);
--      pressed = true;
--    }
--  }
--  void release() {
--    KeyClassPtr keyc = vncKeyboardDevice->key;
--    if (keyc->state & (1<<modIndex)) {
--      for (int k = 0; k < keyc->maxKeysPerModifier; k++) {
--        int keycode
--          = keyc->modifierKeyMap[modIndex * keyc->maxKeysPerModifier + k];
--        if (keycode && IS_PRESSED(keyc, keycode))
--          tempKeyEvent(keycode, false);
--      }
--    }
--  }
--private:
--  void tempKeyEvent(int keycode, bool down) {
--    if (keycode) {
--      if (!keys) keys = new int[vncKeyboardDevice->key->maxKeysPerModifier];
--      keys[nKeys++] = keycode;
--      generateXKeyEvent(keycode, down);
--    }
--  }
--  void generateXKeyEvent(int keycode, bool down) {
--    int i, n;
--    n = GetKeyboardEvents (eventq, vncKeyboardDevice,
--			   down ? KeyPress : KeyRelease, keycode);
--    for (i = 0; i < n; i++) {
--      mieqEnqueue (vncKeyboardDevice,
--#if XORG == 15
--		   eventq + i
--#else
--		   (eventq + i)->event
--#endif
--      );
--    }
--    vlog.debug("fake keycode %d %s", keycode, down ? "down" : "up");
--  }
--  int modIndex;
--  int nKeys;
--  int* keys;
--  bool pressed;
--};
--
--
--// altKeysym is a table of alternative keysyms which have the same meaning.
--
--struct altKeysym_t {
--  KeySym a, b;
--};
--
--altKeysym_t altKeysym[] = {
--  { XK_Shift_L,        XK_Shift_R },
--  { XK_Control_L,      XK_Control_R },
--  { XK_Meta_L,         XK_Meta_R },
--  { XK_Alt_L,          XK_Alt_R },
--  { XK_Super_L,        XK_Super_R },
--  { XK_Hyper_L,        XK_Hyper_R },
--  { XK_KP_Space,       XK_space },
--  { XK_KP_Tab,         XK_Tab },
--  { XK_KP_Enter,       XK_Return },
--  { XK_KP_F1,          XK_F1 },
--  { XK_KP_F2,          XK_F2 },
--  { XK_KP_F3,          XK_F3 },
--  { XK_KP_F4,          XK_F4 },
--  { XK_KP_Home,        XK_Home },
--  { XK_KP_Left,        XK_Left },
--  { XK_KP_Up,          XK_Up },
--  { XK_KP_Right,       XK_Right },
--  { XK_KP_Down,        XK_Down },
--  { XK_KP_Page_Up,     XK_Page_Up },
--  { XK_KP_Page_Down,   XK_Page_Down },
--  { XK_KP_End,         XK_End },
--  { XK_KP_Begin,       XK_Begin },
--  { XK_KP_Insert,      XK_Insert },
--  { XK_KP_Delete,      XK_Delete },
--  { XK_KP_Equal,       XK_equal },
--  { XK_KP_Multiply,    XK_asterisk },
--  { XK_KP_Add,         XK_plus },
--  { XK_KP_Separator,   XK_comma },
--  { XK_KP_Subtract,    XK_minus },
--  { XK_KP_Decimal,     XK_period },
--  { XK_KP_Divide,      XK_slash },
--  { XK_KP_0,           XK_0 },
--  { XK_KP_1,           XK_1 },
--  { XK_KP_2,           XK_2 },
--  { XK_KP_3,           XK_3 },
--  { XK_KP_4,           XK_4 },
--  { XK_KP_5,           XK_5 },
--  { XK_KP_6,           XK_6 },
--  { XK_KP_7,           XK_7 },
--  { XK_KP_8,           XK_8 },
--  { XK_KP_9,           XK_9 },
--};
--
--/*
-- * keyEvent() - work out the best keycode corresponding to the keysym sent by
-- * the viewer.  This is non-trivial because we can't assume much about the
-- * local keyboard layout.  We must also find out which column of the keyboard
-- * mapping the keysym is in, and alter the shift state appropriately.  Column 0
-- * means both shift and "mode_switch" (AltGr) must be released, column 1 means
-- * shift must be pressed and mode_switch released, column 2 means shift must be
-- * released and mode_switch pressed, and column 3 means both shift and
-- * mode_switch must be pressed.
-- *
-- * Magic, which dynamically adds keysym<->keycode mapping depends on X.Org
-- * version. Quick explanation of that "magic":
-- * 
-- * 1.5
-- * - has only one core keyboard so we have to keep core keyboard mapping
-- *   synchronized with vncKeyboardDevice. Do it via SwitchCoreKeyboard()
-- *
-- * 1.6 (aka MPX - Multi pointer X)
-- * - multiple master devices (= core devices) exists, keep vncKeyboardDevice
-- *   synchronized with proper master device
-- */
--
- void XserverDesktop::keyEvent(rdr::U32 keysym, bool down)
- {
--  DeviceIntPtr master;
--  KeyClassPtr keyc = vncKeyboardDevice->key;
--  KeySymsPtr keymap = &keyc->curKeySyms;
--  unsigned int i, n;
--  int j, k;
--
--  /* 
--   * Since we are checking the current state to determine if we need
--   * to fake modifiers, we must make sure that everything put on the
--   * input queue is processed before we start. Otherwise, shift may be
--   * stuck down.
--   */ 
--  mieqProcessInputEvents();
--
--  if (keysym == XK_Caps_Lock) {
--    vlog.debug("Ignoring caps lock");
--    return;
--  }
--
--  // find which modifier Mode_switch is on.
--  int modeSwitchMapIndex = 0;
--  for (i = 3; i < 8; i++) {
--    for (k = 0; k < keyc->maxKeysPerModifier; k++) {
--      int keycode = keyc->modifierKeyMap[i * keyc->maxKeysPerModifier + k];
--      for (j = 0; j < keymap->mapWidth; j++) {
--        if (keycode != 0 &&
--            keymap->map[(keycode - keymap->minKeyCode)
--                        * keymap->mapWidth + j] == XK_Mode_switch)
--        {
--          modeSwitchMapIndex = i;
--          break;
--        }
--      }
--    }
--  }
--
--  int col = 0;
--  if (keyc->state & (1<<ShiftMapIndex)) col |= 1;
--  if (modeSwitchMapIndex && (keyc->state & (1<<modeSwitchMapIndex))) col |= 2;
--
--  int kc = KeysymToKeycode(keymap, keysym, &col);
--
--  // Sort out the "shifted Tab" mess.  If we are sent a shifted Tab, generate a
--  // local shifted Tab regardless of what the "shifted Tab" keysym is on the
--  // local keyboard (it might be Tab, ISO_Left_Tab or HP's private BackTab
--  // keysym, and quite possibly some others too).  We never get ISO_Left_Tab
--  // here because it's already been translated in VNCSConnectionST.
--  if (keysym == XK_Tab && (keyc->state & (1<<ShiftMapIndex)))
--    col |= 1;
--
--  if (kc == 0) {
--    // Not a direct match in the local keyboard mapping.  Check for alternative
--    // keysyms with the same meaning.
--    for (i = 0; i < sizeof(altKeysym) / sizeof(altKeysym_t); i++) {
--      if (keysym == altKeysym[i].a)
--        kc = KeysymToKeycode(keymap, altKeysym[i].b, &col);
--      else if (keysym == altKeysym[i].b)
--        kc = KeysymToKeycode(keymap, altKeysym[i].a, &col);
--      if (kc) break;
--    }
--  }
--
--  if (kc == 0) {
--    // Last resort - dynamically add a new key to the keyboard mapping.
--    for (kc = keymap->maxKeyCode; kc >= keymap->minKeyCode; kc--) {
--      if (!keymap->map[(kc - keymap->minKeyCode) * keymap->mapWidth]) {
--        keymap->map[(kc - keymap->minKeyCode) * keymap->mapWidth] = keysym;
--        col = 0;
--
--	vlog.info("Added unknown keysym 0x%x to keycode %d",keysym,kc);
--
--#if XORG == 15
--	master = inputInfo.keyboard;
--#else
--	master = vncKeyboardDevice->u.master;
--#endif
--	if (vncKeyboardDevice ==
--	    dixLookupPrivate(&master->devPrivates, CoreDevicePrivateKey)) {
--	  dixSetPrivate(&master->devPrivates, CoreDevicePrivateKey, NULL);
--#if XORG == 15
--	  SwitchCoreKeyboard(vncKeyboardDevice);
--#else
--	  CopyKeyClass(vncKeyboardDevice, master);
--#endif
--	}
--        break;
--      }
--    }
--    if (kc < keymap->minKeyCode) {
--      vlog.info("Keyboard mapping full - ignoring unknown keysym 0x%x",keysym);
--      return;
--    }
--  }
--
--  // See if it's a modifier key.  If so, then don't do any auto-repeat, because
--  // the X server will translate each press into a release followed by a press.
--  for (i = 0; i < 8; i++) {
--    for (k = 0; k < keyc->maxKeysPerModifier; k++) {
--      if (kc == keyc->modifierKeyMap[i * keyc->maxKeysPerModifier + k] &&
--          IS_PRESSED(keyc,kc) && down)
--        return;
--    }
--  }
--
--  ModifierState shift(ShiftMapIndex);
--  ModifierState modeSwitch(modeSwitchMapIndex);
--  if (down) {
--    if (col & 1)
--      shift.press();
--    else
--      shift.release();
--    if (modeSwitchMapIndex) {
--      if (col & 2)
--        modeSwitch.press();
--      else
--        modeSwitch.release();
--    }
--  }
--  vlog.debug("keycode %d %s", kc, down ? "down" : "up");
--  n = GetKeyboardEvents (eventq, vncKeyboardDevice, down ?
--			 KeyPress : KeyRelease, kc);
--  for (i = 0; i < n; i++) {
--    mieqEnqueue (vncKeyboardDevice,
--#if XORG == 15
--		 eventq + i
--#else
--		 (eventq + i)->event
--#endif
--    );
--  }
--
--  /*
--   * When faking a modifier we are putting a keycode (which can
--   * currently activate the desired modifier) on the input
--   * queue. A future modmap change can change the mapping so
--   * that this keycode means something else entirely. Guard
--   * against this by processing the queue now.
--   */
--  mieqProcessInputEvents();
-+	if (down)
-+		keyboardDevice->Press(keysym);
-+	else
-+		keyboardDevice->Release(keysym);
- }
--
--static KeySym KeyCodetoKeySym(KeySymsPtr keymap, int keycode, int col)
--{
--  register int per = keymap->mapWidth;
--  register KeySym *syms;
--  KeySym lsym, usym;
--
--  if ((col < 0) || ((col >= per) && (col > 3)) ||
--      (keycode < keymap->minKeyCode) || (keycode > keymap->maxKeyCode))
--    return NoSymbol;
--
--  syms = &keymap->map[(keycode - keymap->minKeyCode) * per];
--  if (col < 4) {
--    if (col > 1) {
--      while ((per > 2) && (syms[per - 1] == NoSymbol))
--        per--;
--      if (per < 3)
--        col -= 2;
--    }
--    if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) {
--      XConvertCase(syms[col&~1], &lsym, &usym);
--      if (!(col & 1))
--        return lsym;
--      // I'm commenting out this logic because it's incorrect even though it
--      // was copied from the Xlib sources.  The X protocol book quite clearly
--      // states that where a group consists of element 1 being a non-alphabetic
--      // keysym and element 2 being NoSymbol that you treat the second element
--      // as being the same as the first.  This also tallies with the behaviour
--      // produced by the installed Xlib on my linux box (I believe this is
--      // because it uses some XKB code rather than the original Xlib code -
--      // compare XKBBind.c with KeyBind.c in lib/X11).
--      // else if (usym == lsym)
--      //   return NoSymbol;
--      else
--        return usym;
--    }
--  }
--  return syms[col];
--}
--
--// KeysymToKeycode() - find the keycode and column corresponding to the given
--// keysym.  The value of col passed in should be the column determined from the
--// current shift state.  If the keysym can be found in that column we prefer
--// that to finding it in a different column (which would require fake events to
--// alter the shift state).
--
--static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col)
--{
--  register int i, j;
--
--  j = *col;
--  for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) {
--    if (KeyCodetoKeySym(keymap, i, j) == ks)
--      return i;
--  }
--
--  for (j = 0; j < keymap->mapWidth; j++) {
--    for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) {
--      if (KeyCodetoKeySym(keymap, i, j) == ks) {
--        *col = j;
--        return i;
--      }
--    }
--  }
--  return 0;
--}
--
--/* Fairly standard US PC Keyboard */
--
--#define VFB_MIN_KEY 8
--#define VFB_MAX_KEY 255
--#define VFB_MAP_LEN (VFB_MAX_KEY - VFB_MIN_KEY + 1)
--#define KEYSYMS_PER_KEY 2
--KeySym keyboardMap[VFB_MAP_LEN * KEYSYMS_PER_KEY] = {
--  NoSymbol, NoSymbol,
--  XK_Escape, NoSymbol,
--  XK_1, XK_exclam,
--  XK_2, XK_at,
--  XK_3, XK_numbersign,
--  XK_4, XK_dollar,
--  XK_5, XK_percent,
--  XK_6, XK_asciicircum,
--  XK_7, XK_ampersand,
--  XK_8, XK_asterisk,
--  XK_9, XK_parenleft,
--  XK_0, XK_parenright,
--  XK_minus, XK_underscore,
--  XK_equal, XK_plus,
--  XK_BackSpace, NoSymbol,
--  XK_Tab, NoSymbol,
--  XK_q, XK_Q,
--  XK_w, XK_W,
--  XK_e, XK_E,
--  XK_r, XK_R,
--  XK_t, XK_T,
--  XK_y, XK_Y,
--  XK_u, XK_U,
--  XK_i, XK_I,
--  XK_o, XK_O,
--  XK_p, XK_P,
--  XK_bracketleft, XK_braceleft,
--  XK_bracketright, XK_braceright,
--  XK_Return, NoSymbol,
--  XK_Control_L, NoSymbol,
--  XK_a, XK_A,
--  XK_s, XK_S,
--  XK_d, XK_D,
--  XK_f, XK_F,
--  XK_g, XK_G,
--  XK_h, XK_H,
--  XK_j, XK_J,
--  XK_k, XK_K,
--  XK_l, XK_L,
--  XK_semicolon, XK_colon,
--  XK_apostrophe, XK_quotedbl,
--  XK_grave, XK_asciitilde,
--  XK_Shift_L, NoSymbol,
--  XK_backslash, XK_bar,
--  XK_z, XK_Z,
--  XK_x, XK_X,
--  XK_c, XK_C,
--  XK_v, XK_V,
--  XK_b, XK_B,
--  XK_n, XK_N,
--  XK_m, XK_M,
--  XK_comma, XK_less,
--  XK_period, XK_greater,
--  XK_slash, XK_question,
--  XK_Shift_R, NoSymbol,
--  XK_KP_Multiply, NoSymbol,
--  XK_Alt_L, XK_Meta_L,
--  XK_space, NoSymbol,
--  /*XK_Caps_Lock*/ NoSymbol, NoSymbol,
--  XK_F1, NoSymbol,
--  XK_F2, NoSymbol,
--  XK_F3, NoSymbol,
--  XK_F4, NoSymbol,
--  XK_F5, NoSymbol,
--  XK_F6, NoSymbol,
--  XK_F7, NoSymbol,
--  XK_F8, NoSymbol,
--  XK_F9, NoSymbol,
--  XK_F10, NoSymbol,
--  XK_Num_Lock, XK_Pointer_EnableKeys,
--  XK_Scroll_Lock, NoSymbol,
--  XK_KP_Home, XK_KP_7,
--  XK_KP_Up, XK_KP_8,
--  XK_KP_Prior, XK_KP_9,
--  XK_KP_Subtract, NoSymbol,
--  XK_KP_Left, XK_KP_4,
--  XK_KP_Begin, XK_KP_5,
--  XK_KP_Right, XK_KP_6,
--  XK_KP_Add, NoSymbol,
--  XK_KP_End, XK_KP_1,
--  XK_KP_Down, XK_KP_2,
--  XK_KP_Next, XK_KP_3,
--  XK_KP_Insert, XK_KP_0,
--  XK_KP_Delete, XK_KP_Decimal,
--  NoSymbol, NoSymbol,
--  NoSymbol, NoSymbol,
--  NoSymbol, NoSymbol,
--  XK_F11, NoSymbol,
--  XK_F12, NoSymbol,
--  XK_Home, NoSymbol,
--  XK_Up, NoSymbol,
--  XK_Prior, NoSymbol,
--  XK_Left, NoSymbol,
--  NoSymbol, NoSymbol,
--  XK_Right, NoSymbol,
--  XK_End, NoSymbol,
--  XK_Down, NoSymbol,
--  XK_Next, NoSymbol,
--  XK_Insert, NoSymbol,
--  XK_Delete, NoSymbol,
--  XK_KP_Enter, NoSymbol,
--  XK_Control_R, NoSymbol,
--  XK_Pause, XK_Break,
--  XK_Print, XK_Execute,
--  XK_KP_Divide, NoSymbol,
--  XK_Alt_R, XK_Meta_R,
--};
--
--static Bool GetMappings(KeySymsPtr pKeySyms, CARD8 *pModMap)
--{
--  int i;
--
--  for (i = 0; i < MAP_LENGTH; i++)
--    pModMap[i] = NoSymbol;
--
--  for (i = 0; i < VFB_MAP_LEN; i++) {
--    if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Caps_Lock)
--      pModMap[i + VFB_MIN_KEY] = LockMask;
--    else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_L ||
--             keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_R)
--      pModMap[i + VFB_MIN_KEY] = ShiftMask;
--    else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_L ||
--             keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_R) {
--      pModMap[i + VFB_MIN_KEY] = ControlMask;
--    }
--    else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_L ||
--             keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_R)
--      pModMap[i + VFB_MIN_KEY] = Mod1Mask;
--  }
--
--  pKeySyms->minKeyCode = VFB_MIN_KEY;
--  pKeySyms->maxKeyCode = VFB_MAX_KEY;
--  pKeySyms->mapWidth = KEYSYMS_PER_KEY;
--  pKeySyms->map = keyboardMap;
--
--  return TRUE;
--}
--
--static void vfbBell(int percent, DeviceIntPtr device, pointer ctrl, int class_)
--{
--  if (percent > 0)
--    vncBell();
--}
--
--static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff)
--{
--  KeySymsRec            keySyms;
--  CARD8                 modMap[MAP_LENGTH];
--  DevicePtr pDev = (DevicePtr)pDevice;
--#ifdef XKB
--  XkbComponentNamesRec names;
--#endif
--
--  switch (onoff)
--  {
--  case DEVICE_INIT:
--    GetMappings(&keySyms, modMap);
--#ifdef XKB
--    if (!noXkbExtension) {
--      memset(&names, 0, sizeof (names));
--      XkbSetRulesDflts("base", "pc105", "us", NULL, NULL);
--      XkbInitKeyboardDeviceStruct(pDevice, &names, &keySyms, modMap,
--				  (BellProcPtr)vfbBell,
--				  (KbdCtrlProcPtr)NoopDDA);
--    } else
--#endif
--    {
--      InitKeyboardDeviceStruct(pDev, &keySyms, modMap,
--			      (BellProcPtr)vfbBell, (KbdCtrlProcPtr)NoopDDA);
--    }
--    break;
--  case DEVICE_ON:
--    pDev->on = TRUE;
--    break;
--  case DEVICE_OFF:
--    pDev->on = FALSE;
--    break;
--  case DEVICE_CLOSE:
--    break;
--  }
--  return Success;
--}
--
-diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h
-index 9f300f5..6e4f609 100644
---- a/unix/xserver/hw/vnc/XserverDesktop.h
-+++ b/unix/xserver/hw/vnc/XserverDesktop.h
-@@ -123,6 +123,7 @@ private:
-   void deferUpdate();
-   ScreenPtr pScreen;
-   PointerDevice *pointerDevice;
-+  KeyboardDevice *keyboardDevice;
-   OsTimerPtr deferredUpdateTimer, dummyTimer;
-   rfb::VNCServerST* server;
-   rfb::HTTPServer* httpServer;
-
--- 
-1.5.6.5
-