How to connect / remap an arbitrary keyboard event on OSX?

I would like to map:

  • CAPS-LOCK to Fn
  • Fn left-MOUSE
  • LSHIFT + 3 to #
  • RSHIFT + 3 to something else
  • and etc.

I have searched exhaustively for any tool that offers complete freedom to reassign keyboard input but cannot find it. (Windows has an AutoHotkey).

I plan to write my own tool that analyzes the configuration file.

But how to really dig around and do it?

Solving this problem will require a deep understanding of the keypress path through the operating system in order to intercept the corresponding point.

I think I need to eat an event at a low level, where it is still a virtual key code, and then provide my own customized matching system and enter the corresponding event further than the system.

But where (and how)?

Edit: I will detail the results of my research in the answer below (which, perhaps, at some point should be brought back to the question).

+6
source share
2 answers

I am creating this community wiki, please welcome to improve it.

The subtasks that I asked:

I can catch almost all the keydown / keyup events at the bottom of the middle level. With the exception of power, as well as the CAPSLOCK key, when it goes from ON to OFF.

Pretty nasty!

Working at the lower level, I can get all the up / down keys except PowerKey.

If not for this uncomfortable 75% chance of success for CapsLock, I would have a good solution. It is unfortunate that key processing in such a useful place significantly increases the required complexity.

I found DDHidLib and am now looking through it to find out if this problem will be alleviated.

Study

Googling "keyEventWithType CGEventTapCreate" seems like a good idea, as they are important components for Tapping the event and Re-Emitting it.

Hooray! Change the output of keyDown - this code compiles with a minor tweak ( CGEventMaskBit( kCGEventKeyDown ) | CGEventMaskBit( kCGEventFlagsChanged ), ) I can also get modifier keys. I get different key codes for LSHIFT and RSHIFT. Brilliant!

Problems with the above:

  • Pressing kCGEventKeyDown works for some function keys, but not for others. It seems that Apple only overloads certain keys, while overloaded ones seem to fall to a lower level.
  • The Power / Eject button does not hit.
  • I don’t see a way to eliminate which device is pressing the key.

How to connect F7 via F12 and Power / Eject on a MacBook keyboard

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 may give some insight -> https://github.com/pkamb/PowerKey/blob/master/PowerKey/PKPowerKeyEventListener.m
-> Apple Keyboard Media Key Event Handling - Amoeba Rogue
... system shortcut for Mac OS X
-> http://snippets.aktagon.com/snippets/361-registering-global-hot-keys-with-cocoa-and-objective-c

Another problem: LSHIFT-down RSHIFT-down & up LSHIFT-up. RSHIFT events will not be caught.

Looks like I need to plunge into IOKit

Using IOHIDManager to Retrieve Key Modifier Events
-> 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 

Resources

3-level:

  • Cocoa / AppKit is a higher-level shell
  • Quartz accepts events from IOKit, routes them to applications

    Note: NSEvent is built on the Quartz event.

  • IOKit - talking with equipment

3-tier

Top Level (Cocoa / AppKit)

https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/EventOverview/EventArchitecture/EventArchitecture.html - This document is required and shows the basic 3-tier architecture above. However, it seems to focus only on the top level (Cocoa / AppKit).

http://www.hcs.harvard.edu/~jrus/Site/Cocoa%20Text%20System.html <- this article shows 3 OSX configuration files that work at an even higher level, allowing you to script your own mappings. This is described here .

^ KeyBindingsEditor allows you to make the above changes.

Intermediate Level (Quartz)

QuartzEventServicesRef

NSEvent - in particular Event Creation

A few examples of working code at this level. However, they all perform the same basic trick when receiving one virtual key code and emitting another. Thus, you can use this method, for example, to replace "a" and "z".

Intercepting keyboard input in OSX - results in Quartz event responses

Change NSEvent to send a different key than the one that was pressed - Dave De Long provides a working example, also using QET.

https://gist.github.com/wewearglasses/8313195 <- "Global Keyboard for OSX" is another short working demo using QET.

Ukelele lets you choose which Unicode to associate with a particular key or Modifier + key. It does not allow reassignment of modifiers, and also does not eliminate the ambiguity to the left of the right shift keys, etc.

Keyboard input in OSX - answer the addGlobalMonitorForEventsMatchingMask items in NSEvent (in AppKit)

Basic Level (IOKit)

IOKitFundamentals <- Also IOKit ("Handling interrupts in an I / O set ... Two types of trigger events interrupt: ... Asynchronous events, such as keystrokes")

https://developer.apple.com/library/mac/documentation/DeviceDrivers/Conceptual/AccessingHardware/AH_Other_APIs/AH_Other_APIs.html

How can Mac OS X games accept low-level keyboard input events? <- gamers are interested in this!

http://phrack.org/issues/66/16.html#article - sometimes hackers present things most clearly, have not read it yet. It seems IOKit seems again.


Additional links ...

How do you implement global keyboard interceptors on Mac OS X? <- links to the article.

OSX: Detect System-wide KeyDown Events? <- a bit of OT, because it's just for global monitoring, i.e. for reading.

http://www.codeitive.com/7QHSeVjPWq/where-can-i-find-kcgkeyboardeventkeycode-list-of-key-codes-for-cyrillic-language.html

+14
source

You checked Karabiner (which does everything you want to do .. before OSX 10.11 .. MacOS 10.12 changed the keyboard driver model, and the authors - mostly Tekezo- - still write Karabiner to accommodate the new model - this is from February 2017) Carabiner is open source, and you can download the code from Github and twiddle with it.

As part of the dubbing, they released carabiner elements that work on Sierra 12.12 but cannot yet do everything the carabiner did.

The carabiner is very powerful and I really miss 10.12

+1
source

Source: https://habr.com/ru/post/987429/


All Articles