Hammerspoon / hammerspoon

Staggeringly powerful macOS desktop automation with Lua
http://www.hammerspoon.org
MIT License
11.9k stars 578 forks source link

Is it possible to disable the internal keyboard and keep the external keyboard enable? #2643

Closed LvChengbin closed 3 years ago

LvChengbin commented 3 years ago

I am a newcomer of using hammerspoon and lua script. With the API provided by hammerspoon, is it possible to disable the internal keyboard of mackbook but keep the external keyboard enable?

dasmurphy commented 3 years ago

You may try to check https://www.hammerspoon.org/docs/hs.eventtap.event.html#properties

There is a keyboardEventKeyboardType property. I don't know if this helps, but it may be an indicator for a solution. For me it displays different values between my internal and bluetooth keyboard.

I used for displaying the values in a keyDownHandler

table.print({event:getProperty(hs.eventtap.event.properties.keyboardEventKeyboardType)})
LvChengbin commented 3 years ago

@dasmurphy Thank you for your reply. I got the number 40 and 88 with different keyboards. Shall I select the internal keyboard with the numbers? I didn't find any documents to tell how to use the numbers.

asmagill commented 3 years ago

This is the extent of the documentation provided by the macOS SDK:

kCGKeyboardEventKeyboardType
Key to access an integer field that contains the keyboard type identifier.

Declaration

kCGKeyboardEventKeyboardType = 10
Availability

Mac Catalyst 13.0+
macOS 10.4+

So, we don't have a lookup table for what numbers refer to which types... googling may help.

It's probably reasonable that the type reported for your internal keyboard wont' be used by anything else, so if all you're trying to do is determine if the input came from the internal keyboard or "something else", it should be sufficient to match on that property value.

As I recall, a couple of years ago someone wanted to distinguish key events from which usb keyboard they had attached, and if memory serves, I don't think we ever did find a reliable solution for that; in your case, however, the internal keyboard should remain unique (though the exact number may differ on different models, I would still expect it to be distinct from external USB or external BlueTooth, though in fairness, I haven't actually tested this).

MuhammedZakir commented 3 years ago

It's probably reasonable that the type reported for your internal keyboard wont' be used by anything else, [...]

Unfortunately, that's not the case. I am getting same number for both my internal keyboard and external USB keyboard.

After looking around, I found that kCGKeyboardEventKeyboardType is used to get the layout of keyboard.

  1. https://stackoverflow.com/a/18413469 : LMGetKbdType() == kCGKeyboardEventKeyboardType (?)

    • I am not sure if this is true, because I got different numbers. However, calling KBGetLayoutType(<number>) returned same result - ANSI.
  2. https://developer.apple.com/documentation/coreservices/1390584-uckeytranslate:

    keyboardType

    An unsigned 32-bit integer. Pass a value specifying the physical keyboard type (that is, the keyboard shape shown by Key Caps). You can call the function LMGetKbdType for this value. (see bottom)

  3. https://github.com/microsoft/vscode/issues/26506#issuecomment-301034336 : KBGetLayoutType(LMGetKbdType()) is used to identify keyboard layout - ANSI or ISO.


An interesting find is this [1] which led to a very old tech note [2]. See "Using Macintosh KCAP resource to draw a keyboard" in that doc.

[1] https://web.archive.org/web/20190412132800/http://www.justskins.com/forums/lmgetkbdtype-148232.html [2] https://developer.apple.com/library/archive/technotes/te/te_515.html#//apple_ref/doc/uid/DTS10002838

LvChengbin commented 3 years ago

Thank you guys, I used https://github.com/pqrs-org/Karabiner-Elements to disable the internal keyboard before, but it causes some problems with Apple M1, so I need to find out another way for doing this. Maybe I can try looking for the way how Karabiner-Elements implements this feature. Fortunately, I can use keyboardEventKeyboardType to distinguish the MBP internal keyboard and the external keyboard I am using now, so I will implement it with keyboardEventKeyboardType property before finding out a better way.

asmagill commented 3 years ago

@MuhammedZakir so you're suggesting it's more like a layout or nationalization specifier? Well, it sounds like for @LvChengbin's purposes it might be enough, but it would be nice to be able to document more specifically.

There are things that Karabiner-Elements can do that we can't, largely because we avoid requiring elevated privileges (root) or require a KEXT or other system level driver be installed, but in some cases just because it hasn't come up yet... let us know what you find.

MuhammedZakir commented 3 years ago

@MuhammedZakir so you're suggesting it's more like a layout or nationalization specifier? Well, it sounds like for @LvChengbin's purposes it might be enough, but it would be nice to be able to document more specifically.

That's what I understood. It's not layout identifier per se because to actually identify the layout, one would have to call KBGetLayoutType(<keyboardType>). But, you could consider it as one.

If LMGetKbdType() is the same as kCGKeyboardEventKeyboardType, then the the the closest definition (from Apple doc) is physical keyboard type (that is, the keyboard shape shown by Key Caps) [1]. However, what exactly that represents, I am not sure. We would have to test with a few different keyboards to know what exactly "keyboard type" represents.

[1] https://developer.apple.com/documentation/coreservices/1390584-uckeytranslate


@dasmurphy, @LvChengbin : you got different keyboardType codes, right? Can you please tell these?

  1. keyboards you use.
  2. keyboardEventKeyboardType values.
  3. whether the keyboards are ISO, ANSI or JIS (or something else?).
LvChengbin commented 3 years ago

@MuhammedZakir I tried two HHKBs, the keyboardEventKeyboardType values are 40 while using ANSI layout, and it is 41 in ISO layout and 42 in JIS layout.

The macbook's internal keyboard's keyboardEventKeyboardType value is 88.

koekeishiya commented 3 years ago

If you want a non-hammerspoon solution the following ~35 line program uses IOKit to intercept and void all keys from a given device. Device identifier is specified at line 32 and can be found by looking up the internal keyboard in the System Information application.

https://github.com/koekeishiya/disable_internal_keyboard/blob/master/src/main.c

cmsj commented 3 years ago

I'm going to close this issue because I don't think we will ever support disabling keyboards - it's something that needs to happen at a much lower level than we operate. It could perhaps be hacked together with an eventtap, but overall I think it's a job better left to more specialised tools like Karabiner Elements.