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()
|
||||
{
|
||||
SInt16 x, y;
|
||||
UInt16 mask;
|
||||
{
|
||||
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;
|
||||
}
|
||||
log((CLOG_DEBUG1 "recv enter, %d,%d %d", x, y, m_seqNum));
|
||||
m_screen->enter(x, y);
|
||||
log((CLOG_DEBUG1 "recv enter, %d,%d %d %04x", x, y, m_seqNum, mask));
|
||||
m_screen->enter(x, y, static_cast<KeyModifierMask>(mask));
|
||||
}
|
||||
|
||||
void CClient::onLeave()
|
||||
|
|
|
@ -109,11 +109,12 @@ void CMSWindowsSecondaryScreen::close()
|
|||
m_client = NULL;
|
||||
}
|
||||
|
||||
void CMSWindowsSecondaryScreen::enter(SInt32 x, SInt32 y)
|
||||
void CMSWindowsSecondaryScreen::enter(
|
||||
SInt32 x, SInt32 y, KeyModifierMask mask)
|
||||
{
|
||||
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
|
||||
SInt32 w, h;
|
||||
|
@ -130,6 +131,17 @@ void CMSWindowsSecondaryScreen::enter(SInt32 x, SInt32 y)
|
|||
// update our keyboard state to reflect the local state
|
||||
updateKeys();
|
||||
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()
|
||||
|
@ -1184,3 +1196,16 @@ void CMSWindowsSecondaryScreen::updateModifiers()
|
|||
if ((m_keys[VK_SCROLL] & 0x01) != 0)
|
||||
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 open(CClient*);
|
||||
virtual void close();
|
||||
virtual void enter(SInt32 xAbsolute, SInt32 yAbsolute);
|
||||
virtual void enter(SInt32 xAbsolute, SInt32 yAbsolute,
|
||||
KeyModifierMask mask);
|
||||
virtual void leave();
|
||||
virtual void keyDown(KeyID, KeyModifierMask);
|
||||
virtual void keyRepeat(KeyID, KeyModifierMask, SInt32 count);
|
||||
|
@ -48,6 +49,7 @@ private:
|
|||
|
||||
void updateKeys();
|
||||
void updateModifiers();
|
||||
void toggleKey(UINT virtualKey, KeyModifierMask mask);
|
||||
|
||||
private:
|
||||
CClient* m_client;
|
||||
|
|
|
@ -177,7 +177,8 @@ void CXWindowsSecondaryScreen::close()
|
|||
m_client = NULL;
|
||||
}
|
||||
|
||||
void CXWindowsSecondaryScreen::enter(SInt32 x, SInt32 y)
|
||||
void CXWindowsSecondaryScreen::enter(
|
||||
SInt32 x, SInt32 y, KeyModifierMask mask)
|
||||
{
|
||||
assert(m_window != None);
|
||||
|
||||
|
@ -193,6 +194,19 @@ void CXWindowsSecondaryScreen::enter(SInt32 x, SInt32 y)
|
|||
// 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);
|
||||
}
|
||||
XSync(display, False);
|
||||
}
|
||||
|
||||
void CXWindowsSecondaryScreen::leave()
|
||||
|
@ -461,9 +475,14 @@ KeyModifierMask CXWindowsSecondaryScreen::mapKey(
|
|||
const KeyCode modifierKey = modifierKeys[0];
|
||||
keys.push_back(std::make_pair(modifierKey, True));
|
||||
if ((bit & m_toggleModifierMask) != 0) {
|
||||
keys.push_back(std::make_pair(modifierKey, False));
|
||||
undo.push_back(std::make_pair(modifierKey, False));
|
||||
undo.push_back(std::make_pair(modifierKey, True));
|
||||
if (bit != m_capsLockMask || !m_capsLockHalfDuplex) {
|
||||
keys.push_back(std::make_pair(modifierKey, False));
|
||||
undo.push_back(std::make_pair(modifierKey, False));
|
||||
undo.push_back(std::make_pair(modifierKey, True));
|
||||
}
|
||||
else {
|
||||
undo.push_back(std::make_pair(modifierKey, False));
|
||||
}
|
||||
}
|
||||
else {
|
||||
undo.push_back(std::make_pair(modifierKey, False));
|
||||
|
@ -476,12 +495,18 @@ KeyModifierMask CXWindowsSecondaryScreen::mapKey(
|
|||
// press/release, otherwise deactivate it with a
|
||||
// release. we must check each keycode for the
|
||||
// modifier if not a toggle.
|
||||
if (bit & m_toggleModifierMask) {
|
||||
if ((bit & m_toggleModifierMask) != 0) {
|
||||
const KeyCode modifierKey = modifierKeys[0];
|
||||
keys.push_back(std::make_pair(modifierKey, True));
|
||||
keys.push_back(std::make_pair(modifierKey, False));
|
||||
undo.push_back(std::make_pair(modifierKey, False));
|
||||
undo.push_back(std::make_pair(modifierKey, True));
|
||||
if (bit != m_capsLockMask || !m_capsLockHalfDuplex) {
|
||||
keys.push_back(std::make_pair(modifierKey, True));
|
||||
keys.push_back(std::make_pair(modifierKey, False));
|
||||
undo.push_back(std::make_pair(modifierKey, False));
|
||||
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 {
|
||||
for (unsigned int j = 0; j < m_keysPerModifier; ++j) {
|
||||
|
@ -601,11 +626,11 @@ unsigned int CXWindowsSecondaryScreen::maskToX(
|
|||
if (inMask & KeyModifierMeta)
|
||||
outMask |= Mod4Mask;
|
||||
if (inMask & KeyModifierCapsLock)
|
||||
outMask |= LockMask;
|
||||
outMask |= m_capsLockMask;
|
||||
if (inMask & KeyModifierNumLock)
|
||||
outMask |= Mod2Mask;
|
||||
outMask |= m_numLockMask;
|
||||
if (inMask & KeyModifierScrollLock)
|
||||
outMask |= Mod5Mask;
|
||||
outMask |= m_scrollLockMask;
|
||||
return outMask;
|
||||
}
|
||||
|
||||
|
@ -712,6 +737,7 @@ void CXWindowsSecondaryScreen::updateModifierMap(
|
|||
m_toggleModifierMask = 0;
|
||||
m_numLockMask = 0;
|
||||
m_capsLockMask = 0;
|
||||
m_scrollLockMask = 0;
|
||||
m_keysPerModifier = keymap->max_keypermod;
|
||||
m_modifierToKeycode.clear();
|
||||
m_modifierToKeycode.resize(8 * m_keysPerModifier);
|
||||
|
@ -738,10 +764,15 @@ void CXWindowsSecondaryScreen::updateModifierMap(
|
|||
m_toggleModifierMask |= bit;
|
||||
|
||||
// note num/caps-lock
|
||||
if (keysym == XK_Num_Lock)
|
||||
if (keysym == XK_Num_Lock) {
|
||||
m_numLockMask |= bit;
|
||||
if (keysym == XK_Caps_Lock)
|
||||
}
|
||||
else if (keysym == XK_Caps_Lock) {
|
||||
m_capsLockMask |= bit;
|
||||
}
|
||||
else if (keysym == XK_Scroll_Lock) {
|
||||
m_scrollLockMask |= bit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -749,6 +780,31 @@ void CXWindowsSecondaryScreen::updateModifierMap(
|
|||
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)
|
||||
{
|
||||
switch (key) {
|
||||
|
|
|
@ -15,7 +15,8 @@ public:
|
|||
virtual void stop();
|
||||
virtual void open(CClient*);
|
||||
virtual void close();
|
||||
virtual void enter(SInt32 xAbsolute, SInt32 yAbsolute);
|
||||
virtual void enter(SInt32 xAbsolute, SInt32 yAbsolute,
|
||||
KeyModifierMask mask);
|
||||
virtual void leave();
|
||||
virtual void keyDown(KeyID, KeyModifierMask);
|
||||
virtual void keyRepeat(KeyID, KeyModifierMask, SInt32 count);
|
||||
|
@ -62,6 +63,7 @@ private:
|
|||
void updateKeycodeMap(Display* display);
|
||||
void updateModifiers(Display* display);
|
||||
void updateModifierMap(Display* display);
|
||||
void toggleKey(Display*, KeySym, unsigned int mask);
|
||||
static bool isToggleKeysym(KeySym);
|
||||
|
||||
private:
|
||||
|
@ -88,9 +90,10 @@ private:
|
|||
// set bits indicate modifiers that toggle (e.g. caps-lock)
|
||||
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_capsLockMask;
|
||||
unsigned int m_scrollLockMask;
|
||||
|
||||
// map X modifier key indices to the key codes bound to them
|
||||
unsigned int m_keysPerModifier;
|
||||
|
|
|
@ -252,6 +252,18 @@ void CMSWindowsPrimaryScreen::getClipboard(
|
|||
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
|
||||
|
||||
void CMSWindowsPrimaryScreen::onOpenDisplay()
|
||||
|
|
|
@ -26,6 +26,7 @@ public:
|
|||
virtual void getSize(SInt32* width, SInt32* height) const;
|
||||
virtual SInt32 getJumpZoneSize() const;
|
||||
virtual void getClipboard(ClipboardID, IClipboard*) const;
|
||||
virtual KeyModifierMask getToggleMask() const;
|
||||
|
||||
protected:
|
||||
// CMSWindowsScreen overrides
|
||||
|
|
|
@ -537,7 +537,8 @@ void CServer::switchScreen(CScreenInfo* dst,
|
|||
m_primary->enter(x, y);
|
||||
}
|
||||
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
|
||||
|
|
|
@ -31,7 +31,8 @@ public:
|
|||
virtual void run() = 0;
|
||||
virtual void queryInfo() = 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 sendClipboard(ClipboardID, const CString&) = 0;
|
||||
virtual void sendGrabClipboard(ClipboardID) = 0;
|
||||
|
|
|
@ -91,10 +91,12 @@ void CServerProtocol1_0::sendClose()
|
|||
}
|
||||
|
||||
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));
|
||||
CProtocolUtil::writef(getOutputStream(), kMsgCEnter, 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, mask);
|
||||
}
|
||||
|
||||
void CServerProtocol1_0::sendLeave()
|
||||
|
|
|
@ -16,7 +16,8 @@ public:
|
|||
virtual void run();
|
||||
virtual void queryInfo();
|
||||
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 sendClipboard(ClipboardID, const CString&);
|
||||
virtual void sendGrabClipboard(ClipboardID);
|
||||
|
|
|
@ -47,6 +47,7 @@ void CXWindowsPrimaryScreen::run()
|
|||
// keyboard mapping changed
|
||||
CDisplayLock display(this);
|
||||
XRefreshKeyboardMapping(&xevent.xmapping);
|
||||
updateModifierMap(display);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -219,6 +220,12 @@ void CXWindowsPrimaryScreen::open(CServer* server)
|
|||
// FIXME -- may have to get these from some database
|
||||
m_capsLockHalfDuplex = false;
|
||||
// m_capsLockHalfDuplex = true;
|
||||
|
||||
// update key state
|
||||
{
|
||||
CDisplayLock display(this);
|
||||
updateModifierMap(display);
|
||||
}
|
||||
}
|
||||
|
||||
void CXWindowsPrimaryScreen::close()
|
||||
|
@ -365,6 +372,31 @@ void CXWindowsPrimaryScreen::getClipboard(
|
|||
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()
|
||||
{
|
||||
assert(m_window == None);
|
||||
|
@ -483,3 +515,38 @@ ButtonID CXWindowsPrimaryScreen::mapButton(
|
|||
else
|
||||
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 SInt32 getJumpZoneSize() const;
|
||||
virtual void getClipboard(ClipboardID, IClipboard*) const;
|
||||
virtual KeyModifierMask getToggleMask() const;
|
||||
|
||||
protected:
|
||||
// CXWindowsScreen overrides
|
||||
|
@ -40,12 +41,21 @@ private:
|
|||
KeyID mapKey(XKeyEvent*) const;
|
||||
ButtonID mapButton(unsigned int button) const;
|
||||
|
||||
void updateModifierMap(Display* display);
|
||||
|
||||
private:
|
||||
CServer* m_server;
|
||||
bool m_active;
|
||||
Window m_window;
|
||||
|
||||
// note if caps lock key toggles on up/down (false) or on
|
||||
// transition (true)
|
||||
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
|
||||
|
|
|
@ -79,6 +79,11 @@ public:
|
|||
// and should avoid setting the clipboard object if the screen's
|
||||
// clipboard hasn't changed.
|
||||
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
|
||||
|
|
|
@ -34,7 +34,8 @@ public:
|
|||
// 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) = 0;
|
||||
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.
|
||||
|
|
|
@ -24,7 +24,8 @@ public:
|
|||
|
||||
// send various messages to client
|
||||
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 sendClipboard(ClipboardID, const CString&) = 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
|
||||
// absolute screen coordinates. $3 = sequence number, which is
|
||||
// used to order messages between screens. the secondary screen
|
||||
// must return this number with some messages.
|
||||
static const char kMsgCEnter[] = "CINN%2i%2i%4i";
|
||||
// must return this number with some messages. $4 = modifier key
|
||||
// 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
|
||||
// leaving screen. the secondary screen should send clipboard
|
||||
|
|
Loading…
Reference in New Issue