diff --git a/CClient.cpp b/CClient.cpp index 65030c99..83739e8c 100644 --- a/CClient.cpp +++ b/CClient.cpp @@ -154,8 +154,13 @@ void CClient::onRead() (static_cast(buf[2]) << 16) + (static_cast(buf[3]) << 8) + (static_cast(buf[4]) )); - TRACE((" key down: %d", k)); - m_screen->onKeyDown(k); + const KeyModifierMask m = static_cast( + (static_cast(buf[5]) << 24) + + (static_cast(buf[6]) << 16) + + (static_cast(buf[7]) << 8) + + (static_cast(buf[8]) )); + TRACE((" key down: %d 0x%08x", k, m)); + m_screen->onKeyDown(k, m); break; } @@ -165,13 +170,18 @@ void CClient::onRead() (static_cast(buf[2]) << 16) + (static_cast(buf[3]) << 8) + (static_cast(buf[4]) )); - const SInt32 n = static_cast( + const KeyModifierMask m = static_cast( (static_cast(buf[5]) << 24) + (static_cast(buf[6]) << 16) + (static_cast(buf[7]) << 8) + (static_cast(buf[8]) )); - TRACE((" key repeat: %d x%d", k, n)); - m_screen->onKeyRepeat(k, n); + const SInt32 n = static_cast( + (static_cast(buf[9]) << 24) + + (static_cast(buf[10]) << 16) + + (static_cast(buf[11]) << 8) + + (static_cast(buf[12]) )); + TRACE((" key repeat: %d 0x%08x x%d", k, m, n)); + m_screen->onKeyRepeat(k, m, n); break; } @@ -181,17 +191,13 @@ void CClient::onRead() (static_cast(buf[2]) << 16) + (static_cast(buf[3]) << 8) + (static_cast(buf[4]) )); - TRACE((" key up: %d", k)); - m_screen->onKeyUp(k); - break; - } - - case '\012': { - const KeyToggleMask m = static_cast( - (static_cast(buf[1]) << 8) + - (static_cast(buf[2]) )); - TRACE((" key toggle: 0x%04x", m)); - m_screen->onKeyToggle(m); + const KeyModifierMask m = static_cast( + (static_cast(buf[5]) << 24) + + (static_cast(buf[6]) << 16) + + (static_cast(buf[7]) << 8) + + (static_cast(buf[8]) )); + TRACE((" key up: %d 0x%08x", k, m)); + m_screen->onKeyUp(k, m); break; } diff --git a/CEvent.h b/CEvent.h index 452aa4e6..348218a2 100644 --- a/CEvent.h +++ b/CEvent.h @@ -27,6 +27,7 @@ class CEventBase { class CEventKey : public CEventBase { public: KeyID m_key; + KeyModifierMask m_mask; SInt32 m_count; }; diff --git a/CScreenProxy.cpp b/CScreenProxy.cpp index d287107d..62cf9258 100644 --- a/CScreenProxy.cpp +++ b/CScreenProxy.cpp @@ -82,49 +82,53 @@ void CScreenProxy::setClipboard(const IClipboard*) // FIXME } -void CScreenProxy::onKeyDown(KeyID k) +void CScreenProxy::onKeyDown(KeyID k, KeyModifierMask m) { - char buf[5]; + char buf[9]; memcpy(buf, "\007", 1); buf[1] = static_cast((k >> 24) & 0xff); buf[2] = static_cast((k >> 16) & 0xff); buf[3] = static_cast((k >> 8) & 0xff); buf[4] = static_cast(k & 0xff); + buf[5] = static_cast((m >> 24) & 0xff); + buf[6] = static_cast((m >> 16) & 0xff); + buf[7] = static_cast((m >> 8) & 0xff); + buf[8] = static_cast(m & 0xff); m_socket->write(buf, sizeof(buf)); } -void CScreenProxy::onKeyRepeat(KeyID k, SInt32 n) +void CScreenProxy::onKeyRepeat( + KeyID k, KeyModifierMask m, SInt32 n) { - char buf[9]; + char buf[13]; memcpy(buf, "\010", 1); buf[1] = static_cast((k >> 24) & 0xff); buf[2] = static_cast((k >> 16) & 0xff); buf[3] = static_cast((k >> 8) & 0xff); buf[4] = static_cast(k & 0xff); - buf[5] = static_cast((n >> 24) & 0xff); - buf[6] = static_cast((n >> 16) & 0xff); - buf[7] = static_cast((n >> 8) & 0xff); - buf[8] = static_cast(n & 0xff); + buf[5] = static_cast((m >> 24) & 0xff); + buf[6] = static_cast((m >> 16) & 0xff); + buf[7] = static_cast((m >> 8) & 0xff); + buf[8] = static_cast(m & 0xff); + buf[9] = static_cast((n >> 24) & 0xff); + buf[10] = static_cast((n >> 16) & 0xff); + buf[11] = static_cast((n >> 8) & 0xff); + buf[12] = static_cast(n & 0xff); m_socket->write(buf, sizeof(buf)); } -void CScreenProxy::onKeyUp(KeyID k) +void CScreenProxy::onKeyUp(KeyID k, KeyModifierMask m) { - char buf[5]; + char buf[9]; memcpy(buf, "\011", 1); buf[1] = static_cast((k >> 24) & 0xff); buf[2] = static_cast((k >> 16) & 0xff); buf[3] = static_cast((k >> 8) & 0xff); buf[4] = static_cast(k & 0xff); - m_socket->write(buf, sizeof(buf)); -} - -void CScreenProxy::onKeyToggle(KeyToggleMask m) -{ - char buf[3]; - memcpy(buf, "\012", 1); - buf[1] = static_cast((m >> 8) & 0xff); - buf[2] = static_cast(m & 0xff); + buf[5] = static_cast((m >> 24) & 0xff); + buf[6] = static_cast((m >> 16) & 0xff); + buf[7] = static_cast((m >> 8) & 0xff); + buf[8] = static_cast(m & 0xff); m_socket->write(buf, sizeof(buf)); } diff --git a/CScreenProxy.h b/CScreenProxy.h index 39786d82..bbcb7a1d 100644 --- a/CScreenProxy.h +++ b/CScreenProxy.h @@ -18,10 +18,9 @@ class CScreenProxy : public IScreen { virtual void warpCursor(SInt32 xAbsolute, SInt32 yAbsolute); virtual void setClipboard(const IClipboard*); virtual void onScreenSaver(bool show); - virtual void onKeyDown(KeyID); - virtual void onKeyRepeat(KeyID, SInt32 count); - virtual void onKeyUp(KeyID); - virtual void onKeyToggle(KeyToggleMask); + virtual void onKeyDown(KeyID, KeyModifierMask); + virtual void onKeyRepeat(KeyID, KeyModifierMask, SInt32 count); + virtual void onKeyUp(KeyID, KeyModifierMask); virtual void onMouseDown(ButtonID); virtual void onMouseUp(ButtonID); virtual void onMouseMove(SInt32 xAbsolute, SInt32 yAbsolute); diff --git a/CServer.cpp b/CServer.cpp index fb28810f..80bf026c 100644 --- a/CServer.cpp +++ b/CServer.cpp @@ -350,15 +350,16 @@ void CServer::relayEvent(const CEvent* event) break; case CEventBase::kKeyDown: - m_activeScreen->onKeyDown(event->m_key.m_key); + m_activeScreen->onKeyDown(event->m_key.m_key, event->m_key.m_mask); break; case CEventBase::kKeyRepeat: - m_activeScreen->onKeyRepeat(event->m_key.m_key, event->m_key.m_count); + m_activeScreen->onKeyRepeat(event->m_key.m_key, + event->m_key.m_mask, event->m_key.m_count); break; case CEventBase::kKeyUp: - m_activeScreen->onKeyUp(event->m_key.m_key); + m_activeScreen->onKeyUp(event->m_key.m_key, event->m_key.m_mask); break; case CEventBase::kMouseDown: diff --git a/CXScreen.cpp b/CXScreen.cpp index 1f738fc2..049641c6 100644 --- a/CXScreen.cpp +++ b/CXScreen.cpp @@ -146,7 +146,17 @@ void CXScreen::onScreenSaver(bool show) onScreenSaverSecondary(show); } -void CXScreen::onKeyDown(KeyID) +void CXScreen::onKeyDown(KeyID key, KeyModifierMask) +{ + assert(m_display != NULL); + assert(m_primary == false); + + // FIXME -- use mask + ::XTestFakeKeyEvent(m_display, mapKeyToX(key), True, CurrentTime); + ::XSync(m_display, False); +} + +void CXScreen::onKeyRepeat(KeyID, KeyModifierMask, SInt32) { assert(m_display != NULL); assert(m_primary == false); @@ -154,44 +164,32 @@ void CXScreen::onKeyDown(KeyID) // FIXME } -void CXScreen::onKeyRepeat(KeyID, SInt32) +void CXScreen::onKeyUp(KeyID key, KeyModifierMask) { assert(m_display != NULL); assert(m_primary == false); - // FIXME + // FIXME -- use mask + ::XTestFakeKeyEvent(m_display, mapKeyToX(key), False, CurrentTime); + ::XSync(m_display, False); } -void CXScreen::onKeyUp(KeyID) +void CXScreen::onMouseDown(ButtonID button) { assert(m_display != NULL); assert(m_primary == false); - // FIXME + ::XTestFakeButtonEvent(m_display, mapButtonToX(button), True, CurrentTime); + ::XSync(m_display, False); } -void CXScreen::onKeyToggle(KeyToggleMask) +void CXScreen::onMouseUp(ButtonID button) { assert(m_display != NULL); assert(m_primary == false); - // FIXME -} - -void CXScreen::onMouseDown(ButtonID) -{ - assert(m_display != NULL); - assert(m_primary == false); - - // FIXME -} - -void CXScreen::onMouseUp(ButtonID) -{ - assert(m_display != NULL); - assert(m_primary == false); - - // FIXME + ::XTestFakeButtonEvent(m_display, mapButtonToX(button), False, CurrentTime); + ::XSync(m_display, False); } void CXScreen::onMouseMove(SInt32 x, SInt32 y) @@ -430,25 +428,77 @@ void CXScreen::selectEvents(Window w) const } } -KeyID CXScreen::mapKey(unsigned int keycode) const +KeyModifierMask CXScreen::mapModifierFromX(unsigned int state) const { - return keycode; + // FIXME -- should be configurable + KeyModifierMask mask = 0; + if (state & 1) + mask |= KeyModifierShift; + if (state & 2) + mask |= KeyModifierCapsLock; + if (state & 4) + mask |= KeyModifierControl; + if (state & 8) + mask |= KeyModifierAlt; + if (state & 16) + mask |= KeyModifierNumLock; + if (state & 32) + mask |= KeyModifierMeta; + if (state & 128) + mask |= KeyModifierScrollLock; + return mask; } -ButtonID CXScreen::mapButton(unsigned int button) const +unsigned int CXScreen::mapModifierToX(KeyModifierMask mask) const { - switch (button) { - case 1: - return kButtonLeft; + // FIXME -- should be configurable + unsigned int state = 0; + if (mask & KeyModifierShift) + state |= 1; + if (mask & KeyModifierControl) + state |= 4; + if (mask & KeyModifierAlt) + state |= 8; + if (mask & KeyModifierMeta) + state |= 32; + if (mask & KeyModifierCapsLock) + state |= 2; + if (mask & KeyModifierNumLock) + state |= 16; + if (mask & KeyModifierScrollLock) + state |= 128; + return state; +} - case 2: - return kButtonMiddle; +KeyID CXScreen::mapKeyFromX( + KeyCode keycode, KeyModifierMask mask) const +{ + int index; + if (mask & KeyModifierShift) + index = 1; + else + index = 0; + return static_cast(::XKeycodeToKeysym(m_display, keycode, index)); +} - case 3: - return kButtonRight; - } +KeyCode CXScreen::mapKeyToX(KeyID keyID) const +{ + return ::XKeysymToKeycode(m_display, static_cast(keyID)); +} - return kButtonNone; +ButtonID CXScreen::mapButtonFromX(unsigned int button) const +{ + // FIXME -- should use button mapping? + if (button >= 1 && button <= 3) + return static_cast(button); + else + return kButtonNone; +} + +unsigned int CXScreen::mapButtonToX(ButtonID buttonID) const +{ + // FIXME -- should use button mapping? + return static_cast(buttonID); } void CXScreen::onPrimaryEvents() @@ -459,11 +509,13 @@ void CXScreen::onPrimaryEvents() switch (xevent.type) { case KeyPress: { - const KeyID key = mapKey(xevent.xkey.keycode); + const KeyModifierMask mask = mapModifierFromX(xevent.xkey.state); + const KeyID key = mapKeyFromX(xevent.xkey.keycode, mask); if (key != kKeyNone) { CEvent event; event.m_key.m_type = CEventBase::kKeyDown; event.m_key.m_key = key; + event.m_key.m_mask = mask; event.m_key.m_count = 0; CEQ->push(&event); } @@ -473,11 +525,13 @@ void CXScreen::onPrimaryEvents() // FIXME -- simulate key repeat. X sends press/release for // repeat. must detect auto repeat and use kKeyRepeat. case KeyRelease: { - const KeyID key = mapKey(xevent.xkey.keycode); + const KeyModifierMask mask = mapModifierFromX(xevent.xkey.state); + const KeyID key = mapKeyFromX(xevent.xkey.keycode, mask); if (key != kKeyNone) { CEvent event; event.m_key.m_type = CEventBase::kKeyUp; event.m_key.m_key = key; + event.m_key.m_mask = mask; event.m_key.m_count = 0; CEQ->push(&event); } @@ -485,7 +539,7 @@ void CXScreen::onPrimaryEvents() } case ButtonPress: { - const ButtonID button = mapButton(xevent.xbutton.button); + const ButtonID button = mapButtonFromX(xevent.xbutton.button); if (button != kButtonNone) { CEvent event; event.m_mouse.m_type = CEventBase::kMouseDown; @@ -498,7 +552,7 @@ void CXScreen::onPrimaryEvents() } case ButtonRelease: { - const ButtonID button = mapButton(xevent.xbutton.button); + const ButtonID button = mapButtonFromX(xevent.xbutton.button); if (button != kButtonNone) { CEvent event; event.m_mouse.m_type = CEventBase::kMouseUp; diff --git a/CXScreen.h b/CXScreen.h index c2fb9b83..96a4ab28 100644 --- a/CXScreen.h +++ b/CXScreen.h @@ -17,10 +17,9 @@ class CXScreen : public IScreen { virtual void warpCursor(SInt32 x, SInt32 y); virtual void setClipboard(const IClipboard*); virtual void onScreenSaver(bool); - virtual void onKeyDown(KeyID); - virtual void onKeyRepeat(KeyID, SInt32); - virtual void onKeyUp(KeyID); - virtual void onKeyToggle(KeyToggleMask); + virtual void onKeyDown(KeyID, KeyModifierMask); + virtual void onKeyRepeat(KeyID, KeyModifierMask, SInt32); + virtual void onKeyUp(KeyID, KeyModifierMask); virtual void onMouseDown(ButtonID); virtual void onMouseUp(ButtonID); virtual void onMouseMove(SInt32, SInt32); @@ -61,8 +60,12 @@ class CXScreen : public IScreen { private: void selectEvents(Window) const; - KeyID mapKey(unsigned int keycode) const; - ButtonID mapButton(unsigned int button) const; + KeyModifierMask mapModifierFromX(unsigned int) const; + unsigned int mapModifierToX(KeyModifierMask) const; + KeyID mapKeyFromX(KeyCode, KeyModifierMask) const; + KeyCode mapKeyToX(KeyID) const; + ButtonID mapButtonFromX(unsigned int button) const; + unsigned int mapButtonToX(ButtonID) const; void onPrimaryEvents(); void onSecondaryEvents(); diff --git a/IScreen.h b/IScreen.h index a8427584..fd2a8346 100644 --- a/IScreen.h +++ b/IScreen.h @@ -93,15 +93,13 @@ class IScreen { // input simulation // // these methods must simulate the appropriate input event. - // these methods may only called on secondary screens. + // these methods are only called on secondary screens. // // keyboard input - // onKeyToggle() sets the keyboard toggle key states (e.g. num lock). - virtual void onKeyDown(KeyID) = 0; - virtual void onKeyRepeat(KeyID, SInt32 count) = 0; - virtual void onKeyUp(KeyID) = 0; - virtual void onKeyToggle(KeyToggleMask) = 0; + virtual void onKeyDown(KeyID, KeyModifierMask) = 0; + virtual void onKeyRepeat(KeyID, KeyModifierMask, SInt32 count) = 0; + virtual void onKeyUp(KeyID, KeyModifierMask) = 0; // mouse input virtual void onMouseDown(ButtonID) = 0; diff --git a/KeyTypes.h b/KeyTypes.h index c220a9fc..c3789fa1 100644 --- a/KeyTypes.h +++ b/KeyTypes.h @@ -4,15 +4,19 @@ // type to hold a key identifier typedef UInt32 KeyID; -// type to hold bitmask of keys that have toggle states -typedef UInt16 KeyToggleMask; - -// toggle key bitmasks -static const UInt32 KeyToggleShiftLock = 0x0001; -static const UInt32 KeyToggleNumLock = 0x0002; -static const UInt32 KeyToggleScrollLock = 0x0004; +// type to hold bitmask of key modifiers (i.e. shift keys) +typedef UInt32 KeyModifierMask; // key codes static const KeyID kKeyNone = 0; +// modifier key bitmasks +static const KeyModifierMask KeyModifierShift = 0x0001; +static const KeyModifierMask KeyModifierControl = 0x0002; +static const KeyModifierMask KeyModifierAlt = 0x0004; +static const KeyModifierMask KeyModifierMeta = 0x0008; +static const KeyModifierMask KeyModifierCapsLock = 0x1000; +static const KeyModifierMask KeyModifierNumLock = 0x2000; +static const KeyModifierMask KeyModifierScrollLock = 0x4000; + #endif