Как перехватить / переназначить произвольное событие клавиатуры на OSX?
Я хотел бы на карту:
- CAPS-LOCK для Fn
- Fn влево-мышь
- LSHIFT+3 к #
- RSHIFT+3 к чему-то еще
- и т.п.
Я тщательно искал любой инструмент, который предлагает полную свободу для переназначения ввода с клавиатуры, но не могу найти. (В Windows есть AutoHotkey).
Я планирую написать свой собственный инструмент, который анализирует файл конфигурации.
Но как на самом деле копаться и делать это?
Решение этой проблемы потребует тщательного понимания прохождения нажатия клавиш в операционной системе, чтобы перехватить его в соответствующей точке.
Я думаю, что мне нужно съесть событие на низком уровне, где он все еще является кодом виртуального ключа, а затем предоставить собственную настраиваемую систему сопоставления и внедрить соответствующее событие в систему.
Но где (и как)?
Изменить: я подробно излагаю результаты моего исследования в ответе ниже (который может быть перенесен обратно в вопрос в какой-то момент).
2 ответа
Я делаю это сообщество вики, пожалуйста, не стесняйтесь его улучшать.
Подвопросы, которые я задал:
- Заставьте SHIFT+3 производить `#` не `£` на OSX по коду
- Как нажать (подключить) F7 через F12 и Power/Eject на клавиатуре MacBook
- Как нажать / перехватить события клавиатуры в OSX и записать, какая клавиатура запускает каждое событие
-> https://github.com/Daij-Djan/DDHidLib - Ловушка каждой клавиши SHIFT независимо от OS X
- В OSX, как определить, какая клавиатура сгенерировала NSEvent?
Я могу перехватить почти все события keydown / keyup в нижней части среднего уровня. За исключением питания, а также нажатия клавиши CAPSLOCK при переходе из ON в OFF.
Довольно противно!
Работая на нижнем уровне, я могу получить все ключи вверх / вниз, кроме PowerKey.
Если бы не этот неуклюжий показатель успеха 75% для CapsLock, у меня было бы хорошее решение. Досадно, что обработка ключа в таком полезном месте значительно увеличивает необходимую сложность.
Я нашел DDHidLib и в настоящее время просматриваю его, чтобы выяснить, сглаживает ли он эту проблему.
Исследование
Поиск в Google "keyEventWithType CGEventTapCreate" кажется хорошей идеей, поскольку они являются важными компонентами для прослушивания события и его повторной отправки.
Ура! Изменить вывод keyDown - этот код компилируется и с незначительными изменениями (CGEventMaskBit( kCGEventKeyDown ) | CGEventMaskBit( kCGEventFlagsChanged ),
) Я также могу подобрать клавиши-модификаторы. Я получаю разные коды клавиш для LSHIFT и RSHIFT. Brilliant!
Проблемы с вышесказанным:
- Нажатие kCGEventKeyDown работает для некоторых функциональных клавиш, но не для других. Похоже, что Apple перегружает только определенные ключи, а перегруженные, похоже, попадают на более низкий уровень.
- Клавиша Power/Eject не попадает.
- Я не вижу никакого способа однозначно определить, от какого устройства исходит нажатие клавиши.
Как нажать (подключить) F7 через F12 и Power/Eject на клавиатуре MacBook
http://blog.tklee.org/2008/09/modifiers-across-keyboards.html
-> http://forums.macrumors.com/showthread.php?t=778484
-> https://github.com/maravillas/dual-keyboards
https://github.com/pkamb/PowerKey может дать некоторое представление
-> https://github.com/pkamb/PowerKey/blob/master/PowerKey/PKPowerKeyEventListener.m
-> Обработка событий клавиатуры Apple Keyboard - Rogue Amoeba
... общесистемный ярлык для Mac OS X
-> http://snippets.aktagon.com/snippets/361-registering-global-hot-keys-with-cocoa-and-objective-c
Еще одна проблема: LSHIFT-вниз RSHIFT-вниз и вверх LSHIFT-вверх. События RSHIFT не будут пойманы.
Похоже, мне нужно окунуться в IOKit
Использование IOHIDManager для получения событий ключа модификатора
-> https://github.com/candera/khordr/blob/master/src/c/keygrab/hid-scratch.c
kEventRawKeyDown in:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/
Developer/SDKs/MacOSX10.10.sdk/System/Library/
Frameworks//Carbon.framework/Frameworks/HIToolbox.framework/
Headers/CarbonEvents.h
Ресурсы
3-х уровневая:
- Cocoa / AppKit - это оболочка более высокого уровня
Кварц берет события из IOKit направляет их в приложения
Примечание: NSEvent построен на Quartz EventIOKit - общается с оборудованием
Top Tier (Какао / AppKit)
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/EventOverview/EventArchitecture/EventArchitecture.html - этот документ является обязательным для просмотра и показывает вышеуказанную базовую трехуровневую архитектуру рис. Однако, похоже, что он фокусируется только на верхнем уровне (Cocoa / AppKit).
http://www.hcs.harvard.edu/~jrus/Site/Cocoa%20Text%20System.html <- в этой статье показаны 3 файла конфигурации OSX, которые работают на еще более высоком уровне и позволяют создавать собственные сопоставления. Это задокументировано здесь.
^ KeyBindingsEditor позволяет вам сделать вышеуказанные изменения.
Средний Ярус (Кварц)
NSEvent - специально создание событий
Пара рабочих примеров кода на этом уровне. Однако все они выполняют один и тот же основной прием: получают один код виртуального ключа и излучают другой. Таким образом, вы можете использовать эту технику, например, чтобы поменять местами "a" и "z".
Перехватывать ввод с клавиатуры в OSX - приводит к прослушиванию кварцевых событий
Измените NSEvent, чтобы посылать клавишу, отличную от той, которая была нажата - Дейв Де Лонг (Dave De Long) предоставляет рабочий пример, также используя QET.
https://gist.github.com/wewearglasses/8313195 <- "Глобальная клавиатура хук для OSX" - еще одна короткая рабочая демонстрация с использованием QET.
Ukelele позволяет вам выбрать, какой Unicode ассоциируется с определенным ключом или клавишей Modifier+. Не разрешает переназначение модификаторов, а также не устраняет неоднозначность влево от правых клавиш Shift и т. Д.
Ввод с клавиатуры в OSX - ответ указывает на addGlobalMonitorForEventsMatchingMask
в NSEvent (в AppKit)
Базовый уровень (IOKit)
IOKitFundamentals <- Также IOKit ("Обработка прерываний в наборе ввода-вывода... Два типа событий инициируют прерывание:... Асинхронные события, такие как нажатия клавиш")
Как игры для Mac OS X могут получать события ввода с клавиатуры низкого уровня? <- геймеры заинтересованы в этом!
http://phrack.org/issues/66/16.html - иногда хакеры представляют вещи наиболее четко, еще не прочитав это. IOKit снова, кажется.
Больше ссылок...
Как вы реализуете глобальные зацепки клавиатуры в Mac OS X? <- ссылки на статью.
OSX: обнаруживать общесистемные события keyDown? <- немного ОТ, так как это связано только с глобальным мониторингом, то есть только для чтения.
Вы проверили Karabiner (который делает все, что вы хотите сделать... до OSX 10.11 ... MacOS 10.12 изменил модель драйвера клавиатуры, и авторы - в основном Tekezo- все еще переписывают Karabiner, чтобы учесть новую модель - это по состоянию на февраль 2017 года) Karabiner имеет открытый исходный код, и вы можете скачать код с Github и использовать его.
В рамках переписывания они выпустили элементы Karabiner, которые работают на 10.12 Sierra, но пока не могут сделать все, что сделал карабинер.
Карабинер очень мощный, и я очень скучаю по нему 10.12