checkpoint. now sending toggle modifier state when entering
a screen. this allows the secondary screen to set it's modifier state to match the primary screen's state. this is not strictly necessary since each keystroke should adjust the modifier state as needed to get the right result.
This commit is contained in:
parent
56877bcc7d
commit
b279c80608
|
@ -341,13 +341,14 @@ void CClient::closeSecondaryScreen()
|
||||||
void CClient::onEnter()
|
void CClient::onEnter()
|
||||||
{
|
{
|
||||||
SInt16 x, y;
|
SInt16 x, y;
|
||||||
|
UInt16 mask;
|
||||||
{
|
{
|
||||||
CLock lock(&m_mutex);
|
CLock lock(&m_mutex);
|
||||||
CProtocolUtil::readf(m_input, kMsgCEnter + 4, &x, &y, &m_seqNum);
|
CProtocolUtil::readf(m_input, kMsgCEnter + 4, &x, &y, &m_seqNum, &mask);
|
||||||
m_active = true;
|
m_active = true;
|
||||||
}
|
}
|
||||||
log((CLOG_DEBUG1 "recv enter, %d,%d %d", x, y, m_seqNum));
|
log((CLOG_DEBUG1 "recv enter, %d,%d %d %04x", x, y, m_seqNum, mask));
|
||||||
m_screen->enter(x, y);
|
m_screen->enter(x, y, static_cast<KeyModifierMask>(mask));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClient::onLeave()
|
void CClient::onLeave()
|
||||||
|
|
|
@ -109,11 +109,12 @@ void CMSWindowsSecondaryScreen::close()
|
||||||
m_client = NULL;
|
m_client = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMSWindowsSecondaryScreen::enter(SInt32 x, SInt32 y)
|
void CMSWindowsSecondaryScreen::enter(
|
||||||
|
SInt32 x, SInt32 y, KeyModifierMask mask)
|
||||||
{
|
{
|
||||||
assert(m_window != NULL);
|
assert(m_window != NULL);
|
||||||
|
|
||||||
log((CLOG_INFO "entering screen at %d,%d", x, y));
|
log((CLOG_INFO "entering screen at %d,%d mask=%04x", x, y, mask));
|
||||||
|
|
||||||
// warp to requested location
|
// warp to requested location
|
||||||
SInt32 w, h;
|
SInt32 w, h;
|
||||||
|
@ -130,6 +131,17 @@ void CMSWindowsSecondaryScreen::enter(SInt32 x, SInt32 y)
|
||||||
// update our keyboard state to reflect the local state
|
// update our keyboard state to reflect the local state
|
||||||
updateKeys();
|
updateKeys();
|
||||||
updateModifiers();
|
updateModifiers();
|
||||||
|
|
||||||
|
// toggle modifiers that don't match the desired state
|
||||||
|
if ((mask & KeyModifierCapsLock) != (m_mask & KeyModifierCapsLock)) {
|
||||||
|
toggleKey(VK_CAPITAL, KeyModifierCapsLock);
|
||||||
|
}
|
||||||
|
if ((mask & KeyModifierNumLock) != (m_mask & KeyModifierNumLock)) {
|
||||||
|
toggleKey(VK_NUMLOCK, KeyModifierNumLock);
|
||||||
|
}
|
||||||
|
if ((mask & KeyModifierScrollLock) != (m_mask & KeyModifierScrollLock)) {
|
||||||
|
toggleKey(VK_SCROLL, KeyModifierScrollLock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMSWindowsSecondaryScreen::leave()
|
void CMSWindowsSecondaryScreen::leave()
|
||||||
|
@ -1184,3 +1196,16 @@ void CMSWindowsSecondaryScreen::updateModifiers()
|
||||||
if ((m_keys[VK_SCROLL] & 0x01) != 0)
|
if ((m_keys[VK_SCROLL] & 0x01) != 0)
|
||||||
m_mask |= KeyModifierScrollLock;
|
m_mask |= KeyModifierScrollLock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CMSWindowsSecondaryScreen::toggleKey(
|
||||||
|
UINT virtualKey, KeyModifierMask mask)
|
||||||
|
{
|
||||||
|
// send key events to simulate a press and release
|
||||||
|
const UINT code = MapVirtualKey(virtualKey, 0);
|
||||||
|
keybd_event(virtualKey, code, 0, 0);
|
||||||
|
keybd_event(virtualKey, code, KEYEVENTF_KEYUP, 0);
|
||||||
|
|
||||||
|
// toggle shadow state
|
||||||
|
m_mask ^= mask;
|
||||||
|
m_keys[virtualKey] ^= 0x01;
|
||||||
|
}
|
||||||
|
|
|
@ -16,7 +16,8 @@ public:
|
||||||
virtual void stop();
|
virtual void stop();
|
||||||
virtual void open(CClient*);
|
virtual void open(CClient*);
|
||||||
virtual void close();
|
virtual void close();
|
||||||
virtual void enter(SInt32 xAbsolute, SInt32 yAbsolute);
|
virtual void enter(SInt32 xAbsolute, SInt32 yAbsolute,
|
||||||
|
KeyModifierMask mask);
|
||||||
virtual void leave();
|
virtual void leave();
|
||||||
virtual void keyDown(KeyID, KeyModifierMask);
|
virtual void keyDown(KeyID, KeyModifierMask);
|
||||||
virtual void keyRepeat(KeyID, KeyModifierMask, SInt32 count);
|
virtual void keyRepeat(KeyID, KeyModifierMask, SInt32 count);
|
||||||
|
@ -48,6 +49,7 @@ private:
|
||||||
|
|
||||||
void updateKeys();
|
void updateKeys();
|
||||||
void updateModifiers();
|
void updateModifiers();
|
||||||
|
void toggleKey(UINT virtualKey, KeyModifierMask mask);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CClient* m_client;
|
CClient* m_client;
|
||||||
|
|
|
@ -177,7 +177,8 @@ void CXWindowsSecondaryScreen::close()
|
||||||
m_client = NULL;
|
m_client = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CXWindowsSecondaryScreen::enter(SInt32 x, SInt32 y)
|
void CXWindowsSecondaryScreen::enter(
|
||||||
|
SInt32 x, SInt32 y, KeyModifierMask mask)
|
||||||
{
|
{
|
||||||
assert(m_window != None);
|
assert(m_window != None);
|
||||||
|
|
||||||
|
@ -193,6 +194,19 @@ void CXWindowsSecondaryScreen::enter(SInt32 x, SInt32 y)
|
||||||
// update our keyboard state to reflect the local state
|
// update our keyboard state to reflect the local state
|
||||||
updateKeys(display);
|
updateKeys(display);
|
||||||
updateModifiers(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);
|
||||||
|
}
|
||||||
|
XSync(display, False);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CXWindowsSecondaryScreen::leave()
|
void CXWindowsSecondaryScreen::leave()
|
||||||
|
@ -461,6 +475,7 @@ KeyModifierMask CXWindowsSecondaryScreen::mapKey(
|
||||||
const KeyCode modifierKey = modifierKeys[0];
|
const KeyCode modifierKey = modifierKeys[0];
|
||||||
keys.push_back(std::make_pair(modifierKey, True));
|
keys.push_back(std::make_pair(modifierKey, True));
|
||||||
if ((bit & m_toggleModifierMask) != 0) {
|
if ((bit & m_toggleModifierMask) != 0) {
|
||||||
|
if (bit != m_capsLockMask || !m_capsLockHalfDuplex) {
|
||||||
keys.push_back(std::make_pair(modifierKey, False));
|
keys.push_back(std::make_pair(modifierKey, False));
|
||||||
undo.push_back(std::make_pair(modifierKey, False));
|
undo.push_back(std::make_pair(modifierKey, False));
|
||||||
undo.push_back(std::make_pair(modifierKey, True));
|
undo.push_back(std::make_pair(modifierKey, True));
|
||||||
|
@ -469,6 +484,10 @@ KeyModifierMask CXWindowsSecondaryScreen::mapKey(
|
||||||
undo.push_back(std::make_pair(modifierKey, False));
|
undo.push_back(std::make_pair(modifierKey, False));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
undo.push_back(std::make_pair(modifierKey, False));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
// modifier is active but should not be. if the
|
// modifier is active but should not be. if the
|
||||||
|
@ -476,13 +495,19 @@ KeyModifierMask CXWindowsSecondaryScreen::mapKey(
|
||||||
// press/release, otherwise deactivate it with a
|
// press/release, otherwise deactivate it with a
|
||||||
// release. we must check each keycode for the
|
// release. we must check each keycode for the
|
||||||
// modifier if not a toggle.
|
// modifier if not a toggle.
|
||||||
if (bit & m_toggleModifierMask) {
|
if ((bit & m_toggleModifierMask) != 0) {
|
||||||
const KeyCode modifierKey = modifierKeys[0];
|
const KeyCode modifierKey = modifierKeys[0];
|
||||||
|
if (bit != m_capsLockMask || !m_capsLockHalfDuplex) {
|
||||||
keys.push_back(std::make_pair(modifierKey, True));
|
keys.push_back(std::make_pair(modifierKey, True));
|
||||||
keys.push_back(std::make_pair(modifierKey, False));
|
keys.push_back(std::make_pair(modifierKey, False));
|
||||||
undo.push_back(std::make_pair(modifierKey, False));
|
undo.push_back(std::make_pair(modifierKey, False));
|
||||||
undo.push_back(std::make_pair(modifierKey, True));
|
undo.push_back(std::make_pair(modifierKey, True));
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
keys.push_back(std::make_pair(modifierKey, False));
|
||||||
|
undo.push_back(std::make_pair(modifierKey, True));
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
for (unsigned int j = 0; j < m_keysPerModifier; ++j) {
|
for (unsigned int j = 0; j < m_keysPerModifier; ++j) {
|
||||||
const KeyCode key = modifierKeys[j];
|
const KeyCode key = modifierKeys[j];
|
||||||
|
@ -601,11 +626,11 @@ unsigned int CXWindowsSecondaryScreen::maskToX(
|
||||||
if (inMask & KeyModifierMeta)
|
if (inMask & KeyModifierMeta)
|
||||||
outMask |= Mod4Mask;
|
outMask |= Mod4Mask;
|
||||||
if (inMask & KeyModifierCapsLock)
|
if (inMask & KeyModifierCapsLock)
|
||||||
outMask |= LockMask;
|
outMask |= m_capsLockMask;
|
||||||
if (inMask & KeyModifierNumLock)
|
if (inMask & KeyModifierNumLock)
|
||||||
outMask |= Mod2Mask;
|
outMask |= m_numLockMask;
|
||||||
if (inMask & KeyModifierScrollLock)
|
if (inMask & KeyModifierScrollLock)
|
||||||
outMask |= Mod5Mask;
|
outMask |= m_scrollLockMask;
|
||||||
return outMask;
|
return outMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -712,6 +737,7 @@ void CXWindowsSecondaryScreen::updateModifierMap(
|
||||||
m_toggleModifierMask = 0;
|
m_toggleModifierMask = 0;
|
||||||
m_numLockMask = 0;
|
m_numLockMask = 0;
|
||||||
m_capsLockMask = 0;
|
m_capsLockMask = 0;
|
||||||
|
m_scrollLockMask = 0;
|
||||||
m_keysPerModifier = keymap->max_keypermod;
|
m_keysPerModifier = keymap->max_keypermod;
|
||||||
m_modifierToKeycode.clear();
|
m_modifierToKeycode.clear();
|
||||||
m_modifierToKeycode.resize(8 * m_keysPerModifier);
|
m_modifierToKeycode.resize(8 * m_keysPerModifier);
|
||||||
|
@ -738,17 +764,47 @@ void CXWindowsSecondaryScreen::updateModifierMap(
|
||||||
m_toggleModifierMask |= bit;
|
m_toggleModifierMask |= bit;
|
||||||
|
|
||||||
// note num/caps-lock
|
// note num/caps-lock
|
||||||
if (keysym == XK_Num_Lock)
|
if (keysym == XK_Num_Lock) {
|
||||||
m_numLockMask |= bit;
|
m_numLockMask |= bit;
|
||||||
if (keysym == XK_Caps_Lock)
|
}
|
||||||
|
else if (keysym == XK_Caps_Lock) {
|
||||||
m_capsLockMask |= bit;
|
m_capsLockMask |= bit;
|
||||||
}
|
}
|
||||||
|
else if (keysym == XK_Scroll_Lock) {
|
||||||
|
m_scrollLockMask |= bit;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XFreeModifiermap(keymap);
|
XFreeModifiermap(keymap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CXWindowsSecondaryScreen::toggleKey(
|
||||||
|
Display* display,
|
||||||
|
KeySym keysym, unsigned int mask)
|
||||||
|
{
|
||||||
|
// lookup the keycode
|
||||||
|
KeyCodeMap::const_iterator index = m_keycodeMap.find(keysym);
|
||||||
|
if (index == m_keycodeMap.end())
|
||||||
|
return;
|
||||||
|
KeyCode keycode = index->second.keycode;
|
||||||
|
|
||||||
|
// toggle the key
|
||||||
|
if (keysym == XK_Caps_Lock && m_capsLockHalfDuplex) {
|
||||||
|
// "half-duplex" toggle
|
||||||
|
XTestFakeKeyEvent(display, keycode, (m_mask & mask) == 0, CurrentTime);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// normal toggle
|
||||||
|
XTestFakeKeyEvent(display, keycode, True, CurrentTime);
|
||||||
|
XTestFakeKeyEvent(display, keycode, False, CurrentTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
// toggle shadow state
|
||||||
|
m_mask ^= mask;
|
||||||
|
}
|
||||||
|
|
||||||
bool CXWindowsSecondaryScreen::isToggleKeysym(KeySym key)
|
bool CXWindowsSecondaryScreen::isToggleKeysym(KeySym key)
|
||||||
{
|
{
|
||||||
switch (key) {
|
switch (key) {
|
||||||
|
|
|
@ -15,7 +15,8 @@ public:
|
||||||
virtual void stop();
|
virtual void stop();
|
||||||
virtual void open(CClient*);
|
virtual void open(CClient*);
|
||||||
virtual void close();
|
virtual void close();
|
||||||
virtual void enter(SInt32 xAbsolute, SInt32 yAbsolute);
|
virtual void enter(SInt32 xAbsolute, SInt32 yAbsolute,
|
||||||
|
KeyModifierMask mask);
|
||||||
virtual void leave();
|
virtual void leave();
|
||||||
virtual void keyDown(KeyID, KeyModifierMask);
|
virtual void keyDown(KeyID, KeyModifierMask);
|
||||||
virtual void keyRepeat(KeyID, KeyModifierMask, SInt32 count);
|
virtual void keyRepeat(KeyID, KeyModifierMask, SInt32 count);
|
||||||
|
@ -62,6 +63,7 @@ private:
|
||||||
void updateKeycodeMap(Display* display);
|
void updateKeycodeMap(Display* display);
|
||||||
void updateModifiers(Display* display);
|
void updateModifiers(Display* display);
|
||||||
void updateModifierMap(Display* display);
|
void updateModifierMap(Display* display);
|
||||||
|
void toggleKey(Display*, KeySym, unsigned int mask);
|
||||||
static bool isToggleKeysym(KeySym);
|
static bool isToggleKeysym(KeySym);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -88,9 +90,10 @@ private:
|
||||||
// set bits indicate modifiers that toggle (e.g. caps-lock)
|
// set bits indicate modifiers that toggle (e.g. caps-lock)
|
||||||
unsigned int m_toggleModifierMask;
|
unsigned int m_toggleModifierMask;
|
||||||
|
|
||||||
// masks that indicate which modifier bits are num-lock and caps-lock
|
// masks that indicate which modifier bits are for toggle keys
|
||||||
unsigned int m_numLockMask;
|
unsigned int m_numLockMask;
|
||||||
unsigned int m_capsLockMask;
|
unsigned int m_capsLockMask;
|
||||||
|
unsigned int m_scrollLockMask;
|
||||||
|
|
||||||
// map X modifier key indices to the key codes bound to them
|
// map X modifier key indices to the key codes bound to them
|
||||||
unsigned int m_keysPerModifier;
|
unsigned int m_keysPerModifier;
|
||||||
|
|
|
@ -252,6 +252,18 @@ void CMSWindowsPrimaryScreen::getClipboard(
|
||||||
CClipboard::copy(dst, &src);
|
CClipboard::copy(dst, &src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyModifierMask CXWindowsPrimaryScreen::getToggleMask() const
|
||||||
|
{
|
||||||
|
KeyModifierMask mask;
|
||||||
|
if ((m_keys[VK_CAPITAL] & 0x01) != 0)
|
||||||
|
mask |= KeyModifierCapsLock;
|
||||||
|
if ((m_keys[VK_NUMLOCK] & 0x01) != 0)
|
||||||
|
mask |= KeyModifierNumLock;
|
||||||
|
if ((m_keys[VK_SCROLL] & 0x01) != 0)
|
||||||
|
mask |= KeyModifierScrollLock;
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
#include "resource.h" // FIXME
|
#include "resource.h" // FIXME
|
||||||
|
|
||||||
void CMSWindowsPrimaryScreen::onOpenDisplay()
|
void CMSWindowsPrimaryScreen::onOpenDisplay()
|
||||||
|
|
|
@ -26,6 +26,7 @@ public:
|
||||||
virtual void getSize(SInt32* width, SInt32* height) const;
|
virtual void getSize(SInt32* width, SInt32* height) const;
|
||||||
virtual SInt32 getJumpZoneSize() const;
|
virtual SInt32 getJumpZoneSize() const;
|
||||||
virtual void getClipboard(ClipboardID, IClipboard*) const;
|
virtual void getClipboard(ClipboardID, IClipboard*) const;
|
||||||
|
virtual KeyModifierMask getToggleMask() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// CMSWindowsScreen overrides
|
// CMSWindowsScreen overrides
|
||||||
|
|
|
@ -537,7 +537,8 @@ void CServer::switchScreen(CScreenInfo* dst,
|
||||||
m_primary->enter(x, y);
|
m_primary->enter(x, y);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_active->m_protocol->sendEnter(x, y, m_seqNum);
|
m_active->m_protocol->sendEnter(x, y, m_seqNum,
|
||||||
|
m_primary->getToggleMask());
|
||||||
}
|
}
|
||||||
|
|
||||||
// send the clipboard data to new active screen
|
// send the clipboard data to new active screen
|
||||||
|
|
|
@ -31,7 +31,8 @@ public:
|
||||||
virtual void run() = 0;
|
virtual void run() = 0;
|
||||||
virtual void queryInfo() = 0;
|
virtual void queryInfo() = 0;
|
||||||
virtual void sendClose() = 0;
|
virtual void sendClose() = 0;
|
||||||
virtual void sendEnter(SInt32 xAbs, SInt32 yAbs, UInt32 seqNum) = 0;
|
virtual void sendEnter(SInt32 xAbs, SInt32 yAbs,
|
||||||
|
UInt32 seqNum, KeyModifierMask mask) = 0;
|
||||||
virtual void sendLeave() = 0;
|
virtual void sendLeave() = 0;
|
||||||
virtual void sendClipboard(ClipboardID, const CString&) = 0;
|
virtual void sendClipboard(ClipboardID, const CString&) = 0;
|
||||||
virtual void sendGrabClipboard(ClipboardID) = 0;
|
virtual void sendGrabClipboard(ClipboardID) = 0;
|
||||||
|
|
|
@ -91,10 +91,12 @@ void CServerProtocol1_0::sendClose()
|
||||||
}
|
}
|
||||||
|
|
||||||
void CServerProtocol1_0::sendEnter(
|
void CServerProtocol1_0::sendEnter(
|
||||||
SInt32 xAbs, SInt32 yAbs, UInt32 seqNum)
|
SInt32 xAbs, SInt32 yAbs,
|
||||||
|
UInt32 seqNum, KeyModifierMask mask)
|
||||||
{
|
{
|
||||||
log((CLOG_DEBUG1 "send enter to \"%s\", %d,%d %d", getClient().c_str(), xAbs, yAbs, seqNum));
|
log((CLOG_DEBUG1 "send enter to \"%s\", %d,%d %d %04x", getClient().c_str(), xAbs, yAbs, seqNum, mask));
|
||||||
CProtocolUtil::writef(getOutputStream(), kMsgCEnter, xAbs, yAbs, seqNum);
|
CProtocolUtil::writef(getOutputStream(), kMsgCEnter,
|
||||||
|
xAbs, yAbs, seqNum, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CServerProtocol1_0::sendLeave()
|
void CServerProtocol1_0::sendLeave()
|
||||||
|
|
|
@ -16,7 +16,8 @@ public:
|
||||||
virtual void run();
|
virtual void run();
|
||||||
virtual void queryInfo();
|
virtual void queryInfo();
|
||||||
virtual void sendClose();
|
virtual void sendClose();
|
||||||
virtual void sendEnter(SInt32 xAbs, SInt32 yAbs, UInt32 seqNum);
|
virtual void sendEnter(SInt32 xAbs, SInt32 yAbs,
|
||||||
|
UInt32 seqNum, KeyModifierMask mask);
|
||||||
virtual void sendLeave();
|
virtual void sendLeave();
|
||||||
virtual void sendClipboard(ClipboardID, const CString&);
|
virtual void sendClipboard(ClipboardID, const CString&);
|
||||||
virtual void sendGrabClipboard(ClipboardID);
|
virtual void sendGrabClipboard(ClipboardID);
|
||||||
|
|
|
@ -47,6 +47,7 @@ void CXWindowsPrimaryScreen::run()
|
||||||
// keyboard mapping changed
|
// keyboard mapping changed
|
||||||
CDisplayLock display(this);
|
CDisplayLock display(this);
|
||||||
XRefreshKeyboardMapping(&xevent.xmapping);
|
XRefreshKeyboardMapping(&xevent.xmapping);
|
||||||
|
updateModifierMap(display);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,6 +220,12 @@ void CXWindowsPrimaryScreen::open(CServer* server)
|
||||||
// FIXME -- may have to get these from some database
|
// FIXME -- may have to get these from some database
|
||||||
m_capsLockHalfDuplex = false;
|
m_capsLockHalfDuplex = false;
|
||||||
// m_capsLockHalfDuplex = true;
|
// m_capsLockHalfDuplex = true;
|
||||||
|
|
||||||
|
// update key state
|
||||||
|
{
|
||||||
|
CDisplayLock display(this);
|
||||||
|
updateModifierMap(display);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CXWindowsPrimaryScreen::close()
|
void CXWindowsPrimaryScreen::close()
|
||||||
|
@ -365,6 +372,31 @@ void CXWindowsPrimaryScreen::getClipboard(
|
||||||
getDisplayClipboard(id, clipboard, m_window, getCurrentTime(m_window));
|
getDisplayClipboard(id, clipboard, m_window, getCurrentTime(m_window));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyModifierMask CXWindowsPrimaryScreen::getToggleMask() const
|
||||||
|
{
|
||||||
|
CDisplayLock display(this);
|
||||||
|
|
||||||
|
// query the pointer to get the keyboard state
|
||||||
|
// FIXME -- is there a better way to do this?
|
||||||
|
Window root, window;
|
||||||
|
int xRoot, yRoot, xWindow, yWindow;
|
||||||
|
unsigned int state;
|
||||||
|
if (!XQueryPointer(display, m_window, &root, &window,
|
||||||
|
&xRoot, &yRoot, &xWindow, &yWindow, &state))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// convert to KeyModifierMask
|
||||||
|
KeyModifierMask mask;
|
||||||
|
if (state & m_numLockMask)
|
||||||
|
mask |= KeyModifierNumLock;
|
||||||
|
if (state & m_capsLockMask)
|
||||||
|
mask |= KeyModifierCapsLock;
|
||||||
|
if (state & m_scrollLockMask)
|
||||||
|
mask |= KeyModifierScrollLock;
|
||||||
|
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
void CXWindowsPrimaryScreen::onOpenDisplay()
|
void CXWindowsPrimaryScreen::onOpenDisplay()
|
||||||
{
|
{
|
||||||
assert(m_window == None);
|
assert(m_window == None);
|
||||||
|
@ -483,3 +515,38 @@ ButtonID CXWindowsPrimaryScreen::mapButton(
|
||||||
else
|
else
|
||||||
return kButtonNone;
|
return kButtonNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CXWindowsPrimaryScreen::updateModifierMap(
|
||||||
|
Display* display)
|
||||||
|
{
|
||||||
|
// get modifier map from server
|
||||||
|
XModifierKeymap* keymap = XGetModifierMapping(display);
|
||||||
|
|
||||||
|
// initialize
|
||||||
|
m_numLockMask = 0;
|
||||||
|
m_capsLockMask = 0;
|
||||||
|
m_scrollLockMask = 0;
|
||||||
|
|
||||||
|
// set keycodes and masks
|
||||||
|
for (unsigned int i = 0; i < 8; ++i) {
|
||||||
|
const unsigned int bit = (1 << i);
|
||||||
|
for (int j = 0; j < keymap->max_keypermod; ++j) {
|
||||||
|
KeyCode keycode = keymap->modifiermap[i *
|
||||||
|
keymap->max_keypermod + j];
|
||||||
|
|
||||||
|
// note toggle modifier bits
|
||||||
|
const KeySym keysym = XKeycodeToKeysym(display, keycode, 0);
|
||||||
|
if (keysym == XK_Num_Lock) {
|
||||||
|
m_numLockMask |= bit;
|
||||||
|
}
|
||||||
|
else if (keysym == XK_Caps_Lock) {
|
||||||
|
m_capsLockMask |= bit;
|
||||||
|
}
|
||||||
|
else if (keysym == XK_Scroll_Lock) {
|
||||||
|
m_scrollLockMask |= bit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XFreeModifiermap(keymap);
|
||||||
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ public:
|
||||||
virtual void getSize(SInt32* width, SInt32* height) const;
|
virtual void getSize(SInt32* width, SInt32* height) const;
|
||||||
virtual SInt32 getJumpZoneSize() const;
|
virtual SInt32 getJumpZoneSize() const;
|
||||||
virtual void getClipboard(ClipboardID, IClipboard*) const;
|
virtual void getClipboard(ClipboardID, IClipboard*) const;
|
||||||
|
virtual KeyModifierMask getToggleMask() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// CXWindowsScreen overrides
|
// CXWindowsScreen overrides
|
||||||
|
@ -40,12 +41,21 @@ private:
|
||||||
KeyID mapKey(XKeyEvent*) const;
|
KeyID mapKey(XKeyEvent*) const;
|
||||||
ButtonID mapButton(unsigned int button) const;
|
ButtonID mapButton(unsigned int button) const;
|
||||||
|
|
||||||
|
void updateModifierMap(Display* display);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CServer* m_server;
|
CServer* m_server;
|
||||||
bool m_active;
|
bool m_active;
|
||||||
Window m_window;
|
Window m_window;
|
||||||
|
|
||||||
|
// note if caps lock key toggles on up/down (false) or on
|
||||||
|
// transition (true)
|
||||||
bool m_capsLockHalfDuplex;
|
bool m_capsLockHalfDuplex;
|
||||||
|
|
||||||
|
// masks that indicate which modifier bits are for toggle keys
|
||||||
|
unsigned int m_numLockMask;
|
||||||
|
unsigned int m_capsLockMask;
|
||||||
|
unsigned int m_scrollLockMask;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -79,6 +79,11 @@ public:
|
||||||
// and should avoid setting the clipboard object if the screen's
|
// and should avoid setting the clipboard object if the screen's
|
||||||
// clipboard hasn't changed.
|
// clipboard hasn't changed.
|
||||||
virtual void getClipboard(ClipboardID, IClipboard*) const = 0;
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -34,7 +34,8 @@ public:
|
||||||
// called when the user navigates to the secondary screen. warp
|
// called when the user navigates to the secondary screen. warp
|
||||||
// the cursor to the given coordinates and unhide it. prepare to
|
// the cursor to the given coordinates and unhide it. prepare to
|
||||||
// simulate input events.
|
// simulate input events.
|
||||||
virtual void enter(SInt32 xAbsolute, SInt32 yAbsolute) = 0;
|
virtual void enter(SInt32 xAbsolute, SInt32 yAbsolute,
|
||||||
|
KeyModifierMask mask) = 0;
|
||||||
|
|
||||||
// called when the user navigates off the secondary screen. clean
|
// called when the user navigates off the secondary screen. clean
|
||||||
// up input event simulation and hide the cursor.
|
// up input event simulation and hide the cursor.
|
||||||
|
|
|
@ -24,7 +24,8 @@ public:
|
||||||
|
|
||||||
// send various messages to client
|
// send various messages to client
|
||||||
virtual void sendClose() = 0;
|
virtual void sendClose() = 0;
|
||||||
virtual void sendEnter(SInt32 xAbs, SInt32 yAbs, UInt32 seqNum) = 0;
|
virtual void sendEnter(SInt32 xAbs, SInt32 yAbs,
|
||||||
|
UInt32 seqNum, KeyModifierMask mask) = 0;
|
||||||
virtual void sendLeave() = 0;
|
virtual void sendLeave() = 0;
|
||||||
virtual void sendClipboard(ClipboardID, const CString&) = 0;
|
virtual void sendClipboard(ClipboardID, const CString&) = 0;
|
||||||
virtual void sendGrabClipboard(ClipboardID) = 0;
|
virtual void sendGrabClipboard(ClipboardID) = 0;
|
||||||
|
|
|
@ -24,8 +24,11 @@ static const char kMsgCClose[] = "CBYE";
|
||||||
// entering screen at screen position $1 = x, $2 = y. x,y are
|
// entering screen at screen position $1 = x, $2 = y. x,y are
|
||||||
// absolute screen coordinates. $3 = sequence number, which is
|
// absolute screen coordinates. $3 = sequence number, which is
|
||||||
// used to order messages between screens. the secondary screen
|
// used to order messages between screens. the secondary screen
|
||||||
// must return this number with some messages.
|
// must return this number with some messages. $4 = modifier key
|
||||||
static const char kMsgCEnter[] = "CINN%2i%2i%4i";
|
// mask. this will have bits set for each toggle modifier key
|
||||||
|
// that is activated on entry to the screen. the secondary screen
|
||||||
|
// should adjust its toggle modifiers to reflect that state.
|
||||||
|
static const char kMsgCEnter[] = "CINN%2i%2i%4i%2i";
|
||||||
|
|
||||||
// leave screen: primary -> secondary
|
// leave screen: primary -> secondary
|
||||||
// leaving screen. the secondary screen should send clipboard
|
// leaving screen. the secondary screen should send clipboard
|
||||||
|
|
Loading…
Reference in New Issue