Для Windows:
Я не знаю ни одного приложения на моей голове, но вот некоторые идеи, которые могут работать в пределах 100 строк кода ...
Я бы избегал SetWindowsHook, так как это внедрило бы ваш код во все приложения. (Потому что я потратил много времени на отладку аварийных дампов и ошибок из-за плохо написанных хуков ...)
Вы можете написать консольное приложение с DirectInput (старый API игровой клавиатуры). Я полагаю, вы просто передаете DISCL_BACKGROUND и DISCL_NONEXCLUSIVE в вызов IDirectInputDevice8 :: SetCooperativeLevel. Используйте IDirectInputDevice8 :: SetEventNotification, чтобы установить дескриптор события, чтобы вы не попали в занятый цикл ожидания для ввода. И это должно сделать это. Я сделал это один раз для своего приложения давным-давно на Windows 98, и оно работало очень хорошо. Но DirectInput очень близок к устаревшей технологии, поэтому YMMV.
Еще один простой взломанный способ сделать то, что вы делаете, - это заставить ваше приложение создать скрытое окно, вызвать callHotkey для всей клавиатуры и прокачать сообщения окна. Ваш wndproc получит сообщение окна WM_HOTKEY, которое вы можете использовать для генерации сообщения на стандартный вывод.
Самый простой способ, но он будет немного подвержен ошибкам и дорогостоящему процессору - это заставить ваше консольное приложение войти в цикл и вызвать GetKeyboardState. Это вернет все состояние клавиатуры всех клавиш, которые находятся вверх и вниз. Вы должны выяснить, как перевести каждый опрос в логическое нажатие клавиши. Я бы посоветовал поспать несколько миллисекунд между опросами, чтобы не снизить производительность всей системы.
Не могу помочь вам в OSX.