added logging facility and added a bunch of log messages.

This commit is contained in:
crs 2001-10-14 14:37:41 +00:00
parent 23f948d55a
commit 1ed2b43e13
8 changed files with 136 additions and 31 deletions

View File

@ -13,7 +13,7 @@ RMR = /bin/rm -rf
#
# compiler options
#
GCXXDEFS = -D_POSIX_C_SOURCE=199309
GCXXDEFS = -D_XOPEN_SOURCE=500
GCXXINCS = -I$(DEPTH)/include -I/usr/X11R6/include
GCXXOPTS = -Wall -W -fexceptions -fno-rtti
CXXOPTIMIZER = -g

View File

@ -13,6 +13,7 @@ LCXXINCS = \
$(NULL)
CXXFILES = \
XBase.cpp \
CLog.cpp \
CFunctionJob.cpp \
CStopwatch.cpp \
$(NULL)

View File

@ -6,7 +6,7 @@
#include "ProtocolTypes.h"
#include "CTimerThread.h"
#include "XSynergy.h"
#include <stdio.h>
#include "CLog.h"
#include <memory>
//
@ -29,6 +29,8 @@ CClient::~CClient()
#include "CXWindowsSecondaryScreen.h"
void CClient::run(const CNetworkAddress& serverAddress)
{
log((CLOG_DEBUG "starting client \"%s\"", m_name.c_str()));
std::auto_ptr<ISocket> socket;
std::auto_ptr<IInputStream> input;
std::auto_ptr<IOutputStream> output;
@ -37,8 +39,10 @@ void CClient::run(const CNetworkAddress& serverAddress)
CTimerThread timer(30.0); // FIXME -- timeout in member
// create socket and attempt to connect to server
log((CLOG_DEBUG "connecting to server"));
socket.reset(new CTCPSocket()); // FIXME -- use factory
socket->connect(serverAddress);
log((CLOG_INFO "connected to server"));
// get the input and output streams
IInputStream* srcInput = socket->getInputStream();
@ -59,16 +63,19 @@ void CClient::run(const CNetworkAddress& serverAddress)
output.reset(new COutputPacketStream(srcOutput, true));
// wait for hello from server
log((CLOG_DEBUG "wait for hello"));
SInt32 major, minor;
CProtocolUtil::readf(input.get(), "Synergy%2i%2i", &major, &minor);
// check versions
log((CLOG_DEBUG "got hello version %d.%d", major, minor));
if (major < kMajorVersion ||
(major == kMajorVersion && minor < kMinorVersion)) {
throw XIncompatibleClient(major, minor);
}
// say hello back
log((CLOG_DEBUG "say hello version %d.%d", kMajorVersion, kMinorVersion));
CProtocolUtil::writef(output.get(), "Synergy%2i%2i%s",
kMajorVersion, kMinorVersion,
m_name.size(), m_name.data());
@ -78,27 +85,27 @@ void CClient::run(const CNetworkAddress& serverAddress)
m_output = output.get();
}
catch (XIncompatibleClient& e) {
fprintf(stderr, "incompatible server version (%d.%d)\n",
e.getMajor(), e.getMinor());
log((CLOG_ERR "server has incompatible version %d.%d", e.getMajor(), e.getMinor()));
return;
}
catch (XThread&) {
fprintf(stderr, "connection timed out\n");
log((CLOG_ERR "connection timed out"));
throw;
}
catch (XBase& e) {
fprintf(stderr, "connection failed: %s\n", e.what());
log((CLOG_ERR "connection failed: %s", e.what()));
return;
}
// connect to screen
std::auto_ptr<CScreenCleaner> screenCleaner;
try {
log((CLOG_DEBUG "creating secondary screen"));
m_screen = new CXWindowsSecondaryScreen;
screenCleaner.reset(new CScreenCleaner(this, m_screen));
}
catch (XBase& e) {
fprintf(stderr, "cannot open screen: %s\n", e.what());
log((CLOG_ERR "cannot open screen: %s", e.what()));
return;
}
@ -106,21 +113,24 @@ void CClient::run(const CNetworkAddress& serverAddress)
// handle messages from server
for (;;) {
// wait for reply
log((CLOG_DEBUG "waiting for message"));
UInt8 code[4];
UInt32 n = input->read(code, 4);
// verify we got an entire code
if (n == 0) {
log((CLOG_NOTE "server disconnected"));
// server hungup
break;
}
if (n != 4) {
// client sent an incomplete message
fprintf(stderr, "incomplete message from server\n");
log((CLOG_ERR "incomplete message from server"));
break;
}
// parse message
log((CLOG_DEBUG "msg from server: %c%c%c%c", code[0], code[1], code[2], code[3]));
if (memcmp(code, kMsgDMouseMove, 4) == 0) {
onMouseMove();
}
@ -169,20 +179,22 @@ void CClient::run(const CNetworkAddress& serverAddress)
}
else {
// unknown message
fprintf(stderr, "unknown message from server\n");
log((CLOG_ERR "unknown message from server"));
break;
}
}
}
catch (XBase& e) {
fprintf(stderr, "error: %s\n", e.what());
log((CLOG_ERR "error: %s", e.what()));
return;
}
// done with screen
log((CLOG_DEBUG "destroying secondary screen"));
screenCleaner.reset();
// done with socket
log((CLOG_DEBUG "disconnecting from server"));
socket->close();
}
@ -215,6 +227,7 @@ void CClient::onQueryInfo()
SInt32 w, h;
m_screen->getSize(&w, &h);
SInt32 zoneSize = m_screen->getJumpZoneSize();
log((CLOG_DEBUG "sending info size=%d,%d zone=%d", w, h, zoneSize));
CProtocolUtil::writef(m_output, kMsgDInfo, w, h, zoneSize);
}

View File

@ -87,3 +87,9 @@ CString CScreenMap::getNeighbor(const CString& srcName,
// return connection
return index->second.m_neighbor[srcSide - kFirstDirection];
}
const char* CScreenMap::dirName(EDirection dir)
{
static const char* s_name[] = { "left", "right", "top", "bottom" };
return s_name[dir - kFirstDirection];
}

View File

@ -33,6 +33,9 @@ class CScreenMap {
// if there is no neighbor in that direction.
CString getNeighbor(const CString&, EDirection) const throw();
// get the name of a direction (for debugging)
static const char* dirName(EDirection);
private:
class CCell {
public:

View File

@ -16,7 +16,7 @@
#include "CTimerThread.h"
#include "CStopwatch.h"
#include "TMethodJob.h"
#include <stdio.h>
#include "CLog.h"
#include <assert.h>
#include <memory>
@ -38,6 +38,8 @@ CServer::~CServer()
void CServer::run()
{
try {
log((CLOG_NOTE "starting server"));
// connect to primary screen
openPrimaryScreen();
@ -48,23 +50,27 @@ void CServer::run()
// FIXME
// wait until done
log((CLOG_DEBUG "waiting for quit"));
CLock lock(&m_mutex);
while (m_done == false) {
m_done.wait();
}
// clean up
log((CLOG_DEBUG "stopping server"));
closePrimaryScreen();
cleanupThreads();
}
catch (XBase& e) {
fprintf(stderr, "server error: %s\n", e.what());
log((CLOG_ERR "server error: %s\n", e.what()));
// clean up
closePrimaryScreen();
cleanupThreads();
}
catch (...) {
log((CLOG_DEBUG "server shutdown"));
// clean up
closePrimaryScreen();
cleanupThreads();
@ -108,6 +114,7 @@ void CServer::setInfo(const CString& client,
info->m_width = w;
info->m_height = h;
info->m_zoneSize = zoneSize;
log((CLOG_NOTE "client \"%s\" size=%dx%d zone=%d", client.c_str(), w, h, zoneSize));
}
bool CServer::onCommandKey(KeyID /*id*/,
@ -118,6 +125,7 @@ bool CServer::onCommandKey(KeyID /*id*/,
void CServer::onKeyDown(KeyID id, KeyModifierMask mask)
{
log((CLOG_DEBUG "onKeyDown id=%d mask=0x%04x", id, mask));
assert(m_active != NULL);
// handle command keys
@ -133,6 +141,7 @@ void CServer::onKeyDown(KeyID id, KeyModifierMask mask)
void CServer::onKeyUp(KeyID id, KeyModifierMask mask)
{
log((CLOG_DEBUG "onKeyUp id=%d mask=0x%04x", id, mask));
assert(m_active != NULL);
// handle command keys
@ -148,6 +157,7 @@ void CServer::onKeyUp(KeyID id, KeyModifierMask mask)
void CServer::onKeyRepeat(KeyID id, KeyModifierMask mask)
{
log((CLOG_DEBUG "onKeyRepeat id=%d mask=0x%04x", id, mask));
assert(m_active != NULL);
// handle command keys
@ -164,6 +174,7 @@ void CServer::onKeyRepeat(KeyID id, KeyModifierMask mask)
void CServer::onMouseDown(ButtonID id)
{
log((CLOG_DEBUG "onMouseDown id=%d", id));
assert(m_active != NULL);
// relay
@ -174,6 +185,7 @@ void CServer::onMouseDown(ButtonID id)
void CServer::onMouseUp(ButtonID id)
{
log((CLOG_DEBUG "onMouseUp id=%d", id));
assert(m_active != NULL);
// relay
@ -184,6 +196,8 @@ void CServer::onMouseUp(ButtonID id)
void CServer::onMouseMovePrimary(SInt32 x, SInt32 y)
{
log((CLOG_DEBUG "onMouseMovePrimary %d,%d", x, y));
// mouse move on primary (server's) screen
assert(m_active != NULL);
assert(m_active->m_protocol == NULL);
@ -198,18 +212,22 @@ void CServer::onMouseMovePrimary(SInt32 x, SInt32 y)
if (x < m_active->m_zoneSize) {
x -= m_active->m_zoneSize;
dir = CScreenMap::kLeft;
log((CLOG_DEBUG "switch to left"));
}
else if (x >= m_active->m_width - m_active->m_zoneSize) {
x += m_active->m_zoneSize;
dir = CScreenMap::kRight;
log((CLOG_DEBUG "switch to right"));
}
else if (y < m_active->m_zoneSize) {
y -= m_active->m_zoneSize;
dir = CScreenMap::kTop;
log((CLOG_DEBUG "switch to top"));
}
else if (y >= m_active->m_height - m_active->m_zoneSize) {
y += m_active->m_zoneSize;
dir = CScreenMap::kBottom;
log((CLOG_DEBUG "switch to bottom"));
}
else {
// still on local screen
@ -233,6 +251,8 @@ void CServer::onMouseMovePrimary(SInt32 x, SInt32 y)
void CServer::onMouseMoveSecondary(SInt32 dx, SInt32 dy)
{
log((CLOG_DEBUG "onMouseMoveSecondary %+d,%+d", dx, dy));
// mouse move on secondary (client's) screen
assert(m_active != NULL);
assert(m_active->m_protocol != NULL);
@ -264,8 +284,7 @@ void CServer::onMouseMoveSecondary(SInt32 dx, SInt32 dy)
// get neighbor if we should switch
if (newScreen == NULL) {
// TRACE(("leave %s on %s", m_activeScreen->getName().c_str(),
// s_dirName[dir]));
log((CLOG_DEBUG "leave \"%s\" on %s", m_active->m_name.c_str(), CScreenMap::dirName(dir)));
SInt32 x = m_x, y = m_y;
newScreen = getNeighbor(m_active, dir, x, y);
@ -290,7 +309,7 @@ void CServer::onMouseMoveSecondary(SInt32 dx, SInt32 dy)
}
else {
// clamp to edge when locked
// TRACE(("clamp to %s", m_activeScreen->getName().c_str()));
log((CLOG_DEBUG "clamp to \"%s\"", m_active->m_name.c_str()));
if (m_x < 0)
m_x = 0;
else if (m_x > m_active->m_width - 1)
@ -305,8 +324,7 @@ void CServer::onMouseMoveSecondary(SInt32 dx, SInt32 dy)
if (newScreen == NULL || newScreen == m_active) {
// do nothing if mouse didn't move
if (m_x != xOld || m_y != yOld) {
// TRACE(("move on %s to %d,%d",
// m_activeScreen->getName().c_str(), m_x, m_y));
log((CLOG_DEBUG "move on %s to %d,%d", m_active->m_name.c_str(), m_x, m_y));
m_active->m_protocol->sendMouseMove(m_x, m_y);
}
}
@ -319,6 +337,7 @@ void CServer::onMouseMoveSecondary(SInt32 dx, SInt32 dy)
void CServer::onMouseWheel(SInt32 delta)
{
log((CLOG_DEBUG "onMouseWheel %+d", delta));
assert(m_active != NULL);
// relay
@ -340,8 +359,7 @@ void CServer::switchScreen(CScreenInfo* dst,
assert(x >= 0 && y >= 0 && x < dst->m_width && y < dst->m_height);
assert(m_active != NULL);
// TRACE(("switch %s to %s at %d,%d", m_active->m_name.c_str(),
// dst->m_name.c_str(), x, y));
log((CLOG_NOTE "switch from \"%s\" to \"%s\" at %d,%d", m_active->m_name.c_str(), dst->m_name.c_str(), x, y));
// wrapping means leaving the active screen and entering it again.
// since that's a waste of time we skip that and just warp the
@ -387,22 +405,27 @@ CServer::CScreenInfo* CServer::getNeighbor(CScreenInfo* src,
CString srcName = src->m_name;
assert(!srcName.empty());
log((CLOG_DEBUG "find neighbor on %s of \"%s\"", CScreenMap::dirName(dir), srcName.c_str()));
for (;;) {
// look up name of neighbor
const CString dstName(m_screenMap.getNeighbor(srcName, dir));
// if nothing in that direction then return NULL
if (dstName.empty())
if (dstName.empty()) {
log((CLOG_DEBUG "no neighbor on %s of \"%s\"", CScreenMap::dirName(dir), srcName.c_str()));
return NULL;
}
// look up neighbor cell. if the screen is connected then
// we can stop. otherwise we skip over an unconnected
// screen.
CScreenList::const_iterator index = m_screens.find(dstName);
if (index != m_screens.end()) {
log((CLOG_DEBUG "\"%s\" is on %s of \"%s\"", dstName.c_str(), CScreenMap::dirName(dir), srcName.c_str()));
return index->second;
}
log((CLOG_DEBUG "ignored \"%s\" on %s of \"%s\"", dstName.c_str(), CScreenMap::dirName(dir), srcName.c_str()));
srcName = dstName;
}
}
@ -431,7 +454,7 @@ CServer::CScreenInfo* CServer::getNeighbor(CScreenInfo* src,
if (x >= 0) {
break;
}
// TRACE(("skipping over screen %s", dst->m_name.c_str()));
log((CLOG_DEBUG "skipping over screen %s", dst->m_name.c_str()));
dst = getNeighbor(lastGoodScreen, srcSide);
}
break;
@ -445,7 +468,7 @@ CServer::CScreenInfo* CServer::getNeighbor(CScreenInfo* src,
if (x < w) {
break;
}
// TRACE(("skipping over screen %s", dst->m_name.c_str()));
log((CLOG_DEBUG "skipping over screen %s", dst->m_name.c_str()));
dst = getNeighbor(lastGoodScreen, srcSide);
}
break;
@ -459,7 +482,7 @@ CServer::CScreenInfo* CServer::getNeighbor(CScreenInfo* src,
if (y >= 0) {
break;
}
// TRACE(("skipping over screen %s", dst->m_name.c_str()));
log((CLOG_DEBUG "skipping over screen %s", dst->m_name.c_str()));
dst = getNeighbor(lastGoodScreen, srcSide);
}
break;
@ -473,7 +496,7 @@ CServer::CScreenInfo* CServer::getNeighbor(CScreenInfo* src,
if (y < h) {
break;
}
// TRACE(("skipping over screen %s", dst->m_name.c_str()));
log((CLOG_DEBUG "skipping over screen %s", dst->m_name.c_str()));
dst = getNeighbor(lastGoodScreen, srcSide);
}
break;
@ -548,6 +571,8 @@ void CServer::mapPosition(CScreenInfo* src,
#include "CTCPListenSocket.h"
void CServer::acceptClients(void*)
{
log((CLOG_DEBUG "starting to wait for clients"));
// add this thread to the list of threads to cancel. remove from
// list in d'tor.
CCleanupNote cleanupNote(this);
@ -564,25 +589,30 @@ void CServer::acceptClients(void*)
CNetworkAddress addr(50001 /* FIXME -- m_port */);
for (;;) {
try {
log((CLOG_DEBUG "binding listen socket"));
listen->bind(addr);
break;
}
catch (XSocketAddressInUse&) {
// give up if we've waited too long
if (timer.getTime() >= m_bindTimeout) {
log((CLOG_DEBUG "waited too long to bind, giving up"));
throw;
}
// wait a bit before retrying
log((CLOG_DEBUG "bind failed; waiting to retry"));
CThread::sleep(5.0);
}
}
// accept connections and begin processing them
log((CLOG_DEBUG "waiting for client connections"));
for (;;) {
// accept connection
CThread::testCancel();
ISocket* socket = listen->accept();
log((CLOG_NOTE "accepted client connection"));
CThread::testCancel();
// start handshake thread
@ -591,13 +621,15 @@ void CServer::acceptClients(void*)
}
}
catch (XBase& e) {
fprintf(stderr, "cannot listen for clients: %s\n", e.what());
log((CLOG_ERR "cannot listen for clients: %s", e.what()));
quit();
}
}
void CServer::handshakeClient(void* vsocket)
{
log((CLOG_DEBUG "negotiating with new client"));
// get the socket pointer from the argument
assert(vsocket != NULL);
std::auto_ptr<ISocket> socket(reinterpret_cast<ISocket*>(vsocket));
@ -638,11 +670,13 @@ void CServer::handshakeClient(void* vsocket)
static const UInt32 maxHelloLen = 1024;
// say hello
log((CLOG_DEBUG "saying hello"));
CProtocolUtil::writef(output.get(), "Synergy%2i%2i",
kMajorVersion, kMinorVersion);
output->flush();
// wait for the reply
log((CLOG_DEBUG "waiting for hello reply"));
UInt32 n = input->getSize();
if (n > maxHelloLen) {
throw XBadClient();
@ -651,6 +685,7 @@ void CServer::handshakeClient(void* vsocket)
// get and parse the reply to hello
SInt32 major, minor;
try {
log((CLOG_DEBUG "parsing hello reply"));
CProtocolUtil::readf(input.get(), "Synergy%2i%2i%s",
&major, &minor, &name);
}
@ -662,6 +697,7 @@ void CServer::handshakeClient(void* vsocket)
}
// create a protocol interpreter for the version
log((CLOG_DEBUG "creating interpreter for client %s version %d.%d", name.c_str(), major, minor));
protocol.reset(CServerProtocol::create(major, minor,
this, name, input.get(), output.get()));
@ -670,28 +706,28 @@ void CServer::handshakeClient(void* vsocket)
name, protocol.get()));
// ask and wait for the client's info
log((CLOG_DEBUG "waiting for info for client %s", name.c_str()));
protocol->queryInfo();
}
// handle messages from client. returns when the client
// disconnects.
log((CLOG_NOTE "client %s is connected", name.c_str()));
protocol->run();
}
catch (XIncompatibleClient& e) {
// client is incompatible
fprintf(stderr, "client is incompatible (%s, %d.%d)\n",
name.c_str(), e.getMajor(), e.getMinor());
log((CLOG_WARN "client \"%s\" has incompatible version %d.%d)", name.c_str(), e.getMajor(), e.getMinor()));
// FIXME -- could print network address if socket had suitable method
}
catch (XBadClient&) {
// client not behaving
fprintf(stderr, "protocol error from client %s\n", name.c_str());
log((CLOG_WARN "protocol error from client \"%s\"", name.c_str()));
// FIXME -- could print network address if socket had suitable method
}
catch (XBase& e) {
// misc error
fprintf(stderr, "error communicating with client %s: %s\n",
name.c_str(), e.what());
log((CLOG_WARN "error communicating with client \"%s\": %s", name.c_str(), e.what()));
// FIXME -- could print network address if socket had suitable method
}
}
@ -710,7 +746,9 @@ void CServer::openPrimaryScreen()
assert(m_primary == NULL);
// open screen
log((CLOG_DEBUG "creating primary screen"));
m_primary = new CXWindowsPrimaryScreen;
log((CLOG_DEBUG "opening primary screen"));
m_primary->open(this);
// add connection
@ -719,6 +757,7 @@ void CServer::openPrimaryScreen()
// update info
m_primary->getSize(&m_active->m_width, &m_active->m_height);
m_active->m_zoneSize = m_primary->getJumpZoneSize();
log((CLOG_NOTE "server size=%dx%d zone=%d", m_active->m_width, m_active->m_height, m_active->m_zoneSize));
// FIXME -- need way for primary screen to call us back
}
@ -731,6 +770,7 @@ void CServer::closePrimaryScreen() throw()
// close the primary screen
try {
log((CLOG_DEBUG "closing primary screen"));
m_primary->close();
}
catch (...) {
@ -738,6 +778,7 @@ void CServer::closePrimaryScreen() throw()
}
// clean up
log((CLOG_DEBUG "destroying primary screen"));
delete m_primary;
m_primary = NULL;
}
@ -763,6 +804,7 @@ void CServer::removeCleanupThread(const CThread& thread)
void CServer::cleanupThreads() throw()
{
log((CLOG_DEBUG "cleaning up threads"));
m_mutex.lock();
while (m_cleanupList.begin() != m_cleanupList.end()) {
// get the next thread and cancel it
@ -778,11 +820,13 @@ void CServer::cleanupThreads() throw()
// FIXME -- delete remaining threads from list
m_mutex.unlock();
log((CLOG_DEBUG "cleaned up threads"));
}
CServer::CScreenInfo* CServer::addConnection(
const CString& name, IServerProtocol* protocol)
{
log((CLOG_DEBUG "adding connection \"%s\"", name.c_str()));
CLock lock(&m_mutex);
assert(m_screens.count(name) == 0);
CScreenInfo* newScreen = new CScreenInfo(name, protocol);
@ -792,6 +836,7 @@ CServer::CScreenInfo* CServer::addConnection(
void CServer::removeConnection(const CString& name)
{
log((CLOG_DEBUG "removing connection \"%s\"", name.c_str()));
CLock lock(&m_mutex);
CScreenList::iterator index = m_screens.find(name);
assert(index == m_screens.end());

View File

@ -3,6 +3,7 @@
#include "CProtocolUtil.h"
#include "ProtocolTypes.h"
#include "IInputStream.h"
#include "CLog.h"
#include <string.h>
//
@ -40,6 +41,7 @@ void CServerProtocol1_0::run() throw(XIO,XBadClient)
}
// parse message
log((CLOG_DEBUG "msg from \"%s\": %c%c%c%c", getClient().c_str(), code[0], code[1], code[2], code[3]));
if (memcmp(code, kMsgDInfo, 4) == 0) {
recvInfo();
}
@ -53,6 +55,8 @@ void CServerProtocol1_0::run() throw(XIO,XBadClient)
void CServerProtocol1_0::queryInfo() throw(XIO,XBadClient)
{
log((CLOG_INFO "querying client \"%s\" info", getClient().c_str()));
// send request
CProtocolUtil::writef(getOutputStream(), kMsgQInfo);
@ -69,74 +73,87 @@ void CServerProtocol1_0::queryInfo() throw(XIO,XBadClient)
void CServerProtocol1_0::sendClose() throw(XIO)
{
log((CLOG_INFO "send close to \"%s\"", getClient().c_str()));
CProtocolUtil::writef(getOutputStream(), kMsgCClose);
}
void CServerProtocol1_0::sendEnter(
SInt32 xAbs, SInt32 yAbs) throw(XIO)
{
log((CLOG_INFO "send enter to \"%s\", %d,%d", getClient().c_str(), xAbs, yAbs));
CProtocolUtil::writef(getOutputStream(), kMsgCEnter, xAbs, yAbs);
}
void CServerProtocol1_0::sendLeave() throw(XIO)
{
log((CLOG_INFO "send leave to \"%s\"", getClient().c_str()));
CProtocolUtil::writef(getOutputStream(), kMsgCLeave);
}
void CServerProtocol1_0::sendGrabClipboard() throw(XIO)
{
log((CLOG_INFO "send grab clipboard to \"%s\"", getClient().c_str()));
CProtocolUtil::writef(getOutputStream(), kMsgCClipboard);
}
void CServerProtocol1_0::sendQueryClipboard() throw(XIO)
{
log((CLOG_INFO "query clipboard to \"%s\"", getClient().c_str()));
CProtocolUtil::writef(getOutputStream(), kMsgQClipboard);
}
void CServerProtocol1_0::sendScreenSaver(bool on) throw(XIO)
{
log((CLOG_INFO "send screen saver to \"%s\"", getClient().c_str()));
CProtocolUtil::writef(getOutputStream(), kMsgCScreenSaver, on ? 1 : 0);
}
void CServerProtocol1_0::sendKeyDown(
KeyID key, KeyModifierMask mask) throw(XIO)
{
log((CLOG_INFO "send key down to \"%s\" id=%d, mask=0x%04x", getClient().c_str(), key, mask));
CProtocolUtil::writef(getOutputStream(), kMsgDKeyDown, key, mask);
}
void CServerProtocol1_0::sendKeyRepeat(
KeyID key, KeyModifierMask mask) throw(XIO)
{
log((CLOG_INFO "send key repeat to \"%s\" id=%d, mask=0x%04x", getClient().c_str(), key, mask));
CProtocolUtil::writef(getOutputStream(), kMsgDKeyRepeat, key, mask);
}
void CServerProtocol1_0::sendKeyUp(
KeyID key, KeyModifierMask mask) throw(XIO)
{
log((CLOG_INFO "send key up to \"%s\" id=%d, mask=0x%04x", getClient().c_str(), key, mask));
CProtocolUtil::writef(getOutputStream(), kMsgDKeyUp, key, mask);
}
void CServerProtocol1_0::sendMouseDown(
ButtonID button) throw(XIO)
{
log((CLOG_INFO "send mouse down to \"%s\" id=%d", getClient().c_str(), button));
CProtocolUtil::writef(getOutputStream(), kMsgDMouseDown, button);
}
void CServerProtocol1_0::sendMouseUp(
ButtonID button) throw(XIO)
{
log((CLOG_INFO "send mouse up to \"%s\" id=%d", getClient().c_str(), button));
CProtocolUtil::writef(getOutputStream(), kMsgDMouseUp, button);
}
void CServerProtocol1_0::sendMouseMove(
SInt32 xAbs, SInt32 yAbs) throw(XIO)
{
log((CLOG_INFO "send mouse move to \"%s\" %d,%d", getClient().c_str(), xAbs, yAbs));
CProtocolUtil::writef(getOutputStream(), kMsgDMouseMove, xAbs, yAbs);
}
void CServerProtocol1_0::sendMouseWheel(
SInt32 delta) throw(XIO)
{
log((CLOG_INFO "send mouse wheel to \"%s\" %+d", getClient().c_str(), delta));
CProtocolUtil::writef(getOutputStream(), kMsgDMouseWheel, delta);
}
@ -145,6 +162,7 @@ void CServerProtocol1_0::recvInfo() throw(XIO,XBadClient)
// parse the message
SInt32 w, h, zoneInfo;
CProtocolUtil::readf(getInputStream(), kMsgDInfo + 4, &w, &h, &zoneInfo);
log((CLOG_INFO "received client \"%s\" info size=%dx%d, zone=%d", getClient().c_str(), w, h, zoneInfo));
// validate
if (w == 0 || h == 0) {

View File

@ -2,6 +2,7 @@
#include "CServer.h"
#include "CThread.h"
#include "TMethodJob.h"
#include "CLog.h"
#include <assert.h>
#include <X11/X.h>
@ -33,6 +34,7 @@ void CXWindowsPrimaryScreen::open(CServer* server)
m_server = server;
// open the display
log((CLOG_DEBUG "XOpenDisplay(%s)", "NULL"));
m_display = ::XOpenDisplay(NULL); // FIXME -- allow non-default
if (m_display == NULL)
throw int(5); // FIXME -- make exception for this
@ -44,6 +46,7 @@ void CXWindowsPrimaryScreen::open(CServer* server)
// get screen size
m_w = WidthOfScreen(screen);
m_h = HeightOfScreen(screen);
log((CLOG_INFO "primary display size: %dx%d", m_w, m_h));
// get the root window
Window root = RootWindow(m_display, m_screen);
@ -80,10 +83,12 @@ void CXWindowsPrimaryScreen::close()
assert(m_eventThread != NULL);
// stop event thread
log((CLOG_DEBUG "stopping event thread"));
m_eventThread->cancel();
m_eventThread->wait();
delete m_eventThread;
m_eventThread = NULL;
log((CLOG_DEBUG "stopped event thread"));
// destroy window
::XDestroyWindow(m_display, m_window);
@ -92,10 +97,12 @@ void CXWindowsPrimaryScreen::close()
// close the display
::XCloseDisplay(m_display);
m_display = NULL;
log((CLOG_DEBUG "closed display"));
}
void CXWindowsPrimaryScreen::enter(SInt32 x, SInt32 y)
{
log((CLOG_INFO "entering primary at %d,%d", x, y));
assert(m_display != NULL);
assert(m_window != None);
assert(m_active == true);
@ -123,6 +130,7 @@ void CXWindowsPrimaryScreen::enter(SInt32 x, SInt32 y)
void CXWindowsPrimaryScreen::leave()
{
log((CLOG_INFO "leaving primary"));
assert(m_display != NULL);
assert(m_window != None);
assert(m_active == false);
@ -141,9 +149,12 @@ void CXWindowsPrimaryScreen::leave()
GrabModeAsync, GrabModeAsync,
m_window, None, CurrentTime);
assert(result != GrabNotViewable);
if (result != GrabSuccess)
if (result != GrabSuccess) {
log((CLOG_DEBUG "waiting to grab pointer"));
CThread::sleep(0.25);
}
} while (result != GrabSuccess);
log((CLOG_DEBUG "grabbed pointer"));
// now the keyboard
result = ::XGrabKeyboard(m_display, m_window, True,
@ -151,9 +162,11 @@ void CXWindowsPrimaryScreen::leave()
assert(result != GrabNotViewable);
if (result != GrabSuccess) {
::XUngrabPointer(m_display, CurrentTime);
log((CLOG_DEBUG "ungrabbed pointer, waiting to grab keyboard"));
CThread::sleep(0.25);
}
} while (result != GrabSuccess);
log((CLOG_DEBUG "grabbed keyboard"));
// move the mouse to the center of grab window
warpCursor(m_w >> 1, m_h >> 1);
@ -169,6 +182,7 @@ void CXWindowsPrimaryScreen::warpCursor(SInt32 x, SInt32 y)
Window root = RootWindow(m_display, m_screen);
::XWarpPointer(m_display, None, root, 0, 0, 0, 0, x, y);
::XSync(m_display, False);
log((CLOG_DEBUG "warped to %d,%d", x, y));
// discard mouse events since we just added one we don't want
XEvent xevent;
@ -237,6 +251,7 @@ void CXWindowsPrimaryScreen::eventThread(void*)
break;
case KeyPress: {
log((CLOG_DEBUG "event: KeyPress code=%d, state=0x%04x", xevent.xkey.keycode, xevent.xkey.state));
const KeyModifierMask mask = mapModifier(xevent.xkey.state);
const KeyID key = mapKey(xevent.xkey.keycode, mask);
if (key != kKeyNone) {
@ -248,6 +263,7 @@ void CXWindowsPrimaryScreen::eventThread(void*)
// FIXME -- simulate key repeat. X sends press/release for
// repeat. must detect auto repeat and use kKeyRepeat.
case KeyRelease: {
log((CLOG_DEBUG "event: KeyRelease code=%d, state=0x%04x", xevent.xkey.keycode, xevent.xkey.state));
const KeyModifierMask mask = mapModifier(xevent.xkey.state);
const KeyID key = mapKey(xevent.xkey.keycode, mask);
if (key != kKeyNone) {
@ -257,6 +273,7 @@ void CXWindowsPrimaryScreen::eventThread(void*)
}
case ButtonPress: {
log((CLOG_DEBUG "event: ButtonPress button=%d", xevent.xbutton.button));
const ButtonID button = mapButton(xevent.xbutton.button);
if (button != kButtonNone) {
m_server->onMouseDown(button);
@ -265,6 +282,7 @@ void CXWindowsPrimaryScreen::eventThread(void*)
}
case ButtonRelease: {
log((CLOG_DEBUG "event: ButtonRelease button=%d", xevent.xbutton.button));
const ButtonID button = mapButton(xevent.xbutton.button);
if (button != kButtonNone) {
m_server->onMouseUp(button);
@ -273,6 +291,7 @@ void CXWindowsPrimaryScreen::eventThread(void*)
}
case MotionNotify: {
log((CLOG_DEBUG "event: MotionNotify %d,%d", xevent.xmotion.x_root, xevent.xmotion.y_root));
SInt32 x, y;
if (!m_active) {
x = xevent.xmotion.x_root;