diff --git a/src/lib/barrier/IKeyState.cpp b/src/lib/barrier/IKeyState.cpp index e89c0e9d..f4766073 100644 --- a/src/lib/barrier/IKeyState.cpp +++ b/src/lib/barrier/IKeyState.cpp @@ -43,6 +43,7 @@ IKeyState::KeyInfo::alloc(KeyID id, info->m_mask = mask; info->m_button = button; info->m_count = count; + info->m_activeScreenOnly = false; info->m_screens = NULL; info->m_screensBuffer[0] = '\0'; return info; @@ -51,7 +52,7 @@ IKeyState::KeyInfo::alloc(KeyID id, IKeyState::KeyInfo* IKeyState::KeyInfo::alloc(KeyID id, KeyModifierMask mask, KeyButton button, SInt32 count, - const std::set& destinations) + const std::set& destinations, bool activeScreenOnly) { String screens = join(destinations); @@ -61,6 +62,7 @@ IKeyState::KeyInfo::alloc(KeyID id, info->m_mask = mask; info->m_button = button; info->m_count = count; + info->m_activeScreenOnly = activeScreenOnly; info->m_screens = info->m_screensBuffer; strcpy(info->m_screensBuffer, screens.c_str()); return info; @@ -75,6 +77,7 @@ IKeyState::KeyInfo::alloc(const KeyInfo& x) info->m_mask = x.m_mask; info->m_button = x.m_button; info->m_count = x.m_count; + info->m_activeScreenOnly = x.m_activeScreenOnly; info->m_screens = x.m_screens ? info->m_screensBuffer : NULL; strcpy(info->m_screensBuffer, x.m_screensBuffer); return info; diff --git a/src/lib/barrier/IKeyState.h b/src/lib/barrier/IKeyState.h index e7f88fa9..0f5bc70f 100644 --- a/src/lib/barrier/IKeyState.h +++ b/src/lib/barrier/IKeyState.h @@ -44,7 +44,7 @@ public: public: static KeyInfo* alloc(KeyID, KeyModifierMask, KeyButton, SInt32 count); static KeyInfo* alloc(KeyID, KeyModifierMask, KeyButton, SInt32 count, - const std::set& destinations); + const std::set& destinations, bool activeScreenOnly); static KeyInfo* alloc(const KeyInfo&); static bool isDefault(const char* screens); @@ -58,6 +58,7 @@ public: KeyModifierMask m_mask; KeyButton m_button; SInt32 m_count; + bool m_activeScreenOnly; char* m_screens; char m_screensBuffer[1]; }; diff --git a/src/lib/server/Config.cpp b/src/lib/server/Config.cpp index bcdb88cd..86568b80 100644 --- a/src/lib/server/Config.cpp +++ b/src/lib/server/Config.cpp @@ -1074,8 +1074,8 @@ void Config::parseAction(ConfigReadContext& s, const std::string& name, InputFilter::Action* action; if (name == "keystroke" || name == "keyDown" || name == "keyUp") { - if (args.size() < 1 || args.size() > 2) { - throw XConfigRead(s, "syntax for action: keystroke(modifiers+key[,screens])"); + if (args.size() < 1 || args.size() > 3) { + throw XConfigRead(s, "syntax for action: keystroke(modifiers+key[,screens[,options]])"); } IPlatformScreen::KeyInfo* keyInfo; @@ -1085,7 +1085,12 @@ void Config::parseAction(ConfigReadContext& s, const std::string& name, else { std::set screens; parseScreens(s, args[1], screens); - keyInfo = s.parseKeystroke(args[0], screens); + bool activeScreenOnly = false; + if (args.size() > 2) + { + parseKeystrokeActionOptions(s, args[2], activeScreenOnly); + } + keyInfo = s.parseKeystroke(args[0], screens, activeScreenOnly); } if (name == "keystroke") { @@ -1288,6 +1293,19 @@ void Config::parseScreens(ConfigReadContext& c, const std::string& s, } } +void Config::parseKeystrokeActionOptions(ConfigReadContext& c, const std::string& s, + bool& activeScreenOnly) const +{ + if (s == "activeScreenOnly") + { + activeScreenOnly = true; + } + else + { + activeScreenOnly = false; + } +} + const char* Config::getOptionName(OptionID id) { @@ -2184,6 +2202,13 @@ IPlatformScreen::KeyInfo* ConfigReadContext::parseKeystroke(const std::string& k IPlatformScreen::KeyInfo* ConfigReadContext::parseKeystroke(const std::string& keystroke, const std::set& screens) const +{ + return parseKeystroke(keystroke, screens, false); +} + +IPlatformScreen::KeyInfo* ConfigReadContext::parseKeystroke(const std::string& keystroke, + const std::set& screens, + const bool& activeScreenOnly) const { std::string s = keystroke; @@ -2201,7 +2226,7 @@ IPlatformScreen::KeyInfo* ConfigReadContext::parseKeystroke(const std::string& k throw XConfigRead(*this, "missing key and/or modifiers in keystroke"); } - return IPlatformScreen::KeyInfo::alloc(key, mask, 0, 0, screens); + return IPlatformScreen::KeyInfo::alloc(key, mask, 0, 0, screens, activeScreenOnly); } IPlatformScreen::ButtonInfo* diff --git a/src/lib/server/Config.h b/src/lib/server/Config.h index 17756a0a..49fd548e 100644 --- a/src/lib/server/Config.h +++ b/src/lib/server/Config.h @@ -453,6 +453,8 @@ private: void parseScreens(ConfigReadContext&, const std::string&, std::set& screens) const; + void parseKeystrokeActionOptions(ConfigReadContext& c, const std::string& s, bool& activeScreenOnly) const; + static const char* getOptionName(OptionID); static std::string getOptionValue(OptionID, OptionValue); @@ -497,6 +499,9 @@ public: IPlatformScreen::KeyInfo* parseKeystroke(const std::string& keystroke) const; IPlatformScreen::KeyInfo* parseKeystroke(const std::string& keystroke, const std::set& screens) const; + IPlatformScreen::KeyInfo* parseKeystroke(const std::string& keystroke, + const std::set& screens, + const bool& activeScreenOnly) const; IPlatformScreen::ButtonInfo* parseMouse(const std::string& mouse) const; KeyModifierMask parseModifier(const std::string& modifiers) const; diff --git a/src/lib/server/PrimaryClient.cpp b/src/lib/server/PrimaryClient.cpp index 6583e5d2..7e052749 100644 --- a/src/lib/server/PrimaryClient.cpp +++ b/src/lib/server/PrimaryClient.cpp @@ -187,11 +187,7 @@ void PrimaryClient::keyDown(KeyID key, KeyModifierMask mask, KeyButton button) { if (m_fakeInputCount > 0) { -// XXX -- don't forward keystrokes to primary screen for now - (void)key; - (void)mask; - (void)button; -// m_screen->keyDown(key, mask, button); + m_screen->keyDown(key, mask, button); } } @@ -205,11 +201,7 @@ void PrimaryClient::keyUp(KeyID key, KeyModifierMask mask, KeyButton button) { if (m_fakeInputCount > 0) { -// XXX -- don't forward keystrokes to primary screen for now - (void)key; - (void)mask; - (void)button; -// m_screen->keyUp(key, mask, button); + m_screen->keyUp(key, mask, button); } } diff --git a/src/lib/server/Server.cpp b/src/lib/server/Server.cpp index a169db16..5dde031f 100644 --- a/src/lib/server/Server.cpp +++ b/src/lib/server/Server.cpp @@ -1285,7 +1285,9 @@ Server::handleKeyDownEvent(const Event& event, void*) { IPlatformScreen::KeyInfo* info = static_cast(event.getData()); - onKeyDown(info->m_key, info->m_mask, info->m_button, info->m_screens); + onKeyDown(info->m_key, info->m_mask, info->m_button, + info->m_screens, + info->m_activeScreenOnly); } void @@ -1293,7 +1295,9 @@ Server::handleKeyUpEvent(const Event& event, void*) { IPlatformScreen::KeyInfo* info = static_cast(event.getData()); - onKeyUp(info->m_key, info->m_mask, info->m_button, info->m_screens); + onKeyUp(info->m_key, info->m_mask, info->m_button, + info->m_screens, + info->m_activeScreenOnly); } void @@ -1630,7 +1634,7 @@ Server::onScreensaver(bool activated) void Server::onKeyDown(KeyID id, KeyModifierMask mask, KeyButton button, - const char* screens) + const char* screens, bool activeScreenOnly) { LOG((CLOG_DEBUG1 "onKeyDown id=%d mask=0x%04x button=0x%04x", id, mask, button)); assert(m_active != NULL); @@ -1639,6 +1643,15 @@ Server::onKeyDown(KeyID id, KeyModifierMask mask, KeyButton button, if (!m_keyboardBroadcasting && IKeyState::KeyInfo::isDefault(screens)) { m_active->keyDown(id, mask, button); } + else if (activeScreenOnly) { + auto activeName = m_active->getName(); + if (IKeyState::KeyInfo::contains(screens, activeName)) { + // This won't work on the primary client if the action has the same keystroke as the condition. + // Unlike other clients, the primary client registers the original keystroke with the OS as a hotkey to block + // other apps from handling them, which also stops Barrier from being able to create a fake event for them. + m_active->keyDown(id, mask, button); + } + } else { if (!screens && m_keyboardBroadcasting) { screens = m_keyboardBroadcastingScreens.c_str(); @@ -1657,7 +1670,7 @@ Server::onKeyDown(KeyID id, KeyModifierMask mask, KeyButton button, void Server::onKeyUp(KeyID id, KeyModifierMask mask, KeyButton button, - const char* screens) + const char* screens, bool activeScreenOnly) { LOG((CLOG_DEBUG1 "onKeyUp id=%d mask=0x%04x button=0x%04x", id, mask, button)); assert(m_active != NULL); @@ -1666,6 +1679,15 @@ Server::onKeyUp(KeyID id, KeyModifierMask mask, KeyButton button, if (!m_keyboardBroadcasting && IKeyState::KeyInfo::isDefault(screens)) { m_active->keyUp(id, mask, button); } + else if (activeScreenOnly) { + auto activeName = m_active->getName(); + if (IKeyState::KeyInfo::contains(screens, activeName)) { + // This won't work on the primary client if the action has the same keystroke as the condition. + // Unlike other clients, the primary client registers the original keystroke with the OS as a hotkey to block + // other apps from handling them, which also stops Barrier from being able to create a fake event for them. + m_active->keyUp(id, mask, button); + } + } else { if (!screens && m_keyboardBroadcasting) { screens = m_keyboardBroadcastingScreens.c_str(); diff --git a/src/lib/server/Server.h b/src/lib/server/Server.h index ae8b2bd5..2a234bd4 100644 --- a/src/lib/server/Server.h +++ b/src/lib/server/Server.h @@ -322,9 +322,9 @@ private: ClipboardID id, UInt32 seqNum); void onScreensaver(bool activated); void onKeyDown(KeyID, KeyModifierMask, KeyButton, - const char* screens); + const char* screens, bool activeScreenOnly); void onKeyUp(KeyID, KeyModifierMask, KeyButton, - const char* screens); + const char* screens, bool activeScreenOnly); void onKeyRepeat(KeyID, KeyModifierMask, SInt32, KeyButton); void onMouseDown(ButtonID); void onMouseUp(ButtonID);