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 -#include +#include +#include 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 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(); } }