Using CGEventTapCreate instead of addGlobalMonitorForEventsMatchingMask
to listen to global hotkeys has the advantage of tighter control over
what permissions we need. Since we only listen to and do not modify the
event, it is enough to have "Input Monitoring" instead of the full
"Accessibility" (which would allow modifying the event after catching
it).
Per the documentation of CFStringGetCString, the buffer provided must be
large enough not just for the string itself, but also for a NUL
terminator. This space for the NUL terminator is currently ignored, and
we just get lucky that CFStringGetMaximumSizeForEncoding often
dramatically overestimates the space required. However, it is possible
to actually hit the maximum with the string itself (for example by using
strings that contain exclusively Chinese characters such as "我"), in
which case the conversion fails. Adding the extra byte for the NUL
terminator fixes this.
At this point, we can also safely assert that our max_size is larger
than zero, silencing a clang analyzer warning that now is no longer
valid.
Cleans up the source code by sorting functions by topic and also
removes macros for hotkey implementation, removing the need to disable
compiler warnings.
Key codes and descriptions are now contained in arrays which either
use the OBS key code or the macOS key code as lookup keys with all
necessary context information directly associated with the key.
The implementation also uses the zero-initialization rule for arrays
of structs in such a way that the struct's "is_valid" boolean is
"false" by default so that only values explicitly initialized with a
key are ever "valid".
To avoid a mismatch between the state of pressed keys as held by the
hotkey thread and keys pressed while the application is in focus, local
key events need to be monitored as well (even though they are already
handled by Cocoa's main event loop).
Also remove use of deprecated [NSProcessInfo operatingSystem]. It always
returns the NSMACHOperatingSystem.
Also stop parsing [NSProcessInfo operatingSystemVersionString]. The
documentation explicitly says "not for parsing".
On 10.15, if a user activates secure input of some sort, the hotkey code
will begin to crash inside of any Apple function related to hotkeys,
even after secure input has ended. This does not appear to be the fault
of OBS; the reason to this is still as of yet unknown, but is suspected
to be a bug inside of Apple code that's a new regression as of 10.15.
So for the time being as a temporary solution to the crash, simply
disable external hotkey support once secure input has been detected.
Because of this issue, the hotkey code should probably be replaced by a
different method of tracking hotkeys, perhaps InstallEventHandler for
example. This commit is little more than a bandaid to the crash.