fnesveda / ExternalDisplayBrightness

A Mac app to control the brightness of external displays using keyboard shortcuts
https://www.nesveda.com/projects/ExternalDisplayBrightness/
MIT License
378 stars 17 forks source link

Brightness keys on Logitech MX Keys not working #8

Open NiknakSi opened 4 years ago

NiknakSi commented 4 years ago

On the Logitech MX Keys keyboard, which has a very similar layout to a Mac keyboard, the screen brightness keys are not working. As normal function keys they trigger brightness down/up but not when used with the Fn key. I've tried using the MK_BDN and MK_BUP options but no luck. I've also tried the playground from this previously closed issue - https://github.com/fnesveda/ExternalDisplayBrightness/issues/1 - but nothing in the output.

Any ideas?

fnesveda commented 4 years ago

Hi,

I'm not sure if the brightness keys (or any special keys) from Logitech keyboards are sent as regular keycodes, but if they are, it should be fairly easy to add support for them. Could you please try using the Key Codes app to see what, if any, keycodes are generated by the brightness keys?

Thanks!

NiknakSi commented 4 years ago

Nothing registered by Key Codes unfortunately. I'm not sure how the other keys are doing their job (e.g. for mission control, volume, etc), perhaps the Logitech software is issuing system commands some other way?

fnesveda commented 4 years ago

I'm afraid so. Do you have to have some additional software installed for the special keys like Mission Control to work, or do they work out of the box?

I was thinking about buying the MX Keys myself one day, if I do, I'll try to get to the bottom of this.

NiknakSi commented 4 years ago

Yes I have Logitech Options installed, but I was fairly sure the keys worked before I installed it. I just tried it on my Macbook but forgot that also already has Options installed for a mouse. If I get a chance I'll uninstall the software and test again.

fnesveda commented 4 years ago

Hi,

I've been looking into this a bit again, would you mind testing this new playground to see if it produces any output when you press the brightness keys?

Thanks!

NiknakSi commented 4 years ago

Success! A keypress of Fn+F1 and Fn+F2 (brightness down and up respectively) yields the following:

NSEvent: type=SysDefined loc=(311.855,276.375) time=39836.3 flags=0x20800000 win=0x0 winNum=0 ctxt=0x0 subtype=6 data1=100107 data2=0
NSEvent: type=SysDefined loc=(311.855,276.375) time=39836.3 flags=0x20800000 win=0x0 winNum=0 ctxt=0x0 subtype=9 data1=100107 data2=0
NSEvent: type=SysDefined loc=(311.855,276.375) time=39837.5 flags=0x20800000 win=0x0 winNum=0 ctxt=0x0 subtype=6 data1=100113 data2=0
NSEvent: type=SysDefined loc=(311.855,276.375) time=39837.5 flags=0x20800000 win=0x0 winNum=0 ctxt=0x0 subtype=9 data1=100113 data2=0

Hopefully that's useful?

fnesveda commented 4 years ago

Thanks! Yup, that's useful. Can you try selecting F14 and F15 in the app's preferences and see if it works then?

NiknakSi commented 4 years ago

Sadly selecting F14 and F15 does not work...

fnesveda commented 4 years ago

Huh, that's strange. According to the playground output, the keycodes of the captured events are 107 and 113, which should correspond to F14 and F15 and be captured by the app. Maybe something else is listening for them and captures them before they reach the app, perhaps even the Logitech Options app, but I'm honestly not sure now.

NiknakSi commented 4 years ago

Just had a look at the code again and can confirm, if I debug with a breakpoint in KeyboardShourtcutsManager.swift on line 71 it hits with just a normal F1 keypress but nothing at all with Fn+F1. If I set the key action as 'none' in Options it doesn't register either. None of the Fn+F{n} key presses register when the app's running.

What if ExternalDisplayBrightness could have some kind of external trigger instead of a keypress. Something that could be hit via shell script or Apple Script. The script could be attached to the keypress in Options.

fnesveda commented 4 years ago

Enabling scripting support would be a good workaround, but it requires quite a lot of effort to implement, so I'd see it only as a last resort.

To me it feels like Logitech Options is listening for the keycodes generated by the special keys in the background, which for the brightness keys are 107 and 113, and consumes them, and even if you select "none" as their action there, it doesn't let them through. Is there any option to set the action of the keys as "Send keycode" or something similar?

The playground sees the keypresses because it hooks itself to very low level functions of the system, so they probably get captured even before Logitech OptionsOptions gets to them, but this would be quite cumbersome to use in the app itself, and could break unexpectedly with a system update.

fnesveda commented 4 years ago

I might have figured out a different workaround, but it's pretty ugly and hacky, to be honest. I've made a short Swift script for faking keypresses:

import CoreGraphics

if CommandLine.arguments.count > 1 {
    if let keycode = CGKeyCode(CommandLine.arguments[1]) {
        CGEvent.init(keyboardEventSource: nil, virtualKey: keycode, keyDown: true)?.post(tap: .cghidEventTap)
        usleep(50000)
        CGEvent.init(keyboardEventSource: nil, virtualKey: keycode, keyDown: false)?.post(tap: .cghidEventTap)
    }
}

You could save it to a file, say fakeKeypress.swift, then compile it to a binary using swiftc fakeKeypress.swift, and then call that binary using ./fakeKeypress <keycode>. You could then set an action in Logitech Options for the brightness keys which would call a shell script calling this binary with the right keycodes for the keys you'd set in ExternalDisplayBrightness preferences.

It's a big stretch, but I think it could work.

barnabasbusa commented 4 years ago

Actually the workaround is much easier than that.

If you go to Logitech options, and you click on whatever button you want to use for brightness, then you select keystroke assignment, then you press Fn+F1 lets say, then it will assign the F1 command to that keystone. Screenshot 2020-03-10 at 02 33 40

volkancaliskan commented 4 years ago

Actually the workaround is much easier than that.

If you go to Logitech options, and you click on whatever button you want to use for brightness, then you select keystroke assignment, then you press Fn+F1 lets say, then it will assign the F1 command to that keystone. Screenshot 2020-03-10 at 02 33 40

This workaround solves the issue but you also need to assign F1 and F2 as brightness shortcuts on the Keyboard Shortcuts settings as shown in the SS.

Screenshot 2020-07-07 at 19 04 34
perteraul commented 3 years ago

Yup, can confirm that the workaround works.

djr1028 commented 3 years ago

For me, the workaround was to go to System Preferences -> Shortcuts -> Display, and reset the keyboard shortcuts only, without remapping the buttons to F1 and F2 in Logitech Options. After going to System Preferences -> Shortcuts -> Display, enable the checkmark for both "Decrease display brightness" and "Increase display brightness".

Then simply reset the keyboard shortcuts for both "Decrease display brightness" and "Increase display brightness" using the "F1/Decrease Brightness" and "F2/Increase Brightness" keys. When pressing the F1 key, System Preferences will receive the keycode for F14. When pressing the F2 key, it will receive the keycode for F15.

Screen Shot 2021-01-15 at 12 36 12 AM
bradparks commented 2 years ago

Turns out you can assign it directly using the options dialog. Just click that "MORE" link in the option there. Note that you can't do it for F1/F2/F3, but can for any other FN key

image