Added support on X11 for a global option to delay switching screens
when the mouse reaches a jump zone.
This commit is contained in:
parent
aef50800e3
commit
7bbd33d787
|
@ -102,6 +102,12 @@ CXWindowsPrimaryScreen::setOptions(const COptionsList& options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UInt32
|
||||||
|
CXWindowsPrimaryScreen::addOneShotTimer(double timeout)
|
||||||
|
{
|
||||||
|
return m_screen->addOneShotTimer(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
KeyModifierMask
|
KeyModifierMask
|
||||||
CXWindowsPrimaryScreen::getToggleMask() const
|
CXWindowsPrimaryScreen::getToggleMask() const
|
||||||
{
|
{
|
||||||
|
@ -387,6 +393,12 @@ CXWindowsPrimaryScreen::onEvent(CEvent* event)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CXWindowsPrimaryScreen::onOneShotTimerExpired(UInt32 id)
|
||||||
|
{
|
||||||
|
m_receiver->onOneShotTimerExpired(id);
|
||||||
|
}
|
||||||
|
|
||||||
SInt32
|
SInt32
|
||||||
CXWindowsPrimaryScreen::getJumpZoneSize() const
|
CXWindowsPrimaryScreen::getJumpZoneSize() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -40,6 +40,7 @@ public:
|
||||||
virtual void warpCursor(SInt32 x, SInt32 y);
|
virtual void warpCursor(SInt32 x, SInt32 y);
|
||||||
virtual void resetOptions();
|
virtual void resetOptions();
|
||||||
virtual void setOptions(const COptionsList& options);
|
virtual void setOptions(const COptionsList& options);
|
||||||
|
virtual UInt32 addOneShotTimer(double timeout);
|
||||||
virtual KeyModifierMask getToggleMask() const;
|
virtual KeyModifierMask getToggleMask() const;
|
||||||
virtual bool isLockedToScreen() const;
|
virtual bool isLockedToScreen() const;
|
||||||
virtual IScreen* getScreen() const;
|
virtual IScreen* getScreen() const;
|
||||||
|
@ -48,6 +49,7 @@ public:
|
||||||
virtual void onScreensaver(bool activated);
|
virtual void onScreensaver(bool activated);
|
||||||
virtual bool onPreDispatch(const CEvent* event);
|
virtual bool onPreDispatch(const CEvent* event);
|
||||||
virtual bool onEvent(CEvent* event);
|
virtual bool onEvent(CEvent* event);
|
||||||
|
virtual void onOneShotTimerExpired(UInt32 id);
|
||||||
virtual SInt32 getJumpZoneSize() const;
|
virtual SInt32 getJumpZoneSize() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -54,14 +54,13 @@
|
||||||
// CXWindowsScreen::CTimer
|
// CXWindowsScreen::CTimer
|
||||||
//
|
//
|
||||||
|
|
||||||
CXWindowsScreen::CTimer::CTimer(IJob* job, double timeout) :
|
CXWindowsScreen::CTimer::CTimer(IJob* job, double startTime, double resetTime) :
|
||||||
m_job(job),
|
m_job(job),
|
||||||
m_timeout(timeout)
|
m_timeout(resetTime),
|
||||||
|
m_time(resetTime),
|
||||||
|
m_startTime(startTime)
|
||||||
{
|
{
|
||||||
assert(m_job != NULL);
|
|
||||||
assert(m_timeout > 0.0);
|
assert(m_timeout > 0.0);
|
||||||
|
|
||||||
reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CXWindowsScreen::CTimer::~CTimer()
|
CXWindowsScreen::CTimer::~CTimer()
|
||||||
|
@ -72,19 +71,23 @@ CXWindowsScreen::CTimer::~CTimer()
|
||||||
void
|
void
|
||||||
CXWindowsScreen::CTimer::run()
|
CXWindowsScreen::CTimer::run()
|
||||||
{
|
{
|
||||||
m_job->run();
|
if (m_job != NULL) {
|
||||||
|
m_job->run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CXWindowsScreen::CTimer::reset()
|
CXWindowsScreen::CTimer::reset()
|
||||||
{
|
{
|
||||||
m_time = m_timeout;
|
m_time = m_timeout;
|
||||||
|
m_startTime = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CXWindowsScreen::CTimer::CTimer&
|
CXWindowsScreen::CTimer::CTimer&
|
||||||
CXWindowsScreen::CTimer::operator-=(double dt)
|
CXWindowsScreen::CTimer::operator-=(double dt)
|
||||||
{
|
{
|
||||||
m_time -= dt;
|
m_time -= dt - m_startTime;
|
||||||
|
m_startTime = 0.0;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +121,8 @@ CXWindowsScreen::CXWindowsScreen(IScreenReceiver* receiver,
|
||||||
m_w(0), m_h(0),
|
m_w(0), m_h(0),
|
||||||
m_screensaver(NULL),
|
m_screensaver(NULL),
|
||||||
m_screensaverNotify(false),
|
m_screensaverNotify(false),
|
||||||
m_atomScreensaver(None)
|
m_atomScreensaver(None),
|
||||||
|
m_oneShotTimer(NULL)
|
||||||
{
|
{
|
||||||
assert(s_screen == NULL);
|
assert(s_screen == NULL);
|
||||||
assert(m_receiver != NULL);
|
assert(m_receiver != NULL);
|
||||||
|
@ -137,6 +141,7 @@ CXWindowsScreen::~CXWindowsScreen()
|
||||||
assert(s_screen != NULL);
|
assert(s_screen != NULL);
|
||||||
assert(m_display == NULL);
|
assert(m_display == NULL);
|
||||||
|
|
||||||
|
delete m_oneShotTimer;
|
||||||
s_screen = NULL;
|
s_screen = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +150,7 @@ CXWindowsScreen::addTimer(IJob* job, double timeout)
|
||||||
{
|
{
|
||||||
CLock lock(&m_timersMutex);
|
CLock lock(&m_timersMutex);
|
||||||
removeTimerNoLock(job);
|
removeTimerNoLock(job);
|
||||||
m_timers.push(CTimer(job, timeout));
|
m_timers.push(CTimer(job, m_time.getTime(), timeout));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -172,6 +177,15 @@ CXWindowsScreen::removeTimerNoLock(IJob* job)
|
||||||
m_timers.swap(tmp);
|
m_timers.swap(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UInt32
|
||||||
|
CXWindowsScreen::addOneShotTimer(double timeout)
|
||||||
|
{
|
||||||
|
CLock lock(&m_timersMutex);
|
||||||
|
// FIXME -- support multiple one-shot timers
|
||||||
|
m_oneShotTimer = new CTimer(NULL, m_time.getTime(), timeout);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CXWindowsScreen::setWindow(Window window)
|
CXWindowsScreen::setWindow(Window window)
|
||||||
{
|
{
|
||||||
|
@ -262,19 +276,27 @@ CXWindowsScreen::mainLoop()
|
||||||
#endif
|
#endif
|
||||||
while (!m_stop) {
|
while (!m_stop) {
|
||||||
// compute timeout to next timer
|
// compute timeout to next timer
|
||||||
|
double dtimeout;
|
||||||
|
{
|
||||||
|
CLock timersLock(&m_timersMutex);
|
||||||
|
dtimeout = (m_timers.empty() ? -1.0 : m_timers.top());
|
||||||
|
if (m_oneShotTimer != NULL &&
|
||||||
|
(dtimeout == -1.0 || *m_oneShotTimer < dtimeout)) {
|
||||||
|
dtimeout = *m_oneShotTimer;
|
||||||
|
}
|
||||||
|
}
|
||||||
#if HAVE_POLL
|
#if HAVE_POLL
|
||||||
int timeout = (m_timers.empty() ? -1 :
|
int timeout = static_cast<int>(1000.0 * dtimeout);
|
||||||
static_cast<int>(1000.0 * m_timers.top()));
|
|
||||||
#else
|
#else
|
||||||
struct timeval timeout;
|
struct timeval timeout;
|
||||||
struct timeval* timeoutPtr;
|
struct timeval* timeoutPtr;
|
||||||
if (m_timers.empty()) {
|
if (dtimeout < 0.0) {
|
||||||
timeoutPtr = NULL;
|
timeoutPtr = NULL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
timeout.tv_sec = static_cast<int>(m_timers.top());
|
timeout.tv_sec = static_cast<int>(dtimeout);
|
||||||
timeout.tv_usec = static_cast<int>(1.0e+6 *
|
timeout.tv_usec = static_cast<int>(1.0e+6 *
|
||||||
(m_timers.top() - timeout.tv_sec));
|
(dtimeout - timeout.tv_sec));
|
||||||
timeoutPtr = &timeout;
|
timeoutPtr = &timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -697,6 +719,7 @@ CXWindowsScreen::createBlankCursor()
|
||||||
bool
|
bool
|
||||||
CXWindowsScreen::processTimers()
|
CXWindowsScreen::processTimers()
|
||||||
{
|
{
|
||||||
|
bool oneShot = false;
|
||||||
std::vector<IJob*> jobs;
|
std::vector<IJob*> jobs;
|
||||||
{
|
{
|
||||||
CLock lock(&m_timersMutex);
|
CLock lock(&m_timersMutex);
|
||||||
|
@ -705,10 +728,21 @@ CXWindowsScreen::processTimers()
|
||||||
const double time = m_time.getTime();
|
const double time = m_time.getTime();
|
||||||
|
|
||||||
// done if no timers have expired
|
// done if no timers have expired
|
||||||
if (m_timers.empty() || m_timers.top() > time) {
|
if ((m_oneShotTimer == NULL || *m_oneShotTimer > time) &&
|
||||||
|
(m_timers.empty() || m_timers.top() > time)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle one shot timers
|
||||||
|
if (m_oneShotTimer != NULL) {
|
||||||
|
*m_oneShotTimer -= time;
|
||||||
|
if (*m_oneShotTimer <= 0.0) {
|
||||||
|
delete m_oneShotTimer;
|
||||||
|
m_oneShotTimer = NULL;
|
||||||
|
oneShot = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// subtract current time from all timers. note that this won't
|
// subtract current time from all timers. note that this won't
|
||||||
// change the order of elements in the priority queue (except
|
// change the order of elements in the priority queue (except
|
||||||
// for floating point round off which we'll ignore).
|
// for floating point round off which we'll ignore).
|
||||||
|
@ -718,18 +752,27 @@ CXWindowsScreen::processTimers()
|
||||||
}
|
}
|
||||||
|
|
||||||
// process all timers at or below zero, saving the jobs
|
// process all timers at or below zero, saving the jobs
|
||||||
while (m_timers.top() <= 0.0) {
|
if (!m_timers.empty()) {
|
||||||
CTimer timer = m_timers.top();
|
while (m_timers.top() <= 0.0) {
|
||||||
jobs.push_back(timer.getJob());
|
CTimer timer = m_timers.top();
|
||||||
timer.reset();
|
jobs.push_back(timer.getJob());
|
||||||
m_timers.pop();
|
timer.reset();
|
||||||
m_timers.push(timer);
|
m_timers.pop();
|
||||||
|
m_timers.push(timer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset the clock
|
// reset the clock
|
||||||
m_time.reset();
|
m_time.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// now notify of the one shot timers
|
||||||
|
if (oneShot) {
|
||||||
|
m_mutex.unlock();
|
||||||
|
m_eventHandler->onOneShotTimerExpired(0);
|
||||||
|
m_mutex.lock();
|
||||||
|
}
|
||||||
|
|
||||||
// now run the jobs. note that if one of these jobs removes
|
// now run the jobs. note that if one of these jobs removes
|
||||||
// a timer later in the jobs list and deletes that job pointer
|
// a timer later in the jobs list and deletes that job pointer
|
||||||
// then this will crash when it tries to run that job.
|
// then this will crash when it tries to run that job.
|
||||||
|
|
|
@ -69,6 +69,14 @@ public:
|
||||||
*/
|
*/
|
||||||
void removeTimer(IJob*);
|
void removeTimer(IJob*);
|
||||||
|
|
||||||
|
//! Install a one-shot timer
|
||||||
|
/*!
|
||||||
|
Installs a one-shot timer for \c timeout seconds and returns the
|
||||||
|
id of the timer (which will be passed to the receiver's
|
||||||
|
\c onTimerExpired()).
|
||||||
|
*/
|
||||||
|
UInt32 addOneShotTimer(double timeout);
|
||||||
|
|
||||||
//! Set window
|
//! Set window
|
||||||
/*!
|
/*!
|
||||||
Set the window (created by the subclass). This performs some
|
Set the window (created by the subclass). This performs some
|
||||||
|
@ -216,7 +224,7 @@ private:
|
||||||
// a timer priority queue element
|
// a timer priority queue element
|
||||||
class CTimer {
|
class CTimer {
|
||||||
public:
|
public:
|
||||||
CTimer(IJob* job, double timeout);
|
CTimer(IJob* job, double startTime, double resetTime);
|
||||||
~CTimer();
|
~CTimer();
|
||||||
|
|
||||||
// manipulators
|
// manipulators
|
||||||
|
@ -242,6 +250,7 @@ private:
|
||||||
IJob* m_job;
|
IJob* m_job;
|
||||||
double m_timeout;
|
double m_timeout;
|
||||||
double m_time;
|
double m_time;
|
||||||
|
double m_startTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -278,6 +287,7 @@ private:
|
||||||
CTimerPriorityQueue m_timers;
|
CTimerPriorityQueue m_timers;
|
||||||
CStopwatch m_time;
|
CStopwatch m_time;
|
||||||
CMutex m_timersMutex;
|
CMutex m_timersMutex;
|
||||||
|
CTimer* m_oneShotTimer;
|
||||||
|
|
||||||
// pointer to (singleton) screen. this is only needed by
|
// pointer to (singleton) screen. this is only needed by
|
||||||
// ioErrorHandler().
|
// ioErrorHandler().
|
||||||
|
|
|
@ -263,6 +263,12 @@ CXWindowsSecondaryScreen::onEvent(CEvent* event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CXWindowsSecondaryScreen::onOneShotTimerExpired(UInt32)
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
SInt32
|
SInt32
|
||||||
CXWindowsSecondaryScreen::getJumpZoneSize() const
|
CXWindowsSecondaryScreen::getJumpZoneSize() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -51,6 +51,7 @@ public:
|
||||||
virtual void onScreensaver(bool activated);
|
virtual void onScreensaver(bool activated);
|
||||||
virtual bool onPreDispatch(const CEvent* event);
|
virtual bool onPreDispatch(const CEvent* event);
|
||||||
virtual bool onEvent(CEvent* event);
|
virtual bool onEvent(CEvent* event);
|
||||||
|
virtual void onOneShotTimerExpired(UInt32 id);
|
||||||
virtual SInt32 getJumpZoneSize() const;
|
virtual SInt32 getJumpZoneSize() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -624,6 +624,9 @@ CConfig::getOptionName(OptionID id)
|
||||||
if (id == kOptionHeartbeat) {
|
if (id == kOptionHeartbeat) {
|
||||||
return "heartbeat";
|
return "heartbeat";
|
||||||
}
|
}
|
||||||
|
if (id == kOptionScreenSwitchDelay) {
|
||||||
|
return "switchDelay";
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -659,7 +662,8 @@ CConfig::getOptionValue(OptionID id, OptionValue value)
|
||||||
return "none";
|
return "none";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (id == kOptionHeartbeat) {
|
if (id == kOptionHeartbeat ||
|
||||||
|
id == kOptionScreenSwitchDelay) {
|
||||||
return CStringUtil::print("%d", value);
|
return CStringUtil::print("%d", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -767,6 +771,9 @@ CConfig::readSectionOptions(std::istream& s)
|
||||||
else if (name == "heartbeat") {
|
else if (name == "heartbeat") {
|
||||||
addOption("", kOptionHeartbeat, parseInt(value));
|
addOption("", kOptionHeartbeat, parseInt(value));
|
||||||
}
|
}
|
||||||
|
else if (name == "switchDelay") {
|
||||||
|
addOption("", kOptionScreenSwitchDelay, parseInt(value));
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
throw XConfigRead("unknown argument");
|
throw XConfigRead("unknown argument");
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,12 @@ CPrimaryClient::reconfigure(UInt32 activeSides)
|
||||||
m_screen->reconfigure(activeSides);
|
m_screen->reconfigure(activeSides);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UInt32
|
||||||
|
CPrimaryClient::addOneShotTimer(double timeout)
|
||||||
|
{
|
||||||
|
return m_screen->addOneShotTimer(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CPrimaryClient::getClipboard(ClipboardID id, CString& data) const
|
CPrimaryClient::getClipboard(ClipboardID id, CString& data) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -59,6 +59,13 @@ public:
|
||||||
*/
|
*/
|
||||||
void reconfigure(UInt32 activeSides);
|
void reconfigure(UInt32 activeSides);
|
||||||
|
|
||||||
|
//! Install a one-shot timer
|
||||||
|
/*!
|
||||||
|
Installs a one-shot timer for \c timeout seconds and returns the
|
||||||
|
id of the timer (which will be passed to \c onTimerExpired()).
|
||||||
|
*/
|
||||||
|
UInt32 addOneShotTimer(double timeout);
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
//! @name accessors
|
//! @name accessors
|
||||||
//@{
|
//@{
|
||||||
|
|
|
@ -59,7 +59,9 @@ CServer::CServer(const CString& serverName) :
|
||||||
m_seqNum(0),
|
m_seqNum(0),
|
||||||
m_activeSaver(NULL),
|
m_activeSaver(NULL),
|
||||||
m_httpServer(NULL),
|
m_httpServer(NULL),
|
||||||
m_httpAvailable(&m_mutex, s_httpMaxSimultaneousRequests)
|
m_httpAvailable(&m_mutex, s_httpMaxSimultaneousRequests),
|
||||||
|
m_switchWaitDelay(0.0),
|
||||||
|
m_switchWaitScreen(NULL)
|
||||||
{
|
{
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
@ -220,13 +222,18 @@ CServer::setConfig(const CConfig& config)
|
||||||
// process global options
|
// process global options
|
||||||
const CConfig::CScreenOptions* options = m_config.getOptions("");
|
const CConfig::CScreenOptions* options = m_config.getOptions("");
|
||||||
if (options != NULL && options->size() > 0) {
|
if (options != NULL && options->size() > 0) {
|
||||||
/*
|
|
||||||
for (CConfig::CScreenOptions::const_iterator index = options->begin();
|
for (CConfig::CScreenOptions::const_iterator index = options->begin();
|
||||||
index != options->end(); ++index) {
|
index != options->end(); ++index) {
|
||||||
const OptionID id = index->first;
|
const OptionID id = index->first;
|
||||||
const OptionValue value = index->second;
|
const OptionValue value = index->second;
|
||||||
|
if (id == kOptionScreenSwitchDelay) {
|
||||||
|
m_switchWaitDelay = 1.0e-3 * static_cast<double>(value);
|
||||||
|
if (m_switchWaitDelay < 0.0) {
|
||||||
|
m_switchWaitDelay = 0.0;
|
||||||
|
}
|
||||||
|
clearSwitchWait();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// tell primary screen about reconfiguration
|
// tell primary screen about reconfiguration
|
||||||
|
@ -496,6 +503,36 @@ CServer::onScreensaver(bool activated)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CServer::onOneShotTimerExpired(UInt32 id)
|
||||||
|
{
|
||||||
|
CLock lock(&m_mutex);
|
||||||
|
|
||||||
|
// ignore old timer or if there's no jump screen anymore
|
||||||
|
if (m_switchWaitScreen == NULL || id != m_switchWaitTimer) {
|
||||||
|
clearSwitchWait();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore if mouse is locked to screen
|
||||||
|
if (isLockedToScreenNoLock()) {
|
||||||
|
clearSwitchWait();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// switch screen
|
||||||
|
switchScreen(m_switchWaitScreen, m_switchWaitX, m_switchWaitY, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CServer::clearSwitchWait()
|
||||||
|
{
|
||||||
|
if (m_switchWaitScreen != NULL) {
|
||||||
|
LOG((CLOG_DEBUG1 "cancel switch wait"));
|
||||||
|
m_switchWaitScreen = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CServer::onKeyDown(KeyID id, KeyModifierMask mask)
|
CServer::onKeyDown(KeyID id, KeyModifierMask mask)
|
||||||
{
|
{
|
||||||
|
@ -582,11 +619,6 @@ CServer::onMouseMovePrimaryNoLock(SInt32 x, SInt32 y)
|
||||||
assert(m_primaryClient != NULL);
|
assert(m_primaryClient != NULL);
|
||||||
assert(m_active == m_primaryClient);
|
assert(m_active == m_primaryClient);
|
||||||
|
|
||||||
// ignore if mouse is locked to screen
|
|
||||||
if (isLockedToScreenNoLock()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get screen shape
|
// get screen shape
|
||||||
SInt32 ax, ay, aw, ah;
|
SInt32 ax, ay, aw, ah;
|
||||||
m_active->getShape(ax, ay, aw, ah);
|
m_active->getShape(ax, ay, aw, ah);
|
||||||
|
@ -616,6 +648,7 @@ CServer::onMouseMovePrimaryNoLock(SInt32 x, SInt32 y)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// still on local screen
|
// still on local screen
|
||||||
|
clearSwitchWait();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -623,6 +656,27 @@ CServer::onMouseMovePrimaryNoLock(SInt32 x, SInt32 y)
|
||||||
// then ignore the move.
|
// then ignore the move.
|
||||||
IClient* newScreen = getNeighbor(m_active, dir, x, y);
|
IClient* newScreen = getNeighbor(m_active, dir, x, y);
|
||||||
if (newScreen == NULL) {
|
if (newScreen == NULL) {
|
||||||
|
clearSwitchWait();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if waiting before a switch then prepare to switch later
|
||||||
|
if (m_switchWaitDelay > 0.0) {
|
||||||
|
if (m_switchWaitScreen == NULL || dir != m_switchWaitDir) {
|
||||||
|
m_switchWaitDir = dir;
|
||||||
|
m_switchWaitScreen = newScreen;
|
||||||
|
m_switchWaitX = x;
|
||||||
|
m_switchWaitY = y;
|
||||||
|
m_switchWaitTimer = m_primaryClient->addOneShotTimer(
|
||||||
|
m_switchWaitDelay);
|
||||||
|
LOG((CLOG_DEBUG1 "waiting to switch"));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore if mouse is locked to screen
|
||||||
|
if (isLockedToScreenNoLock()) {
|
||||||
|
LOG((CLOG_DEBUG1 "locked to screen"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -667,72 +721,110 @@ CServer::onMouseMoveSecondaryNoLock(SInt32 dx, SInt32 dy)
|
||||||
SInt32 ax, ay, aw, ah;
|
SInt32 ax, ay, aw, ah;
|
||||||
m_active->getShape(ax, ay, aw, ah);
|
m_active->getShape(ax, ay, aw, ah);
|
||||||
|
|
||||||
|
// find direction of neighbor
|
||||||
|
EDirection dir;
|
||||||
|
IClient* newScreen = NULL;
|
||||||
|
if (m_x < ax) {
|
||||||
|
dir = kLeft;
|
||||||
|
}
|
||||||
|
else if (m_x > ax + aw - 1) {
|
||||||
|
dir = kRight;
|
||||||
|
}
|
||||||
|
else if (m_y < ay) {
|
||||||
|
dir = kTop;
|
||||||
|
}
|
||||||
|
else if (m_y > ay + ah - 1) {
|
||||||
|
dir = kBottom;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
newScreen = m_active;
|
||||||
|
|
||||||
|
// keep compiler quiet about unset variable
|
||||||
|
dir = kLeft;
|
||||||
|
}
|
||||||
|
|
||||||
// switch screens if the mouse is outside the screen and not
|
// switch screens if the mouse is outside the screen and not
|
||||||
// locked to the screen
|
// locked to the screen
|
||||||
IClient* newScreen = NULL;
|
bool clamp = false;
|
||||||
if (!isLockedToScreenNoLock()) {
|
if (newScreen == NULL) {
|
||||||
// find direction of neighbor
|
// get neighbor we should switch to
|
||||||
EDirection dir;
|
newScreen = getNeighbor(m_active, dir, m_x, m_y);
|
||||||
if (m_x < ax) {
|
LOG((CLOG_DEBUG1 "leave \"%s\" on %s", m_active->getName().c_str(), CConfig::dirName(dir)));
|
||||||
dir = kLeft;
|
|
||||||
}
|
|
||||||
else if (m_x > ax + aw - 1) {
|
|
||||||
dir = kRight;
|
|
||||||
}
|
|
||||||
else if (m_y < ay) {
|
|
||||||
dir = kTop;
|
|
||||||
}
|
|
||||||
else if (m_y > ay + ah - 1) {
|
|
||||||
dir = kBottom;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
newScreen = m_active;
|
|
||||||
|
|
||||||
// keep compiler quiet about unset variable
|
|
||||||
dir = kLeft;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get neighbor if we should switch
|
|
||||||
if (newScreen == NULL) {
|
if (newScreen == NULL) {
|
||||||
LOG((CLOG_DEBUG1 "leave \"%s\" on %s", m_active->getName().c_str(), CConfig::dirName(dir)));
|
LOG((CLOG_DEBUG1 "no neighbor %s", CConfig::dirName(dir)));
|
||||||
|
clamp = true;
|
||||||
// get new position or clamp to current screen
|
}
|
||||||
newScreen = getNeighbor(m_active, dir, m_x, m_y);
|
else if (m_switchWaitDelay > 0.0) {
|
||||||
if (newScreen == NULL) {
|
// wait to switch; prepare to switch later
|
||||||
LOG((CLOG_DEBUG1 "no neighbor; clamping"));
|
if (m_switchWaitScreen == NULL || dir != m_switchWaitDir) {
|
||||||
if (m_x < ax) {
|
m_switchWaitDir = dir;
|
||||||
m_x = ax;
|
m_switchWaitScreen = newScreen;
|
||||||
}
|
m_switchWaitX = m_x;
|
||||||
else if (m_x > ax + aw - 1) {
|
m_switchWaitY = m_y;
|
||||||
m_x = ax + aw - 1;
|
m_switchWaitTimer = m_primaryClient->addOneShotTimer(
|
||||||
}
|
m_switchWaitDelay);
|
||||||
if (m_y < ay) {
|
LOG((CLOG_DEBUG1 "waiting to switch"));
|
||||||
m_y = ay;
|
|
||||||
}
|
|
||||||
else if (m_y > ay + ah - 1) {
|
|
||||||
m_y = ay + ah - 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// don't try to switch screen now
|
||||||
|
m_x = xOld + dx;
|
||||||
|
m_y = yOld + dy;
|
||||||
|
clamp = true;
|
||||||
|
}
|
||||||
|
else if (isLockedToScreenNoLock()) {
|
||||||
|
// clamp to edge when locked to screen
|
||||||
|
LOG((CLOG_DEBUG1 "locked to screen"));
|
||||||
|
clamp = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// clamp to edge when locked
|
// on same screen. if waiting and mouse is not on the border
|
||||||
|
// we're waiting on then stop waiting.
|
||||||
|
if (m_switchWaitScreen != NULL) {
|
||||||
|
bool clearWait;
|
||||||
|
SInt32 zoneSize = m_primaryClient->getJumpZoneSize();
|
||||||
|
switch (m_switchWaitDir) {
|
||||||
|
case kLeft:
|
||||||
|
clearWait = (m_x >= ax + zoneSize);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kRight:
|
||||||
|
clearWait = (m_x <= ax + aw - 1 - zoneSize);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kTop:
|
||||||
|
clearWait = (m_y >= ay + zoneSize);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kBottom:
|
||||||
|
clearWait = (m_y <= ay + ah - 1 + zoneSize);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (clearWait) {
|
||||||
|
clearSwitchWait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// clamp mouse to edge
|
||||||
|
if (clamp) {
|
||||||
if (m_x < ax) {
|
if (m_x < ax) {
|
||||||
m_x = ax;
|
m_x = ax;
|
||||||
LOG((CLOG_DEBUG1 "clamp to left of \"%s\"", m_active->getName().c_str()));
|
LOG((CLOG_DEBUG2 "clamp to left of \"%s\"", m_active->getName().c_str()));
|
||||||
}
|
}
|
||||||
else if (m_x > ax + aw - 1) {
|
else if (m_x > ax + aw - 1) {
|
||||||
m_x = ax + aw - 1;
|
m_x = ax + aw - 1;
|
||||||
LOG((CLOG_DEBUG1 "clamp to right of \"%s\"", m_active->getName().c_str()));
|
LOG((CLOG_DEBUG2 "clamp to right of \"%s\"", m_active->getName().c_str()));
|
||||||
}
|
}
|
||||||
if (m_y < ay) {
|
if (m_y < ay) {
|
||||||
m_y = ay;
|
m_y = ay;
|
||||||
LOG((CLOG_DEBUG1 "clamp to top of \"%s\"", m_active->getName().c_str()));
|
LOG((CLOG_DEBUG2 "clamp to top of \"%s\"", m_active->getName().c_str()));
|
||||||
}
|
}
|
||||||
else if (m_y > ay + ah - 1) {
|
else if (m_y > ay + ah - 1) {
|
||||||
m_y = ay + ah - 1;
|
m_y = ay + ah - 1;
|
||||||
LOG((CLOG_DEBUG1 "clamp to bottom of \"%s\"", m_active->getName().c_str()));
|
LOG((CLOG_DEBUG2 "clamp to bottom of \"%s\"", m_active->getName().c_str()));
|
||||||
}
|
}
|
||||||
|
newScreen = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// warp cursor if on same screen
|
// warp cursor if on same screen
|
||||||
|
@ -801,6 +893,9 @@ CServer::switchScreen(IClient* dst, SInt32 x, SInt32 y, bool forScreensaver)
|
||||||
|
|
||||||
LOG((CLOG_INFO "switch from \"%s\" to \"%s\" at %d,%d", m_active->getName().c_str(), dst->getName().c_str(), x, y));
|
LOG((CLOG_INFO "switch from \"%s\" to \"%s\" at %d,%d", m_active->getName().c_str(), dst->getName().c_str(), x, y));
|
||||||
|
|
||||||
|
// stop waiting to switch
|
||||||
|
clearSwitchWait();
|
||||||
|
|
||||||
// record new position
|
// record new position
|
||||||
m_x = x;
|
m_x = x;
|
||||||
m_y = y;
|
m_y = y;
|
||||||
|
@ -1099,6 +1194,11 @@ CServer::closeClients(const CConfig& config)
|
||||||
// close that client
|
// close that client
|
||||||
assert(index2->second != m_primaryClient);
|
assert(index2->second != m_primaryClient);
|
||||||
index2->second->close();
|
index2->second->close();
|
||||||
|
|
||||||
|
// don't switch to it if we planned to
|
||||||
|
if (index2->second == m_switchWaitScreen) {
|
||||||
|
clearSwitchWait();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
++index;
|
++index;
|
||||||
|
@ -1789,6 +1889,9 @@ CServer::removeConnection(const CString& name)
|
||||||
// record new position (center of primary screen)
|
// record new position (center of primary screen)
|
||||||
m_primaryClient->getCursorCenter(m_x, m_y);
|
m_primaryClient->getCursorCenter(m_x, m_y);
|
||||||
|
|
||||||
|
// stop waiting to switch if we were
|
||||||
|
clearSwitchWait();
|
||||||
|
|
||||||
// don't notify active screen since it probably already disconnected
|
// 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));
|
LOG((CLOG_INFO "jump from \"%s\" to \"%s\" at %d,%d", active->getName().c_str(), m_primaryClient->getName().c_str(), m_x, m_y));
|
||||||
|
|
||||||
|
|
|
@ -141,6 +141,7 @@ public:
|
||||||
|
|
||||||
// IPrimaryScreenReceiver overrides
|
// IPrimaryScreenReceiver overrides
|
||||||
virtual void onScreensaver(bool activated);
|
virtual void onScreensaver(bool activated);
|
||||||
|
virtual void onOneShotTimerExpired(UInt32 id);
|
||||||
virtual void onKeyDown(KeyID, KeyModifierMask);
|
virtual void onKeyDown(KeyID, KeyModifierMask);
|
||||||
virtual void onKeyUp(KeyID, KeyModifierMask);
|
virtual void onKeyUp(KeyID, KeyModifierMask);
|
||||||
virtual void onKeyRepeat(KeyID, KeyModifierMask, SInt32 count);
|
virtual void onKeyRepeat(KeyID, KeyModifierMask, SInt32 count);
|
||||||
|
@ -197,6 +198,9 @@ private:
|
||||||
IClient* getNeighbor(IClient*, EDirection,
|
IClient* getNeighbor(IClient*, EDirection,
|
||||||
SInt32& x, SInt32& y) const;
|
SInt32& x, SInt32& y) const;
|
||||||
|
|
||||||
|
// reset switch wait state
|
||||||
|
void clearSwitchWait();
|
||||||
|
|
||||||
// send screen options to \c client
|
// send screen options to \c client
|
||||||
void sendOptions(IClient* client) const;
|
void sendOptions(IClient* client) const;
|
||||||
|
|
||||||
|
@ -320,6 +324,12 @@ private:
|
||||||
CHTTPServer* m_httpServer;
|
CHTTPServer* m_httpServer;
|
||||||
CCondVar<SInt32> m_httpAvailable;
|
CCondVar<SInt32> m_httpAvailable;
|
||||||
static const SInt32 s_httpMaxSimultaneousRequests;
|
static const SInt32 s_httpMaxSimultaneousRequests;
|
||||||
|
|
||||||
|
double m_switchWaitDelay;
|
||||||
|
EDirection m_switchWaitDir;
|
||||||
|
UInt32 m_switchWaitTimer;
|
||||||
|
IClient* m_switchWaitScreen;
|
||||||
|
SInt32 m_switchWaitX, m_switchWaitY;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -129,6 +129,13 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void setOptions(const COptionsList& options) = 0;
|
virtual void setOptions(const COptionsList& options) = 0;
|
||||||
|
|
||||||
|
//! Install a one-shot timer
|
||||||
|
/*!
|
||||||
|
Installs a one-shot timer for \c timeout seconds and returns the
|
||||||
|
id of the timer.
|
||||||
|
*/
|
||||||
|
virtual UInt32 addOneShotTimer(double timeout) = 0;
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
//! @name accessors
|
//! @name accessors
|
||||||
//@{
|
//@{
|
||||||
|
|
|
@ -34,6 +34,12 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void onScreensaver(bool activated) = 0;
|
virtual void onScreensaver(bool activated) = 0;
|
||||||
|
|
||||||
|
//! Notify of one-shot timer expiration
|
||||||
|
/*!
|
||||||
|
Called when a one-shot timer expires.
|
||||||
|
*/
|
||||||
|
virtual void onOneShotTimerExpired(UInt32 id) = 0;
|
||||||
|
|
||||||
// call to notify of events. onMouseMovePrimary() returns
|
// call to notify of events. onMouseMovePrimary() returns
|
||||||
// true iff the mouse enters a jump zone and jumps.
|
// true iff the mouse enters a jump zone and jumps.
|
||||||
//! Notify of key press
|
//! Notify of key press
|
||||||
|
|
|
@ -57,6 +57,12 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual bool onEvent(CEvent* event) = 0;
|
virtual bool onEvent(CEvent* event) = 0;
|
||||||
|
|
||||||
|
//! Notify of one-shot timer expiration
|
||||||
|
/*!
|
||||||
|
Called when a one-shot timer expires.
|
||||||
|
*/
|
||||||
|
virtual void onOneShotTimerExpired(UInt32 id) = 0;
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
//! @name accessors
|
//! @name accessors
|
||||||
//@{
|
//@{
|
||||||
|
|
|
@ -51,6 +51,7 @@ static const OptionID kOptionModifierMapForAlt = OPTION_CODE("MMFA");
|
||||||
static const OptionID kOptionModifierMapForMeta = OPTION_CODE("MMFM");
|
static const OptionID kOptionModifierMapForMeta = OPTION_CODE("MMFM");
|
||||||
static const OptionID kOptionModifierMapForSuper = OPTION_CODE("MMFR");
|
static const OptionID kOptionModifierMapForSuper = OPTION_CODE("MMFR");
|
||||||
static const OptionID kOptionHeartbeat = OPTION_CODE("HART");
|
static const OptionID kOptionHeartbeat = OPTION_CODE("HART");
|
||||||
|
static const OptionID kOptionScreenSwitchDelay = OPTION_CODE("SSWT");
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
#undef OPTION_CODE
|
#undef OPTION_CODE
|
||||||
|
|
Loading…
Reference in New Issue