--- 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
-