--- /dev/null
+/* Copyright (C) 2009 TightVNC Team
+ * Copyright (C) 2009 Red Hat, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "Input.h"
+#include "xorg-version.h"
+
+extern "C" {
+#include "mi.h"
+}
+
+/* Event queue is shared between all devices. */
+#if XORG == 15
+static xEvent *eventq = NULL;
+#else
+static EventList *eventq = NULL;
+#endif
+
+static void initEventq(void)
+{
+ /* eventq is never free()-ed because it exists during server life. */
+ if (eventq == NULL) {
+#if XORG == 15
+ eventq = (xEvent *)xcalloc(sizeof(xEvent),
+ GetMaximumEventsNum());
+ if (!eventq)
+ FatalError("Couldn't allocate eventq\n");
+#else
+ GetEventList(&eventq);
+#endif
+ }
+}
+
+static void enqueueEvents(DeviceIntPtr dev, int n)
+{
+ int i;
+
+ for (i = 0; i < n; i++) {
+ /*
+ * Passing arguments in global variable eventq is probably not
+ * good programming practise but in this case it is safe and
+ * clear.
+ */
+ mieqEnqueue(dev,
+#if XORG == 15
+ eventq + i
+#else
+ (eventq + i)->event
+#endif
+ );
+ }
+}
+
+/* Pointer device pre-declarations */
+#define BUTTONS 5
+static int pointerProc(DeviceIntPtr pDevice, int onoff);
+
+/* Pointer device methods */
+
+PointerDevice::PointerDevice(rfb::VNCServerST *_server)
+ : server(_server), oldButtonMask(0)
+{
+ dev = AddInputDevice(
+#if XORG >= 16
+ serverClient,
+#endif
+ pointerProc, TRUE);
+ RegisterPointerDevice(dev);
+ initEventq();
+}
+
+void PointerDevice::ButtonAction(int buttonMask)
+{
+ int i, n;
+
+ for (i = 0; i < BUTTONS; i++) {
+ if ((buttonMask ^ oldButtonMask) & (1 << i)) {
+ int action = (buttonMask & (1<<i)) ?
+ ButtonPress : ButtonRelease;
+ n = GetPointerEvents(eventq, dev, action, i + 1,
+ POINTER_RELATIVE, 0, 0, NULL);
+ enqueueEvents(dev, n);
+
+ }
+ }
+
+ oldButtonMask = buttonMask;
+}
+
+void PointerDevice::Move(const rfb::Point &pos)
+{
+ int n, valuators[2];
+
+ if (pos.equals(cursorPos))
+ return;
+
+ valuators[0] = pos.x;
+ valuators[1] = pos.y;
+ n = GetPointerEvents(eventq, dev, MotionNotify, 0, POINTER_ABSOLUTE, 0,
+ 2, valuators);
+ enqueueEvents(dev, n);
+
+ cursorPos = pos;
+}
+
+void PointerDevice::Sync(void)
+{
+ if (cursorPos.equals(oldCursorPos))
+ return;
+
+ oldCursorPos = cursorPos;
+ server->setCursorPos(cursorPos);
+ server->tryUpdate();
+}
+
+static int pointerProc(DeviceIntPtr pDevice, int onoff)
+{
+ BYTE map[BUTTONS + 1];
+ DevicePtr pDev = (DevicePtr)pDevice;
+ int i;
+
+ switch (onoff) {
+ case DEVICE_INIT:
+ for (i = 0; i < BUTTONS + 1; i++)
+ map[i] = i;
+
+ InitPointerDeviceStruct(pDev, map, BUTTONS,
+#if XORG == 15
+ GetMotionHistory,
+#endif
+ (PtrCtrlProcPtr)NoopDDA,
+ GetMotionHistorySize(), 2);
+ break;
+ case DEVICE_ON:
+ pDev->on = TRUE;
+ break;
+ case DEVICE_OFF:
+ pDev->on = FALSE;
+ break;
+#if 0
+ case DEVICE_CLOSE:
+ break;
+#endif
+ }
+
+ return Success;
+}
+
--- /dev/null
+/* Copyright (C) 2009 TightVNC Team
+ * Copyright (C) 2009 Red Hat, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/* Make sure macro doesn't conflict with macro in include/input.h. */
+#ifndef INPUT_H_
+#define INPUT_H_
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <rfb/VNCServerST.h>
+
+extern "C" {
+#include "input.h"
+};
+
+/* Represents pointer device. */
+class PointerDevice {
+public:
+ /* Create new PointerDevice instance. */
+ PointerDevice(rfb::VNCServerST *_server);
+
+ /*
+ * Press or release buttons. Relationship between buttonMask and
+ * buttons is specified in RFB protocol.
+ */
+ void ButtonAction(int buttonMask);
+
+ /* Move pointer to target location (point coords are absolute). */
+ void Move(const rfb::Point &point);
+
+ /*
+ * Send pointer position to clients. If not called then Move() calls
+ * won't be visible to clients.
+ */
+ void Sync(void);
+private:
+ rfb::VNCServerST *server;
+ DeviceIntPtr dev;
+ int oldButtonMask;
+ rfb::Point cursorPos, oldCursorPos;
+};
+
+#endif
noinst_LTLIBRARIES = libvnccommon.la
-HDRS = RegionHelper.h vncExtInit.h vncHooks.h XserverDesktop.h xorg-version.h
+HDRS = RegionHelper.h vncExtInit.h vncHooks.h XserverDesktop.h xorg-version.h \
+ Input.h
-libvnccommon_la_SOURCES = $(HDRS) vncExtInit.cc vncHooks.cc XserverDesktop.cc
+libvnccommon_la_SOURCES = $(HDRS) vncExtInit.cc vncHooks.cc XserverDesktop.cc \
+ Input.cc
libvnccommon_la_CPPFLAGS = -DVENDOR_RELEASE="$(VENDOR_RELEASE)" \
-DVENDOR_STRING="\"$(VENDOR_STRING)\"" -I$(LIB_DIR) \
#include "XserverDesktop.h"
#include "vncExtInit.h"
#include "xorg-version.h"
+#include "Input.h"
extern "C" {
#define public c_public
}
static DeviceIntPtr vncKeyboardDevice = NULL;
-static DeviceIntPtr vncPointerDevice = NULL;
#if XORG == 15
static xEvent *eventq = NULL;
#else
#endif
static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff);
-static int vfbMouseProc(DeviceIntPtr pDevice, int onoff);
using namespace rfb;
using namespace network;
listener(listener_), httpListener(httpListener_),
cmap(0), deferredUpdateTimerSet(false),
grabbing(false), ignoreHooks_(false), directFbptr(true),
- oldButtonMask(0),
queryConnectId(0)
{
format = pf;
RegisterKeyboardDevice(vncKeyboardDevice);
}
- if (vncPointerDevice == NULL) {
- vncPointerDevice = AddInputDevice(
-#if XORG >= 16
- serverClient,
-#endif
- vfbMouseProc, TRUE);
- RegisterPointerDevice(vncPointerDevice);
- }
+ pointerDevice = new PointerDevice(server);
}
XserverDesktop::~XserverDesktop()
delete [] data;
TimerFree(deferredUpdateTimer);
TimerFree(dummyTimer);
+ delete pointerDevice;
delete httpServer;
delete server;
}
}
}
-void XserverDesktop::positionCursor()
-{
- if (!cursorPos.equals(oldCursorPos)) {
- oldCursorPos = cursorPos;
- (*pScreen->SetCursorPosition) (
-#if XORG >= 16
- vncPointerDevice,
-#endif
- pScreen, cursorPos.x, cursorPos.y, FALSE);
- server->setCursorPos(cursorPos);
- server->tryUpdate();
- }
-}
-
void XserverDesktop::blockHandler(fd_set* fds)
{
try {
-#if XORG == 15
- ScreenPtr screenWithCursor = GetCurrentRootWindow()->drawable.pScreen;
-#else
- ScreenPtr screenWithCursor =
- GetCurrentRootWindow(vncPointerDevice)->drawable.pScreen;
-#endif
- if (screenWithCursor == pScreen) {
- int x, y;
- GetSpritePosition(
-#if XORG >= 16
- vncPointerDevice,
-#endif
- &x, &y);
- if (x != cursorPos.x || y != cursorPos.y) {
- cursorPos = oldCursorPos = Point(x, y);
- server->setCursorPos(cursorPos);
- server->tryUpdate();
- }
- }
-
if (listener)
FD_SET(listener->getFd(), fds);
if (httpListener)
}
}
- positionCursor();
+ pointerDevice->Sync();
}
int timeout = server->checkTimeouts();
void XserverDesktop::pointerEvent(const Point& pos, int buttonMask)
{
- int i, j, n, valuators[2];
-
- // SetCursorPosition seems to be very expensive (at least on XFree86 3.3.6
- // for S3), so we delay calling it until positionCursor() is called at the
- // end of processing a load of RFB.
- //(*pScreen->SetCursorPosition) (pScreen, pos.x, pos.y, FALSE);
-
- NewCurrentScreen(
-#if XORG >= 16
- vncPointerDevice,
-#endif
- pScreen, pos.x, pos.y);
-
- if (!pos.equals(cursorPos)) {
- valuators[0] = pos.x;
- valuators[1] = pos.y;
-
-#if XORG >= 16
- GetEventList(&eventq);
-#endif
- n = GetPointerEvents (eventq, vncPointerDevice, MotionNotify, 0,
- POINTER_ABSOLUTE, 0, 2, valuators);
-
- for (i = 0; i < n; i++) {
- mieqEnqueue (vncPointerDevice,
-#if XORG == 15
- eventq + i
-#else
- (eventq + i)->event
-#endif
- );
- }
- }
-
- for (i = 0; i < 5; i++) {
- if ((buttonMask ^ oldButtonMask) & (1<<i)) {
- // Do not use the pointer mapping. Treat VNC buttons as logical
- // buttons.
- n = GetPointerEvents (eventq, vncPointerDevice,
- (buttonMask & (1<<i)) ?
- ButtonPress : ButtonRelease,
- i + 1, POINTER_RELATIVE, 0, 0, NULL);
-
- for (j = 0; j < n; j++) {
- mieqEnqueue (vncPointerDevice,
-#if XORG == 15
- eventq + j
-#else
- (eventq + j)->event
-#endif
- );
- }
- }
- }
-
- cursorPos = pos;
- oldButtonMask = buttonMask;
+ pointerDevice->Move(pos);
+ pointerDevice->ButtonAction(buttonMask);
}
void XserverDesktop::clientCutText(const char* str, int len)
return Success;
}
-static int vfbMouseProc(DeviceIntPtr pDevice, int onoff)
-{
- BYTE map[6];
- DevicePtr pDev = (DevicePtr)pDevice;
-
- switch (onoff)
- {
- case DEVICE_INIT:
- map[1] = 1;
- map[2] = 2;
- map[3] = 3;
- map[4] = 4;
- map[5] = 5;
- InitPointerDeviceStruct(pDev, map, 5,
-#if XORG == 15
- GetMotionHistory,
-#endif
- (PtrCtrlProcPtr)NoopDDA, GetMotionHistorySize(), 2);
- break;
-
- case DEVICE_ON:
- pDev->on = TRUE;
- break;
-
- case DEVICE_OFF:
- pDev->on = FALSE;
- break;
-
- case DEVICE_CLOSE:
- break;
- }
- return Success;
-}
#include <rfb/Configuration.h>
#include <rfb/VNCServerST.h>
#include <rdr/SubstitutingInStream.h>
+#include "Input.h"
extern "C" {
#define class c_class
void setCursor(CursorPtr cursor);
void add_changed(RegionPtr reg);
void add_copied(RegionPtr dst, int dx, int dy);
- void positionCursor();
void ignoreHooks(bool b) { ignoreHooks_ = b; }
void blockHandler(fd_set* fds);
void wakeupHandler(fd_set* fds, int nfds);
pointer arg);
void deferUpdate();
ScreenPtr pScreen;
+ PointerDevice *pointerDevice;
OsTimerPtr deferredUpdateTimer, dummyTimer;
rfb::VNCServerST* server;
rfb::HTTPServer* httpServer;
bool grabbing;
bool ignoreHooks_;
bool directFbptr;
- int oldButtonMask;
- rfb::Point cursorPos, oldCursorPos;
void* queryConnectId;
rfb::CharArray queryConnectAddress;