Blob Blame History Raw
diff --git a/unix/xserver/hw/vnc/Input.cc b/unix/xserver/hw/vnc/Input.cc
index 43c3ac3..4112fee 100644
--- a/unix/xserver/hw/vnc/Input.cc
+++ b/unix/xserver/hw/vnc/Input.cc
@@ -68,6 +68,9 @@ rfb::BoolParameter avoidShiftNumLock("AvoidShiftNumLock", "Avoid fake Shift pres
 
 #define BUTTONS 7
 
+class InputDevice *vncInputDevice;
+InputDevice InputDevice::singleton;
+
 /* Event queue is shared between all devices. */
 #if XORG == 15
 static xEvent *eventq = NULL;
@@ -116,11 +119,12 @@ static void enqueueEvents(DeviceIntPtr dev, int n)
 }
 #endif /* XORG < 111 */
 
-InputDevice::InputDevice(rfb::VNCServerST *_server)
-	: server(_server), initialized(false), oldButtonMask(0)
+InputDevice::InputDevice()
+	: oldButtonMask(0)
 {
 	int i;
 
+        vncInputDevice = this;
 #if XORG < 111
 	initEventq();
 #endif
@@ -195,7 +199,7 @@ void InputDevice::PointerMove(const rfb::Point &pos)
 	cursorPos = pos;
 }
 
-void InputDevice::PointerSync(void)
+const rfb::Point &InputDevice::getPointerPos(void)
 {
 	if (pointerDev) {
 		int x, y;
@@ -205,14 +209,10 @@ void InputDevice::PointerSync(void)
 		cursorPos.y = y;
 	}
 
-	if (cursorPos.equals(oldCursorPos))
-		return;
-
-	oldCursorPos = cursorPos;
-	server->setCursorPos(cursorPos);
+        return cursorPos;
 }
 
-static int pointerProc(DeviceIntPtr pDevice, int onoff)
+int InputDevice::pointerProc(DeviceIntPtr pDevice, int onoff)
 {
 	BYTE map[BUTTONS + 1];
 	DevicePtr pDev = (DevicePtr)pDevice;
@@ -237,6 +237,8 @@ static int pointerProc(DeviceIntPtr pDevice, int onoff)
 		btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
 		btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
 		btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
+		btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
+		btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
 
 		axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
 		axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
@@ -261,10 +263,9 @@ static int pointerProc(DeviceIntPtr pDevice, int onoff)
 	case DEVICE_OFF:
 		pDev->on = FALSE;
 		break;
-#if 0
 	case DEVICE_CLOSE:
+		singleton.pointerDev = NULL;
 		break;
-#endif
 	}
 
 	return Success;
@@ -277,9 +278,7 @@ static void keyboardBell(int percent, DeviceIntPtr device, void * ctrl,
 		vncBell();
 }
 
-extern void GetInitKeyboardMap(KeySymsPtr keysyms, CARD8 *modmap);
-
-static int keyboardProc(DeviceIntPtr pDevice, int onoff)
+int InputDevice::keyboardProc(DeviceIntPtr pDevice, int onoff)
 {
 #if XORG < 17
 	KeySymsRec keySyms;
@@ -306,6 +305,9 @@ static int keyboardProc(DeviceIntPtr pDevice, int onoff)
 	case DEVICE_OFF:
 		pDev->on = FALSE;
 		break;
+	case DEVICE_CLOSE:
+		singleton.keyboardDev = NULL;
+		break;
 	}
 
 	return Success;
@@ -313,11 +315,9 @@ static int keyboardProc(DeviceIntPtr pDevice, int onoff)
 
 void InputDevice::InitInputDevice(void)
 {
-	if (initialized)
+	if ((pointerDev != NULL) || (keyboardDev != NULL))
 		return;
 
-	initialized = true;
-
 #if XORG < 17
 	pointerDev = AddInputDevice(
 #if XORG >= 16
diff --git a/unix/xserver/hw/vnc/Input.h b/unix/xserver/hw/vnc/Input.h
index e893049..f58242d 100644
--- a/unix/xserver/hw/vnc/Input.h
+++ b/unix/xserver/hw/vnc/Input.h
@@ -29,20 +29,26 @@
 
 #include <list>
 
-#include <rfb/VNCServerST.h>
+#include <rdr/types.h>
+#include <rfb/Rect.h>
 
 extern "C" {
 #include "input.h"
+/* The Xorg headers define macros that wreak havoc with STL */
+#undef max
 };
 
 #include "xorg-version.h"
 
-/* Represents input device (keyboard + pointer) */
+/*
+ * Represents input device (keyboard + pointer)
+ *
+ * Is a singleton as input devices are global in the X server so
+ * we do not have one per desktop (i.e. per screen).
+ */
+extern class InputDevice *vncInputDevice;
 class InputDevice {
 public:
-	/* Create new InputDevice instance */
-	InputDevice(rfb::VNCServerST *_server);
-
 	/*
 	 * Press or release buttons. Relationship between buttonMask and
 	 * buttons is specified in RFB protocol.
@@ -52,27 +58,28 @@ public:
 	/* Move pointer to target location (point coords are absolute). */
 	void PointerMove(const rfb::Point &point);
 
-	/*
-	 * Send pointer position to clients. If not called then Move() calls
-	 * won't be visible to VNC clients.
-	 */
-	void PointerSync(void);
+	/* Get current known location of the pointer */
+	const rfb::Point &getPointerPos(void);
 
+	/* Press or release one or more keys to get the given symbol */
 	void KeyboardPress(rdr::U32 keysym) { keyEvent(keysym, true); }
 	void KeyboardRelease(rdr::U32 keysym) { keyEvent(keysym, false); }
 
 	/*
-	 * Init input device. This cannot be done in the constructor
-	 * because constructor is called during X server extensions
-	 * initialization. Devices must be initialized after core
-	 * pointer/keyboard initialization which is actually after extesions
-	 * initialization. Check InitExtensions(), InitCoreDevices() and
-	 * InitInput() calls in dix/main.c. Instead it is called from
-	 * XserverDesktop at an appropriate time.
+	 * Init input device.
+	 * This has to be called after core pointer/keyboard
+	 * initialization which unfortunately is after extesions
+	 * initialization (which means we cannot call it in
+	 * vncExtensionInit(). Check InitExtensions(),
+	 * InitCoreDevices() and InitInput() calls in dix/main.c.
+	 * Instead we call it from XserverDesktop at an appropriate
+	 * time.
 	 */
 	void InitInputDevice(void);
 
 private:
+	InputDevice();
+
 	void keyEvent(rdr::U32 keysym, bool down);
 
 	/* Backend dependent functions below here */
@@ -96,22 +103,26 @@ private:
 	KeyCode addKeysym(KeySym keysym, unsigned state);
 
 private:
+	static int pointerProc(DeviceIntPtr pDevice, int onoff);
+	static int keyboardProc(DeviceIntPtr pDevice, int onoff);
+
 #if XORG >= 17
 	static void vncXkbProcessDeviceEvent(int screenNum,
 	                                     InternalEvent *event,
 	                                     DeviceIntPtr dev);
+#else
+	static void GetInitKeyboardMap(KeySymsPtr keysyms, CARD8 *modmap);
 #endif
 
 private:
-	rfb::VNCServerST *server;
-	bool initialized;
 	DeviceIntPtr keyboardDev;
 	DeviceIntPtr pointerDev;
 
 	int oldButtonMask;
-	rfb::Point cursorPos, oldCursorPos;
-
+	rfb::Point cursorPos;
 	KeySym pressedKeys[256];
+private:
+	static InputDevice singleton;
 };
 
 #endif
diff --git a/unix/xserver/hw/vnc/InputCore.cc b/unix/xserver/hw/vnc/InputCore.cc
index a880ca0..b565c73 100644
--- a/unix/xserver/hw/vnc/InputCore.cc
+++ b/unix/xserver/hw/vnc/InputCore.cc
@@ -174,7 +174,7 @@ KeySym keyboardMap[MAP_LEN * KEYSYMS_PER_KEY] = {
 	XK_Menu, NoSymbol,
 };
 
-void GetInitKeyboardMap(KeySymsPtr keysyms, CARD8 *modmap)
+void InputDevice::GetInitKeyboardMap(KeySymsPtr keysyms, CARD8 *modmap)
 {
 	int i;
 
diff --git a/unix/xserver/hw/vnc/InputXKB.cc b/unix/xserver/hw/vnc/InputXKB.cc
index ed93afc..92288aa 100644
--- a/unix/xserver/hw/vnc/InputXKB.cc
+++ b/unix/xserver/hw/vnc/InputXKB.cc
@@ -42,18 +42,6 @@ extern "C" {
 #undef class
 }
 
-#if XORG < 19
-static int vncXkbScreenPrivateKeyIndex;
-static DevPrivateKey vncXkbScreenPrivateKey = &vncXkbScreenPrivateKeyIndex;
-#else
-static DevPrivateKeyRec vncXkbPrivateKeyRec;
-#define vncXkbScreenPrivateKey (&vncXkbPrivateKeyRec)
-#endif
-
-#define vncXkbScreenPrivate(pScreen) \
-	(*(InputDevice**) dixLookupPrivate(&(pScreen)->devPrivates, \
-	                                   vncXkbScreenPrivateKey))
-
 #ifndef KEYBOARD_OR_FLOAT
 #define KEYBOARD_OR_FLOAT MASTER_KEYBOARD
 #endif
@@ -209,18 +197,6 @@ static unsigned XkbKeyEffectiveGroup(XkbDescPtr xkb, KeyCode key, unsigned int m
 
 void InputDevice::PrepareInputDevices(void)
 {
-#if XORG < 19
-	if (!dixRequestPrivate(vncXkbScreenPrivateKey, sizeof(InputDevice*)))
-		FatalError("Failed to register TigerVNC XKB screen key\n");
-#else
-	if (!dixRegisterPrivateKey(vncXkbScreenPrivateKey, PRIVATE_SCREEN,
-	                           sizeof(InputDevice*)))
-		FatalError("Failed to register TigerVNC XKB screen key\n");
-#endif
-
-	for (int scr = 0; scr < screenInfo.numScreens; scr++)
-		vncXkbScreenPrivate(screenInfo.screens[scr]) = this;
-
 	/*
 	 * Not ideal since these callbacks do not stack, but it's the only
 	 * decent way we can reliably catch events for both the slave and
@@ -636,10 +612,9 @@ void InputDevice::vncXkbProcessDeviceEvent(int screenNum,
                                            InternalEvent *event,
                                            DeviceIntPtr dev)
 {
-	InputDevice *self = vncXkbScreenPrivate(screenInfo.screens[screenNum]);
 	unsigned int backupctrls;
 
-	if (event->device_event.sourceid == self->keyboardDev->id) {
+	if (event->device_event.sourceid == singleton.keyboardDev->id) {
 		XkbControlsPtr ctrls;
 
 		/*
@@ -661,7 +636,7 @@ void InputDevice::vncXkbProcessDeviceEvent(int screenNum,
 
 	dev->c_public.processInputProc(event, dev);
 
-	if (event->device_event.sourceid == self->keyboardDev->id) {
+	if (event->device_event.sourceid == singleton.keyboardDev->id) {
 		XkbControlsPtr ctrls;
 
 		ctrls = dev->key->xkbInfo->desc->ctrls;
diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc
index fc0646d..05169b0 100644
--- a/unix/xserver/hw/vnc/XserverDesktop.cc
+++ b/unix/xserver/hw/vnc/XserverDesktop.cc
@@ -157,15 +157,12 @@ XserverDesktop::XserverDesktop(ScreenPtr pScreen_,
 
   if (httpListener)
     httpServer = new FileHTTPServer(this);
-
-  inputDevice = new InputDevice(server);
 }
 
 XserverDesktop::~XserverDesktop()
 {
   if (!directFbptr)
     delete [] data;
-  delete inputDevice;
   delete httpServer;
   delete server;
 }
@@ -583,7 +580,7 @@ void XserverDesktop::blockHandler(fd_set* fds, OSTimePtr timeout)
   // so we abuse the fact that this routine will be called first thing
   // once the dix is done initialising.
   // [1] Technically Xvnc has InitInput(), but libvnc.so has nothing.
-  inputDevice->InitInputDevice();
+  vncInputDevice->InitInputDevice();
 
   try {
     int nextTimeout;
@@ -691,7 +688,11 @@ void XserverDesktop::wakeupHandler(fd_set* fds, int nfds)
         }
       }
 
-      inputDevice->PointerSync();
+      // We are responsible for propagating mouse movement between clients
+      if (!oldCursorPos.equals(vncInputDevice->getPointerPos())) {
+        oldCursorPos = vncInputDevice->getPointerPos();
+        server->setCursorPos(oldCursorPos);
+      }
     }
 
     // Then let the timers do some processing. Rescheduling is done in
@@ -818,8 +819,8 @@ void XserverDesktop::approveConnection(void* opaqueId, bool accept,
 
 void XserverDesktop::pointerEvent(const Point& pos, int buttonMask)
 {
-  inputDevice->PointerMove(pos);
-  inputDevice->PointerButtonAction(buttonMask);
+  vncInputDevice->PointerMove(pos);
+  vncInputDevice->PointerButtonAction(buttonMask);
 }
 
 void XserverDesktop::clientCutText(const char* str, int len)
@@ -1136,7 +1137,7 @@ void XserverDesktop::lookup(int index, int* r, int* g, int* b)
 void XserverDesktop::keyEvent(rdr::U32 keysym, bool down)
 {
 	if (down)
-		inputDevice->KeyboardPress(keysym);
+		vncInputDevice->KeyboardPress(keysym);
 	else
-		inputDevice->KeyboardRelease(keysym);
+		vncInputDevice->KeyboardRelease(keysym);
 }
diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h
index fb247b0..ca6e8af 100644
--- a/unix/xserver/hw/vnc/XserverDesktop.h
+++ b/unix/xserver/hw/vnc/XserverDesktop.h
@@ -153,5 +153,7 @@ private:
   typedef std::map<RROutputPtr, rdr::U32> OutputIdMap;
   OutputIdMap outputIdMap;
 #endif
+
+  rfb::Point oldCursorPos;
 };
 #endif
diff --git a/unix/xserver/hw/vnc/xf86vncModule.cc b/unix/xserver/hw/vnc/xf86vncModule.cc
index 3187bba..596d399 100644
--- a/unix/xserver/hw/vnc/xf86vncModule.cc
+++ b/unix/xserver/hw/vnc/xf86vncModule.cc
@@ -112,9 +112,9 @@ static void vncExtensionInitWithParams(INITARGS)
           i.param->setParam(val);
       }
     }
-
-    vncExtensionInit();
   }
+
+  vncExtensionInit();
 }
 }