Reorganized source tree. Moved client.cpp into cmd/synergy as

synergy.cpp and server.cpp into cmd/synergyd as synergyd.cpp.
Moved and renamed related files.  Moved remaining source files
into lib/....  Modified and added makefiles as appropriate.
Result is that library files are under lib with each library
in its own directory and program files are under cmd with each
command in its own directory.
This commit is contained in:
crs
2002-07-30 16:52:46 +00:00
parent 9792d35a6b
commit fee4095624
201 changed files with 367 additions and 375 deletions

212
lib/synergy/CClipboard.cpp Normal file
View File

@@ -0,0 +1,212 @@
#include "CClipboard.h"
//
// CClipboard
//
CClipboard::CClipboard() :
m_open(false),
m_owner(false)
{
open(0);
empty();
close();
}
CClipboard::~CClipboard()
{
// do nothing
}
bool
CClipboard::empty()
{
assert(m_open);
// clear all data
for (SInt32 index = 0; index < kNumFormats; ++index) {
m_data[index] = "";
m_added[index] = false;
}
// save time
m_timeOwned = m_time;
// we're the owner now
m_owner = true;
return true;
}
void
CClipboard::add(EFormat format, const CString& data)
{
assert(m_open);
assert(m_owner);
m_data[format] = data;
m_added[format] = true;
}
bool
CClipboard::open(Time time) const
{
assert(!m_open);
m_open = true;
m_time = time;
return true;
}
void
CClipboard::close() const
{
assert(m_open);
m_open = false;
}
CClipboard::Time
CClipboard::getTime() const
{
return m_timeOwned;
}
bool
CClipboard::has(EFormat format) const
{
assert(m_open);
return m_added[format];
}
CString
CClipboard::get(EFormat format) const
{
assert(m_open);
return m_data[format];
}
bool
CClipboard::copy(IClipboard* dst, const IClipboard* src)
{
assert(dst != NULL);
assert(src != NULL);
return copy(dst, src, src->getTime());
}
bool
CClipboard::copy(IClipboard* dst, const IClipboard* src, Time time)
{
assert(dst != NULL);
assert(src != NULL);
bool success = false;
if (src->open(time)) {
if (dst->open(time)) {
if (dst->empty()) {
for (SInt32 format = 0;
format != IClipboard::kNumFormats; ++format) {
IClipboard::EFormat eFormat = (IClipboard::EFormat)format;
if (src->has(eFormat)) {
dst->add(eFormat, src->get(eFormat));
}
}
success = true;
}
dst->close();
}
src->close();
}
return success;
}
void
CClipboard::unmarshall(const CString& data, Time time)
{
const char* index = data.data();
// clear existing data
open(time);
empty();
// read the number of formats
const UInt32 numFormats = readUInt32(index);
index += 4;
// read each format
for (UInt32 i = 0; i < numFormats; ++i) {
// get the format id
UInt32 format = readUInt32(index);
index += 4;
// get the size of the format data
UInt32 size = readUInt32(index);
index += 4;
// save the data if it's a known format. if either the client
// or server supports more clipboard formats than the other
// then one of them will get a format >= kNumFormats here.
if (format < static_cast<UInt32>(IClipboard::kNumFormats)) {
m_added[format] = true;
m_data[format] = CString(index, size);
}
index += size;
}
// done
close();
}
CString
CClipboard::marshall() const
{
CString data;
// compute size of marshalled data
UInt32 size = 4;
UInt32 numFormats = 0;
UInt32 format;
for (format = 0; format != IClipboard::kNumFormats; ++format) {
if (m_added[format]) {
++numFormats;
size += 4 + 4 + m_data[format].size();
}
}
// allocate space
data.reserve(size);
// marshall the data
writeUInt32(&data, numFormats);
for (format = 0; format != IClipboard::kNumFormats; ++format) {
if (m_added[format]) {
writeUInt32(&data, format);
writeUInt32(&data, m_data[format].size());
data += m_data[format];
}
}
return data;
}
UInt32
CClipboard::readUInt32(const char* buf) const
{
const unsigned char* ubuf = reinterpret_cast<const unsigned char*>(buf);
return (static_cast<UInt32>(ubuf[0]) << 24) |
(static_cast<UInt32>(ubuf[1]) << 16) |
(static_cast<UInt32>(ubuf[2]) << 8) |
static_cast<UInt32>(ubuf[3]);
}
void
CClipboard::writeUInt32(CString* buf, UInt32 v) const
{
*buf += static_cast<UInt8>((v >> 24) & 0xff);
*buf += static_cast<UInt8>((v >> 16) & 0xff);
*buf += static_cast<UInt8>((v >> 8) & 0xff);
*buf += static_cast<UInt8>( v & 0xff);
}

79
lib/synergy/CClipboard.h Normal file
View File

@@ -0,0 +1,79 @@
#ifndef CCLIPBOARD_H
#define CCLIPBOARD_H
#include "IClipboard.h"
//! Memory buffer clipboard
/*!
This class implements a clipboard that stores data in memory.
*/
class CClipboard : public IClipboard {
public:
CClipboard();
virtual ~CClipboard();
//! @name manipulators
//@{
//! Unmarshall clipboard data
/*!
Extract marshalled clipboard data and store it in this clipboard.
Sets the clipboard time to \c time.
*/
void unmarshall(const CString& data, Time time);
//@}
//! @name accessors
//@{
//! Marshall clipboard data
/*!
Merge this clipboard's data into a single buffer that can be later
unmarshalled to restore the clipboard and return the buffer.
*/
CString marshall() const;
//! Copy clipboard
/*!
Transfers all the data in one clipboard to another. The
clipboards can be of any concrete clipboard type (and
they don't have to be the same type). This also sets
the destination clipboard's timestamp to source clipboard's
timestamp. Returns true iff the copy succeeded.
*/
static bool copy(IClipboard* dst, const IClipboard* src);
//! Copy clipboard
/*!
Transfers all the data in one clipboard to another. The
clipboards can be of any concrete clipboard type (and they
don't have to be the same type). This also sets the
timestamp to \c time. Returns true iff the copy succeeded.
*/
static bool copy(IClipboard* dst, const IClipboard* src, Time);
//@}
// IClipboard overrides
virtual bool empty();
virtual void add(EFormat, const CString& data);
virtual bool open(Time) const;
virtual void close() const;
virtual Time getTime() const;
virtual bool has(EFormat) const;
virtual CString get(EFormat) const;
private:
UInt32 readUInt32(const char*) const;
void writeUInt32(CString*, UInt32) const;
private:
mutable bool m_open;
mutable Time m_time;
bool m_owner;
Time m_timeOwned;
bool m_added[kNumFormats];
CString m_data[kNumFormats];
};
#endif

View File

@@ -0,0 +1,167 @@
#include "CInputPacketStream.h"
#include "CLock.h"
#include "CStopwatch.h"
//
// CInputPacketStream
//
CInputPacketStream::CInputPacketStream(IInputStream* stream, bool adopt) :
CInputStreamFilter(stream, adopt),
m_mutex(),
m_size(0),
m_buffer(&m_mutex, NULL)
{
// do nothing
}
CInputPacketStream::~CInputPacketStream()
{
// do nothing
}
void
CInputPacketStream::close()
{
getStream()->close();
}
UInt32
CInputPacketStream::read(void* buffer, UInt32 n, double timeout)
{
CLock lock(&m_mutex);
// wait for entire message to be read. return if stream
// hungup or timeout.
switch (waitForFullMessage(timeout)) {
case kData:
break;
case kHungup:
return 0;
case kTimedout:
return (UInt32)-1;
}
// limit number of bytes to read to the number of bytes left in the
// current message.
if (n > m_size) {
n = m_size;
}
// now read from our buffer
n = m_buffer.readNoLock(buffer, n, -1.0);
assert(n <= m_size);
m_size -= n;
return n;
}
UInt32
CInputPacketStream::getSize() const
{
CLock lock(&m_mutex);
return getSizeNoLock();
}
UInt32
CInputPacketStream::getSizeNoLock() const
{
CStopwatch timer(true);
while (!hasFullMessage() && getStream()->getSize() > 0) {
// read more data
if (getMoreMessage(-1.0) != kData) {
// stream hungup
return 0;
}
}
return m_size;
}
CInputPacketStream::EResult
CInputPacketStream::waitForFullMessage(double timeout) const
{
CStopwatch timer(true);
while (!hasFullMessage()) {
// compute remaining timeout
double t = timeout - timer.getTime();
if (timeout >= 0.0 && t <= 0.0) {
// timeout
return kTimedout;
}
// read more data
switch (getMoreMessage(t)) {
case kData:
break;
case kHungup:
// stream hungup
return kHungup;
case kTimedout:
// stream timed out
return kTimedout;
}
}
return kData;
}
CInputPacketStream::EResult
CInputPacketStream::getMoreMessage(double timeout) const
{
// read more data
char buffer[4096];
UInt32 n = getStream()->read(buffer, sizeof(buffer), timeout);
// return if stream timed out
if (n == (UInt32)-1) {
return kTimedout;
}
// return if stream hungup
if (n == 0) {
m_buffer.hangup();
return kHungup;
}
// append to our buffer
m_buffer.write(buffer, n);
return kData;
}
bool
CInputPacketStream::hasFullMessage() const
{
// get payload length if we don't have it yet
if (m_size == 0) {
// check if length field has been read yet
if (m_buffer.getSizeNoLock() < 4) {
// not enough data for payload length
return false;
}
// save payload length
UInt8 buffer[4];
UInt32 n = m_buffer.readNoLock(buffer, sizeof(buffer), -1.0);
assert(n == 4);
m_size = ((UInt32)buffer[0] << 24) |
((UInt32)buffer[1] << 16) |
((UInt32)buffer[2] << 8) |
(UInt32)buffer[3];
// if payload length is zero then discard null message
if (m_size == 0) {
return false;
}
}
assert(m_size > 0);
// we have the full message when we have at least m_size bytes in
// the buffer
return (m_buffer.getSizeNoLock() >= m_size);
}

View File

@@ -0,0 +1,37 @@
#ifndef CINPUTPACKETSTREAM_H
#define CINPUTPACKETSTREAM_H
#include "CInputStreamFilter.h"
#include "CBufferedInputStream.h"
#include "CMutex.h"
//! Packetizing input stream filter
/*!
Filters an input stream to extract packet by packet.
*/
class CInputPacketStream : public CInputStreamFilter {
public:
CInputPacketStream(IInputStream*, bool adoptStream = true);
~CInputPacketStream();
// IInputStream overrides
virtual void close();
virtual UInt32 read(void*, UInt32 maxCount, double timeout);
virtual UInt32 getSize() const;
private:
enum EResult { kData, kHungup, kTimedout };
UInt32 getSizeNoLock() const;
EResult waitForFullMessage(double timeout) const;
EResult getMoreMessage(double timeout) const;
bool hasFullMessage() const;
private:
CMutex m_mutex;
mutable UInt32 m_size;
mutable CBufferedInputStream m_buffer;
};
#endif

View File

@@ -0,0 +1,58 @@
#include "COutputPacketStream.h"
//
// COuputPacketStream
//
COutputPacketStream::COutputPacketStream(IOutputStream* stream, bool adopt) :
COutputStreamFilter(stream, adopt)
{
// do nothing
}
COutputPacketStream::~COutputPacketStream()
{
// do nothing
}
void
COutputPacketStream::close()
{
getStream()->close();
}
UInt32
COutputPacketStream::write(const void* buffer, UInt32 count)
{
// write the length of the payload
UInt8 length[4];
length[0] = (UInt8)((count >> 24) & 0xff);
length[1] = (UInt8)((count >> 16) & 0xff);
length[2] = (UInt8)((count >> 8) & 0xff);
length[3] = (UInt8)( count & 0xff);
UInt32 count2 = sizeof(length);
const UInt8* cbuffer = length;
while (count2 > 0) {
UInt32 n = getStream()->write(cbuffer, count2);
cbuffer += n;
count2 -= n;
}
// write the payload
count2 = count;
cbuffer = reinterpret_cast<const UInt8*>(buffer);
while (count2 > 0) {
UInt32 n = getStream()->write(cbuffer, count2);
cbuffer += n;
count2 -= n;
}
return count;
}
void
COutputPacketStream::flush()
{
getStream()->flush();
}

View File

@@ -0,0 +1,22 @@
#ifndef COUTPUTPACKETSTREAM_H
#define COUTPUTPACKETSTREAM_H
#include "COutputStreamFilter.h"
//! Packetizing output stream filter
/*!
Filters an output stream to create packets that include message
boundaries. Each write() is considered a single packet.
*/
class COutputPacketStream : public COutputStreamFilter {
public:
COutputPacketStream(IOutputStream*, bool adoptStream = true);
~COutputPacketStream();
// IOutputStream overrides
virtual void close();
virtual UInt32 write(const void*, UInt32 count);
virtual void flush();
};
#endif

View File

@@ -0,0 +1,374 @@
#include "CProtocolUtil.h"
#include "IInputStream.h"
#include "IOutputStream.h"
#include "CLog.h"
#include <cctype>
#include <cstring>
//
// CProtocolUtil
//
void
CProtocolUtil::writef(IOutputStream* stream, const char* fmt, ...)
{
assert(stream != NULL);
assert(fmt != NULL);
log((CLOG_DEBUG2 "writef(%s)", fmt));
va_list args;
// determine total size to write
va_start(args, fmt);
UInt32 count = getLength(fmt, args);
va_end(args);
// done if nothing to write
if (count == 0) {
return;
}
// fill buffer
UInt8* buffer = new UInt8[count];
va_start(args, fmt);
writef(buffer, fmt, args);
va_end(args);
// write buffer
UInt8* scan = buffer;
while (count > 0) {
const UInt32 n = stream->write(scan, count);
log((CLOG_DEBUG2 "wrote %d of %d bytes", n, count));
count -= n;
scan += n;
}
delete[] buffer;
}
void
CProtocolUtil::readf(IInputStream* stream, const char* fmt, ...)
{
assert(stream != NULL);
assert(fmt != NULL);
log((CLOG_DEBUG2 "readf(%s)", fmt));
va_list args;
va_start(args, fmt);
// begin scanning
while (*fmt) {
if (*fmt == '%') {
// format specifier. determine argument size.
++fmt;
UInt32 len = eatLength(&fmt);
switch (*fmt) {
case 'i': {
// check for valid length
assert(len == 1 || len == 2 || len == 4);
// read the data
UInt8 buffer[4];
read(stream, buffer, len);
// convert it
void* v = va_arg(args, void*);
switch (len) {
case 1:
// 1 byte integer
*reinterpret_cast<UInt8*>(v) = buffer[0];
log((CLOG_DEBUG2 "readf: read %d byte integer: %d (0x%x)", len, *reinterpret_cast<UInt8*>(v), *reinterpret_cast<UInt8*>(v)));
break;
case 2:
// 2 byte integer
*reinterpret_cast<UInt16*>(v) =
static_cast<UInt16>(
(static_cast<UInt16>(buffer[0]) << 8) |
static_cast<UInt16>(buffer[1]));
log((CLOG_DEBUG2 "readf: read %d byte integer: %d (0x%x)", len, *reinterpret_cast<UInt16*>(v), *reinterpret_cast<UInt16*>(v)));
break;
case 4:
// 4 byte integer
*reinterpret_cast<UInt32*>(v) =
(static_cast<UInt32>(buffer[0]) << 24) |
(static_cast<UInt32>(buffer[1]) << 16) |
(static_cast<UInt32>(buffer[2]) << 8) |
static_cast<UInt32>(buffer[3]);
log((CLOG_DEBUG2 "readf: read %d byte integer: %d (0x%x)", len, *reinterpret_cast<UInt32*>(v), *reinterpret_cast<UInt32*>(v)));
break;
}
break;
}
case 's': {
assert(len == 0);
// read the string length
UInt8 buffer[128];
read(stream, buffer, 4);
UInt32 len = (static_cast<UInt32>(buffer[0]) << 24) |
(static_cast<UInt32>(buffer[1]) << 16) |
(static_cast<UInt32>(buffer[2]) << 8) |
static_cast<UInt32>(buffer[3]);
// use a fixed size buffer if its big enough
const bool useFixed = (len <= sizeof(buffer));
// allocate a buffer to read the data
UInt8* sBuffer;
if (useFixed) {
sBuffer = buffer;
}
else {
sBuffer = new UInt8[len];
}
// read the data
try {
read(stream, sBuffer, len);
}
catch (...) {
if (!useFixed) {
delete[] sBuffer;
}
throw;
}
log((CLOG_DEBUG2 "readf: read %d byte string: %.*s", len, len, sBuffer));
// save the data
CString* dst = va_arg(args, CString*);
dst->assign((const char*)sBuffer, len);
// release the buffer
if (!useFixed) {
delete[] sBuffer;
}
break;
}
case '%':
assert(len == 0);
break;
default:
assert(0 && "invalid format specifier");
}
// next format character
++fmt;
}
else {
// read next character
char buffer[1];
read(stream, buffer, 1);
// verify match
if (buffer[0] != *fmt) {
log((CLOG_DEBUG2 "readf: format mismatch: %c vs %c", *fmt, buffer[0]));
throw XIOReadMismatch();
}
// next format character
++fmt;
}
}
va_end(args);
}
UInt32
CProtocolUtil::getLength(const char* fmt, va_list args)
{
UInt32 n = 0;
while (*fmt) {
if (*fmt == '%') {
// format specifier. determine argument size.
++fmt;
UInt32 len = eatLength(&fmt);
switch (*fmt) {
case 'i':
assert(len == 1 || len == 2 || len == 4);
(void)va_arg(args, UInt32);
break;
case 's':
assert(len == 0);
len = (va_arg(args, CString*))->size() + 4;
(void)va_arg(args, UInt8*);
break;
case 'S':
assert(len == 0);
len = va_arg(args, UInt32) + 4;
(void)va_arg(args, UInt8*);
break;
case '%':
assert(len == 0);
len = 1;
break;
default:
assert(0 && "invalid format specifier");
}
// accumulate size
n += len;
++fmt;
}
else {
// regular character
++n;
++fmt;
}
}
return n;
}
void
CProtocolUtil::writef(void* buffer, const char* fmt, va_list args)
{
UInt8* dst = reinterpret_cast<UInt8*>(buffer);
while (*fmt) {
if (*fmt == '%') {
// format specifier. determine argument size.
++fmt;
UInt32 len = eatLength(&fmt);
switch (*fmt) {
case 'i': {
const UInt32 v = va_arg(args, UInt32);
switch (len) {
case 1:
// 1 byte integer
*dst++ = static_cast<UInt8>(v & 0xff);
break;
case 2:
// 2 byte integer
*dst++ = static_cast<UInt8>((v >> 8) & 0xff);
*dst++ = static_cast<UInt8>( v & 0xff);
break;
case 4:
// 4 byte integer
*dst++ = static_cast<UInt8>((v >> 24) & 0xff);
*dst++ = static_cast<UInt8>((v >> 16) & 0xff);
*dst++ = static_cast<UInt8>((v >> 8) & 0xff);
*dst++ = static_cast<UInt8>( v & 0xff);
break;
default:
assert(0 && "invalid integer format length");
return;
}
break;
}
case 's': {
assert(len == 0);
const CString* src = va_arg(args, CString*);
const UInt32 len = (src != NULL) ? src->size() : 0;
*dst++ = static_cast<UInt8>((len >> 24) & 0xff);
*dst++ = static_cast<UInt8>((len >> 16) & 0xff);
*dst++ = static_cast<UInt8>((len >> 8) & 0xff);
*dst++ = static_cast<UInt8>( len & 0xff);
if (len != 0) {
memcpy(dst, src->data(), len);
dst += len;
}
break;
}
case 'S': {
assert(len == 0);
const UInt32 len = va_arg(args, UInt32);
const UInt8* src = va_arg(args, UInt8*);
*dst++ = static_cast<UInt8>((len >> 24) & 0xff);
*dst++ = static_cast<UInt8>((len >> 16) & 0xff);
*dst++ = static_cast<UInt8>((len >> 8) & 0xff);
*dst++ = static_cast<UInt8>( len & 0xff);
memcpy(dst, src, len);
dst += len;
break;
}
case '%':
assert(len == 0);
*dst++ = '%';
break;
default:
assert(0 && "invalid format specifier");
}
// next format character
++fmt;
}
else {
// copy regular character
*dst++ = *fmt++;
}
}
}
UInt32
CProtocolUtil::eatLength(const char** pfmt)
{
const char* fmt = *pfmt;
UInt32 n = 0;
for (;;) {
UInt32 d;
switch (*fmt) {
case '0': d = 0; break;
case '1': d = 1; break;
case '2': d = 2; break;
case '3': d = 3; break;
case '4': d = 4; break;
case '5': d = 5; break;
case '6': d = 6; break;
case '7': d = 7; break;
case '8': d = 8; break;
case '9': d = 9; break;
default: *pfmt = fmt; return n;
}
n = 10 * n + d;
++fmt;
}
}
void
CProtocolUtil::read(IInputStream* stream, void* vbuffer, UInt32 count)
{
assert(stream != NULL);
assert(vbuffer != NULL);
UInt8* buffer = reinterpret_cast<UInt8*>(vbuffer);
while (count > 0) {
// read more
UInt32 n = stream->read(buffer, count, -1.0);
// bail if stream has hungup
if (n == 0) {
log((CLOG_DEBUG2 "unexpected disconnect in readf(), %d bytes left", count));
throw XIOEndOfStream();
}
// prepare for next read
buffer += n;
count -= n;
}
}
//
// XIOReadMismatch
//
CString
XIOReadMismatch::getWhat() const throw()
{
return format("XIOReadMismatch", "CProtocolUtil::readf() mismatch");
}

View File

@@ -0,0 +1,70 @@
#ifndef CPROTOCOLUTIL_H
#define CPROTOCOLUTIL_H
#include "BasicTypes.h"
#include "XIO.h"
#include <stdarg.h>
class IInputStream;
class IOutputStream;
//! Synergy protocol utilities
/*!
This class provides various functions for implementing the synergy
protocol.
*/
class CProtocolUtil {
public:
//! Write formatted data
/*!
Write formatted binary data to a stream. \c fmt consists of
regular characters and format specifiers. Format specifiers
begin with \%. All characters not part of a format specifier
are regular and are transmitted unchanged.
Format specifiers are:
- \%\% -- literal `\%'
- \%1i -- converts integer argument to 1 byte integer
- \%2i -- converts integer argument to 2 byte integer in NBO
- \%4i -- converts integer argument to 4 byte integer in NBO
- \%s -- converts CString* to stream of bytes
- \%S -- converts integer N and const UInt8* to stream of N bytes
*/
static void writef(IOutputStream*,
const char* fmt, ...);
//! Read formatted data
/*!
Read formatted binary data from a buffer. This performs the
reverse operation of writef().
Format specifiers are:
- \%\% -- read (and discard) a literal `\%'
- \%1i -- reads a 1 byte integer; argument is a SInt32* or UInt32*
- \%2i -- reads an NBO 2 byte integer; arg is SInt32* or UInt32*
- \%4i -- reads an NBO 4 byte integer; arg is SInt32* or UInt32*
- \%s -- reads bytes; argument must be a CString*, \b not a char*
*/
static void readf(IInputStream*,
const char* fmt, ...);
private:
static UInt32 getLength(const char* fmt, va_list);
static void writef(void*, const char* fmt, va_list);
static UInt32 eatLength(const char** fmt);
static void read(IInputStream*, void*, UInt32);
};
//! Mismatched read exception
/*!
Thrown by CProtocolUtil::readf() when the data being read does not
match the format.
*/
class XIOReadMismatch : public XIO {
public:
// XBase overrides
virtual CString getWhat() const throw();
};
#endif

View File

@@ -0,0 +1,29 @@
#include "CTCPSocketFactory.h"
#include "CTCPSocket.h"
#include "CTCPListenSocket.h"
//
// CTCPSocketFactory
//
CTCPSocketFactory::CTCPSocketFactory()
{
// do nothing
}
CTCPSocketFactory::~CTCPSocketFactory()
{
// do nothing
}
IDataSocket*
CTCPSocketFactory::create() const
{
return new CTCPSocket;
}
IListenSocket*
CTCPSocketFactory::createListen() const
{
return new CTCPListenSocket;
}

View File

@@ -0,0 +1,17 @@
#ifndef CTCPSOCKETFACTORY_H
#define CTCPSOCKETFACTORY_H
#include "ISocketFactory.h"
//! Socket factory for TCP sockets
class CTCPSocketFactory : public ISocketFactory {
public:
CTCPSocketFactory();
virtual ~CTCPSocketFactory();
// ISocketFactory overrides
virtual IDataSocket* create() const;
virtual IListenSocket* createListen() const;
};
#endif

View File

@@ -0,0 +1,27 @@
#ifndef CLIPBOARDTYPES_H
#define CLIPBOARDTYPES_H
#include "BasicTypes.h"
//! Clipboard ID
/*!
Type to hold a clipboard identifier.
*/
typedef UInt8 ClipboardID;
//! @name Clipboard identifiers
//@{
// clipboard identifiers. kClipboardClipboard is what is normally
// considered the clipboard (e.g. the cut/copy/paste menu items
// affect it). kClipboardSelection is the selection on those
// platforms that can treat the selection as a clipboard (e.g. X
// windows). clipboard identifiers must be sequential starting
// at zero.
static const ClipboardID kClipboardClipboard = 0;
static const ClipboardID kClipboardSelection = 1;
// the number of clipboards (i.e. one greater than the last clipboard id)
static const ClipboardID kClipboardEnd = 2;
//@}
#endif

179
lib/synergy/IClient.h Normal file
View File

@@ -0,0 +1,179 @@
#ifndef ICLIENT_H
#define ICLIENT_H
#include "IInterface.h"
#include "ClipboardTypes.h"
#include "KeyTypes.h"
#include "MouseTypes.h"
#include "CString.h"
//! Client interface
/*!
This interface defines the methods necessary for the server to
communicate with a client.
*/
class IClient : public IInterface {
public:
//! @name manipulators
//@{
//! Open client
/*!
Open the client and return true iff successful.
*/
virtual bool open() = 0;
//! Client main loop
/*!
Run client's event loop. This method is typically called in a
separate thread and is exited by cancelling the thread. This
must be called between a successful open() and close().
(cancellation point)
*/
virtual void mainLoop() = 0;
//! Close client
/*!
Close the client.
*/
virtual void close() = 0;
//! Enter screen
/*!
Enter the screen. The cursor should be warped to \c xAbs,yAbs.
The client should record seqNum for future reporting of
clipboard changes. \c mask is the expected toggle button state
and the client should update its state to match. \c forScreensaver
is true iff the screen is being entered because the screen saver is
starting.
*/
virtual void enter(SInt32 xAbs, SInt32 yAbs,
UInt32 seqNum, KeyModifierMask mask,
bool forScreensaver) = 0;
//! Leave screen
/*!
Leave the screen. Return false iff the user may not leave the
client's screen (because, for example, a button is down).
*/
virtual bool leave() = 0;
//! Set clipboard
/*!
Update the client's clipboard. This implies that the client's
clipboard is now up to date. If the client's clipboard was
already known to be up to date then this may do nothing. \c data
has marshalled clipboard data.
*/
virtual void setClipboard(ClipboardID, const CString& data) = 0;
//! Grab clipboard
/*!
Grab (i.e. take ownership of) the client's clipboard. Since this
is called when another client takes ownership of the clipboard it
implies that the client's clipboard is out of date.
*/
virtual void grabClipboard(ClipboardID) = 0;
//! Mark clipboard dirty
/*!
Mark the client's clipboard as dirty (out of date) or clean (up to
date).
*/
virtual void setClipboardDirty(ClipboardID, bool dirty) = 0;
//! Notify of key press
/*!
Synthesize key events to generate a press of key \c id. If possible
match the given modifier mask.
*/
virtual void keyDown(KeyID id, KeyModifierMask) = 0;
//! Notify of key repeat
/*!
Synthesize key events to generate a press and release of key \c id
\c count times. If possible match the given modifier mask.
*/
virtual void keyRepeat(KeyID id, KeyModifierMask, SInt32 count) = 0;
//! Notify of key release
/*!
Synthesize key events to generate a release of key \c id. If possible
match the given modifier mask.
*/
virtual void keyUp(KeyID id, KeyModifierMask) = 0;
//! Notify of mouse press
/*!
Synthesize mouse events to generate a press of mouse button \c id.
*/
virtual void mouseDown(ButtonID id) = 0;
//! Notify of mouse release
/*!
Synthesize mouse events to generate a release of mouse button \c id.
*/
virtual void mouseUp(ButtonID id) = 0;
//! Notify of mouse motion
/*!
Synthesize mouse events to generate mouse motion to the absolute
screen position \c xAbs,yAbs.
*/
virtual void mouseMove(SInt32 xAbs, SInt32 yAbs) = 0;
//! Notify of mouse wheel motion
/*!
Synthesize mouse events to generate mouse wheel motion of \c delta.
\c delta is positive for motion away from the user and negative for
motion towards the user. Each wheel click should generate a delta
of +/-120.
*/
virtual void mouseWheel(SInt32 delta) = 0;
//! Notify of screen saver change
virtual void screensaver(bool activate) = 0;
//@}
//! @name accessors
//@{
//! Get client name
/*!
Return the client's name.
*/
virtual CString getName() const = 0;
//! Get jump zone size
/*!
Called to get the jump zone size.
*/
virtual SInt32 getJumpZoneSize() const = 0;
//! Get screen shape
/*!
Return the position of the upper-left corner of the screen in \c x and
\c y and the size of the screen in \c width and \c height.
*/
virtual void getShape(SInt32& x, SInt32& y,
SInt32& width, SInt32& height) const = 0;
//! Get cursor position
/*!
Return the current position of the cursor in \c x and \c y.
*/
virtual void getCursorPos(SInt32& x, SInt32& y) const = 0;
//! 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.
*/
virtual void getCursorCenter(SInt32& x, SInt32& y) const = 0;
//@}
};
#endif

103
lib/synergy/IClipboard.h Normal file
View File

@@ -0,0 +1,103 @@
#ifndef ICLIPBOARD_H
#define ICLIPBOARD_H
#include "IInterface.h"
#include "CString.h"
#include "BasicTypes.h"
//! Clipboard interface
/*!
This interface defines the methods common to all clipboards.
*/
class IClipboard : public IInterface {
public:
//! Timestamp type
/*!
Timestamp type. Timestamps are in milliseconds from some
arbitrary starting time. Timestamps will wrap around to 0
after about 49 3/4 days.
*/
typedef UInt32 Time;
//! Clipboard formats
/*!
The list of known clipboard formats. kNumFormats must be last and
formats must be sequential starting from zero. Clipboard data set
via add() and retrieved via get() must be in one of these formats.
Platform dependent clipboard subclasses can and should present any
suitable formats derivable from these formats.
*/
enum EFormat {
kText, //!< Text format, UTF-8, newline is LF
kNumFormats //!< The number of clipboard formats
};
//! @name manipulators
//@{
//! Empty clipboard
/*!
Take ownership of the clipboard and clear all data from it.
This must be called between a successful open() and close().
Return false if the clipboard ownership could not be taken;
the clipboard should not be emptied in this case.
*/
virtual bool empty() = 0;
//! Add data
/*!
Add data in the given format to the clipboard. May only be
called after a successful empty().
*/
virtual void add(EFormat, const CString& data) = 0;
//@}
//! @name accessors
//@{
//! Open clipboard
/*!
Open the clipboard. Return true iff the clipboard could be
opened. If open() returns true then the client must call
close() at some later time; if it returns false then close()
must not be called. \c time should be the current time or
a time in the past when the open should effectively have taken
place.
*/
virtual bool open(Time time) const = 0;
//! Close clipboard
/*!
Close the clipboard. close() must match a preceding successful
open(). This signals that the clipboard has been filled with
all the necessary data or all data has been read. It does not
mean the clipboard ownership should be released (if it was
taken).
*/
virtual void close() const = 0;
//! Get time
/*!
Return the timestamp passed to the last successful open().
*/
virtual Time getTime() const = 0;
//! Check for data
/*!
Return true iff the clipboard contains data in the given
format. Must be called between a successful open() and close().
*/
virtual bool has(EFormat) const = 0;
//! Get data
/*!
Return the data in the given format. Returns the empty string
if there is no data in that format. Must be called between
a successful open() and close().
*/
virtual CString get(EFormat) const = 0;
//@}
};
#endif

View File

@@ -0,0 +1,52 @@
#ifndef IPRIMARYSCREENRECEIVER_H
#define IPRIMARYSCREENRECEIVER_H
#include "IInterface.h"
#include "KeyTypes.h"
#include "MouseTypes.h"
//! Primary screen event receiver interface
/*!
The interface for receiving notification of events on the primary
screen. The server implements this interface to handle user input.
Platform dependent primary screen implementation will need to take
an IPrimaryScreenReceiver* and notify it of events.
*/
class IPrimaryScreenReceiver : public IInterface {
public:
//! Notify of screen saver change
/*!
Called when the screensaver is activated or deactivated.
*/
virtual void onScreensaver(bool activated) = 0;
// call to notify of events. onMouseMovePrimary() returns
// true iff the mouse enters a jump zone and jumps.
//! Notify of key press
virtual void onKeyDown(KeyID, KeyModifierMask) = 0;
//! Notify of key release
virtual void onKeyUp(KeyID, KeyModifierMask) = 0;
//! Notify of key repeat
virtual void onKeyRepeat(KeyID, KeyModifierMask, SInt32 count) = 0;
//! Notify of mouse button press
virtual void onMouseDown(ButtonID) = 0;
//! Notify of mouse button release
virtual void onMouseUp(ButtonID) = 0;
//! Notify of mouse motion
/*!
Called when the mouse has moved while on the primary screen. \c x
and \c y are the absolute screen position of the mouse. Return
true iff the mouse enters a jump zone and jumps.
*/
virtual bool onMouseMovePrimary(SInt32 x, SInt32 y) = 0;
//! Notify of mouse motion
/*!
Called when the mouse has moved while on the secondary screen.
\c dx and \c dy are the relative motion from the last position.
*/
virtual void onMouseMoveSecondary(SInt32 dx, SInt32 dy) = 0;
//! Notify of mouse wheen motion
virtual void onMouseWheel(SInt32 delta) = 0;
};
#endif

134
lib/synergy/IScreen.h Normal file
View File

@@ -0,0 +1,134 @@
#ifndef ISCREEN_H
#define ISCREEN_H
#include "IInterface.h"
#include "ClipboardTypes.h"
class IClipboard;
//! Screen interface
/*!
This interface defines the methods common to all platform dependent
screen implementations that are use by both primary and secondary
screens.
*/
class IScreen : public IInterface {
public:
//! @name manipulators
//@{
//! Open screen
/*!
Called to open and initialize the screen.
*/
virtual void open() = 0;
//! Run event loop
/*!
Run the event loop and return when exitMainLoop() is called.
This must be called between a successful open() and close().
*/
virtual void mainLoop() = 0;
//! Exit event loop
/*!
Force mainLoop() to return. This call can return before
mainLoop() does (i.e. asynchronously). This may only be
called between a successful open() and close().
*/
virtual void exitMainLoop() = 0;
//! Close screen
/*!
Called to close the screen. close() should quietly ignore calls
that don't have a matching successful call to open().
*/
virtual void close() = 0;
//! Set clipboard
/*!
Set the contents of the system clipboard indicated by \c id.
*/
virtual bool setClipboard(ClipboardID id, const IClipboard*) = 0;
//! Check clipboard owner
/*!
Check ownership of all clipboards and notify an IScreenReceiver (set
through some other interface) if any changed. This is used as a
backup in case the system doesn't reliably report clipboard ownership
changes.
*/
virtual void checkClipboards() = 0;
//! Open screen saver
/*!
Open the screen saver. If \c notify is true then this object must
call an IScreenEventHandler's (set through some other interface)
onScreenSaver() when the screensaver activates or deactivates until
it's closed. If \c notify is false then the screen saver is
disabled on open and restored on close.
*/
virtual void openScreensaver(bool notify) = 0;
//! Close screen saver
/*!
// Close the screen saver. Stop reporting screen saver activation
and deactivation and, if the screen saver was disabled by
openScreensaver(), enable the screen saver.
*/
virtual void closeScreensaver() = 0;
//! Activate/deactivate screen saver
/*!
Forcibly activate the screen saver if \c activate is true otherwise
forcibly deactivate it.
*/
virtual void screensaver(bool activate) = 0;
//! Attach to desktop
/*!
Called to ensure that this thread is attached to the visible desktop.
This is mainly intended for microsoft windows which has an artificial
distinction between desktops where a thread cannot interact with the
visible desktop unless the thread is attached to that desktop. Since
it doesn't report when the visible desktop changes we must poll.
*/
virtual void syncDesktop() = 0;
//@}
//! @name accessors
//@{
//! Get clipboard
/*!
Save the contents of the clipboard indicated by \c id and return
true iff successful.
*/
virtual bool getClipboard(ClipboardID id, IClipboard*) const = 0;
//! Get screen shape
/*!
Return the position of the upper-left corner of the screen in \c x and
\c y and the size of the screen in \c w (width) and \c h (height).
*/
virtual void getShape(SInt32& x, SInt32& y,
SInt32& w, SInt32& h) const = 0;
//! Get cursor position
/*!
Return the current position of the cursor in \c x and \c y.
*/
virtual void getCursorPos(SInt32& x, SInt32& y) const = 0;
//! 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.
*/
virtual void getCursorCenter(SInt32& x, SInt32& y) const = 0;
//@}
};
#endif

View File

@@ -0,0 +1,59 @@
#ifndef ISCREENEVENTHANDLER_H
#define ISCREENEVENTHANDLER_H
#include "IInterface.h"
// the platform screen should define this
class CEvent;
class IScreen;
//! Screen event handler interface
/*!
This is the interface through which IScreen sends notification of events.
Each platform will derive two types from IScreenEventHandler, one
for handling events on the primary screen and one for the
secondary screen. The header file with the IScreen subclass for
each platform should define the CEvent type, which depends on the
type of native events for that platform.
*/
class IScreenEventHandler : public IInterface {
public:
//! @name manipulators
//@{
//! Notify of screen saver change
/*!
Called when the screensaver is activated or deactivated.
*/
virtual void onScreensaver(bool activated) = 0;
//! Event filtering
/*!
Called for each event before event translation and dispatch. Return
true to skip translation and dispatch. Subclasses should call the
superclass's version first and return true if it returns true.
*/
virtual bool onPreDispatch(const CEvent* event) = 0;
//! Event handling
/*!
Called to handle an event. Iff the event was handled return true and
store the result, if any, in event->m_result, which defaults to zero.
*/
virtual bool onEvent(CEvent* event) = 0;
//@}
//! @name accessors
//@{
//! Get jump zone size
/*!
Called to get the jump zone size.
*/
virtual SInt32 getJumpZoneSize() const = 0;
//@}
};
#endif

View File

@@ -0,0 +1,51 @@
#ifndef ISCREENRECEIVER_H
#define ISCREENRECEIVER_H
#include "IInterface.h"
#include "ClipboardTypes.h"
#include "ProtocolTypes.h"
#include "CString.h"
//! Screen event receiver interface
/*!
This interface defines the methods common to most types that receive
events for changes to a screen. Note that the methods in this
interface are similar to the methods in IServer but have different
parameters. This interface is suitable for client-side types.
*/
class IScreenReceiver : public IInterface {
public:
//! Notify of error
/*!
Called when the screen is unexpectedly closing. This implies that
the screen is no longer usable and that the program should close
the screen and probably terminate.
*/
virtual void onError() = 0;
//! Notify of client screen change
/*!
Called when the client's info has changed. For example, when the
screen resolution has changed.
*/
virtual void onInfoChanged(const CClientInfo&) = 0;
//! Notify of clipboad grab
/*!
Called when the clipboard was grabbed by another program and,
therefore, we no longer own it. Returns true if the grab was
honored, false otherwise.
*/
virtual bool onGrabClipboard(ClipboardID) = 0;
//! Notify of new clipboard data
/*!
Called when the data on the clipboard has changed because some
other program has changed it. \c data will have marshalled
clipboard data.
*/
virtual void onClipboardChanged(ClipboardID,
const CString& data) = 0;
};
#endif

View File

@@ -0,0 +1,59 @@
#ifndef ISCREENSAVER_H
#define ISCREENSAVER_H
#include "IInterface.h"
//! Screen saver interface
/*!
This interface defines the methods common to all screen savers.
*/
class IScreenSaver : public IInterface {
public:
// note -- the c'tor/d'tor must *not* enable/disable the screen saver
//! @name manipulators
//@{
//! Enable screen saver
/*!
Enable the screen saver, restoring the screen saver settings to
what they were when disable() was previously called. If disable()
wasn't previously called then it should keep the current settings
or use reasonable defaults.
*/
virtual void enable() = 0;
//! Disable screen saver
/*!
Disable the screen saver, saving the old settings for the next
call to enable().
*/
virtual void disable() = 0;
//! Activate screen saver
/*!
Activate (i.e. show) the screen saver.
*/
virtual void activate() = 0;
//! Deactivate screen saver
/*!
Deactivate (i.e. hide) the screen saver, reseting the screen saver
timer.
*/
virtual void deactivate() = 0;
//@}
//! @name accessors
//@{
//! Test if screen saver on
/*!
Returns true iff the screen saver is currently active (showing).
*/
virtual bool isActive() const = 0;
//@}
};
#endif

61
lib/synergy/IServer.h Normal file
View File

@@ -0,0 +1,61 @@
#ifndef ISERVER_H
#define ISERVER_H
#include "IInterface.h"
#include "ClipboardTypes.h"
#include "CString.h"
class CClientInfo;
//! Server interface
/*!
This interface defines the methods necessary for clients to
communicate with the server. Note that the methods in this
interface are similar to the methods in IScreenReceiver but
include extra parameters. This interface is suitable for
server-side client proxies. Client-side objects should use
the IScreenReceiver interface since the extra parameters are
meaningless on the client-side.
*/
class IServer : public IInterface {
public:
//! @name manipulators
//@{
//! Notify of error
/*!
Called when the screen is unexpectedly closing. This implies that
the screen is no longer usable and that the program should close
the screen and probably terminate.
*/
virtual void onError() = 0;
//! Notify of client screen change
/*!
Called when the client's info has changed.
*/
virtual void onInfoChanged(const CString& clientName,
const CClientInfo&) = 0;
//! Notify of clipboad grab
/*!
Called when the clipboard was grabbed by another program and,
therefore, we no longer own it. Returns true if the grab was
honored, false otherwise.
*/
virtual bool onGrabClipboard(const CString& clientName,
ClipboardID, UInt32 seqNum) = 0;
//! Notify of new clipboard data
/*!
Called when the data on the clipboard has changed because some
other program has changed it. \c data has the marshalled clipboard
data.
*/
virtual void onClipboardChanged(ClipboardID,
UInt32 seqNum, const CString& data) = 0;
//@}
};
#endif

View File

@@ -0,0 +1,28 @@
#ifndef ISOCKETFACTORY_H
#define ISOCKETFACTORY_H
#include "IInterface.h"
class IDataSocket;
class IListenSocket;
//! Socket factory
/*!
This interface defines the methods common to all factories used to
create sockets.
*/
class ISocketFactory : public IInterface {
public:
//! @name accessors
//@{
//! Create data socket
virtual IDataSocket* create() const = 0;
//! Create listen socket
virtual IListenSocket* createListen() const = 0;
//@}
};
#endif

176
lib/synergy/KeyTypes.h Normal file
View File

@@ -0,0 +1,176 @@
#ifndef KEYTYPES_H
#define KEYTYPES_H
#include "BasicTypes.h"
//! Key ID
/*!
Type to hold a key identifier. The encoding is UTF-32, using
U+E000 through U+EFFF for the various control keys (e.g. arrow
keys, function keys, modifier keys, etc).
*/
typedef UInt32 KeyID;
//! Modifier key ID
/*!
Type to hold a bitmask of key modifiers (e.g. shift keys).
*/
typedef UInt32 KeyModifierMask;
//! @name Modifier key identifiers
//@{
static const KeyModifierMask KeyModifierShift = 0x0001;
static const KeyModifierMask KeyModifierControl = 0x0002;
static const KeyModifierMask KeyModifierAlt = 0x0004;
static const KeyModifierMask KeyModifierMeta = 0x0008;
static const KeyModifierMask KeyModifierCapsLock = 0x1000;
static const KeyModifierMask KeyModifierNumLock = 0x2000;
static const KeyModifierMask KeyModifierScrollLock = 0x4000;
//@}
//! @name Key identifiers
//@{
// all identifiers except kKeyNone are equal to the corresponding
// X11 keysym - 0x1000.
// no key
static const KeyID kKeyNone = 0x0000;
// TTY functions
static const KeyID kKeyBackSpace = 0xEF08; /* back space, back char */
static const KeyID kKeyTab = 0xEF09;
static const KeyID kKeyLinefeed = 0xEF0A; /* Linefeed, LF */
static const KeyID kKeyClear = 0xEF0B;
static const KeyID kKeyReturn = 0xEF0D; /* Return, enter */
static const KeyID kKeyPause = 0xEF13; /* Pause, hold */
static const KeyID kKeyScrollLock = 0xEF14;
static const KeyID kKeySysReq = 0xEF15;
static const KeyID kKeyEscape = 0xEF1B;
static const KeyID kKeyDelete = 0xEFFF; /* Delete, rubout */
// multi-key character composition
static const KeyID kKeyMultiKey = 0xEF20; /* Multi-key character compose */
// cursor control
static const KeyID kKeyHome = 0xEF50;
static const KeyID kKeyLeft = 0xEF51; /* Move left, left arrow */
static const KeyID kKeyUp = 0xEF52; /* Move up, up arrow */
static const KeyID kKeyRight = 0xEF53; /* Move right, right arrow */
static const KeyID kKeyDown = 0xEF54; /* Move down, down arrow */
static const KeyID kKeyPageUp = 0xEF55;
static const KeyID kKeyPageDown = 0xEF56;
static const KeyID kKeyEnd = 0xEF57; /* EOL */
static const KeyID kKeyBegin = 0xEF58; /* BOL */
// misc functions
static const KeyID kKeySelect = 0xEF60; /* Select, mark */
static const KeyID kKeyPrint = 0xEF61;
static const KeyID kKeyExecute = 0xEF62; /* Execute, run, do */
static const KeyID kKeyInsert = 0xEF63; /* Insert, insert here */
static const KeyID kKeyUndo = 0xEF65; /* Undo, oops */
static const KeyID kKeyRedo = 0xEF66; /* redo, again */
static const KeyID kKeyMenu = 0xEF67;
static const KeyID kKeyFind = 0xEF68; /* Find, search */
static const KeyID kKeyCancel = 0xEF69; /* Cancel, stop, abort, exit */
static const KeyID kKeyHelp = 0xEF6A; /* Help */
static const KeyID kKeyBreak = 0xEF6B;
static const KeyID kKeyModeSwitch = 0xEF7E; /* Character set switch */
static const KeyID kKeyNumLock = 0xEF7F;
// keypad
static const KeyID kKeyKP_Space = 0xEF80; /* space */
static const KeyID kKeyKP_Tab = 0xEF89;
static const KeyID kKeyKP_Enter = 0xEF8D; /* enter */
static const KeyID kKeyKP_F1 = 0xEF91; /* PF1, KP_A, ... */
static const KeyID kKeyKP_F2 = 0xEF92;
static const KeyID kKeyKP_F3 = 0xEF93;
static const KeyID kKeyKP_F4 = 0xEF94;
static const KeyID kKeyKP_Home = 0xEF95;
static const KeyID kKeyKP_Left = 0xEF96;
static const KeyID kKeyKP_Up = 0xEF97;
static const KeyID kKeyKP_Right = 0xEF98;
static const KeyID kKeyKP_Down = 0xEF99;
static const KeyID kKeyKP_Prior = 0xEF9A;
static const KeyID kKeyKP_PageUp = 0xEF9A;
static const KeyID kKeyKP_Next = 0xEF9B;
static const KeyID kKeyKP_PageDown = 0xEF9B;
static const KeyID kKeyKP_End = 0xEF9C;
static const KeyID kKeyKP_Begin = 0xEF9D;
static const KeyID kKeyKP_Insert = 0xEF9E;
static const KeyID kKeyKP_Delete = 0xEF9F;
static const KeyID kKeyKP_Equal = 0xEFBD; /* equals */
static const KeyID kKeyKP_Multiply = 0xEFAA;
static const KeyID kKeyKP_Add = 0xEFAB;
static const KeyID kKeyKP_Separator= 0xEFAC; /* separator, often comma */
static const KeyID kKeyKP_Subtract = 0xEFAD;
static const KeyID kKeyKP_Decimal = 0xEFAE;
static const KeyID kKeyKP_Divide = 0xEFAF;
static const KeyID kKeyKP_0 = 0xEFB0;
static const KeyID kKeyKP_1 = 0xEFB1;
static const KeyID kKeyKP_2 = 0xEFB2;
static const KeyID kKeyKP_3 = 0xEFB3;
static const KeyID kKeyKP_4 = 0xEFB4;
static const KeyID kKeyKP_5 = 0xEFB5;
static const KeyID kKeyKP_6 = 0xEFB6;
static const KeyID kKeyKP_7 = 0xEFB7;
static const KeyID kKeyKP_8 = 0xEFB8;
static const KeyID kKeyKP_9 = 0xEFB9;
// function keys
static const KeyID kKeyF1 = 0xEFBE;
static const KeyID kKeyF2 = 0xEFBF;
static const KeyID kKeyF3 = 0xEFC0;
static const KeyID kKeyF4 = 0xEFC1;
static const KeyID kKeyF5 = 0xEFC2;
static const KeyID kKeyF6 = 0xEFC3;
static const KeyID kKeyF7 = 0xEFC4;
static const KeyID kKeyF8 = 0xEFC5;
static const KeyID kKeyF9 = 0xEFC6;
static const KeyID kKeyF10 = 0xEFC7;
static const KeyID kKeyF11 = 0xEFC8;
static const KeyID kKeyF12 = 0xEFC9;
static const KeyID kKeyF13 = 0xEFCA;
static const KeyID kKeyF14 = 0xEFCB;
static const KeyID kKeyF15 = 0xEFCC;
static const KeyID kKeyF16 = 0xEFCD;
static const KeyID kKeyF17 = 0xEFCE;
static const KeyID kKeyF18 = 0xEFCF;
static const KeyID kKeyF19 = 0xEFD0;
static const KeyID kKeyF20 = 0xEFD1;
static const KeyID kKeyF21 = 0xEFD2;
static const KeyID kKeyF22 = 0xEFD3;
static const KeyID kKeyF23 = 0xEFD4;
static const KeyID kKeyF24 = 0xEFD5;
static const KeyID kKeyF25 = 0xEFD6;
static const KeyID kKeyF26 = 0xEFD7;
static const KeyID kKeyF27 = 0xEFD8;
static const KeyID kKeyF28 = 0xEFD9;
static const KeyID kKeyF29 = 0xEFDA;
static const KeyID kKeyF30 = 0xEFDB;
static const KeyID kKeyF31 = 0xEFDC;
static const KeyID kKeyF32 = 0xEFDD;
static const KeyID kKeyF33 = 0xEFDE;
static const KeyID kKeyF34 = 0xEFDF;
static const KeyID kKeyF35 = 0xEFE0;
// modifiers
static const KeyID kKeyShift_L = 0xEFE1; /* Left shift */
static const KeyID kKeyShift_R = 0xEFE2; /* Right shift */
static const KeyID kKeyControl_L = 0xEFE3; /* Left control */
static const KeyID kKeyControl_R = 0xEFE4; /* Right control */
static const KeyID kKeyCapsLock = 0xEFE5; /* Caps lock */
static const KeyID kKeyShiftLock = 0xEFE6; /* Shift lock */
static const KeyID kKeyMeta_L = 0xEFE7; /* Left meta */
static const KeyID kKeyMeta_R = 0xEFE8; /* Right meta */
static const KeyID kKeyAlt_L = 0xEFE9; /* Left alt */
static const KeyID kKeyAlt_R = 0xEFEA; /* Right alt */
static const KeyID kKeySuper_L = 0xEFEB; /* Left super */
static const KeyID kKeySuper_R = 0xEFEC; /* Right super */
static const KeyID kKeyHyper_L = 0xEFED; /* Left hyper */
static const KeyID kKeyHyper_R = 0xEFEE; /* Right hyper */
// more function and modifier keys
static const KeyID kKeyLeftTab = 0xEE20;
//@}
#endif

41
lib/synergy/Makefile.am Normal file
View File

@@ -0,0 +1,41 @@
## Process this file with automake to produce Makefile.in
NULL =
DEPTH = ../..
noinst_LIBRARIES = libsynergy.a
libsynergy_a_SOURCES = \
CInputPacketStream.cpp \
COutputPacketStream.cpp \
CProtocolUtil.cpp \
CClipboard.cpp \
CTCPSocketFactory.cpp \
XScreen.cpp \
XSynergy.cpp \
CClipboard.h \
CInputPacketStream.h \
COutputPacketStream.h \
CProtocolUtil.h \
CTCPSocketFactory.h \
ClipboardTypes.h \
IClient.h \
IClipboard.h \
IPrimaryScreenReceiver.h\
IScreen.h \
IScreenEventHandler.h \
IScreenReceiver.h \
IScreenSaver.h \
IServer.h \
ISocketFactory.h \
KeyTypes.h \
MouseTypes.h \
ProtocolTypes.h \
Version.h \
XScreen.h \
XSynergy.h \
$(NULL)
INCLUDES = \
-I$(DEPTH)/lib/base \
-I$(DEPTH)/lib/mt \
-I$(DEPTH)/lib/io \
-I$(DEPTH)/lib/net \
$(NULL)

20
lib/synergy/MouseTypes.h Normal file
View File

@@ -0,0 +1,20 @@
#ifndef MOUSETYPES_H
#define MOUSETYPES_H
#include "BasicTypes.h"
//! Mouse button ID
/*!
Type to hold a mouse button identifier.
*/
typedef UInt8 ButtonID;
//! @name Mouse button identifiers
//@{
static const ButtonID kButtonNone = 0;
static const ButtonID kButtonLeft = 1;
static const ButtonID kButtonMiddle = 2;
static const ButtonID kButtonRight = 3;
//@}
#endif

219
lib/synergy/ProtocolTypes.h Normal file
View File

@@ -0,0 +1,219 @@
#ifndef PROTOCOLTYPES_H
#define PROTOCOLTYPES_H
#include "BasicTypes.h"
// protocol version number
static const SInt16 kProtocolMajorVersion = 0;
static const SInt16 kProtocolMinorVersion = 7;
// default contact port number
static const UInt16 kDefaultPort = 24800;
// time between heartbeats (in seconds)
static const double kHeartRate = 2.0;
// time without a heartbeat that we call death
static const double kHeartDeath = 3.0 * kHeartRate;
// direction constants
enum EDirection {
kLeft,
kRight,
kTop,
kBottom,
kFirstDirection = kLeft,
kLastDirection = kBottom
};
enum EDirectionMask {
kLeftMask = 1 << kLeft,
kRightMask = 1 << kRight,
kTopMask = 1 << kTop,
kBottomMask = 1 << kBottom
};
//
// message codes (trailing NUL is not part of code). in comments, $n
// refers to the n'th argument (counting from one). message codes are
// always 4 bytes optionally followed by message specific parameters.
//
//
// positions and sizes are signed 16 bit integers.
//
//
// command codes
//
// no operation; secondary -> primary
static const char kMsgCNoop[] = "CNOP";
// close connection; primary -> secondary
static const char kMsgCClose[] = "CBYE";
// enter screen: primary -> secondary
// entering screen at screen position $1 = x, $2 = y. x,y are
// absolute screen coordinates. $3 = sequence number, which is
// used to order messages between screens. the secondary screen
// must return this number with some messages. $4 = modifier key
// mask. this will have bits set for each toggle modifier key
// that is activated on entry to the screen. the secondary screen
// should adjust its toggle modifiers to reflect that state.
static const char kMsgCEnter[] = "CINN%2i%2i%4i%2i";
// leave screen: primary -> secondary
// leaving screen. the secondary screen should send clipboard
// data in response to this message for those clipboards that
// it has grabbed (i.e. has sent a kMsgCClipboard for and has
// not received a kMsgCClipboard for with a greater sequence
// number) and that were grabbed or have changed since the
// last leave.
static const char kMsgCLeave[] = "COUT";
// grab clipboard: primary <-> secondary
// sent by screen when some other app on that screen grabs a
// clipboard. $1 = the clipboard identifier, $2 = sequence number.
// secondary screens must use the sequence number passed in the
// most recent kMsgCEnter. the primary always sends 0.
static const char kMsgCClipboard[] = "CCLP%1i%4i";
// screensaver change: primary -> secondary
// screensaver on primary has started ($1 == 1) or closed ($1 == 0)
static const char kMsgCScreenSaver[] = "CSEC%1i";
// resolution change acknowledgment: primary -> secondary
// sent by primary in response to a secondary screen's kMsgDInfo.
// this is sent for every kMsgDInfo, whether or not the primary
// had sent a kMsgQInfo.
static const char kMsgCInfoAck[] = "CIAK";
//
// data codes
//
// key pressed: primary -> secondary
// $1 = KeyID, $2 = KeyModifierMask
static const char kMsgDKeyDown[] = "DKDN%2i%2i";
// key auto-repeat: primary -> secondary
// $1 = KeyID, $2 = KeyModifierMask, $3 = number of repeats
static const char kMsgDKeyRepeat[] = "DKRP%2i%2i%2i";
// key released: primary -> secondary
// $1 = KeyID, $2 = KeyModifierMask
static const char kMsgDKeyUp[] = "DKUP%2i%2i";
// mouse button pressed: primary -> secondary
// $1 = ButtonID
static const char kMsgDMouseDown[] = "DMDN%1i";
// mouse button released: primary -> secondary
// $1 = ButtonID
static const char kMsgDMouseUp[] = "DMUP%1i";
// mouse moved: primary -> secondary
// $1 = x, $2 = y. x,y are absolute screen coordinates.
static const char kMsgDMouseMove[] = "DMMV%2i%2i";
// mouse button pressed: primary -> secondary
// $1 = delta. the delta should be +120 for one tick forward (away
// from the user) and -120 for one tick backward (toward the user).
static const char kMsgDMouseWheel[] = "DMWM%2i";
// clipboard data: primary <-> secondary
// $2 = sequence number, $3 = clipboard data. the sequence number
// is 0 when sent by the primary. secondary screens should use the
// sequence number from the most recent kMsgCEnter. $1 = clipboard
// identifier.
static const char kMsgDClipboard[] = "DCLP%1i%4i%s";
// client data: secondary -> primary
// $1 = coordinate of leftmost pixel on secondary screen,
// $2 = coordinate of topmost pixel on secondary screen,
// $3 = width of secondary screen in pixels,
// $4 = height of secondary screen in pixels,
// $5 = size of warp zone,
// $6, $7 = the x,y position of the mouse on the secondary screen.
//
// the secondary screen must send this message in response to the
// kMsgQInfo message. it must also send this message when the
// screen's resolution changes. in this case, the secondary screen
// should ignore any kMsgDMouseMove messages until it receives a
// kMsgCInfoAck in order to prevent attempts to move the mouse off
// the new screen area.
static const char kMsgDInfo[] = "DINF%2i%2i%2i%2i%2i%2i%2i";
//
// query codes
//
// query screen info: primary -> secondary
// client should reply with a kMsgDInfo.
static const char kMsgQInfo[] = "QINF";
//
// error codes
//
// incompatible versions: primary -> secondary
// $1 = major version of primary, $2 = minor version of primary.
static const char kMsgEIncompatible[] = "EICV%2i%2i";
// name provided when connecting is already in use: primary -> secondary
static const char kMsgEBusy[] = "EBSY";
// unknown client: primary -> secondary
// name provided when connecting is not in primary's screen
// configuration map.
static const char kMsgEUnknown[] = "EUNK";
// protocol violation: primary -> secondary
// primary should disconnect after sending this message.
static const char kMsgEBad[] = "EBAD";
//
// structures
//
//! Screen information
/*!
This class contains information about a screen.
*/
class CClientInfo {
public:
//! Screen position
/*!
The position of the upper-left corner of the screen. This is
typically 0,0.
*/
SInt32 m_x, m_y;
//! Screen size
/*!
The size of the screen in pixels.
*/
SInt32 m_w, m_h;
//! Jump zone size
/*!
This is the size of the jump zone. The cursor jumps to the adjacent
screen when it comes within this many pixels of the edge of the screen.
*/
SInt32 m_zoneSize;
//! Mouse position
/*!
The position of the cursor. This is not kept up-to-date so it's
only meaningful when receiving an update.
*/
SInt32 m_mx, m_my;
};
#endif

24
lib/synergy/Version.h Normal file
View File

@@ -0,0 +1,24 @@
#ifndef VERSION_H
#define VERSION_H
#include "BasicTypes.h"
// important strings
static const char* kCopyright = "Copyright (C) 2002 Chris Schoeneman";
static const char* kContact = "Chris Schoeneman, crs23@bigfoot.com";
static const char* kWebsite = "";
// build version. follows linux kernel style: an even minor number implies
// a release version, odd implies development version.
static const SInt16 kMajorVersion = 0;
static const SInt16 kMinorVersion = 9;
static const SInt16 kReleaseVersion = 7;
// exit codes
static const int kExitSuccess = 0; // successful completion
static const int kExitFailed = 1; // general failure
static const int kExitTerminated = 2; // killed by signal
static const int kExitArgs = 3; // bad arguments
static const int kExitConfig = 4; // cannot read configuration
#endif

11
lib/synergy/XScreen.cpp Normal file
View File

@@ -0,0 +1,11 @@
#include "XScreen.h"
//
// XScreenOpenFailure
//
CString
XScreenOpenFailure::getWhat() const throw()
{
return format("XScreenOpenFailure", "unable to open screen");
}

18
lib/synergy/XScreen.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef XSCREEN_H
#define XSCREEN_H
#include "XBase.h"
//! Generic screen exception
class XScreen : public XBase { };
//! Cannot open screen exception
/*!
Thrown when a screen cannot be opened or initialized.
*/
class XScreenOpenFailure : public XScreen {
protected:
virtual CString getWhat() const throw();
};
#endif

89
lib/synergy/XSynergy.cpp Normal file
View File

@@ -0,0 +1,89 @@
#include "XSynergy.h"
//
// XBadClient
//
CString
XBadClient::getWhat() const throw()
{
return "XBadClient";
}
//
// XIncompatibleClient
//
XIncompatibleClient::XIncompatibleClient(int major, int minor) :
m_major(major),
m_minor(minor)
{
// do nothing
}
int
XIncompatibleClient::getMajor() const throw()
{
return m_major;
}
int
XIncompatibleClient::getMinor() const throw()
{
return m_minor;
}
CString
XIncompatibleClient::getWhat() const throw()
{
return format("XIncompatibleClient", "incompatible client %{1}.%{2}",
CStringUtil::print("%d", m_major).c_str(),
CStringUtil::print("%d", m_minor).c_str());
}
//
// XDuplicateClient
//
XDuplicateClient::XDuplicateClient(const CString& name) :
m_name(name)
{
// do nothing
}
const CString&
XDuplicateClient::getName() const throw()
{
return m_name;
}
CString
XDuplicateClient::getWhat() const throw()
{
return format("XDuplicateClient", "duplicate client %{1}", m_name.c_str());
}
//
// XUnknownClient
//
XUnknownClient::XUnknownClient(const CString& name) :
m_name(name)
{
// do nothing
}
const CString&
XUnknownClient::getName() const throw()
{
return m_name;
}
CString
XUnknownClient::getWhat() const throw()
{
return format("XUnknownClient", "unknown client %{1}", m_name.c_str());
}

94
lib/synergy/XSynergy.h Normal file
View File

@@ -0,0 +1,94 @@
#ifndef XSYNERGY_H
#define XSYNERGY_H
#include "XBase.h"
//! Generic synergy exception
class XSynergy : public XBase { };
//! Client error exception
/*!
Thrown when the client fails to follow the protocol.
*/
class XBadClient : public XSynergy {
protected:
virtual CString getWhat() const throw();
};
//! Incompatible client exception
/*!
Thrown when a client attempting to connect has an incompatible version.
*/
class XIncompatibleClient : public XSynergy {
public:
XIncompatibleClient(int major, int minor);
//! @name accessors
//@{
//! Get client's major version number
int getMajor() const throw();
//! Get client's minor version number
int getMinor() const throw();
//@}
protected:
virtual CString getWhat() const throw();
private:
int m_major;
int m_minor;
};
//! Client already connected exception
/*!
Thrown when a client attempting to connect is using the same name as
a client that is already connected.
*/
class XDuplicateClient : public XSynergy {
public:
XDuplicateClient(const CString& name);
//! @name accessors
//@{
//! Get client's name
virtual const CString&
getName() const throw();
//@}
protected:
virtual CString getWhat() const throw();
private:
CString m_name;
};
//! Client not in map
/*!
Thrown when a client attempting to connect is using a name that is
unknown to the server.
*/
class XUnknownClient : public XSynergy {
public:
XUnknownClient(const CString& name);
//! @name accessors
//@{
//! Get the client's name
virtual const CString&
getName() const throw();
//@}
protected:
virtual CString getWhat() const throw();
private:
CString m_name;
};
#endif

206
lib/synergy/libsynergy.dsp Normal file
View File

@@ -0,0 +1,206 @@
# Microsoft Developer Studio Project File - Name="libsynergy" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=synergy - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "libsynergy.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "libsynergy.mak" CFG="libsynergy - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "libsynergy - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "libsynergy - Win32 Debug" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "libsynergy - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /MT /W4 /GX /O2 /I "..\base" /I "..\io" /I "..\mt" /I "..\net" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ELSEIF "$(CFG)" == "libsynergy - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "..\base" /I "..\io" /I "..\mt" /I "..\net" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FD /GZ /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ENDIF
# Begin Target
# Name "libsynergy - Win32 Release"
# Name "libsynergy - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\CClipboard.cpp
# End Source File
# Begin Source File
SOURCE=.\CInputPacketStream.cpp
# End Source File
# Begin Source File
SOURCE=.\COutputPacketStream.cpp
# End Source File
# Begin Source File
SOURCE=.\CProtocolUtil.cpp
# End Source File
# Begin Source File
SOURCE=.\CTCPSocketFactory.cpp
# End Source File
# Begin Source File
SOURCE=.\XScreen.cpp
# End Source File
# Begin Source File
SOURCE=.\XSynergy.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\CClipboard.h
# End Source File
# Begin Source File
SOURCE=.\CInputPacketStream.h
# End Source File
# Begin Source File
SOURCE=.\ClipboardTypes.h
# End Source File
# Begin Source File
SOURCE=.\COutputPacketStream.h
# End Source File
# Begin Source File
SOURCE=.\CProtocolUtil.h
# End Source File
# Begin Source File
SOURCE=.\CTCPSocketFactory.h
# End Source File
# Begin Source File
SOURCE=.\IClient.h
# End Source File
# Begin Source File
SOURCE=.\IClipboard.h
# End Source File
# Begin Source File
SOURCE=.\IPrimaryScreenReceiver.h
# End Source File
# Begin Source File
SOURCE=.\IScreen.h
# End Source File
# Begin Source File
SOURCE=.\IScreenEventHandler.h
# End Source File
# Begin Source File
SOURCE=.\IScreenReceiver.h
# End Source File
# Begin Source File
SOURCE=.\IScreenSaver.h
# End Source File
# Begin Source File
SOURCE=.\IServer.h
# End Source File
# Begin Source File
SOURCE=.\ISocketFactory.h
# End Source File
# Begin Source File
SOURCE=.\KeyTypes.h
# End Source File
# Begin Source File
SOURCE=.\MouseTypes.h
# End Source File
# Begin Source File
SOURCE=.\ProtocolTypes.h
# End Source File
# Begin Source File
SOURCE=.\XScreen.h
# End Source File
# Begin Source File
SOURCE=.\XSynergy.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project