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