| 150 | } |
| 151 | |
| 152 | bool KeyPressCatcher::init() |
| 153 | { |
| 154 | CGEventMask modifiersPressedMask = CGEventMaskBit(kCGEventFlagsChanged); |
| 155 | |
| 156 | m_eventTapPtr = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, modifiersPressedMask, |
| 157 | [] (CGEventTapProxy, CGEventType type, CGEventRef event, void *keyPressCatcherRawPtr) |
| 158 | { |
| 159 | auto catcher = static_cast<KeyPressCatcher *>(keyPressCatcherRawPtr); |
| 160 | CGEventFlags flags = CGEventGetFlags(event); |
| 161 | auto secondTriggerKey = catcher->getSecondShortcutKey(); |
| 162 | // Checking whether a second key that we expected (depending on configuration) was pressed |
| 163 | auto second_key_pressed_down = ((secondTriggerKey == CS::SecondShortcutKeyEnum::GlobalFN && flags & kCGEventFlagMaskSecondaryFn) || |
| 164 | (secondTriggerKey == CS::SecondShortcutKeyEnum::Control && flags & kCGEventFlagMaskControl) || |
| 165 | (secondTriggerKey == CS::SecondShortcutKeyEnum::Option && flags & kCGEventFlagMaskAlternate) || |
| 166 | (secondTriggerKey == CS::SecondShortcutKeyEnum::Command && flags & kCGEventFlagMaskCommand) || |
| 167 | (secondTriggerKey == CS::SecondShortcutKeyEnum::Nothing)); |
| 168 | |
| 169 | // If Shift and second key were pressed (released) |
| 170 | catcher->handleModifierKeysStatusChange((flags & kCGEventFlagMaskShift), second_key_pressed_down); |
| 171 | return event; |
| 172 | }, this); |
| 173 | |
| 174 | if (m_eventTapPtr == nullptr) |
| 175 | { |
| 176 | return false; |
| 177 | } |
| 178 | |
| 179 | CFRunLoopAddSource(CFRunLoopGetCurrent(), |
| 180 | CFMachPortCreateRunLoopSource(kCFAllocatorDefault, m_eventTapPtr, 0), |
| 181 | kCFRunLoopCommonModes); |
| 182 | |
| 183 | CGEventTapEnable(m_eventTapPtr, true); |
| 184 | return true; |
| 185 | } |
nothing calls this directly
no test coverage detected