open-src/xserver/xvnc/upstream-input-refactor.patch
changeset 1124 7bc7e624f965
parent 1123 4678f8c1d429
child 1125 0776474068be
equal deleted inserted replaced
1123:4678f8c1d429 1124:7bc7e624f965
     1 From 2f97d8a75e7371ac7f3a9a1338db55888754d7c0 Mon Sep 17 00:00:00 2001
       
     2 From: atkac <atkac@3789f03b-4d11-0410-bbf8-ca57d06f2519>
       
     3 Date: Fri, 28 Aug 2009 12:03:11 +0000
       
     4 Subject: [PATCH] Initialize eventq in all cases.
       
     5 
       
     6 git-svn-id: https://tigervnc.svn.sourceforge.net/svnroot/tigervnc/trunk@3885 3789f03b-4d11-0410-bbf8-ca57d06f2519
       
     7 ---
       
     8  unix/xserver/hw/vnc/XserverDesktop.cc |    2 ++
       
     9  1 files changed, 2 insertions(+), 0 deletions(-)
       
    10 
       
    11 diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc
       
    12 index d6fe993..533f31b 100644
       
    13 --- a/unix/xserver/hw/vnc/XserverDesktop.cc
       
    14 +++ b/unix/xserver/hw/vnc/XserverDesktop.cc
       
    15 @@ -203,6 +203,8 @@ XserverDesktop::XserverDesktop(ScreenPtr pScreen_,
       
    16      eventq = (xEvent *) xcalloc(sizeof(xEvent), GetMaximumEventsNum());
       
    17    if (!eventq)
       
    18      FatalError("Couldn't allocate eventq\n");
       
    19 +#else
       
    20 +  GetEventList(&eventq);
       
    21  #endif
       
    22  
       
    23    /*
       
    24 -- 
       
    25 1.5.6.5
       
    26 
       
    27 From 1093aa3149c24b362781ab7f19c4c63a6eb19990 Mon Sep 17 00:00:00 2001
       
    28 From: atkac <atkac@3789f03b-4d11-0410-bbf8-ca57d06f2519>
       
    29 Date: Fri, 28 Aug 2009 12:04:20 +0000
       
    30 Subject: [PATCH] Add Input.h and Input.cc and move all mouse input related code there.
       
    31 
       
    32 git-svn-id: https://tigervnc.svn.sourceforge.net/svnroot/tigervnc/trunk@3886 3789f03b-4d11-0410-bbf8-ca57d06f2519
       
    33 ---
       
    34  unix/xserver/hw/vnc/Input.cc          |  167 +++++++++++++++++++++++++++++++++
       
    35  unix/xserver/hw/vnc/Input.h           |   61 ++++++++++++
       
    36  unix/xserver/hw/vnc/Makefile.am       |    6 +-
       
    37  unix/xserver/hw/vnc/XserverDesktop.cc |  142 +---------------------------
       
    38  unix/xserver/hw/vnc/XserverDesktop.h  |    5 +-
       
    39  5 files changed, 240 insertions(+), 141 deletions(-)
       
    40  create mode 100644 unix/xserver/hw/vnc/Input.cc
       
    41  create mode 100644 unix/xserver/hw/vnc/Input.h
       
    42 
       
    43 diff --git a/unix/xserver/hw/vnc/Input.cc b/unix/xserver/hw/vnc/Input.cc
       
    44 new file mode 100644
       
    45 index 0000000..ca279f0
       
    46 --- /dev/null
       
    47 +++ b/unix/xserver/hw/vnc/Input.cc
       
    48 @@ -0,0 +1,167 @@
       
    49 +/* Copyright (C) 2009 TightVNC Team
       
    50 + * Copyright (C) 2009 Red Hat, Inc.
       
    51 + *
       
    52 + * This is free software; you can redistribute it and/or modify
       
    53 + * it under the terms of the GNU General Public License as published by
       
    54 + * the Free Software Foundation; either version 2 of the License, or
       
    55 + * (at your option) any later version.
       
    56 + * 
       
    57 + * This software is distributed in the hope that it will be useful,
       
    58 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    59 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    60 + * GNU General Public License for more details.
       
    61 + * 
       
    62 + * You should have received a copy of the GNU General Public License
       
    63 + * along with this software; if not, write to the Free Software
       
    64 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
       
    65 + * USA.
       
    66 + */
       
    67 +
       
    68 +#ifdef HAVE_DIX_CONFIG_H
       
    69 +#include <dix-config.h>
       
    70 +#endif
       
    71 +
       
    72 +#include "Input.h"
       
    73 +#include "xorg-version.h"
       
    74 +
       
    75 +extern "C" {
       
    76 +#include "mi.h"
       
    77 +}
       
    78 +
       
    79 +/* Event queue is shared between all devices. */
       
    80 +#if XORG == 15
       
    81 +static xEvent *eventq = NULL;
       
    82 +#else
       
    83 +static EventList *eventq = NULL;
       
    84 +#endif
       
    85 +
       
    86 +static void initEventq(void)
       
    87 +{
       
    88 +	/* eventq is never free()-ed because it exists during server life. */
       
    89 +	if (eventq == NULL) {
       
    90 +#if XORG == 15
       
    91 +		eventq = (xEvent *)xcalloc(sizeof(xEvent),
       
    92 +					   GetMaximumEventsNum());
       
    93 +		if (!eventq)
       
    94 +			FatalError("Couldn't allocate eventq\n");
       
    95 +#else
       
    96 +		GetEventList(&eventq);
       
    97 +#endif
       
    98 +	}
       
    99 +}
       
   100 +
       
   101 +static void enqueueEvents(DeviceIntPtr dev, int n)
       
   102 +{
       
   103 +	int i;
       
   104 +
       
   105 +	for (i = 0; i < n; i++) {
       
   106 +		/*
       
   107 +		 * Passing arguments in global variable eventq is probably not
       
   108 +		 * good programming practise but in this case it is safe and
       
   109 +		 * clear.
       
   110 +		 */
       
   111 +		mieqEnqueue(dev,
       
   112 +#if XORG == 15
       
   113 +			    eventq + i
       
   114 +#else
       
   115 +			    (eventq + i)->event
       
   116 +#endif
       
   117 +			   );
       
   118 +	}
       
   119 +}
       
   120 +
       
   121 +/* Pointer device pre-declarations */
       
   122 +#define BUTTONS 5
       
   123 +static int pointerProc(DeviceIntPtr pDevice, int onoff);
       
   124 +
       
   125 +/* Pointer device methods */
       
   126 +
       
   127 +PointerDevice::PointerDevice(rfb::VNCServerST *_server)
       
   128 +	: server(_server), oldButtonMask(0)
       
   129 +{
       
   130 +	dev = AddInputDevice(
       
   131 +#if XORG >= 16
       
   132 +			     serverClient,
       
   133 +#endif
       
   134 +			     pointerProc, TRUE);
       
   135 +	RegisterPointerDevice(dev);
       
   136 +	initEventq();
       
   137 +}
       
   138 +
       
   139 +void PointerDevice::ButtonAction(int buttonMask)
       
   140 +{
       
   141 +	int i, n;
       
   142 +
       
   143 +	for (i = 0; i < BUTTONS; i++) {
       
   144 +		if ((buttonMask ^ oldButtonMask) & (1 << i)) {
       
   145 +			int action = (buttonMask & (1<<i)) ?
       
   146 +				     ButtonPress : ButtonRelease;
       
   147 +			n = GetPointerEvents(eventq, dev, action, i + 1,
       
   148 +					     POINTER_RELATIVE, 0, 0, NULL);
       
   149 +			enqueueEvents(dev, n);
       
   150 +
       
   151 +		}
       
   152 +	}
       
   153 +
       
   154 +	oldButtonMask = buttonMask;
       
   155 +}
       
   156 +
       
   157 +void PointerDevice::Move(const rfb::Point &pos)
       
   158 +{
       
   159 +	int n, valuators[2];
       
   160 +
       
   161 +	if (pos.equals(cursorPos))
       
   162 +		return;
       
   163 +
       
   164 +	valuators[0] = pos.x;
       
   165 +	valuators[1] = pos.y;
       
   166 +	n = GetPointerEvents(eventq, dev, MotionNotify, 0, POINTER_ABSOLUTE, 0,
       
   167 +			     2, valuators);
       
   168 +	enqueueEvents(dev, n);
       
   169 +
       
   170 +	cursorPos = pos;
       
   171 +}
       
   172 +
       
   173 +void PointerDevice::Sync(void)
       
   174 +{
       
   175 +	if (cursorPos.equals(oldCursorPos))
       
   176 +		return;
       
   177 +
       
   178 +	oldCursorPos = cursorPos;
       
   179 +	server->setCursorPos(cursorPos);
       
   180 +	server->tryUpdate();
       
   181 +}
       
   182 +
       
   183 +static int pointerProc(DeviceIntPtr pDevice, int onoff)
       
   184 +{
       
   185 +	BYTE map[BUTTONS + 1];
       
   186 +	DevicePtr pDev = (DevicePtr)pDevice;
       
   187 +	int i;
       
   188 +
       
   189 +	switch (onoff) {
       
   190 +	case DEVICE_INIT:
       
   191 +		for (i = 0; i < BUTTONS + 1; i++)
       
   192 +			map[i] = i;
       
   193 +
       
   194 +		InitPointerDeviceStruct(pDev, map, BUTTONS,
       
   195 +#if XORG == 15
       
   196 +					GetMotionHistory,
       
   197 +#endif
       
   198 +					(PtrCtrlProcPtr)NoopDDA,
       
   199 +					GetMotionHistorySize(), 2);
       
   200 +		break;
       
   201 +	case DEVICE_ON:
       
   202 +		pDev->on = TRUE;
       
   203 +		break;
       
   204 +	case DEVICE_OFF:
       
   205 +		pDev->on = FALSE;
       
   206 +		break;
       
   207 +#if 0
       
   208 +	case DEVICE_CLOSE:
       
   209 +		break;
       
   210 +#endif
       
   211 +	}
       
   212 +
       
   213 +	return Success;
       
   214 +}
       
   215 +
       
   216 diff --git a/unix/xserver/hw/vnc/Input.h b/unix/xserver/hw/vnc/Input.h
       
   217 new file mode 100644
       
   218 index 0000000..49cedf2
       
   219 --- /dev/null
       
   220 +++ b/unix/xserver/hw/vnc/Input.h
       
   221 @@ -0,0 +1,61 @@
       
   222 +/* Copyright (C) 2009 TightVNC Team
       
   223 + * Copyright (C) 2009 Red Hat, Inc.
       
   224 + *
       
   225 + * This is free software; you can redistribute it and/or modify
       
   226 + * it under the terms of the GNU General Public License as published by
       
   227 + * the Free Software Foundation; either version 2 of the License, or
       
   228 + * (at your option) any later version.
       
   229 + * 
       
   230 + * This software is distributed in the hope that it will be useful,
       
   231 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
   232 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
   233 + * GNU General Public License for more details.
       
   234 + * 
       
   235 + * You should have received a copy of the GNU General Public License
       
   236 + * along with this software; if not, write to the Free Software
       
   237 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
       
   238 + * USA.
       
   239 + */
       
   240 +
       
   241 +/* Make sure macro doesn't conflict with macro in include/input.h. */
       
   242 +#ifndef INPUT_H_
       
   243 +#define INPUT_H_
       
   244 +
       
   245 +#ifdef HAVE_DIX_CONFIG_H
       
   246 +#include <dix-config.h>
       
   247 +#endif
       
   248 +
       
   249 +#include <rfb/VNCServerST.h>
       
   250 +
       
   251 +extern "C" {
       
   252 +#include "input.h"
       
   253 +};
       
   254 +
       
   255 +/* Represents pointer device. */
       
   256 +class PointerDevice {
       
   257 +public:
       
   258 +	/* Create new PointerDevice instance. */
       
   259 +	PointerDevice(rfb::VNCServerST *_server);
       
   260 +
       
   261 +	/*
       
   262 +	 * Press or release buttons. Relationship between buttonMask and
       
   263 +	 * buttons is specified in RFB protocol.
       
   264 +	 */
       
   265 +	void ButtonAction(int buttonMask);
       
   266 +
       
   267 +	/* Move pointer to target location (point coords are absolute). */
       
   268 +	void Move(const rfb::Point &point);
       
   269 +
       
   270 +	/*
       
   271 +	 * Send pointer position to clients. If not called then Move() calls
       
   272 +	 * won't be visible to clients.
       
   273 +	 */
       
   274 +	void Sync(void);
       
   275 +private:
       
   276 +	rfb::VNCServerST *server;
       
   277 +	DeviceIntPtr dev;
       
   278 +	int oldButtonMask;
       
   279 +	rfb::Point cursorPos, oldCursorPos;
       
   280 +};
       
   281 +
       
   282 +#endif
       
   283 diff --git a/unix/xserver/hw/vnc/Makefile.am b/unix/xserver/hw/vnc/Makefile.am
       
   284 index a39a10d..c2e78df 100644
       
   285 --- a/unix/xserver/hw/vnc/Makefile.am
       
   286 +++ b/unix/xserver/hw/vnc/Makefile.am
       
   287 @@ -9,9 +9,11 @@ COMMON_LIBS=$(NETWORK_LIB) $(RFB_LIB) $(RDR_LIB) $(XREGION_LIB)
       
   288  
       
   289  noinst_LTLIBRARIES = libvnccommon.la
       
   290  
       
   291 -HDRS = RegionHelper.h vncExtInit.h vncHooks.h XserverDesktop.h xorg-version.h
       
   292 +HDRS = RegionHelper.h vncExtInit.h vncHooks.h XserverDesktop.h xorg-version.h \
       
   293 +	Input.h
       
   294  
       
   295 -libvnccommon_la_SOURCES = $(HDRS) vncExtInit.cc vncHooks.cc XserverDesktop.cc
       
   296 +libvnccommon_la_SOURCES = $(HDRS) vncExtInit.cc vncHooks.cc XserverDesktop.cc \
       
   297 +	Input.cc
       
   298  
       
   299  libvnccommon_la_CPPFLAGS = -DVENDOR_RELEASE="$(VENDOR_RELEASE)" \
       
   300  	-DVENDOR_STRING="\"$(VENDOR_STRING)\"" -I$(LIB_DIR) \
       
   301 diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc
       
   302 index 533f31b..58f70d9 100644
       
   303 --- a/unix/xserver/hw/vnc/XserverDesktop.cc
       
   304 +++ b/unix/xserver/hw/vnc/XserverDesktop.cc
       
   305 @@ -42,6 +42,7 @@
       
   306  #include "XserverDesktop.h"
       
   307  #include "vncExtInit.h"
       
   308  #include "xorg-version.h"
       
   309 +#include "Input.h"
       
   310  
       
   311  extern "C" {
       
   312  #define public c_public
       
   313 @@ -77,7 +78,6 @@ CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master);
       
   314  }
       
   315  
       
   316  static DeviceIntPtr vncKeyboardDevice = NULL;
       
   317 -static DeviceIntPtr vncPointerDevice = NULL;
       
   318  #if XORG == 15
       
   319  static xEvent *eventq = NULL;
       
   320  #else
       
   321 @@ -85,7 +85,6 @@ static EventList *eventq = NULL;
       
   322  #endif
       
   323  
       
   324  static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff);
       
   325 -static int vfbMouseProc(DeviceIntPtr pDevice, int onoff);
       
   326  
       
   327  using namespace rfb;
       
   328  using namespace network;
       
   329 @@ -180,7 +179,6 @@ XserverDesktop::XserverDesktop(ScreenPtr pScreen_,
       
   330      listener(listener_), httpListener(httpListener_),
       
   331      cmap(0), deferredUpdateTimerSet(false),
       
   332      grabbing(false), ignoreHooks_(false), directFbptr(true),
       
   333 -    oldButtonMask(0),
       
   334      queryConnectId(0)
       
   335  {
       
   336    format = pf;
       
   337 @@ -221,14 +219,7 @@ XserverDesktop::XserverDesktop(ScreenPtr pScreen_,
       
   338      RegisterKeyboardDevice(vncKeyboardDevice);
       
   339    }
       
   340  
       
   341 -  if (vncPointerDevice == NULL) {
       
   342 -    vncPointerDevice = AddInputDevice(
       
   343 -#if XORG >= 16
       
   344 -				      serverClient,
       
   345 -#endif
       
   346 -				      vfbMouseProc, TRUE);
       
   347 -    RegisterPointerDevice(vncPointerDevice);
       
   348 -  }
       
   349 +  pointerDevice = new PointerDevice(server);
       
   350  }
       
   351  
       
   352  XserverDesktop::~XserverDesktop()
       
   353 @@ -237,6 +228,7 @@ XserverDesktop::~XserverDesktop()
       
   354      delete [] data;
       
   355    TimerFree(deferredUpdateTimer);
       
   356    TimerFree(dummyTimer);
       
   357 +  delete pointerDevice;
       
   358    delete httpServer;
       
   359    delete server;
       
   360  }
       
   361 @@ -555,43 +547,9 @@ void XserverDesktop::add_copied(RegionPtr dst, int dx, int dy)
       
   362    }
       
   363  }
       
   364  
       
   365 -void XserverDesktop::positionCursor()
       
   366 -{
       
   367 -  if (!cursorPos.equals(oldCursorPos)) {
       
   368 -    oldCursorPos = cursorPos;
       
   369 -    (*pScreen->SetCursorPosition) (
       
   370 -#if XORG >= 16
       
   371 -				   vncPointerDevice,
       
   372 -#endif
       
   373 -				   pScreen, cursorPos.x, cursorPos.y, FALSE);
       
   374 -    server->setCursorPos(cursorPos);
       
   375 -    server->tryUpdate();
       
   376 -  }
       
   377 -}
       
   378 -
       
   379  void XserverDesktop::blockHandler(fd_set* fds)
       
   380  {
       
   381    try {
       
   382 -#if XORG == 15
       
   383 -    ScreenPtr screenWithCursor = GetCurrentRootWindow()->drawable.pScreen;
       
   384 -#else
       
   385 -    ScreenPtr screenWithCursor =
       
   386 -	GetCurrentRootWindow(vncPointerDevice)->drawable.pScreen;
       
   387 -#endif
       
   388 -    if (screenWithCursor == pScreen) {
       
   389 -      int x, y;
       
   390 -      GetSpritePosition(
       
   391 -#if XORG >= 16
       
   392 -			vncPointerDevice,
       
   393 -#endif
       
   394 -			&x, &y);
       
   395 -      if (x != cursorPos.x || y != cursorPos.y) {
       
   396 -        cursorPos = oldCursorPos = Point(x, y);
       
   397 -        server->setCursorPos(cursorPos);
       
   398 -        server->tryUpdate();
       
   399 -      }
       
   400 -    }
       
   401 -
       
   402      if (listener)
       
   403        FD_SET(listener->getFd(), fds);
       
   404      if (httpListener)
       
   405 @@ -678,7 +636,7 @@ void XserverDesktop::wakeupHandler(fd_set* fds, int nfds)
       
   406          }
       
   407        }
       
   408  
       
   409 -      positionCursor();
       
   410 +      pointerDevice->Sync();
       
   411      }
       
   412  
       
   413      int timeout = server->checkTimeouts();
       
   414 @@ -737,63 +695,8 @@ void XserverDesktop::approveConnection(void* opaqueId, bool accept,
       
   415  
       
   416  void XserverDesktop::pointerEvent(const Point& pos, int buttonMask)
       
   417  {
       
   418 -  int i, j, n, valuators[2];
       
   419 -
       
   420 -  // SetCursorPosition seems to be very expensive (at least on XFree86 3.3.6
       
   421 -  // for S3), so we delay calling it until positionCursor() is called at the
       
   422 -  // end of processing a load of RFB.
       
   423 -  //(*pScreen->SetCursorPosition) (pScreen, pos.x, pos.y, FALSE);
       
   424 -
       
   425 -  NewCurrentScreen(
       
   426 -#if XORG >= 16
       
   427 -		   vncPointerDevice,
       
   428 -#endif
       
   429 -		   pScreen, pos.x, pos.y);
       
   430 -
       
   431 -  if (!pos.equals(cursorPos)) {
       
   432 -    valuators[0] = pos.x;
       
   433 -    valuators[1] = pos.y;
       
   434 -
       
   435 -#if XORG >= 16
       
   436 -    GetEventList(&eventq);
       
   437 -#endif
       
   438 -    n = GetPointerEvents (eventq, vncPointerDevice, MotionNotify, 0,
       
   439 -			  POINTER_ABSOLUTE, 0, 2, valuators);
       
   440 -
       
   441 -    for (i = 0; i < n; i++) {
       
   442 -      mieqEnqueue (vncPointerDevice,
       
   443 -#if XORG == 15
       
   444 -		   eventq + i
       
   445 -#else
       
   446 -		   (eventq + i)->event
       
   447 -#endif
       
   448 -      );
       
   449 -    }
       
   450 -  }
       
   451 -
       
   452 -  for (i = 0; i < 5; i++) {
       
   453 -    if ((buttonMask ^ oldButtonMask) & (1<<i)) {
       
   454 -      // Do not use the pointer mapping. Treat VNC buttons as logical
       
   455 -      // buttons.
       
   456 -      n = GetPointerEvents (eventq, vncPointerDevice,
       
   457 -			    (buttonMask & (1<<i)) ?
       
   458 -			     ButtonPress : ButtonRelease,
       
   459 -			    i + 1, POINTER_RELATIVE, 0, 0, NULL);
       
   460 -
       
   461 -      for (j = 0; j < n; j++) {
       
   462 -	mieqEnqueue (vncPointerDevice,
       
   463 -#if XORG == 15
       
   464 -		     eventq + j
       
   465 -#else
       
   466 -		     (eventq + j)->event
       
   467 -#endif
       
   468 -	);
       
   469 -      }
       
   470 -    }
       
   471 -  }
       
   472 -
       
   473 -  cursorPos = pos;
       
   474 -  oldButtonMask = buttonMask;
       
   475 +  pointerDevice->Move(pos);
       
   476 +  pointerDevice->ButtonAction(buttonMask);
       
   477  }
       
   478  
       
   479  void XserverDesktop::clientCutText(const char* str, int len)
       
   480 @@ -1481,36 +1384,3 @@ static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff)
       
   481    return Success;
       
   482  }
       
   483  
       
   484 -static int vfbMouseProc(DeviceIntPtr pDevice, int onoff)
       
   485 -{
       
   486 -  BYTE map[6];
       
   487 -  DevicePtr pDev = (DevicePtr)pDevice;
       
   488 -
       
   489 -  switch (onoff)
       
   490 -  {
       
   491 -  case DEVICE_INIT:
       
   492 -    map[1] = 1;
       
   493 -    map[2] = 2;
       
   494 -    map[3] = 3;
       
   495 -    map[4] = 4;
       
   496 -    map[5] = 5;
       
   497 -    InitPointerDeviceStruct(pDev, map, 5,
       
   498 -#if XORG == 15
       
   499 -			    GetMotionHistory,
       
   500 -#endif
       
   501 -			    (PtrCtrlProcPtr)NoopDDA, GetMotionHistorySize(), 2);
       
   502 -    break;
       
   503 -
       
   504 -  case DEVICE_ON:
       
   505 -    pDev->on = TRUE;
       
   506 -    break;
       
   507 -
       
   508 -  case DEVICE_OFF:
       
   509 -    pDev->on = FALSE;
       
   510 -    break;
       
   511 -
       
   512 -  case DEVICE_CLOSE:
       
   513 -    break;
       
   514 -  }
       
   515 -  return Success;
       
   516 -}
       
   517 diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h
       
   518 index 7729d3f..9f300f5 100644
       
   519 --- a/unix/xserver/hw/vnc/XserverDesktop.h
       
   520 +++ b/unix/xserver/hw/vnc/XserverDesktop.h
       
   521 @@ -32,6 +32,7 @@
       
   522  #include <rfb/Configuration.h>
       
   523  #include <rfb/VNCServerST.h>
       
   524  #include <rdr/SubstitutingInStream.h>
       
   525 +#include "Input.h"
       
   526  
       
   527  extern "C" {
       
   528  #define class c_class
       
   529 @@ -68,7 +69,6 @@ public:
       
   530    void setCursor(CursorPtr cursor);
       
   531    void add_changed(RegionPtr reg);
       
   532    void add_copied(RegionPtr dst, int dx, int dy);
       
   533 -  void positionCursor();
       
   534    void ignoreHooks(bool b) { ignoreHooks_ = b; }
       
   535    void blockHandler(fd_set* fds);
       
   536    void wakeupHandler(fd_set* fds, int nfds);
       
   537 @@ -122,6 +122,7 @@ private:
       
   538                                              pointer arg);
       
   539    void deferUpdate();
       
   540    ScreenPtr pScreen;
       
   541 +  PointerDevice *pointerDevice;
       
   542    OsTimerPtr deferredUpdateTimer, dummyTimer;
       
   543    rfb::VNCServerST* server;
       
   544    rfb::HTTPServer* httpServer;
       
   545 @@ -133,8 +134,6 @@ private:
       
   546    bool grabbing;
       
   547    bool ignoreHooks_;
       
   548    bool directFbptr;
       
   549 -  int oldButtonMask;
       
   550 -  rfb::Point cursorPos, oldCursorPos;
       
   551  
       
   552    void* queryConnectId;
       
   553    rfb::CharArray queryConnectAddress;
       
   554 -- 
       
   555 1.5.6.5
       
   556 
       
   557 From 845dbbfbb6a2c0e1a4981920121935febe7c0a50 Mon Sep 17 00:00:00 2001
       
   558 From: atkac <atkac@3789f03b-4d11-0410-bbf8-ca57d06f2519>
       
   559 Date: Fri, 28 Aug 2009 12:05:24 +0000
       
   560 Subject: [PATCH] Move keyboard input related code to Input.h and Input.cc.
       
   561 
       
   562 git-svn-id: https://tigervnc.svn.sourceforge.net/svnroot/tigervnc/trunk@3887 3789f03b-4d11-0410-bbf8-ca57d06f2519
       
   563 ---
       
   564  unix/xserver/hw/vnc/Input.cc          |  606 ++++++++++++++++++++++++++++++++-
       
   565  unix/xserver/hw/vnc/Input.h           |   13 +
       
   566  unix/xserver/hw/vnc/XserverDesktop.cc |  589 +-------------------------------
       
   567  unix/xserver/hw/vnc/XserverDesktop.h  |    1 +
       
   568  4 files changed, 622 insertions(+), 587 deletions(-)
       
   569 
       
   570 diff --git a/unix/xserver/hw/vnc/Input.cc b/unix/xserver/hw/vnc/Input.cc
       
   571 index ca279f0..478240c 100644
       
   572 --- a/unix/xserver/hw/vnc/Input.cc
       
   573 +++ b/unix/xserver/hw/vnc/Input.cc
       
   574 @@ -21,13 +21,49 @@
       
   575  #include <dix-config.h>
       
   576  #endif
       
   577  
       
   578 +#include <rfb/LogWriter.h>
       
   579  #include "Input.h"
       
   580  #include "xorg-version.h"
       
   581 +#include "vncExtInit.h"
       
   582  
       
   583  extern "C" {
       
   584 +#define public c_public
       
   585 +#define class c_class
       
   586 +#include "inputstr.h"
       
   587  #include "mi.h"
       
   588 +#ifndef XKB_IN_SERVER
       
   589 +#define XKB_IN_SERVER
       
   590 +#endif
       
   591 +#ifdef XKB
       
   592 +/*
       
   593 + * This include is needed to use XkbConvertCase instead of XConvertCase even if
       
   594 + * we don't use XKB extension.
       
   595 + */
       
   596 +#include <xkbsrv.h>
       
   597 +#endif
       
   598 +#if XORG >= 16
       
   599 +#include "exevents.h"
       
   600 +extern void
       
   601 +CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master);
       
   602 +#endif
       
   603 +#include <X11/keysym.h>
       
   604 +#include <X11/Xutil.h>
       
   605 +#undef public
       
   606 +#undef class
       
   607  }
       
   608  
       
   609 +using namespace rdr;
       
   610 +using namespace rfb;
       
   611 +
       
   612 +static LogWriter vlog("Input");
       
   613 +
       
   614 +#define BUTTONS 5
       
   615 +static int pointerProc(DeviceIntPtr pDevice, int onoff);
       
   616 +
       
   617 +static int keyboardProc(DeviceIntPtr pDevice, int onoff);
       
   618 +static KeySym KeyCodetoKeySym(KeySymsPtr keymap, int keycode, int col);
       
   619 +static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col);
       
   620 +
       
   621  /* Event queue is shared between all devices. */
       
   622  #if XORG == 15
       
   623  static xEvent *eventq = NULL;
       
   624 @@ -70,10 +106,6 @@ static void enqueueEvents(DeviceIntPtr dev, int n)
       
   625  	}
       
   626  }
       
   627  
       
   628 -/* Pointer device pre-declarations */
       
   629 -#define BUTTONS 5
       
   630 -static int pointerProc(DeviceIntPtr pDevice, int onoff);
       
   631 -
       
   632  /* Pointer device methods */
       
   633  
       
   634  PointerDevice::PointerDevice(rfb::VNCServerST *_server)
       
   635 @@ -165,3 +197,569 @@ static int pointerProc(DeviceIntPtr pDevice, int onoff)
       
   636  	return Success;
       
   637  }
       
   638  
       
   639 +/* KeyboardDevice methods */
       
   640 +
       
   641 +KeyboardDevice::KeyboardDevice(void)
       
   642 +{
       
   643 +	dev = AddInputDevice(
       
   644 +#if XORG >= 16
       
   645 +			     serverClient,
       
   646 +#endif
       
   647 +			     keyboardProc, TRUE);
       
   648 +	RegisterKeyboardDevice(dev);
       
   649 +	initEventq();
       
   650 +}
       
   651 +
       
   652 +#define IS_PRESSED(keyc, keycode) \
       
   653 +	((keyc)->down[(keycode) >> 3] & (1 << ((keycode) & 7)))
       
   654 +
       
   655 +/*
       
   656 + * ModifierState is a class which helps simplify generating a "fake" press or
       
   657 + * release of shift, ctrl, alt, etc.  An instance of the class is created for
       
   658 + * every modifier which may need to be pressed or released.  Then either
       
   659 + * press() or release() may be called to make sure that the corresponding keys
       
   660 + * are in the right state.  The destructor of the class automatically reverts
       
   661 + * to the previous state.  Each modifier may have multiple keys associated with
       
   662 + * it, so in the case of a fake release, this may involve releasing more than
       
   663 + * one key.
       
   664 + */
       
   665 +
       
   666 +class ModifierState {
       
   667 +public:
       
   668 +	ModifierState(DeviceIntPtr _dev, int _modIndex)
       
   669 +		: modIndex(_modIndex), nKeys(0), keys(0), pressed(false),
       
   670 +		  dev(_dev) {}
       
   671 +
       
   672 +	~ModifierState()
       
   673 +	{
       
   674 +		for (int i = 0; i < nKeys; i++)
       
   675 +			generateXKeyEvent(keys[i], !pressed);
       
   676 +		delete [] keys;
       
   677 +	}
       
   678 +
       
   679 +	void press()
       
   680 +	{
       
   681 +		KeyClassPtr keyc = dev->key;
       
   682 +		if (!(keyc->state & (1 << modIndex))) {
       
   683 +			int index = modIndex * keyc->maxKeysPerModifier;
       
   684 +			tempKeyEvent(keyc->modifierKeyMap[index], true);
       
   685 +			pressed = true;
       
   686 +		}
       
   687 +	}
       
   688 +
       
   689 +	void release()
       
   690 +	{
       
   691 +		KeyClassPtr keyc = dev->key;
       
   692 +		if ((keyc->state & (1 << modIndex)) == 0)
       
   693 +			return;
       
   694 +
       
   695 +		for (int k = 0; k < keyc->maxKeysPerModifier; k++) {
       
   696 +			int index = modIndex * keyc->maxKeysPerModifier + k;
       
   697 +			int keycode = keyc->modifierKeyMap[index];
       
   698 +			if (keycode && IS_PRESSED(keyc, keycode))
       
   699 +				tempKeyEvent(keycode, false);
       
   700 +		}
       
   701 +	}
       
   702 +
       
   703 +private:
       
   704 +	void tempKeyEvent(int keycode, bool down)
       
   705 +	{
       
   706 +		if (keycode) {
       
   707 +			if (!keys) keys = new int[dev->key->maxKeysPerModifier];
       
   708 +			keys[nKeys++] = keycode;
       
   709 +			generateXKeyEvent(keycode, down);
       
   710 +		}
       
   711 +	}
       
   712 +
       
   713 +	void generateXKeyEvent(int keycode, bool down)
       
   714 +	{
       
   715 +		int n, action;
       
   716 +
       
   717 +		action = down ? KeyPress : KeyRelease;
       
   718 +		n = GetKeyboardEvents(eventq, dev, action, keycode);
       
   719 +		enqueueEvents(dev, n);
       
   720 +
       
   721 +		vlog.debug("fake keycode %d %s", keycode,
       
   722 +			   down ? "down" : "up");
       
   723 +	}
       
   724 +
       
   725 +	int modIndex;
       
   726 +	int nKeys;
       
   727 +	int *keys;
       
   728 +	bool pressed;
       
   729 +	DeviceIntPtr dev;
       
   730 +};
       
   731 +
       
   732 +
       
   733 +/* altKeysym is a table of alternative keysyms which have the same meaning. */
       
   734 +
       
   735 +static struct altKeysym_t {
       
   736 +	KeySym a, b;
       
   737 +} altKeysym[] = {
       
   738 +	{ XK_Shift_L,		XK_Shift_R },
       
   739 +	{ XK_Control_L,		XK_Control_R },
       
   740 +	{ XK_Meta_L,		XK_Meta_R },
       
   741 +	{ XK_Alt_L,		XK_Alt_R },
       
   742 +	{ XK_Super_L,		XK_Super_R },
       
   743 +	{ XK_Hyper_L,		XK_Hyper_R },
       
   744 +	{ XK_KP_Space,		XK_space },
       
   745 +	{ XK_KP_Tab,		XK_Tab },
       
   746 +	{ XK_KP_Enter,		XK_Return },
       
   747 +	{ XK_KP_F1,		XK_F1 },
       
   748 +	{ XK_KP_F2,		XK_F2 },
       
   749 +	{ XK_KP_F3,		XK_F3 },
       
   750 +	{ XK_KP_F4,		XK_F4 },
       
   751 +	{ XK_KP_Home,		XK_Home },
       
   752 +	{ XK_KP_Left,		XK_Left },
       
   753 +	{ XK_KP_Up,		XK_Up },
       
   754 +	{ XK_KP_Right,		XK_Right },
       
   755 +	{ XK_KP_Down,		XK_Down },
       
   756 +	{ XK_KP_Page_Up,	XK_Page_Up },
       
   757 +	{ XK_KP_Page_Down,	XK_Page_Down },
       
   758 +	{ XK_KP_End,		XK_End },
       
   759 +	{ XK_KP_Begin,		XK_Begin },
       
   760 +	{ XK_KP_Insert,		XK_Insert },
       
   761 +	{ XK_KP_Delete,		XK_Delete },
       
   762 +	{ XK_KP_Equal,		XK_equal },
       
   763 +	{ XK_KP_Multiply,	XK_asterisk },
       
   764 +	{ XK_KP_Add,		XK_plus },
       
   765 +	{ XK_KP_Separator,	XK_comma },
       
   766 +	{ XK_KP_Subtract,	XK_minus },
       
   767 +	{ XK_KP_Decimal,	XK_period },
       
   768 +	{ XK_KP_Divide,		XK_slash },
       
   769 +	{ XK_KP_0,		XK_0 },
       
   770 +	{ XK_KP_1,		XK_1 },
       
   771 +	{ XK_KP_2,		XK_2 },
       
   772 +	{ XK_KP_3,		XK_3 },
       
   773 +	{ XK_KP_4,		XK_4 },
       
   774 +	{ XK_KP_5,		XK_5 },
       
   775 +	{ XK_KP_6,		XK_6 },
       
   776 +	{ XK_KP_7,		XK_7 },
       
   777 +	{ XK_KP_8,		XK_8 },
       
   778 +	{ XK_KP_9,		XK_9 },
       
   779 +};
       
   780 +
       
   781 +/*
       
   782 + * keyEvent() - work out the best keycode corresponding to the keysym sent by
       
   783 + * the viewer.  This is non-trivial because we can't assume much about the
       
   784 + * local keyboard layout.  We must also find out which column of the keyboard
       
   785 + * mapping the keysym is in, and alter the shift state appropriately.  Column 0
       
   786 + * means both shift and "mode_switch" (AltGr) must be released, column 1 means
       
   787 + * shift must be pressed and mode_switch released, column 2 means shift must be
       
   788 + * released and mode_switch pressed, and column 3 means both shift and
       
   789 + * mode_switch must be pressed.
       
   790 + *
       
   791 + * Magic, which dynamically adds keysym<->keycode mapping depends on X.Org
       
   792 + * version. Quick explanation of that "magic":
       
   793 + * 
       
   794 + * 1.5
       
   795 + * - has only one core keyboard so we have to keep core keyboard mapping
       
   796 + *   synchronized with vncKeyboardDevice. Do it via SwitchCoreKeyboard()
       
   797 + *
       
   798 + * 1.6 (aka MPX - Multi pointer X)
       
   799 + * - multiple master devices (= core devices) exists, keep vncKeyboardDevice
       
   800 + *   synchronized with proper master device
       
   801 + */
       
   802 +
       
   803 +void KeyboardDevice::keyEvent(rdr::U32 keysym, bool down)
       
   804 +{
       
   805 +	DeviceIntPtr master;
       
   806 +	KeyClassPtr keyc = dev->key;
       
   807 +	KeySymsPtr keymap = &keyc->curKeySyms;
       
   808 +	KeySym *map = keymap->map;
       
   809 +	KeyCode minKeyCode = keymap->minKeyCode;
       
   810 +	KeyCode maxKeyCode = keymap->maxKeyCode;
       
   811 +	int mapWidth = keymap->mapWidth;
       
   812 +	unsigned int i, n;
       
   813 +	int j, k, action;
       
   814 +
       
   815 +	if (keysym == XK_Caps_Lock) {
       
   816 +		vlog.debug("Ignoring caps lock");
       
   817 +		return;
       
   818 +	}
       
   819 +
       
   820 +	/* find which modifier Mode_switch is on. */
       
   821 +	int modeSwitchMapIndex = 0;
       
   822 +	for (i = 3; i < 8; i++) {
       
   823 +		for (k = 0; k < keyc->maxKeysPerModifier; k++) {
       
   824 +			int index = i * keyc->maxKeysPerModifier + k;
       
   825 +			int keycode = keyc->modifierKeyMap[index];
       
   826 +
       
   827 +			if (keycode == 0)
       
   828 +				continue;
       
   829 +
       
   830 +			for (j = 0; j < mapWidth; j++) {
       
   831 +				if (map[(keycode - minKeyCode) * mapWidth + j]
       
   832 +				    == XK_Mode_switch) {
       
   833 +					modeSwitchMapIndex = i;
       
   834 +					goto ModeSwitchFound;
       
   835 +				}
       
   836 +			}
       
   837 +		}
       
   838 +	}
       
   839 +ModeSwitchFound:
       
   840 +
       
   841 +	int col = 0;
       
   842 +	if ((keyc->state & (1 << ShiftMapIndex)) != 0)
       
   843 +		col |= 1;
       
   844 +	if (modeSwitchMapIndex != 0 &&
       
   845 +	    ((keyc->state & (1 << modeSwitchMapIndex))) != 0)
       
   846 +		col |= 2;
       
   847 +
       
   848 +	int kc = KeysymToKeycode(keymap, keysym, &col);
       
   849 +
       
   850 +	/*
       
   851 +	 * Sort out the "shifted Tab" mess.  If we are sent a shifted Tab,
       
   852 +	 * generate a local shifted Tab regardless of what the "shifted Tab"
       
   853 +	 * keysym is on the local keyboard (it might be Tab, ISO_Left_Tab or
       
   854 +	 * HP's private BackTab keysym, and quite possibly some others too).
       
   855 +	 * We never get ISO_Left_Tab here because it's already been translated
       
   856 +	 * in VNCSConnectionST.
       
   857 +	 */
       
   858 +	if (keysym == XK_Tab && ((keyc->state & (1 << ShiftMapIndex))) != 0)
       
   859 +		col |= 1;
       
   860 +
       
   861 +	if (kc == 0) {
       
   862 +		/*
       
   863 +		 * Not a direct match in the local keyboard mapping.  Check for
       
   864 +		 * alternative keysyms with the same meaning.
       
   865 +		 */
       
   866 +		for (i = 0; i < sizeof(altKeysym) / sizeof(altKeysym_t); i++) {
       
   867 +			if (keysym == altKeysym[i].a)
       
   868 +				kc = KeysymToKeycode(keymap, altKeysym[i].b,
       
   869 +						     &col);
       
   870 +			else if (keysym == altKeysym[i].b)
       
   871 +				kc = KeysymToKeycode(keymap, altKeysym[i].a,
       
   872 +						     &col);
       
   873 +			if (kc)
       
   874 +				break;
       
   875 +		}
       
   876 +	}
       
   877 +
       
   878 +	if (kc == 0) {
       
   879 +		/* Dynamically add a new key to the keyboard mapping. */
       
   880 +		for (kc = maxKeyCode; kc >= minKeyCode; kc--) {
       
   881 +			if (map[(kc - minKeyCode) * mapWidth] != 0)
       
   882 +				continue;
       
   883 +
       
   884 +			map[(kc - minKeyCode) * mapWidth] = keysym;
       
   885 +			col = 0;
       
   886 +
       
   887 +			vlog.info("Added unknown keysym 0x%x to keycode %d",
       
   888 +				  keysym, kc);
       
   889 +#if XORG == 15
       
   890 +			master = inputInfo.keyboard;
       
   891 +#else
       
   892 +			master = dev->u.master;
       
   893 +#endif
       
   894 +			void *slave = dixLookupPrivate(&master->devPrivates,
       
   895 +						       CoreDevicePrivateKey);
       
   896 +			if (dev == slave) {
       
   897 +				dixSetPrivate(&master->devPrivates,
       
   898 +					      CoreDevicePrivateKey, NULL);
       
   899 +#if XORG == 15
       
   900 +				SwitchCoreKeyboard(dev);
       
   901 +#else
       
   902 +				CopyKeyClass(dev, master);
       
   903 +#endif
       
   904 +			}
       
   905 +			break;
       
   906 +		}
       
   907 +	}
       
   908 +
       
   909 +	if (kc < minKeyCode) {
       
   910 +		vlog.info("Keyboard mapping full - ignoring unknown keysym "
       
   911 +			  "0x%x",keysym);
       
   912 +		return;
       
   913 +	}
       
   914 +
       
   915 +	/*
       
   916 +	 * See if it's a modifier key.  If so, then don't do any auto-repeat,
       
   917 +	 * because the X server will translate each press into a release
       
   918 +	 * followed by a press.
       
   919 +	 */
       
   920 +	for (i = 0; i < 8; i++) {
       
   921 +		for (k = 0; k < keyc->maxKeysPerModifier; k++) {
       
   922 +			int index = i * keyc->maxKeysPerModifier + k;
       
   923 +			if (kc == keyc->modifierKeyMap[index] &&
       
   924 +			    IS_PRESSED(keyc,kc) && down)
       
   925 +				return;
       
   926 +		}
       
   927 +	}
       
   928 +
       
   929 +	ModifierState shift(dev, ShiftMapIndex);
       
   930 +	ModifierState modeSwitch(dev, modeSwitchMapIndex);
       
   931 +	if (down) {
       
   932 +		if (col & 1)
       
   933 +			shift.press();
       
   934 +		else
       
   935 +			shift.release();
       
   936 +		if (modeSwitchMapIndex) {
       
   937 +			if (col & 2)
       
   938 +				modeSwitch.press();
       
   939 +			else
       
   940 +				modeSwitch.release();
       
   941 +		}
       
   942 +	}
       
   943 +
       
   944 +	vlog.debug("keycode %d %s", kc, down ? "down" : "up");
       
   945 +	action = down ? KeyPress : KeyRelease;
       
   946 +	n = GetKeyboardEvents(eventq, dev, action, kc);
       
   947 +	enqueueEvents(dev, n);
       
   948 +}
       
   949 +
       
   950 +static KeySym KeyCodetoKeySym(KeySymsPtr keymap, int keycode, int col)
       
   951 +{
       
   952 +	int per = keymap->mapWidth;
       
   953 +	KeySym *syms;
       
   954 +	KeySym lsym, usym;
       
   955 +
       
   956 +	if ((col < 0) || ((col >= per) && (col > 3)) ||
       
   957 +	    (keycode < keymap->minKeyCode) || (keycode > keymap->maxKeyCode))
       
   958 +		return NoSymbol;
       
   959 +
       
   960 +	syms = &keymap->map[(keycode - keymap->minKeyCode) * per];
       
   961 +	if (col >= 4)
       
   962 +		return syms[col];
       
   963 +
       
   964 +	if (col > 1) {
       
   965 +		while ((per > 2) && (syms[per - 1] == NoSymbol))
       
   966 +			per--;
       
   967 +		if (per < 3)
       
   968 +			col -= 2;
       
   969 +	}
       
   970 +
       
   971 +	if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) {
       
   972 +		XConvertCase(syms[col&~1], &lsym, &usym);
       
   973 +		if (!(col & 1))
       
   974 +			return lsym;
       
   975 +		/*
       
   976 +		 * I'm commenting out this logic because it's incorrect even
       
   977 +		 * though it was copied from the Xlib sources.  The X protocol
       
   978 +		 * book quite clearly states that where a group consists of
       
   979 +		 * element 1 being a non-alphabetic keysym and element 2 being
       
   980 +		 * NoSymbol that you treat the second element as being the
       
   981 +		 * same as the first.  This also tallies with the behaviour
       
   982 +		 * produced by the installed Xlib on my linux box (I believe
       
   983 +		 * this is because it uses some XKB code rather than the
       
   984 +		 * original Xlib code - compare XKBBind.c with KeyBind.c in
       
   985 +		 * lib/X11).
       
   986 +		 */
       
   987 +#if 0
       
   988 +		else if (usym == lsym)
       
   989 +			return NoSymbol;
       
   990 +#endif
       
   991 +		else
       
   992 +			return usym;
       
   993 +	}
       
   994 +
       
   995 +	return syms[col];
       
   996 +}
       
   997 +
       
   998 +/*
       
   999 + * KeysymToKeycode() - find the keycode and column corresponding to the given
       
  1000 + * keysym.  The value of col passed in should be the column determined from the
       
  1001 + * current shift state.  If the keysym can be found in that column we prefer
       
  1002 + * that to finding it in a different column (which would require fake events to
       
  1003 + * alter the shift state).
       
  1004 + */
       
  1005 +static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col)
       
  1006 +{
       
  1007 +	int i, j;
       
  1008 +
       
  1009 +	j = *col;
       
  1010 +	for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) {
       
  1011 +		if (KeyCodetoKeySym(keymap, i, j) == ks)
       
  1012 +			return i;
       
  1013 +	}
       
  1014 +
       
  1015 +	for (j = 0; j < keymap->mapWidth; j++) {
       
  1016 +		for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) {
       
  1017 +			if (KeyCodetoKeySym(keymap, i, j) == ks) {
       
  1018 +				*col = j;
       
  1019 +				return i;
       
  1020 +			}
       
  1021 +		}
       
  1022 +	}
       
  1023 +
       
  1024 +	return 0;
       
  1025 +}
       
  1026 +
       
  1027 +/* Fairly standard US PC Keyboard */
       
  1028 +
       
  1029 +#define MIN_KEY 8
       
  1030 +#define MAX_KEY 255
       
  1031 +#define MAP_LEN (MAX_KEY - MIN_KEY + 1)
       
  1032 +#define KEYSYMS_PER_KEY 2
       
  1033 +KeySym keyboardMap[MAP_LEN * KEYSYMS_PER_KEY] = {
       
  1034 +	NoSymbol, NoSymbol,
       
  1035 +	XK_Escape, NoSymbol,
       
  1036 +	XK_1, XK_exclam,
       
  1037 +	XK_2, XK_at,
       
  1038 +	XK_3, XK_numbersign,
       
  1039 +	XK_4, XK_dollar,
       
  1040 +	XK_5, XK_percent,
       
  1041 +	XK_6, XK_asciicircum,
       
  1042 +	XK_7, XK_ampersand,
       
  1043 +	XK_8, XK_asterisk,
       
  1044 +	XK_9, XK_parenleft,
       
  1045 +	XK_0, XK_parenright,
       
  1046 +	XK_minus, XK_underscore,
       
  1047 +	XK_equal, XK_plus,
       
  1048 +	XK_BackSpace, NoSymbol,
       
  1049 +	XK_Tab, NoSymbol,
       
  1050 +	XK_q, XK_Q,
       
  1051 +	XK_w, XK_W,
       
  1052 +	XK_e, XK_E,
       
  1053 +	XK_r, XK_R,
       
  1054 +	XK_t, XK_T,
       
  1055 +	XK_y, XK_Y,
       
  1056 +	XK_u, XK_U,
       
  1057 +	XK_i, XK_I,
       
  1058 +	XK_o, XK_O,
       
  1059 +	XK_p, XK_P,
       
  1060 +	XK_bracketleft, XK_braceleft,
       
  1061 +	XK_bracketright, XK_braceright,
       
  1062 +	XK_Return, NoSymbol,
       
  1063 +	XK_Control_L, NoSymbol,
       
  1064 +	XK_a, XK_A,
       
  1065 +	XK_s, XK_S,
       
  1066 +	XK_d, XK_D,
       
  1067 +	XK_f, XK_F,
       
  1068 +	XK_g, XK_G,
       
  1069 +	XK_h, XK_H,
       
  1070 +	XK_j, XK_J,
       
  1071 +	XK_k, XK_K,
       
  1072 +	XK_l, XK_L,
       
  1073 +	XK_semicolon, XK_colon,
       
  1074 +	XK_apostrophe, XK_quotedbl,
       
  1075 +	XK_grave, XK_asciitilde,
       
  1076 +	XK_Shift_L, NoSymbol,
       
  1077 +	XK_backslash, XK_bar,
       
  1078 +	XK_z, XK_Z,
       
  1079 +	XK_x, XK_X,
       
  1080 +	XK_c, XK_C,
       
  1081 +	XK_v, XK_V,
       
  1082 +	XK_b, XK_B,
       
  1083 +	XK_n, XK_N,
       
  1084 +	XK_m, XK_M,
       
  1085 +	XK_comma, XK_less,
       
  1086 +	XK_period, XK_greater,
       
  1087 +	XK_slash, XK_question,
       
  1088 +	XK_Shift_R, NoSymbol,
       
  1089 +	XK_KP_Multiply, NoSymbol,
       
  1090 +	XK_Alt_L, XK_Meta_L,
       
  1091 +	XK_space, NoSymbol,
       
  1092 +	/* XK_Caps_Lock */ NoSymbol, NoSymbol,
       
  1093 +	XK_F1, NoSymbol,
       
  1094 +	XK_F2, NoSymbol,
       
  1095 +	XK_F3, NoSymbol,
       
  1096 +	XK_F4, NoSymbol,
       
  1097 +	XK_F5, NoSymbol,
       
  1098 +	XK_F6, NoSymbol,
       
  1099 +	XK_F7, NoSymbol,
       
  1100 +	XK_F8, NoSymbol,
       
  1101 +	XK_F9, NoSymbol,
       
  1102 +	XK_F10, NoSymbol,
       
  1103 +	XK_Num_Lock, XK_Pointer_EnableKeys,
       
  1104 +	XK_Scroll_Lock, NoSymbol,
       
  1105 +	XK_KP_Home, XK_KP_7,
       
  1106 +	XK_KP_Up, XK_KP_8,
       
  1107 +	XK_KP_Prior, XK_KP_9,
       
  1108 +	XK_KP_Subtract, NoSymbol,
       
  1109 +	XK_KP_Left, XK_KP_4,
       
  1110 +	XK_KP_Begin, XK_KP_5,
       
  1111 +	XK_KP_Right, XK_KP_6,
       
  1112 +	XK_KP_Add, NoSymbol,
       
  1113 +	XK_KP_End, XK_KP_1,
       
  1114 +	XK_KP_Down, XK_KP_2,
       
  1115 +	XK_KP_Next, XK_KP_3,
       
  1116 +	XK_KP_Insert, XK_KP_0,
       
  1117 +	XK_KP_Delete, XK_KP_Decimal,
       
  1118 +	NoSymbol, NoSymbol,
       
  1119 +	NoSymbol, NoSymbol,
       
  1120 +	NoSymbol, NoSymbol,
       
  1121 +	XK_F11, NoSymbol,
       
  1122 +	XK_F12, NoSymbol,
       
  1123 +	XK_Home, NoSymbol,
       
  1124 +	XK_Up, NoSymbol,
       
  1125 +	XK_Prior, NoSymbol,
       
  1126 +	XK_Left, NoSymbol,
       
  1127 +	NoSymbol, NoSymbol,
       
  1128 +	XK_Right, NoSymbol,
       
  1129 +	XK_End, NoSymbol,
       
  1130 +	XK_Down, NoSymbol,
       
  1131 +	XK_Next, NoSymbol,
       
  1132 +	XK_Insert, NoSymbol,
       
  1133 +	XK_Delete, NoSymbol,
       
  1134 +	XK_KP_Enter, NoSymbol,
       
  1135 +	XK_Control_R, NoSymbol,
       
  1136 +	XK_Pause, XK_Break,
       
  1137 +	XK_Print, XK_Execute,
       
  1138 +	XK_KP_Divide, NoSymbol,
       
  1139 +	XK_Alt_R, XK_Meta_R,
       
  1140 +};
       
  1141 +
       
  1142 +static Bool GetMappings(KeySymsPtr pKeySyms, CARD8 *pModMap)
       
  1143 +{
       
  1144 +	int i;
       
  1145 +
       
  1146 +	for (i = 0; i < MAP_LENGTH; i++)
       
  1147 +		pModMap[i] = NoSymbol;
       
  1148 +
       
  1149 +	for (i = 0; i < MAP_LEN; i++) {
       
  1150 +		if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Caps_Lock)
       
  1151 +			pModMap[i + MIN_KEY] = LockMask;
       
  1152 +		else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_L ||
       
  1153 +			 keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_R)
       
  1154 +			pModMap[i + MIN_KEY] = ShiftMask;
       
  1155 +		else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_L ||
       
  1156 +			 keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_R)
       
  1157 +			pModMap[i + MIN_KEY] = ControlMask;
       
  1158 +		else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_L ||
       
  1159 +			 keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_R)
       
  1160 +			pModMap[i + MIN_KEY] = Mod1Mask;
       
  1161 +	}
       
  1162 +
       
  1163 +	pKeySyms->minKeyCode = MIN_KEY;
       
  1164 +	pKeySyms->maxKeyCode = MAX_KEY;
       
  1165 +	pKeySyms->mapWidth = KEYSYMS_PER_KEY;
       
  1166 +	pKeySyms->map = keyboardMap;
       
  1167 +
       
  1168 +	return TRUE;
       
  1169 +}
       
  1170 +
       
  1171 +static void keyboardBell(int percent, DeviceIntPtr device, pointer ctrl,
       
  1172 +			 int class_)
       
  1173 +{
       
  1174 +	if (percent > 0)
       
  1175 +		vncBell();
       
  1176 +}
       
  1177 +
       
  1178 +static int keyboardProc(DeviceIntPtr pDevice, int onoff)
       
  1179 +{
       
  1180 +	KeySymsRec keySyms;
       
  1181 +	CARD8 modMap[MAP_LENGTH];
       
  1182 +	DevicePtr pDev = (DevicePtr)pDevice;
       
  1183 +
       
  1184 +	switch (onoff) {
       
  1185 +	case DEVICE_INIT:
       
  1186 +		GetMappings(&keySyms, modMap);
       
  1187 +		InitKeyboardDeviceStruct(pDev, &keySyms, modMap, keyboardBell,
       
  1188 +					 (KbdCtrlProcPtr)NoopDDA);
       
  1189 +		break;
       
  1190 +	case DEVICE_ON:
       
  1191 +		pDev->on = TRUE;
       
  1192 +		break;
       
  1193 +	case DEVICE_OFF:
       
  1194 +		pDev->on = FALSE;
       
  1195 +		break;
       
  1196 +#if 0
       
  1197 +	case DEVICE_CLOSE:
       
  1198 +		break;
       
  1199 +#endif
       
  1200 +	}
       
  1201 +
       
  1202 +	return Success;
       
  1203 +}
       
  1204 +
       
  1205 diff --git a/unix/xserver/hw/vnc/Input.h b/unix/xserver/hw/vnc/Input.h
       
  1206 index 49cedf2..1bfec92 100644
       
  1207 --- a/unix/xserver/hw/vnc/Input.h
       
  1208 +++ b/unix/xserver/hw/vnc/Input.h
       
  1209 @@ -58,4 +58,17 @@ private:
       
  1210  	rfb::Point cursorPos, oldCursorPos;
       
  1211  };
       
  1212  
       
  1213 +/* Represents keyboard device. */
       
  1214 +class KeyboardDevice {
       
  1215 +public:
       
  1216 +	/* Create new Keyboard device instance. */
       
  1217 +	KeyboardDevice(void);
       
  1218 +
       
  1219 +	void Press(rdr::U32 keysym) { keyEvent(keysym, true); }
       
  1220 +	void Release(rdr::U32 keysym) { keyEvent(keysym, false); }
       
  1221 +private:
       
  1222 +	void keyEvent(rdr::U32 keysym, bool down);
       
  1223 +	DeviceIntPtr dev;
       
  1224 +};
       
  1225 +
       
  1226  #endif
       
  1227 diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc
       
  1228 index 58f70d9..66c92d2 100644
       
  1229 --- a/unix/xserver/hw/vnc/XserverDesktop.cc
       
  1230 +++ b/unix/xserver/hw/vnc/XserverDesktop.cc
       
  1231 @@ -50,26 +50,7 @@ extern "C" {
       
  1232  
       
  1233  extern char *display;
       
  1234  
       
  1235 -#include "inputstr.h"
       
  1236 -#include "servermd.h"
       
  1237  #include "colormapst.h"
       
  1238 -#include "resource.h"
       
  1239 -#include "cursorstr.h"
       
  1240 -#include "windowstr.h"
       
  1241 -#include "mi.h"
       
  1242 -#define XK_CYRILLIC
       
  1243 -#include <X11/keysym.h>
       
  1244 -#ifndef XKB_IN_SERVER
       
  1245 -#define XKB_IN_SERVER
       
  1246 -#endif
       
  1247 -#ifdef XKB
       
  1248 -#include <xkbsrv.h>
       
  1249 -#endif
       
  1250 -#if XORG >= 16
       
  1251 -#include "exevents.h"
       
  1252 -extern void
       
  1253 -CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master);
       
  1254 -#endif
       
  1255  #ifdef RANDR
       
  1256  #include "randrstr.h"
       
  1257  #endif
       
  1258 @@ -77,15 +58,6 @@ CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master);
       
  1259  #undef class
       
  1260  }
       
  1261  
       
  1262 -static DeviceIntPtr vncKeyboardDevice = NULL;
       
  1263 -#if XORG == 15
       
  1264 -static xEvent *eventq = NULL;
       
  1265 -#else
       
  1266 -static EventList *eventq = NULL;
       
  1267 -#endif
       
  1268 -
       
  1269 -static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff);
       
  1270 -
       
  1271  using namespace rfb;
       
  1272  using namespace network;
       
  1273  
       
  1274 @@ -102,8 +74,6 @@ IntParameter queryConnectTimeout("QueryConnectTimeout",
       
  1275                                   "rejecting the connection",
       
  1276                                   10);
       
  1277  
       
  1278 -static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col);
       
  1279 -
       
  1280  static rdr::U8 reverseBits[] = {
       
  1281    0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0,
       
  1282    0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
       
  1283 @@ -193,33 +163,8 @@ XserverDesktop::XserverDesktop(ScreenPtr pScreen_,
       
  1284    if (httpListener)
       
  1285      httpServer = new FileHTTPServer(this);
       
  1286  
       
  1287 -#if XORG == 15
       
  1288 -  /*
       
  1289 -   * XXX eventq is never free()-ed because it has to exist during server life
       
  1290 -   * */
       
  1291 -  if (!eventq)
       
  1292 -    eventq = (xEvent *) xcalloc(sizeof(xEvent), GetMaximumEventsNum());
       
  1293 -  if (!eventq)
       
  1294 -    FatalError("Couldn't allocate eventq\n");
       
  1295 -#else
       
  1296 -  GetEventList(&eventq);
       
  1297 -#endif
       
  1298 -
       
  1299 -  /*
       
  1300 -   * NOTE:
       
  1301 -   * We _might_ have to call ActivateDevice function for both keyboard and
       
  1302 -   * mouse. For Xvnc it's not needed but I have to check libvnc.so module.
       
  1303 -   */
       
  1304 -  if (vncKeyboardDevice == NULL) {
       
  1305 -    vncKeyboardDevice = AddInputDevice(
       
  1306 -#if XORG >= 16
       
  1307 -				       serverClient,
       
  1308 -#endif
       
  1309 -				       vfbKeybdProc, TRUE);
       
  1310 -    RegisterKeyboardDevice(vncKeyboardDevice);
       
  1311 -  }
       
  1312 -
       
  1313    pointerDevice = new PointerDevice(server);
       
  1314 +  keyboardDevice = new KeyboardDevice();
       
  1315  }
       
  1316  
       
  1317  XserverDesktop::~XserverDesktop()
       
  1318 @@ -229,6 +174,7 @@ XserverDesktop::~XserverDesktop()
       
  1319    TimerFree(deferredUpdateTimer);
       
  1320    TimerFree(dummyTimer);
       
  1321    delete pointerDevice;
       
  1322 +  delete keyboardDevice;
       
  1323    delete httpServer;
       
  1324    delete server;
       
  1325  }
       
  1326 @@ -854,550 +800,10 @@
       
  1327    }
       
  1328  }
       
  1329  
       
  1330 -//
       
  1331 -// Keyboard handling
       
  1332 -//
       
  1333 -
       
  1334 -#define IS_PRESSED(keyc, keycode) \
       
  1335 -  ((keyc)->down[(keycode) >> 3] & (1 << ((keycode) & 7)))
       
  1336 -
       
  1337 -// ModifierState is a class which helps simplify generating a "fake" press
       
  1338 -// or release of shift, ctrl, alt, etc.  An instance of the class is created
       
  1339 -// for every modifier which may need to be pressed or released.  Then either
       
  1340 -// press() or release() may be called to make sure that the corresponding keys
       
  1341 -// are in the right state.  The destructor of the class automatically reverts
       
  1342 -// to the previous state.  Each modifier may have multiple keys associated with
       
  1343 -// it, so in the case of a fake release, this may involve releasing more than
       
  1344 -// one key.
       
  1345 -
       
  1346 -class ModifierState {
       
  1347 -public:
       
  1348 -  ModifierState(int modIndex_)
       
  1349 -    : modIndex(modIndex_), nKeys(0), keys(0), pressed(false)
       
  1350 -  {
       
  1351 -  }
       
  1352 -  ~ModifierState() {
       
  1353 -    for (int i = 0; i < nKeys; i++)
       
  1354 -      generateXKeyEvent(keys[i], !pressed);
       
  1355 -    delete [] keys;
       
  1356 -  }
       
  1357 -  void press() {
       
  1358 -    KeyClassPtr keyc = vncKeyboardDevice->key;
       
  1359 -    if (!(keyc->state & (1<<modIndex))) {
       
  1360 -      tempKeyEvent(keyc->modifierKeyMap[modIndex * keyc->maxKeysPerModifier],
       
  1361 -                   true);
       
  1362 -      pressed = true;
       
  1363 -    }
       
  1364 -  }
       
  1365 -  void release() {
       
  1366 -    KeyClassPtr keyc = vncKeyboardDevice->key;
       
  1367 -    if (keyc->state & (1<<modIndex)) {
       
  1368 -      for (int k = 0; k < keyc->maxKeysPerModifier; k++) {
       
  1369 -        int keycode
       
  1370 -          = keyc->modifierKeyMap[modIndex * keyc->maxKeysPerModifier + k];
       
  1371 -        if (keycode && IS_PRESSED(keyc, keycode))
       
  1372 -          tempKeyEvent(keycode, false);
       
  1373 -      }
       
  1374 -    }
       
  1375 -  }
       
  1376 -private:
       
  1377 -  void tempKeyEvent(int keycode, bool down) {
       
  1378 -    if (keycode) {
       
  1379 -      if (!keys) keys = new int[vncKeyboardDevice->key->maxKeysPerModifier];
       
  1380 -      keys[nKeys++] = keycode;
       
  1381 -      generateXKeyEvent(keycode, down);
       
  1382 -    }
       
  1383 -  }
       
  1384 -  void generateXKeyEvent(int keycode, bool down) {
       
  1385 -    int i, n;
       
  1386 -    n = GetKeyboardEvents (eventq, vncKeyboardDevice,
       
  1387 -			   down ? KeyPress : KeyRelease, keycode);
       
  1388 -    for (i = 0; i < n; i++) {
       
  1389 -      mieqEnqueue (vncKeyboardDevice,
       
  1390 -#if XORG == 15
       
  1391 -		   eventq + i
       
  1392 -#else
       
  1393 -		   (eventq + i)->event
       
  1394 -#endif
       
  1395 -      );
       
  1396 -    }
       
  1397 -    vlog.debug("fake keycode %d %s", keycode, down ? "down" : "up");
       
  1398 -  }
       
  1399 -  int modIndex;
       
  1400 -  int nKeys;
       
  1401 -  int* keys;
       
  1402 -  bool pressed;
       
  1403 -};
       
  1404 -
       
  1405 -
       
  1406 -// altKeysym is a table of alternative keysyms which have the same meaning.
       
  1407 -
       
  1408 -struct altKeysym_t {
       
  1409 -  KeySym a, b;
       
  1410 -};
       
  1411 -
       
  1412 -altKeysym_t altKeysym[] = {
       
  1413 -  { XK_Shift_L,        XK_Shift_R },
       
  1414 -  { XK_Control_L,      XK_Control_R },
       
  1415 -  { XK_Meta_L,         XK_Meta_R },
       
  1416 -  { XK_Alt_L,          XK_Alt_R },
       
  1417 -  { XK_Super_L,        XK_Super_R },
       
  1418 -  { XK_Hyper_L,        XK_Hyper_R },
       
  1419 -  { XK_KP_Space,       XK_space },
       
  1420 -  { XK_KP_Tab,         XK_Tab },
       
  1421 -  { XK_KP_Enter,       XK_Return },
       
  1422 -  { XK_KP_F1,          XK_F1 },
       
  1423 -  { XK_KP_F2,          XK_F2 },
       
  1424 -  { XK_KP_F3,          XK_F3 },
       
  1425 -  { XK_KP_F4,          XK_F4 },
       
  1426 -  { XK_KP_Home,        XK_Home },
       
  1427 -  { XK_KP_Left,        XK_Left },
       
  1428 -  { XK_KP_Up,          XK_Up },
       
  1429 -  { XK_KP_Right,       XK_Right },
       
  1430 -  { XK_KP_Down,        XK_Down },
       
  1431 -  { XK_KP_Page_Up,     XK_Page_Up },
       
  1432 -  { XK_KP_Page_Down,   XK_Page_Down },
       
  1433 -  { XK_KP_End,         XK_End },
       
  1434 -  { XK_KP_Begin,       XK_Begin },
       
  1435 -  { XK_KP_Insert,      XK_Insert },
       
  1436 -  { XK_KP_Delete,      XK_Delete },
       
  1437 -  { XK_KP_Equal,       XK_equal },
       
  1438 -  { XK_KP_Multiply,    XK_asterisk },
       
  1439 -  { XK_KP_Add,         XK_plus },
       
  1440 -  { XK_KP_Separator,   XK_comma },
       
  1441 -  { XK_KP_Subtract,    XK_minus },
       
  1442 -  { XK_KP_Decimal,     XK_period },
       
  1443 -  { XK_KP_Divide,      XK_slash },
       
  1444 -  { XK_KP_0,           XK_0 },
       
  1445 -  { XK_KP_1,           XK_1 },
       
  1446 -  { XK_KP_2,           XK_2 },
       
  1447 -  { XK_KP_3,           XK_3 },
       
  1448 -  { XK_KP_4,           XK_4 },
       
  1449 -  { XK_KP_5,           XK_5 },
       
  1450 -  { XK_KP_6,           XK_6 },
       
  1451 -  { XK_KP_7,           XK_7 },
       
  1452 -  { XK_KP_8,           XK_8 },
       
  1453 -  { XK_KP_9,           XK_9 },
       
  1454 -};
       
  1455 -
       
  1456 -/*
       
  1457 - * keyEvent() - work out the best keycode corresponding to the keysym sent by
       
  1458 - * the viewer.  This is non-trivial because we can't assume much about the
       
  1459 - * local keyboard layout.  We must also find out which column of the keyboard
       
  1460 - * mapping the keysym is in, and alter the shift state appropriately.  Column 0
       
  1461 - * means both shift and "mode_switch" (AltGr) must be released, column 1 means
       
  1462 - * shift must be pressed and mode_switch released, column 2 means shift must be
       
  1463 - * released and mode_switch pressed, and column 3 means both shift and
       
  1464 - * mode_switch must be pressed.
       
  1465 - *
       
  1466 - * Magic, which dynamically adds keysym<->keycode mapping depends on X.Org
       
  1467 - * version. Quick explanation of that "magic":
       
  1468 - * 
       
  1469 - * 1.5
       
  1470 - * - has only one core keyboard so we have to keep core keyboard mapping
       
  1471 - *   synchronized with vncKeyboardDevice. Do it via SwitchCoreKeyboard()
       
  1472 - *
       
  1473 - * 1.6 (aka MPX - Multi pointer X)
       
  1474 - * - multiple master devices (= core devices) exists, keep vncKeyboardDevice
       
  1475 - *   synchronized with proper master device
       
  1476 - */
       
  1477 -
       
  1478  void XserverDesktop::keyEvent(rdr::U32 keysym, bool down)
       
  1479  {
       
  1480 -  DeviceIntPtr master;
       
  1481 -  KeyClassPtr keyc = vncKeyboardDevice->key;
       
  1482 -  KeySymsPtr keymap = &keyc->curKeySyms;
       
  1483 -  unsigned int i, n;
       
  1484 -  int j, k;
       
  1485 -
       
  1486 -  /* 
       
  1487 -   * Since we are checking the current state to determine if we need
       
  1488 -   * to fake modifiers, we must make sure that everything put on the
       
  1489 -   * input queue is processed before we start. Otherwise, shift may be
       
  1490 -   * stuck down.
       
  1491 -   */ 
       
  1492 -  mieqProcessInputEvents();
       
  1493 -
       
  1494 -  if (keysym == XK_Caps_Lock) {
       
  1495 -    vlog.debug("Ignoring caps lock");
       
  1496 -    return;
       
  1497 -  }
       
  1498 -
       
  1499 -  // find which modifier Mode_switch is on.
       
  1500 -  int modeSwitchMapIndex = 0;
       
  1501 -  for (i = 3; i < 8; i++) {
       
  1502 -    for (k = 0; k < keyc->maxKeysPerModifier; k++) {
       
  1503 -      int keycode = keyc->modifierKeyMap[i * keyc->maxKeysPerModifier + k];
       
  1504 -      for (j = 0; j < keymap->mapWidth; j++) {
       
  1505 -        if (keycode != 0 &&
       
  1506 -            keymap->map[(keycode - keymap->minKeyCode)
       
  1507 -                        * keymap->mapWidth + j] == XK_Mode_switch)
       
  1508 -        {
       
  1509 -          modeSwitchMapIndex = i;
       
  1510 -          break;
       
  1511 -        }
       
  1512 -      }
       
  1513 -    }
       
  1514 -  }
       
  1515 -
       
  1516 -  int col = 0;
       
  1517 -  if (keyc->state & (1<<ShiftMapIndex)) col |= 1;
       
  1518 -  if (modeSwitchMapIndex && (keyc->state & (1<<modeSwitchMapIndex))) col |= 2;
       
  1519 -
       
  1520 -  int kc = KeysymToKeycode(keymap, keysym, &col);
       
  1521 -
       
  1522 -  // Sort out the "shifted Tab" mess.  If we are sent a shifted Tab, generate a
       
  1523 -  // local shifted Tab regardless of what the "shifted Tab" keysym is on the
       
  1524 -  // local keyboard (it might be Tab, ISO_Left_Tab or HP's private BackTab
       
  1525 -  // keysym, and quite possibly some others too).  We never get ISO_Left_Tab
       
  1526 -  // here because it's already been translated in VNCSConnectionST.
       
  1527 -  if (keysym == XK_Tab && (keyc->state & (1<<ShiftMapIndex)))
       
  1528 -    col |= 1;
       
  1529 -
       
  1530 -  if (kc == 0) {
       
  1531 -    // Not a direct match in the local keyboard mapping.  Check for alternative
       
  1532 -    // keysyms with the same meaning.
       
  1533 -    for (i = 0; i < sizeof(altKeysym) / sizeof(altKeysym_t); i++) {
       
  1534 -      if (keysym == altKeysym[i].a)
       
  1535 -        kc = KeysymToKeycode(keymap, altKeysym[i].b, &col);
       
  1536 -      else if (keysym == altKeysym[i].b)
       
  1537 -        kc = KeysymToKeycode(keymap, altKeysym[i].a, &col);
       
  1538 -      if (kc) break;
       
  1539 -    }
       
  1540 -  }
       
  1541 -
       
  1542 -  if (kc == 0) {
       
  1543 -    // Last resort - dynamically add a new key to the keyboard mapping.
       
  1544 -    for (kc = keymap->maxKeyCode; kc >= keymap->minKeyCode; kc--) {
       
  1545 -      if (!keymap->map[(kc - keymap->minKeyCode) * keymap->mapWidth]) {
       
  1546 -        keymap->map[(kc - keymap->minKeyCode) * keymap->mapWidth] = keysym;
       
  1547 -        col = 0;
       
  1548 -
       
  1549 -	vlog.info("Added unknown keysym 0x%x to keycode %d",keysym,kc);
       
  1550 -
       
  1551 -#if XORG == 15
       
  1552 -	master = inputInfo.keyboard;
       
  1553 -#else
       
  1554 -	master = vncKeyboardDevice->u.master;
       
  1555 -#endif
       
  1556 -	if (vncKeyboardDevice ==
       
  1557 -	    dixLookupPrivate(&master->devPrivates, CoreDevicePrivateKey)) {
       
  1558 -	  dixSetPrivate(&master->devPrivates, CoreDevicePrivateKey, NULL);
       
  1559 -#if XORG == 15
       
  1560 -	  SwitchCoreKeyboard(vncKeyboardDevice);
       
  1561 -#else
       
  1562 -	  CopyKeyClass(vncKeyboardDevice, master);
       
  1563 -#endif
       
  1564 -	}
       
  1565 -        break;
       
  1566 -      }
       
  1567 -    }
       
  1568 -    if (kc < keymap->minKeyCode) {
       
  1569 -      vlog.info("Keyboard mapping full - ignoring unknown keysym 0x%x",keysym);
       
  1570 -      return;
       
  1571 -    }
       
  1572 -  }
       
  1573 -
       
  1574 -  // See if it's a modifier key.  If so, then don't do any auto-repeat, because
       
  1575 -  // the X server will translate each press into a release followed by a press.
       
  1576 -  for (i = 0; i < 8; i++) {
       
  1577 -    for (k = 0; k < keyc->maxKeysPerModifier; k++) {
       
  1578 -      if (kc == keyc->modifierKeyMap[i * keyc->maxKeysPerModifier + k] &&
       
  1579 -          IS_PRESSED(keyc,kc) && down)
       
  1580 -        return;
       
  1581 -    }
       
  1582 -  }
       
  1583 -
       
  1584 -  ModifierState shift(ShiftMapIndex);
       
  1585 -  ModifierState modeSwitch(modeSwitchMapIndex);
       
  1586 -  if (down) {
       
  1587 -    if (col & 1)
       
  1588 -      shift.press();
       
  1589 -    else
       
  1590 -      shift.release();
       
  1591 -    if (modeSwitchMapIndex) {
       
  1592 -      if (col & 2)
       
  1593 -        modeSwitch.press();
       
  1594 -      else
       
  1595 -        modeSwitch.release();
       
  1596 -    }
       
  1597 -  }
       
  1598 -  vlog.debug("keycode %d %s", kc, down ? "down" : "up");
       
  1599 -  n = GetKeyboardEvents (eventq, vncKeyboardDevice, down ?
       
  1600 -			 KeyPress : KeyRelease, kc);
       
  1601 -  for (i = 0; i < n; i++) {
       
  1602 -    mieqEnqueue (vncKeyboardDevice,
       
  1603 -#if XORG == 15
       
  1604 -		 eventq + i
       
  1605 -#else
       
  1606 -		 (eventq + i)->event
       
  1607 -#endif
       
  1608 -    );
       
  1609 -  }
       
  1610 -
       
  1611 -  /*
       
  1612 -   * When faking a modifier we are putting a keycode (which can
       
  1613 -   * currently activate the desired modifier) on the input
       
  1614 -   * queue. A future modmap change can change the mapping so
       
  1615 -   * that this keycode means something else entirely. Guard
       
  1616 -   * against this by processing the queue now.
       
  1617 -   */
       
  1618 -  mieqProcessInputEvents();
       
  1619 +	if (down)
       
  1620 +		keyboardDevice->Press(keysym);
       
  1621 +	else
       
  1622 +		keyboardDevice->Release(keysym);
       
  1623  }
       
  1624 -
       
  1625 -static KeySym KeyCodetoKeySym(KeySymsPtr keymap, int keycode, int col)
       
  1626 -{
       
  1627 -  register int per = keymap->mapWidth;
       
  1628 -  register KeySym *syms;
       
  1629 -  KeySym lsym, usym;
       
  1630 -
       
  1631 -  if ((col < 0) || ((col >= per) && (col > 3)) ||
       
  1632 -      (keycode < keymap->minKeyCode) || (keycode > keymap->maxKeyCode))
       
  1633 -    return NoSymbol;
       
  1634 -
       
  1635 -  syms = &keymap->map[(keycode - keymap->minKeyCode) * per];
       
  1636 -  if (col < 4) {
       
  1637 -    if (col > 1) {
       
  1638 -      while ((per > 2) && (syms[per - 1] == NoSymbol))
       
  1639 -        per--;
       
  1640 -      if (per < 3)
       
  1641 -        col -= 2;
       
  1642 -    }
       
  1643 -    if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) {
       
  1644 -      XConvertCase(syms[col&~1], &lsym, &usym);
       
  1645 -      if (!(col & 1))
       
  1646 -        return lsym;
       
  1647 -      // I'm commenting out this logic because it's incorrect even though it
       
  1648 -      // was copied from the Xlib sources.  The X protocol book quite clearly
       
  1649 -      // states that where a group consists of element 1 being a non-alphabetic
       
  1650 -      // keysym and element 2 being NoSymbol that you treat the second element
       
  1651 -      // as being the same as the first.  This also tallies with the behaviour
       
  1652 -      // produced by the installed Xlib on my linux box (I believe this is
       
  1653 -      // because it uses some XKB code rather than the original Xlib code -
       
  1654 -      // compare XKBBind.c with KeyBind.c in lib/X11).
       
  1655 -      // else if (usym == lsym)
       
  1656 -      //   return NoSymbol;
       
  1657 -      else
       
  1658 -        return usym;
       
  1659 -    }
       
  1660 -  }
       
  1661 -  return syms[col];
       
  1662 -}
       
  1663 -
       
  1664 -// KeysymToKeycode() - find the keycode and column corresponding to the given
       
  1665 -// keysym.  The value of col passed in should be the column determined from the
       
  1666 -// current shift state.  If the keysym can be found in that column we prefer
       
  1667 -// that to finding it in a different column (which would require fake events to
       
  1668 -// alter the shift state).
       
  1669 -
       
  1670 -static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col)
       
  1671 -{
       
  1672 -  register int i, j;
       
  1673 -
       
  1674 -  j = *col;
       
  1675 -  for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) {
       
  1676 -    if (KeyCodetoKeySym(keymap, i, j) == ks)
       
  1677 -      return i;
       
  1678 -  }
       
  1679 -
       
  1680 -  for (j = 0; j < keymap->mapWidth; j++) {
       
  1681 -    for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) {
       
  1682 -      if (KeyCodetoKeySym(keymap, i, j) == ks) {
       
  1683 -        *col = j;
       
  1684 -        return i;
       
  1685 -      }
       
  1686 -    }
       
  1687 -  }
       
  1688 -  return 0;
       
  1689 -}
       
  1690 -
       
  1691 -/* Fairly standard US PC Keyboard */
       
  1692 -
       
  1693 -#define VFB_MIN_KEY 8
       
  1694 -#define VFB_MAX_KEY 255
       
  1695 -#define VFB_MAP_LEN (VFB_MAX_KEY - VFB_MIN_KEY + 1)
       
  1696 -#define KEYSYMS_PER_KEY 2
       
  1697 -KeySym keyboardMap[VFB_MAP_LEN * KEYSYMS_PER_KEY] = {
       
  1698 -  NoSymbol, NoSymbol,
       
  1699 -  XK_Escape, NoSymbol,
       
  1700 -  XK_1, XK_exclam,
       
  1701 -  XK_2, XK_at,
       
  1702 -  XK_3, XK_numbersign,
       
  1703 -  XK_4, XK_dollar,
       
  1704 -  XK_5, XK_percent,
       
  1705 -  XK_6, XK_asciicircum,
       
  1706 -  XK_7, XK_ampersand,
       
  1707 -  XK_8, XK_asterisk,
       
  1708 -  XK_9, XK_parenleft,
       
  1709 -  XK_0, XK_parenright,
       
  1710 -  XK_minus, XK_underscore,
       
  1711 -  XK_equal, XK_plus,
       
  1712 -  XK_BackSpace, NoSymbol,
       
  1713 -  XK_Tab, NoSymbol,
       
  1714 -  XK_q, XK_Q,
       
  1715 -  XK_w, XK_W,
       
  1716 -  XK_e, XK_E,
       
  1717 -  XK_r, XK_R,
       
  1718 -  XK_t, XK_T,
       
  1719 -  XK_y, XK_Y,
       
  1720 -  XK_u, XK_U,
       
  1721 -  XK_i, XK_I,
       
  1722 -  XK_o, XK_O,
       
  1723 -  XK_p, XK_P,
       
  1724 -  XK_bracketleft, XK_braceleft,
       
  1725 -  XK_bracketright, XK_braceright,
       
  1726 -  XK_Return, NoSymbol,
       
  1727 -  XK_Control_L, NoSymbol,
       
  1728 -  XK_a, XK_A,
       
  1729 -  XK_s, XK_S,
       
  1730 -  XK_d, XK_D,
       
  1731 -  XK_f, XK_F,
       
  1732 -  XK_g, XK_G,
       
  1733 -  XK_h, XK_H,
       
  1734 -  XK_j, XK_J,
       
  1735 -  XK_k, XK_K,
       
  1736 -  XK_l, XK_L,
       
  1737 -  XK_semicolon, XK_colon,
       
  1738 -  XK_apostrophe, XK_quotedbl,
       
  1739 -  XK_grave, XK_asciitilde,
       
  1740 -  XK_Shift_L, NoSymbol,
       
  1741 -  XK_backslash, XK_bar,
       
  1742 -  XK_z, XK_Z,
       
  1743 -  XK_x, XK_X,
       
  1744 -  XK_c, XK_C,
       
  1745 -  XK_v, XK_V,
       
  1746 -  XK_b, XK_B,
       
  1747 -  XK_n, XK_N,
       
  1748 -  XK_m, XK_M,
       
  1749 -  XK_comma, XK_less,
       
  1750 -  XK_period, XK_greater,
       
  1751 -  XK_slash, XK_question,
       
  1752 -  XK_Shift_R, NoSymbol,
       
  1753 -  XK_KP_Multiply, NoSymbol,
       
  1754 -  XK_Alt_L, XK_Meta_L,
       
  1755 -  XK_space, NoSymbol,
       
  1756 -  /*XK_Caps_Lock*/ NoSymbol, NoSymbol,
       
  1757 -  XK_F1, NoSymbol,
       
  1758 -  XK_F2, NoSymbol,
       
  1759 -  XK_F3, NoSymbol,
       
  1760 -  XK_F4, NoSymbol,
       
  1761 -  XK_F5, NoSymbol,
       
  1762 -  XK_F6, NoSymbol,
       
  1763 -  XK_F7, NoSymbol,
       
  1764 -  XK_F8, NoSymbol,
       
  1765 -  XK_F9, NoSymbol,
       
  1766 -  XK_F10, NoSymbol,
       
  1767 -  XK_Num_Lock, XK_Pointer_EnableKeys,
       
  1768 -  XK_Scroll_Lock, NoSymbol,
       
  1769 -  XK_KP_Home, XK_KP_7,
       
  1770 -  XK_KP_Up, XK_KP_8,
       
  1771 -  XK_KP_Prior, XK_KP_9,
       
  1772 -  XK_KP_Subtract, NoSymbol,
       
  1773 -  XK_KP_Left, XK_KP_4,
       
  1774 -  XK_KP_Begin, XK_KP_5,
       
  1775 -  XK_KP_Right, XK_KP_6,
       
  1776 -  XK_KP_Add, NoSymbol,
       
  1777 -  XK_KP_End, XK_KP_1,
       
  1778 -  XK_KP_Down, XK_KP_2,
       
  1779 -  XK_KP_Next, XK_KP_3,
       
  1780 -  XK_KP_Insert, XK_KP_0,
       
  1781 -  XK_KP_Delete, XK_KP_Decimal,
       
  1782 -  NoSymbol, NoSymbol,
       
  1783 -  NoSymbol, NoSymbol,
       
  1784 -  NoSymbol, NoSymbol,
       
  1785 -  XK_F11, NoSymbol,
       
  1786 -  XK_F12, NoSymbol,
       
  1787 -  XK_Home, NoSymbol,
       
  1788 -  XK_Up, NoSymbol,
       
  1789 -  XK_Prior, NoSymbol,
       
  1790 -  XK_Left, NoSymbol,
       
  1791 -  NoSymbol, NoSymbol,
       
  1792 -  XK_Right, NoSymbol,
       
  1793 -  XK_End, NoSymbol,
       
  1794 -  XK_Down, NoSymbol,
       
  1795 -  XK_Next, NoSymbol,
       
  1796 -  XK_Insert, NoSymbol,
       
  1797 -  XK_Delete, NoSymbol,
       
  1798 -  XK_KP_Enter, NoSymbol,
       
  1799 -  XK_Control_R, NoSymbol,
       
  1800 -  XK_Pause, XK_Break,
       
  1801 -  XK_Print, XK_Execute,
       
  1802 -  XK_KP_Divide, NoSymbol,
       
  1803 -  XK_Alt_R, XK_Meta_R,
       
  1804 -};
       
  1805 -
       
  1806 -static Bool GetMappings(KeySymsPtr pKeySyms, CARD8 *pModMap)
       
  1807 -{
       
  1808 -  int i;
       
  1809 -
       
  1810 -  for (i = 0; i < MAP_LENGTH; i++)
       
  1811 -    pModMap[i] = NoSymbol;
       
  1812 -
       
  1813 -  for (i = 0; i < VFB_MAP_LEN; i++) {
       
  1814 -    if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Caps_Lock)
       
  1815 -      pModMap[i + VFB_MIN_KEY] = LockMask;
       
  1816 -    else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_L ||
       
  1817 -             keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_R)
       
  1818 -      pModMap[i + VFB_MIN_KEY] = ShiftMask;
       
  1819 -    else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_L ||
       
  1820 -             keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_R) {
       
  1821 -      pModMap[i + VFB_MIN_KEY] = ControlMask;
       
  1822 -    }
       
  1823 -    else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_L ||
       
  1824 -             keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_R)
       
  1825 -      pModMap[i + VFB_MIN_KEY] = Mod1Mask;
       
  1826 -  }
       
  1827 -
       
  1828 -  pKeySyms->minKeyCode = VFB_MIN_KEY;
       
  1829 -  pKeySyms->maxKeyCode = VFB_MAX_KEY;
       
  1830 -  pKeySyms->mapWidth = KEYSYMS_PER_KEY;
       
  1831 -  pKeySyms->map = keyboardMap;
       
  1832 -
       
  1833 -  return TRUE;
       
  1834 -}
       
  1835 -
       
  1836 -static void vfbBell(int percent, DeviceIntPtr device, pointer ctrl, int class_)
       
  1837 -{
       
  1838 -  if (percent > 0)
       
  1839 -    vncBell();
       
  1840 -}
       
  1841 -
       
  1842 -static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff)
       
  1843 -{
       
  1844 -  KeySymsRec            keySyms;
       
  1845 -  CARD8                 modMap[MAP_LENGTH];
       
  1846 -  DevicePtr pDev = (DevicePtr)pDevice;
       
  1847 -#ifdef XKB
       
  1848 -  XkbComponentNamesRec names;
       
  1849 -#endif
       
  1850 -
       
  1851 -  switch (onoff)
       
  1852 -  {
       
  1853 -  case DEVICE_INIT:
       
  1854 -    GetMappings(&keySyms, modMap);
       
  1855 -#ifdef XKB
       
  1856 -    if (!noXkbExtension) {
       
  1857 -      memset(&names, 0, sizeof (names));
       
  1858 -      XkbSetRulesDflts("base", "pc105", "us", NULL, NULL);
       
  1859 -      XkbInitKeyboardDeviceStruct(pDevice, &names, &keySyms, modMap,
       
  1860 -				  (BellProcPtr)vfbBell,
       
  1861 -				  (KbdCtrlProcPtr)NoopDDA);
       
  1862 -    } else
       
  1863 -#endif
       
  1864 -    {
       
  1865 -      InitKeyboardDeviceStruct(pDev, &keySyms, modMap,
       
  1866 -			      (BellProcPtr)vfbBell, (KbdCtrlProcPtr)NoopDDA);
       
  1867 -    }
       
  1868 -    break;
       
  1869 -  case DEVICE_ON:
       
  1870 -    pDev->on = TRUE;
       
  1871 -    break;
       
  1872 -  case DEVICE_OFF:
       
  1873 -    pDev->on = FALSE;
       
  1874 -    break;
       
  1875 -  case DEVICE_CLOSE:
       
  1876 -    break;
       
  1877 -  }
       
  1878 -  return Success;
       
  1879 -}
       
  1880 -
       
  1881 diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h
       
  1882 index 9f300f5..6e4f609 100644
       
  1883 --- a/unix/xserver/hw/vnc/XserverDesktop.h
       
  1884 +++ b/unix/xserver/hw/vnc/XserverDesktop.h
       
  1885 @@ -123,6 +123,7 @@ private:
       
  1886    void deferUpdate();
       
  1887    ScreenPtr pScreen;
       
  1888    PointerDevice *pointerDevice;
       
  1889 +  KeyboardDevice *keyboardDevice;
       
  1890    OsTimerPtr deferredUpdateTimer, dummyTimer;
       
  1891    rfb::VNCServerST* server;
       
  1892    rfb::HTTPServer* httpServer;
       
  1893 
       
  1894 -- 
       
  1895 1.5.6.5
       
  1896