checkpoint. first cut of client and server apps. not tested

yet but they compile and *should* work as is.
This commit is contained in:
crs 2001-10-08 19:24:46 +00:00
parent 23f1b1aba1
commit 23f948d55a
12 changed files with 434 additions and 40 deletions

View File

@ -42,6 +42,7 @@ LCXXINCS = \
-I$(DEPTH)/mt \ -I$(DEPTH)/mt \
-I$(DEPTH)/io \ -I$(DEPTH)/io \
-I$(DEPTH)/net \ -I$(DEPTH)/net \
-I$(DEPTH)/synergy \
$(NULL) $(NULL)
CXXFILES = test.cpp CXXFILES = test.cpp
@ -49,6 +50,7 @@ CXXFILES = test.cpp
# libraries we depend on # libraries we depend on
# #
DEPLIBS = \ DEPLIBS = \
$(LIBDIR)/libsynergy.a \
$(LIBDIR)/libnet.a \ $(LIBDIR)/libnet.a \
$(LIBDIR)/libio.a \ $(LIBDIR)/libio.a \
$(LIBDIR)/libmt.a \ $(LIBDIR)/libmt.a \
@ -61,3 +63,4 @@ LLDLIBS = \
test: $(OBJECTS) $(DEPLIBS) test: $(OBJECTS) $(DEPLIBS)
$(CXX) $(CXXFLAGS) -o $@ $(OBJECTS) $(LDFLAGS) $(CXX) $(CXXFLAGS) -o $@ $(OBJECTS) $(LDFLAGS)

1
notes
View File

@ -9,7 +9,6 @@ CServer
* put mutex locks wherever necessary (like accessing m_active) * put mutex locks wherever necessary (like accessing m_active)
CClient CClient
* need thread to handle screen
* need methods for screen event handler to call as appropriate * need methods for screen event handler to call as appropriate
server client server client

View File

@ -2,15 +2,22 @@
#include "CInputPacketStream.h" #include "CInputPacketStream.h"
#include "COutputPacketStream.h" #include "COutputPacketStream.h"
#include "CProtocolUtil.h" #include "CProtocolUtil.h"
#include "ISecondaryScreen.h"
#include "ProtocolTypes.h"
#include "CTimerThread.h" #include "CTimerThread.h"
#include "XSynergy.h"
#include <stdio.h> #include <stdio.h>
#include <memory>
// //
// CClient // CClient
// //
CClient::CClient(const CString& clientName) : CClient::CClient(const CString& clientName) :
m_name(clientName) m_name(clientName),
m_input(NULL),
m_output(NULL),
m_screen(NULL)
{ {
} }
@ -19,6 +26,7 @@ CClient::~CClient()
} }
#include "CTCPSocket.h" #include "CTCPSocket.h"
#include "CXWindowsSecondaryScreen.h"
void CClient::run(const CNetworkAddress& serverAddress) void CClient::run(const CNetworkAddress& serverAddress)
{ {
std::auto_ptr<ISocket> socket; std::auto_ptr<ISocket> socket;
@ -84,12 +92,18 @@ void CClient::run(const CNetworkAddress& serverAddress)
} }
// connect to screen // connect to screen
// FIXME -- make object that closes and destroys screen in std::auto_ptr<CScreenCleaner> screenCleaner;
// it's d'tor. screen must not be handling event queue by
// the time the streams are destroyed.
// handle messages from server
try { try {
m_screen = new CXWindowsSecondaryScreen;
screenCleaner.reset(new CScreenCleaner(this, m_screen));
}
catch (XBase& e) {
fprintf(stderr, "cannot open screen: %s\n", e.what());
return;
}
try {
// handle messages from server
for (;;) { for (;;) {
// wait for reply // wait for reply
UInt8 code[4]; UInt8 code[4];
@ -108,46 +122,46 @@ void CClient::run(const CNetworkAddress& serverAddress)
// parse message // parse message
if (memcmp(code, kMsgDMouseMove, 4) == 0) { if (memcmp(code, kMsgDMouseMove, 4) == 0) {
onMouseMove(input.get()); onMouseMove();
} }
else if (memcmp(code, kMsgDMouseWheel, 4) == 0) { else if (memcmp(code, kMsgDMouseWheel, 4) == 0) {
onMouseWheel(input.get()); onMouseWheel();
} }
else if (memcmp(code, kMsgDKeyDown, 4) == 0) { else if (memcmp(code, kMsgDKeyDown, 4) == 0) {
onKeyDown(input.get()); onKeyDown();
} }
else if (memcmp(code, kMsgDKeyUp, 4) == 0) { else if (memcmp(code, kMsgDKeyUp, 4) == 0) {
onKeyUp(input.get()); onKeyUp();
} }
else if (memcmp(code, kMsgDMouseDown, 4) == 0) { else if (memcmp(code, kMsgDMouseDown, 4) == 0) {
onMouseDown(input.get()); onMouseDown();
} }
else if (memcmp(code, kMsgDMouseUp, 4) == 0) { else if (memcmp(code, kMsgDMouseUp, 4) == 0) {
onMouseUp(input.get()); onMouseUp();
} }
else if (memcmp(code, kMsgDKeyRepeat, 4) == 0) { else if (memcmp(code, kMsgDKeyRepeat, 4) == 0) {
onKeyRepeat(input.get()); onKeyRepeat();
} }
else if (memcmp(code, kMsgCEnter, 4) == 0) { else if (memcmp(code, kMsgCEnter, 4) == 0) {
onEnter(input.get()); onEnter();
} }
else if (memcmp(code, kMsgCLeave, 4) == 0) { else if (memcmp(code, kMsgCLeave, 4) == 0) {
onLeave(input.get()); onLeave();
} }
else if (memcmp(code, kMsgCClipboard, 4) == 0) { else if (memcmp(code, kMsgCClipboard, 4) == 0) {
onGrabClipboard(input.get()); onGrabClipboard();
} }
else if (memcmp(code, kMsgCScreenSaver, 4) == 0) { else if (memcmp(code, kMsgCScreenSaver, 4) == 0) {
onScreenSaver(input.get()); onScreenSaver();
} }
else if (memcmp(code, kMsgQInfo, 4) == 0) { else if (memcmp(code, kMsgQInfo, 4) == 0) {
onQueryInfo(input.get()); onQueryInfo();
} }
else if (memcmp(code, kMsgQClipboard, 4) == 0) { else if (memcmp(code, kMsgQClipboard, 4) == 0) {
onQueryClipboard(input.get()); onQueryClipboard();
} }
else if (memcmp(code, kMsgDClipboard, 4) == 0) { else if (memcmp(code, kMsgDClipboard, 4) == 0) {
onSetClipboard(input.get()); onSetClipboard();
} }
else if (memcmp(code, kMsgCClose, 4) == 0) { else if (memcmp(code, kMsgCClose, 4) == 0) {
// server wants us to hangup // server wants us to hangup
@ -159,14 +173,17 @@ void CClient::run(const CNetworkAddress& serverAddress)
break; break;
} }
} }
// done with socket
m_socket->close();
} }
catch (XBase& e) { catch (XBase& e) {
fprintf(stderr, "error: %s\n", e.what()); fprintf(stderr, "error: %s\n", e.what());
return; return;
} }
// done with screen
screenCleaner.reset();
// done with socket
socket->close();
} }
void CClient::onEnter() void CClient::onEnter()
@ -196,7 +213,7 @@ void CClient::onScreenSaver()
void CClient::onQueryInfo() void CClient::onQueryInfo()
{ {
SInt32 w, h; SInt32 w, h;
m_screen->getSize(w, h); m_screen->getSize(&w, &h);
SInt32 zoneSize = m_screen->getJumpZoneSize(); SInt32 zoneSize = m_screen->getJumpZoneSize();
CProtocolUtil::writef(m_output, kMsgDInfo, w, h, zoneSize); CProtocolUtil::writef(m_output, kMsgDInfo, w, h, zoneSize);
} }
@ -215,16 +232,16 @@ void CClient::onKeyDown()
{ {
SInt32 id, mask; SInt32 id, mask;
CProtocolUtil::readf(m_input, kMsgDKeyDown + 4, &id, &mask); CProtocolUtil::readf(m_input, kMsgDKeyDown + 4, &id, &mask);
m_screen->onKeyDown(reinterpret_cast<KeyID>(id), m_screen->onKeyDown(static_cast<KeyID>(id),
reinterpret_cast<KeyModifierMask>(mask)); static_cast<KeyModifierMask>(mask));
} }
void CClient::onKeyRepeat() void CClient::onKeyRepeat()
{ {
SInt32 id, mask, count; SInt32 id, mask, count;
CProtocolUtil::readf(m_input, kMsgDKeyRepeat + 4, &id, &mask, &count); CProtocolUtil::readf(m_input, kMsgDKeyRepeat + 4, &id, &mask, &count);
m_screen->onKeyRepeat(reinterpret_cast<KeyID>(id), m_screen->onKeyRepeat(static_cast<KeyID>(id),
reinterpret_cast<KeyModifierMask>(mask), static_cast<KeyModifierMask>(mask),
count); count);
} }
@ -232,22 +249,22 @@ void CClient::onKeyUp()
{ {
SInt32 id, mask; SInt32 id, mask;
CProtocolUtil::readf(m_input, kMsgDKeyUp + 4, &id, &mask); CProtocolUtil::readf(m_input, kMsgDKeyUp + 4, &id, &mask);
m_screen->onKeyUp(reinterpret_cast<KeyID>(id), m_screen->onKeyUp(static_cast<KeyID>(id),
reinterpret_cast<KeyModifierMask>(mask)); static_cast<KeyModifierMask>(mask));
} }
void CClient::onMouseDown() void CClient::onMouseDown()
{ {
SInt32 id; SInt32 id;
CProtocolUtil::readf(m_input, kMsgDMouseDown + 4, &id); CProtocolUtil::readf(m_input, kMsgDMouseDown + 4, &id);
m_screen->onMouseDown(reinterpret_cast<ButonID>(id)); m_screen->onMouseDown(static_cast<ButtonID>(id));
} }
void CClient::onMouseUp() void CClient::onMouseUp()
{ {
SInt32 id; SInt32 id;
CProtocolUtil::readf(m_input, kMsgDMouseUp + 4, &id); CProtocolUtil::readf(m_input, kMsgDMouseUp + 4, &id);
m_screen->onMouseUp(reinterpret_cast<ButonID>(id)); m_screen->onMouseUp(static_cast<ButtonID>(id));
} }
void CClient::onMouseMove() void CClient::onMouseMove()
@ -263,3 +280,28 @@ void CClient::onMouseWheel()
CProtocolUtil::readf(m_input, kMsgDMouseWheel + 4, &delta); CProtocolUtil::readf(m_input, kMsgDMouseWheel + 4, &delta);
m_screen->onMouseWheel(delta); m_screen->onMouseWheel(delta);
} }
//
// CClient::CScreenCleaner
//
CClient::CScreenCleaner::CScreenCleaner(CClient* client,
ISecondaryScreen* screen) :
m_screen(screen)
{
assert(m_screen != NULL);
try {
m_screen->open(client);
}
catch (...) {
delete m_screen;
throw;
}
}
CClient::CScreenCleaner::~CScreenCleaner()
{
m_screen->close();
delete m_screen;
}

View File

@ -7,6 +7,7 @@
class CNetworkAddress; class CNetworkAddress;
class IInputStream; class IInputStream;
class IOutputStream; class IOutputStream;
class ISecondaryScreen;
class CClient { class CClient {
public: public:
@ -37,10 +38,21 @@ class CClient {
void onMouseMove(); void onMouseMove();
void onMouseWheel(); void onMouseWheel();
private:
class CScreenCleaner {
public:
CScreenCleaner(CClient*, ISecondaryScreen*);
~CScreenCleaner();
private:
ISecondaryScreen* m_screen;
};
private: private:
CString m_name; CString m_name;
IInputStream* m_output; IInputStream* m_input;
IOutputStream* m_output; IOutputStream* m_output;
ISecondaryScreen* m_screen;
}; };
#endif #endif

View File

@ -545,6 +545,7 @@ void CServer::mapPosition(CScreenInfo* src,
} }
} }
#include "CTCPListenSocket.h"
void CServer::acceptClients(void*) void CServer::acceptClients(void*)
{ {
// add this thread to the list of threads to cancel. remove from // add this thread to the list of threads to cancel. remove from
@ -554,7 +555,8 @@ void CServer::acceptClients(void*)
std::auto_ptr<IListenSocket> listen; std::auto_ptr<IListenSocket> listen;
try { try {
// create socket listener // create socket listener
listen.reset(m_socketFactory->createListen()); // listen.reset(m_socketFactory->createListen());
listen.reset(new CTCPListenSocket); // FIXME
// bind to the desired port. keep retrying if we can't bind // bind to the desired port. keep retrying if we can't bind
// the address immediately. // the address immediately.
@ -712,7 +714,12 @@ void CServer::openPrimaryScreen()
m_primary->open(this); m_primary->open(this);
// add connection // add connection
m_active = addConnection(CString("primary"/* FIXME */), NULL); m_active = addConnection(CString("primary"/* FIXME */), NULL);
// update info
m_primary->getSize(&m_active->m_width, &m_active->m_height);
m_active->m_zoneSize = m_primary->getJumpZoneSize();
// FIXME -- need way for primary screen to call us back
} }
void CServer::closePrimaryScreen() throw() void CServer::closePrimaryScreen() throw()

View File

@ -4,7 +4,6 @@
#include "TMethodJob.h" #include "TMethodJob.h"
#include <assert.h> #include <assert.h>
#include <X11/X.h> #include <X11/X.h>
#include <X11/extensions/XTest.h>
// //
// CXWindowsPrimaryScreen // CXWindowsPrimaryScreen

View File

@ -0,0 +1,231 @@
#include "CXWindowsSecondaryScreen.h"
#include "CClient.h"
#include "CThread.h"
#include "TMethodJob.h"
#include <assert.h>
#include <X11/X.h>
#include <X11/extensions/XTest.h>
//
// CXWindowsSecondaryScreen
//
CXWindowsSecondaryScreen::CXWindowsSecondaryScreen() :
m_client(NULL),
m_display(NULL),
m_window(None),
m_w(0), m_h(0)
{
// do nothing
}
CXWindowsSecondaryScreen::~CXWindowsSecondaryScreen()
{
assert(m_display == NULL);
}
void CXWindowsSecondaryScreen::open(CClient* client)
{
assert(m_client == NULL);
assert(client != NULL);
// set the client
m_client = client;
// open the display
m_display = ::XOpenDisplay(NULL); // FIXME -- allow non-default
if (m_display == NULL)
throw int(5); // FIXME -- make exception for this
// get default screen
m_screen = DefaultScreen(m_display);
Screen* screen = ScreenOfDisplay(m_display, m_screen);
// get screen size
m_w = WidthOfScreen(screen);
m_h = HeightOfScreen(screen);
// verify the availability of the XTest extension
int majorOpcode, firstEvent, firstError;
if (!::XQueryExtension(m_display, XTestExtensionName,
&majorOpcode, &firstEvent, &firstError))
throw int(6); // FIXME -- make exception for this
// become impervious to server grabs
::XTestGrabControl(m_display, True);
// start processing events
m_eventThread = new CThread(new TMethodJob<CXWindowsSecondaryScreen>(
this, &CXWindowsSecondaryScreen::eventThread));
}
void CXWindowsSecondaryScreen::close()
{
assert(m_client != NULL);
assert(m_eventThread != NULL);
// stop event thread
m_eventThread->cancel();
m_eventThread->wait();
delete m_eventThread;
m_eventThread = NULL;
// no longer impervious to server grabs
::XTestGrabControl(m_display, False);
// close the display
::XCloseDisplay(m_display);
m_display = NULL;
}
void CXWindowsSecondaryScreen::enter(SInt32 x, SInt32 y)
{
assert(m_display != NULL);
// warp to requested location
warpCursor(x, y);
// show cursor
// FIXME
}
void CXWindowsSecondaryScreen::leave()
{
assert(m_display != NULL);
// hide cursor
// FIXME
}
void CXWindowsSecondaryScreen::warpCursor(SInt32 x, SInt32 y)
{
assert(m_display != NULL);
::XTestFakeMotionEvent(m_display, m_screen, x, y, CurrentTime);
::XSync(m_display, False);
}
void CXWindowsSecondaryScreen::onKeyDown(
KeyID key, KeyModifierMask mask)
{
assert(m_display != NULL);
::XTestFakeKeyEvent(m_display, mapKey(key, mask), True, CurrentTime);
::XSync(m_display, False);
}
void CXWindowsSecondaryScreen::onKeyRepeat(
KeyID, KeyModifierMask, SInt32)
{
assert(m_display != NULL);
// FIXME
}
void CXWindowsSecondaryScreen::onKeyUp(
KeyID key, KeyModifierMask mask)
{
assert(m_display != NULL);
::XTestFakeKeyEvent(m_display, mapKey(key, mask), False, CurrentTime);
::XSync(m_display, False);
}
void CXWindowsSecondaryScreen::onMouseDown(ButtonID button)
{
assert(m_display != NULL);
::XTestFakeButtonEvent(m_display, mapButton(button), True, CurrentTime);
::XSync(m_display, False);
}
void CXWindowsSecondaryScreen::onMouseUp(ButtonID button)
{
assert(m_display != NULL);
::XTestFakeButtonEvent(m_display, mapButton(button), False, CurrentTime);
::XSync(m_display, False);
}
void CXWindowsSecondaryScreen::onMouseMove(
SInt32 x, SInt32 y)
{
assert(m_display != NULL);
::XTestFakeMotionEvent(m_display, m_screen, x, y, CurrentTime);
::XSync(m_display, False);
}
void CXWindowsSecondaryScreen::onMouseWheel(SInt32)
{
assert(m_display != NULL);
// FIXME
}
void CXWindowsSecondaryScreen::getSize(
SInt32* width, SInt32* height) const
{
assert(m_display != NULL);
assert(width != NULL && height != NULL);
*width = m_w;
*height = m_h;
}
SInt32 CXWindowsSecondaryScreen::getJumpZoneSize() const
{
assert(m_display != NULL);
return 0;
}
void CXWindowsSecondaryScreen::eventThread(void*)
{
for (;;) {
// wait for and then get the next event
while (XPending(m_display) == 0) {
CThread::sleep(0.05);
}
XEvent xevent;
XNextEvent(m_display, &xevent);
// handle event
switch (xevent.type) {
case LeaveNotify:
// mouse moved out of window somehow. hide the window.
// ::XUnmapWindow(m_display, m_window);
break;
/*
// FIXME -- handle screen resolution changes
case SelectionClear:
target->XXX(xevent.xselectionclear.);
break;
case SelectionNotify:
target->XXX(xevent.xselection.);
break;
case SelectionRequest:
target->XXX(xevent.xselectionrequest.);
break;
*/
}
}
}
KeyCode CXWindowsSecondaryScreen::mapKey(
KeyID id, KeyModifierMask /*mask*/) const
{
// FIXME -- use mask
return ::XKeysymToKeycode(m_display, static_cast<KeySym>(id));
}
unsigned int CXWindowsSecondaryScreen::mapButton(
ButtonID id) const
{
// FIXME -- should use button mapping?
return static_cast<unsigned int>(id);
}

View File

@ -0,0 +1,44 @@
#ifndef CXWINDOWSSECONDARYSCREEN_H
#define CXWINDOWSSECONDARYSCREEN_H
#include "ISecondaryScreen.h"
#include <X11/Xlib.h>
class CThread;
class CXWindowsSecondaryScreen : public ISecondaryScreen {
public:
CXWindowsSecondaryScreen();
virtual ~CXWindowsSecondaryScreen();
// ISecondaryScreen overrides
virtual void open(CClient*);
virtual void close();
virtual void enter(SInt32 xAbsolute, SInt32 yAbsolute);
virtual void leave();
virtual void warpCursor(SInt32 xAbsolute, SInt32 yAbsolute);
virtual void onKeyDown(KeyID, KeyModifierMask);
virtual void onKeyRepeat(KeyID, KeyModifierMask, SInt32 count);
virtual void onKeyUp(KeyID, KeyModifierMask);
virtual void onMouseDown(ButtonID);
virtual void onMouseUp(ButtonID);
virtual void onMouseMove(SInt32 xAbsolute, SInt32 yAbsolute);
virtual void onMouseWheel(SInt32 delta);
virtual void getSize(SInt32* width, SInt32* height) const;
virtual SInt32 getJumpZoneSize() const;
private:
void eventThread(void*);
KeyCode mapKey(KeyID, KeyModifierMask) const;
unsigned int mapButton(ButtonID button) const;
private:
CClient* m_client;
CThread* m_eventThread;
Display* m_display;
int m_screen;
Window m_window;
SInt32 m_w, m_h;
};
#endif

View File

@ -3,6 +3,8 @@
#include "IInterface.h" #include "IInterface.h"
#include "BasicTypes.h" #include "BasicTypes.h"
#include "KeyTypes.h"
#include "MouseTypes.h"
class CClient; class CClient;
//class IClipboard; //class IClipboard;

View File

@ -15,11 +15,13 @@ CXXFILES = \
COutputPacketStream.cpp \ COutputPacketStream.cpp \
CTCPSocketFactory.cpp \ CTCPSocketFactory.cpp \
CProtocolUtil.cpp \ CProtocolUtil.cpp \
CClient.cpp \
CServerProtocol.cpp \ CServerProtocol.cpp \
CServerProtocol1_0.cpp \ CServerProtocol1_0.cpp \
CScreenMap.cpp \ CScreenMap.cpp \
CServer.cpp \ CServer.cpp \
CXWindowsPrimaryScreen.cpp \ CXWindowsPrimaryScreen.cpp \
CXWindowsSecondaryScreen.cpp \
XSynergy.cpp \ XSynergy.cpp \
$(NULL) $(NULL)
@ -37,8 +39,11 @@ LLDLIBS = \
-lpthread \ -lpthread \
$(NULL) $(NULL)
targets: server targets: server client
server: $(OBJECTS) $(DEPLIBS) server: server.o $(OBJECTS) $(DEPLIBS)
$(CXX) $(CXXFLAGS) -o $@ $(OBJECTS) $(LDFLAGS) $(CXX) $(CXXFLAGS) -o $@ server.o $(OBJECTS) $(LDFLAGS)
client: client.o $(OBJECTS) $(DEPLIBS)
$(CXX) $(CXXFLAGS) -o $@ client.o $(OBJECTS) $(LDFLAGS)

21
synergy/client.cpp Normal file
View File

@ -0,0 +1,21 @@
#include "CClient.h"
#include "CNetworkAddress.h"
#include <stdio.h>
int main(int argc, char** argv)
{
if (argc != 2) {
fprintf(stderr, "usage: %s <hostname>\n", argv[0]);
return 1;
}
try {
CClient* client = new CClient("ingrid");
client->run(CNetworkAddress(argv[1], 50001));
}
catch (XBase& e) {
fprintf(stderr, "failed: %s\n", e.what());
return 1;
}
return 0;
}

29
synergy/server.cpp Normal file
View File

@ -0,0 +1,29 @@
#include "CServer.h"
#include "CScreenMap.h"
#include <stdio.h>
int main(int argc, char** argv)
{
if (argc != 1) {
fprintf(stderr, "usage: %s\n", argv[0]);
return 1;
}
CScreenMap screenMap;
screenMap.addScreen("primary");
screenMap.addScreen("ingrid");
screenMap.connect("primary", CScreenMap::kRight, "ingrid");
screenMap.connect("ingrid", CScreenMap::kLeft, "primary");
try {
CServer* server = new CServer();
server->setScreenMap(screenMap);
server->run();
}
catch (XBase& e) {
fprintf(stderr, "failed: %s\n", e.what());
return 1;
}
return 0;
}