mirror of
https://github.com/debauchee/barrier.git
synced 2026-11-03 22:14:26 +08:00
Initial commit of the synergy trunk sources from sf.net
This commit is contained in:
52
lib/server/CBaseClientProxy.cpp
Normal file
52
lib/server/CBaseClientProxy.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2006 Chris Schoeneman
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* found in the file COPYING that should have accompanied this file.
|
||||
*
|
||||
* This package 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.
|
||||
*/
|
||||
|
||||
#include "CBaseClientProxy.h"
|
||||
|
||||
//
|
||||
// CBaseClientProxy
|
||||
//
|
||||
|
||||
CBaseClientProxy::CBaseClientProxy(const CString& name) :
|
||||
m_name(name),
|
||||
m_x(0),
|
||||
m_y(0)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
CBaseClientProxy::~CBaseClientProxy()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CBaseClientProxy::setJumpCursorPos(SInt32 x, SInt32 y)
|
||||
{
|
||||
m_x = x;
|
||||
m_y = y;
|
||||
}
|
||||
|
||||
void
|
||||
CBaseClientProxy::getJumpCursorPos(SInt32& x, SInt32& y) const
|
||||
{
|
||||
x = m_x;
|
||||
y = m_y;
|
||||
}
|
||||
|
||||
CString
|
||||
CBaseClientProxy::getName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
85
lib/server/CBaseClientProxy.h
Normal file
85
lib/server/CBaseClientProxy.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2002 Chris Schoeneman
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* found in the file COPYING that should have accompanied this file.
|
||||
*
|
||||
* This package 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.
|
||||
*/
|
||||
|
||||
#ifndef CBASECLIENTPROXY_H
|
||||
#define CBASECLIENTPROXY_H
|
||||
|
||||
#include "IClient.h"
|
||||
#include "CString.h"
|
||||
|
||||
//! Generic proxy for client or primary
|
||||
class CBaseClientProxy : public IClient {
|
||||
public:
|
||||
/*!
|
||||
\c name is the name of the client.
|
||||
*/
|
||||
CBaseClientProxy(const CString& name);
|
||||
~CBaseClientProxy();
|
||||
|
||||
//! @name manipulators
|
||||
//@{
|
||||
|
||||
//! Save cursor position
|
||||
/*!
|
||||
Save the position of the cursor when jumping from client.
|
||||
*/
|
||||
void setJumpCursorPos(SInt32 x, SInt32 y);
|
||||
|
||||
//@}
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Get cursor position
|
||||
/*!
|
||||
Get the position of the cursor when last jumping from client.
|
||||
*/
|
||||
void getJumpCursorPos(SInt32& x, SInt32& y) const;
|
||||
|
||||
//@}
|
||||
|
||||
// IScreen
|
||||
virtual void* getEventTarget() const = 0;
|
||||
virtual bool getClipboard(ClipboardID id, IClipboard*) const = 0;
|
||||
virtual void getShape(SInt32& x, SInt32& y,
|
||||
SInt32& width, SInt32& height) const = 0;
|
||||
virtual void getCursorPos(SInt32& x, SInt32& y) const = 0;
|
||||
|
||||
// IClient overrides
|
||||
virtual void enter(SInt32 xAbs, SInt32 yAbs,
|
||||
UInt32 seqNum, KeyModifierMask mask,
|
||||
bool forScreensaver) = 0;
|
||||
virtual bool leave() = 0;
|
||||
virtual void setClipboard(ClipboardID, const IClipboard*) = 0;
|
||||
virtual void grabClipboard(ClipboardID) = 0;
|
||||
virtual void setClipboardDirty(ClipboardID, bool) = 0;
|
||||
virtual void keyDown(KeyID, KeyModifierMask, KeyButton) = 0;
|
||||
virtual void keyRepeat(KeyID, KeyModifierMask,
|
||||
SInt32 count, KeyButton) = 0;
|
||||
virtual void keyUp(KeyID, KeyModifierMask, KeyButton) = 0;
|
||||
virtual void mouseDown(ButtonID) = 0;
|
||||
virtual void mouseUp(ButtonID) = 0;
|
||||
virtual void mouseMove(SInt32 xAbs, SInt32 yAbs) = 0;
|
||||
virtual void mouseRelativeMove(SInt32 xRel, SInt32 yRel) = 0;
|
||||
virtual void mouseWheel(SInt32 xDelta, SInt32 yDelta) = 0;
|
||||
virtual void screensaver(bool activate) = 0;
|
||||
virtual void resetOptions() = 0;
|
||||
virtual void setOptions(const COptionsList& options) = 0;
|
||||
virtual CString getName() const;
|
||||
|
||||
private:
|
||||
CString m_name;
|
||||
SInt32 m_x, m_y;
|
||||
};
|
||||
|
||||
#endif
|
||||
194
lib/server/CClientListener.cpp
Normal file
194
lib/server/CClientListener.cpp
Normal file
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2004 Chris Schoeneman
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* found in the file COPYING that should have accompanied this file.
|
||||
*
|
||||
* This package 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.
|
||||
*/
|
||||
|
||||
#include "CClientListener.h"
|
||||
#include "CClientProxy.h"
|
||||
#include "CClientProxyUnknown.h"
|
||||
#include "CPacketStreamFilter.h"
|
||||
#include "IStreamFilterFactory.h"
|
||||
#include "IDataSocket.h"
|
||||
#include "IListenSocket.h"
|
||||
#include "ISocketFactory.h"
|
||||
#include "XSocket.h"
|
||||
#include "CLog.h"
|
||||
#include "IEventQueue.h"
|
||||
#include "TMethodEventJob.h"
|
||||
|
||||
//
|
||||
// CClientListener
|
||||
//
|
||||
|
||||
CEvent::Type CClientListener::s_connectedEvent = CEvent::kUnknown;
|
||||
|
||||
CClientListener::CClientListener(const CNetworkAddress& address,
|
||||
ISocketFactory* socketFactory,
|
||||
IStreamFilterFactory* streamFilterFactory) :
|
||||
m_socketFactory(socketFactory),
|
||||
m_streamFilterFactory(streamFilterFactory)
|
||||
{
|
||||
assert(m_socketFactory != NULL);
|
||||
|
||||
try {
|
||||
// create listen socket
|
||||
m_listen = m_socketFactory->createListen();
|
||||
|
||||
// bind listen address
|
||||
LOG((CLOG_DEBUG1 "binding listen socket"));
|
||||
m_listen->bind(address);
|
||||
}
|
||||
catch (XSocketAddressInUse&) {
|
||||
delete m_listen;
|
||||
delete m_socketFactory;
|
||||
delete m_streamFilterFactory;
|
||||
throw;
|
||||
}
|
||||
catch (XBase&) {
|
||||
delete m_listen;
|
||||
delete m_socketFactory;
|
||||
delete m_streamFilterFactory;
|
||||
throw;
|
||||
}
|
||||
LOG((CLOG_DEBUG1 "listening for clients"));
|
||||
|
||||
// setup event handler
|
||||
EVENTQUEUE->adoptHandler(IListenSocket::getConnectingEvent(), m_listen,
|
||||
new TMethodEventJob<CClientListener>(this,
|
||||
&CClientListener::handleClientConnecting));
|
||||
}
|
||||
|
||||
CClientListener::~CClientListener()
|
||||
{
|
||||
LOG((CLOG_DEBUG1 "stop listening for clients"));
|
||||
|
||||
// discard already connected clients
|
||||
for (CNewClients::iterator index = m_newClients.begin();
|
||||
index != m_newClients.end(); ++index) {
|
||||
CClientProxyUnknown* client = *index;
|
||||
EVENTQUEUE->removeHandler(
|
||||
CClientProxyUnknown::getSuccessEvent(), client);
|
||||
EVENTQUEUE->removeHandler(
|
||||
CClientProxyUnknown::getFailureEvent(), client);
|
||||
EVENTQUEUE->removeHandler(
|
||||
CClientProxy::getDisconnectedEvent(), client);
|
||||
delete client;
|
||||
}
|
||||
|
||||
// discard waiting clients
|
||||
CClientProxy* client = getNextClient();
|
||||
while (client != NULL) {
|
||||
delete client;
|
||||
client = getNextClient();
|
||||
}
|
||||
|
||||
EVENTQUEUE->removeHandler(IListenSocket::getConnectingEvent(), m_listen);
|
||||
delete m_listen;
|
||||
delete m_socketFactory;
|
||||
delete m_streamFilterFactory;
|
||||
}
|
||||
|
||||
CClientProxy*
|
||||
CClientListener::getNextClient()
|
||||
{
|
||||
CClientProxy* client = NULL;
|
||||
if (!m_waitingClients.empty()) {
|
||||
client = m_waitingClients.front();
|
||||
m_waitingClients.pop_front();
|
||||
EVENTQUEUE->removeHandler(CClientProxy::getDisconnectedEvent(), client);
|
||||
}
|
||||
return client;
|
||||
}
|
||||
|
||||
CEvent::Type
|
||||
CClientListener::getConnectedEvent()
|
||||
{
|
||||
return CEvent::registerTypeOnce(s_connectedEvent,
|
||||
"CClientListener::connected");
|
||||
}
|
||||
|
||||
void
|
||||
CClientListener::handleClientConnecting(const CEvent&, void*)
|
||||
{
|
||||
// accept client connection
|
||||
IStream* stream = m_listen->accept();
|
||||
if (stream == NULL) {
|
||||
return;
|
||||
}
|
||||
LOG((CLOG_NOTE "accepted client connection"));
|
||||
|
||||
// filter socket messages, including a packetizing filter
|
||||
if (m_streamFilterFactory != NULL) {
|
||||
stream = m_streamFilterFactory->create(stream, true);
|
||||
}
|
||||
stream = new CPacketStreamFilter(stream, true);
|
||||
|
||||
// create proxy for unknown client
|
||||
CClientProxyUnknown* client = new CClientProxyUnknown(stream, 30.0);
|
||||
m_newClients.insert(client);
|
||||
|
||||
// watch for events from unknown client
|
||||
EVENTQUEUE->adoptHandler(CClientProxyUnknown::getSuccessEvent(), client,
|
||||
new TMethodEventJob<CClientListener>(this,
|
||||
&CClientListener::handleUnknownClient, client));
|
||||
EVENTQUEUE->adoptHandler(CClientProxyUnknown::getFailureEvent(), client,
|
||||
new TMethodEventJob<CClientListener>(this,
|
||||
&CClientListener::handleUnknownClient, client));
|
||||
}
|
||||
|
||||
void
|
||||
CClientListener::handleUnknownClient(const CEvent&, void* vclient)
|
||||
{
|
||||
CClientProxyUnknown* unknownClient =
|
||||
reinterpret_cast<CClientProxyUnknown*>(vclient);
|
||||
|
||||
// we should have the client in our new client list
|
||||
assert(m_newClients.count(unknownClient) == 1);
|
||||
|
||||
// get the real client proxy and install it
|
||||
CClientProxy* client = unknownClient->orphanClientProxy();
|
||||
if (client != NULL) {
|
||||
// handshake was successful
|
||||
m_waitingClients.push_back(client);
|
||||
EVENTQUEUE->addEvent(CEvent(getConnectedEvent(), this));
|
||||
|
||||
// watch for client to disconnect while it's in our queue
|
||||
EVENTQUEUE->adoptHandler(CClientProxy::getDisconnectedEvent(), client,
|
||||
new TMethodEventJob<CClientListener>(this,
|
||||
&CClientListener::handleClientDisconnected,
|
||||
client));
|
||||
}
|
||||
|
||||
// now finished with unknown client
|
||||
EVENTQUEUE->removeHandler(CClientProxyUnknown::getSuccessEvent(), client);
|
||||
EVENTQUEUE->removeHandler(CClientProxyUnknown::getFailureEvent(), client);
|
||||
m_newClients.erase(unknownClient);
|
||||
delete unknownClient;
|
||||
}
|
||||
|
||||
void
|
||||
CClientListener::handleClientDisconnected(const CEvent&, void* vclient)
|
||||
{
|
||||
CClientProxy* client = reinterpret_cast<CClientProxy*>(vclient);
|
||||
|
||||
// find client in waiting clients queue
|
||||
for (CWaitingClients::iterator i = m_waitingClients.begin(),
|
||||
n = m_waitingClients.end(); i != n; ++i) {
|
||||
if (*i == client) {
|
||||
m_waitingClients.erase(i);
|
||||
EVENTQUEUE->removeHandler(CClientProxy::getDisconnectedEvent(),
|
||||
client);
|
||||
delete client;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
76
lib/server/CClientListener.h
Normal file
76
lib/server/CClientListener.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2004 Chris Schoeneman
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* found in the file COPYING that should have accompanied this file.
|
||||
*
|
||||
* This package 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.
|
||||
*/
|
||||
|
||||
#ifndef CCLIENTLISTENER_H
|
||||
#define CCLIENTLISTENER_H
|
||||
|
||||
#include "CConfig.h"
|
||||
#include "CEvent.h"
|
||||
#include "stddeque.h"
|
||||
#include "stdset.h"
|
||||
|
||||
class CClientProxy;
|
||||
class CClientProxyUnknown;
|
||||
class CNetworkAddress;
|
||||
class IListenSocket;
|
||||
class ISocketFactory;
|
||||
class IStreamFilterFactory;
|
||||
|
||||
class CClientListener {
|
||||
public:
|
||||
// The factories are adopted.
|
||||
CClientListener(const CNetworkAddress&,
|
||||
ISocketFactory*, IStreamFilterFactory*);
|
||||
~CClientListener();
|
||||
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Get next connected client
|
||||
/*!
|
||||
Returns the next connected client and removes it from the internal
|
||||
list. The client is responsible for deleting the returned client.
|
||||
Returns NULL if no clients are available.
|
||||
*/
|
||||
CClientProxy* getNextClient();
|
||||
|
||||
//! Get connected event type
|
||||
/*!
|
||||
Returns the connected event type. This is sent whenever a
|
||||
a client connects.
|
||||
*/
|
||||
static CEvent::Type getConnectedEvent();
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
// client connection event handlers
|
||||
void handleClientConnecting(const CEvent&, void*);
|
||||
void handleUnknownClient(const CEvent&, void*);
|
||||
void handleClientDisconnected(const CEvent&, void*);
|
||||
|
||||
private:
|
||||
typedef std::set<CClientProxyUnknown*> CNewClients;
|
||||
typedef std::deque<CClientProxy*> CWaitingClients;
|
||||
|
||||
IListenSocket* m_listen;
|
||||
ISocketFactory* m_socketFactory;
|
||||
IStreamFilterFactory* m_streamFilterFactory;
|
||||
CNewClients m_newClients;
|
||||
CWaitingClients m_waitingClients;
|
||||
|
||||
static CEvent::Type s_connectedEvent;
|
||||
};
|
||||
|
||||
#endif
|
||||
81
lib/server/CClientProxy.cpp
Normal file
81
lib/server/CClientProxy.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2002 Chris Schoeneman
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* found in the file COPYING that should have accompanied this file.
|
||||
*
|
||||
* This package 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.
|
||||
*/
|
||||
|
||||
#include "CClientProxy.h"
|
||||
#include "CProtocolUtil.h"
|
||||
#include "IStream.h"
|
||||
#include "CLog.h"
|
||||
|
||||
//
|
||||
// CClientProxy
|
||||
//
|
||||
|
||||
CEvent::Type CClientProxy::s_readyEvent = CEvent::kUnknown;
|
||||
CEvent::Type CClientProxy::s_disconnectedEvent = CEvent::kUnknown;
|
||||
CEvent::Type CClientProxy::s_clipboardChangedEvent= CEvent::kUnknown;
|
||||
|
||||
CClientProxy::CClientProxy(const CString& name, IStream* stream) :
|
||||
CBaseClientProxy(name),
|
||||
m_stream(stream)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
CClientProxy::~CClientProxy()
|
||||
{
|
||||
delete m_stream;
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy::close(const char* msg)
|
||||
{
|
||||
LOG((CLOG_DEBUG1 "send close \"%s\" to \"%s\"", msg, getName().c_str()));
|
||||
CProtocolUtil::writef(getStream(), msg);
|
||||
|
||||
// force the close to be sent before we return
|
||||
getStream()->flush();
|
||||
}
|
||||
|
||||
IStream*
|
||||
CClientProxy::getStream() const
|
||||
{
|
||||
return m_stream;
|
||||
}
|
||||
|
||||
CEvent::Type
|
||||
CClientProxy::getReadyEvent()
|
||||
{
|
||||
return CEvent::registerTypeOnce(s_readyEvent,
|
||||
"CClientProxy::ready");
|
||||
}
|
||||
|
||||
CEvent::Type
|
||||
CClientProxy::getDisconnectedEvent()
|
||||
{
|
||||
return CEvent::registerTypeOnce(s_disconnectedEvent,
|
||||
"CClientProxy::disconnected");
|
||||
}
|
||||
|
||||
CEvent::Type
|
||||
CClientProxy::getClipboardChangedEvent()
|
||||
{
|
||||
return CEvent::registerTypeOnce(s_clipboardChangedEvent,
|
||||
"CClientProxy::clipboardChanged");
|
||||
}
|
||||
|
||||
void*
|
||||
CClientProxy::getEventTarget() const
|
||||
{
|
||||
return static_cast<IScreen*>(const_cast<CClientProxy*>(this));
|
||||
}
|
||||
113
lib/server/CClientProxy.h
Normal file
113
lib/server/CClientProxy.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2002 Chris Schoeneman
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* found in the file COPYING that should have accompanied this file.
|
||||
*
|
||||
* This package 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.
|
||||
*/
|
||||
|
||||
#ifndef CCLIENTPROXY_H
|
||||
#define CCLIENTPROXY_H
|
||||
|
||||
#include "CBaseClientProxy.h"
|
||||
#include "CEvent.h"
|
||||
#include "CString.h"
|
||||
|
||||
class IStream;
|
||||
|
||||
//! Generic proxy for client
|
||||
class CClientProxy : public CBaseClientProxy {
|
||||
public:
|
||||
/*!
|
||||
\c name is the name of the client.
|
||||
*/
|
||||
CClientProxy(const CString& name, IStream* adoptedStream);
|
||||
~CClientProxy();
|
||||
|
||||
//! @name manipulators
|
||||
//@{
|
||||
|
||||
//! Disconnect
|
||||
/*!
|
||||
Ask the client to disconnect, using \p msg as the reason.
|
||||
*/
|
||||
void close(const char* msg);
|
||||
|
||||
//@}
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Get stream
|
||||
/*!
|
||||
Returns the stream passed to the c'tor.
|
||||
*/
|
||||
IStream* getStream() const;
|
||||
|
||||
//! Get ready event type
|
||||
/*!
|
||||
Returns the ready event type. This is sent when the client has
|
||||
completed the initial handshake. Until it is sent, the client is
|
||||
not fully connected.
|
||||
*/
|
||||
static CEvent::Type getReadyEvent();
|
||||
|
||||
//! Get disconnect event type
|
||||
/*!
|
||||
Returns the disconnect event type. This is sent when the client
|
||||
disconnects or is disconnected. The target is getEventTarget().
|
||||
*/
|
||||
static CEvent::Type getDisconnectedEvent();
|
||||
|
||||
//! Get clipboard changed event type
|
||||
/*!
|
||||
Returns the clipboard changed event type. This is sent whenever the
|
||||
contents of the clipboard has changed. The data is a pointer to a
|
||||
IScreen::CClipboardInfo.
|
||||
*/
|
||||
static CEvent::Type getClipboardChangedEvent();
|
||||
|
||||
//@}
|
||||
|
||||
// IScreen
|
||||
virtual void* getEventTarget() const;
|
||||
virtual bool getClipboard(ClipboardID id, IClipboard*) const = 0;
|
||||
virtual void getShape(SInt32& x, SInt32& y,
|
||||
SInt32& width, SInt32& height) const = 0;
|
||||
virtual void getCursorPos(SInt32& x, SInt32& y) const = 0;
|
||||
|
||||
// IClient overrides
|
||||
virtual void enter(SInt32 xAbs, SInt32 yAbs,
|
||||
UInt32 seqNum, KeyModifierMask mask,
|
||||
bool forScreensaver) = 0;
|
||||
virtual bool leave() = 0;
|
||||
virtual void setClipboard(ClipboardID, const IClipboard*) = 0;
|
||||
virtual void grabClipboard(ClipboardID) = 0;
|
||||
virtual void setClipboardDirty(ClipboardID, bool) = 0;
|
||||
virtual void keyDown(KeyID, KeyModifierMask, KeyButton) = 0;
|
||||
virtual void keyRepeat(KeyID, KeyModifierMask,
|
||||
SInt32 count, KeyButton) = 0;
|
||||
virtual void keyUp(KeyID, KeyModifierMask, KeyButton) = 0;
|
||||
virtual void mouseDown(ButtonID) = 0;
|
||||
virtual void mouseUp(ButtonID) = 0;
|
||||
virtual void mouseMove(SInt32 xAbs, SInt32 yAbs) = 0;
|
||||
virtual void mouseRelativeMove(SInt32 xRel, SInt32 yRel) = 0;
|
||||
virtual void mouseWheel(SInt32 xDelta, SInt32 yDelta) = 0;
|
||||
virtual void screensaver(bool activate) = 0;
|
||||
virtual void resetOptions() = 0;
|
||||
virtual void setOptions(const COptionsList& options) = 0;
|
||||
|
||||
private:
|
||||
IStream* m_stream;
|
||||
|
||||
static CEvent::Type s_readyEvent;
|
||||
static CEvent::Type s_disconnectedEvent;
|
||||
static CEvent::Type s_clipboardChangedEvent;
|
||||
};
|
||||
|
||||
#endif
|
||||
498
lib/server/CClientProxy1_0.cpp
Normal file
498
lib/server/CClientProxy1_0.cpp
Normal file
@@ -0,0 +1,498 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2002 Chris Schoeneman
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* found in the file COPYING that should have accompanied this file.
|
||||
*
|
||||
* This package 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.
|
||||
*/
|
||||
|
||||
#include "CClientProxy1_0.h"
|
||||
#include "CProtocolUtil.h"
|
||||
#include "XSynergy.h"
|
||||
#include "IStream.h"
|
||||
#include "CLog.h"
|
||||
#include "IEventQueue.h"
|
||||
#include "TMethodEventJob.h"
|
||||
#include <cstring>
|
||||
|
||||
//
|
||||
// CClientProxy1_0
|
||||
//
|
||||
|
||||
CClientProxy1_0::CClientProxy1_0(const CString& name, IStream* stream) :
|
||||
CClientProxy(name, stream),
|
||||
m_heartbeatTimer(NULL),
|
||||
m_parser(&CClientProxy1_0::parseHandshakeMessage)
|
||||
{
|
||||
// install event handlers
|
||||
EVENTQUEUE->adoptHandler(IStream::getInputReadyEvent(),
|
||||
stream->getEventTarget(),
|
||||
new TMethodEventJob<CClientProxy1_0>(this,
|
||||
&CClientProxy1_0::handleData, NULL));
|
||||
EVENTQUEUE->adoptHandler(IStream::getOutputErrorEvent(),
|
||||
stream->getEventTarget(),
|
||||
new TMethodEventJob<CClientProxy1_0>(this,
|
||||
&CClientProxy1_0::handleWriteError, NULL));
|
||||
EVENTQUEUE->adoptHandler(IStream::getInputShutdownEvent(),
|
||||
stream->getEventTarget(),
|
||||
new TMethodEventJob<CClientProxy1_0>(this,
|
||||
&CClientProxy1_0::handleDisconnect, NULL));
|
||||
EVENTQUEUE->adoptHandler(IStream::getOutputShutdownEvent(),
|
||||
stream->getEventTarget(),
|
||||
new TMethodEventJob<CClientProxy1_0>(this,
|
||||
&CClientProxy1_0::handleWriteError, NULL));
|
||||
EVENTQUEUE->adoptHandler(CEvent::kTimer, this,
|
||||
new TMethodEventJob<CClientProxy1_0>(this,
|
||||
&CClientProxy1_0::handleFlatline, NULL));
|
||||
|
||||
setHeartbeatRate(kHeartRate, kHeartRate * kHeartBeatsUntilDeath);
|
||||
|
||||
LOG((CLOG_DEBUG1 "querying client \"%s\" info", getName().c_str()));
|
||||
CProtocolUtil::writef(getStream(), kMsgQInfo);
|
||||
}
|
||||
|
||||
CClientProxy1_0::~CClientProxy1_0()
|
||||
{
|
||||
removeHandlers();
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::disconnect()
|
||||
{
|
||||
removeHandlers();
|
||||
getStream()->close();
|
||||
EVENTQUEUE->addEvent(CEvent(getDisconnectedEvent(), getEventTarget()));
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::removeHandlers()
|
||||
{
|
||||
// uninstall event handlers
|
||||
EVENTQUEUE->removeHandler(IStream::getInputReadyEvent(),
|
||||
getStream()->getEventTarget());
|
||||
EVENTQUEUE->removeHandler(IStream::getOutputErrorEvent(),
|
||||
getStream()->getEventTarget());
|
||||
EVENTQUEUE->removeHandler(IStream::getInputShutdownEvent(),
|
||||
getStream()->getEventTarget());
|
||||
EVENTQUEUE->removeHandler(IStream::getOutputShutdownEvent(),
|
||||
getStream()->getEventTarget());
|
||||
EVENTQUEUE->removeHandler(CEvent::kTimer, this);
|
||||
|
||||
// remove timer
|
||||
removeHeartbeatTimer();
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::addHeartbeatTimer()
|
||||
{
|
||||
if (m_heartbeatAlarm > 0.0) {
|
||||
m_heartbeatTimer = EVENTQUEUE->newOneShotTimer(m_heartbeatAlarm, this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::removeHeartbeatTimer()
|
||||
{
|
||||
if (m_heartbeatTimer != NULL) {
|
||||
EVENTQUEUE->deleteTimer(m_heartbeatTimer);
|
||||
m_heartbeatTimer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::resetHeartbeatTimer()
|
||||
{
|
||||
// reset the alarm
|
||||
removeHeartbeatTimer();
|
||||
addHeartbeatTimer();
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::resetHeartbeatRate()
|
||||
{
|
||||
setHeartbeatRate(kHeartRate, kHeartRate * kHeartBeatsUntilDeath);
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::setHeartbeatRate(double, double alarm)
|
||||
{
|
||||
m_heartbeatAlarm = alarm;
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::handleData(const CEvent&, void*)
|
||||
{
|
||||
// handle messages until there are no more. first read message code.
|
||||
UInt8 code[4];
|
||||
UInt32 n = getStream()->read(code, 4);
|
||||
while (n != 0) {
|
||||
// verify we got an entire code
|
||||
if (n != 4) {
|
||||
LOG((CLOG_ERR "incomplete message from \"%s\": %d bytes", getName().c_str(), n));
|
||||
disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
// parse message
|
||||
LOG((CLOG_DEBUG2 "msg from \"%s\": %c%c%c%c", getName().c_str(), code[0], code[1], code[2], code[3]));
|
||||
if (!(this->*m_parser)(code)) {
|
||||
LOG((CLOG_ERR "invalid message from client \"%s\": %c%c%c%c", getName().c_str(), code[0], code[1], code[2], code[3]));
|
||||
disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
// next message
|
||||
n = getStream()->read(code, 4);
|
||||
}
|
||||
|
||||
// restart heartbeat timer
|
||||
resetHeartbeatTimer();
|
||||
}
|
||||
|
||||
bool
|
||||
CClientProxy1_0::parseHandshakeMessage(const UInt8* code)
|
||||
{
|
||||
if (memcmp(code, kMsgCNoop, 4) == 0) {
|
||||
// discard no-ops
|
||||
LOG((CLOG_DEBUG2 "no-op from", getName().c_str()));
|
||||
return true;
|
||||
}
|
||||
else if (memcmp(code, kMsgDInfo, 4) == 0) {
|
||||
// future messages get parsed by parseMessage
|
||||
m_parser = &CClientProxy1_0::parseMessage;
|
||||
if (recvInfo()) {
|
||||
EVENTQUEUE->addEvent(CEvent(getReadyEvent(), getEventTarget()));
|
||||
addHeartbeatTimer();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CClientProxy1_0::parseMessage(const UInt8* code)
|
||||
{
|
||||
if (memcmp(code, kMsgDInfo, 4) == 0) {
|
||||
if (recvInfo()) {
|
||||
EVENTQUEUE->addEvent(
|
||||
CEvent(getShapeChangedEvent(), getEventTarget()));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (memcmp(code, kMsgCNoop, 4) == 0) {
|
||||
// discard no-ops
|
||||
LOG((CLOG_DEBUG2 "no-op from", getName().c_str()));
|
||||
return true;
|
||||
}
|
||||
else if (memcmp(code, kMsgCClipboard, 4) == 0) {
|
||||
return recvGrabClipboard();
|
||||
}
|
||||
else if (memcmp(code, kMsgDClipboard, 4) == 0) {
|
||||
return recvClipboard();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::handleDisconnect(const CEvent&, void*)
|
||||
{
|
||||
LOG((CLOG_NOTE "client \"%s\" has disconnected", getName().c_str()));
|
||||
disconnect();
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::handleWriteError(const CEvent&, void*)
|
||||
{
|
||||
LOG((CLOG_WARN "error writing to client \"%s\"", getName().c_str()));
|
||||
disconnect();
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::handleFlatline(const CEvent&, void*)
|
||||
{
|
||||
// didn't get a heartbeat fast enough. assume client is dead.
|
||||
LOG((CLOG_NOTE "client \"%s\" is dead", getName().c_str()));
|
||||
disconnect();
|
||||
}
|
||||
|
||||
bool
|
||||
CClientProxy1_0::getClipboard(ClipboardID id, IClipboard* clipboard) const
|
||||
{
|
||||
CClipboard::copy(clipboard, &m_clipboard[id].m_clipboard);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h) const
|
||||
{
|
||||
x = m_info.m_x;
|
||||
y = m_info.m_y;
|
||||
w = m_info.m_w;
|
||||
h = m_info.m_h;
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::getCursorPos(SInt32& x, SInt32& y) const
|
||||
{
|
||||
// note -- this returns the cursor pos from when we last got client info
|
||||
x = m_info.m_mx;
|
||||
y = m_info.m_my;
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::enter(SInt32 xAbs, SInt32 yAbs,
|
||||
UInt32 seqNum, KeyModifierMask mask, bool)
|
||||
{
|
||||
LOG((CLOG_DEBUG1 "send enter to \"%s\", %d,%d %d %04x", getName().c_str(), xAbs, yAbs, seqNum, mask));
|
||||
CProtocolUtil::writef(getStream(), kMsgCEnter,
|
||||
xAbs, yAbs, seqNum, mask);
|
||||
}
|
||||
|
||||
bool
|
||||
CClientProxy1_0::leave()
|
||||
{
|
||||
LOG((CLOG_DEBUG1 "send leave to \"%s\"", getName().c_str()));
|
||||
CProtocolUtil::writef(getStream(), kMsgCLeave);
|
||||
|
||||
// we can never prevent the user from leaving
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::setClipboard(ClipboardID id, const IClipboard* clipboard)
|
||||
{
|
||||
// ignore if this clipboard is already clean
|
||||
if (m_clipboard[id].m_dirty) {
|
||||
// this clipboard is now clean
|
||||
m_clipboard[id].m_dirty = false;
|
||||
CClipboard::copy(&m_clipboard[id].m_clipboard, clipboard);
|
||||
|
||||
CString data = m_clipboard[id].m_clipboard.marshall();
|
||||
LOG((CLOG_DEBUG "send clipboard %d to \"%s\" size=%d", id, getName().c_str(), data.size()));
|
||||
CProtocolUtil::writef(getStream(), kMsgDClipboard, id, 0, &data);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::grabClipboard(ClipboardID id)
|
||||
{
|
||||
LOG((CLOG_DEBUG "send grab clipboard %d to \"%s\"", id, getName().c_str()));
|
||||
CProtocolUtil::writef(getStream(), kMsgCClipboard, id, 0);
|
||||
|
||||
// this clipboard is now dirty
|
||||
m_clipboard[id].m_dirty = true;
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::setClipboardDirty(ClipboardID id, bool dirty)
|
||||
{
|
||||
m_clipboard[id].m_dirty = dirty;
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::keyDown(KeyID key, KeyModifierMask mask, KeyButton)
|
||||
{
|
||||
LOG((CLOG_DEBUG1 "send key down to \"%s\" id=%d, mask=0x%04x", getName().c_str(), key, mask));
|
||||
CProtocolUtil::writef(getStream(), kMsgDKeyDown1_0, key, mask);
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::keyRepeat(KeyID key, KeyModifierMask mask,
|
||||
SInt32 count, KeyButton)
|
||||
{
|
||||
LOG((CLOG_DEBUG1 "send key repeat to \"%s\" id=%d, mask=0x%04x, count=%d", getName().c_str(), key, mask, count));
|
||||
CProtocolUtil::writef(getStream(), kMsgDKeyRepeat1_0, key, mask, count);
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::keyUp(KeyID key, KeyModifierMask mask, KeyButton)
|
||||
{
|
||||
LOG((CLOG_DEBUG1 "send key up to \"%s\" id=%d, mask=0x%04x", getName().c_str(), key, mask));
|
||||
CProtocolUtil::writef(getStream(), kMsgDKeyUp1_0, key, mask);
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::mouseDown(ButtonID button)
|
||||
{
|
||||
LOG((CLOG_DEBUG1 "send mouse down to \"%s\" id=%d", getName().c_str(), button));
|
||||
CProtocolUtil::writef(getStream(), kMsgDMouseDown, button);
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::mouseUp(ButtonID button)
|
||||
{
|
||||
LOG((CLOG_DEBUG1 "send mouse up to \"%s\" id=%d", getName().c_str(), button));
|
||||
CProtocolUtil::writef(getStream(), kMsgDMouseUp, button);
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::mouseMove(SInt32 xAbs, SInt32 yAbs)
|
||||
{
|
||||
LOG((CLOG_DEBUG2 "send mouse move to \"%s\" %d,%d", getName().c_str(), xAbs, yAbs));
|
||||
CProtocolUtil::writef(getStream(), kMsgDMouseMove, xAbs, yAbs);
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::mouseRelativeMove(SInt32, SInt32)
|
||||
{
|
||||
// ignore -- not supported in protocol 1.0
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::mouseWheel(SInt32, SInt32 yDelta)
|
||||
{
|
||||
// clients prior to 1.3 only support the y axis
|
||||
LOG((CLOG_DEBUG2 "send mouse wheel to \"%s\" %+d", getName().c_str(), yDelta));
|
||||
CProtocolUtil::writef(getStream(), kMsgDMouseWheel1_0, yDelta);
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::screensaver(bool on)
|
||||
{
|
||||
LOG((CLOG_DEBUG1 "send screen saver to \"%s\" on=%d", getName().c_str(), on ? 1 : 0));
|
||||
CProtocolUtil::writef(getStream(), kMsgCScreenSaver, on ? 1 : 0);
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::resetOptions()
|
||||
{
|
||||
LOG((CLOG_DEBUG1 "send reset options to \"%s\"", getName().c_str()));
|
||||
CProtocolUtil::writef(getStream(), kMsgCResetOptions);
|
||||
|
||||
// reset heart rate and death
|
||||
resetHeartbeatRate();
|
||||
removeHeartbeatTimer();
|
||||
addHeartbeatTimer();
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::setOptions(const COptionsList& options)
|
||||
{
|
||||
LOG((CLOG_DEBUG1 "send set options to \"%s\" size=%d", getName().c_str(), options.size()));
|
||||
CProtocolUtil::writef(getStream(), kMsgDSetOptions, &options);
|
||||
|
||||
// check options
|
||||
for (UInt32 i = 0, n = options.size(); i < n; i += 2) {
|
||||
if (options[i] == kOptionHeartbeat) {
|
||||
double rate = 1.0e-3 * static_cast<double>(options[i + 1]);
|
||||
if (rate <= 0.0) {
|
||||
rate = -1.0;
|
||||
}
|
||||
setHeartbeatRate(rate, rate * kHeartBeatsUntilDeath);
|
||||
removeHeartbeatTimer();
|
||||
addHeartbeatTimer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CClientProxy1_0::recvInfo()
|
||||
{
|
||||
// parse the message
|
||||
SInt16 x, y, w, h, dummy1, mx, my;
|
||||
if (!CProtocolUtil::readf(getStream(), kMsgDInfo + 4,
|
||||
&x, &y, &w, &h, &dummy1, &mx, &my)) {
|
||||
return false;
|
||||
}
|
||||
LOG((CLOG_DEBUG "received client \"%s\" info shape=%d,%d %dx%d at %d,%d", getName().c_str(), x, y, w, h, mx, my));
|
||||
|
||||
// validate
|
||||
if (w <= 0 || h <= 0) {
|
||||
return false;
|
||||
}
|
||||
if (mx < x || mx >= x + w || my < y || my >= y + h) {
|
||||
mx = x + w / 2;
|
||||
my = y + h / 2;
|
||||
}
|
||||
|
||||
// save
|
||||
m_info.m_x = x;
|
||||
m_info.m_y = y;
|
||||
m_info.m_w = w;
|
||||
m_info.m_h = h;
|
||||
m_info.m_mx = mx;
|
||||
m_info.m_my = my;
|
||||
|
||||
// acknowledge receipt
|
||||
LOG((CLOG_DEBUG1 "send info ack to \"%s\"", getName().c_str()));
|
||||
CProtocolUtil::writef(getStream(), kMsgCInfoAck);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CClientProxy1_0::recvClipboard()
|
||||
{
|
||||
// parse message
|
||||
ClipboardID id;
|
||||
UInt32 seqNum;
|
||||
CString data;
|
||||
if (!CProtocolUtil::readf(getStream(),
|
||||
kMsgDClipboard + 4, &id, &seqNum, &data)) {
|
||||
return false;
|
||||
}
|
||||
LOG((CLOG_DEBUG "received client \"%s\" clipboard %d seqnum=%d, size=%d", getName().c_str(), id, seqNum, data.size()));
|
||||
|
||||
// validate
|
||||
if (id >= kClipboardEnd) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// save clipboard
|
||||
m_clipboard[id].m_clipboard.unmarshall(data, 0);
|
||||
m_clipboard[id].m_sequenceNumber = seqNum;
|
||||
|
||||
// notify
|
||||
CClipboardInfo* info = new CClipboardInfo;
|
||||
info->m_id = id;
|
||||
info->m_sequenceNumber = seqNum;
|
||||
EVENTQUEUE->addEvent(CEvent(getClipboardChangedEvent(),
|
||||
getEventTarget(), info));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CClientProxy1_0::recvGrabClipboard()
|
||||
{
|
||||
// parse message
|
||||
ClipboardID id;
|
||||
UInt32 seqNum;
|
||||
if (!CProtocolUtil::readf(getStream(), kMsgCClipboard + 4, &id, &seqNum)) {
|
||||
return false;
|
||||
}
|
||||
LOG((CLOG_DEBUG "received client \"%s\" grabbed clipboard %d seqnum=%d", getName().c_str(), id, seqNum));
|
||||
|
||||
// validate
|
||||
if (id >= kClipboardEnd) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// notify
|
||||
CClipboardInfo* info = new CClipboardInfo;
|
||||
info->m_id = id;
|
||||
info->m_sequenceNumber = seqNum;
|
||||
EVENTQUEUE->addEvent(CEvent(getClipboardGrabbedEvent(),
|
||||
getEventTarget(), info));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// CClientProxy1_0::CClientClipboard
|
||||
//
|
||||
|
||||
CClientProxy1_0::CClientClipboard::CClientClipboard() :
|
||||
m_clipboard(),
|
||||
m_sequenceNumber(0),
|
||||
m_dirty(true)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
100
lib/server/CClientProxy1_0.h
Normal file
100
lib/server/CClientProxy1_0.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2002 Chris Schoeneman
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* found in the file COPYING that should have accompanied this file.
|
||||
*
|
||||
* This package 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.
|
||||
*/
|
||||
|
||||
#ifndef CCLIENTPROXY1_0_H
|
||||
#define CCLIENTPROXY1_0_H
|
||||
|
||||
#include "CClientProxy.h"
|
||||
#include "CClipboard.h"
|
||||
#include "ProtocolTypes.h"
|
||||
|
||||
class CEvent;
|
||||
class CEventQueueTimer;
|
||||
|
||||
//! Proxy for client implementing protocol version 1.0
|
||||
class CClientProxy1_0 : public CClientProxy {
|
||||
public:
|
||||
CClientProxy1_0(const CString& name, IStream* adoptedStream);
|
||||
~CClientProxy1_0();
|
||||
|
||||
// IScreen
|
||||
virtual bool getClipboard(ClipboardID id, IClipboard*) const;
|
||||
virtual void getShape(SInt32& x, SInt32& y,
|
||||
SInt32& width, SInt32& height) const;
|
||||
virtual void getCursorPos(SInt32& x, SInt32& y) const;
|
||||
|
||||
// IClient overrides
|
||||
virtual void enter(SInt32 xAbs, SInt32 yAbs,
|
||||
UInt32 seqNum, KeyModifierMask mask,
|
||||
bool forScreensaver);
|
||||
virtual bool leave();
|
||||
virtual void setClipboard(ClipboardID, const IClipboard*);
|
||||
virtual void grabClipboard(ClipboardID);
|
||||
virtual void setClipboardDirty(ClipboardID, bool);
|
||||
virtual void keyDown(KeyID, KeyModifierMask, KeyButton);
|
||||
virtual void keyRepeat(KeyID, KeyModifierMask,
|
||||
SInt32 count, KeyButton);
|
||||
virtual void keyUp(KeyID, KeyModifierMask, KeyButton);
|
||||
virtual void mouseDown(ButtonID);
|
||||
virtual void mouseUp(ButtonID);
|
||||
virtual void mouseMove(SInt32 xAbs, SInt32 yAbs);
|
||||
virtual void mouseRelativeMove(SInt32 xRel, SInt32 yRel);
|
||||
virtual void mouseWheel(SInt32 xDelta, SInt32 yDelta);
|
||||
virtual void screensaver(bool activate);
|
||||
virtual void resetOptions();
|
||||
virtual void setOptions(const COptionsList& options);
|
||||
|
||||
protected:
|
||||
virtual bool parseHandshakeMessage(const UInt8* code);
|
||||
virtual bool parseMessage(const UInt8* code);
|
||||
|
||||
virtual void resetHeartbeatRate();
|
||||
virtual void setHeartbeatRate(double rate, double alarm);
|
||||
virtual void resetHeartbeatTimer();
|
||||
virtual void addHeartbeatTimer();
|
||||
virtual void removeHeartbeatTimer();
|
||||
|
||||
private:
|
||||
void disconnect();
|
||||
void removeHandlers();
|
||||
|
||||
void handleData(const CEvent&, void*);
|
||||
void handleDisconnect(const CEvent&, void*);
|
||||
void handleWriteError(const CEvent&, void*);
|
||||
void handleFlatline(const CEvent&, void*);
|
||||
|
||||
bool recvInfo();
|
||||
bool recvClipboard();
|
||||
bool recvGrabClipboard();
|
||||
|
||||
private:
|
||||
typedef bool (CClientProxy1_0::*MessageParser)(const UInt8*);
|
||||
struct CClientClipboard {
|
||||
public:
|
||||
CClientClipboard();
|
||||
|
||||
public:
|
||||
CClipboard m_clipboard;
|
||||
UInt32 m_sequenceNumber;
|
||||
bool m_dirty;
|
||||
};
|
||||
|
||||
CClientInfo m_info;
|
||||
CClientClipboard m_clipboard[kClipboardEnd];
|
||||
double m_heartbeatAlarm;
|
||||
CEventQueueTimer* m_heartbeatTimer;
|
||||
MessageParser m_parser;
|
||||
};
|
||||
|
||||
#endif
|
||||
55
lib/server/CClientProxy1_1.cpp
Normal file
55
lib/server/CClientProxy1_1.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2002 Chris Schoeneman
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* found in the file COPYING that should have accompanied this file.
|
||||
*
|
||||
* This package 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.
|
||||
*/
|
||||
|
||||
#include "CClientProxy1_1.h"
|
||||
#include "CProtocolUtil.h"
|
||||
#include "CLog.h"
|
||||
#include <cstring>
|
||||
|
||||
//
|
||||
// CClientProxy1_1
|
||||
//
|
||||
|
||||
CClientProxy1_1::CClientProxy1_1(const CString& name, IStream* stream) :
|
||||
CClientProxy1_0(name, stream)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
CClientProxy1_1::~CClientProxy1_1()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_1::keyDown(KeyID key, KeyModifierMask mask, KeyButton button)
|
||||
{
|
||||
LOG((CLOG_DEBUG1 "send key down to \"%s\" id=%d, mask=0x%04x, button=0x%04x", getName().c_str(), key, mask, button));
|
||||
CProtocolUtil::writef(getStream(), kMsgDKeyDown, key, mask, button);
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_1::keyRepeat(KeyID key, KeyModifierMask mask,
|
||||
SInt32 count, KeyButton button)
|
||||
{
|
||||
LOG((CLOG_DEBUG1 "send key repeat to \"%s\" id=%d, mask=0x%04x, count=%d, button=0x%04x", getName().c_str(), key, mask, count, button));
|
||||
CProtocolUtil::writef(getStream(), kMsgDKeyRepeat, key, mask, count, button);
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_1::keyUp(KeyID key, KeyModifierMask mask, KeyButton button)
|
||||
{
|
||||
LOG((CLOG_DEBUG1 "send key up to \"%s\" id=%d, mask=0x%04x, button=0x%04x", getName().c_str(), key, mask, button));
|
||||
CProtocolUtil::writef(getStream(), kMsgDKeyUp, key, mask, button);
|
||||
}
|
||||
33
lib/server/CClientProxy1_1.h
Normal file
33
lib/server/CClientProxy1_1.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2002 Chris Schoeneman
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* found in the file COPYING that should have accompanied this file.
|
||||
*
|
||||
* This package 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.
|
||||
*/
|
||||
|
||||
#ifndef CCLIENTPROXY1_1_H
|
||||
#define CCLIENTPROXY1_1_H
|
||||
|
||||
#include "CClientProxy1_0.h"
|
||||
|
||||
//! Proxy for client implementing protocol version 1.1
|
||||
class CClientProxy1_1 : public CClientProxy1_0 {
|
||||
public:
|
||||
CClientProxy1_1(const CString& name, IStream* adoptedStream);
|
||||
~CClientProxy1_1();
|
||||
|
||||
// IClient overrides
|
||||
virtual void keyDown(KeyID, KeyModifierMask, KeyButton);
|
||||
virtual void keyRepeat(KeyID, KeyModifierMask,
|
||||
SInt32 count, KeyButton);
|
||||
virtual void keyUp(KeyID, KeyModifierMask, KeyButton);
|
||||
};
|
||||
|
||||
#endif
|
||||
39
lib/server/CClientProxy1_2.cpp
Normal file
39
lib/server/CClientProxy1_2.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2002 Chris Schoeneman
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* found in the file COPYING that should have accompanied this file.
|
||||
*
|
||||
* This package 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.
|
||||
*/
|
||||
|
||||
#include "CClientProxy1_2.h"
|
||||
#include "CProtocolUtil.h"
|
||||
#include "CLog.h"
|
||||
|
||||
//
|
||||
// CClientProxy1_1
|
||||
//
|
||||
|
||||
CClientProxy1_2::CClientProxy1_2(const CString& name, IStream* stream) :
|
||||
CClientProxy1_1(name, stream)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
CClientProxy1_2::~CClientProxy1_2()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_2::mouseRelativeMove(SInt32 xRel, SInt32 yRel)
|
||||
{
|
||||
LOG((CLOG_DEBUG2 "send mouse relative move to \"%s\" %d,%d", getName().c_str(), xRel, yRel));
|
||||
CProtocolUtil::writef(getStream(), kMsgDMouseRelMove, xRel, yRel);
|
||||
}
|
||||
30
lib/server/CClientProxy1_2.h
Normal file
30
lib/server/CClientProxy1_2.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2004 Chris Schoeneman
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* found in the file COPYING that should have accompanied this file.
|
||||
*
|
||||
* This package 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.
|
||||
*/
|
||||
|
||||
#ifndef CCLIENTPROXY1_2_H
|
||||
#define CCLIENTPROXY1_2_H
|
||||
|
||||
#include "CClientProxy1_1.h"
|
||||
|
||||
//! Proxy for client implementing protocol version 1.2
|
||||
class CClientProxy1_2 : public CClientProxy1_1 {
|
||||
public:
|
||||
CClientProxy1_2(const CString& name, IStream* adoptedStream);
|
||||
~CClientProxy1_2();
|
||||
|
||||
// IClient overrides
|
||||
virtual void mouseRelativeMove(SInt32 xRel, SInt32 yRel);
|
||||
};
|
||||
|
||||
#endif
|
||||
114
lib/server/CClientProxy1_3.cpp
Normal file
114
lib/server/CClientProxy1_3.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2006 Chris Schoeneman
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* found in the file COPYING that should have accompanied this file.
|
||||
*
|
||||
* This package 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.
|
||||
*/
|
||||
|
||||
#include "CClientProxy1_3.h"
|
||||
#include "CProtocolUtil.h"
|
||||
#include "CLog.h"
|
||||
#include "IEventQueue.h"
|
||||
#include "TMethodEventJob.h"
|
||||
|
||||
//
|
||||
// CClientProxy1_3
|
||||
//
|
||||
|
||||
CClientProxy1_3::CClientProxy1_3(const CString& name, IStream* stream) :
|
||||
CClientProxy1_2(name, stream),
|
||||
m_keepAliveRate(kKeepAliveRate),
|
||||
m_keepAliveTimer(NULL)
|
||||
{
|
||||
setHeartbeatRate(kKeepAliveRate, kKeepAliveRate * kKeepAlivesUntilDeath);
|
||||
}
|
||||
|
||||
CClientProxy1_3::~CClientProxy1_3()
|
||||
{
|
||||
// cannot do this in superclass or our override wouldn't get called
|
||||
removeHeartbeatTimer();
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_3::mouseWheel(SInt32 xDelta, SInt32 yDelta)
|
||||
{
|
||||
LOG((CLOG_DEBUG2 "send mouse wheel to \"%s\" %+d,%+d", getName().c_str(), xDelta, yDelta));
|
||||
CProtocolUtil::writef(getStream(), kMsgDMouseWheel, xDelta, yDelta);
|
||||
}
|
||||
|
||||
bool
|
||||
CClientProxy1_3::parseMessage(const UInt8* code)
|
||||
{
|
||||
// process message
|
||||
if (memcmp(code, kMsgCKeepAlive, 4) == 0) {
|
||||
// reset alarm
|
||||
resetHeartbeatTimer();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return CClientProxy1_2::parseMessage(code);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_3::resetHeartbeatRate()
|
||||
{
|
||||
setHeartbeatRate(kKeepAliveRate, kKeepAliveRate * kKeepAlivesUntilDeath);
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_3::setHeartbeatRate(double rate, double)
|
||||
{
|
||||
m_keepAliveRate = rate;
|
||||
CClientProxy1_2::setHeartbeatRate(rate, rate * kKeepAlivesUntilDeath);
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_3::resetHeartbeatTimer()
|
||||
{
|
||||
// reset the alarm but not the keep alive timer
|
||||
CClientProxy1_2::removeHeartbeatTimer();
|
||||
CClientProxy1_2::addHeartbeatTimer();
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_3::addHeartbeatTimer()
|
||||
{
|
||||
// create and install a timer to periodically send keep alives
|
||||
if (m_keepAliveRate > 0.0) {
|
||||
m_keepAliveTimer = EVENTQUEUE->newTimer(m_keepAliveRate, NULL);
|
||||
EVENTQUEUE->adoptHandler(CEvent::kTimer, m_keepAliveTimer,
|
||||
new TMethodEventJob<CClientProxy1_3>(this,
|
||||
&CClientProxy1_3::handleKeepAlive, NULL));
|
||||
}
|
||||
|
||||
// superclass does the alarm
|
||||
CClientProxy1_2::addHeartbeatTimer();
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_3::removeHeartbeatTimer()
|
||||
{
|
||||
// remove the timer that sends keep alives periodically
|
||||
if (m_keepAliveTimer != NULL) {
|
||||
EVENTQUEUE->removeHandler(CEvent::kTimer, m_keepAliveTimer);
|
||||
EVENTQUEUE->deleteTimer(m_keepAliveTimer);
|
||||
m_keepAliveTimer = NULL;
|
||||
}
|
||||
|
||||
// superclass does the alarm
|
||||
CClientProxy1_2::removeHeartbeatTimer();
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_3::handleKeepAlive(const CEvent&, void*)
|
||||
{
|
||||
CProtocolUtil::writef(getStream(), kMsgCKeepAlive);
|
||||
}
|
||||
47
lib/server/CClientProxy1_3.h
Normal file
47
lib/server/CClientProxy1_3.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2006 Chris Schoeneman
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* found in the file COPYING that should have accompanied this file.
|
||||
*
|
||||
* This package 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.
|
||||
*/
|
||||
|
||||
#ifndef CCLIENTPROXY1_3_H
|
||||
#define CCLIENTPROXY1_3_H
|
||||
|
||||
#include "CClientProxy1_2.h"
|
||||
|
||||
//! Proxy for client implementing protocol version 1.3
|
||||
class CClientProxy1_3 : public CClientProxy1_2 {
|
||||
public:
|
||||
CClientProxy1_3(const CString& name, IStream* adoptedStream);
|
||||
~CClientProxy1_3();
|
||||
|
||||
// IClient overrides
|
||||
virtual void mouseWheel(SInt32 xDelta, SInt32 yDelta);
|
||||
|
||||
protected:
|
||||
// CClientProxy overrides
|
||||
virtual bool parseMessage(const UInt8* code);
|
||||
virtual void resetHeartbeatRate();
|
||||
virtual void setHeartbeatRate(double rate, double alarm);
|
||||
virtual void resetHeartbeatTimer();
|
||||
virtual void addHeartbeatTimer();
|
||||
virtual void removeHeartbeatTimer();
|
||||
|
||||
private:
|
||||
void handleKeepAlive(const CEvent&, void*);
|
||||
|
||||
|
||||
private:
|
||||
double m_keepAliveRate;
|
||||
CEventQueueTimer* m_keepAliveTimer;
|
||||
};
|
||||
|
||||
#endif
|
||||
287
lib/server/CClientProxyUnknown.cpp
Normal file
287
lib/server/CClientProxyUnknown.cpp
Normal file
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2004 Chris Schoeneman
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* found in the file COPYING that should have accompanied this file.
|
||||
*
|
||||
* This package 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.
|
||||
*/
|
||||
|
||||
#include "CClientProxyUnknown.h"
|
||||
#include "CClientProxy1_0.h"
|
||||
#include "CClientProxy1_1.h"
|
||||
#include "CClientProxy1_2.h"
|
||||
#include "CClientProxy1_3.h"
|
||||
#include "ProtocolTypes.h"
|
||||
#include "CProtocolUtil.h"
|
||||
#include "XSynergy.h"
|
||||
#include "IStream.h"
|
||||
#include "XIO.h"
|
||||
#include "CLog.h"
|
||||
#include "CString.h"
|
||||
#include "IEventQueue.h"
|
||||
#include "TMethodEventJob.h"
|
||||
|
||||
//
|
||||
// CClientProxyUnknown
|
||||
//
|
||||
|
||||
CEvent::Type CClientProxyUnknown::s_successEvent = CEvent::kUnknown;
|
||||
CEvent::Type CClientProxyUnknown::s_failureEvent = CEvent::kUnknown;
|
||||
|
||||
CClientProxyUnknown::CClientProxyUnknown(IStream* stream, double timeout) :
|
||||
m_stream(stream),
|
||||
m_proxy(NULL),
|
||||
m_ready(false)
|
||||
{
|
||||
EVENTQUEUE->adoptHandler(CEvent::kTimer, this,
|
||||
new TMethodEventJob<CClientProxyUnknown>(this,
|
||||
&CClientProxyUnknown::handleTimeout, NULL));
|
||||
m_timer = EVENTQUEUE->newOneShotTimer(timeout, this);
|
||||
addStreamHandlers();
|
||||
|
||||
LOG((CLOG_DEBUG1 "saying hello"));
|
||||
CProtocolUtil::writef(m_stream, kMsgHello,
|
||||
kProtocolMajorVersion,
|
||||
kProtocolMinorVersion);
|
||||
}
|
||||
|
||||
CClientProxyUnknown::~CClientProxyUnknown()
|
||||
{
|
||||
removeHandlers();
|
||||
removeTimer();
|
||||
delete m_stream;
|
||||
delete m_proxy;
|
||||
}
|
||||
|
||||
CClientProxy*
|
||||
CClientProxyUnknown::orphanClientProxy()
|
||||
{
|
||||
if (m_ready) {
|
||||
removeHandlers();
|
||||
CClientProxy* proxy = m_proxy;
|
||||
m_proxy = NULL;
|
||||
return proxy;
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
CEvent::Type
|
||||
CClientProxyUnknown::getSuccessEvent()
|
||||
{
|
||||
return CEvent::registerTypeOnce(s_successEvent,
|
||||
"CClientProxy::success");
|
||||
}
|
||||
|
||||
CEvent::Type
|
||||
CClientProxyUnknown::getFailureEvent()
|
||||
{
|
||||
return CEvent::registerTypeOnce(s_failureEvent,
|
||||
"CClientProxy::failure");
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxyUnknown::sendSuccess()
|
||||
{
|
||||
m_ready = true;
|
||||
removeTimer();
|
||||
EVENTQUEUE->addEvent(CEvent(getSuccessEvent(), this));
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxyUnknown::sendFailure()
|
||||
{
|
||||
delete m_proxy;
|
||||
m_proxy = NULL;
|
||||
m_ready = false;
|
||||
removeHandlers();
|
||||
removeTimer();
|
||||
EVENTQUEUE->addEvent(CEvent(getFailureEvent(), this));
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxyUnknown::addStreamHandlers()
|
||||
{
|
||||
assert(m_stream != NULL);
|
||||
|
||||
EVENTQUEUE->adoptHandler(IStream::getInputReadyEvent(),
|
||||
m_stream->getEventTarget(),
|
||||
new TMethodEventJob<CClientProxyUnknown>(this,
|
||||
&CClientProxyUnknown::handleData));
|
||||
EVENTQUEUE->adoptHandler(IStream::getOutputErrorEvent(),
|
||||
m_stream->getEventTarget(),
|
||||
new TMethodEventJob<CClientProxyUnknown>(this,
|
||||
&CClientProxyUnknown::handleWriteError));
|
||||
EVENTQUEUE->adoptHandler(IStream::getInputShutdownEvent(),
|
||||
m_stream->getEventTarget(),
|
||||
new TMethodEventJob<CClientProxyUnknown>(this,
|
||||
&CClientProxyUnknown::handleDisconnect));
|
||||
EVENTQUEUE->adoptHandler(IStream::getOutputShutdownEvent(),
|
||||
m_stream->getEventTarget(),
|
||||
new TMethodEventJob<CClientProxyUnknown>(this,
|
||||
&CClientProxyUnknown::handleWriteError));
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxyUnknown::addProxyHandlers()
|
||||
{
|
||||
assert(m_proxy != NULL);
|
||||
|
||||
EVENTQUEUE->adoptHandler(CClientProxy::getReadyEvent(),
|
||||
m_proxy,
|
||||
new TMethodEventJob<CClientProxyUnknown>(this,
|
||||
&CClientProxyUnknown::handleReady));
|
||||
EVENTQUEUE->adoptHandler(CClientProxy::getDisconnectedEvent(),
|
||||
m_proxy,
|
||||
new TMethodEventJob<CClientProxyUnknown>(this,
|
||||
&CClientProxyUnknown::handleDisconnect));
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxyUnknown::removeHandlers()
|
||||
{
|
||||
if (m_stream != NULL) {
|
||||
EVENTQUEUE->removeHandler(IStream::getInputReadyEvent(),
|
||||
m_stream->getEventTarget());
|
||||
EVENTQUEUE->removeHandler(IStream::getOutputErrorEvent(),
|
||||
m_stream->getEventTarget());
|
||||
EVENTQUEUE->removeHandler(IStream::getInputShutdownEvent(),
|
||||
m_stream->getEventTarget());
|
||||
EVENTQUEUE->removeHandler(IStream::getOutputShutdownEvent(),
|
||||
m_stream->getEventTarget());
|
||||
}
|
||||
if (m_proxy != NULL) {
|
||||
EVENTQUEUE->removeHandler(CClientProxy::getReadyEvent(),
|
||||
m_proxy);
|
||||
EVENTQUEUE->removeHandler(CClientProxy::getDisconnectedEvent(),
|
||||
m_proxy);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxyUnknown::removeTimer()
|
||||
{
|
||||
if (m_timer != NULL) {
|
||||
EVENTQUEUE->deleteTimer(m_timer);
|
||||
EVENTQUEUE->removeHandler(CEvent::kTimer, this);
|
||||
m_timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxyUnknown::handleData(const CEvent&, void*)
|
||||
{
|
||||
LOG((CLOG_DEBUG1 "parsing hello reply"));
|
||||
|
||||
CString name("<unknown>");
|
||||
try {
|
||||
// limit the maximum length of the hello
|
||||
UInt32 n = m_stream->getSize();
|
||||
if (n > kMaxHelloLength) {
|
||||
LOG((CLOG_DEBUG1 "hello reply too long"));
|
||||
throw XBadClient();
|
||||
}
|
||||
|
||||
// parse the reply to hello
|
||||
SInt16 major, minor;
|
||||
if (!CProtocolUtil::readf(m_stream, kMsgHelloBack,
|
||||
&major, &minor, &name)) {
|
||||
throw XBadClient();
|
||||
}
|
||||
|
||||
// disallow invalid version numbers
|
||||
if (major <= 0 || minor < 0) {
|
||||
throw XIncompatibleClient(major, minor);
|
||||
}
|
||||
|
||||
// remove stream event handlers. the proxy we're about to create
|
||||
// may install its own handlers and we don't want to accidentally
|
||||
// remove those later.
|
||||
removeHandlers();
|
||||
|
||||
// create client proxy for highest version supported by the client
|
||||
if (major == 1) {
|
||||
switch (minor) {
|
||||
case 0:
|
||||
m_proxy = new CClientProxy1_0(name, m_stream);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
m_proxy = new CClientProxy1_1(name, m_stream);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m_proxy = new CClientProxy1_2(name, m_stream);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
m_proxy = new CClientProxy1_3(name, m_stream);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// hangup (with error) if version isn't supported
|
||||
if (m_proxy == NULL) {
|
||||
throw XIncompatibleClient(major, minor);
|
||||
}
|
||||
|
||||
// the proxy is created and now proxy now owns the stream
|
||||
LOG((CLOG_DEBUG1 "created proxy for client \"%s\" version %d.%d", name.c_str(), major, minor));
|
||||
m_stream = NULL;
|
||||
|
||||
// wait until the proxy signals that it's ready or has disconnected
|
||||
addProxyHandlers();
|
||||
return;
|
||||
}
|
||||
catch (XIncompatibleClient& e) {
|
||||
// client is incompatible
|
||||
LOG((CLOG_WARN "client \"%s\" has incompatible version %d.%d)", name.c_str(), e.getMajor(), e.getMinor()));
|
||||
CProtocolUtil::writef(m_stream,
|
||||
kMsgEIncompatible,
|
||||
kProtocolMajorVersion, kProtocolMinorVersion);
|
||||
}
|
||||
catch (XBadClient&) {
|
||||
// client not behaving
|
||||
LOG((CLOG_WARN "protocol error from client \"%s\"", name.c_str()));
|
||||
CProtocolUtil::writef(m_stream, kMsgEBad);
|
||||
}
|
||||
catch (XBase& e) {
|
||||
// misc error
|
||||
LOG((CLOG_WARN "error communicating with client \"%s\": %s", name.c_str(), e.what()));
|
||||
}
|
||||
sendFailure();
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxyUnknown::handleWriteError(const CEvent&, void*)
|
||||
{
|
||||
LOG((CLOG_NOTE "error communicating with new client"));
|
||||
sendFailure();
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxyUnknown::handleTimeout(const CEvent&, void*)
|
||||
{
|
||||
LOG((CLOG_NOTE "new client is unresponsive"));
|
||||
sendFailure();
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxyUnknown::handleDisconnect(const CEvent&, void*)
|
||||
{
|
||||
LOG((CLOG_NOTE "new client disconnected"));
|
||||
sendFailure();
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxyUnknown::handleReady(const CEvent&, void*)
|
||||
{
|
||||
sendSuccess();
|
||||
}
|
||||
83
lib/server/CClientProxyUnknown.h
Normal file
83
lib/server/CClientProxyUnknown.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2004 Chris Schoeneman
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* found in the file COPYING that should have accompanied this file.
|
||||
*
|
||||
* This package 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.
|
||||
*/
|
||||
|
||||
#ifndef CCLIENTPROXYUNKNOWN_H
|
||||
#define CCLIENTPROXYUNKNOWN_H
|
||||
|
||||
#include "CEvent.h"
|
||||
|
||||
class CClientProxy;
|
||||
class CEventQueueTimer;
|
||||
class IStream;
|
||||
|
||||
class CClientProxyUnknown {
|
||||
public:
|
||||
CClientProxyUnknown(IStream* stream, double timeout);
|
||||
~CClientProxyUnknown();
|
||||
|
||||
//! @name manipulators
|
||||
//@{
|
||||
|
||||
//! Get the client proxy
|
||||
/*!
|
||||
Returns the client proxy created after a successful handshake
|
||||
(i.e. when this object sends a success event). Returns NULL
|
||||
if the handshake is unsuccessful or incomplete.
|
||||
*/
|
||||
CClientProxy* orphanClientProxy();
|
||||
|
||||
//@}
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Get success event type
|
||||
/*!
|
||||
Returns the success event type. This is sent when the client has
|
||||
correctly responded to the hello message. The target is this.
|
||||
*/
|
||||
static CEvent::Type getSuccessEvent();
|
||||
|
||||
//! Get failure event type
|
||||
/*!
|
||||
Returns the failure event type. This is sent when a client fails
|
||||
to correctly respond to the hello message. The target is this.
|
||||
*/
|
||||
static CEvent::Type getFailureEvent();
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
void sendSuccess();
|
||||
void sendFailure();
|
||||
void addStreamHandlers();
|
||||
void addProxyHandlers();
|
||||
void removeHandlers();
|
||||
void removeTimer();
|
||||
void handleData(const CEvent&, void*);
|
||||
void handleWriteError(const CEvent&, void*);
|
||||
void handleTimeout(const CEvent&, void*);
|
||||
void handleDisconnect(const CEvent&, void*);
|
||||
void handleReady(const CEvent&, void*);
|
||||
|
||||
private:
|
||||
IStream* m_stream;
|
||||
CEventQueueTimer* m_timer;
|
||||
CClientProxy* m_proxy;
|
||||
bool m_ready;
|
||||
|
||||
static CEvent::Type s_successEvent;
|
||||
static CEvent::Type s_failureEvent;
|
||||
};
|
||||
|
||||
#endif
|
||||
2277
lib/server/CConfig.cpp
Normal file
2277
lib/server/CConfig.cpp
Normal file
File diff suppressed because it is too large
Load Diff
536
lib/server/CConfig.h
Normal file
536
lib/server/CConfig.h
Normal file
@@ -0,0 +1,536 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2002 Chris Schoeneman
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* found in the file COPYING that should have accompanied this file.
|
||||
*
|
||||
* This package 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.
|
||||
*/
|
||||
|
||||
#ifndef CCONFIG_H
|
||||
#define CCONFIG_H
|
||||
|
||||
#include "OptionTypes.h"
|
||||
#include "ProtocolTypes.h"
|
||||
#include "CNetworkAddress.h"
|
||||
#include "CStringUtil.h"
|
||||
#include "CInputFilter.h"
|
||||
#include "XBase.h"
|
||||
#include "stdmap.h"
|
||||
#include "stdset.h"
|
||||
#include "IPlatformScreen.h"
|
||||
#include <iosfwd>
|
||||
|
||||
class CConfig;
|
||||
class CConfigReadContext;
|
||||
|
||||
namespace std {
|
||||
template <>
|
||||
struct iterator_traits<CConfig> {
|
||||
typedef CString value_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef bidirectional_iterator_tag iterator_category;
|
||||
typedef CString* pointer;
|
||||
typedef CString& reference;
|
||||
};
|
||||
};
|
||||
|
||||
//! Server configuration
|
||||
/*!
|
||||
This class holds server configuration information. That includes
|
||||
the names of screens and their aliases, the links between them,
|
||||
and network addresses.
|
||||
|
||||
Note that case is preserved in screen names but is ignored when
|
||||
comparing names. Screen names and their aliases share a
|
||||
namespace and must be unique.
|
||||
*/
|
||||
class CConfig {
|
||||
public:
|
||||
typedef std::map<OptionID, OptionValue> CScreenOptions;
|
||||
typedef std::pair<float, float> CInterval;
|
||||
|
||||
class CCellEdge {
|
||||
public:
|
||||
CCellEdge(EDirection side, float position);
|
||||
CCellEdge(EDirection side, const CInterval&);
|
||||
CCellEdge(const CString& name, EDirection side, const CInterval&);
|
||||
~CCellEdge();
|
||||
|
||||
CInterval getInterval() const;
|
||||
void setName(const CString& newName);
|
||||
CString getName() const;
|
||||
EDirection getSide() const;
|
||||
bool overlaps(const CCellEdge&) const;
|
||||
bool isInside(float x) const;
|
||||
|
||||
// transform position to [0,1]
|
||||
float transform(float x) const;
|
||||
|
||||
// transform [0,1] to position
|
||||
float inverseTransform(float x) const;
|
||||
|
||||
// compares side and start of interval
|
||||
bool operator<(const CCellEdge&) const;
|
||||
|
||||
// compares side and interval
|
||||
bool operator==(const CCellEdge&) const;
|
||||
bool operator!=(const CCellEdge&) const;
|
||||
|
||||
private:
|
||||
void init(const CString& name, EDirection side,
|
||||
const CInterval&);
|
||||
|
||||
private:
|
||||
CString m_name;
|
||||
EDirection m_side;
|
||||
CInterval m_interval;
|
||||
};
|
||||
|
||||
private:
|
||||
class CName {
|
||||
public:
|
||||
CName(CConfig*, const CString& name);
|
||||
|
||||
bool operator==(const CString& name) const;
|
||||
|
||||
private:
|
||||
CConfig* m_config;
|
||||
CString m_name;
|
||||
};
|
||||
|
||||
class CCell {
|
||||
private:
|
||||
typedef std::map<CCellEdge, CCellEdge> CEdgeLinks;
|
||||
|
||||
public:
|
||||
typedef CEdgeLinks::const_iterator const_iterator;
|
||||
|
||||
bool add(const CCellEdge& src, const CCellEdge& dst);
|
||||
void remove(EDirection side);
|
||||
void remove(EDirection side, float position);
|
||||
void remove(const CName& destinationName);
|
||||
void rename(const CName& oldName, const CString& newName);
|
||||
|
||||
bool hasEdge(const CCellEdge&) const;
|
||||
bool overlaps(const CCellEdge&) const;
|
||||
|
||||
bool getLink(EDirection side, float position,
|
||||
const CCellEdge*& src, const CCellEdge*& dst) const;
|
||||
|
||||
bool operator==(const CCell&) const;
|
||||
bool operator!=(const CCell&) const;
|
||||
|
||||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
|
||||
private:
|
||||
CEdgeLinks m_neighbors;
|
||||
|
||||
public:
|
||||
CScreenOptions m_options;
|
||||
};
|
||||
typedef std::map<CString, CCell, CStringUtil::CaselessCmp> CCellMap;
|
||||
typedef std::map<CString, CString, CStringUtil::CaselessCmp> CNameMap;
|
||||
|
||||
public:
|
||||
typedef CCell::const_iterator link_const_iterator;
|
||||
typedef CCellMap::const_iterator internal_const_iterator;
|
||||
typedef CNameMap::const_iterator all_const_iterator;
|
||||
class const_iterator : std::iterator_traits<CConfig> {
|
||||
public:
|
||||
explicit const_iterator() : m_i() { }
|
||||
explicit const_iterator(const internal_const_iterator& i) : m_i(i) { }
|
||||
|
||||
const_iterator& operator=(const const_iterator& i) {
|
||||
m_i = i.m_i;
|
||||
return *this;
|
||||
}
|
||||
CString operator*() { return m_i->first; }
|
||||
const CString* operator->() { return &(m_i->first); }
|
||||
const_iterator& operator++() { ++m_i; return *this; }
|
||||
const_iterator operator++(int) { return const_iterator(m_i++); }
|
||||
const_iterator& operator--() { --m_i; return *this; }
|
||||
const_iterator operator--(int) { return const_iterator(m_i--); }
|
||||
bool operator==(const const_iterator& i) const {
|
||||
return (m_i == i.m_i);
|
||||
}
|
||||
bool operator!=(const const_iterator& i) const {
|
||||
return (m_i != i.m_i);
|
||||
}
|
||||
|
||||
private:
|
||||
internal_const_iterator m_i;
|
||||
};
|
||||
|
||||
CConfig();
|
||||
virtual ~CConfig();
|
||||
|
||||
//! @name manipulators
|
||||
//@{
|
||||
|
||||
//! Add screen
|
||||
/*!
|
||||
Adds a screen, returning true iff successful. If a screen or
|
||||
alias with the given name exists then it fails.
|
||||
*/
|
||||
bool addScreen(const CString& name);
|
||||
|
||||
//! Rename screen
|
||||
/*!
|
||||
Renames a screen. All references to the name are updated.
|
||||
Returns true iff successful.
|
||||
*/
|
||||
bool renameScreen(const CString& oldName,
|
||||
const CString& newName);
|
||||
|
||||
//! Remove screen
|
||||
/*!
|
||||
Removes a screen. This also removes aliases for the screen and
|
||||
disconnects any connections to the screen. \c name may be an
|
||||
alias.
|
||||
*/
|
||||
void removeScreen(const CString& name);
|
||||
|
||||
//! Remove all screens
|
||||
/*!
|
||||
Removes all screens, aliases, and connections.
|
||||
*/
|
||||
void removeAllScreens();
|
||||
|
||||
//! Add alias
|
||||
/*!
|
||||
Adds an alias for a screen name. An alias can be used
|
||||
any place the canonical screen name can (except addScreen()).
|
||||
Returns false if the alias name already exists or the canonical
|
||||
name is unknown, otherwise returns true.
|
||||
*/
|
||||
bool addAlias(const CString& canonical,
|
||||
const CString& alias);
|
||||
|
||||
//! Remove alias
|
||||
/*!
|
||||
Removes an alias for a screen name. It returns false if the
|
||||
alias is unknown or a canonical name, otherwise returns true.
|
||||
*/
|
||||
bool removeAlias(const CString& alias);
|
||||
|
||||
//! Remove aliases
|
||||
/*!
|
||||
Removes all aliases for a canonical screen name. It returns false
|
||||
if the canonical name is unknown, otherwise returns true.
|
||||
*/
|
||||
bool removeAliases(const CString& canonical);
|
||||
|
||||
//! Remove all aliases
|
||||
/*!
|
||||
This removes all aliases but not the screens.
|
||||
*/
|
||||
void removeAllAliases();
|
||||
|
||||
//! Connect screens
|
||||
/*!
|
||||
Establishes a one-way connection between portions of opposite edges
|
||||
of two screens. Each portion is described by an interval defined
|
||||
by two numbers, the start and end of the interval half-open on the
|
||||
end. The numbers range from 0 to 1, inclusive, for the left/top
|
||||
to the right/bottom. The user will be able to jump from the
|
||||
\c srcStart to \c srcSend interval of \c srcSide of screen
|
||||
\c srcName to the opposite side of screen \c dstName in the interval
|
||||
\c dstStart and \c dstEnd when both screens are connected to the
|
||||
server and the user isn't locked to a screen. Returns false if
|
||||
\c srcName is unknown. \c srcStart must be less than or equal to
|
||||
\c srcEnd and \c dstStart must be less then or equal to \c dstEnd
|
||||
and all of \c srcStart, \c srcEnd, \c dstStart, or \c dstEnd must
|
||||
be inside the range [0,1].
|
||||
*/
|
||||
bool connect(const CString& srcName,
|
||||
EDirection srcSide,
|
||||
float srcStart, float srcEnd,
|
||||
const CString& dstName,
|
||||
float dstStart, float dstEnd);
|
||||
|
||||
//! Disconnect screens
|
||||
/*!
|
||||
Removes all connections created by connect() on side \c srcSide.
|
||||
Returns false if \c srcName is unknown.
|
||||
*/
|
||||
bool disconnect(const CString& srcName,
|
||||
EDirection srcSide);
|
||||
|
||||
//! Disconnect screens
|
||||
/*!
|
||||
Removes the connections created by connect() on side \c srcSide
|
||||
covering position \c position. Returns false if \c srcName is
|
||||
unknown.
|
||||
*/
|
||||
bool disconnect(const CString& srcName,
|
||||
EDirection srcSide, float position);
|
||||
|
||||
//! Set server address
|
||||
/*!
|
||||
Set the synergy listen addresses. There is no default address so
|
||||
this must be called to run a server using this configuration.
|
||||
*/
|
||||
void setSynergyAddress(const CNetworkAddress&);
|
||||
|
||||
//! Add a screen option
|
||||
/*!
|
||||
Adds an option and its value to the named screen. Replaces the
|
||||
existing option's value if there is one. Returns true iff \c name
|
||||
is a known screen.
|
||||
*/
|
||||
bool addOption(const CString& name,
|
||||
OptionID option, OptionValue value);
|
||||
|
||||
//! Remove a screen option
|
||||
/*!
|
||||
Removes an option and its value from the named screen. Does
|
||||
nothing if the option doesn't exist on the screen. Returns true
|
||||
iff \c name is a known screen.
|
||||
*/
|
||||
bool removeOption(const CString& name, OptionID option);
|
||||
|
||||
//! Remove a screen options
|
||||
/*!
|
||||
Removes all options and values from the named screen. Returns true
|
||||
iff \c name is a known screen.
|
||||
*/
|
||||
bool removeOptions(const CString& name);
|
||||
|
||||
//! Get the hot key input filter
|
||||
/*!
|
||||
Returns the hot key input filter. Clients can modify hotkeys using
|
||||
that object.
|
||||
*/
|
||||
CInputFilter* getInputFilter();
|
||||
|
||||
//@}
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Test screen name validity
|
||||
/*!
|
||||
Returns true iff \c name is a valid screen name.
|
||||
*/
|
||||
bool isValidScreenName(const CString& name) const;
|
||||
|
||||
//! Get beginning (canonical) screen name iterator
|
||||
const_iterator begin() const;
|
||||
//! Get ending (canonical) screen name iterator
|
||||
const_iterator end() const;
|
||||
|
||||
//! Get beginning screen name iterator
|
||||
all_const_iterator beginAll() const;
|
||||
//! Get ending screen name iterator
|
||||
all_const_iterator endAll() const;
|
||||
|
||||
//! Test for screen name
|
||||
/*!
|
||||
Returns true iff \c name names a screen.
|
||||
*/
|
||||
bool isScreen(const CString& name) const;
|
||||
|
||||
//! Test for canonical screen name
|
||||
/*!
|
||||
Returns true iff \c name is the canonical name of a screen.
|
||||
*/
|
||||
bool isCanonicalName(const CString& name) const;
|
||||
|
||||
//! Get canonical name
|
||||
/*!
|
||||
Returns the canonical name of a screen or the empty string if
|
||||
the name is unknown. Returns the canonical name if one is given.
|
||||
*/
|
||||
CString getCanonicalName(const CString& name) const;
|
||||
|
||||
//! Get neighbor
|
||||
/*!
|
||||
Returns the canonical screen name of the neighbor in the given
|
||||
direction (set through connect()) at position \c position. Returns
|
||||
the empty string if there is no neighbor in that direction, otherwise
|
||||
saves the position on the neighbor in \c positionOut if it's not
|
||||
\c NULL.
|
||||
*/
|
||||
CString getNeighbor(const CString&, EDirection,
|
||||
float position, float* positionOut) const;
|
||||
|
||||
//! Check for neighbor
|
||||
/*!
|
||||
Returns \c true if the screen has a neighbor anywhere along the edge
|
||||
given by the direction.
|
||||
*/
|
||||
bool hasNeighbor(const CString&, EDirection) const;
|
||||
|
||||
//! Check for neighbor
|
||||
/*!
|
||||
Returns \c true if the screen has a neighbor in the given range along
|
||||
the edge given by the direction.
|
||||
*/
|
||||
bool hasNeighbor(const CString&, EDirection,
|
||||
float start, float end) const;
|
||||
|
||||
//! Get beginning neighbor iterator
|
||||
link_const_iterator beginNeighbor(const CString&) const;
|
||||
//! Get ending neighbor iterator
|
||||
link_const_iterator endNeighbor(const CString&) const;
|
||||
|
||||
//! Get the server address
|
||||
const CNetworkAddress& getSynergyAddress() const;
|
||||
|
||||
//! Get the screen options
|
||||
/*!
|
||||
Returns all the added options for the named screen. Returns NULL
|
||||
if the screen is unknown and an empty collection if there are no
|
||||
options.
|
||||
*/
|
||||
const CScreenOptions* getOptions(const CString& name) const;
|
||||
|
||||
//! Check for lock to screen action
|
||||
/*!
|
||||
Returns \c true if this configuration has a lock to screen action.
|
||||
This is for backwards compatible support of ScrollLock locking.
|
||||
*/
|
||||
bool hasLockToScreenAction() const;
|
||||
|
||||
//! Compare configurations
|
||||
bool operator==(const CConfig&) const;
|
||||
//! Compare configurations
|
||||
bool operator!=(const CConfig&) const;
|
||||
|
||||
//! Read configuration
|
||||
/*!
|
||||
Reads a configuration from a context. Throws XConfigRead on error
|
||||
and context is unchanged.
|
||||
*/
|
||||
void read(CConfigReadContext& context);
|
||||
|
||||
//! Read configuration
|
||||
/*!
|
||||
Reads a configuration from a stream. Throws XConfigRead on error.
|
||||
*/
|
||||
friend std::istream& operator>>(std::istream&, CConfig&);
|
||||
|
||||
//! Write configuration
|
||||
/*!
|
||||
Writes a configuration to a stream.
|
||||
*/
|
||||
friend std::ostream& operator<<(std::ostream&, const CConfig&);
|
||||
|
||||
//! Get direction name
|
||||
/*!
|
||||
Returns the name of a direction (for debugging).
|
||||
*/
|
||||
static const char* dirName(EDirection);
|
||||
|
||||
//! Get interval as string
|
||||
/*!
|
||||
Returns an interval as a parseable string.
|
||||
*/
|
||||
static CString formatInterval(const CInterval&);
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
void readSection(CConfigReadContext&);
|
||||
void readSectionOptions(CConfigReadContext&);
|
||||
void readSectionScreens(CConfigReadContext&);
|
||||
void readSectionLinks(CConfigReadContext&);
|
||||
void readSectionAliases(CConfigReadContext&);
|
||||
|
||||
CInputFilter::CCondition*
|
||||
parseCondition(CConfigReadContext&,
|
||||
const CString& condition,
|
||||
const std::vector<CString>& args);
|
||||
void parseAction(CConfigReadContext&,
|
||||
const CString& action,
|
||||
const std::vector<CString>& args,
|
||||
CInputFilter::CRule&, bool activate);
|
||||
|
||||
void parseScreens(CConfigReadContext&, const CString&,
|
||||
std::set<CString>& screens) const;
|
||||
static const char* getOptionName(OptionID);
|
||||
static CString getOptionValue(OptionID, OptionValue);
|
||||
|
||||
private:
|
||||
CCellMap m_map;
|
||||
CNameMap m_nameToCanonicalName;
|
||||
CNetworkAddress m_synergyAddress;
|
||||
CScreenOptions m_globalOptions;
|
||||
CInputFilter m_inputFilter;
|
||||
bool m_hasLockToScreenAction;
|
||||
};
|
||||
|
||||
//! Configuration read context
|
||||
/*!
|
||||
Maintains a context when reading a configuration from a stream.
|
||||
*/
|
||||
class CConfigReadContext {
|
||||
public:
|
||||
typedef std::vector<CString> ArgList;
|
||||
|
||||
CConfigReadContext(std::istream&, SInt32 firstLine = 1);
|
||||
~CConfigReadContext();
|
||||
|
||||
bool readLine(CString&);
|
||||
UInt32 getLineNumber() const;
|
||||
|
||||
operator void*() const;
|
||||
bool operator!() const;
|
||||
|
||||
OptionValue parseBoolean(const CString&) const;
|
||||
OptionValue parseInt(const CString&) const;
|
||||
OptionValue parseModifierKey(const CString&) const;
|
||||
OptionValue parseCorner(const CString&) const;
|
||||
OptionValue parseCorners(const CString&) const;
|
||||
CConfig::CInterval
|
||||
parseInterval(const ArgList& args) const;
|
||||
void parseNameWithArgs(
|
||||
const CString& type, const CString& line,
|
||||
const CString& delim, CString::size_type& index,
|
||||
CString& name, ArgList& args) const;
|
||||
IPlatformScreen::CKeyInfo*
|
||||
parseKeystroke(const CString& keystroke) const;
|
||||
IPlatformScreen::CKeyInfo*
|
||||
parseKeystroke(const CString& keystroke,
|
||||
const std::set<CString>& screens) const;
|
||||
IPlatformScreen::CButtonInfo*
|
||||
parseMouse(const CString& mouse) const;
|
||||
KeyModifierMask parseModifier(const CString& modifiers) const;
|
||||
|
||||
private:
|
||||
// not implemented
|
||||
CConfigReadContext& operator=(const CConfigReadContext&);
|
||||
|
||||
static CString concatArgs(const ArgList& args);
|
||||
|
||||
private:
|
||||
std::istream& m_stream;
|
||||
SInt32 m_line;
|
||||
};
|
||||
|
||||
//! Configuration stream read exception
|
||||
/*!
|
||||
Thrown when a configuration stream cannot be parsed.
|
||||
*/
|
||||
class XConfigRead : public XBase {
|
||||
public:
|
||||
XConfigRead(const CConfigReadContext& context, const CString&);
|
||||
XConfigRead(const CConfigReadContext& context,
|
||||
const char* errorFmt, const CString& arg);
|
||||
~XConfigRead();
|
||||
|
||||
protected:
|
||||
// XBase overrides
|
||||
virtual CString getWhat() const throw();
|
||||
|
||||
private:
|
||||
CString m_error;
|
||||
};
|
||||
|
||||
#endif
|
||||
1066
lib/server/CInputFilter.cpp
Normal file
1066
lib/server/CInputFilter.cpp
Normal file
File diff suppressed because it is too large
Load Diff
344
lib/server/CInputFilter.h
Normal file
344
lib/server/CInputFilter.h
Normal file
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2005 Chris Schoeneman
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* found in the file COPYING that should have accompanied this file.
|
||||
*
|
||||
* This package 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.
|
||||
*/
|
||||
|
||||
#ifndef CINPUTFILTER_H
|
||||
#define CINPUTFILTER_H
|
||||
|
||||
#include "KeyTypes.h"
|
||||
#include "MouseTypes.h"
|
||||
#include "ProtocolTypes.h"
|
||||
#include "IPlatformScreen.h"
|
||||
#include "CString.h"
|
||||
#include "stdmap.h"
|
||||
#include "stdset.h"
|
||||
|
||||
class CPrimaryClient;
|
||||
class CEvent;
|
||||
|
||||
class CInputFilter {
|
||||
public:
|
||||
// -------------------------------------------------------------------------
|
||||
// Input Filter Condition Classes
|
||||
// -------------------------------------------------------------------------
|
||||
enum EFilterStatus {
|
||||
kNoMatch,
|
||||
kActivate,
|
||||
kDeactivate
|
||||
};
|
||||
|
||||
class CCondition {
|
||||
public:
|
||||
CCondition();
|
||||
virtual ~CCondition();
|
||||
|
||||
virtual CCondition* clone() const = 0;
|
||||
virtual CString format() const = 0;
|
||||
|
||||
virtual EFilterStatus match(const CEvent&) = 0;
|
||||
|
||||
virtual void enablePrimary(CPrimaryClient*);
|
||||
virtual void disablePrimary(CPrimaryClient*);
|
||||
};
|
||||
|
||||
// CKeystrokeCondition
|
||||
class CKeystrokeCondition : public CCondition {
|
||||
public:
|
||||
CKeystrokeCondition(IPlatformScreen::CKeyInfo*);
|
||||
CKeystrokeCondition(KeyID key, KeyModifierMask mask);
|
||||
virtual ~CKeystrokeCondition();
|
||||
|
||||
KeyID getKey() const;
|
||||
KeyModifierMask getMask() const;
|
||||
|
||||
// CCondition overrides
|
||||
virtual CCondition* clone() const;
|
||||
virtual CString format() const;
|
||||
virtual EFilterStatus match(const CEvent&);
|
||||
virtual void enablePrimary(CPrimaryClient*);
|
||||
virtual void disablePrimary(CPrimaryClient*);
|
||||
|
||||
private:
|
||||
UInt32 m_id;
|
||||
KeyID m_key;
|
||||
KeyModifierMask m_mask;
|
||||
};
|
||||
|
||||
// CMouseButtonCondition
|
||||
class CMouseButtonCondition : public CCondition {
|
||||
public:
|
||||
CMouseButtonCondition(IPlatformScreen::CButtonInfo*);
|
||||
CMouseButtonCondition(ButtonID, KeyModifierMask mask);
|
||||
virtual ~CMouseButtonCondition();
|
||||
|
||||
ButtonID getButton() const;
|
||||
KeyModifierMask getMask() const;
|
||||
|
||||
// CCondition overrides
|
||||
virtual CCondition* clone() const;
|
||||
virtual CString format() const;
|
||||
virtual EFilterStatus match(const CEvent&);
|
||||
|
||||
private:
|
||||
ButtonID m_button;
|
||||
KeyModifierMask m_mask;
|
||||
};
|
||||
|
||||
// CScreenConnectedCondition
|
||||
class CScreenConnectedCondition : public CCondition {
|
||||
public:
|
||||
CScreenConnectedCondition(const CString& screen);
|
||||
virtual ~CScreenConnectedCondition();
|
||||
|
||||
// CCondition overrides
|
||||
virtual CCondition* clone() const;
|
||||
virtual CString format() const;
|
||||
virtual EFilterStatus match(const CEvent&);
|
||||
|
||||
private:
|
||||
CString m_screen;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Input Filter Action Classes
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
class CAction {
|
||||
public:
|
||||
CAction();
|
||||
virtual ~CAction();
|
||||
|
||||
virtual CAction* clone() const = 0;
|
||||
virtual CString format() const = 0;
|
||||
|
||||
virtual void perform(const CEvent&) = 0;
|
||||
};
|
||||
|
||||
// CLockCursorToScreenAction
|
||||
class CLockCursorToScreenAction : public CAction {
|
||||
public:
|
||||
enum Mode { kOff, kOn, kToggle };
|
||||
|
||||
CLockCursorToScreenAction(Mode = kToggle);
|
||||
|
||||
Mode getMode() const;
|
||||
|
||||
// CAction overrides
|
||||
virtual CAction* clone() const;
|
||||
virtual CString format() const;
|
||||
virtual void perform(const CEvent&);
|
||||
|
||||
private:
|
||||
Mode m_mode;
|
||||
};
|
||||
|
||||
// CSwitchToScreenAction
|
||||
class CSwitchToScreenAction : public CAction {
|
||||
public:
|
||||
CSwitchToScreenAction(const CString& screen);
|
||||
|
||||
CString getScreen() const;
|
||||
|
||||
// CAction overrides
|
||||
virtual CAction* clone() const;
|
||||
virtual CString format() const;
|
||||
virtual void perform(const CEvent&);
|
||||
|
||||
private:
|
||||
CString m_screen;
|
||||
};
|
||||
|
||||
// CSwitchInDirectionAction
|
||||
class CSwitchInDirectionAction : public CAction {
|
||||
public:
|
||||
CSwitchInDirectionAction(EDirection);
|
||||
|
||||
EDirection getDirection() const;
|
||||
|
||||
// CAction overrides
|
||||
virtual CAction* clone() const;
|
||||
virtual CString format() const;
|
||||
virtual void perform(const CEvent&);
|
||||
|
||||
private:
|
||||
EDirection m_direction;
|
||||
};
|
||||
|
||||
// CKeyboardBroadcastAction
|
||||
class CKeyboardBroadcastAction : public CAction {
|
||||
public:
|
||||
enum Mode { kOff, kOn, kToggle };
|
||||
|
||||
CKeyboardBroadcastAction(Mode = kToggle);
|
||||
CKeyboardBroadcastAction(Mode, const std::set<CString>& screens);
|
||||
|
||||
Mode getMode() const;
|
||||
std::set<CString> getScreens() const;
|
||||
|
||||
// CAction overrides
|
||||
virtual CAction* clone() const;
|
||||
virtual CString format() const;
|
||||
virtual void perform(const CEvent&);
|
||||
|
||||
private:
|
||||
Mode m_mode;
|
||||
CString m_screens;
|
||||
};
|
||||
|
||||
// CKeystrokeAction
|
||||
class CKeystrokeAction : public CAction {
|
||||
public:
|
||||
CKeystrokeAction(IPlatformScreen::CKeyInfo* adoptedInfo, bool press);
|
||||
~CKeystrokeAction();
|
||||
|
||||
void adoptInfo(IPlatformScreen::CKeyInfo*);
|
||||
const IPlatformScreen::CKeyInfo*
|
||||
getInfo() const;
|
||||
bool isOnPress() const;
|
||||
|
||||
// CAction overrides
|
||||
virtual CAction* clone() const;
|
||||
virtual CString format() const;
|
||||
virtual void perform(const CEvent&);
|
||||
|
||||
protected:
|
||||
virtual const char* formatName() const;
|
||||
|
||||
private:
|
||||
IPlatformScreen::CKeyInfo* m_keyInfo;
|
||||
bool m_press;
|
||||
};
|
||||
|
||||
// CMouseButtonAction -- modifier combinations not implemented yet
|
||||
class CMouseButtonAction : public CAction {
|
||||
public:
|
||||
CMouseButtonAction(IPlatformScreen::CButtonInfo* adoptedInfo,
|
||||
bool press);
|
||||
~CMouseButtonAction();
|
||||
|
||||
const IPlatformScreen::CButtonInfo*
|
||||
getInfo() const;
|
||||
bool isOnPress() const;
|
||||
|
||||
// CAction overrides
|
||||
virtual CAction* clone() const;
|
||||
virtual CString format() const;
|
||||
virtual void perform(const CEvent&);
|
||||
|
||||
protected:
|
||||
virtual const char* formatName() const;
|
||||
|
||||
private:
|
||||
IPlatformScreen::CButtonInfo* m_buttonInfo;
|
||||
bool m_press;
|
||||
};
|
||||
|
||||
class CRule {
|
||||
public:
|
||||
CRule();
|
||||
CRule(CCondition* adopted);
|
||||
CRule(const CRule&);
|
||||
~CRule();
|
||||
|
||||
CRule& operator=(const CRule&);
|
||||
|
||||
// replace the condition
|
||||
void setCondition(CCondition* adopted);
|
||||
|
||||
// add an action to the rule
|
||||
void adoptAction(CAction*, bool onActivation);
|
||||
|
||||
// remove an action from the rule
|
||||
void removeAction(bool onActivation, UInt32 index);
|
||||
|
||||
// replace an action in the rule
|
||||
void replaceAction(CAction* adopted,
|
||||
bool onActivation, UInt32 index);
|
||||
|
||||
// enable/disable
|
||||
void enable(CPrimaryClient*);
|
||||
void disable(CPrimaryClient*);
|
||||
|
||||
// event handling
|
||||
bool handleEvent(const CEvent&);
|
||||
|
||||
// convert rule to a string
|
||||
CString format() const;
|
||||
|
||||
// get the rule's condition
|
||||
const CCondition*
|
||||
getCondition() const;
|
||||
|
||||
// get number of actions
|
||||
UInt32 getNumActions(bool onActivation) const;
|
||||
|
||||
// get action by index
|
||||
const CAction& getAction(bool onActivation, UInt32 index) const;
|
||||
|
||||
private:
|
||||
void clear();
|
||||
void copy(const CRule&);
|
||||
|
||||
private:
|
||||
typedef std::vector<CAction*> CActionList;
|
||||
|
||||
CCondition* m_condition;
|
||||
CActionList m_activateActions;
|
||||
CActionList m_deactivateActions;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Input Filter Class
|
||||
// -------------------------------------------------------------------------
|
||||
typedef std::vector<CRule> CRuleList;
|
||||
|
||||
CInputFilter();
|
||||
CInputFilter(const CInputFilter&);
|
||||
virtual ~CInputFilter();
|
||||
|
||||
CInputFilter& operator=(const CInputFilter&);
|
||||
|
||||
// add rule, adopting the condition and the actions
|
||||
void addFilterRule(const CRule& rule);
|
||||
|
||||
// remove a rule
|
||||
void removeFilterRule(UInt32 index);
|
||||
|
||||
// get rule by index
|
||||
CRule& getRule(UInt32 index);
|
||||
|
||||
// enable event filtering using the given primary client. disable
|
||||
// if client is NULL.
|
||||
void setPrimaryClient(CPrimaryClient* client);
|
||||
|
||||
// convert rules to a string
|
||||
CString format(const CString& linePrefix) const;
|
||||
|
||||
// get number of rules
|
||||
UInt32 getNumRules() const;
|
||||
|
||||
//! Compare filters
|
||||
bool operator==(const CInputFilter&) const;
|
||||
//! Compare filters
|
||||
bool operator!=(const CInputFilter&) const;
|
||||
|
||||
private:
|
||||
// event handling
|
||||
void handleEvent(const CEvent&, void*);
|
||||
|
||||
private:
|
||||
CRuleList m_ruleList;
|
||||
CPrimaryClient* m_primaryClient;
|
||||
};
|
||||
|
||||
#endif
|
||||
257
lib/server/CPrimaryClient.cpp
Normal file
257
lib/server/CPrimaryClient.cpp
Normal file
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2002 Chris Schoeneman
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* found in the file COPYING that should have accompanied this file.
|
||||
*
|
||||
* This package 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.
|
||||
*/
|
||||
|
||||
#include "CPrimaryClient.h"
|
||||
#include "CScreen.h"
|
||||
#include "CClipboard.h"
|
||||
#include "CLog.h"
|
||||
|
||||
//
|
||||
// CPrimaryClient
|
||||
//
|
||||
|
||||
CPrimaryClient::CPrimaryClient(const CString& name, CScreen* screen) :
|
||||
CBaseClientProxy(name),
|
||||
m_screen(screen),
|
||||
m_fakeInputCount(0)
|
||||
{
|
||||
// all clipboards are clean
|
||||
for (UInt32 i = 0; i < kClipboardEnd; ++i) {
|
||||
m_clipboardDirty[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
CPrimaryClient::~CPrimaryClient()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::reconfigure(UInt32 activeSides)
|
||||
{
|
||||
m_screen->reconfigure(activeSides);
|
||||
}
|
||||
|
||||
UInt32
|
||||
CPrimaryClient::registerHotKey(KeyID key, KeyModifierMask mask)
|
||||
{
|
||||
return m_screen->registerHotKey(key, mask);
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::unregisterHotKey(UInt32 id)
|
||||
{
|
||||
m_screen->unregisterHotKey(id);
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::fakeInputBegin()
|
||||
{
|
||||
if (++m_fakeInputCount == 1) {
|
||||
m_screen->fakeInputBegin();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::fakeInputEnd()
|
||||
{
|
||||
if (--m_fakeInputCount == 0) {
|
||||
m_screen->fakeInputEnd();
|
||||
}
|
||||
}
|
||||
|
||||
SInt32
|
||||
CPrimaryClient::getJumpZoneSize() const
|
||||
{
|
||||
return m_screen->getJumpZoneSize();
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::getCursorCenter(SInt32& x, SInt32& y) const
|
||||
{
|
||||
m_screen->getCursorCenter(x, y);
|
||||
}
|
||||
|
||||
KeyModifierMask
|
||||
CPrimaryClient::getToggleMask() const
|
||||
{
|
||||
return m_screen->pollActiveModifiers();
|
||||
}
|
||||
|
||||
bool
|
||||
CPrimaryClient::isLockedToScreen() const
|
||||
{
|
||||
return m_screen->isLockedToScreen();
|
||||
}
|
||||
|
||||
void*
|
||||
CPrimaryClient::getEventTarget() const
|
||||
{
|
||||
return m_screen->getEventTarget();
|
||||
}
|
||||
|
||||
bool
|
||||
CPrimaryClient::getClipboard(ClipboardID id, IClipboard* clipboard) const
|
||||
{
|
||||
return m_screen->getClipboard(id, clipboard);
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::getShape(SInt32& x, SInt32& y,
|
||||
SInt32& width, SInt32& height) const
|
||||
{
|
||||
m_screen->getShape(x, y, width, height);
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::getCursorPos(SInt32& x, SInt32& y) const
|
||||
{
|
||||
m_screen->getCursorPos(x, y);
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::enable()
|
||||
{
|
||||
m_screen->enable();
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::disable()
|
||||
{
|
||||
m_screen->disable();
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::enter(SInt32 xAbs, SInt32 yAbs,
|
||||
UInt32 seqNum, KeyModifierMask mask, bool screensaver)
|
||||
{
|
||||
m_screen->setSequenceNumber(seqNum);
|
||||
if (!screensaver) {
|
||||
m_screen->warpCursor(xAbs, yAbs);
|
||||
}
|
||||
m_screen->enter(mask);
|
||||
}
|
||||
|
||||
bool
|
||||
CPrimaryClient::leave()
|
||||
{
|
||||
return m_screen->leave();
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::setClipboard(ClipboardID id, const IClipboard* clipboard)
|
||||
{
|
||||
// ignore if this clipboard is already clean
|
||||
if (m_clipboardDirty[id]) {
|
||||
// this clipboard is now clean
|
||||
m_clipboardDirty[id] = false;
|
||||
|
||||
// set clipboard
|
||||
m_screen->setClipboard(id, clipboard);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::grabClipboard(ClipboardID id)
|
||||
{
|
||||
// grab clipboard
|
||||
m_screen->grabClipboard(id);
|
||||
|
||||
// clipboard is dirty (because someone else owns it now)
|
||||
m_clipboardDirty[id] = true;
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::setClipboardDirty(ClipboardID id, bool dirty)
|
||||
{
|
||||
m_clipboardDirty[id] = dirty;
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::keyDown(KeyID key, KeyModifierMask mask, KeyButton button)
|
||||
{
|
||||
if (m_fakeInputCount > 0) {
|
||||
// XXX -- don't forward keystrokes to primary screen for now
|
||||
(void)key;
|
||||
(void)mask;
|
||||
(void)button;
|
||||
// m_screen->keyDown(key, mask, button);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::keyRepeat(KeyID, KeyModifierMask, SInt32, KeyButton)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::keyUp(KeyID key, KeyModifierMask mask, KeyButton button)
|
||||
{
|
||||
if (m_fakeInputCount > 0) {
|
||||
// XXX -- don't forward keystrokes to primary screen for now
|
||||
(void)key;
|
||||
(void)mask;
|
||||
(void)button;
|
||||
// m_screen->keyUp(key, mask, button);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::mouseDown(ButtonID)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::mouseUp(ButtonID)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::mouseMove(SInt32 x, SInt32 y)
|
||||
{
|
||||
m_screen->warpCursor(x, y);
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::mouseRelativeMove(SInt32, SInt32)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::mouseWheel(SInt32, SInt32)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::screensaver(bool)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::resetOptions()
|
||||
{
|
||||
m_screen->resetOptions();
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::setOptions(const COptionsList& options)
|
||||
{
|
||||
m_screen->setOptions(options);
|
||||
}
|
||||
145
lib/server/CPrimaryClient.h
Normal file
145
lib/server/CPrimaryClient.h
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2002 Chris Schoeneman
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* found in the file COPYING that should have accompanied this file.
|
||||
*
|
||||
* This package 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.
|
||||
*/
|
||||
|
||||
#ifndef CPRIMARYCLIENT_H
|
||||
#define CPRIMARYCLIENT_H
|
||||
|
||||
#include "CBaseClientProxy.h"
|
||||
#include "ProtocolTypes.h"
|
||||
|
||||
class CScreen;
|
||||
|
||||
//! Primary screen as pseudo-client
|
||||
/*!
|
||||
The primary screen does not have a client associated with it. This
|
||||
class provides a pseudo-client to allow the primary screen to be
|
||||
treated as if it was a client.
|
||||
*/
|
||||
class CPrimaryClient : public CBaseClientProxy {
|
||||
public:
|
||||
/*!
|
||||
\c name is the name of the server and \p screen is primary screen.
|
||||
*/
|
||||
CPrimaryClient(const CString& name, CScreen* screen);
|
||||
~CPrimaryClient();
|
||||
|
||||
//! @name manipulators
|
||||
//@{
|
||||
|
||||
//! Update configuration
|
||||
/*!
|
||||
Handles reconfiguration of jump zones.
|
||||
*/
|
||||
void reconfigure(UInt32 activeSides);
|
||||
|
||||
//! Register a system hotkey
|
||||
/*!
|
||||
Registers a system-wide hotkey for key \p key with modifiers \p mask.
|
||||
Returns an id used to unregister the hotkey.
|
||||
*/
|
||||
UInt32 registerHotKey(KeyID key, KeyModifierMask mask);
|
||||
|
||||
//! Unregister a system hotkey
|
||||
/*!
|
||||
Unregisters a previously registered hot key.
|
||||
*/
|
||||
void unregisterHotKey(UInt32 id);
|
||||
|
||||
//! Prepare to synthesize input on primary screen
|
||||
/*!
|
||||
Prepares the primary screen to receive synthesized input. We do not
|
||||
want to receive this synthesized input as user input so this method
|
||||
ensures that we ignore it. Calls to \c fakeInputBegin() and
|
||||
\c fakeInputEnd() may be nested; only the outermost have an effect.
|
||||
*/
|
||||
void fakeInputBegin();
|
||||
|
||||
//! Done synthesizing input on primary screen
|
||||
/*!
|
||||
Undoes whatever \c fakeInputBegin() did.
|
||||
*/
|
||||
void fakeInputEnd();
|
||||
|
||||
//@}
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Get jump zone size
|
||||
/*!
|
||||
Return the jump zone size, the size of the regions on the edges of
|
||||
the screen that cause the cursor to jump to another screen.
|
||||
*/
|
||||
SInt32 getJumpZoneSize() const;
|
||||
|
||||
//! Get cursor center position
|
||||
/*!
|
||||
Return the cursor center position which is where we park the
|
||||
cursor to compute cursor motion deltas and should be far from
|
||||
the edges of the screen, typically the center.
|
||||
*/
|
||||
void getCursorCenter(SInt32& x, SInt32& y) const;
|
||||
|
||||
//! Get toggle key state
|
||||
/*!
|
||||
Returns the primary screen's current toggle modifier key state.
|
||||
*/
|
||||
KeyModifierMask getToggleMask() const;
|
||||
|
||||
//! Get screen lock state
|
||||
/*!
|
||||
Returns true if the user is locked to the screen.
|
||||
*/
|
||||
bool isLockedToScreen() const;
|
||||
|
||||
//@}
|
||||
|
||||
// FIXME -- these probably belong on IScreen
|
||||
virtual void enable();
|
||||
virtual void disable();
|
||||
|
||||
// IScreen overrides
|
||||
virtual void* getEventTarget() const;
|
||||
virtual bool getClipboard(ClipboardID id, IClipboard*) const;
|
||||
virtual void getShape(SInt32& x, SInt32& y,
|
||||
SInt32& width, SInt32& height) const;
|
||||
virtual void getCursorPos(SInt32& x, SInt32& y) const;
|
||||
|
||||
// IClient overrides
|
||||
virtual void enter(SInt32 xAbs, SInt32 yAbs,
|
||||
UInt32 seqNum, KeyModifierMask mask,
|
||||
bool forScreensaver);
|
||||
virtual bool leave();
|
||||
virtual void setClipboard(ClipboardID, const IClipboard*);
|
||||
virtual void grabClipboard(ClipboardID);
|
||||
virtual void setClipboardDirty(ClipboardID, bool);
|
||||
virtual void keyDown(KeyID, KeyModifierMask, KeyButton);
|
||||
virtual void keyRepeat(KeyID, KeyModifierMask,
|
||||
SInt32 count, KeyButton);
|
||||
virtual void keyUp(KeyID, KeyModifierMask, KeyButton);
|
||||
virtual void mouseDown(ButtonID);
|
||||
virtual void mouseUp(ButtonID);
|
||||
virtual void mouseMove(SInt32 xAbs, SInt32 yAbs);
|
||||
virtual void mouseRelativeMove(SInt32 xRel, SInt32 yRel);
|
||||
virtual void mouseWheel(SInt32 xDelta, SInt32 yDelta);
|
||||
virtual void screensaver(bool activate);
|
||||
virtual void resetOptions();
|
||||
virtual void setOptions(const COptionsList& options);
|
||||
|
||||
private:
|
||||
CScreen* m_screen;
|
||||
bool m_clipboardDirty[kClipboardEnd];
|
||||
SInt32 m_fakeInputCount;
|
||||
};
|
||||
|
||||
#endif
|
||||
2176
lib/server/CServer.cpp
Normal file
2176
lib/server/CServer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
464
lib/server/CServer.h
Normal file
464
lib/server/CServer.h
Normal file
@@ -0,0 +1,464 @@
|
||||
/*
|
||||
* synergy -- mouse and keyboard sharing utility
|
||||
* Copyright (C) 2002 Chris Schoeneman
|
||||
*
|
||||
* This package is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* found in the file COPYING that should have accompanied this file.
|
||||
*
|
||||
* This package 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.
|
||||
*/
|
||||
|
||||
#ifndef CSERVER_H
|
||||
#define CSERVER_H
|
||||
|
||||
#include "CConfig.h"
|
||||
#include "CClipboard.h"
|
||||
#include "ClipboardTypes.h"
|
||||
#include "KeyTypes.h"
|
||||
#include "MouseTypes.h"
|
||||
#include "CEvent.h"
|
||||
#include "CStopwatch.h"
|
||||
#include "stdmap.h"
|
||||
#include "stdset.h"
|
||||
#include "stdvector.h"
|
||||
|
||||
class CBaseClientProxy;
|
||||
class CEventQueueTimer;
|
||||
class CPrimaryClient;
|
||||
class CInputFilter;
|
||||
|
||||
//! Synergy server
|
||||
/*!
|
||||
This class implements the top-level server algorithms for synergy.
|
||||
*/
|
||||
class CServer {
|
||||
public:
|
||||
//! Lock cursor to screen data
|
||||
class CLockCursorToScreenInfo {
|
||||
public:
|
||||
enum State { kOff, kOn, kToggle };
|
||||
|
||||
static CLockCursorToScreenInfo* alloc(State state = kToggle);
|
||||
|
||||
public:
|
||||
State m_state;
|
||||
};
|
||||
|
||||
//! Switch to screen data
|
||||
class CSwitchToScreenInfo {
|
||||
public:
|
||||
static CSwitchToScreenInfo* alloc(const CString& screen);
|
||||
|
||||
public:
|
||||
// this is a C-string; this type is a variable size structure
|
||||
char m_screen[1];
|
||||
};
|
||||
|
||||
//! Switch in direction data
|
||||
class CSwitchInDirectionInfo {
|
||||
public:
|
||||
static CSwitchInDirectionInfo* alloc(EDirection direction);
|
||||
|
||||
public:
|
||||
EDirection m_direction;
|
||||
};
|
||||
|
||||
//! Screen connected data
|
||||
class CScreenConnectedInfo {
|
||||
public:
|
||||
static CScreenConnectedInfo* alloc(const CString& screen);
|
||||
|
||||
public:
|
||||
// this is a C-string; this type is a variable size structure
|
||||
char m_screen[1];
|
||||
};
|
||||
|
||||
//! Keyboard broadcast data
|
||||
class CKeyboardBroadcastInfo {
|
||||
public:
|
||||
enum State { kOff, kOn, kToggle };
|
||||
|
||||
static CKeyboardBroadcastInfo* alloc(State state = kToggle);
|
||||
static CKeyboardBroadcastInfo* alloc(State state,
|
||||
const CString& screens);
|
||||
|
||||
public:
|
||||
State m_state;
|
||||
char m_screens[1];
|
||||
};
|
||||
|
||||
/*!
|
||||
Start the server with the configuration \p config and the primary
|
||||
client (local screen) \p primaryClient. The client retains
|
||||
ownership of \p primaryClient.
|
||||
*/
|
||||
CServer(const CConfig& config, CPrimaryClient* primaryClient);
|
||||
~CServer();
|
||||
|
||||
//! @name manipulators
|
||||
//@{
|
||||
|
||||
//! Set configuration
|
||||
/*!
|
||||
Change the server's configuration. Returns true iff the new
|
||||
configuration was accepted (it must include the server's name).
|
||||
This will disconnect any clients no longer in the configuration.
|
||||
*/
|
||||
bool setConfig(const CConfig&);
|
||||
|
||||
//! Add a client
|
||||
/*!
|
||||
Adds \p client to the server. The client is adopted and will be
|
||||
destroyed when the client disconnects or is disconnected.
|
||||
*/
|
||||
void adoptClient(CBaseClientProxy* client);
|
||||
|
||||
//! Disconnect clients
|
||||
/*!
|
||||
Disconnect clients. This tells them to disconnect but does not wait
|
||||
for them to actually do so. The server sends the disconnected event
|
||||
when they're all disconnected (or immediately if none are connected).
|
||||
The caller can also just destroy this object to force the disconnection.
|
||||
*/
|
||||
void disconnect();
|
||||
|
||||
//@}
|
||||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Get number of connected clients
|
||||
/*!
|
||||
Returns the number of connected clients, including the server itself.
|
||||
*/
|
||||
UInt32 getNumClients() const;
|
||||
|
||||
//! Get the list of connected clients
|
||||
/*!
|
||||
Set the \c list to the names of the currently connected clients.
|
||||
*/
|
||||
void getClients(std::vector<CString>& list) const;
|
||||
|
||||
//! Get error event type
|
||||
/*!
|
||||
Returns the error event type. This is sent when the server fails
|
||||
for some reason.
|
||||
*/
|
||||
static CEvent::Type getErrorEvent();
|
||||
|
||||
//! Get connected event type
|
||||
/*!
|
||||
Returns the connected event type. This is sent when a client screen
|
||||
has connected. The event data is a \c CScreenConnectedInfo* that
|
||||
indicates the connected screen.
|
||||
*/
|
||||
static CEvent::Type getConnectedEvent();
|
||||
|
||||
//! Get disconnected event type
|
||||
/*!
|
||||
Returns the disconnected event type. This is sent when all the
|
||||
clients have disconnected.
|
||||
*/
|
||||
static CEvent::Type getDisconnectedEvent();
|
||||
|
||||
//! Get switch to screen event type
|
||||
/*!
|
||||
Returns the switch to screen event type. The server responds to this
|
||||
by switching screens. The event data is a \c CSwitchToScreenInfo*
|
||||
that indicates the target screen.
|
||||
*/
|
||||
static CEvent::Type getSwitchToScreenEvent();
|
||||
|
||||
//! Get switch in direction event type
|
||||
/*!
|
||||
Returns the switch in direction event type. The server responds to this
|
||||
by switching screens. The event data is a \c CSwitchInDirectionInfo*
|
||||
that indicates the target direction.
|
||||
*/
|
||||
static CEvent::Type getSwitchInDirectionEvent();
|
||||
|
||||
//! Get keyboard broadcast event type
|
||||
/*!
|
||||
Returns the keyboard broadcast event type. The server responds
|
||||
to this by turning on keyboard broadcasting or turning it off. The
|
||||
event data is a \c CKeyboardBroadcastInfo*.
|
||||
*/
|
||||
static CEvent::Type getKeyboardBroadcastEvent();
|
||||
|
||||
//! Get lock cursor event type
|
||||
/*!
|
||||
Returns the lock cursor event type. The server responds to this
|
||||
by locking the cursor to the active screen or unlocking it. The
|
||||
event data is a \c CLockCursorToScreenInfo*.
|
||||
*/
|
||||
static CEvent::Type getLockCursorToScreenEvent();
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
// get canonical name of client
|
||||
CString getName(const CBaseClientProxy*) const;
|
||||
|
||||
// get the sides of the primary screen that have neighbors
|
||||
UInt32 getActivePrimarySides() const;
|
||||
|
||||
// returns true iff mouse should be locked to the current screen
|
||||
// according to this object only, ignoring what the primary client
|
||||
// says.
|
||||
bool isLockedToScreenServer() const;
|
||||
|
||||
// returns true iff mouse should be locked to the current screen
|
||||
// according to this object or the primary client.
|
||||
bool isLockedToScreen() const;
|
||||
|
||||
// returns the jump zone of the client
|
||||
SInt32 getJumpZoneSize(CBaseClientProxy*) const;
|
||||
|
||||
// change the active screen
|
||||
void switchScreen(CBaseClientProxy*,
|
||||
SInt32 x, SInt32 y, bool forScreenSaver);
|
||||
|
||||
// jump to screen
|
||||
void jumpToScreen(CBaseClientProxy*);
|
||||
|
||||
// convert pixel position to fraction, using x or y depending on the
|
||||
// direction.
|
||||
float mapToFraction(CBaseClientProxy*, EDirection,
|
||||
SInt32 x, SInt32 y) const;
|
||||
|
||||
// convert fraction to pixel position, writing only x or y depending
|
||||
// on the direction.
|
||||
void mapToPixel(CBaseClientProxy*, EDirection, float f,
|
||||
SInt32& x, SInt32& y) const;
|
||||
|
||||
// returns true if the client has a neighbor anywhere along the edge
|
||||
// indicated by the direction.
|
||||
bool hasAnyNeighbor(CBaseClientProxy*, EDirection) const;
|
||||
|
||||
// lookup neighboring screen, mapping the coordinate independent of
|
||||
// the direction to the neighbor's coordinate space.
|
||||
CBaseClientProxy* getNeighbor(CBaseClientProxy*, EDirection,
|
||||
SInt32& x, SInt32& y) const;
|
||||
|
||||
// lookup neighboring screen. given a position relative to the
|
||||
// source screen, find the screen we should move onto and where.
|
||||
// if the position is sufficiently far from the source then we
|
||||
// cross multiple screens. if there is no suitable screen then
|
||||
// return NULL and x,y are not modified.
|
||||
CBaseClientProxy* mapToNeighbor(CBaseClientProxy*, EDirection,
|
||||
SInt32& x, SInt32& y) const;
|
||||
|
||||
// adjusts x and y or neither to avoid ending up in a jump zone
|
||||
// after entering the client in the given direction.
|
||||
void avoidJumpZone(CBaseClientProxy*, EDirection,
|
||||
SInt32& x, SInt32& y) const;
|
||||
|
||||
// test if a switch is permitted. this includes testing user
|
||||
// options like switch delay and tracking any state required to
|
||||
// implement them. returns true iff a switch is permitted.
|
||||
bool isSwitchOkay(CBaseClientProxy* dst, EDirection,
|
||||
SInt32 x, SInt32 y, SInt32 xActive, SInt32 yActive);
|
||||
|
||||
// update switch state due to a mouse move at \p x, \p y that
|
||||
// doesn't switch screens.
|
||||
void noSwitch(SInt32 x, SInt32 y);
|
||||
|
||||
// stop switch timers
|
||||
void stopSwitch();
|
||||
|
||||
// start two tap switch timer
|
||||
void startSwitchTwoTap();
|
||||
|
||||
// arm the two tap switch timer if \p x, \p y is outside the tap zone
|
||||
void armSwitchTwoTap(SInt32 x, SInt32 y);
|
||||
|
||||
// stop the two tap switch timer
|
||||
void stopSwitchTwoTap();
|
||||
|
||||
// returns true iff the two tap switch timer is started
|
||||
bool isSwitchTwoTapStarted() const;
|
||||
|
||||
// returns true iff should switch because of two tap
|
||||
bool shouldSwitchTwoTap() const;
|
||||
|
||||
// start delay switch timer
|
||||
void startSwitchWait(SInt32 x, SInt32 y);
|
||||
|
||||
// stop delay switch timer
|
||||
void stopSwitchWait();
|
||||
|
||||
// returns true iff the delay switch timer is started
|
||||
bool isSwitchWaitStarted() const;
|
||||
|
||||
// returns the corner (EScreenSwitchCornerMasks) where x,y is on the
|
||||
// given client. corners have the given size.
|
||||
UInt32 getCorner(CBaseClientProxy*,
|
||||
SInt32 x, SInt32 y, SInt32 size) const;
|
||||
|
||||
// stop relative mouse moves
|
||||
void stopRelativeMoves();
|
||||
|
||||
// send screen options to \c client
|
||||
void sendOptions(CBaseClientProxy* client) const;
|
||||
|
||||
// process options from configuration
|
||||
void processOptions();
|
||||
|
||||
// event handlers
|
||||
void handleShapeChanged(const CEvent&, void*);
|
||||
void handleClipboardGrabbed(const CEvent&, void*);
|
||||
void handleClipboardChanged(const CEvent&, void*);
|
||||
void handleKeyDownEvent(const CEvent&, void*);
|
||||
void handleKeyUpEvent(const CEvent&, void*);
|
||||
void handleKeyRepeatEvent(const CEvent&, void*);
|
||||
void handleButtonDownEvent(const CEvent&, void*);
|
||||
void handleButtonUpEvent(const CEvent&, void*);
|
||||
void handleMotionPrimaryEvent(const CEvent&, void*);
|
||||
void handleMotionSecondaryEvent(const CEvent&, void*);
|
||||
void handleWheelEvent(const CEvent&, void*);
|
||||
void handleScreensaverActivatedEvent(const CEvent&, void*);
|
||||
void handleScreensaverDeactivatedEvent(const CEvent&, void*);
|
||||
void handleSwitchWaitTimeout(const CEvent&, void*);
|
||||
void handleClientDisconnected(const CEvent&, void*);
|
||||
void handleClientCloseTimeout(const CEvent&, void*);
|
||||
void handleSwitchToScreenEvent(const CEvent&, void*);
|
||||
void handleSwitchInDirectionEvent(const CEvent&, void*);
|
||||
void handleKeyboardBroadcastEvent(const CEvent&,void*);
|
||||
void handleLockCursorToScreenEvent(const CEvent&, void*);
|
||||
void handleFakeInputBeginEvent(const CEvent&, void*);
|
||||
void handleFakeInputEndEvent(const CEvent&, void*);
|
||||
|
||||
// event processing
|
||||
void onClipboardChanged(CBaseClientProxy* sender,
|
||||
ClipboardID id, UInt32 seqNum);
|
||||
void onScreensaver(bool activated);
|
||||
void onKeyDown(KeyID, KeyModifierMask, KeyButton,
|
||||
const char* screens);
|
||||
void onKeyUp(KeyID, KeyModifierMask, KeyButton,
|
||||
const char* screens);
|
||||
void onKeyRepeat(KeyID, KeyModifierMask, SInt32, KeyButton);
|
||||
void onMouseDown(ButtonID);
|
||||
void onMouseUp(ButtonID);
|
||||
bool onMouseMovePrimary(SInt32 x, SInt32 y);
|
||||
void onMouseMoveSecondary(SInt32 dx, SInt32 dy);
|
||||
void onMouseWheel(SInt32 xDelta, SInt32 yDelta);
|
||||
|
||||
// add client to list and attach event handlers for client
|
||||
bool addClient(CBaseClientProxy*);
|
||||
|
||||
// remove client from list and detach event handlers for client
|
||||
bool removeClient(CBaseClientProxy*);
|
||||
|
||||
// close a client
|
||||
void closeClient(CBaseClientProxy*, const char* msg);
|
||||
|
||||
// close clients not in \p config
|
||||
void closeClients(const CConfig& config);
|
||||
|
||||
// close all clients whether they've completed the handshake or not,
|
||||
// except the primary client
|
||||
void closeAllClients();
|
||||
|
||||
// remove clients from internal state
|
||||
void removeActiveClient(CBaseClientProxy*);
|
||||
void removeOldClient(CBaseClientProxy*);
|
||||
|
||||
// force the cursor off of \p client
|
||||
void forceLeaveClient(CBaseClientProxy* client);
|
||||
|
||||
private:
|
||||
class CClipboardInfo {
|
||||
public:
|
||||
CClipboardInfo();
|
||||
|
||||
public:
|
||||
CClipboard m_clipboard;
|
||||
CString m_clipboardData;
|
||||
CString m_clipboardOwner;
|
||||
UInt32 m_clipboardSeqNum;
|
||||
};
|
||||
|
||||
// the primary screen client
|
||||
CPrimaryClient* m_primaryClient;
|
||||
|
||||
// all clients (including the primary client) indexed by name
|
||||
typedef std::map<CString, CBaseClientProxy*> CClientList;
|
||||
typedef std::set<CBaseClientProxy*> CClientSet;
|
||||
CClientList m_clients;
|
||||
CClientSet m_clientSet;
|
||||
|
||||
// all old connections that we're waiting to hangup
|
||||
typedef std::map<CBaseClientProxy*, CEventQueueTimer*> COldClients;
|
||||
COldClients m_oldClients;
|
||||
|
||||
// the client with focus
|
||||
CBaseClientProxy* m_active;
|
||||
|
||||
// the sequence number of enter messages
|
||||
UInt32 m_seqNum;
|
||||
|
||||
// current mouse position (in absolute screen coordinates) on
|
||||
// whichever screen is active
|
||||
SInt32 m_x, m_y;
|
||||
|
||||
// last mouse deltas. this is needed to smooth out double tap
|
||||
// on win32 which reports bogus mouse motion at the edge of
|
||||
// the screen when using low level hooks, synthesizing motion
|
||||
// in the opposite direction the mouse actually moved.
|
||||
SInt32 m_xDelta, m_yDelta;
|
||||
SInt32 m_xDelta2, m_yDelta2;
|
||||
|
||||
// current configuration
|
||||
CConfig m_config;
|
||||
|
||||
// input filter (from m_config);
|
||||
CInputFilter* m_inputFilter;
|
||||
|
||||
// clipboard cache
|
||||
CClipboardInfo m_clipboards[kClipboardEnd];
|
||||
|
||||
// state saved when screen saver activates
|
||||
CBaseClientProxy* m_activeSaver;
|
||||
SInt32 m_xSaver, m_ySaver;
|
||||
|
||||
// common state for screen switch tests. all tests are always
|
||||
// trying to reach the same screen in the same direction.
|
||||
EDirection m_switchDir;
|
||||
CBaseClientProxy* m_switchScreen;
|
||||
|
||||
// state for delayed screen switching
|
||||
double m_switchWaitDelay;
|
||||
CEventQueueTimer* m_switchWaitTimer;
|
||||
SInt32 m_switchWaitX, m_switchWaitY;
|
||||
|
||||
// state for double-tap screen switching
|
||||
double m_switchTwoTapDelay;
|
||||
CStopwatch m_switchTwoTapTimer;
|
||||
bool m_switchTwoTapEngaged;
|
||||
bool m_switchTwoTapArmed;
|
||||
SInt32 m_switchTwoTapZone;
|
||||
|
||||
// relative mouse move option
|
||||
bool m_relativeMoves;
|
||||
|
||||
// flag whether or not we have broadcasting enabled and the screens to
|
||||
// which we should send broadcasted keys.
|
||||
bool m_keyboardBroadcasting;
|
||||
CString m_keyboardBroadcastingScreens;
|
||||
|
||||
// screen locking (former scroll lock)
|
||||
bool m_lockedToScreen;
|
||||
|
||||
static CEvent::Type s_errorEvent;
|
||||
static CEvent::Type s_connectedEvent;
|
||||
static CEvent::Type s_disconnectedEvent;
|
||||
static CEvent::Type s_switchToScreen;
|
||||
static CEvent::Type s_switchInDirection;
|
||||
static CEvent::Type s_keyboardBroadcast;
|
||||
static CEvent::Type s_lockCursorToScreen;
|
||||
};
|
||||
|
||||
#endif
|
||||
60
lib/server/Makefile.am
Normal file
60
lib/server/Makefile.am
Normal file
@@ -0,0 +1,60 @@
|
||||
# synergy -- mouse and keyboard sharing utility
|
||||
# Copyright (C) 2002 Chris Schoeneman
|
||||
#
|
||||
# This package is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# found in the file COPYING that should have accompanied this file.
|
||||
#
|
||||
# This package 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.
|
||||
|
||||
## Process this file with automake to produce Makefile.in
|
||||
NULL =
|
||||
|
||||
EXTRA_DIST = \
|
||||
Makefile.win \
|
||||
$(NULL)
|
||||
|
||||
MAINTAINERCLEANFILES = \
|
||||
Makefile.in \
|
||||
$(NULL)
|
||||
|
||||
noinst_LIBRARIES = libserver.a
|
||||
libserver_a_SOURCES = \
|
||||
CBaseClientProxy.cpp \
|
||||
CClientListener.cpp \
|
||||
CClientProxy.cpp \
|
||||
CClientProxy1_0.cpp \
|
||||
CClientProxy1_1.cpp \
|
||||
CClientProxy1_2.cpp \
|
||||
CClientProxy1_3.cpp \
|
||||
CClientProxyUnknown.cpp \
|
||||
CConfig.cpp \
|
||||
CInputFilter.cpp \
|
||||
CPrimaryClient.cpp \
|
||||
CServer.cpp \
|
||||
CBaseClientProxy.h \
|
||||
CClientListener.h \
|
||||
CClientProxy.h \
|
||||
CClientProxy1_0.h \
|
||||
CClientProxy1_1.h \
|
||||
CClientProxy1_2.h \
|
||||
CClientProxy1_3.h \
|
||||
CClientProxyUnknown.h \
|
||||
CConfig.h \
|
||||
CInputFilter.h \
|
||||
CPrimaryClient.h \
|
||||
CServer.h \
|
||||
$(NULL)
|
||||
INCLUDES = \
|
||||
-I$(top_srcdir)/lib/common \
|
||||
-I$(top_srcdir)/lib/arch \
|
||||
-I$(top_srcdir)/lib/base \
|
||||
-I$(top_srcdir)/lib/mt \
|
||||
-I$(top_srcdir)/lib/io \
|
||||
-I$(top_srcdir)/lib/net \
|
||||
-I$(top_srcdir)/lib/synergy \
|
||||
-I$(top_srcdir)/lib/platform \
|
||||
$(NULL)
|
||||
83
lib/server/Makefile.win
Normal file
83
lib/server/Makefile.win
Normal file
@@ -0,0 +1,83 @@
|
||||
# synergy -- mouse and keyboard sharing utility
|
||||
# Copyright (C) 2007 Chris Schoeneman
|
||||
#
|
||||
# This package is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# found in the file COPYING that should have accompanied this file.
|
||||
#
|
||||
# This package 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.
|
||||
|
||||
LIB_SERVER_SRC = lib\server
|
||||
LIB_SERVER_DST = $(BUILD_DST)\$(LIB_SERVER_SRC)
|
||||
LIB_SERVER_LIB = "$(LIB_SERVER_DST)\server.lib"
|
||||
LIB_SERVER_CPP = \
|
||||
"CBaseClientProxy.cpp" \
|
||||
"CClientListener.cpp" \
|
||||
"CClientProxy.cpp" \
|
||||
"CClientProxy1_0.cpp" \
|
||||
"CClientProxy1_1.cpp" \
|
||||
"CClientProxy1_2.cpp" \
|
||||
"CClientProxy1_3.cpp" \
|
||||
"CClientProxyUnknown.cpp" \
|
||||
"CConfig.cpp" \
|
||||
"CInputFilter.cpp" \
|
||||
"CPrimaryClient.cpp" \
|
||||
"CServer.cpp" \
|
||||
$(NULL)
|
||||
LIB_SERVER_OBJ = \
|
||||
"$(LIB_SERVER_DST)\CBaseClientProxy.obj" \
|
||||
"$(LIB_SERVER_DST)\CClientListener.obj" \
|
||||
"$(LIB_SERVER_DST)\CClientProxy.obj" \
|
||||
"$(LIB_SERVER_DST)\CClientProxy1_0.obj" \
|
||||
"$(LIB_SERVER_DST)\CClientProxy1_1.obj" \
|
||||
"$(LIB_SERVER_DST)\CClientProxy1_2.obj" \
|
||||
"$(LIB_SERVER_DST)\CClientProxy1_3.obj" \
|
||||
"$(LIB_SERVER_DST)\CClientProxyUnknown.obj" \
|
||||
"$(LIB_SERVER_DST)\CConfig.obj" \
|
||||
"$(LIB_SERVER_DST)\CInputFilter.obj" \
|
||||
"$(LIB_SERVER_DST)\CPrimaryClient.obj" \
|
||||
"$(LIB_SERVER_DST)\CServer.obj" \
|
||||
$(NULL)
|
||||
LIB_SERVER_INC = \
|
||||
/I"lib\common" \
|
||||
/I"lib\arch" \
|
||||
/I"lib\base" \
|
||||
/I"lib\mt" \
|
||||
/I"lib\io" \
|
||||
/I"lib\net" \
|
||||
/I"lib\synergy" \
|
||||
/I"lib\platform" \
|
||||
$(NULL)
|
||||
|
||||
CPP_FILES = $(CPP_FILES) $(LIB_SERVER_CPP)
|
||||
OBJ_FILES = $(OBJ_FILES) $(LIB_SERVER_OBJ)
|
||||
LIB_FILES = $(LIB_FILES) $(LIB_SERVER_LIB)
|
||||
|
||||
# Dependency rules
|
||||
$(LIB_SERVER_OBJ): $(AUTODEP)
|
||||
!if EXIST($(LIB_SERVER_DST)\deps.mak)
|
||||
!include $(LIB_SERVER_DST)\deps.mak
|
||||
!endif
|
||||
|
||||
# Build rules. Use batch-mode rules if possible.
|
||||
!if DEFINED(_NMAKE_VER)
|
||||
{$(LIB_SERVER_SRC)\}.cpp{$(LIB_SERVER_DST)\}.obj::
|
||||
!else
|
||||
{$(LIB_SERVER_SRC)\}.cpp{$(LIB_SERVER_DST)\}.obj:
|
||||
!endif
|
||||
@$(ECHO) Compile in $(LIB_SERVER_SRC)
|
||||
-@$(MKDIR) $(LIB_SERVER_DST) 2>NUL:
|
||||
$(cpp) $(cppdebug) $(cppflags) $(cppvarsmt) /showIncludes \
|
||||
$(LIB_SERVER_INC) \
|
||||
/Fo$(LIB_SERVER_DST)\ \
|
||||
/Fd$(LIB_SERVER_LIB:.lib=.pdb) \
|
||||
$< | $(AUTODEP) $(LIB_SERVER_SRC) $(LIB_SERVER_DST)
|
||||
$(LIB_SERVER_LIB): $(LIB_SERVER_OBJ)
|
||||
@$(ECHO) Link $(@F)
|
||||
$(implib) $(ildebug) $(ilflags) \
|
||||
/out:$@ \
|
||||
$**
|
||||
$(AUTODEP) $(LIB_SERVER_SRC) $(LIB_SERVER_DST) $(**:.obj=.d)
|
||||
Reference in New Issue
Block a user