[FEATURE] Implement `disableGlobalHotkeyRegister` option for keystroke conditions to allow apps on the primary client to respond to the keystroke without the OS blocking them
This commit is contained in:
parent
f38ab7d569
commit
903b34c32a
|
@ -155,8 +155,8 @@ public:
|
|||
// IPrimaryScreen overrides
|
||||
virtual void reconfigure(UInt32 activeSides) = 0;
|
||||
virtual void warpCursor(SInt32 x, SInt32 y) = 0;
|
||||
virtual UInt32 registerHotKey(KeyID key, KeyModifierMask mask) = 0;
|
||||
virtual void unregisterHotKey(UInt32 id) = 0;
|
||||
virtual UInt32 registerHotKey(KeyID key, KeyModifierMask mask, bool registerGlobalHotkey) = 0;
|
||||
virtual void unregisterHotKey(UInt32 id, bool unregisterGlobalHotkey) = 0;
|
||||
virtual void fakeInputBegin() = 0;
|
||||
virtual void fakeInputEnd() = 0;
|
||||
virtual SInt32 getJumpZoneSize() const = 0;
|
||||
|
|
|
@ -111,13 +111,13 @@ public:
|
|||
the modifiers in any order or to require the user to press the given key
|
||||
last.
|
||||
*/
|
||||
virtual UInt32 registerHotKey(KeyID key, KeyModifierMask mask) = 0;
|
||||
virtual UInt32 registerHotKey(KeyID key, KeyModifierMask mask, bool registerGlobalHotkey) = 0;
|
||||
|
||||
//! Unregister a system hotkey
|
||||
/*!
|
||||
Unregisters a previously registered hot key.
|
||||
*/
|
||||
virtual void unregisterHotKey(UInt32 id) = 0;
|
||||
virtual void unregisterHotKey(UInt32 id, bool unregisterGlobalHotkey) = 0;
|
||||
|
||||
//! Prepare to synthesize input on primary screen
|
||||
/*!
|
||||
|
|
|
@ -44,8 +44,8 @@ public:
|
|||
virtual void reconfigure(UInt32 activeSides) = 0;
|
||||
virtual void warpCursor(SInt32 x, SInt32 y) = 0;
|
||||
virtual UInt32 registerHotKey(KeyID key,
|
||||
KeyModifierMask mask) = 0;
|
||||
virtual void unregisterHotKey(UInt32 id) = 0;
|
||||
KeyModifierMask mask, bool registerGlobalHotkey) = 0;
|
||||
virtual void unregisterHotKey(UInt32 id, bool unregisterGlobalHotkey) = 0;
|
||||
virtual void fakeInputBegin() = 0;
|
||||
virtual void fakeInputEnd() = 0;
|
||||
virtual SInt32 getJumpZoneSize() const = 0;
|
||||
|
|
|
@ -330,15 +330,15 @@ Screen::setSequenceNumber(UInt32 seqNum)
|
|||
}
|
||||
|
||||
UInt32
|
||||
Screen::registerHotKey(KeyID key, KeyModifierMask mask)
|
||||
Screen::registerHotKey(KeyID key, KeyModifierMask mask, bool registerGlobalHotkey)
|
||||
{
|
||||
return m_screen->registerHotKey(key, mask);
|
||||
return m_screen->registerHotKey(key, mask, registerGlobalHotkey);
|
||||
}
|
||||
|
||||
void
|
||||
Screen::unregisterHotKey(UInt32 id)
|
||||
Screen::unregisterHotKey(UInt32 id, bool unregisterGlobalHotkey)
|
||||
{
|
||||
m_screen->unregisterHotKey(id);
|
||||
m_screen->unregisterHotKey(id, unregisterGlobalHotkey);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -198,13 +198,13 @@ public:
|
|||
Registers a system-wide hotkey for key \p key with modifiers \p mask.
|
||||
Returns an id used to unregister the hotkey.
|
||||
*/
|
||||
UInt32 registerHotKey(KeyID key, KeyModifierMask mask);
|
||||
UInt32 registerHotKey(KeyID key, KeyModifierMask mask, bool registerGlobalHotkey);
|
||||
|
||||
//! Unregister a system hotkey
|
||||
/*!
|
||||
Unregisters a previously registered hot key.
|
||||
*/
|
||||
void unregisterHotKey(UInt32 id);
|
||||
void unregisterHotKey(UInt32 id, bool unregisterGlobalHotkey);
|
||||
|
||||
//! Prepare to synthesize input on primary screen
|
||||
/*!
|
||||
|
|
|
@ -548,7 +548,7 @@ void MSWindowsScreen::saveMousePosition(SInt32 x, SInt32 y) {
|
|||
}
|
||||
|
||||
UInt32
|
||||
MSWindowsScreen::registerHotKey(KeyID key, KeyModifierMask mask)
|
||||
MSWindowsScreen::registerHotKey(KeyID key, KeyModifierMask mask, bool registerGlobalHotkey)
|
||||
{
|
||||
// only allow certain modifiers
|
||||
if ((mask & ~(KeyModifierShift | KeyModifierControl |
|
||||
|
@ -599,12 +599,12 @@ MSWindowsScreen::registerHotKey(KeyID key, KeyModifierMask mask)
|
|||
}
|
||||
|
||||
// if this hot key has modifiers only then we'll handle it specially
|
||||
bool err;
|
||||
bool err = false;
|
||||
if (key == kKeyNone) {
|
||||
// check if already registered
|
||||
err = (m_hotKeyToIDMap.count(HotKeyItem(vk, modifiers)) > 0);
|
||||
}
|
||||
else {
|
||||
else if (registerGlobalHotkey) {
|
||||
// register with OS
|
||||
err = (RegisterHotKey(NULL, id, modifiers, vk) == 0);
|
||||
}
|
||||
|
@ -625,7 +625,7 @@ MSWindowsScreen::registerHotKey(KeyID key, KeyModifierMask mask)
|
|||
}
|
||||
|
||||
void
|
||||
MSWindowsScreen::unregisterHotKey(UInt32 id)
|
||||
MSWindowsScreen::unregisterHotKey(UInt32 id, bool unregisterGlobalHotkey)
|
||||
{
|
||||
// look up hotkey
|
||||
HotKeyMap::iterator i = m_hotKeys.find(id);
|
||||
|
@ -634,13 +634,10 @@ MSWindowsScreen::unregisterHotKey(UInt32 id)
|
|||
}
|
||||
|
||||
// unregister with OS
|
||||
bool err;
|
||||
if (i->second.getVirtualKey() != 0) {
|
||||
bool err = false;
|
||||
if (unregisterGlobalHotkey && i->second.getVirtualKey() != 0) {
|
||||
err = !UnregisterHotKey(NULL, id);
|
||||
}
|
||||
else {
|
||||
err = false;
|
||||
}
|
||||
if (err) {
|
||||
LOG((CLOG_WARN "failed to unregister hotkey id=%d", id));
|
||||
}
|
||||
|
|
|
@ -80,8 +80,8 @@ public:
|
|||
virtual void reconfigure(UInt32 activeSides);
|
||||
virtual void warpCursor(SInt32 x, SInt32 y);
|
||||
virtual UInt32 registerHotKey(KeyID key,
|
||||
KeyModifierMask mask);
|
||||
virtual void unregisterHotKey(UInt32 id);
|
||||
KeyModifierMask mask, bool registerGlobalHotkey);
|
||||
virtual void unregisterHotKey(UInt32 id, bool unregisterGlobalHotkey);
|
||||
virtual void fakeInputBegin();
|
||||
virtual void fakeInputEnd();
|
||||
virtual SInt32 getJumpZoneSize() const;
|
||||
|
|
|
@ -68,8 +68,8 @@ public:
|
|||
// IPrimaryScreen overrides
|
||||
virtual void reconfigure(UInt32 activeSides);
|
||||
virtual void warpCursor(SInt32 x, SInt32 y);
|
||||
virtual UInt32 registerHotKey(KeyID key, KeyModifierMask mask);
|
||||
virtual void unregisterHotKey(UInt32 id);
|
||||
virtual UInt32 registerHotKey(KeyID key, KeyModifierMask mask, bool registerGlobalHotkey);
|
||||
virtual void unregisterHotKey(UInt32 id, bool unregisterGlobalHotkey);
|
||||
virtual void fakeInputBegin();
|
||||
virtual void fakeInputEnd();
|
||||
virtual SInt32 getJumpZoneSize() const;
|
||||
|
|
|
@ -315,7 +315,7 @@ OSXScreen::getCursorCenter(SInt32& x, SInt32& y) const
|
|||
}
|
||||
|
||||
UInt32
|
||||
OSXScreen::registerHotKey(KeyID key, KeyModifierMask mask)
|
||||
OSXScreen::registerHotKey(KeyID key, KeyModifierMask mask, bool registerGlobalHotkey)
|
||||
{
|
||||
// get mac virtual key and modifier mask matching barrier key and mask
|
||||
UInt32 macKey, macMask;
|
||||
|
@ -348,11 +348,13 @@ OSXScreen::registerHotKey(KeyID key, KeyModifierMask mask)
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (registerGlobalHotkey) {
|
||||
EventHotKeyID hkid = { 'SNRG', (UInt32)id };
|
||||
OSStatus status = RegisterEventHotKey(macKey, macMask, hkid,
|
||||
GetApplicationEventTarget(), 0,
|
||||
&ref);
|
||||
okay = (status == noErr);
|
||||
}
|
||||
m_hotKeyToIDMap[HotKeyItem(macKey, macMask)] = id;
|
||||
}
|
||||
|
||||
|
@ -370,7 +372,7 @@ OSXScreen::registerHotKey(KeyID key, KeyModifierMask mask)
|
|||
}
|
||||
|
||||
void
|
||||
OSXScreen::unregisterHotKey(UInt32 id)
|
||||
OSXScreen::unregisterHotKey(UInt32 id, bool unregisterGlobalHotkey)
|
||||
{
|
||||
// look up hotkey
|
||||
HotKeyMap::iterator i = m_hotKeys.find(id);
|
||||
|
@ -380,7 +382,7 @@ OSXScreen::unregisterHotKey(UInt32 id)
|
|||
|
||||
// unregister with OS
|
||||
bool okay;
|
||||
if (i->second.getRef() != NULL) {
|
||||
if (unregisterGlobalHotkey && i->second.getRef() != NULL) {
|
||||
okay = (UnregisterEventHotKey(i->second.getRef()) == noErr);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -524,7 +524,7 @@ XWindowsScreen::warpCursor(SInt32 x, SInt32 y)
|
|||
}
|
||||
|
||||
UInt32
|
||||
XWindowsScreen::registerHotKey(KeyID key, KeyModifierMask mask)
|
||||
XWindowsScreen::registerHotKey(KeyID key, KeyModifierMask mask, bool registerGlobalHotkey)
|
||||
{
|
||||
// only allow certain modifiers
|
||||
if ((mask & ~(KeyModifierShift | KeyModifierControl |
|
||||
|
@ -642,8 +642,10 @@ XWindowsScreen::registerHotKey(KeyID key, KeyModifierMask mask)
|
|||
for (int k = 0; k < modKeymap->max_keypermod && !err; ++k) {
|
||||
KeyCode code = modifiermap[k];
|
||||
if (modifiermap[k] != 0) {
|
||||
if (registerGlobalHotkey) {
|
||||
m_impl->XGrabKey(m_display, code, modifiers2, m_root,
|
||||
False, GrabModeAsync, GrabModeAsync);
|
||||
}
|
||||
if (!err) {
|
||||
hotKeys.push_back(std::make_pair(code, modifiers2));
|
||||
m_hotKeyToIDMap[HotKeyItem(code, modifiers2)] = id;
|
||||
|
@ -689,8 +691,10 @@ XWindowsScreen::registerHotKey(KeyID key, KeyModifierMask mask)
|
|||
}
|
||||
|
||||
// add grab
|
||||
if (registerGlobalHotkey) {
|
||||
m_impl->XGrabKey(m_display, *j, tmpModifiers, m_root,
|
||||
False, GrabModeAsync, GrabModeAsync);
|
||||
}
|
||||
if (!err) {
|
||||
hotKeys.push_back(std::make_pair(*j, tmpModifiers));
|
||||
m_hotKeyToIDMap[HotKeyItem(*j, tmpModifiers)] = id;
|
||||
|
@ -719,7 +723,7 @@ XWindowsScreen::registerHotKey(KeyID key, KeyModifierMask mask)
|
|||
}
|
||||
|
||||
void
|
||||
XWindowsScreen::unregisterHotKey(UInt32 id)
|
||||
XWindowsScreen::unregisterHotKey(UInt32 id, bool unregisterGlobalHotkey)
|
||||
{
|
||||
// look up hotkey
|
||||
HotKeyMap::iterator i = m_hotKeys.find(id);
|
||||
|
@ -734,7 +738,9 @@ XWindowsScreen::unregisterHotKey(UInt32 id)
|
|||
HotKeyList& hotKeys = i->second;
|
||||
for (HotKeyList::iterator j = hotKeys.begin();
|
||||
j != hotKeys.end(); ++j) {
|
||||
if (unregisterGlobalHotkey) {
|
||||
m_impl->XUngrabKey(m_display, j->first, j->second, m_root);
|
||||
}
|
||||
m_hotKeyToIDMap.erase(HotKeyItem(j->first, j->second));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,8 +53,8 @@ public:
|
|||
// IPrimaryScreen overrides
|
||||
virtual void reconfigure(UInt32 activeSides);
|
||||
virtual void warpCursor(SInt32 x, SInt32 y);
|
||||
virtual UInt32 registerHotKey(KeyID key, KeyModifierMask mask);
|
||||
virtual void unregisterHotKey(UInt32 id);
|
||||
virtual UInt32 registerHotKey(KeyID key, KeyModifierMask mask, bool registerGlobalHotkey);
|
||||
virtual void unregisterHotKey(UInt32 id, bool unregisterGlobalHotkey);
|
||||
virtual void fakeInputBegin();
|
||||
virtual void fakeInputEnd();
|
||||
virtual SInt32 getJumpZoneSize() const;
|
||||
|
|
|
@ -1029,13 +1029,19 @@ InputFilter::Condition* Config::parseCondition(ConfigReadContext& s, const std::
|
|||
const std::vector<std::string>& args)
|
||||
{
|
||||
if (name == "keystroke") {
|
||||
if (args.size() != 1) {
|
||||
throw XConfigRead(s, "syntax for condition: keystroke(modifiers+key)");
|
||||
if (args.size() < 1 || args.size() > 2) {
|
||||
throw XConfigRead(s, "syntax for condition: keystroke(modifiers+key[,options])");
|
||||
}
|
||||
|
||||
IPlatformScreen::KeyInfo* keyInfo = s.parseKeystroke(args[0]);
|
||||
bool disableGlobalHotkeyRegister = false;
|
||||
|
||||
return new InputFilter::KeystrokeCondition(m_events, keyInfo);
|
||||
if (args.size() > 1)
|
||||
{
|
||||
parseKeystrokeConditionOptions(s, args[1], disableGlobalHotkeyRegister);
|
||||
}
|
||||
|
||||
return new InputFilter::KeystrokeCondition(m_events, keyInfo, disableGlobalHotkeyRegister);
|
||||
}
|
||||
|
||||
if (name == "mousebutton") {
|
||||
|
@ -1293,6 +1299,19 @@ void Config::parseScreens(ConfigReadContext& c, const std::string& s,
|
|||
}
|
||||
}
|
||||
|
||||
void Config::parseKeystrokeConditionOptions(ConfigReadContext& c, const std::string& s,
|
||||
bool& disableGlobalHotkeyRegister) const
|
||||
{
|
||||
if (s == "disableGlobalHotkeyRegister")
|
||||
{
|
||||
disableGlobalHotkeyRegister = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
disableGlobalHotkeyRegister = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Config::parseKeystrokeActionOptions(ConfigReadContext& c, const std::string& s,
|
||||
bool& activeScreenOnly) const
|
||||
{
|
||||
|
|
|
@ -453,6 +453,7 @@ private:
|
|||
|
||||
void parseScreens(ConfigReadContext&, const std::string&, std::set<std::string>& screens) const;
|
||||
|
||||
void parseKeystrokeConditionOptions(ConfigReadContext& c, const std::string& s, bool& activeScreenOnly) const;
|
||||
void parseKeystrokeActionOptions(ConfigReadContext& c, const std::string& s, bool& activeScreenOnly) const;
|
||||
|
||||
static const char* getOptionName(OptionID);
|
||||
|
|
|
@ -53,21 +53,23 @@ InputFilter::Condition::disablePrimary(PrimaryClient*)
|
|||
}
|
||||
|
||||
InputFilter::KeystrokeCondition::KeystrokeCondition(
|
||||
IEventQueue* events, IPlatformScreen::KeyInfo* info) :
|
||||
IEventQueue* events, IPlatformScreen::KeyInfo* info, bool disableGlobalHotkeyRegister) :
|
||||
m_id(0),
|
||||
m_key(info->m_key),
|
||||
m_mask(info->m_mask),
|
||||
m_events(events)
|
||||
m_events(events),
|
||||
m_disableGlobalHotkeyRegister(disableGlobalHotkeyRegister)
|
||||
{
|
||||
free(info);
|
||||
}
|
||||
|
||||
InputFilter::KeystrokeCondition::KeystrokeCondition(
|
||||
IEventQueue* events, KeyID key, KeyModifierMask mask) :
|
||||
IEventQueue* events, KeyID key, KeyModifierMask mask, bool disableGlobalHotkeyRegister) :
|
||||
m_id(0),
|
||||
m_key(key),
|
||||
m_mask(mask),
|
||||
m_events(events)
|
||||
m_events(events),
|
||||
m_disableGlobalHotkeyRegister(disableGlobalHotkeyRegister)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
@ -92,7 +94,7 @@ InputFilter::KeystrokeCondition::getMask() const
|
|||
InputFilter::Condition*
|
||||
InputFilter::KeystrokeCondition::clone() const
|
||||
{
|
||||
return new KeystrokeCondition(m_events, m_key, m_mask);
|
||||
return new KeystrokeCondition(m_events, m_key, m_mask, m_disableGlobalHotkeyRegister);
|
||||
}
|
||||
|
||||
std::string InputFilter::KeystrokeCondition::format() const
|
||||
|
@ -131,13 +133,13 @@ InputFilter::KeystrokeCondition::match(const Event& event)
|
|||
void
|
||||
InputFilter::KeystrokeCondition::enablePrimary(PrimaryClient* primary)
|
||||
{
|
||||
m_id = primary->registerHotKey(m_key, m_mask);
|
||||
m_id = primary->registerHotKey(m_key, m_mask, !m_disableGlobalHotkeyRegister);
|
||||
}
|
||||
|
||||
void
|
||||
InputFilter::KeystrokeCondition::disablePrimary(PrimaryClient* primary)
|
||||
{
|
||||
primary->unregisterHotKey(m_id);
|
||||
primary->unregisterHotKey(m_id, !m_disableGlobalHotkeyRegister);
|
||||
m_id = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,8 +57,8 @@ public:
|
|||
// KeystrokeCondition
|
||||
class KeystrokeCondition : public Condition {
|
||||
public:
|
||||
KeystrokeCondition(IEventQueue* events, IPlatformScreen::KeyInfo*);
|
||||
KeystrokeCondition(IEventQueue* events, KeyID key, KeyModifierMask mask);
|
||||
KeystrokeCondition(IEventQueue* events, IPlatformScreen::KeyInfo*, bool disableGlobalHotkeyRegister);
|
||||
KeystrokeCondition(IEventQueue* events, KeyID key, KeyModifierMask mask, bool disableGlobalHotkeyRegister);
|
||||
virtual ~KeystrokeCondition();
|
||||
|
||||
KeyID getKey() const;
|
||||
|
@ -76,6 +76,7 @@ public:
|
|||
KeyID m_key;
|
||||
KeyModifierMask m_mask;
|
||||
IEventQueue* m_events;
|
||||
bool m_disableGlobalHotkeyRegister;
|
||||
};
|
||||
|
||||
// MouseButtonCondition
|
||||
|
|
|
@ -49,15 +49,15 @@ PrimaryClient::reconfigure(UInt32 activeSides)
|
|||
}
|
||||
|
||||
UInt32
|
||||
PrimaryClient::registerHotKey(KeyID key, KeyModifierMask mask)
|
||||
PrimaryClient::registerHotKey(KeyID key, KeyModifierMask mask, bool registerGlobalHotkey)
|
||||
{
|
||||
return m_screen->registerHotKey(key, mask);
|
||||
return m_screen->registerHotKey(key, mask, registerGlobalHotkey);
|
||||
}
|
||||
|
||||
void
|
||||
PrimaryClient::unregisterHotKey(UInt32 id)
|
||||
PrimaryClient::unregisterHotKey(UInt32 id, bool unregisterGlobalHotkey)
|
||||
{
|
||||
m_screen->unregisterHotKey(id);
|
||||
m_screen->unregisterHotKey(id, unregisterGlobalHotkey);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -55,13 +55,13 @@ public:
|
|||
Registers a system-wide hotkey for key \p key with modifiers \p mask.
|
||||
Returns an id used to unregister the hotkey.
|
||||
*/
|
||||
virtual UInt32 registerHotKey(KeyID key, KeyModifierMask mask);
|
||||
virtual UInt32 registerHotKey(KeyID key, KeyModifierMask mask, bool registerGlobalHotkey);
|
||||
|
||||
//! Unregister a system hotkey
|
||||
/*!
|
||||
Unregisters a previously registered hot key.
|
||||
*/
|
||||
virtual void unregisterHotKey(UInt32 id);
|
||||
virtual void unregisterHotKey(UInt32 id, bool unregisterGlobalHotkey);
|
||||
|
||||
//! Prepare to synthesize input on primary screen
|
||||
/*!
|
||||
|
|
|
@ -293,7 +293,7 @@ Server::setConfig(const Config& config)
|
|||
if (!m_config->hasLockToScreenAction()) {
|
||||
IPlatformScreen::KeyInfo* key =
|
||||
IPlatformScreen::KeyInfo::alloc(kKeyScrollLock, 0, 0, 0);
|
||||
InputFilter::Rule rule(new InputFilter::KeystrokeCondition(m_events, key));
|
||||
InputFilter::Rule rule(new InputFilter::KeystrokeCondition(m_events, key, true));
|
||||
rule.adoptAction(new InputFilter::LockCursorToScreenAction(m_events), true);
|
||||
m_inputFilter->addFilterRule(rule);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue