Added support for a user option to require hitting the edge of a
screen twice within a specified amount of time in order to switch screens. This can help prevent unintended switching.
This commit is contained in:
parent
7bbd33d787
commit
f411df65fb
|
@ -79,7 +79,7 @@ CConfig::renameScreen(const CString& oldName,
|
|||
|
||||
// update connections
|
||||
for (index = m_map.begin(); index != m_map.end(); ++index) {
|
||||
for (UInt32 i = 0; i <= kLastDirection - kFirstDirection; ++i) {
|
||||
for (UInt32 i = 0; i < kNumDirections; ++i) {
|
||||
if (CStringUtil::CaselessCmp::equal(getCanonicalName(
|
||||
index->second.m_neighbor[i]), oldCanonical)) {
|
||||
index->second.m_neighbor[i] = newName;
|
||||
|
@ -117,7 +117,7 @@ CConfig::removeScreen(const CString& name)
|
|||
// disconnect
|
||||
for (index = m_map.begin(); index != m_map.end(); ++index) {
|
||||
CCell& cell = index->second;
|
||||
for (UInt32 i = 0; i <= kLastDirection - kFirstDirection; ++i) {
|
||||
for (UInt32 i = 0; i < kNumDirections; ++i) {
|
||||
if (getCanonicalName(cell.m_neighbor[i]) == canonical) {
|
||||
cell.m_neighbor[i].erase();
|
||||
}
|
||||
|
@ -200,6 +200,8 @@ bool
|
|||
CConfig::connect(const CString& srcName,
|
||||
EDirection srcSide, const CString& dstName)
|
||||
{
|
||||
assert(srcSide >= kFirstDirection && srcSide <= kLastDirection);
|
||||
|
||||
// find source cell
|
||||
CCellMap::iterator index = m_map.find(getCanonicalName(srcName));
|
||||
if (index == m_map.end()) {
|
||||
|
@ -217,6 +219,8 @@ CConfig::connect(const CString& srcName,
|
|||
bool
|
||||
CConfig::disconnect(const CString& srcName, EDirection srcSide)
|
||||
{
|
||||
assert(srcSide >= kFirstDirection && srcSide <= kLastDirection);
|
||||
|
||||
// find source cell
|
||||
CCellMap::iterator index = m_map.find(srcName);
|
||||
if (index == m_map.end()) {
|
||||
|
@ -406,6 +410,8 @@ CConfig::getCanonicalName(const CString& name) const
|
|||
CString
|
||||
CConfig::getNeighbor(const CString& srcName, EDirection srcSide) const
|
||||
{
|
||||
assert(srcSide >= kFirstDirection && srcSide <= kLastDirection);
|
||||
|
||||
// find source cell
|
||||
CCellMap::const_iterator index = m_map.find(getCanonicalName(srcName));
|
||||
if (index == m_map.end()) {
|
||||
|
@ -485,7 +491,7 @@ CConfig::operator==(const CConfig& x) const
|
|||
}
|
||||
|
||||
// compare neighbors
|
||||
for (UInt32 i = 0; i <= kLastDirection - kFirstDirection; ++i) {
|
||||
for (UInt32 i = 0; i < kNumDirections; ++i) {
|
||||
if (!CStringUtil::CaselessCmp::equal(index1->second.m_neighbor[i],
|
||||
index2->second.m_neighbor[i])) {
|
||||
return false;
|
||||
|
@ -516,6 +522,9 @@ const char*
|
|||
CConfig::dirName(EDirection dir)
|
||||
{
|
||||
static const char* s_name[] = { "left", "right", "top", "bottom" };
|
||||
|
||||
assert(dir >= kFirstDirection && dir <= kLastDirection);
|
||||
|
||||
return s_name[dir - kFirstDirection];
|
||||
}
|
||||
|
||||
|
@ -627,6 +636,9 @@ CConfig::getOptionName(OptionID id)
|
|||
if (id == kOptionScreenSwitchDelay) {
|
||||
return "switchDelay";
|
||||
}
|
||||
if (id == kOptionScreenSwitchTwoTap) {
|
||||
return "switchDoubleTap";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -663,7 +675,8 @@ CConfig::getOptionValue(OptionID id, OptionValue value)
|
|||
}
|
||||
}
|
||||
if (id == kOptionHeartbeat ||
|
||||
id == kOptionScreenSwitchDelay) {
|
||||
id == kOptionScreenSwitchDelay ||
|
||||
id == kOptionScreenSwitchTwoTap) {
|
||||
return CStringUtil::print("%d", value);
|
||||
}
|
||||
|
||||
|
@ -774,6 +787,9 @@ CConfig::readSectionOptions(std::istream& s)
|
|||
else if (name == "switchDelay") {
|
||||
addOption("", kOptionScreenSwitchDelay, parseInt(value));
|
||||
}
|
||||
else if (name == "switchDoubleTap") {
|
||||
addOption("", kOptionScreenSwitchTwoTap, parseInt(value));
|
||||
}
|
||||
else {
|
||||
throw XConfigRead("unknown argument");
|
||||
}
|
||||
|
|
|
@ -60,8 +60,13 @@ CServer::CServer(const CString& serverName) :
|
|||
m_activeSaver(NULL),
|
||||
m_httpServer(NULL),
|
||||
m_httpAvailable(&m_mutex, s_httpMaxSimultaneousRequests),
|
||||
m_switchDir(kNoDirection),
|
||||
m_switchScreen(NULL),
|
||||
m_switchWaitDelay(0.0),
|
||||
m_switchWaitScreen(NULL)
|
||||
m_switchWaitEngaged(false),
|
||||
m_switchTwoTapDelay(0.0),
|
||||
m_switchTwoTapEngaged(false),
|
||||
m_switchTwoTapArmed(false)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
@ -231,7 +236,14 @@ CServer::setConfig(const CConfig& config)
|
|||
if (m_switchWaitDelay < 0.0) {
|
||||
m_switchWaitDelay = 0.0;
|
||||
}
|
||||
clearSwitchWait();
|
||||
m_switchWaitEngaged = false;
|
||||
}
|
||||
else if (id == kOptionScreenSwitchTwoTap) {
|
||||
m_switchTwoTapDelay = 1.0e-3 * static_cast<double>(value);
|
||||
if (m_switchTwoTapDelay < 0.0) {
|
||||
m_switchTwoTapDelay = 0.0;
|
||||
}
|
||||
m_switchTwoTapEngaged = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -508,29 +520,20 @@ 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();
|
||||
// ignore if it's an old timer or if switch wait isn't engaged anymore
|
||||
if (!m_switchWaitEngaged || id != m_switchWaitTimer) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore if mouse is locked to screen
|
||||
if (isLockedToScreenNoLock()) {
|
||||
clearSwitchWait();
|
||||
LOG((CLOG_DEBUG1 "locked to screen"));
|
||||
clearSwitchState();
|
||||
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;
|
||||
}
|
||||
switchScreen(m_switchScreen, m_switchWaitX, m_switchWaitY, false);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -629,61 +632,38 @@ CServer::onMouseMovePrimaryNoLock(SInt32 x, SInt32 y)
|
|||
if (x < ax + zoneSize) {
|
||||
x -= zoneSize;
|
||||
dir = kLeft;
|
||||
LOG((CLOG_DEBUG1 "switch to left"));
|
||||
}
|
||||
else if (x >= ax + aw - zoneSize) {
|
||||
x += zoneSize;
|
||||
dir = kRight;
|
||||
LOG((CLOG_DEBUG1 "switch to right"));
|
||||
}
|
||||
else if (y < ay + zoneSize) {
|
||||
y -= zoneSize;
|
||||
dir = kTop;
|
||||
LOG((CLOG_DEBUG1 "switch to top"));
|
||||
}
|
||||
else if (y >= ay + ah - zoneSize) {
|
||||
y += zoneSize;
|
||||
dir = kBottom;
|
||||
LOG((CLOG_DEBUG1 "switch to bottom"));
|
||||
}
|
||||
else {
|
||||
// still on local screen
|
||||
clearSwitchWait();
|
||||
onNoSwitch();
|
||||
return false;
|
||||
}
|
||||
|
||||
// get jump destination and, if no screen in jump direction,
|
||||
// then ignore the move.
|
||||
// get jump destination
|
||||
IClient* newScreen = getNeighbor(m_active, dir, x, y);
|
||||
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;
|
||||
}
|
||||
|
||||
// should we switch or not?
|
||||
if (isSwitchOkay(newScreen, dir, x, y)) {
|
||||
// switch screen
|
||||
switchScreen(newScreen, x, y, false);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CServer::onMouseMoveSecondary(SInt32 dx, SInt32 dy)
|
||||
|
@ -721,9 +701,10 @@ CServer::onMouseMoveSecondaryNoLock(SInt32 dx, SInt32 dy)
|
|||
SInt32 ax, ay, aw, ah;
|
||||
m_active->getShape(ax, ay, aw, ah);
|
||||
|
||||
// find direction of neighbor
|
||||
// find direction of neighbor and get the neighbor
|
||||
IClient* newScreen;
|
||||
do {
|
||||
EDirection dir;
|
||||
IClient* newScreen = NULL;
|
||||
if (m_x < ax) {
|
||||
dir = kLeft;
|
||||
}
|
||||
|
@ -737,53 +718,16 @@ CServer::onMouseMoveSecondaryNoLock(SInt32 dx, SInt32 dy)
|
|||
dir = kBottom;
|
||||
}
|
||||
else {
|
||||
// we haven't left the screen
|
||||
newScreen = m_active;
|
||||
|
||||
// keep compiler quiet about unset variable
|
||||
dir = kLeft;
|
||||
}
|
||||
|
||||
// switch screens if the mouse is outside the screen and not
|
||||
// locked to the screen
|
||||
bool clamp = false;
|
||||
if (newScreen == NULL) {
|
||||
// get neighbor we should switch to
|
||||
newScreen = getNeighbor(m_active, dir, m_x, m_y);
|
||||
LOG((CLOG_DEBUG1 "leave \"%s\" on %s", m_active->getName().c_str(), CConfig::dirName(dir)));
|
||||
if (newScreen == NULL) {
|
||||
LOG((CLOG_DEBUG1 "no neighbor %s", CConfig::dirName(dir)));
|
||||
clamp = true;
|
||||
}
|
||||
else if (m_switchWaitDelay > 0.0) {
|
||||
// wait to switch; prepare to switch later
|
||||
if (m_switchWaitScreen == NULL || dir != m_switchWaitDir) {
|
||||
m_switchWaitDir = dir;
|
||||
m_switchWaitScreen = newScreen;
|
||||
m_switchWaitX = m_x;
|
||||
m_switchWaitY = m_y;
|
||||
m_switchWaitTimer = m_primaryClient->addOneShotTimer(
|
||||
m_switchWaitDelay);
|
||||
LOG((CLOG_DEBUG1 "waiting to switch"));
|
||||
}
|
||||
|
||||
// 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 {
|
||||
// on same screen. if waiting and mouse is not on the border
|
||||
// we're waiting on then stop waiting.
|
||||
if (m_switchWaitScreen != NULL) {
|
||||
// if waiting and mouse is not on the border we're waiting
|
||||
// on then stop waiting. also if it's not on the border
|
||||
// then arm the double tap.
|
||||
if (m_switchScreen != NULL) {
|
||||
bool clearWait;
|
||||
SInt32 zoneSize = m_primaryClient->getJumpZoneSize();
|
||||
switch (m_switchWaitDir) {
|
||||
switch (m_switchDir) {
|
||||
case kLeft:
|
||||
clearWait = (m_x >= ax + zoneSize);
|
||||
break;
|
||||
|
@ -801,13 +745,31 @@ CServer::onMouseMoveSecondaryNoLock(SInt32 dx, SInt32 dy)
|
|||
break;
|
||||
}
|
||||
if (clearWait) {
|
||||
clearSwitchWait();
|
||||
}
|
||||
onNoSwitch();
|
||||
}
|
||||
}
|
||||
|
||||
// clamp mouse to edge
|
||||
if (clamp) {
|
||||
// skip rest of block
|
||||
break;
|
||||
}
|
||||
|
||||
// try to switch screen. get the neighbor.
|
||||
newScreen = getNeighbor(m_active, dir, m_x, m_y);
|
||||
|
||||
// see if we should switch
|
||||
if (!isSwitchOkay(newScreen, dir, m_x, m_y)) {
|
||||
newScreen = m_active;
|
||||
}
|
||||
} while (false);
|
||||
|
||||
if (newScreen != m_active) {
|
||||
// switch screens
|
||||
switchScreen(newScreen, m_x, m_y, false);
|
||||
}
|
||||
else {
|
||||
// same screen. clamp mouse to edge.
|
||||
m_x = xOld + dx;
|
||||
m_y = yOld + dy;
|
||||
if (m_x < ax) {
|
||||
m_x = ax;
|
||||
LOG((CLOG_DEBUG2 "clamp to left of \"%s\"", m_active->getName().c_str()));
|
||||
|
@ -824,22 +786,13 @@ CServer::onMouseMoveSecondaryNoLock(SInt32 dx, SInt32 dy)
|
|||
m_y = ay + ah - 1;
|
||||
LOG((CLOG_DEBUG2 "clamp to bottom of \"%s\"", m_active->getName().c_str()));
|
||||
}
|
||||
newScreen = NULL;
|
||||
}
|
||||
|
||||
// warp cursor if on same screen
|
||||
if (newScreen == NULL || newScreen == m_active) {
|
||||
// do nothing if mouse didn't move
|
||||
// warp cursor if it moved.
|
||||
if (m_x != xOld || m_y != yOld) {
|
||||
LOG((CLOG_DEBUG2 "move on %s to %d,%d", m_active->getName().c_str(), m_x, m_y));
|
||||
m_active->mouseMove(m_x, m_y);
|
||||
}
|
||||
}
|
||||
|
||||
// otherwise screen screens
|
||||
else {
|
||||
switchScreen(newScreen, m_x, m_y, false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -894,7 +847,7 @@ 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));
|
||||
|
||||
// stop waiting to switch
|
||||
clearSwitchWait();
|
||||
clearSwitchState();
|
||||
|
||||
// record new position
|
||||
m_x = x;
|
||||
|
@ -1166,6 +1119,120 @@ CServer::getNeighbor(IClient* src,
|
|||
return dst;
|
||||
}
|
||||
|
||||
bool
|
||||
CServer::isSwitchOkay(IClient* newScreen, EDirection dir, SInt32 x, SInt32 y)
|
||||
{
|
||||
LOG((CLOG_DEBUG1 "try to leave \"%s\" on %s", m_active->getName().c_str(), CConfig::dirName(dir)));
|
||||
|
||||
// is there a neighbor?
|
||||
if (newScreen == NULL) {
|
||||
// there's no neighbor. we don't want to switch and we don't
|
||||
// want to try to switch later.
|
||||
LOG((CLOG_DEBUG1 "no neighbor %s", CConfig::dirName(dir)));
|
||||
clearSwitchState();
|
||||
return false;
|
||||
}
|
||||
|
||||
// should we switch or not?
|
||||
bool preventSwitch = false;
|
||||
bool allowSwitch = false;
|
||||
|
||||
// note if the switch direction has changed. save the new
|
||||
// direction and screen if so.
|
||||
bool isNewDirection = (dir != m_switchDir);
|
||||
if (isNewDirection || m_switchScreen == NULL) {
|
||||
m_switchDir = dir;
|
||||
m_switchScreen = newScreen;
|
||||
}
|
||||
|
||||
// is this a double tap and do we care?
|
||||
if (!allowSwitch && m_switchTwoTapDelay > 0.0) {
|
||||
if (isNewDirection || !m_switchTwoTapEngaged) {
|
||||
// tapping a different or new edge. prepare for second tap.
|
||||
preventSwitch = true;
|
||||
m_switchTwoTapEngaged = true;
|
||||
m_switchTwoTapArmed = false;
|
||||
m_switchTwoTapTimer.reset();
|
||||
LOG((CLOG_DEBUG1 "waiting for second tap"));
|
||||
}
|
||||
else {
|
||||
// second tap if we were armed. if soon enough then switch.
|
||||
if (m_switchTwoTapArmed &&
|
||||
m_switchTwoTapTimer.getTime() <= m_switchTwoTapDelay) {
|
||||
allowSwitch = true;
|
||||
}
|
||||
else {
|
||||
// not fast enough. reset the clock.
|
||||
preventSwitch = true;
|
||||
m_switchTwoTapEngaged = true;
|
||||
m_switchTwoTapArmed = false;
|
||||
m_switchTwoTapTimer.reset();
|
||||
LOG((CLOG_DEBUG1 "waiting for second tap"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if waiting before a switch then prepare to switch later
|
||||
if (!allowSwitch && m_switchWaitDelay > 0.0) {
|
||||
if (isNewDirection) {
|
||||
m_switchWaitEngaged = true;
|
||||
m_switchWaitX = x;
|
||||
m_switchWaitY = y;
|
||||
m_switchWaitTimer = m_primaryClient->addOneShotTimer(
|
||||
m_switchWaitDelay);
|
||||
LOG((CLOG_DEBUG1 "waiting to switch"));
|
||||
}
|
||||
preventSwitch = true;
|
||||
}
|
||||
|
||||
// ignore if mouse is locked to screen
|
||||
if (!preventSwitch && isLockedToScreenNoLock()) {
|
||||
LOG((CLOG_DEBUG1 "locked to screen"));
|
||||
preventSwitch = true;
|
||||
|
||||
// don't try to switch later. it's possible that we might
|
||||
// not be locked to the screen when the wait delay expires
|
||||
// and could switch then but we'll base the decision on
|
||||
// when the user first attempts the switch. this also
|
||||
// ensures that all switch tests are using the same
|
||||
clearSwitchState();
|
||||
}
|
||||
|
||||
return !preventSwitch;
|
||||
}
|
||||
|
||||
void
|
||||
CServer::onNoSwitch()
|
||||
{
|
||||
if (m_switchTwoTapEngaged) {
|
||||
if (m_switchTwoTapTimer.getTime() > m_switchTwoTapDelay) {
|
||||
// second tap took too long. disengage.
|
||||
m_switchTwoTapEngaged = false;
|
||||
m_switchTwoTapArmed = false;
|
||||
}
|
||||
else {
|
||||
// we've moved away from the edge and there's still
|
||||
// time to get back for a double tap.
|
||||
m_switchTwoTapArmed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// once the mouse moves away from the edge we no longer want to
|
||||
// switch after a delay.
|
||||
m_switchWaitEngaged = false;
|
||||
}
|
||||
|
||||
void
|
||||
CServer::clearSwitchState()
|
||||
{
|
||||
if (m_switchScreen != NULL) {
|
||||
m_switchDir = kNoDirection;
|
||||
m_switchScreen = NULL;
|
||||
m_switchWaitEngaged = false;
|
||||
m_switchTwoTapEngaged = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CServer::closeClients(const CConfig& config)
|
||||
{
|
||||
|
@ -1196,8 +1263,8 @@ CServer::closeClients(const CConfig& config)
|
|||
index2->second->close();
|
||||
|
||||
// don't switch to it if we planned to
|
||||
if (index2->second == m_switchWaitScreen) {
|
||||
clearSwitchWait();
|
||||
if (index2->second == m_switchScreen) {
|
||||
clearSwitchState();
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1890,7 +1957,9 @@ CServer::removeConnection(const CString& name)
|
|||
m_primaryClient->getCursorCenter(m_x, m_y);
|
||||
|
||||
// stop waiting to switch if we were
|
||||
clearSwitchWait();
|
||||
if (active == m_switchScreen) {
|
||||
clearSwitchState();
|
||||
}
|
||||
|
||||
// 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));
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "CCondVar.h"
|
||||
#include "CMutex.h"
|
||||
#include "CThread.h"
|
||||
#include "CStopwatch.h"
|
||||
#include "stdlist.h"
|
||||
#include "stdmap.h"
|
||||
|
||||
|
@ -198,8 +199,18 @@ private:
|
|||
IClient* getNeighbor(IClient*, EDirection,
|
||||
SInt32& x, SInt32& y) const;
|
||||
|
||||
// test if a switch is permitted. this includes testing user
|
||||
// options like switch delay and tracking any state required to
|
||||
// implement them. returns true iff a switch is permitted.
|
||||
bool isSwitchOkay(IClient* dst, EDirection,
|
||||
SInt32 x, SInt32 y);
|
||||
|
||||
// update switch state due to a mouse move that doesn't try to
|
||||
// switch screens.
|
||||
void onNoSwitch();
|
||||
|
||||
// reset switch wait state
|
||||
void clearSwitchWait();
|
||||
void clearSwitchState();
|
||||
|
||||
// send screen options to \c client
|
||||
void sendOptions(IClient* client) const;
|
||||
|
@ -325,11 +336,22 @@ private:
|
|||
CCondVar<SInt32> m_httpAvailable;
|
||||
static const SInt32 s_httpMaxSimultaneousRequests;
|
||||
|
||||
// common state for screen switch tests. all tests are always
|
||||
// trying to reach the same screen in the same direction.
|
||||
EDirection m_switchDir;
|
||||
IClient* m_switchScreen;
|
||||
|
||||
// state for delayed screen switching
|
||||
double m_switchWaitDelay;
|
||||
EDirection m_switchWaitDir;
|
||||
UInt32 m_switchWaitTimer;
|
||||
IClient* m_switchWaitScreen;
|
||||
bool m_switchWaitEngaged;
|
||||
SInt32 m_switchWaitX, m_switchWaitY;
|
||||
|
||||
// state for double-tap screen switching
|
||||
double m_switchTwoTapDelay;
|
||||
CStopwatch m_switchTwoTapTimer;
|
||||
bool m_switchTwoTapEngaged;
|
||||
bool m_switchTwoTapArmed;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -52,6 +52,7 @@ static const OptionID kOptionModifierMapForMeta = OPTION_CODE("MMFM");
|
|||
static const OptionID kOptionModifierMapForSuper = OPTION_CODE("MMFR");
|
||||
static const OptionID kOptionHeartbeat = OPTION_CODE("HART");
|
||||
static const OptionID kOptionScreenSwitchDelay = OPTION_CODE("SSWT");
|
||||
static const OptionID kOptionScreenSwitchTwoTap = OPTION_CODE("SSTT");
|
||||
//@}
|
||||
|
||||
#undef OPTION_CODE
|
||||
|
|
|
@ -36,14 +36,17 @@ static const double kHeartBeatsUntilDeath = 3.0;
|
|||
|
||||
// direction constants
|
||||
enum EDirection {
|
||||
kNoDirection,
|
||||
kLeft,
|
||||
kRight,
|
||||
kTop,
|
||||
kBottom,
|
||||
kFirstDirection = kLeft,
|
||||
kLastDirection = kBottom
|
||||
kLastDirection = kBottom,
|
||||
kNumDirections = kLastDirection - kFirstDirection + 1
|
||||
};
|
||||
enum EDirectionMask {
|
||||
kNoDirMask = 0,
|
||||
kLeftMask = 1 << kLeft,
|
||||
kRightMask = 1 << kRight,
|
||||
kTopMask = 1 << kTop,
|
||||
|
|
Loading…
Reference in New Issue