mirror of
https://github.com/debauchee/barrier.git
synced 2024-11-23 20:12:39 +03:00
checkpoint. still refactoring. merged common code from primary
screens into CPrimaryScreen and merged common code from secondary screens into CSecondaryScreen. changed is-a relationship to a has-a between the primary and secondary screen classes and the generic platform dependent screen class to avoid multiple inheritance of implementation. also standardized the interface for those generic screen classes. adding a platform now involves implementing simpler interfaces: IScreen for the generic screen, IScreenEventHandler and some methods of CPrimaryScreen for the primary screen, and IScreenEventHandler and some methods of CSecondaryScreen for the secondary screen. did X11 platform but not win32 platform.
This commit is contained in:
parent
52b60d5175
commit
f48a5fe387
@ -4,7 +4,7 @@
|
||||
#include "CInputPacketStream.h"
|
||||
#include "COutputPacketStream.h"
|
||||
#include "CProtocolUtil.h"
|
||||
#include "ISecondaryScreen.h"
|
||||
#include "CSecondaryScreen.h"
|
||||
#include "IServer.h"
|
||||
#include "ProtocolTypes.h"
|
||||
#include "XScreen.h"
|
||||
@ -148,9 +148,7 @@ CClient::run()
|
||||
this, &CClient::runSession));
|
||||
|
||||
// handle events
|
||||
log((CLOG_DEBUG "starting event handling"));
|
||||
m_screen->run();
|
||||
log((CLOG_DEBUG "stopped event handling"));
|
||||
|
||||
// clean up
|
||||
deleteSession(thread);
|
||||
@ -160,7 +158,6 @@ CClient::run()
|
||||
log((CLOG_ERR "client error: %s", e.what()));
|
||||
|
||||
// clean up
|
||||
log((CLOG_DEBUG "stopped event handling"));
|
||||
deleteSession(thread);
|
||||
log((CLOG_NOTE "stopping client \"%s\"", m_name.c_str()));
|
||||
CLock lock(&m_mutex);
|
||||
@ -168,7 +165,6 @@ CClient::run()
|
||||
}
|
||||
catch (XThread&) {
|
||||
// clean up
|
||||
log((CLOG_DEBUG "stopped event handling"));
|
||||
deleteSession(thread);
|
||||
log((CLOG_NOTE "stopping client \"%s\"", m_name.c_str()));
|
||||
throw;
|
||||
@ -177,7 +173,6 @@ CClient::run()
|
||||
log((CLOG_DEBUG "unknown client error"));
|
||||
|
||||
// clean up
|
||||
log((CLOG_DEBUG "stopped event handling"));
|
||||
deleteSession(thread);
|
||||
log((CLOG_NOTE "stopping client \"%s\"", m_name.c_str()));
|
||||
throw;
|
||||
@ -188,6 +183,7 @@ void
|
||||
CClient::close()
|
||||
{
|
||||
closeSecondaryScreen();
|
||||
log((CLOG_INFO "closed screen"));
|
||||
}
|
||||
|
||||
void
|
||||
@ -291,9 +287,9 @@ CClient::mouseWheel(SInt32 delta)
|
||||
}
|
||||
|
||||
void
|
||||
CClient::screenSaver(bool activate)
|
||||
CClient::screensaver(bool activate)
|
||||
{
|
||||
m_screen->screenSaver(activate);
|
||||
m_screen->screensaver(activate);
|
||||
}
|
||||
|
||||
CString
|
||||
@ -302,6 +298,12 @@ CClient::getName() const
|
||||
return m_name;
|
||||
}
|
||||
|
||||
SInt32
|
||||
CClient::getJumpZoneSize() const
|
||||
{
|
||||
return m_screen->getJumpZoneSize();
|
||||
}
|
||||
|
||||
void
|
||||
CClient::getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h) const
|
||||
{
|
||||
@ -309,21 +311,15 @@ CClient::getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h) const
|
||||
}
|
||||
|
||||
void
|
||||
CClient::getCenter(SInt32&, SInt32&) const
|
||||
CClient::getCursorPos(SInt32& x, SInt32& y) const
|
||||
{
|
||||
assert(0 && "shouldn't be called");
|
||||
m_screen->getCursorPos(x, y);
|
||||
}
|
||||
|
||||
void
|
||||
CClient::getMousePos(SInt32& x, SInt32& y) const
|
||||
CClient::getCursorCenter(SInt32&, SInt32&) const
|
||||
{
|
||||
m_screen->getMousePos(x, y);
|
||||
}
|
||||
|
||||
SInt32
|
||||
CClient::getJumpZoneSize() const
|
||||
{
|
||||
return m_screen->getJumpZoneSize();
|
||||
assert(0 && "shouldn't be called");
|
||||
}
|
||||
|
||||
// FIXME -- use factory to create screen
|
||||
|
@ -7,10 +7,10 @@
|
||||
#include "CNetworkAddress.h"
|
||||
#include "CMutex.h"
|
||||
|
||||
class CSecondaryScreen;
|
||||
class CServerProxy;
|
||||
class CThread;
|
||||
class IDataSocket;
|
||||
class ISecondaryScreen;
|
||||
class IScreenReceiver;
|
||||
|
||||
class CClient : public IScreenReceiver, public IClient {
|
||||
@ -50,7 +50,7 @@ public:
|
||||
// FIXME -- can we avoid passing everything here?
|
||||
virtual void enter(SInt32 xAbs, SInt32 yAbs,
|
||||
UInt32 seqNum, KeyModifierMask mask,
|
||||
bool screenSaver);
|
||||
bool forScreensaver);
|
||||
virtual bool leave();
|
||||
virtual void setClipboard(ClipboardID, const CString&);
|
||||
virtual void grabClipboard(ClipboardID);
|
||||
@ -62,13 +62,13 @@ public:
|
||||
virtual void mouseUp(ButtonID);
|
||||
virtual void mouseMove(SInt32 xAbs, SInt32 yAbs);
|
||||
virtual void mouseWheel(SInt32 delta);
|
||||
virtual void screenSaver(bool activate);
|
||||
virtual void screensaver(bool activate);
|
||||
virtual CString getName() const;
|
||||
virtual SInt32 getJumpZoneSize() const;
|
||||
virtual void getShape(SInt32& x, SInt32& y,
|
||||
SInt32& width, SInt32& height) const;
|
||||
virtual void getCenter(SInt32& x, SInt32& y) const;
|
||||
virtual void getMousePos(SInt32& x, SInt32& y) const;
|
||||
virtual SInt32 getJumpZoneSize() const;
|
||||
virtual void getCursorPos(SInt32& x, SInt32& y) const;
|
||||
virtual void getCursorCenter(SInt32& x, SInt32& y) const;
|
||||
|
||||
private:
|
||||
// open/close the secondary screen
|
||||
@ -87,7 +87,7 @@ private:
|
||||
private:
|
||||
CMutex m_mutex;
|
||||
CString m_name;
|
||||
ISecondaryScreen* m_screen;
|
||||
CSecondaryScreen* m_screen;
|
||||
IScreenReceiver* m_server;
|
||||
CNetworkAddress m_serverAddress;
|
||||
bool m_camp;
|
||||
|
263
client/CSecondaryScreen.cpp
Normal file
263
client/CSecondaryScreen.cpp
Normal file
@ -0,0 +1,263 @@
|
||||
#include "CSecondaryScreen.h"
|
||||
#include "IScreen.h"
|
||||
#include "CLock.h"
|
||||
#include "CThread.h"
|
||||
#include "CLog.h"
|
||||
|
||||
//
|
||||
// CSecondaryScreen
|
||||
//
|
||||
|
||||
CSecondaryScreen::CSecondaryScreen()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
CSecondaryScreen::~CSecondaryScreen()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
bool
|
||||
CSecondaryScreen::isActive() const
|
||||
{
|
||||
CLock lock(&m_mutex);
|
||||
return m_active;
|
||||
}
|
||||
|
||||
void
|
||||
CSecondaryScreen::run()
|
||||
{
|
||||
// change our priority
|
||||
CThread::getCurrentThread().setPriority(-7);
|
||||
|
||||
// run event loop
|
||||
try {
|
||||
log((CLOG_DEBUG "entering event loop"));
|
||||
onPreRun();
|
||||
getScreen()->mainLoop();
|
||||
onPostRun();
|
||||
log((CLOG_DEBUG "exiting event loop"));
|
||||
}
|
||||
catch (...) {
|
||||
onPostRun();
|
||||
log((CLOG_DEBUG "exiting event loop"));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CSecondaryScreen::stop()
|
||||
{
|
||||
getScreen()->exitMainLoop();
|
||||
}
|
||||
|
||||
void
|
||||
CSecondaryScreen::open()
|
||||
{
|
||||
try {
|
||||
// subclass hook
|
||||
onPreOpen();
|
||||
|
||||
// open the screen
|
||||
getScreen()->open();
|
||||
|
||||
// create and prepare our window
|
||||
createWindow();
|
||||
|
||||
// assume primary has all clipboards
|
||||
for (ClipboardID id = 0; id < kClipboardEnd; ++id) {
|
||||
grabClipboard(id);
|
||||
}
|
||||
|
||||
// update keyboard state
|
||||
updateKeys();
|
||||
|
||||
// disable the screen saver
|
||||
getScreen()->openScreenSaver(false);
|
||||
|
||||
// subclass hook
|
||||
onPostOpen();
|
||||
}
|
||||
catch (...) {
|
||||
close();
|
||||
throw;
|
||||
}
|
||||
|
||||
// hide the cursor
|
||||
m_active = true;
|
||||
leave();
|
||||
}
|
||||
|
||||
void
|
||||
CSecondaryScreen::close()
|
||||
{
|
||||
onPreClose();
|
||||
getScreen()->closeScreenSaver();
|
||||
destroyWindow();
|
||||
getScreen()->close();
|
||||
onPostClose();
|
||||
}
|
||||
|
||||
void
|
||||
CSecondaryScreen::enter(SInt32 x, SInt32 y, KeyModifierMask mask)
|
||||
{
|
||||
CLock lock(&m_mutex);
|
||||
assert(m_active == false);
|
||||
|
||||
log((CLOG_INFO "entering screen at %d,%d mask=%04x", x, y, mask));
|
||||
|
||||
getScreen()->syncDesktop();
|
||||
|
||||
// now active
|
||||
m_active = true;
|
||||
|
||||
// subclass hook
|
||||
onPreEnter();
|
||||
|
||||
// update our keyboard state to reflect the local state
|
||||
updateKeys();
|
||||
|
||||
// toggle modifiers that don't match the desired state
|
||||
setToggleState(mask);
|
||||
|
||||
// warp to requested location
|
||||
warpCursor(x, y);
|
||||
|
||||
// show mouse
|
||||
hideWindow();
|
||||
|
||||
// subclass hook
|
||||
onPostEnter();
|
||||
}
|
||||
|
||||
void
|
||||
CSecondaryScreen::leave()
|
||||
{
|
||||
log((CLOG_INFO "leaving screen"));
|
||||
CLock lock(&m_mutex);
|
||||
assert(m_active == true);
|
||||
|
||||
getScreen()->syncDesktop();
|
||||
|
||||
// subclass hook
|
||||
onPreLeave();
|
||||
|
||||
// hide mouse
|
||||
showWindow();
|
||||
|
||||
// subclass hook
|
||||
onPostLeave();
|
||||
|
||||
// not active anymore
|
||||
m_active = false;
|
||||
|
||||
// make sure our idea of clipboard ownership is correct
|
||||
getScreen()->checkClipboards();
|
||||
}
|
||||
|
||||
void
|
||||
CSecondaryScreen::setClipboard(ClipboardID id,
|
||||
const IClipboard* clipboard)
|
||||
{
|
||||
getScreen()->setClipboard(id, clipboard);
|
||||
}
|
||||
|
||||
void
|
||||
CSecondaryScreen::grabClipboard(ClipboardID id)
|
||||
{
|
||||
getScreen()->setClipboard(id, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
CSecondaryScreen::screensaver(bool activate)
|
||||
{
|
||||
getScreen()->screensaver(activate);
|
||||
}
|
||||
|
||||
void
|
||||
CSecondaryScreen::getClipboard(ClipboardID id,
|
||||
IClipboard* clipboard) const
|
||||
{
|
||||
getScreen()->getClipboard(id, clipboard);
|
||||
}
|
||||
|
||||
SInt32
|
||||
CSecondaryScreen::getJumpZoneSize() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
CSecondaryScreen::getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h) const
|
||||
{
|
||||
getScreen()->syncDesktop();
|
||||
getScreen()->getShape(x, y, w, h);
|
||||
}
|
||||
|
||||
void
|
||||
CSecondaryScreen::getCursorPos(SInt32& x, SInt32& y) const
|
||||
{
|
||||
getScreen()->syncDesktop();
|
||||
getScreen()->getCursorPos(x, y);
|
||||
}
|
||||
|
||||
void
|
||||
CSecondaryScreen::onPreRun()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CSecondaryScreen::onPostRun()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CSecondaryScreen::onPreOpen()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CSecondaryScreen::onPostOpen()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CSecondaryScreen::onPreClose()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CSecondaryScreen::onPostClose()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CSecondaryScreen::onPreEnter()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CSecondaryScreen::onPostEnter()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CSecondaryScreen::onPreLeave()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CSecondaryScreen::onPostLeave()
|
||||
{
|
||||
// do nothing
|
||||
}
|
141
client/CSecondaryScreen.h
Normal file
141
client/CSecondaryScreen.h
Normal file
@ -0,0 +1,141 @@
|
||||
#ifndef CSECONDARYSCREEN_H
|
||||
#define CSECONDARYSCREEN_H
|
||||
|
||||
#include "ClipboardTypes.h"
|
||||
#include "KeyTypes.h"
|
||||
#include "MouseTypes.h"
|
||||
#include "CMutex.h"
|
||||
|
||||
class IClipboard;
|
||||
class IScreen;
|
||||
|
||||
// platform independent base class for secondary screen implementations.
|
||||
// each platform will derive a class from CSecondaryScreen to handle
|
||||
// platform dependent operations.
|
||||
class CSecondaryScreen {
|
||||
public:
|
||||
CSecondaryScreen();
|
||||
virtual ~CSecondaryScreen();
|
||||
|
||||
// manipulators
|
||||
|
||||
// enter the screen's message loop. this returns when it detects
|
||||
// the application should terminate or when stop() is called.
|
||||
// run() may only be called between open() and close().
|
||||
void run();
|
||||
|
||||
// cause run() to return
|
||||
void stop();
|
||||
|
||||
// initialize the screen, hide the cursor, and disable the screen
|
||||
// saver. start reporting events to the IScreenReceiver (which is
|
||||
// set through some other interface).
|
||||
void open();
|
||||
|
||||
// close the screen. should restore the screen saver. it should
|
||||
// also simulate key up events for any keys that have simulate key
|
||||
// down events without a matching key up. without this the client
|
||||
// will leave its keyboard in the wrong logical state.
|
||||
void close();
|
||||
|
||||
// called when the user navigates to this secondary screen. warps
|
||||
// the cursor to the given absoltue coordinates and unhide it. prepare to
|
||||
// simulate input events.
|
||||
void enter(SInt32 x, SInt32 y, KeyModifierMask mask);
|
||||
|
||||
// called when the user navigates off the secondary screen. clean
|
||||
// up input event simulation and hide the cursor.
|
||||
void leave();
|
||||
|
||||
// set the screen's clipboard contents. this is usually called
|
||||
// soon after an enter().
|
||||
void setClipboard(ClipboardID, const IClipboard*);
|
||||
|
||||
// synergy should own the clipboard
|
||||
void grabClipboard(ClipboardID);
|
||||
|
||||
// activate or deactivate the screen saver
|
||||
void screensaver(bool activate);
|
||||
|
||||
// keyboard input event synthesis
|
||||
virtual void keyDown(KeyID, KeyModifierMask) = 0;
|
||||
virtual void keyRepeat(KeyID, KeyModifierMask, SInt32 count) = 0;
|
||||
virtual void keyUp(KeyID, KeyModifierMask) = 0;
|
||||
|
||||
// mouse input event synthesis
|
||||
virtual void mouseDown(ButtonID) = 0;
|
||||
virtual void mouseUp(ButtonID) = 0;
|
||||
virtual void mouseMove(SInt32 xAbsolute, SInt32 yAbsolute) = 0;
|
||||
virtual void mouseWheel(SInt32 delta) = 0;
|
||||
|
||||
// accessors
|
||||
|
||||
// returns true iff the screen is active (i.e. the user has entered
|
||||
// the screen)
|
||||
bool isActive() const;
|
||||
|
||||
// return the contents of the given clipboard
|
||||
void getClipboard(ClipboardID, IClipboard*) const;
|
||||
|
||||
// returns the size of the zone on the edges of the screen that
|
||||
// causes the cursor to jump to another screen. default returns 0.
|
||||
virtual SInt32 getJumpZoneSize() const;
|
||||
|
||||
// get the shape (position of upper-left corner and size) of the
|
||||
// screen
|
||||
virtual void getShape(SInt32& x, SInt32& y,
|
||||
SInt32& width, SInt32& height) const;
|
||||
|
||||
// get the position of the mouse on the screen
|
||||
virtual void getCursorPos(SInt32& x, SInt32& y) const;
|
||||
|
||||
// get the platform dependent screen object
|
||||
virtual IScreen* getScreen() const = 0;
|
||||
|
||||
protected:
|
||||
// template method hooks. these are called on entry/exit to the
|
||||
// named method. override to do platform specific operations.
|
||||
// defaults do nothing.
|
||||
virtual void onPreRun();
|
||||
virtual void onPostRun();
|
||||
virtual void onPreOpen();
|
||||
virtual void onPostOpen();
|
||||
virtual void onPreClose();
|
||||
virtual void onPostClose();
|
||||
virtual void onPreEnter();
|
||||
virtual void onPostEnter();
|
||||
virtual void onPreLeave();
|
||||
virtual void onPostLeave();
|
||||
|
||||
// create/destroy the window. this window is generally used to
|
||||
// receive events and hide the cursor.
|
||||
virtual void createWindow() = 0;
|
||||
virtual void destroyWindow() = 0;
|
||||
|
||||
// called when the user navigates off the secondary screen. hide
|
||||
// the cursor.
|
||||
virtual void showWindow() = 0;
|
||||
|
||||
// called when the user navigates to this secondary screen. show
|
||||
// the cursor and prepare to synthesize input events.
|
||||
virtual void hideWindow() = 0;
|
||||
|
||||
// warp the cursor to the given absolute coordinates
|
||||
virtual void warpCursor(SInt32 x, SInt32 y) = 0;
|
||||
|
||||
// check the current keyboard state. normally a screen will save
|
||||
// the keyboard state in this method and use this shadow state
|
||||
// when synthesizing events.
|
||||
virtual void updateKeys() = 0;
|
||||
|
||||
// toggle modifiers that don't match the given state
|
||||
virtual void setToggleState(KeyModifierMask) = 0;
|
||||
|
||||
private:
|
||||
CMutex m_mutex;
|
||||
|
||||
// m_active is true if this screen has been entered
|
||||
bool m_active;
|
||||
};
|
||||
|
||||
#endif
|
@ -131,7 +131,7 @@ CServerProxy::run()
|
||||
}
|
||||
|
||||
else if (memcmp(code, kMsgCScreenSaver, 4) == 0) {
|
||||
screenSaver();
|
||||
screensaver();
|
||||
}
|
||||
|
||||
else if (memcmp(code, kMsgQInfo, 4) == 0) {
|
||||
@ -484,7 +484,7 @@ CServerProxy::mouseWheel()
|
||||
}
|
||||
|
||||
void
|
||||
CServerProxy::screenSaver()
|
||||
CServerProxy::screensaver()
|
||||
{
|
||||
// parse
|
||||
SInt8 on;
|
||||
@ -492,7 +492,7 @@ CServerProxy::screenSaver()
|
||||
log((CLOG_DEBUG1 "recv screen saver on=%d", on));
|
||||
|
||||
// forward
|
||||
getClient()->screenSaver(on != 0);
|
||||
getClient()->screensaver(on != 0);
|
||||
}
|
||||
|
||||
void
|
||||
@ -501,7 +501,7 @@ CServerProxy::queryInfo()
|
||||
// get current info
|
||||
CClientInfo info;
|
||||
getClient()->getShape(info.m_x, info.m_y, info.m_w, info.m_h);
|
||||
getClient()->getMousePos(info.m_mx, info.m_my);
|
||||
getClient()->getCursorPos(info.m_mx, info.m_my);
|
||||
info.m_zoneSize = getClient()->getJumpZoneSize();
|
||||
|
||||
// send it
|
||||
|
@ -56,7 +56,7 @@ private:
|
||||
void mouseUp();
|
||||
void mouseMove();
|
||||
void mouseWheel();
|
||||
void screenSaver();
|
||||
void screensaver();
|
||||
void queryInfo();
|
||||
void infoAcknowledgment();
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
#include "CXWindowsSecondaryScreen.h"
|
||||
#include "IScreenReceiver.h"
|
||||
#include "CXWindowsClipboard.h"
|
||||
#include "CXWindowsScreen.h"
|
||||
#include "CXWindowsScreenSaver.h"
|
||||
#include "CXWindowsUtil.h"
|
||||
#include "IScreenReceiver.h"
|
||||
#include "XScreen.h"
|
||||
#include "CThread.h"
|
||||
#include "CLog.h"
|
||||
@ -26,153 +27,16 @@
|
||||
//
|
||||
|
||||
CXWindowsSecondaryScreen::CXWindowsSecondaryScreen(IScreenReceiver* receiver) :
|
||||
m_receiver(receiver),
|
||||
m_window(None),
|
||||
m_active(false)
|
||||
CSecondaryScreen(),
|
||||
m_window(None)
|
||||
{
|
||||
assert(m_receiver != NULL);
|
||||
m_screen = new CXWindowsScreen(receiver, this);
|
||||
}
|
||||
|
||||
CXWindowsSecondaryScreen::~CXWindowsSecondaryScreen()
|
||||
{
|
||||
assert(m_window == None);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::run()
|
||||
{
|
||||
assert(m_window != None);
|
||||
|
||||
// change our priority
|
||||
CThread::getCurrentThread().setPriority(-7);
|
||||
|
||||
// run event loop
|
||||
try {
|
||||
log((CLOG_INFO "entering event loop"));
|
||||
mainLoop();
|
||||
log((CLOG_INFO "exiting event loop"));
|
||||
}
|
||||
catch (...) {
|
||||
log((CLOG_INFO "exiting event loop"));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::stop()
|
||||
{
|
||||
exitMainLoop();
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::open()
|
||||
{
|
||||
assert(m_window == None);
|
||||
|
||||
try {
|
||||
// open the display
|
||||
openDisplay();
|
||||
|
||||
// create and prepare our window
|
||||
createWindow();
|
||||
|
||||
// initialize the clipboards; assume primary has all clipboards
|
||||
initClipboards(m_window);
|
||||
for (ClipboardID id = 0; id < kClipboardEnd; ++id) {
|
||||
grabClipboard(id);
|
||||
}
|
||||
|
||||
// check for peculiarities
|
||||
// FIXME -- may have to get these from some database
|
||||
m_numLockHalfDuplex = false;
|
||||
m_capsLockHalfDuplex = false;
|
||||
// m_numLockHalfDuplex = true;
|
||||
// m_capsLockHalfDuplex = true;
|
||||
|
||||
// get the display
|
||||
CDisplayLock display(this);
|
||||
|
||||
// update key state
|
||||
updateKeys(display);
|
||||
updateKeycodeMap(display);
|
||||
updateModifierMap(display);
|
||||
updateModifiers(display);
|
||||
|
||||
// disable the screen saver
|
||||
installScreenSaver();
|
||||
}
|
||||
catch (...) {
|
||||
close();
|
||||
throw;
|
||||
}
|
||||
|
||||
// hide the cursor
|
||||
m_active = true;
|
||||
leave();
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::close()
|
||||
{
|
||||
uninstallScreenSaver();
|
||||
destroyWindow();
|
||||
closeDisplay();
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::enter(SInt32 x, SInt32 y, KeyModifierMask mask)
|
||||
{
|
||||
assert(m_window != None);
|
||||
assert(m_active == false);
|
||||
|
||||
log((CLOG_INFO "entering screen at %d,%d mask=%04x", x, y, mask));
|
||||
|
||||
CDisplayLock display(this);
|
||||
|
||||
// now active
|
||||
m_active = true;
|
||||
|
||||
// update our keyboard state to reflect the local state
|
||||
updateKeys(display);
|
||||
updateModifiers(display);
|
||||
|
||||
// toggle modifiers that don't match the desired state
|
||||
unsigned int xMask = maskToX(mask);
|
||||
if ((xMask & m_capsLockMask) != (m_mask & m_capsLockMask)) {
|
||||
toggleKey(display, XK_Caps_Lock, m_capsLockMask);
|
||||
}
|
||||
if ((xMask & m_numLockMask) != (m_mask & m_numLockMask)) {
|
||||
toggleKey(display, XK_Num_Lock, m_numLockMask);
|
||||
}
|
||||
if ((xMask & m_scrollLockMask) != (m_mask & m_scrollLockMask)) {
|
||||
toggleKey(display, XK_Scroll_Lock, m_scrollLockMask);
|
||||
}
|
||||
|
||||
// warp to requested location
|
||||
warpCursor(x, y);
|
||||
|
||||
// show mouse
|
||||
hideWindow();
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::leave()
|
||||
{
|
||||
assert(m_window != None);
|
||||
assert(m_active == true);
|
||||
|
||||
log((CLOG_INFO "leaving screen"));
|
||||
|
||||
CDisplayLock display(this);
|
||||
|
||||
// hide mouse
|
||||
showWindow();
|
||||
|
||||
// not active anymore
|
||||
m_active = false;
|
||||
|
||||
// make sure our idea of clipboard ownership is correct
|
||||
checkClipboard();
|
||||
delete m_screen;
|
||||
}
|
||||
|
||||
void
|
||||
@ -236,7 +100,7 @@ CXWindowsSecondaryScreen::keyUp(KeyID key, KeyModifierMask mask)
|
||||
void
|
||||
CXWindowsSecondaryScreen::mouseDown(ButtonID button)
|
||||
{
|
||||
CDisplayLock display(this);
|
||||
CDisplayLock display(m_screen);
|
||||
XTestFakeButtonEvent(display, mapButton(button), True, CurrentTime);
|
||||
XSync(display, False);
|
||||
}
|
||||
@ -244,7 +108,7 @@ CXWindowsSecondaryScreen::mouseDown(ButtonID button)
|
||||
void
|
||||
CXWindowsSecondaryScreen::mouseUp(ButtonID button)
|
||||
{
|
||||
CDisplayLock display(this);
|
||||
CDisplayLock display(m_screen);
|
||||
XTestFakeButtonEvent(display, mapButton(button), False, CurrentTime);
|
||||
XSync(display, False);
|
||||
}
|
||||
@ -252,7 +116,6 @@ CXWindowsSecondaryScreen::mouseUp(ButtonID button)
|
||||
void
|
||||
CXWindowsSecondaryScreen::mouseMove(SInt32 x, SInt32 y)
|
||||
{
|
||||
CDisplayLock display(this);
|
||||
warpCursor(x, y);
|
||||
}
|
||||
|
||||
@ -268,7 +131,7 @@ CXWindowsSecondaryScreen::mouseWheel(SInt32 delta)
|
||||
}
|
||||
|
||||
// send as many clicks as necessary
|
||||
CDisplayLock display(this);
|
||||
CDisplayLock display(m_screen);
|
||||
for (; delta >= 120; delta -= 120) {
|
||||
XTestFakeButtonEvent(display, button, True, CurrentTime);
|
||||
XTestFakeButtonEvent(display, button, False, CurrentTime);
|
||||
@ -276,63 +139,29 @@ CXWindowsSecondaryScreen::mouseWheel(SInt32 delta)
|
||||
XSync(display, False);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::setClipboard(ClipboardID id,
|
||||
const IClipboard* clipboard)
|
||||
IScreen*
|
||||
CXWindowsSecondaryScreen::getScreen() const
|
||||
{
|
||||
setDisplayClipboard(id, clipboard);
|
||||
return m_screen;
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::grabClipboard(ClipboardID id)
|
||||
CXWindowsSecondaryScreen::onScreensaver(bool)
|
||||
{
|
||||
setDisplayClipboard(id, NULL);
|
||||
// ignore
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::screenSaver(bool activate)
|
||||
CXWindowsSecondaryScreen::onError()
|
||||
{
|
||||
CDisplayLock display(this);
|
||||
if (activate) {
|
||||
getScreenSaver()->activate();
|
||||
}
|
||||
else {
|
||||
getScreenSaver()->deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::getMousePos(SInt32& x, SInt32& y) const
|
||||
{
|
||||
CDisplayLock display(this);
|
||||
getCursorPos(x, y);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::getShape(
|
||||
SInt32& x, SInt32& y, SInt32& w, SInt32& h) const
|
||||
{
|
||||
getScreenShape(x, y, w, h);
|
||||
}
|
||||
|
||||
SInt32
|
||||
CXWindowsSecondaryScreen::getJumpZoneSize() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::getClipboard(ClipboardID id,
|
||||
IClipboard* clipboard) const
|
||||
{
|
||||
getDisplayClipboard(id, clipboard);
|
||||
// ignore
|
||||
// FIXME -- forward this? to whom?
|
||||
}
|
||||
|
||||
bool
|
||||
CXWindowsSecondaryScreen::onPreDispatch(const CEvent* event)
|
||||
CXWindowsSecondaryScreen::onPreDispatch(const CEvent*)
|
||||
{
|
||||
// forward to superclass
|
||||
return CXWindowsScreen::onPreDispatch(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -344,77 +173,58 @@ CXWindowsSecondaryScreen::onEvent(CEvent* event)
|
||||
// handle event
|
||||
switch (xevent.type) {
|
||||
case MappingNotify:
|
||||
{
|
||||
// keyboard mapping changed
|
||||
CDisplayLock display(this);
|
||||
XRefreshKeyboardMapping(&xevent.xmapping);
|
||||
updateKeys(display);
|
||||
updateKeycodeMap(display);
|
||||
updateModifierMap(display);
|
||||
updateModifiers(display);
|
||||
}
|
||||
updateKeys();
|
||||
return true;
|
||||
|
||||
case LeaveNotify:
|
||||
{
|
||||
// mouse moved out of hider window somehow. hide the window.
|
||||
assert(m_window != None);
|
||||
CDisplayLock display(this);
|
||||
hideWindow();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::onLostClipboard(ClipboardID id)
|
||||
CXWindowsSecondaryScreen::onPreRun()
|
||||
{
|
||||
// tell client that the clipboard was grabbed locally
|
||||
m_receiver->onGrabClipboard(id);
|
||||
assert(m_window != None);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::showWindow()
|
||||
CXWindowsSecondaryScreen::onPreOpen()
|
||||
{
|
||||
// move hider window under the mouse (rather than moving the mouse
|
||||
// somewhere else on the screen)
|
||||
SInt32 x, y;
|
||||
getCursorPos(x, y);
|
||||
XMoveWindow(getDisplay(), m_window, x, y);
|
||||
|
||||
// raise and show the hider window. take activation.
|
||||
// FIXME -- take focus?
|
||||
XMapRaised(getDisplay(), m_window);
|
||||
|
||||
/* XXX -- this should have no effect
|
||||
// hide cursor by moving it into the hider window
|
||||
XWarpPointer(getDisplay(), None, m_window, 0, 0, 0, 0, 0, 0);
|
||||
*/
|
||||
assert(m_window == None);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::hideWindow()
|
||||
CXWindowsSecondaryScreen::onPostOpen()
|
||||
{
|
||||
XUnmapWindow(getDisplay(), m_window);
|
||||
// check for peculiarities
|
||||
// FIXME -- may have to get these from some database
|
||||
m_numLockHalfDuplex = false;
|
||||
m_capsLockHalfDuplex = false;
|
||||
// m_numLockHalfDuplex = true;
|
||||
// m_capsLockHalfDuplex = true;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::warpCursor(SInt32 x, SInt32 y)
|
||||
CXWindowsSecondaryScreen::onPreEnter()
|
||||
{
|
||||
XTestFakeMotionEvent(getDisplay(), getScreen(), x, y, CurrentTime);
|
||||
XSync(getDisplay(), False);
|
||||
assert(m_window != None);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::checkClipboard()
|
||||
CXWindowsSecondaryScreen::onPreLeave()
|
||||
{
|
||||
// do nothing, we're always up to date
|
||||
assert(m_window != None);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::createWindow()
|
||||
{
|
||||
CDisplayLock display(this);
|
||||
{
|
||||
CDisplayLock display(m_screen);
|
||||
|
||||
// verify the availability of the XTest extension
|
||||
int majorOpcode, firstEvent, firstError;
|
||||
@ -432,10 +242,10 @@ CXWindowsSecondaryScreen::createWindow()
|
||||
attr.event_mask = LeaveWindowMask;
|
||||
attr.do_not_propagate_mask = 0;
|
||||
attr.override_redirect = True;
|
||||
attr.cursor = getBlankCursor();
|
||||
attr.cursor = m_screen->getBlankCursor();
|
||||
|
||||
// create the cursor hider window
|
||||
m_window = XCreateWindow(display, getRoot(),
|
||||
m_window = XCreateWindow(display, m_screen->getRoot(),
|
||||
0, 0, 1, 1, 0, 0,
|
||||
InputOnly, CopyFromParent,
|
||||
CWDontPropagate | CWEventMask |
|
||||
@ -450,13 +260,18 @@ CXWindowsSecondaryScreen::createWindow()
|
||||
XTestGrabControl(display, True);
|
||||
}
|
||||
|
||||
// tell our superclass about the window
|
||||
m_screen->setWindow(m_window);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::destroyWindow()
|
||||
{
|
||||
releaseKeys();
|
||||
|
||||
CDisplayLock display(this);
|
||||
CDisplayLock display(m_screen);
|
||||
if (display != NULL) {
|
||||
// release keys that are still pressed
|
||||
releaseKeys(display);
|
||||
|
||||
// no longer impervious to server grabs
|
||||
XTestGrabControl(display, False);
|
||||
|
||||
@ -465,19 +280,66 @@ CXWindowsSecondaryScreen::destroyWindow()
|
||||
XDestroyWindow(display, m_window);
|
||||
m_window = None;
|
||||
}
|
||||
|
||||
// update
|
||||
XSync(display, False);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::installScreenSaver()
|
||||
CXWindowsSecondaryScreen::showWindow()
|
||||
{
|
||||
getScreenSaver()->disable();
|
||||
// move hider window under the mouse (rather than moving the mouse
|
||||
// somewhere else on the screen)
|
||||
SInt32 x, y;
|
||||
getCursorPos(x, y);
|
||||
CDisplayLock display(m_screen);
|
||||
XMoveWindow(display, m_window, x, y);
|
||||
|
||||
// raise and show the hider window. take activation.
|
||||
// FIXME -- take focus?
|
||||
XMapRaised(display, m_window);
|
||||
|
||||
/* XXX -- this should have no effect
|
||||
// hide cursor by moving it into the hider window
|
||||
XWarpPointer(display, None, m_window, 0, 0, 0, 0, 0, 0);
|
||||
*/
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::uninstallScreenSaver()
|
||||
CXWindowsSecondaryScreen::hideWindow()
|
||||
{
|
||||
getScreenSaver()->enable();
|
||||
assert(m_window != None);
|
||||
|
||||
CDisplayLock display(m_screen);
|
||||
XUnmapWindow(display, m_window);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::warpCursor(SInt32 x, SInt32 y)
|
||||
{
|
||||
CDisplayLock display(m_screen);
|
||||
Display* pDisplay = display;
|
||||
XTestFakeMotionEvent(display, DefaultScreen(pDisplay), x, y, CurrentTime);
|
||||
XSync(display, False);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::setToggleState(KeyModifierMask mask)
|
||||
{
|
||||
CDisplayLock display(m_screen);
|
||||
|
||||
// toggle modifiers that don't match the desired state
|
||||
unsigned int xMask = maskToX(mask);
|
||||
if ((xMask & m_capsLockMask) != (m_mask & m_capsLockMask)) {
|
||||
toggleKey(display, XK_Caps_Lock, m_capsLockMask);
|
||||
}
|
||||
if ((xMask & m_numLockMask) != (m_mask & m_numLockMask)) {
|
||||
toggleKey(display, XK_Num_Lock, m_numLockMask);
|
||||
}
|
||||
if ((xMask & m_scrollLockMask) != (m_mask & m_scrollLockMask)) {
|
||||
toggleKey(display, XK_Scroll_Lock, m_scrollLockMask);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int
|
||||
@ -848,7 +710,7 @@ CXWindowsSecondaryScreen::doKeystrokes(const Keystrokes& keys, SInt32 count)
|
||||
}
|
||||
|
||||
// lock display
|
||||
CDisplayLock display(this);
|
||||
CDisplayLock display(m_screen);
|
||||
|
||||
// generate key events
|
||||
for (Keystrokes::const_iterator k = keys.begin(); k != keys.end(); ) {
|
||||
@ -910,11 +772,10 @@ CXWindowsSecondaryScreen::maskToX(KeyModifierMask inMask) const
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::releaseKeys()
|
||||
CXWindowsSecondaryScreen::releaseKeys(Display* display)
|
||||
{
|
||||
CDisplayLock display(this);
|
||||
assert(display != NULL);
|
||||
|
||||
if (display != NULL) {
|
||||
// key up for each key that's down
|
||||
for (UInt32 i = 0; i < 256; ++i) {
|
||||
if (m_keys[i]) {
|
||||
@ -922,15 +783,13 @@ CXWindowsSecondaryScreen::releaseKeys()
|
||||
m_keys[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
// update
|
||||
XSync(display, False);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsSecondaryScreen::updateKeys(Display* display)
|
||||
CXWindowsSecondaryScreen::updateKeys()
|
||||
{
|
||||
CDisplayLock display(m_screen);
|
||||
|
||||
// ask server which keys are pressed
|
||||
char keys[32];
|
||||
XQueryKeymap(display, keys);
|
||||
@ -946,6 +805,11 @@ CXWindowsSecondaryScreen::updateKeys(Display* display)
|
||||
m_keys[j + 6] = ((keys[i] & 0x40) != 0);
|
||||
m_keys[j + 7] = ((keys[i] & 0x80) != 0);
|
||||
}
|
||||
|
||||
// update mappings and current modifiers
|
||||
updateKeycodeMap(display);
|
||||
updateModifierMap(display);
|
||||
updateModifiers(display);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1,47 +1,55 @@
|
||||
#ifndef CXWINDOWSSECONDARYSCREEN_H
|
||||
#define CXWINDOWSSECONDARYSCREEN_H
|
||||
|
||||
#include "CXWindowsScreen.h"
|
||||
#include "ISecondaryScreen.h"
|
||||
#include "CSecondaryScreen.h"
|
||||
#include "IScreenEventHandler.h"
|
||||
#include "stdmap.h"
|
||||
#include "stdvector.h"
|
||||
#if defined(X_DISPLAY_MISSING)
|
||||
# error X11 is required to build synergy
|
||||
#else
|
||||
# include <X11/Xlib.h>
|
||||
#endif
|
||||
|
||||
class CXWindowsScreen;
|
||||
class IScreenReceiver;
|
||||
|
||||
class CXWindowsSecondaryScreen : public CXWindowsScreen,
|
||||
public ISecondaryScreen {
|
||||
class CXWindowsSecondaryScreen :
|
||||
public CSecondaryScreen, public IScreenEventHandler {
|
||||
public:
|
||||
CXWindowsSecondaryScreen(IScreenReceiver*);
|
||||
virtual ~CXWindowsSecondaryScreen();
|
||||
|
||||
// ISecondaryScreen overrides
|
||||
virtual void run();
|
||||
virtual void stop();
|
||||
virtual void open();
|
||||
virtual void close();
|
||||
virtual void enter(SInt32 xAbsolute, SInt32 yAbsolute,
|
||||
KeyModifierMask mask);
|
||||
virtual void leave();
|
||||
// CSecondaryScreen overrides
|
||||
virtual void keyDown(KeyID, KeyModifierMask);
|
||||
virtual void keyRepeat(KeyID, KeyModifierMask, SInt32 count);
|
||||
virtual void keyUp(KeyID, KeyModifierMask);
|
||||
virtual void mouseDown(ButtonID);
|
||||
virtual void mouseUp(ButtonID);
|
||||
virtual void mouseMove(SInt32 xAbsolute, SInt32 yAbsolute);
|
||||
virtual void mouseMove(SInt32 x, SInt32 y);
|
||||
virtual void mouseWheel(SInt32 delta);
|
||||
virtual void setClipboard(ClipboardID, const IClipboard*);
|
||||
virtual void grabClipboard(ClipboardID);
|
||||
virtual void screenSaver(bool activate);
|
||||
virtual void getMousePos(SInt32& x, SInt32& y) const;
|
||||
virtual void getShape(SInt32&, SInt32&, SInt32&, SInt32&) const;
|
||||
virtual SInt32 getJumpZoneSize() const;
|
||||
virtual void getClipboard(ClipboardID, IClipboard*) const;
|
||||
virtual IScreen* getScreen() const;
|
||||
|
||||
protected:
|
||||
// CXWindowsScreen overrides
|
||||
// IScreenEventHandler overrides
|
||||
virtual void onError();
|
||||
virtual void onScreensaver(bool activated);
|
||||
virtual bool onPreDispatch(const CEvent* event);
|
||||
virtual bool onEvent(CEvent* event);
|
||||
virtual void onLostClipboard(ClipboardID);
|
||||
|
||||
protected:
|
||||
// CSecondaryScreen overrides
|
||||
virtual void onPreRun();
|
||||
virtual void onPreOpen();
|
||||
virtual void onPostOpen();
|
||||
virtual void onPreEnter();
|
||||
virtual void onPreLeave();
|
||||
virtual void createWindow();
|
||||
virtual void destroyWindow();
|
||||
virtual void showWindow();
|
||||
virtual void hideWindow();
|
||||
virtual void warpCursor(SInt32 x, SInt32 y);
|
||||
virtual void updateKeys();
|
||||
virtual void setToggleState(KeyModifierMask);
|
||||
|
||||
private:
|
||||
enum EKeyAction { kPress, kRelease, kRepeat };
|
||||
@ -62,26 +70,6 @@ private:
|
||||
typedef std::map<KeyID, KeyCodeMask> KeyCodeMap;
|
||||
typedef std::map<KeyCode, unsigned int> ModifierMap;
|
||||
|
||||
void showWindow();
|
||||
void hideWindow();
|
||||
|
||||
// warp the mouse to the specified position
|
||||
void warpCursor(SInt32 x, SInt32 y);
|
||||
|
||||
// check clipboard ownership and, if necessary, tell the receiver
|
||||
// of a grab.
|
||||
void checkClipboard();
|
||||
|
||||
// create/destroy window
|
||||
// also attach to desktop; this destroys and recreates the window
|
||||
// as necessary.
|
||||
void createWindow();
|
||||
void destroyWindow();
|
||||
|
||||
// start/stop watch for screen saver changes
|
||||
void installScreenSaver();
|
||||
void uninstallScreenSaver();
|
||||
|
||||
unsigned int mapButton(ButtonID button) const;
|
||||
|
||||
unsigned int mapKey(Keystrokes&, KeyCode&, KeyID,
|
||||
@ -91,8 +79,7 @@ private:
|
||||
void doKeystrokes(const Keystrokes&, SInt32 count);
|
||||
unsigned int maskToX(KeyModifierMask) const;
|
||||
|
||||
void releaseKeys();
|
||||
void updateKeys(Display* display);
|
||||
void releaseKeys(Display*);
|
||||
void updateKeycodeMap(Display* display);
|
||||
void updateModifiers(Display* display);
|
||||
void updateModifierMap(Display* display);
|
||||
@ -100,12 +87,9 @@ private:
|
||||
static bool isToggleKeysym(KeySym);
|
||||
|
||||
private:
|
||||
IScreenReceiver* m_receiver;
|
||||
CXWindowsScreen* m_screen;
|
||||
Window m_window;
|
||||
|
||||
// m_active is true if this screen has been entered
|
||||
bool m_active;
|
||||
|
||||
// note toggle keys that toggles on up/down (false) or on
|
||||
// transition (true)
|
||||
bool m_numLockHalfDuplex;
|
||||
|
@ -1,82 +0,0 @@
|
||||
#ifndef ISECONDARYSCREEN_H
|
||||
#define ISECONDARYSCREEN_H
|
||||
|
||||
#include "IInterface.h"
|
||||
#include "ClipboardTypes.h"
|
||||
#include "KeyTypes.h"
|
||||
#include "MouseTypes.h"
|
||||
|
||||
class IClipboard;
|
||||
|
||||
class ISecondaryScreen : public IInterface {
|
||||
public:
|
||||
// manipulators
|
||||
|
||||
// enter the screen's message loop. this returns when it detects
|
||||
// the application should terminate or when stop() is called.
|
||||
// the screen must be open()'d before run() and must not be
|
||||
// close()'d until run() returns.
|
||||
virtual void run() = 0;
|
||||
|
||||
// cause run() to return
|
||||
virtual void stop() = 0;
|
||||
|
||||
// initialize the screen, hide the cursor, and disable the screen
|
||||
// saver. start reporting events to the IScreenReceiver (which is
|
||||
// set through some other interface).
|
||||
virtual void open() = 0;
|
||||
|
||||
// close the screen. should restore the screen saver. it should
|
||||
// also simulate key up events for any keys that have simulate key
|
||||
// down events without a matching key up. without this the client
|
||||
// will leave its keyboard in the wrong logical state.
|
||||
virtual void close() = 0;
|
||||
|
||||
// called when the user navigates to the secondary screen. warp
|
||||
// the cursor to the given coordinates and unhide it. prepare to
|
||||
// simulate input events.
|
||||
virtual void enter(SInt32 xAbsolute, SInt32 yAbsolute,
|
||||
KeyModifierMask mask) = 0;
|
||||
|
||||
// called when the user navigates off the secondary screen. clean
|
||||
// up input event simulation and hide the cursor.
|
||||
virtual void leave() = 0;
|
||||
|
||||
// keyboard input simulation
|
||||
virtual void keyDown(KeyID, KeyModifierMask) = 0;
|
||||
virtual void keyRepeat(KeyID, KeyModifierMask, SInt32 count) = 0;
|
||||
virtual void keyUp(KeyID, KeyModifierMask) = 0;
|
||||
|
||||
// mouse input simulation
|
||||
virtual void mouseDown(ButtonID) = 0;
|
||||
virtual void mouseUp(ButtonID) = 0;
|
||||
virtual void mouseMove(SInt32 xAbsolute, SInt32 yAbsolute) = 0;
|
||||
virtual void mouseWheel(SInt32 delta) = 0;
|
||||
|
||||
// set the screen's clipboard contents. this is usually called
|
||||
// soon after an enter().
|
||||
virtual void setClipboard(ClipboardID, const IClipboard*) = 0;
|
||||
|
||||
// take ownership of clipboard
|
||||
virtual void grabClipboard(ClipboardID) = 0;
|
||||
|
||||
// activate or deactivate the screen saver
|
||||
virtual void screenSaver(bool activate) = 0;
|
||||
|
||||
// accessors
|
||||
|
||||
// get the position of the mouse on the screen
|
||||
virtual void getMousePos(SInt32& x, SInt32& y) const = 0;
|
||||
|
||||
// get the size of the screen
|
||||
virtual void getShape(SInt32& x, SInt32& y,
|
||||
SInt32& width, SInt32& height) const = 0;
|
||||
|
||||
// get the size of jump zone
|
||||
virtual SInt32 getJumpZoneSize() const = 0;
|
||||
|
||||
// get the screen's clipboard contents
|
||||
virtual void getClipboard(ClipboardID, IClipboard*) const = 0;
|
||||
};
|
||||
|
||||
#endif
|
@ -5,13 +5,14 @@ DEPTH = ..
|
||||
bin_PROGRAMS = synergy
|
||||
synergy_SOURCES = \
|
||||
CClient.cpp \
|
||||
CSecondaryScreen.cpp \
|
||||
CServerProxy.cpp \
|
||||
CXWindowsSecondaryScreen.cpp \
|
||||
client.cpp \
|
||||
CClient.h \
|
||||
CSecondaryScreen.h \
|
||||
CServerProxy.h \
|
||||
CXWindowsSecondaryScreen.h \
|
||||
ISecondaryScreen.h \
|
||||
$(NULL)
|
||||
synergy_LDADD = \
|
||||
$(DEPTH)/platform/libplatform.a \
|
||||
|
@ -116,9 +116,11 @@ realMain(CMutex* mutex)
|
||||
if (!locked && mutex != NULL) {
|
||||
mutex->lock();
|
||||
}
|
||||
if (s_client != NULL) {
|
||||
s_client->close();
|
||||
delete s_client;
|
||||
s_client = NULL;
|
||||
}
|
||||
CLog::setLock(NULL);
|
||||
s_logMutex = NULL;
|
||||
throw;
|
||||
|
@ -3,14 +3,22 @@
|
||||
#include "CXWindowsScreenSaver.h"
|
||||
#include "CXWindowsUtil.h"
|
||||
#include "CClipboard.h"
|
||||
#include "IScreenEventHandler.h"
|
||||
#include "IScreenReceiver.h"
|
||||
#include "XScreen.h"
|
||||
#include "CLock.h"
|
||||
#include "CThread.h"
|
||||
#include "CLog.h"
|
||||
#include "IJob.h"
|
||||
#include "CString.h"
|
||||
#include <cstdlib>
|
||||
//#include "CString.h"
|
||||
//#include <cstdlib>
|
||||
#include <cstring>
|
||||
#if defined(X_DISPLAY_MISSING)
|
||||
# error X11 is required to build synergy
|
||||
#else
|
||||
# include <X11/X.h>
|
||||
# include <X11/Xutil.h>
|
||||
#endif
|
||||
|
||||
//
|
||||
// CXWindowsScreen::CTimer
|
||||
@ -68,15 +76,24 @@ CXWindowsScreen::CTimer::operator<(const CTimer& t) const
|
||||
|
||||
CXWindowsScreen* CXWindowsScreen::s_screen = NULL;
|
||||
|
||||
CXWindowsScreen::CXWindowsScreen() :
|
||||
CXWindowsScreen::CXWindowsScreen(IScreenReceiver* receiver,
|
||||
IScreenEventHandler* eventHandler) :
|
||||
m_display(NULL),
|
||||
m_root(None),
|
||||
m_stop(false),
|
||||
m_receiver(receiver),
|
||||
m_eventHandler(eventHandler),
|
||||
m_window(None),
|
||||
m_x(0), m_y(0),
|
||||
m_w(0), m_h(0),
|
||||
m_stop(false),
|
||||
m_screenSaver(NULL)
|
||||
m_screensaver(NULL),
|
||||
m_screensaverNotify(false),
|
||||
m_atomScreensaver(None)
|
||||
{
|
||||
assert(s_screen == NULL);
|
||||
assert(m_receiver != NULL);
|
||||
assert(m_eventHandler != NULL);
|
||||
|
||||
s_screen = this;
|
||||
}
|
||||
|
||||
@ -120,6 +137,77 @@ CXWindowsScreen::removeTimerNoLock(IJob* job)
|
||||
m_timers.swap(tmp);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsScreen::setWindow(Window window)
|
||||
{
|
||||
CLock lock(&m_mutex);
|
||||
assert(m_display != NULL);
|
||||
|
||||
// destroy the clipboards
|
||||
for (ClipboardID id = 0; id < kClipboardEnd; ++id) {
|
||||
delete m_clipboard[id];
|
||||
m_clipboard[id] = NULL;
|
||||
}
|
||||
|
||||
// save the new window
|
||||
m_window = window;
|
||||
|
||||
// initialize the clipboards
|
||||
if (m_window != None) {
|
||||
for (ClipboardID id = 0; id < kClipboardEnd; ++id) {
|
||||
m_clipboard[id] = new CXWindowsClipboard(m_display, m_window, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Window
|
||||
CXWindowsScreen::getRoot() const
|
||||
{
|
||||
assert(m_display != NULL);
|
||||
return m_root;
|
||||
}
|
||||
|
||||
Cursor
|
||||
CXWindowsScreen::getBlankCursor() const
|
||||
{
|
||||
return m_cursor;
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsScreen::open()
|
||||
{
|
||||
assert(m_display == NULL);
|
||||
|
||||
// set the X I/O error handler so we catch the display disconnecting
|
||||
XSetIOErrorHandler(&CXWindowsScreen::ioErrorHandler);
|
||||
|
||||
// get the DISPLAY
|
||||
const char* display = getenv("DISPLAY");
|
||||
if (display == NULL) {
|
||||
display = ":0.0";
|
||||
}
|
||||
|
||||
// open the display
|
||||
log((CLOG_DEBUG "XOpenDisplay(\"%s\")", display));
|
||||
m_display = XOpenDisplay(display);
|
||||
if (m_display == NULL) {
|
||||
throw XScreenOpenFailure();
|
||||
}
|
||||
|
||||
// get root window
|
||||
m_root = DefaultRootWindow(m_display);
|
||||
|
||||
// create the transparent cursor
|
||||
createBlankCursor();
|
||||
|
||||
// get screen shape
|
||||
updateScreenShape();
|
||||
|
||||
// initialize the screen saver
|
||||
m_atomScreensaver = XInternAtom(m_display, "SCREENSAVER", False);
|
||||
m_screensaver = new CXWindowsScreenSaver(this, m_display);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsScreen::mainLoop()
|
||||
{
|
||||
@ -147,7 +235,7 @@ CXWindowsScreen::mainLoop()
|
||||
// have a go at it.
|
||||
m_mutex.unlock();
|
||||
if (!onPreDispatch(&event)) {
|
||||
onEvent(&event);
|
||||
m_eventHandler->onEvent(&event);
|
||||
}
|
||||
m_mutex.lock();
|
||||
}
|
||||
@ -162,23 +250,210 @@ CXWindowsScreen::exitMainLoop()
|
||||
m_stop = true;
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsScreen::close()
|
||||
{
|
||||
CLock lock(&m_mutex);
|
||||
|
||||
// done with screen saver
|
||||
delete m_screensaver;
|
||||
m_screensaver = NULL;
|
||||
|
||||
// destroy clipboards
|
||||
for (ClipboardID id = 0; id < kClipboardEnd; ++id) {
|
||||
delete m_clipboard[id];
|
||||
m_clipboard[id] = NULL;
|
||||
}
|
||||
|
||||
// close the display
|
||||
if (m_display != NULL) {
|
||||
XCloseDisplay(m_display);
|
||||
m_display = NULL;
|
||||
log((CLOG_DEBUG "closed display"));
|
||||
}
|
||||
XSetIOErrorHandler(NULL);
|
||||
}
|
||||
|
||||
bool
|
||||
CXWindowsScreen::onPreDispatch(const CEvent* event)
|
||||
CXWindowsScreen::setClipboard(ClipboardID id, const IClipboard* clipboard)
|
||||
{
|
||||
CLock lock(&m_mutex);
|
||||
|
||||
// fail if we don't have the requested clipboard
|
||||
if (m_clipboard[id] == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// get the actual time. ICCCM does not allow CurrentTime.
|
||||
Time timestamp = CXWindowsUtil::getCurrentTime(
|
||||
m_display, m_clipboard[id]->getWindow());
|
||||
|
||||
if (clipboard != NULL) {
|
||||
// save clipboard data
|
||||
return CClipboard::copy(m_clipboard[id], clipboard, timestamp);
|
||||
}
|
||||
else {
|
||||
// assert clipboard ownership
|
||||
if (!m_clipboard[id]->open(timestamp)) {
|
||||
return false;
|
||||
}
|
||||
m_clipboard[id]->empty();
|
||||
m_clipboard[id]->close();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsScreen::checkClipboards()
|
||||
{
|
||||
// do nothing, we're always up to date
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsScreen::openScreenSaver(bool notify)
|
||||
{
|
||||
CLock lock(&m_mutex);
|
||||
assert(m_screensaver != NULL);
|
||||
|
||||
m_screensaverNotify = notify;
|
||||
if (m_screensaverNotify) {
|
||||
m_screensaver->setNotify(m_window);
|
||||
}
|
||||
else {
|
||||
m_screensaver->disable();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsScreen::closeScreenSaver()
|
||||
{
|
||||
CLock lock(&m_mutex);
|
||||
if (m_screensaver != NULL) {
|
||||
if (m_screensaverNotify) {
|
||||
m_screensaver->setNotify(None);
|
||||
}
|
||||
else {
|
||||
m_screensaver->enable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsScreen::screensaver(bool activate)
|
||||
{
|
||||
CLock lock(&m_mutex);
|
||||
assert(m_screensaver != NULL);
|
||||
|
||||
if (activate) {
|
||||
m_screensaver->activate();
|
||||
}
|
||||
else {
|
||||
m_screensaver->deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsScreen::syncDesktop()
|
||||
{
|
||||
// do nothing; X doesn't suffer from this bogosity
|
||||
}
|
||||
|
||||
bool
|
||||
CXWindowsScreen::getClipboard(ClipboardID id, IClipboard* clipboard) const
|
||||
{
|
||||
assert(clipboard != NULL);
|
||||
|
||||
// block others from using the display while we get the clipboard
|
||||
CLock lock(&m_mutex);
|
||||
|
||||
// fail if we don't have the requested clipboard
|
||||
if (m_clipboard[id] == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// get the actual time. ICCCM does not allow CurrentTime.
|
||||
Time timestamp = CXWindowsUtil::getCurrentTime(
|
||||
m_display, m_clipboard[id]->getWindow());
|
||||
|
||||
// copy the clipboard
|
||||
return CClipboard::copy(clipboard, m_clipboard[id], timestamp);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsScreen::getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h) const
|
||||
{
|
||||
CLock lock(&m_mutex);
|
||||
assert(m_display != NULL);
|
||||
|
||||
x = m_x;
|
||||
y = m_y;
|
||||
w = m_w;
|
||||
h = m_h;
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsScreen::getCursorPos(SInt32& x, SInt32& y) const
|
||||
{
|
||||
CLock lock(&m_mutex);
|
||||
assert(m_display != NULL);
|
||||
|
||||
Window root, window;
|
||||
int mx, my, xWindow, yWindow;
|
||||
unsigned int mask;
|
||||
if (XQueryPointer(m_display, getRoot(), &root, &window,
|
||||
&mx, &my, &xWindow, &yWindow, &mask)) {
|
||||
x = mx;
|
||||
y = my;
|
||||
}
|
||||
else {
|
||||
getCursorCenter(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsScreen::getCursorCenter(SInt32& x, SInt32& y) const
|
||||
{
|
||||
CLock lock(&m_mutex);
|
||||
assert(m_display != NULL);
|
||||
|
||||
x = m_x + (m_w >> 1);
|
||||
y = m_y + (m_h >> 1);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsScreen::updateScreenShape()
|
||||
{
|
||||
m_x = 0;
|
||||
m_y = 0;
|
||||
m_w = WidthOfScreen(DefaultScreenOfDisplay(m_display));
|
||||
m_h = HeightOfScreen(DefaultScreenOfDisplay(m_display));
|
||||
log((CLOG_INFO "screen shape: %d,%d %dx%d", m_x, m_y, m_w, m_h));
|
||||
}
|
||||
|
||||
bool
|
||||
CXWindowsScreen::onPreDispatch(CEvent* event)
|
||||
{
|
||||
assert(event != NULL);
|
||||
const XEvent* xevent = &event->m_event;
|
||||
XEvent* xevent = &event->m_event;
|
||||
|
||||
switch (xevent->type) {
|
||||
case MappingNotify:
|
||||
// keyboard mapping changed
|
||||
XRefreshKeyboardMapping(&xevent->xmapping);
|
||||
|
||||
// pass event on
|
||||
break;
|
||||
|
||||
case SelectionClear:
|
||||
{
|
||||
// we just lost the selection. that means someone else
|
||||
// grabbed the selection so this screen is now the
|
||||
// selection owner. report that to the subclass.
|
||||
// selection owner. report that to the receiver.
|
||||
ClipboardID id = getClipboardID(xevent->xselectionclear.selection);
|
||||
if (id != kClipboardEnd) {
|
||||
log((CLOG_DEBUG "lost clipboard %d ownership at time %d", id, xevent->xselectionclear.time));
|
||||
m_clipboard[id]->lost(xevent->xselectionclear.time);
|
||||
onLostClipboard(id);
|
||||
m_receiver->onGrabClipboard(id);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -225,6 +500,15 @@ CXWindowsScreen::onPreDispatch(const CEvent* event)
|
||||
}
|
||||
break;
|
||||
|
||||
case ClientMessage:
|
||||
if (xevent->xclient.message_type == m_atomScreensaver ||
|
||||
xevent->xclient.format == 32) {
|
||||
// screen saver activation/deactivation event
|
||||
m_eventHandler->onScreensaver(xevent->xclient.data.l[0] != 0);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case DestroyNotify:
|
||||
// looks like one of the windows that requested a clipboard
|
||||
// transfer has gone bye-bye.
|
||||
@ -237,150 +521,10 @@ CXWindowsScreen::onPreDispatch(const CEvent* event)
|
||||
// let screen saver have a go
|
||||
{
|
||||
CLock lock(&m_mutex);
|
||||
m_screenSaver->onPreDispatch(xevent);
|
||||
m_screensaver->onPreDispatch(xevent);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsScreen::openDisplay()
|
||||
{
|
||||
assert(m_display == NULL);
|
||||
|
||||
// set the X I/O error handler so we catch the display disconnecting
|
||||
XSetIOErrorHandler(&CXWindowsScreen::ioErrorHandler);
|
||||
|
||||
// get the DISPLAY
|
||||
const char* display = getenv("DISPLAY");
|
||||
if (display == NULL) {
|
||||
display = ":0.0";
|
||||
}
|
||||
|
||||
// open the display
|
||||
log((CLOG_DEBUG "XOpenDisplay(\"%s\")", display));
|
||||
m_display = XOpenDisplay(display);
|
||||
if (m_display == NULL) {
|
||||
throw XScreenOpenFailure();
|
||||
}
|
||||
|
||||
// get default screen and root window
|
||||
m_screen = DefaultScreen(m_display);
|
||||
m_root = RootWindow(m_display, m_screen);
|
||||
|
||||
// create the transparent cursor
|
||||
createBlankCursor();
|
||||
|
||||
// get screen shape
|
||||
updateScreenShape();
|
||||
|
||||
// initialize the screen saver
|
||||
m_screenSaver = new CXWindowsScreenSaver(this, m_display);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsScreen::closeDisplay()
|
||||
{
|
||||
CLock lock(&m_mutex);
|
||||
|
||||
// done with screen saver
|
||||
delete m_screenSaver;
|
||||
m_screenSaver = NULL;
|
||||
|
||||
// destroy clipboards
|
||||
for (ClipboardID id = 0; id < kClipboardEnd; ++id) {
|
||||
delete m_clipboard[id];
|
||||
m_clipboard[id] = NULL;
|
||||
}
|
||||
|
||||
// close the display
|
||||
if (m_display != NULL) {
|
||||
XCloseDisplay(m_display);
|
||||
m_display = NULL;
|
||||
log((CLOG_DEBUG "closed display"));
|
||||
}
|
||||
XSetIOErrorHandler(NULL);
|
||||
}
|
||||
|
||||
Display*
|
||||
CXWindowsScreen::getDisplay() const
|
||||
{
|
||||
return m_display;
|
||||
}
|
||||
|
||||
int
|
||||
CXWindowsScreen::getScreen() const
|
||||
{
|
||||
assert(m_display != NULL);
|
||||
return m_screen;
|
||||
}
|
||||
|
||||
Window
|
||||
CXWindowsScreen::getRoot() const
|
||||
{
|
||||
assert(m_display != NULL);
|
||||
return m_root;
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsScreen::initClipboards(Window window)
|
||||
{
|
||||
assert(m_display != NULL);
|
||||
assert(window != None);
|
||||
|
||||
// initialize clipboards
|
||||
for (ClipboardID id = 0; id < kClipboardEnd; ++id) {
|
||||
m_clipboard[id] = new CXWindowsClipboard(m_display, window, id);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsScreen::updateScreenShape()
|
||||
{
|
||||
m_x = 0;
|
||||
m_y = 0;
|
||||
m_w = WidthOfScreen(ScreenOfDisplay(m_display, m_screen));
|
||||
m_h = HeightOfScreen(ScreenOfDisplay(m_display, m_screen));
|
||||
log((CLOG_INFO "screen shape: %d,%d %dx%d", m_x, m_y, m_w, m_h));
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsScreen::getScreenShape(SInt32& x, SInt32& y,
|
||||
SInt32& w, SInt32& h) const
|
||||
{
|
||||
assert(m_display != NULL);
|
||||
|
||||
x = m_x;
|
||||
y = m_y;
|
||||
w = m_w;
|
||||
h = m_h;
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsScreen::getCursorPos(SInt32& x, SInt32& y) const
|
||||
{
|
||||
assert(m_display != NULL);
|
||||
|
||||
Window root, window;
|
||||
int mx, my, xWindow, yWindow;
|
||||
unsigned int mask;
|
||||
if (XQueryPointer(m_display, getRoot(), &root, &window,
|
||||
&mx, &my, &xWindow, &yWindow, &mask)) {
|
||||
x = mx;
|
||||
y = my;
|
||||
}
|
||||
else {
|
||||
getCursorCenter(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsScreen::getCursorCenter(SInt32& x, SInt32& y) const
|
||||
{
|
||||
assert(m_display != NULL);
|
||||
|
||||
x = m_x + (m_w >> 1);
|
||||
y = m_y + (m_h >> 1);
|
||||
return m_eventHandler->onPreDispatch(event);
|
||||
}
|
||||
|
||||
void
|
||||
@ -417,30 +561,6 @@ CXWindowsScreen::createBlankCursor()
|
||||
XFreePixmap(m_display, bitmap);
|
||||
}
|
||||
|
||||
Cursor
|
||||
CXWindowsScreen::getBlankCursor() const
|
||||
{
|
||||
return m_cursor;
|
||||
}
|
||||
|
||||
ClipboardID
|
||||
CXWindowsScreen::getClipboardID(Atom selection) const
|
||||
{
|
||||
for (ClipboardID id = 0; id < kClipboardEnd; ++id) {
|
||||
if (m_clipboard[id] != NULL &&
|
||||
m_clipboard[id]->getSelection() == selection) {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
return kClipboardEnd;
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsScreen::onUnexpectedClose()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
bool
|
||||
CXWindowsScreen::processTimers()
|
||||
{
|
||||
@ -486,62 +606,16 @@ CXWindowsScreen::processTimers()
|
||||
}
|
||||
}
|
||||
|
||||
CXWindowsScreenSaver*
|
||||
CXWindowsScreen::getScreenSaver() const
|
||||
ClipboardID
|
||||
CXWindowsScreen::getClipboardID(Atom selection) const
|
||||
{
|
||||
return m_screenSaver;
|
||||
}
|
||||
|
||||
bool
|
||||
CXWindowsScreen::setDisplayClipboard(ClipboardID id,
|
||||
const IClipboard* clipboard)
|
||||
{
|
||||
CLock lock(&m_mutex);
|
||||
|
||||
// fail if we don't have the requested clipboard
|
||||
if (m_clipboard[id] == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// get the actual time. ICCCM does not allow CurrentTime.
|
||||
Time timestamp = CXWindowsUtil::getCurrentTime(
|
||||
m_display, m_clipboard[id]->getWindow());
|
||||
|
||||
if (clipboard != NULL) {
|
||||
// save clipboard data
|
||||
return CClipboard::copy(m_clipboard[id], clipboard, timestamp);
|
||||
}
|
||||
else {
|
||||
// assert clipboard ownership
|
||||
if (!m_clipboard[id]->open(timestamp)) {
|
||||
return false;
|
||||
}
|
||||
m_clipboard[id]->empty();
|
||||
m_clipboard[id]->close();
|
||||
return true;
|
||||
for (ClipboardID id = 0; id < kClipboardEnd; ++id) {
|
||||
if (m_clipboard[id] != NULL &&
|
||||
m_clipboard[id]->getSelection() == selection) {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CXWindowsScreen::getDisplayClipboard(ClipboardID id,
|
||||
IClipboard* clipboard) const
|
||||
{
|
||||
assert(clipboard != NULL);
|
||||
|
||||
// block others from using the display while we get the clipboard
|
||||
CLock lock(&m_mutex);
|
||||
|
||||
// fail if we don't have the requested clipboard
|
||||
if (m_clipboard[id] == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// get the actual time. ICCCM does not allow CurrentTime.
|
||||
Time timestamp = CXWindowsUtil::getCurrentTime(
|
||||
m_display, m_clipboard[id]->getWindow());
|
||||
|
||||
// copy the clipboard
|
||||
return CClipboard::copy(clipboard, m_clipboard[id], timestamp);
|
||||
return kClipboardEnd;
|
||||
}
|
||||
|
||||
void
|
||||
@ -584,17 +658,17 @@ CXWindowsScreen::ioErrorHandler(Display*)
|
||||
// so we set it to NULL), and exit.
|
||||
log((CLOG_WARN "X display has unexpectedly disconnected"));
|
||||
s_screen->m_display = NULL;
|
||||
s_screen->onUnexpectedClose();
|
||||
s_screen->m_eventHandler->onError();
|
||||
log((CLOG_CRIT "quiting due to X display disconnection"));
|
||||
exit(17);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// CXWindowsScreen::CDisplayLock
|
||||
// CDisplayLock
|
||||
//
|
||||
|
||||
CXWindowsScreen::CDisplayLock::CDisplayLock(const CXWindowsScreen* screen) :
|
||||
CDisplayLock::CDisplayLock(const CXWindowsScreen* screen) :
|
||||
m_mutex(&screen->m_mutex),
|
||||
m_display(screen->m_display)
|
||||
{
|
||||
@ -603,12 +677,12 @@ CXWindowsScreen::CDisplayLock::CDisplayLock(const CXWindowsScreen* screen) :
|
||||
m_mutex->lock();
|
||||
}
|
||||
|
||||
CXWindowsScreen::CDisplayLock::~CDisplayLock()
|
||||
CDisplayLock::~CDisplayLock()
|
||||
{
|
||||
m_mutex->unlock();
|
||||
}
|
||||
|
||||
CXWindowsScreen::CDisplayLock::operator Display*() const
|
||||
CDisplayLock::operator Display*() const
|
||||
{
|
||||
return m_display;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef CXWINDOWSSCREEN_H
|
||||
#define CXWINDOWSSCREEN_H
|
||||
|
||||
#include "IScreen.h"
|
||||
#include "ClipboardTypes.h"
|
||||
#include "CMutex.h"
|
||||
#include "CStopwatch.h"
|
||||
@ -13,9 +14,9 @@
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
class IClipboard;
|
||||
class IJob;
|
||||
class IScreenSaver;
|
||||
class IScreenEventHandler;
|
||||
class IScreenReceiver;
|
||||
class CXWindowsClipboard;
|
||||
class CXWindowsScreenSaver;
|
||||
|
||||
@ -25,9 +26,9 @@ public:
|
||||
SInt32 m_result;
|
||||
};
|
||||
|
||||
class CXWindowsScreen {
|
||||
class CXWindowsScreen : public IScreen {
|
||||
public:
|
||||
CXWindowsScreen();
|
||||
CXWindowsScreen(IScreenReceiver*, IScreenEventHandler*);
|
||||
virtual ~CXWindowsScreen();
|
||||
|
||||
// manipulators
|
||||
@ -39,94 +40,41 @@ public:
|
||||
void addTimer(IJob*, double timeout);
|
||||
void removeTimer(IJob*);
|
||||
|
||||
protected:
|
||||
class CDisplayLock {
|
||||
public:
|
||||
CDisplayLock(const CXWindowsScreen*);
|
||||
~CDisplayLock();
|
||||
// set the window (created by the subclass). this performs some
|
||||
// initialization and saves the window in case it's needed later.
|
||||
void setWindow(Window);
|
||||
|
||||
operator Display*() const;
|
||||
// accessors
|
||||
|
||||
private:
|
||||
const CMutex* m_mutex;
|
||||
Display* m_display;
|
||||
};
|
||||
friend class CDisplayLock;
|
||||
|
||||
// runs an event loop and returns when exitMainLoop() is called
|
||||
void mainLoop();
|
||||
|
||||
// force mainLoop() to return
|
||||
void exitMainLoop();
|
||||
|
||||
// open the X display. calls onOpenDisplay() after opening the display,
|
||||
// getting the screen, its size, and root window. then it starts the
|
||||
// event thread.
|
||||
void openDisplay();
|
||||
|
||||
// destroy the window and close the display. calls onCloseDisplay()
|
||||
// after the event thread has been shut down but before the display
|
||||
// is closed.
|
||||
void closeDisplay();
|
||||
|
||||
// get the Display*. only use this when you know the display is
|
||||
// locked but don't have the CDisplayLock available.
|
||||
Display* getDisplay() const;
|
||||
|
||||
// get the opened screen and its root window. to get the display
|
||||
// create a CDisplayLock object passing this. while the object
|
||||
// exists no other threads may access the display. do not save
|
||||
// the Display* beyond the lifetime of the CDisplayLock.
|
||||
int getScreen() const;
|
||||
// get the root window of the screen
|
||||
Window getRoot() const;
|
||||
|
||||
// initialize the clipboards
|
||||
void initClipboards(Window);
|
||||
|
||||
// update screen size cache
|
||||
void updateScreenShape();
|
||||
|
||||
// get the shape of the screen
|
||||
void getScreenShape(SInt32& x, SInt32& y,
|
||||
SInt32& width, SInt32& height) const;
|
||||
|
||||
// get the current cursor position
|
||||
void getCursorPos(SInt32& x, SInt32& y) const;
|
||||
|
||||
// get the cursor center position
|
||||
void getCursorCenter(SInt32& x, SInt32& y) const;
|
||||
|
||||
// get a cursor that is transparent everywhere
|
||||
Cursor getBlankCursor() const;
|
||||
|
||||
// set the contents of the clipboard (i.e. primary selection)
|
||||
bool setDisplayClipboard(ClipboardID,
|
||||
const IClipboard* clipboard);
|
||||
|
||||
// copy the clipboard contents to clipboard
|
||||
bool getDisplayClipboard(ClipboardID,
|
||||
IClipboard* clipboard) const;
|
||||
|
||||
// get the screen saver object
|
||||
CXWindowsScreenSaver*
|
||||
getScreenSaver() const;
|
||||
|
||||
// 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;
|
||||
|
||||
// called by mainLoop(). iff the event was handled return true and
|
||||
// store the result, if any, in m_result, which defaults to zero.
|
||||
virtual bool onEvent(CEvent* event) = 0;
|
||||
|
||||
// called if the display is unexpectedly closing. default does nothing.
|
||||
virtual void onUnexpectedClose();
|
||||
|
||||
// called when a clipboard is lost
|
||||
virtual void onLostClipboard(ClipboardID) = 0;
|
||||
// IScreen overrides
|
||||
void open();
|
||||
void mainLoop();
|
||||
void exitMainLoop();
|
||||
void close();
|
||||
bool setClipboard(ClipboardID, const IClipboard*);
|
||||
void checkClipboards();
|
||||
void openScreenSaver(bool notify);
|
||||
void closeScreenSaver();
|
||||
void screensaver(bool activate);
|
||||
void syncDesktop();
|
||||
bool getClipboard(ClipboardID, IClipboard*) const;
|
||||
void getShape(SInt32&, SInt32&, SInt32&, SInt32&) const;
|
||||
void getCursorPos(SInt32&, SInt32&) const;
|
||||
void getCursorCenter(SInt32&, SInt32&) const;
|
||||
|
||||
private:
|
||||
// update screen size cache
|
||||
void updateScreenShape();
|
||||
|
||||
// process events before dispatching to receiver
|
||||
bool onPreDispatch(CEvent* event);
|
||||
|
||||
// create the transparent cursor
|
||||
void createBlankCursor();
|
||||
|
||||
@ -255,14 +203,23 @@ private:
|
||||
};
|
||||
|
||||
private:
|
||||
friend class CDisplayLock;
|
||||
|
||||
typedef CPriorityQueue<CTimer> CTimerPriorityQueue;
|
||||
|
||||
// X is not thread safe
|
||||
CMutex m_mutex;
|
||||
|
||||
Display* m_display;
|
||||
int m_screen;
|
||||
Window m_root;
|
||||
bool m_stop;
|
||||
|
||||
IScreenReceiver* m_receiver;
|
||||
IScreenEventHandler* m_eventHandler;
|
||||
Window m_window;
|
||||
|
||||
SInt32 m_x, m_y;
|
||||
SInt32 m_w, m_h;
|
||||
bool m_stop;
|
||||
|
||||
// clipboards
|
||||
CXWindowsClipboard* m_clipboard[kClipboardEnd];
|
||||
@ -270,20 +227,31 @@ private:
|
||||
// the transparent cursor
|
||||
Cursor m_cursor;
|
||||
|
||||
// screen saver
|
||||
CXWindowsScreenSaver* m_screenSaver;
|
||||
// screen saver stuff
|
||||
CXWindowsScreenSaver* m_screensaver;
|
||||
bool m_screensaverNotify;
|
||||
Atom m_atomScreensaver;
|
||||
|
||||
// timers, the stopwatch used to time, and a mutex for the timers
|
||||
CTimerPriorityQueue m_timers;
|
||||
CStopwatch m_time;
|
||||
CMutex m_timersMutex;
|
||||
|
||||
// X is not thread safe
|
||||
CMutex m_mutex;
|
||||
|
||||
// pointer to (singleton) screen. this is only needed by
|
||||
// ioErrorHandler().
|
||||
static CXWindowsScreen* s_screen;
|
||||
};
|
||||
|
||||
class CDisplayLock {
|
||||
public:
|
||||
CDisplayLock(const CXWindowsScreen*);
|
||||
~CDisplayLock();
|
||||
|
||||
operator Display*() const;
|
||||
|
||||
private:
|
||||
const CMutex* m_mutex;
|
||||
Display* m_display;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -32,7 +32,7 @@ public:
|
||||
virtual void close() = 0;
|
||||
virtual void enter(SInt32 xAbs, SInt32 yAbs,
|
||||
UInt32 seqNum, KeyModifierMask mask,
|
||||
bool screenSaver) = 0;
|
||||
bool forScreensaver) = 0;
|
||||
virtual bool leave() = 0;
|
||||
virtual void setClipboard(ClipboardID, const CString&) = 0;
|
||||
virtual void grabClipboard(ClipboardID) = 0;
|
||||
@ -44,13 +44,13 @@ public:
|
||||
virtual void mouseUp(ButtonID) = 0;
|
||||
virtual void mouseMove(SInt32 xAbs, SInt32 yAbs) = 0;
|
||||
virtual void mouseWheel(SInt32 delta) = 0;
|
||||
virtual void screenSaver(bool activate) = 0;
|
||||
virtual void screensaver(bool activate) = 0;
|
||||
virtual CString getName() const;
|
||||
virtual SInt32 getJumpZoneSize() const = 0;
|
||||
virtual void getShape(SInt32& x, SInt32& y,
|
||||
SInt32& width, SInt32& height) const = 0;
|
||||
virtual void getCenter(SInt32& x, SInt32& y) const = 0;
|
||||
virtual void getMousePos(SInt32& x, SInt32& y) const = 0;
|
||||
virtual SInt32 getJumpZoneSize() const = 0;
|
||||
virtual void getCursorPos(SInt32& x, SInt32& y) const = 0;
|
||||
virtual void getCursorCenter(SInt32& x, SInt32& y) const = 0;
|
||||
|
||||
private:
|
||||
IServer* m_server;
|
||||
|
@ -236,12 +236,19 @@ CClientProxy1_0::mouseWheel(SInt32 delta)
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::screenSaver(bool on)
|
||||
CClientProxy1_0::screensaver(bool on)
|
||||
{
|
||||
log((CLOG_DEBUG1 "send screen saver to \"%s\" on=%d", getName().c_str(), on ? 1 : 0));
|
||||
CProtocolUtil::writef(getOutputStream(), kMsgCScreenSaver, on ? 1 : 0);
|
||||
}
|
||||
|
||||
SInt32
|
||||
CClientProxy1_0::getJumpZoneSize() const
|
||||
{
|
||||
CLock lock(&m_mutex);
|
||||
return m_info.m_zoneSize;
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h) const
|
||||
{
|
||||
@ -253,24 +260,17 @@ CClientProxy1_0::getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h) const
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::getCenter(SInt32& x, SInt32& y) const
|
||||
{
|
||||
CLock lock(&m_mutex);
|
||||
x = m_info.m_mx;
|
||||
y = m_info.m_my;
|
||||
}
|
||||
|
||||
void
|
||||
CClientProxy1_0::getMousePos(SInt32&, SInt32&) const
|
||||
CClientProxy1_0::getCursorPos(SInt32&, SInt32&) const
|
||||
{
|
||||
assert(0 && "shouldn't be called");
|
||||
}
|
||||
|
||||
SInt32
|
||||
CClientProxy1_0::getJumpZoneSize() const
|
||||
void
|
||||
CClientProxy1_0::getCursorCenter(SInt32& x, SInt32& y) const
|
||||
{
|
||||
CLock lock(&m_mutex);
|
||||
return m_info.m_zoneSize;
|
||||
x = m_info.m_mx;
|
||||
y = m_info.m_my;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -18,7 +18,7 @@ public:
|
||||
virtual void close();
|
||||
virtual void enter(SInt32 xAbs, SInt32 yAbs,
|
||||
UInt32 seqNum, KeyModifierMask mask,
|
||||
bool screenSaver);
|
||||
bool forScreensaver);
|
||||
virtual bool leave();
|
||||
virtual void setClipboard(ClipboardID, const CString&);
|
||||
virtual void grabClipboard(ClipboardID);
|
||||
@ -30,12 +30,12 @@ public:
|
||||
virtual void mouseUp(ButtonID);
|
||||
virtual void mouseMove(SInt32 xAbs, SInt32 yAbs);
|
||||
virtual void mouseWheel(SInt32 delta);
|
||||
virtual void screenSaver(bool activate);
|
||||
virtual void screensaver(bool activate);
|
||||
virtual SInt32 getJumpZoneSize() const;
|
||||
virtual void getShape(SInt32& x, SInt32& y,
|
||||
SInt32& width, SInt32& height) const;
|
||||
virtual void getCenter(SInt32& x, SInt32& y) const;
|
||||
virtual void getMousePos(SInt32& x, SInt32& y) const;
|
||||
virtual SInt32 getJumpZoneSize() const;
|
||||
virtual void getCursorPos(SInt32& x, SInt32& y) const;
|
||||
virtual void getCursorCenter(SInt32& x, SInt32& y) const;
|
||||
|
||||
private:
|
||||
void recvInfo(bool notify);
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "CPrimaryClient.h"
|
||||
#include "IServer.h"
|
||||
#include "IPrimaryScreen.h"
|
||||
#include "CPrimaryScreen.h"
|
||||
#include "CClipboard.h"
|
||||
#include "CLog.h"
|
||||
|
||||
@ -15,7 +15,8 @@
|
||||
// CPrimaryClient
|
||||
//
|
||||
|
||||
CPrimaryClient::CPrimaryClient(IServer* server, const CString& name) :
|
||||
CPrimaryClient::CPrimaryClient(IServer* server,
|
||||
IPrimaryScreenReceiver* receiver, const CString& name) :
|
||||
m_server(server),
|
||||
m_name(name),
|
||||
m_seqNum(0)
|
||||
@ -25,9 +26,9 @@ CPrimaryClient::CPrimaryClient(IServer* server, const CString& name) :
|
||||
// create screen
|
||||
log((CLOG_DEBUG1 "creating primary screen"));
|
||||
#if WINDOWS_LIKE
|
||||
m_screen = new CMSWindowsPrimaryScreen(this, m_server);
|
||||
m_screen = new CMSWindowsPrimaryScreen(this, receiver);
|
||||
#elif UNIX_LIKE
|
||||
m_screen = new CXWindowsPrimaryScreen(this, m_server);
|
||||
m_screen = new CXWindowsPrimaryScreen(this, receiver);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -211,7 +212,7 @@ CPrimaryClient::mouseWheel(SInt32)
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::screenSaver(bool)
|
||||
CPrimaryClient::screensaver(bool)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
@ -222,6 +223,12 @@ CPrimaryClient::getName() const
|
||||
return m_name;
|
||||
}
|
||||
|
||||
SInt32
|
||||
CPrimaryClient::getJumpZoneSize() const
|
||||
{
|
||||
return m_info.m_zoneSize;
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h) const
|
||||
{
|
||||
@ -232,20 +239,14 @@ CPrimaryClient::getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h) const
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::getCenter(SInt32& x, SInt32& y) const
|
||||
{
|
||||
x = m_info.m_mx;
|
||||
y = m_info.m_my;
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryClient::getMousePos(SInt32&, SInt32&) const
|
||||
CPrimaryClient::getCursorPos(SInt32&, SInt32&) const
|
||||
{
|
||||
assert(0 && "shouldn't be called");
|
||||
}
|
||||
|
||||
SInt32
|
||||
CPrimaryClient::getJumpZoneSize() const
|
||||
void
|
||||
CPrimaryClient::getCursorCenter(SInt32& x, SInt32& y) const
|
||||
{
|
||||
return m_info.m_zoneSize;
|
||||
x = m_info.m_mx;
|
||||
y = m_info.m_my;
|
||||
}
|
||||
|
@ -6,12 +6,13 @@
|
||||
#include "ProtocolTypes.h"
|
||||
|
||||
class IClipboard;
|
||||
class IPrimaryScreen;
|
||||
class CPrimaryScreen;
|
||||
class IPrimaryScreenReceiver;
|
||||
class IServer;
|
||||
|
||||
class CPrimaryClient : public IScreenReceiver, public IClient {
|
||||
public:
|
||||
CPrimaryClient(IServer*, const CString& name);
|
||||
CPrimaryClient(IServer*, IPrimaryScreenReceiver*, const CString& name);
|
||||
~CPrimaryClient();
|
||||
|
||||
// manipulators
|
||||
@ -44,7 +45,7 @@ public:
|
||||
virtual void close();
|
||||
virtual void enter(SInt32 xAbs, SInt32 yAbs,
|
||||
UInt32 seqNum, KeyModifierMask mask,
|
||||
bool screenSaver);
|
||||
bool forScreensaver);
|
||||
virtual bool leave();
|
||||
virtual void setClipboard(ClipboardID, const CString&);
|
||||
virtual void grabClipboard(ClipboardID);
|
||||
@ -56,17 +57,17 @@ public:
|
||||
virtual void mouseUp(ButtonID);
|
||||
virtual void mouseMove(SInt32 xAbs, SInt32 yAbs);
|
||||
virtual void mouseWheel(SInt32 delta);
|
||||
virtual void screenSaver(bool activate);
|
||||
virtual void screensaver(bool activate);
|
||||
virtual CString getName() const;
|
||||
virtual SInt32 getJumpZoneSize() const;
|
||||
virtual void getShape(SInt32& x, SInt32& y,
|
||||
SInt32& width, SInt32& height) const;
|
||||
virtual void getCenter(SInt32& x, SInt32& y) const;
|
||||
virtual void getMousePos(SInt32& x, SInt32& y) const;
|
||||
virtual SInt32 getJumpZoneSize() const;
|
||||
virtual void getCursorPos(SInt32& x, SInt32& y) const;
|
||||
virtual void getCursorCenter(SInt32& x, SInt32& y) const;
|
||||
|
||||
private:
|
||||
IServer* m_server;
|
||||
IPrimaryScreen* m_screen;
|
||||
CPrimaryScreen* m_screen;
|
||||
CString m_name;
|
||||
UInt32 m_seqNum;
|
||||
CClientInfo m_info;
|
||||
|
270
server/CPrimaryScreen.cpp
Normal file
270
server/CPrimaryScreen.cpp
Normal file
@ -0,0 +1,270 @@
|
||||
#include "CPrimaryScreen.h"
|
||||
#include "IScreen.h"
|
||||
#include "IScreenReceiver.h"
|
||||
#include "ProtocolTypes.h"
|
||||
#include "CThread.h"
|
||||
#include "CLog.h"
|
||||
|
||||
// FIXME -- should be locking
|
||||
|
||||
//
|
||||
// CPrimaryScreen
|
||||
//
|
||||
|
||||
CPrimaryScreen::CPrimaryScreen(IScreenReceiver* receiver) :
|
||||
m_receiver(receiver),
|
||||
m_active(false)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
CPrimaryScreen::~CPrimaryScreen()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryScreen::run()
|
||||
{
|
||||
// change our priority
|
||||
CThread::getCurrentThread().setPriority(-3);
|
||||
|
||||
// run event loop
|
||||
try {
|
||||
log((CLOG_DEBUG "entering event loop"));
|
||||
onPreRun();
|
||||
getScreen()->mainLoop();
|
||||
onPostRun();
|
||||
log((CLOG_DEBUG "exiting event loop"));
|
||||
}
|
||||
catch (...) {
|
||||
onPostRun();
|
||||
log((CLOG_DEBUG "exiting event loop"));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryScreen::stop()
|
||||
{
|
||||
getScreen()->exitMainLoop();
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryScreen::open()
|
||||
{
|
||||
CClientInfo info;
|
||||
try {
|
||||
// subclass hook
|
||||
onPreOpen();
|
||||
|
||||
// open the screen
|
||||
getScreen()->open();
|
||||
|
||||
// create and prepare our window
|
||||
createWindow();
|
||||
|
||||
// collect screen info
|
||||
getScreen()->getShape(info.m_x, info.m_y, info.m_w, info.m_h);
|
||||
getScreen()->getCursorPos(info.m_mx, info.m_my);
|
||||
info.m_zoneSize = getJumpZoneSize();
|
||||
|
||||
// update keyboard state
|
||||
updateKeys();
|
||||
|
||||
// get notified of screen saver activation/deactivation
|
||||
getScreen()->openScreenSaver(true);
|
||||
|
||||
// subclass hook
|
||||
onPostOpen();
|
||||
}
|
||||
catch (...) {
|
||||
close();
|
||||
throw;
|
||||
}
|
||||
|
||||
// enter the screen
|
||||
enterNoWarp();
|
||||
|
||||
// send screen info
|
||||
m_receiver->onInfoChanged(info);
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryScreen::close()
|
||||
{
|
||||
onPreClose();
|
||||
getScreen()->closeScreenSaver();
|
||||
destroyWindow();
|
||||
getScreen()->close();
|
||||
onPostClose();
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryScreen::enter(SInt32 x, SInt32 y, bool forScreensaver)
|
||||
{
|
||||
log((CLOG_INFO "entering primary at %d,%d%s", x, y, forScreensaver ? " for screen saver" : ""));
|
||||
assert(m_active == true);
|
||||
|
||||
enterNoWarp();
|
||||
if (!forScreensaver) {
|
||||
warpCursor(x, y);
|
||||
}
|
||||
else {
|
||||
onEnterScreensaver();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryScreen::enterNoWarp()
|
||||
{
|
||||
// not active anymore
|
||||
m_active = false;
|
||||
|
||||
// subclass hook
|
||||
onPreEnter();
|
||||
|
||||
// restore active window and hide our window
|
||||
hideWindow();
|
||||
|
||||
// subclass hook
|
||||
onPostEnter();
|
||||
}
|
||||
|
||||
bool
|
||||
CPrimaryScreen::leave()
|
||||
{
|
||||
log((CLOG_INFO "leaving primary"));
|
||||
assert(m_active == false);
|
||||
|
||||
// subclass hook
|
||||
onPreLeave();
|
||||
|
||||
// show our window
|
||||
if (!showWindow()) {
|
||||
onPostLeave(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// get keyboard state as we leave
|
||||
updateKeys();
|
||||
|
||||
// warp mouse to center
|
||||
warpCursorToCenter();
|
||||
// FIXME -- this doesn't match the win32 version. that just does
|
||||
// the warp while we flush the input queue until we find the warp
|
||||
// and we discard that too. would prefer to at least match our
|
||||
// own warping when we receive MotionNotify; that just does the
|
||||
// warp. however, the win32 version sometimes stutters when
|
||||
// leaving and perhaps this is why. hmm, win32 does ignore the
|
||||
// events until after the warp (via the mark).
|
||||
|
||||
// subclass hook
|
||||
onPostLeave(true);
|
||||
|
||||
// local client now active
|
||||
m_active = true;
|
||||
|
||||
// make sure our idea of clipboard ownership is correct
|
||||
getScreen()->checkClipboards();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryScreen::setClipboard(ClipboardID id,
|
||||
const IClipboard* clipboard)
|
||||
{
|
||||
getScreen()->setClipboard(id, clipboard);
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryScreen::grabClipboard(ClipboardID id)
|
||||
{
|
||||
getScreen()->setClipboard(id, NULL);
|
||||
}
|
||||
|
||||
bool
|
||||
CPrimaryScreen::isActive() const
|
||||
{
|
||||
return m_active;
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryScreen::getClipboard(ClipboardID id,
|
||||
IClipboard* clipboard) const
|
||||
{
|
||||
getScreen()->getClipboard(id, clipboard);
|
||||
}
|
||||
|
||||
SInt32
|
||||
CPrimaryScreen::getJumpZoneSize() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryScreen::onPreRun()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryScreen::onPostRun()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryScreen::onPreOpen()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryScreen::onPostOpen()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryScreen::onPreClose()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryScreen::onPostClose()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryScreen::onPreEnter()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryScreen::onPostEnter()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryScreen::onEnterScreensaver()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryScreen::onPreLeave()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CPrimaryScreen::onPostLeave(bool)
|
||||
{
|
||||
// do nothing
|
||||
}
|
157
server/CPrimaryScreen.h
Normal file
157
server/CPrimaryScreen.h
Normal file
@ -0,0 +1,157 @@
|
||||
#ifndef CPRIMARYSCREEN_H
|
||||
#define CPRIMARYSCREEN_H
|
||||
|
||||
#include "ClipboardTypes.h"
|
||||
#include "KeyTypes.h"
|
||||
|
||||
class IClipboard;
|
||||
class IScreen;
|
||||
class IScreenReceiver;
|
||||
|
||||
// platform independent base class for primary screen implementations.
|
||||
// each platform will derive a class from CPrimaryScreen to handle
|
||||
// platform dependent operations.
|
||||
class CPrimaryScreen {
|
||||
public:
|
||||
CPrimaryScreen(IScreenReceiver*);
|
||||
virtual ~CPrimaryScreen();
|
||||
|
||||
// manipulators
|
||||
|
||||
// enter the screen's message loop. this returns when it detects
|
||||
// the application should terminate or when stop() is called.
|
||||
// run() may only be called between open() and close().
|
||||
void run();
|
||||
|
||||
// cause run() to return
|
||||
void stop();
|
||||
|
||||
// initializes the screen and starts reporting events
|
||||
void open();
|
||||
|
||||
// close the screen
|
||||
void close();
|
||||
|
||||
// called when the user navigates to the primary screen.
|
||||
// forScreensaver == true means that we're entering the primary
|
||||
// screen because the screensaver has activated.
|
||||
void enter(SInt32 x, SInt32 y, bool forScreensaver);
|
||||
|
||||
// called when the user navigates off the primary screen. returns
|
||||
// true iff successful.
|
||||
bool leave();
|
||||
|
||||
// called when the configuration has changed. activeSides is a
|
||||
// bitmask of CConfig::EDirectionMask indicating which sides of
|
||||
// the primary screen are linked to clients.
|
||||
virtual void reconfigure(UInt32 activeSides) = 0;
|
||||
|
||||
// warp the cursor to the given absolute coordinates
|
||||
virtual void warpCursor(SInt32 x, SInt32 y) = 0;
|
||||
|
||||
// set the screen's clipboard contents. this is usually called
|
||||
// soon after an enter().
|
||||
void setClipboard(ClipboardID, const IClipboard*);
|
||||
|
||||
// synergy should own the clipboard
|
||||
void grabClipboard(ClipboardID);
|
||||
|
||||
// accessors
|
||||
|
||||
// returns true iff the screen is active (i.e. the user has left
|
||||
// the screen)
|
||||
bool isActive() const;
|
||||
|
||||
// return the contents of the given clipboard
|
||||
void getClipboard(ClipboardID, IClipboard*) const;
|
||||
|
||||
// returns the size of the zone on the edges of the screen that
|
||||
// causes the cursor to jump to another screen. default returns 1.
|
||||
virtual SInt32 getJumpZoneSize() const;
|
||||
|
||||
// get the primary screen's current toggle modifier key state.
|
||||
// the returned mask should have the corresponding bit set for
|
||||
// each toggle key that is active.
|
||||
virtual KeyModifierMask getToggleMask() const = 0;
|
||||
|
||||
// return true if any key or button is being pressed or if there's
|
||||
// any other reason that the user should not be allowed to switch
|
||||
// screens.
|
||||
virtual bool isLockedToScreen() const = 0;
|
||||
|
||||
// get the platform dependent screen object
|
||||
virtual IScreen* getScreen() const = 0;
|
||||
|
||||
protected:
|
||||
// template method hooks. these are called on entry/exit to the
|
||||
// named method. onEnterScreensaver() is called by enter() iff
|
||||
// forScreensaver is true. onPostLeave() is passed the result of
|
||||
// showWindow(). override to do platform specific operations.
|
||||
// defaults do nothing.
|
||||
virtual void onPreRun();
|
||||
virtual void onPostRun();
|
||||
virtual void onPreOpen();
|
||||
virtual void onPostOpen();
|
||||
virtual void onPreClose();
|
||||
virtual void onPostClose();
|
||||
virtual void onPreEnter();
|
||||
virtual void onPostEnter();
|
||||
virtual void onEnterScreensaver();
|
||||
virtual void onPreLeave();
|
||||
virtual void onPostLeave(bool success);
|
||||
|
||||
// create/destroy the window. this window is generally used to
|
||||
// receive events and, when the user navigates to another screen,
|
||||
// to capture keyboard and mouse input.
|
||||
virtual void createWindow() = 0;
|
||||
virtual void destroyWindow() = 0;
|
||||
|
||||
// called when the user navigates off the primary screen. hide the
|
||||
// cursor and grab exclusive access to the input devices. returns
|
||||
// true iff successful. every call to showWindow() has a matching
|
||||
// call to hideWindow() which preceeds it. return true iff
|
||||
// successful (in particular, iff the input devices were grabbed).
|
||||
//
|
||||
// after a successful showWindow(), user input events and
|
||||
// screensaver activation/deactivation should be reported to an
|
||||
// IPrimaryScreenReceiver until hideWindow() is called. report
|
||||
// mouse motion to IPrimaryScreenReceiver::onMouseMoveSecondary().
|
||||
// user input should not be delivered to any application except
|
||||
// synergy.
|
||||
virtual bool showWindow() = 0;
|
||||
|
||||
// called when the user navigates back to the primary screen. show
|
||||
// the cursor and ungab the input devices.
|
||||
//
|
||||
// after hideWindow(), user input events should be delivered normally.
|
||||
// mouse motion over (at least) the jump zones must be reported to
|
||||
// an IPrimaryScreenReceiver::onMouseMovePrimary().
|
||||
virtual void hideWindow() = 0;
|
||||
|
||||
// prepare the cursor to report relative motion. when the user has
|
||||
// navigated to another screen, synergy requires the cursor motion
|
||||
// deltas, not the absolute coordinates. typically this is done by
|
||||
// warping the cursor to the center of the primary screen and then
|
||||
// every time it moves compute the motion and warp back to the
|
||||
// center (but without reporting that warp as motion). this is
|
||||
// only called after a successful showWindow().
|
||||
virtual void warpCursorToCenter() = 0;
|
||||
|
||||
// check the current keyboard state. normally a screen will save
|
||||
// the keyboard state in this method and use this shadow state
|
||||
// when handling user input and in methods like isLockedToScreen().
|
||||
virtual void updateKeys() = 0;
|
||||
|
||||
private:
|
||||
void enterNoWarp();
|
||||
|
||||
private:
|
||||
// FIXME -- should have a mutex
|
||||
|
||||
IScreenReceiver* m_receiver;
|
||||
|
||||
// m_active is true if this screen has been left
|
||||
bool m_active;
|
||||
};
|
||||
|
||||
#endif
|
@ -92,7 +92,6 @@ CServer::run()
|
||||
}
|
||||
|
||||
// handle events
|
||||
log((CLOG_DEBUG "starting event handling"));
|
||||
m_primaryClient->run();
|
||||
|
||||
// clean up
|
||||
@ -108,9 +107,6 @@ CServer::run()
|
||||
stopThreads(); \
|
||||
delete m_httpServer; \
|
||||
m_httpServer = NULL; \
|
||||
if (m_primaryClient != NULL) { \
|
||||
closePrimaryScreen(); \
|
||||
} \
|
||||
} while (false)
|
||||
FINALLY;
|
||||
}
|
||||
@ -144,6 +140,15 @@ CServer::quit()
|
||||
m_primaryClient->stop();
|
||||
}
|
||||
|
||||
void
|
||||
CServer::close()
|
||||
{
|
||||
if (m_primaryClient != NULL) {
|
||||
closePrimaryScreen();
|
||||
}
|
||||
log((CLOG_INFO "closed screen"));
|
||||
}
|
||||
|
||||
bool
|
||||
CServer::setConfig(const CConfig& config)
|
||||
{
|
||||
@ -211,20 +216,6 @@ CServer::getActivePrimarySides() const
|
||||
return sides;
|
||||
}
|
||||
|
||||
void
|
||||
CServer::onError()
|
||||
{
|
||||
// stop all running threads but don't wait too long since some
|
||||
// threads may be unable to proceed until this thread returns.
|
||||
stopThreads(3.0);
|
||||
|
||||
// done with the HTTP server
|
||||
delete m_httpServer;
|
||||
m_httpServer = NULL;
|
||||
|
||||
// note -- we do not attempt to close down the primary screen
|
||||
}
|
||||
|
||||
void
|
||||
CServer::onInfoChanged(const CString& name, const CClientInfo& info)
|
||||
{
|
||||
@ -347,10 +338,74 @@ CServer::onClipboardChangedNoLock(ClipboardID id,
|
||||
m_active->setClipboard(id, m_clipboards[id].m_clipboardData);
|
||||
}
|
||||
|
||||
bool
|
||||
CServer::onCommandKey(KeyID /*id*/, KeyModifierMask /*mask*/, bool /*down*/)
|
||||
void
|
||||
CServer::onError()
|
||||
{
|
||||
return false;
|
||||
// stop all running threads but don't wait too long since some
|
||||
// threads may be unable to proceed until this thread returns.
|
||||
stopThreads(3.0);
|
||||
|
||||
// done with the HTTP server
|
||||
delete m_httpServer;
|
||||
m_httpServer = NULL;
|
||||
|
||||
// note -- we do not attempt to close down the primary screen
|
||||
}
|
||||
|
||||
void
|
||||
CServer::onScreensaver(bool activated)
|
||||
{
|
||||
log((CLOG_DEBUG "onScreenSaver %s", activated ? "activated" : "deactivated"));
|
||||
CLock lock(&m_mutex);
|
||||
|
||||
if (activated) {
|
||||
// save current screen and position
|
||||
m_activeSaver = m_active;
|
||||
m_xSaver = m_x;
|
||||
m_ySaver = m_y;
|
||||
|
||||
// jump to primary screen
|
||||
if (m_active != m_primaryClient) {
|
||||
switchScreen(m_primaryClient, 0, 0, true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// jump back to previous screen and position. we must check
|
||||
// that the position is still valid since the screen may have
|
||||
// changed resolutions while the screen saver was running.
|
||||
if (m_activeSaver != NULL && m_activeSaver != m_primaryClient) {
|
||||
// check position
|
||||
IClient* screen = m_activeSaver;
|
||||
SInt32 x, y, w, h;
|
||||
screen->getShape(x, y, w, h);
|
||||
SInt32 zoneSize = screen->getJumpZoneSize();
|
||||
if (m_xSaver < x + zoneSize) {
|
||||
m_xSaver = x + zoneSize;
|
||||
}
|
||||
else if (m_xSaver >= x + w - zoneSize) {
|
||||
m_xSaver = x + w - zoneSize - 1;
|
||||
}
|
||||
if (m_ySaver < y + zoneSize) {
|
||||
m_ySaver = y + zoneSize;
|
||||
}
|
||||
else if (m_ySaver >= y + h - zoneSize) {
|
||||
m_ySaver = y + h - zoneSize - 1;
|
||||
}
|
||||
|
||||
// jump
|
||||
switchScreen(screen, m_xSaver, m_ySaver, false);
|
||||
}
|
||||
|
||||
// reset state
|
||||
m_activeSaver = NULL;
|
||||
}
|
||||
|
||||
// send message to all clients
|
||||
for (CClientList::const_iterator index = m_clients.begin();
|
||||
index != m_clients.end(); ++index) {
|
||||
IClient* client = index->second;
|
||||
client->screensaver(activated);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -615,60 +670,10 @@ CServer::onMouseWheel(SInt32 delta)
|
||||
m_active->mouseWheel(delta);
|
||||
}
|
||||
|
||||
void
|
||||
CServer::onScreenSaver(bool activated)
|
||||
bool
|
||||
CServer::onCommandKey(KeyID /*id*/, KeyModifierMask /*mask*/, bool /*down*/)
|
||||
{
|
||||
log((CLOG_DEBUG "onScreenSaver %s", activated ? "activated" : "deactivated"));
|
||||
CLock lock(&m_mutex);
|
||||
|
||||
if (activated) {
|
||||
// save current screen and position
|
||||
m_activeSaver = m_active;
|
||||
m_xSaver = m_x;
|
||||
m_ySaver = m_y;
|
||||
|
||||
// jump to primary screen
|
||||
if (m_active != m_primaryClient) {
|
||||
switchScreen(m_primaryClient, 0, 0, true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// jump back to previous screen and position. we must check
|
||||
// that the position is still valid since the screen may have
|
||||
// changed resolutions while the screen saver was running.
|
||||
if (m_activeSaver != NULL && m_activeSaver != m_primaryClient) {
|
||||
// check position
|
||||
IClient* screen = m_activeSaver;
|
||||
SInt32 x, y, w, h;
|
||||
screen->getShape(x, y, w, h);
|
||||
SInt32 zoneSize = screen->getJumpZoneSize();
|
||||
if (m_xSaver < x + zoneSize) {
|
||||
m_xSaver = x + zoneSize;
|
||||
}
|
||||
else if (m_xSaver >= x + w - zoneSize) {
|
||||
m_xSaver = x + w - zoneSize - 1;
|
||||
}
|
||||
if (m_ySaver < y + zoneSize) {
|
||||
m_ySaver = y + zoneSize;
|
||||
}
|
||||
else if (m_ySaver >= y + h - zoneSize) {
|
||||
m_ySaver = y + h - zoneSize - 1;
|
||||
}
|
||||
|
||||
// jump
|
||||
switchScreen(screen, m_xSaver, m_ySaver, false);
|
||||
}
|
||||
|
||||
// reset state
|
||||
m_activeSaver = NULL;
|
||||
}
|
||||
|
||||
// send message to all clients
|
||||
for (CClientList::const_iterator index = m_clients.begin();
|
||||
index != m_clients.end(); ++index) {
|
||||
IClient* client = index->second;
|
||||
client->screenSaver(activated);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -689,7 +694,7 @@ CServer::isLockedToScreenNoLock() const
|
||||
}
|
||||
|
||||
void
|
||||
CServer::switchScreen(IClient* dst, SInt32 x, SInt32 y, bool screenSaver)
|
||||
CServer::switchScreen(IClient* dst, SInt32 x, SInt32 y, bool forScreensaver)
|
||||
{
|
||||
assert(dst != NULL);
|
||||
#ifndef NDEBUG
|
||||
@ -741,7 +746,8 @@ CServer::switchScreen(IClient* dst, SInt32 x, SInt32 y, bool screenSaver)
|
||||
|
||||
// enter new screen
|
||||
m_active->enter(x, y, m_seqNum,
|
||||
m_primaryClient->getToggleMask(), screenSaver);
|
||||
m_primaryClient->getToggleMask(),
|
||||
forScreensaver);
|
||||
|
||||
// send the clipboard data to new active screen
|
||||
for (ClipboardID id = 0; id < kClipboardEnd; ++id) {
|
||||
@ -1209,7 +1215,7 @@ CServer::runClient(void* vsocket)
|
||||
{
|
||||
CLock lock(&m_mutex);
|
||||
if (m_activeSaver != NULL) {
|
||||
proxy->screenSaver(true);
|
||||
proxy->screensaver(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1510,7 +1516,7 @@ CServer::openPrimaryScreen()
|
||||
|
||||
// create the primary client and open it
|
||||
try {
|
||||
m_primaryClient = new CPrimaryClient(this, primary);
|
||||
m_primaryClient = new CPrimaryClient(this, this, primary);
|
||||
|
||||
// add connection
|
||||
addConnection(m_primaryClient);
|
||||
@ -1593,7 +1599,7 @@ CServer::removeConnection(const CString& name)
|
||||
IClient* active = (m_activeSaver != NULL) ? m_activeSaver : m_active;
|
||||
if (active == index->second && active != m_primaryClient) {
|
||||
// record new position (center of primary screen)
|
||||
m_primaryClient->getCenter(m_x, m_y);
|
||||
m_primaryClient->getCursorCenter(m_x, m_y);
|
||||
|
||||
// don't notify active screen since it probably already disconnected
|
||||
log((CLOG_INFO "jump from \"%s\" to \"%s\" at %d,%d", active->getName().c_str(), m_primaryClient->getName().c_str(), m_x, m_y));
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define CSERVER_H
|
||||
|
||||
#include "IServer.h"
|
||||
#include "IPrimaryScreenReceiver.h"
|
||||
#include "CConfig.h"
|
||||
#include "CClipboard.h"
|
||||
#include "CCondVar.h"
|
||||
@ -20,7 +21,7 @@ class IServerProtocol;
|
||||
class ISocketFactory;
|
||||
class ISecurityFactory;
|
||||
|
||||
class CServer : public IServer {
|
||||
class CServer : public IServer, public IPrimaryScreenReceiver {
|
||||
public:
|
||||
CServer(const CString& serverName);
|
||||
~CServer();
|
||||
@ -38,6 +39,9 @@ public:
|
||||
// after a successful open().
|
||||
void quit();
|
||||
|
||||
// close the server's screen
|
||||
void close();
|
||||
|
||||
// update screen map. returns true iff the new configuration was
|
||||
// accepted.
|
||||
bool setConfig(const CConfig&);
|
||||
@ -50,8 +54,14 @@ public:
|
||||
// get the primary screen's name
|
||||
CString getPrimaryScreenName() const;
|
||||
|
||||
// IServer overrides
|
||||
virtual void onInfoChanged(const CString&, const CClientInfo&);
|
||||
virtual bool onGrabClipboard(const CString&, ClipboardID, UInt32);
|
||||
virtual void onClipboardChanged(ClipboardID, UInt32, const CString&);
|
||||
|
||||
// IPrimaryScreenReceiver overrides
|
||||
virtual void onError();
|
||||
virtual void onScreensaver(bool activated);
|
||||
virtual void onKeyDown(KeyID, KeyModifierMask);
|
||||
virtual void onKeyUp(KeyID, KeyModifierMask);
|
||||
virtual void onKeyRepeat(KeyID, KeyModifierMask, SInt32 count);
|
||||
@ -60,12 +70,6 @@ public:
|
||||
virtual bool onMouseMovePrimary(SInt32 x, SInt32 y);
|
||||
virtual void onMouseMoveSecondary(SInt32 dx, SInt32 dy);
|
||||
virtual void onMouseWheel(SInt32 delta);
|
||||
virtual void onScreenSaver(bool activated);
|
||||
|
||||
// IServer overrides
|
||||
virtual void onInfoChanged(const CString&, const CClientInfo&);
|
||||
virtual bool onGrabClipboard(const CString&, ClipboardID, UInt32);
|
||||
virtual void onClipboardChanged(ClipboardID, UInt32, const CString&);
|
||||
|
||||
protected:
|
||||
bool onCommandKey(KeyID, KeyModifierMask, bool down);
|
||||
|
@ -1,11 +1,7 @@
|
||||
#include "CXWindowsPrimaryScreen.h"
|
||||
#include "IScreenReceiver.h"
|
||||
#include "IPrimaryScreenReceiver.h"
|
||||
#include "CXWindowsClipboard.h"
|
||||
#include "CXWindowsScreenSaver.h"
|
||||
#include "CXWindowsScreen.h"
|
||||
#include "CXWindowsUtil.h"
|
||||
#include "CClipboard.h"
|
||||
#include "ProtocolTypes.h"
|
||||
#include "IPrimaryScreenReceiver.h"
|
||||
#include "XScreen.h"
|
||||
#include "CThread.h"
|
||||
#include "CLog.h"
|
||||
@ -26,162 +22,17 @@
|
||||
CXWindowsPrimaryScreen::CXWindowsPrimaryScreen(
|
||||
IScreenReceiver* receiver,
|
||||
IPrimaryScreenReceiver* primaryReceiver) :
|
||||
m_receiver(receiver),
|
||||
m_primaryReceiver(primaryReceiver),
|
||||
m_active(false),
|
||||
CPrimaryScreen(receiver),
|
||||
m_receiver(primaryReceiver),
|
||||
m_window(None)
|
||||
{
|
||||
// do nothing
|
||||
m_screen = new CXWindowsScreen(receiver, this);
|
||||
}
|
||||
|
||||
CXWindowsPrimaryScreen::~CXWindowsPrimaryScreen()
|
||||
{
|
||||
assert(m_window == None);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::run()
|
||||
{
|
||||
// change our priority
|
||||
CThread::getCurrentThread().setPriority(-3);
|
||||
|
||||
// run event loop
|
||||
try {
|
||||
log((CLOG_INFO "entering event loop"));
|
||||
mainLoop();
|
||||
log((CLOG_INFO "exiting event loop"));
|
||||
}
|
||||
catch (...) {
|
||||
log((CLOG_INFO "exiting event loop"));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::stop()
|
||||
{
|
||||
exitMainLoop();
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::open()
|
||||
{
|
||||
assert(m_window == None);
|
||||
|
||||
CClientInfo info;
|
||||
try {
|
||||
// open the display
|
||||
openDisplay();
|
||||
|
||||
// create and prepare our window
|
||||
createWindow();
|
||||
|
||||
// get the display
|
||||
CDisplayLock display(this);
|
||||
|
||||
// initialize the clipboards
|
||||
initClipboards(m_window);
|
||||
|
||||
// miscellaneous initialization
|
||||
m_atomScreenSaver = XInternAtom(display, "SCREENSAVER", False);
|
||||
|
||||
// check for peculiarities
|
||||
// FIXME -- may have to get these from some database
|
||||
m_numLockHalfDuplex = false;
|
||||
m_capsLockHalfDuplex = false;
|
||||
// m_numLockHalfDuplex = true;
|
||||
// m_capsLockHalfDuplex = true;
|
||||
|
||||
// collect screen info
|
||||
getScreenShape(info.m_x, info.m_y, info.m_w, info.m_h);
|
||||
getCursorPos(info.m_mx, info.m_my);
|
||||
info.m_zoneSize = getJumpZoneSize();
|
||||
|
||||
// save mouse position
|
||||
m_x = info.m_mx;
|
||||
m_y = info.m_my;
|
||||
|
||||
// compute center pixel of primary screen
|
||||
getCursorCenter(m_xCenter, m_yCenter);
|
||||
|
||||
// update key state
|
||||
updateModifierMap(display);
|
||||
|
||||
// get notified of screen saver activation/deactivation
|
||||
installScreenSaver();
|
||||
}
|
||||
catch (...) {
|
||||
close();
|
||||
throw;
|
||||
}
|
||||
|
||||
// enter the screen
|
||||
enterNoWarp();
|
||||
|
||||
// send screen info
|
||||
m_receiver->onInfoChanged(info);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::close()
|
||||
{
|
||||
uninstallScreenSaver();
|
||||
destroyWindow();
|
||||
closeDisplay();
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::enter(SInt32 x, SInt32 y, bool forScreenSaver)
|
||||
{
|
||||
log((CLOG_INFO "entering primary at %d,%d%s", x, y, forScreenSaver ? " for screen saver" : ""));
|
||||
assert(m_active == true);
|
||||
assert(m_window != None);
|
||||
|
||||
// enter the screen
|
||||
enterNoWarp();
|
||||
|
||||
// warp to requested location
|
||||
if (!forScreenSaver) {
|
||||
warpCursor(x, y);
|
||||
}
|
||||
|
||||
// redirect input to root window. do not warp the mouse because
|
||||
// that will deactivate the screen saver.
|
||||
else {
|
||||
CDisplayLock display(this);
|
||||
XSetInputFocus(display, PointerRoot, PointerRoot, CurrentTime);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CXWindowsPrimaryScreen::leave()
|
||||
{
|
||||
log((CLOG_INFO "leaving primary"));
|
||||
assert(m_active == false);
|
||||
assert(m_window != None);
|
||||
|
||||
// show our window
|
||||
if (!showWindow()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// warp mouse to center
|
||||
warpCursorToCenter();
|
||||
// FIXME -- this doesn't match the win32 version. that just does
|
||||
// the warp while we flush the input queue until we find the warp
|
||||
// and we discard that too. would prefer to at least match our
|
||||
// own warping when we receive MotionNotify; that just does the
|
||||
// warp. however, the win32 version sometimes stutters when
|
||||
// leaving and perhaps this is why. hmm, win32 does ignore the
|
||||
// events until after the warp (via the mark).
|
||||
|
||||
// local client now active
|
||||
m_active = true;
|
||||
|
||||
// make sure our idea of clipboard ownership is correct
|
||||
checkClipboard();
|
||||
|
||||
return true;
|
||||
delete m_screen;
|
||||
}
|
||||
|
||||
void
|
||||
@ -193,7 +44,7 @@ CXWindowsPrimaryScreen::reconfigure(UInt32)
|
||||
void
|
||||
CXWindowsPrimaryScreen::warpCursor(SInt32 x, SInt32 y)
|
||||
{
|
||||
CDisplayLock display(this);
|
||||
CDisplayLock display(m_screen);
|
||||
|
||||
// warp mouse
|
||||
warpCursorNoFlush(display, x, y);
|
||||
@ -213,30 +64,10 @@ CXWindowsPrimaryScreen::warpCursor(SInt32 x, SInt32 y)
|
||||
m_y = y;
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::setClipboard(ClipboardID id,
|
||||
const IClipboard* clipboard)
|
||||
{
|
||||
setDisplayClipboard(id, clipboard);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::grabClipboard(ClipboardID id)
|
||||
{
|
||||
setDisplayClipboard(id, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::getClipboard(ClipboardID id,
|
||||
IClipboard* clipboard) const
|
||||
{
|
||||
getDisplayClipboard(id, clipboard);
|
||||
}
|
||||
|
||||
KeyModifierMask
|
||||
CXWindowsPrimaryScreen::getToggleMask() const
|
||||
{
|
||||
CDisplayLock display(this);
|
||||
CDisplayLock display(m_screen);
|
||||
|
||||
// query the pointer to get the keyboard state
|
||||
Window root, window;
|
||||
@ -265,7 +96,7 @@ CXWindowsPrimaryScreen::getToggleMask() const
|
||||
bool
|
||||
CXWindowsPrimaryScreen::isLockedToScreen() const
|
||||
{
|
||||
CDisplayLock display(this);
|
||||
CDisplayLock display(m_screen);
|
||||
|
||||
// query the pointer to get the button state
|
||||
Window root, window;
|
||||
@ -295,11 +126,29 @@ CXWindowsPrimaryScreen::isLockedToScreen() const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CXWindowsPrimaryScreen::onPreDispatch(const CEvent* event)
|
||||
IScreen*
|
||||
CXWindowsPrimaryScreen::getScreen() const
|
||||
{
|
||||
// forward to superclass
|
||||
return CXWindowsScreen::onPreDispatch(event);
|
||||
return m_screen;
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::onError()
|
||||
{
|
||||
// tell server to shutdown
|
||||
m_receiver->onError();
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::onScreensaver(bool activated)
|
||||
{
|
||||
m_receiver->onScreensaver(activated);
|
||||
}
|
||||
|
||||
bool
|
||||
CXWindowsPrimaryScreen::onPreDispatch(const CEvent*)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -313,41 +162,28 @@ CXWindowsPrimaryScreen::onEvent(CEvent* event)
|
||||
case CreateNotify:
|
||||
{
|
||||
// select events on new window
|
||||
CDisplayLock display(this);
|
||||
CDisplayLock display(m_screen);
|
||||
selectEvents(display, xevent.xcreatewindow.window);
|
||||
}
|
||||
return true;
|
||||
|
||||
case MappingNotify:
|
||||
{
|
||||
// keyboard mapping changed
|
||||
CDisplayLock display(this);
|
||||
XRefreshKeyboardMapping(&xevent.xmapping);
|
||||
updateModifierMap(display);
|
||||
}
|
||||
updateKeys();
|
||||
return true;
|
||||
|
||||
case ClientMessage:
|
||||
if (xevent.xclient.message_type == m_atomScreenSaver ||
|
||||
xevent.xclient.format == 32) {
|
||||
// screen saver activation/deactivation event
|
||||
m_primaryReceiver->onScreenSaver(xevent.xclient.data.l[0] != 0);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyPress:
|
||||
{
|
||||
log((CLOG_DEBUG1 "event: KeyPress code=%d, state=0x%04x", xevent.xkey.keycode, xevent.xkey.state));
|
||||
const KeyModifierMask mask = mapModifier(xevent.xkey.state);
|
||||
const KeyID key = mapKey(&xevent.xkey);
|
||||
if (key != kKeyNone) {
|
||||
m_primaryReceiver->onKeyDown(key, mask);
|
||||
m_receiver->onKeyDown(key, mask);
|
||||
if (key == XK_Caps_Lock && m_capsLockHalfDuplex) {
|
||||
m_primaryReceiver->onKeyUp(key, mask | KeyModifierCapsLock);
|
||||
m_receiver->onKeyUp(key, mask | KeyModifierCapsLock);
|
||||
}
|
||||
else if (key == XK_Num_Lock && m_numLockHalfDuplex) {
|
||||
m_primaryReceiver->onKeyUp(key, mask | KeyModifierNumLock);
|
||||
m_receiver->onKeyUp(key, mask | KeyModifierNumLock);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -369,20 +205,24 @@ CXWindowsPrimaryScreen::onEvent(CEvent* event)
|
||||
filter.m_keycode = xevent.xkey.keycode;
|
||||
|
||||
// now check for event
|
||||
bool hasPress;
|
||||
{
|
||||
XEvent xevent2;
|
||||
CDisplayLock display(this);
|
||||
if (XCheckIfEvent(display, &xevent2,
|
||||
CDisplayLock display(m_screen);
|
||||
hasPress = (XCheckIfEvent(display, &xevent2,
|
||||
&CXWindowsPrimaryScreen::findKeyEvent,
|
||||
(XPointer)&filter) != True) {
|
||||
(XPointer)&filter) == True);
|
||||
}
|
||||
if (!hasPress) {
|
||||
// no press event follows so it's a plain release
|
||||
log((CLOG_DEBUG1 "event: KeyRelease code=%d, state=0x%04x", xevent.xkey.keycode, xevent.xkey.state));
|
||||
if (key == XK_Caps_Lock && m_capsLockHalfDuplex) {
|
||||
m_primaryReceiver->onKeyDown(key, mask);
|
||||
m_receiver->onKeyDown(key, mask);
|
||||
}
|
||||
else if (key == XK_Num_Lock && m_numLockHalfDuplex) {
|
||||
m_primaryReceiver->onKeyDown(key, mask);
|
||||
m_receiver->onKeyDown(key, mask);
|
||||
}
|
||||
m_primaryReceiver->onKeyUp(key, mask);
|
||||
m_receiver->onKeyUp(key, mask);
|
||||
}
|
||||
else {
|
||||
// found a press event following so it's a repeat.
|
||||
@ -390,7 +230,7 @@ CXWindowsPrimaryScreen::onEvent(CEvent* event)
|
||||
// repeats but we'll just send a repeat of 1.
|
||||
// note that we discard the press event.
|
||||
log((CLOG_DEBUG1 "event: repeat code=%d, state=0x%04x", xevent.xkey.keycode, xevent.xkey.state));
|
||||
m_primaryReceiver->onKeyRepeat(key, mask, 1);
|
||||
m_receiver->onKeyRepeat(key, mask, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -401,7 +241,7 @@ CXWindowsPrimaryScreen::onEvent(CEvent* event)
|
||||
log((CLOG_DEBUG1 "event: ButtonPress button=%d", xevent.xbutton.button));
|
||||
const ButtonID button = mapButton(xevent.xbutton.button);
|
||||
if (button != kButtonNone) {
|
||||
m_primaryReceiver->onMouseDown(button);
|
||||
m_receiver->onMouseDown(button);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -411,15 +251,15 @@ CXWindowsPrimaryScreen::onEvent(CEvent* event)
|
||||
log((CLOG_DEBUG1 "event: ButtonRelease button=%d", xevent.xbutton.button));
|
||||
const ButtonID button = mapButton(xevent.xbutton.button);
|
||||
if (button != kButtonNone) {
|
||||
m_primaryReceiver->onMouseUp(button);
|
||||
m_receiver->onMouseUp(button);
|
||||
}
|
||||
else if (xevent.xbutton.button == 4) {
|
||||
// wheel forward (away from user)
|
||||
m_primaryReceiver->onMouseWheel(120);
|
||||
m_receiver->onMouseWheel(120);
|
||||
}
|
||||
else if (xevent.xbutton.button == 5) {
|
||||
// wheel backward (toward user)
|
||||
m_primaryReceiver->onMouseWheel(-120);
|
||||
m_receiver->onMouseWheel(-120);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -443,14 +283,14 @@ CXWindowsPrimaryScreen::onEvent(CEvent* event)
|
||||
// warpCursorNoFlush() for where the events are
|
||||
// sent. we discard the matching sent event and
|
||||
// can be sure we've skipped the warp event.
|
||||
CDisplayLock display(this);
|
||||
CDisplayLock display(m_screen);
|
||||
do {
|
||||
XMaskEvent(display, PointerMotionMask, &xevent);
|
||||
} while (!xevent.xmotion.send_event);
|
||||
}
|
||||
else if (!m_active) {
|
||||
else if (!isActive()) {
|
||||
// motion on primary screen
|
||||
m_primaryReceiver->onMouseMovePrimary(m_x, m_y);
|
||||
m_receiver->onMouseMovePrimary(m_x, m_y);
|
||||
}
|
||||
else {
|
||||
// motion on secondary screen. warp mouse back to
|
||||
@ -470,7 +310,7 @@ CXWindowsPrimaryScreen::onEvent(CEvent* event)
|
||||
xevent.xmotion.x_root - m_xCenter > s_size ||
|
||||
xevent.xmotion.y_root - m_yCenter < -s_size ||
|
||||
xevent.xmotion.y_root - m_yCenter > s_size) {
|
||||
CDisplayLock display(this);
|
||||
CDisplayLock display(m_screen);
|
||||
warpCursorNoFlush(display, m_xCenter, m_yCenter);
|
||||
}
|
||||
|
||||
@ -481,7 +321,7 @@ CXWindowsPrimaryScreen::onEvent(CEvent* event)
|
||||
// warping to the primary screen's enter position,
|
||||
// effectively overriding it.
|
||||
if (x != 0 || y != 0) {
|
||||
m_primaryReceiver->onMouseMoveSecondary(x, y);
|
||||
m_receiver->onMouseMoveSecondary(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -492,77 +332,117 @@ CXWindowsPrimaryScreen::onEvent(CEvent* event)
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::onUnexpectedClose()
|
||||
CXWindowsPrimaryScreen::onPreRun()
|
||||
{
|
||||
// tell server to shutdown
|
||||
m_primaryReceiver->onError();
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::onLostClipboard(ClipboardID id)
|
||||
{
|
||||
// tell server that the clipboard was grabbed locally
|
||||
m_receiver->onGrabClipboard(id);
|
||||
}
|
||||
|
||||
SInt32
|
||||
CXWindowsPrimaryScreen::getJumpZoneSize() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::warpCursorToCenter()
|
||||
{
|
||||
warpCursor(m_xCenter, m_yCenter);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::warpCursorNoFlush(
|
||||
Display* display, SInt32 x, SInt32 y)
|
||||
{
|
||||
assert(display != NULL);
|
||||
assert(m_window != None);
|
||||
|
||||
// send an event that we can recognize before the mouse warp
|
||||
XEvent eventBefore;
|
||||
eventBefore.type = MotionNotify;
|
||||
eventBefore.xmotion.display = display;
|
||||
eventBefore.xmotion.window = m_window;
|
||||
eventBefore.xmotion.root = getRoot();
|
||||
eventBefore.xmotion.subwindow = m_window;
|
||||
eventBefore.xmotion.time = CurrentTime;
|
||||
eventBefore.xmotion.x = x;
|
||||
eventBefore.xmotion.y = y;
|
||||
eventBefore.xmotion.x_root = x;
|
||||
eventBefore.xmotion.y_root = y;
|
||||
eventBefore.xmotion.state = 0;
|
||||
eventBefore.xmotion.is_hint = False;
|
||||
eventBefore.xmotion.same_screen = True;
|
||||
XEvent eventAfter = eventBefore;
|
||||
XSendEvent(display, m_window, False, 0, &eventBefore);
|
||||
|
||||
// warp mouse
|
||||
XWarpPointer(display, None, getRoot(), 0, 0, 0, 0, x, y);
|
||||
|
||||
// send an event that we can recognize after the mouse warp
|
||||
XSendEvent(display, m_window, False, 0, &eventAfter);
|
||||
XSync(display, False);
|
||||
|
||||
log((CLOG_DEBUG2 "warped to %d,%d", x, y));
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::enterNoWarp()
|
||||
CXWindowsPrimaryScreen::onPreOpen()
|
||||
{
|
||||
m_active = false;
|
||||
hideWindow();
|
||||
assert(m_window == None);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::onPostOpen()
|
||||
{
|
||||
// get cursor info
|
||||
m_screen->getCursorPos(m_x, m_y);
|
||||
m_screen->getCursorCenter(m_xCenter, m_yCenter);
|
||||
|
||||
// check for peculiarities
|
||||
// FIXME -- may have to get these from some database
|
||||
m_numLockHalfDuplex = false;
|
||||
m_capsLockHalfDuplex = false;
|
||||
// m_numLockHalfDuplex = true;
|
||||
// m_capsLockHalfDuplex = true;
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::onPreEnter()
|
||||
{
|
||||
assert(m_window != None);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::onPreLeave()
|
||||
{
|
||||
assert(m_window != None);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::onEnterScreenSaver()
|
||||
{
|
||||
CDisplayLock display(m_screen);
|
||||
|
||||
// set keyboard focus to root window. the screensaver should then
|
||||
// pick up key events for when the user enters a password to unlock.
|
||||
XSetInputFocus(display, PointerRoot, PointerRoot, CurrentTime);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::createWindow()
|
||||
{
|
||||
assert(m_window == None);
|
||||
|
||||
// get size of screen
|
||||
SInt32 x, y, w, h;
|
||||
m_screen->getShape(x, y, w, h);
|
||||
|
||||
// grab window attributes. this window is used to capture user
|
||||
// input when the user is focused on another client. don't let
|
||||
// the window manager mess with it.
|
||||
XSetWindowAttributes attr;
|
||||
attr.event_mask = PointerMotionMask |
|
||||
ButtonPressMask | ButtonReleaseMask |
|
||||
KeyPressMask | KeyReleaseMask |
|
||||
KeymapStateMask | PropertyChangeMask;
|
||||
attr.do_not_propagate_mask = 0;
|
||||
attr.override_redirect = True;
|
||||
attr.cursor = m_screen->getBlankCursor();
|
||||
|
||||
{
|
||||
// create the grab window
|
||||
CDisplayLock display(m_screen);
|
||||
m_window = XCreateWindow(display, m_screen->getRoot(),
|
||||
x, y, w, h, 0, 0,
|
||||
InputOnly, CopyFromParent,
|
||||
CWDontPropagate | CWEventMask |
|
||||
CWOverrideRedirect | CWCursor,
|
||||
&attr);
|
||||
if (m_window == None) {
|
||||
throw XScreenOpenFailure();
|
||||
}
|
||||
log((CLOG_DEBUG "window is 0x%08x", m_window));
|
||||
|
||||
// start watching for events on other windows
|
||||
selectEvents(display, m_screen->getRoot());
|
||||
}
|
||||
|
||||
// tell our superclass about the window
|
||||
m_screen->setWindow(m_window);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::destroyWindow()
|
||||
{
|
||||
// display can be NULL if the server unexpectedly disconnected
|
||||
if (m_window != None) {
|
||||
m_screen->setWindow(None);
|
||||
CDisplayLock display(m_screen);
|
||||
if (display != NULL) {
|
||||
XDestroyWindow(display, m_window);
|
||||
}
|
||||
m_window = None;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CXWindowsPrimaryScreen::showWindow()
|
||||
{
|
||||
CDisplayLock display(this);
|
||||
assert(m_window != None);
|
||||
|
||||
CDisplayLock display(m_screen);
|
||||
|
||||
// raise and show the input window
|
||||
XMapRaised(display, m_window);
|
||||
@ -616,83 +496,51 @@ CXWindowsPrimaryScreen::showWindow()
|
||||
void
|
||||
CXWindowsPrimaryScreen::hideWindow()
|
||||
{
|
||||
CDisplayLock display(this);
|
||||
CDisplayLock display(m_screen);
|
||||
|
||||
// unmap the grab window. this also ungrabs the mouse and keyboard.
|
||||
XUnmapWindow(display, m_window);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::checkClipboard()
|
||||
CXWindowsPrimaryScreen::warpCursorToCenter()
|
||||
{
|
||||
// do nothing, we're always up to date
|
||||
warpCursor(m_xCenter, m_yCenter);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::createWindow()
|
||||
CXWindowsPrimaryScreen::warpCursorNoFlush(
|
||||
Display* display, SInt32 x, SInt32 y)
|
||||
{
|
||||
assert(m_window == None);
|
||||
assert(display != NULL);
|
||||
assert(m_window != None);
|
||||
|
||||
// get size of screen
|
||||
SInt32 x, y, w, h;
|
||||
getScreenShape(x, y, w, h);
|
||||
// send an event that we can recognize before the mouse warp
|
||||
XEvent eventBefore;
|
||||
eventBefore.type = MotionNotify;
|
||||
eventBefore.xmotion.display = display;
|
||||
eventBefore.xmotion.window = m_window;
|
||||
eventBefore.xmotion.root = m_screen->getRoot();
|
||||
eventBefore.xmotion.subwindow = m_window;
|
||||
eventBefore.xmotion.time = CurrentTime;
|
||||
eventBefore.xmotion.x = x;
|
||||
eventBefore.xmotion.y = y;
|
||||
eventBefore.xmotion.x_root = x;
|
||||
eventBefore.xmotion.y_root = y;
|
||||
eventBefore.xmotion.state = 0;
|
||||
eventBefore.xmotion.is_hint = False;
|
||||
eventBefore.xmotion.same_screen = True;
|
||||
XEvent eventAfter = eventBefore;
|
||||
XSendEvent(display, m_window, False, 0, &eventBefore);
|
||||
|
||||
// grab window attributes. this window is used to capture user
|
||||
// input when the user is focused on another client. don't let
|
||||
// the window manager mess with it.
|
||||
XSetWindowAttributes attr;
|
||||
attr.event_mask = PointerMotionMask |
|
||||
ButtonPressMask | ButtonReleaseMask |
|
||||
KeyPressMask | KeyReleaseMask |
|
||||
KeymapStateMask | PropertyChangeMask;
|
||||
attr.do_not_propagate_mask = 0;
|
||||
attr.override_redirect = True;
|
||||
attr.cursor = getBlankCursor();
|
||||
// warp mouse
|
||||
XWarpPointer(display, None, m_screen->getRoot(), 0, 0, 0, 0, x, y);
|
||||
|
||||
// create the grab window
|
||||
CDisplayLock display(this);
|
||||
m_window = XCreateWindow(display, getRoot(),
|
||||
x, y, w, h, 0, 0,
|
||||
InputOnly, CopyFromParent,
|
||||
CWDontPropagate | CWEventMask |
|
||||
CWOverrideRedirect | CWCursor,
|
||||
&attr);
|
||||
if (m_window == None) {
|
||||
throw XScreenOpenFailure();
|
||||
}
|
||||
log((CLOG_DEBUG "window is 0x%08x", m_window));
|
||||
// send an event that we can recognize after the mouse warp
|
||||
XSendEvent(display, m_window, False, 0, &eventAfter);
|
||||
XSync(display, False);
|
||||
|
||||
// start watching for events on other windows
|
||||
selectEvents(display, getRoot());
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::destroyWindow()
|
||||
{
|
||||
// display can be NULL if the server unexpectedly disconnected
|
||||
CDisplayLock display(this);
|
||||
if (display != NULL && m_window != None) {
|
||||
XDestroyWindow(display, m_window);
|
||||
}
|
||||
m_window = None;
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::installScreenSaver()
|
||||
{
|
||||
assert(getScreenSaver() != NULL);
|
||||
|
||||
getScreenSaver()->setNotify(m_window);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::uninstallScreenSaver()
|
||||
{
|
||||
// stop being notified of screen saver activation/deactivation
|
||||
if (getScreenSaver() != NULL) {
|
||||
getScreenSaver()->setNotify(None);
|
||||
}
|
||||
m_atomScreenSaver = None;
|
||||
log((CLOG_DEBUG2 "warped to %d,%d", x, y));
|
||||
}
|
||||
|
||||
void
|
||||
@ -777,7 +625,7 @@ CXWindowsPrimaryScreen::mapKey(XKeyEvent* event) const
|
||||
KeySym keysym;
|
||||
char dummy[1];
|
||||
|
||||
CDisplayLock display(this);
|
||||
CDisplayLock display(m_screen);
|
||||
XLookupString(event, dummy, 0, &keysym, NULL);
|
||||
return static_cast<KeyID>(keysym);
|
||||
}
|
||||
@ -795,8 +643,10 @@ CXWindowsPrimaryScreen::mapButton(unsigned int button) const
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::updateModifierMap(Display* display)
|
||||
CXWindowsPrimaryScreen::updateKeys()
|
||||
{
|
||||
CDisplayLock display(m_screen);
|
||||
|
||||
// get modifier map from server
|
||||
XModifierKeymap* keymap = XGetModifierMapping(display);
|
||||
|
||||
|
@ -1,63 +1,59 @@
|
||||
#ifndef CXWINDOWSPRIMARYSCREEN_H
|
||||
#define CXWINDOWSPRIMARYSCREEN_H
|
||||
|
||||
#include "CXWindowsScreen.h"
|
||||
#include "IPrimaryScreen.h"
|
||||
#include "CPrimaryScreen.h"
|
||||
#include "IScreenEventHandler.h"
|
||||
#include "MouseTypes.h"
|
||||
#if defined(X_DISPLAY_MISSING)
|
||||
# error X11 is required to build synergy
|
||||
#else
|
||||
# include <X11/Xlib.h>
|
||||
#endif
|
||||
|
||||
class CXWindowsScreen;
|
||||
class IScreenReceiver;
|
||||
class IPrimaryScreenReceiver;
|
||||
|
||||
class CXWindowsPrimaryScreen : public CXWindowsScreen, public IPrimaryScreen {
|
||||
class CXWindowsPrimaryScreen :
|
||||
public CPrimaryScreen, public IScreenEventHandler {
|
||||
public:
|
||||
CXWindowsPrimaryScreen(IScreenReceiver*, IPrimaryScreenReceiver*);
|
||||
virtual ~CXWindowsPrimaryScreen();
|
||||
|
||||
// IPrimaryScreen overrides
|
||||
virtual void run();
|
||||
virtual void stop();
|
||||
virtual void open();
|
||||
virtual void close();
|
||||
virtual void enter(SInt32 xAbsolute, SInt32 yAbsolute, bool);
|
||||
virtual bool leave();
|
||||
// CPrimaryScreen overrides
|
||||
virtual void reconfigure(UInt32 activeSides);
|
||||
virtual void warpCursor(SInt32 xAbsolute, SInt32 yAbsolute);
|
||||
virtual void setClipboard(ClipboardID, const IClipboard*);
|
||||
virtual void grabClipboard(ClipboardID);
|
||||
virtual void getClipboard(ClipboardID, IClipboard*) const;
|
||||
virtual void warpCursor(SInt32 x, SInt32 y);
|
||||
virtual KeyModifierMask getToggleMask() const;
|
||||
virtual bool isLockedToScreen() const;
|
||||
virtual IScreen* getScreen() const;
|
||||
|
||||
protected:
|
||||
// CXWindowsScreen overrides
|
||||
// IScreenEventHandler overrides
|
||||
virtual void onError();
|
||||
virtual void onScreensaver(bool activated);
|
||||
virtual bool onPreDispatch(const CEvent* event);
|
||||
virtual bool onEvent(CEvent* event);
|
||||
virtual void onUnexpectedClose();
|
||||
virtual void onLostClipboard(ClipboardID);
|
||||
|
||||
protected:
|
||||
// CPrimaryScreen overrides
|
||||
virtual void onPreRun();
|
||||
virtual void onPreOpen();
|
||||
virtual void onPostOpen();
|
||||
virtual void onPreEnter();
|
||||
virtual void onPreLeave();
|
||||
virtual void onEnterScreenSaver();
|
||||
|
||||
virtual void createWindow();
|
||||
virtual void destroyWindow();
|
||||
virtual bool showWindow();
|
||||
virtual void hideWindow();
|
||||
virtual void warpCursorToCenter();
|
||||
|
||||
virtual void updateKeys();
|
||||
|
||||
private:
|
||||
SInt32 getJumpZoneSize() const;
|
||||
|
||||
void warpCursorToCenter();
|
||||
void warpCursorNoFlush(Display*,
|
||||
SInt32 xAbsolute, SInt32 yAbsolute);
|
||||
|
||||
void enterNoWarp();
|
||||
bool showWindow();
|
||||
void hideWindow();
|
||||
|
||||
// check clipboard ownership and, if necessary, tell the receiver
|
||||
// of a grab.
|
||||
void checkClipboard();
|
||||
|
||||
// create/destroy window
|
||||
void createWindow();
|
||||
void destroyWindow();
|
||||
|
||||
// start/stop watch for screen saver changes
|
||||
void installScreenSaver();
|
||||
void uninstallScreenSaver();
|
||||
|
||||
void selectEvents(Display*, Window) const;
|
||||
void doSelectEvents(Display*, Window) const;
|
||||
|
||||
@ -65,8 +61,6 @@ private:
|
||||
KeyID mapKey(XKeyEvent*) const;
|
||||
ButtonID mapButton(unsigned int button) const;
|
||||
|
||||
void updateModifierMap(Display* display);
|
||||
|
||||
class CKeyEventInfo {
|
||||
public:
|
||||
int m_event;
|
||||
@ -77,15 +71,12 @@ private:
|
||||
static Bool findKeyEvent(Display*, XEvent* xevent, XPointer arg);
|
||||
|
||||
private:
|
||||
IScreenReceiver* m_receiver;
|
||||
IPrimaryScreenReceiver* m_primaryReceiver;
|
||||
CXWindowsScreen* m_screen;
|
||||
IPrimaryScreenReceiver* m_receiver;
|
||||
|
||||
bool m_active;
|
||||
// our window
|
||||
Window m_window;
|
||||
|
||||
// atom for screen saver messages
|
||||
Atom m_atomScreenSaver;
|
||||
|
||||
// note toggle keys that toggle on up/down (false) or on
|
||||
// transition (true)
|
||||
bool m_numLockHalfDuplex;
|
||||
|
@ -1,95 +0,0 @@
|
||||
#ifndef IPRIMARYSCREEN_H
|
||||
#define IPRIMARYSCREEN_H
|
||||
|
||||
#include "IInterface.h"
|
||||
#include "KeyTypes.h"
|
||||
#include "ClipboardTypes.h"
|
||||
|
||||
class IClipboard;
|
||||
|
||||
class IPrimaryScreen : public IInterface {
|
||||
public:
|
||||
// manipulators
|
||||
|
||||
// enter the screen's message loop. this returns when it detects
|
||||
// the application should terminate or when stop() is called.
|
||||
// the screen must be open()'d before run() and must not be
|
||||
// close()'d until run() returns.
|
||||
virtual void run() = 0;
|
||||
|
||||
// cause run() to return
|
||||
virtual void stop() = 0;
|
||||
|
||||
// initialize the screen and start reporting events to the receiver
|
||||
// (which is set through some interface of the derived class).
|
||||
// events should be reported no matter where on the screen they
|
||||
// occur but do not interfere with normal event dispatch. the
|
||||
// screen saver engaging should be reported as an event. if that
|
||||
// can't be detected then this object should disable the system's
|
||||
// screen saver timer and should start the screen saver after
|
||||
// idling for an appropriate time.
|
||||
//
|
||||
// open() must call receiver->onInfoChanged() to notify of the
|
||||
// primary screen's initial resolution and jump zone size. it
|
||||
// must also call receiver->onClipboardChanged() for each
|
||||
// clipboard that the primary screen has.
|
||||
virtual void open() = 0;
|
||||
|
||||
// close the screen. should restore the screen saver timer if it
|
||||
// was disabled.
|
||||
virtual void close() = 0;
|
||||
|
||||
// called when the user navigates back to the primary screen.
|
||||
// warp the cursor to the given coordinates, unhide it, and
|
||||
// ungrab the input devices. every call to enter has a matching
|
||||
// call to leave() which preceeds it, however the screen should
|
||||
// assume an implicit call to enter() in the call to open().
|
||||
// if warpCursor is false then do not warp the mouse.
|
||||
//
|
||||
// enter() must not call any receiver methods except onError().
|
||||
virtual void enter(SInt32 xAbsolute, SInt32 yAbsolute,
|
||||
bool forScreenSaver) = 0;
|
||||
|
||||
// called when the user navigates off the primary screen. hide the
|
||||
// cursor and grab exclusive access to the input devices. return
|
||||
// true iff successful.
|
||||
//
|
||||
// leave() must not call any receiver methods except onError().
|
||||
virtual bool leave() = 0;
|
||||
|
||||
// called when the configuration has changed. activeSides is a
|
||||
// bitmask of CConfig::EDirectionMask indicating which sides of
|
||||
// the primary screen are linked to clients.
|
||||
virtual void reconfigure(UInt32 activeSides) = 0;
|
||||
|
||||
// warp the cursor to the given position
|
||||
virtual void warpCursor(SInt32 xAbsolute, SInt32 yAbsolute) = 0;
|
||||
|
||||
// set the screen's clipboard contents. this is usually called
|
||||
// soon after an enter().
|
||||
//
|
||||
// setClipboard() must not call any receiver methods except onError().
|
||||
virtual void setClipboard(ClipboardID, const IClipboard*) = 0;
|
||||
|
||||
// synergy should own the clipboard
|
||||
virtual void grabClipboard(ClipboardID) = 0;
|
||||
|
||||
// accessors
|
||||
|
||||
// return the contents of the given clipboard.
|
||||
//
|
||||
// getClipboard() must not call any receiver methods except onError().
|
||||
virtual void getClipboard(ClipboardID, IClipboard*) const = 0;
|
||||
|
||||
// get the primary screen's current toggle modifier key state.
|
||||
// the returned mask should have the corresponding bit set for
|
||||
// each toggle key that is active.
|
||||
virtual KeyModifierMask getToggleMask() const = 0;
|
||||
|
||||
// return true if any key or button is being pressed or if there's
|
||||
// any other reason that the user should not be allowed to switch
|
||||
// screens.
|
||||
virtual bool isLockedToScreen() const = 0;
|
||||
};
|
||||
|
||||
#endif
|
@ -9,6 +9,7 @@ synergyd_SOURCES = \
|
||||
CConfig.cpp \
|
||||
CHTTPServer.cpp \
|
||||
CPrimaryClient.cpp \
|
||||
CPrimaryScreen.cpp \
|
||||
CServer.cpp \
|
||||
CXWindowsPrimaryScreen.cpp \
|
||||
server.cpp \
|
||||
@ -17,9 +18,9 @@ synergyd_SOURCES = \
|
||||
CConfig.h \
|
||||
CHTTPServer.h \
|
||||
CPrimaryClient.h \
|
||||
CPrimaryScreen.h \
|
||||
CServer.h \
|
||||
CXWindowsPrimaryScreen.h \
|
||||
IPrimaryScreen.h \
|
||||
$(NULL)
|
||||
synergyd_LDADD = \
|
||||
$(DEPTH)/platform/libplatform.a \
|
||||
|
@ -132,6 +132,7 @@ realMain(CMutex* mutex)
|
||||
}
|
||||
|
||||
// clean up
|
||||
s_server->close();
|
||||
delete s_server;
|
||||
s_server = NULL;
|
||||
CLog::setLock(NULL);
|
||||
@ -142,8 +143,11 @@ realMain(CMutex* mutex)
|
||||
if (!locked && mutex != NULL) {
|
||||
mutex->lock();
|
||||
}
|
||||
if (s_server != NULL) {
|
||||
s_server->close();
|
||||
delete s_server;
|
||||
s_server = NULL;
|
||||
}
|
||||
CLog::setLock(NULL);
|
||||
s_logMutex = NULL;
|
||||
throw;
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include "MouseTypes.h"
|
||||
#include "CString.h"
|
||||
|
||||
// the client interface. this provides all the methods necessary for
|
||||
// the server to communicate with a client.
|
||||
class IClient : public IInterface {
|
||||
public:
|
||||
// manipulators
|
||||
@ -23,11 +25,11 @@ public:
|
||||
// enter the screen. the cursor should be warped to xAbs,yAbs.
|
||||
// the client should record seqNum for future reporting of
|
||||
// clipboard changes. mask is the expected toggle button state.
|
||||
// screenSaver is true if the screen is being entered because
|
||||
// forScreensaver is true if the screen is being entered because
|
||||
// the screen saver is starting.
|
||||
virtual void enter(SInt32 xAbs, SInt32 yAbs,
|
||||
UInt32 seqNum, KeyModifierMask mask,
|
||||
bool screenSaver) = 0;
|
||||
bool forScreensaver) = 0;
|
||||
|
||||
// leave the screen. returns false if the user may not leave the
|
||||
// client's screen.
|
||||
@ -54,25 +56,25 @@ public:
|
||||
virtual void mouseUp(ButtonID) = 0;
|
||||
virtual void mouseMove(SInt32 xAbs, SInt32 yAbs) = 0;
|
||||
virtual void mouseWheel(SInt32 delta) = 0;
|
||||
virtual void screenSaver(bool activate) = 0;
|
||||
virtual void screensaver(bool activate) = 0;
|
||||
|
||||
// accessors
|
||||
|
||||
// get the client's identifier
|
||||
virtual CString getName() const = 0;
|
||||
|
||||
// get the size of jump zone
|
||||
virtual SInt32 getJumpZoneSize() const = 0;
|
||||
|
||||
// get the screen's shape
|
||||
virtual void getShape(SInt32& x, SInt32& y,
|
||||
SInt32& width, SInt32& height) const = 0;
|
||||
|
||||
// get the center pixel
|
||||
virtual void getCenter(SInt32& x, SInt32& y) const = 0;
|
||||
|
||||
// get the mouse position
|
||||
virtual void getMousePos(SInt32& x, SInt32& y) const = 0;
|
||||
virtual void getCursorPos(SInt32& x, SInt32& y) const = 0;
|
||||
|
||||
// get the size of jump zone
|
||||
virtual SInt32 getJumpZoneSize() const = 0;
|
||||
// get the center pixel
|
||||
virtual void getCursorCenter(SInt32& x, SInt32& y) const = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -5,12 +5,22 @@
|
||||
#include "KeyTypes.h"
|
||||
#include "MouseTypes.h"
|
||||
|
||||
// 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 serious error. this implies that the server should
|
||||
// shutdown.
|
||||
// called if the display is unexpectedly closing.
|
||||
|
||||
// called if the screen is unexpectedly closing. this implies that
|
||||
// the screen is no longer usable and that the program should
|
||||
// close the screen and possibly terminate.
|
||||
virtual void onError() = 0;
|
||||
|
||||
// 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.
|
||||
virtual void onKeyDown(KeyID, KeyModifierMask) = 0;
|
||||
@ -21,8 +31,6 @@ public:
|
||||
virtual bool onMouseMovePrimary(SInt32 x, SInt32 y) = 0;
|
||||
virtual void onMouseMoveSecondary(SInt32 dx, SInt32 dy) = 0;
|
||||
virtual void onMouseWheel(SInt32 delta) = 0;
|
||||
virtual void onScreenSaver(bool activated) = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
66
synergy/IScreen.h
Normal file
66
synergy/IScreen.h
Normal file
@ -0,0 +1,66 @@
|
||||
#ifndef ISCREEN_H
|
||||
#define ISCREEN_H
|
||||
|
||||
#include "IInterface.h"
|
||||
#include "ClipboardTypes.h"
|
||||
|
||||
class IClipboard;
|
||||
|
||||
// the interface for platform dependent screen implementations. each
|
||||
// platform will derive a type from IScreen for interaction with the
|
||||
// platform's screen that's common to primary and secondary screens.
|
||||
class IScreen : public IInterface {
|
||||
public:
|
||||
// manipulators
|
||||
|
||||
// open the screen
|
||||
virtual void open() = 0;
|
||||
|
||||
// runs an event loop and returns when exitMainLoop() is called.
|
||||
// must be called between open() and close().
|
||||
virtual void mainLoop() = 0;
|
||||
|
||||
// force mainLoop() to return
|
||||
virtual void exitMainLoop() = 0;
|
||||
|
||||
// close the screen
|
||||
virtual void close() = 0;
|
||||
|
||||
// set the contents of the clipboard
|
||||
virtual bool setClipboard(ClipboardID, const IClipboard*) = 0;
|
||||
|
||||
// check clipboard ownership and notify IScreenReceiver (set through
|
||||
// some other interface) if any changed
|
||||
virtual void checkClipboards() = 0;
|
||||
|
||||
// open/close the screen saver. if notify is true then this object
|
||||
// will call IScreenEventHandler's onScreenSaver() when the screensaver
|
||||
// activates or deactivates until close. if notify is false then
|
||||
// the screen saver is disabled on open and restored on close.
|
||||
virtual void openScreenSaver(bool notify) = 0;
|
||||
virtual void closeScreenSaver() = 0;
|
||||
|
||||
// activate or deactivate the screen saver
|
||||
virtual void screensaver(bool activate) = 0;
|
||||
|
||||
// FIXME -- need explanation
|
||||
virtual void syncDesktop() = 0;
|
||||
|
||||
// accessors
|
||||
|
||||
// get the contents of the clipboard
|
||||
virtual bool getClipboard(ClipboardID, IClipboard*) const = 0;
|
||||
|
||||
// get the shape of the screen
|
||||
virtual void getShape(SInt32& x, SInt32& y,
|
||||
SInt32& w, SInt32& h) const = 0;
|
||||
|
||||
// get the current cursor coordinates
|
||||
virtual void getCursorPos(SInt32& x, SInt32& y) const = 0;
|
||||
|
||||
// get the cursor center position
|
||||
// FIXME -- need better explanation
|
||||
virtual void getCursorCenter(SInt32& x, SInt32& y) const = 0;
|
||||
};
|
||||
|
||||
#endif
|
39
synergy/IScreenEventHandler.h
Normal file
39
synergy/IScreenEventHandler.h
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef ISCREENEVENTHANDLER_H
|
||||
#define ISCREENEVENTHANDLER_H
|
||||
|
||||
#include "IInterface.h"
|
||||
|
||||
// the platform screen should define this
|
||||
class CEvent;
|
||||
|
||||
class IScreen;
|
||||
|
||||
// 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:
|
||||
// manipulators
|
||||
|
||||
// called if the screen is unexpectedly closing. this implies that
|
||||
// the screen is no longer usable and that the program should
|
||||
// close the screen and possibly terminate.
|
||||
virtual void onError() = 0;
|
||||
|
||||
// called when the screensaver is activated or deactivated
|
||||
virtual void onScreensaver(bool activated) = 0;
|
||||
|
||||
// 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;
|
||||
|
||||
// called by mainLoop(). iff the event was handled return true and
|
||||
// store the result, if any, in m_result, which defaults to zero.
|
||||
virtual bool onEvent(CEvent* event) = 0;
|
||||
};
|
||||
|
||||
#endif
|
@ -6,6 +6,8 @@
|
||||
#include "ProtocolTypes.h"
|
||||
#include "CString.h"
|
||||
|
||||
// the interface for types that receive screen resize and clipboard
|
||||
// notifications (indirectly) from the system.
|
||||
class IScreenReceiver : public IInterface {
|
||||
public:
|
||||
// notify of client info change
|
||||
|
@ -1,13 +1,19 @@
|
||||
#ifndef ISERVER_H
|
||||
#define ISERVER_H
|
||||
|
||||
#include "IPrimaryScreenReceiver.h"
|
||||
#include "IInterface.h"
|
||||
#include "ClipboardTypes.h"
|
||||
#include "CString.h"
|
||||
|
||||
class CClientInfo;
|
||||
|
||||
class IServer : public IPrimaryScreenReceiver {
|
||||
// the server interface. this provides all 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:
|
||||
// manipulators
|
||||
|
||||
@ -23,18 +29,6 @@ public:
|
||||
// notify of new clipboard data
|
||||
virtual void onClipboardChanged(ClipboardID,
|
||||
UInt32 seqNum, const CString& data) = 0;
|
||||
|
||||
// IPrimaryScreenReceiver overrides
|
||||
virtual void onError() = 0;
|
||||
virtual void onKeyDown(KeyID, KeyModifierMask) = 0;
|
||||
virtual void onKeyUp(KeyID, KeyModifierMask) = 0;
|
||||
virtual void onKeyRepeat(KeyID, KeyModifierMask, SInt32 count) = 0;
|
||||
virtual void onMouseDown(ButtonID) = 0;
|
||||
virtual void onMouseUp(ButtonID) = 0;
|
||||
virtual bool onMouseMovePrimary(SInt32 x, SInt32 y) = 0;
|
||||
virtual void onMouseMoveSecondary(SInt32 dx, SInt32 dy) = 0;
|
||||
virtual void onMouseWheel(SInt32 delta) = 0;
|
||||
virtual void onScreenSaver(bool activated) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -20,6 +20,8 @@ libsynergy_a_SOURCES = \
|
||||
IClient.h \
|
||||
IClipboard.h \
|
||||
IPrimaryScreenReceiver.h\
|
||||
IScreen.h \
|
||||
IScreenEventHandler.h \
|
||||
IScreenReceiver.h \
|
||||
IScreenSaver.h \
|
||||
IServer.h \
|
||||
|
Loading…
Reference in New Issue
Block a user