Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re: Insane numbers of combos for fixing numpad nav and media arrows #49

Closed
RedBearAK opened this issue Jun 22, 2022 · 13 comments
Closed

Comments

@RedBearAK
Copy link
Contributor

@joshgoebel

You should perhaps open an issue on my repo to discussion why this insane number of combos is needed and what might be done about that.

First posted in rbreaves/kinto#499

This is really something that is specific to the way Kinto currently remaps the modifier keys, plus the way GTK apps refuse to respect any Numpad nav keys, and then finally the Acer keyboard I have that places media functions on the Fn+arrow keys instead of PgUp/PgDn/Home/End. The PR for Linux is actually a combination of solutions for the two different problems I was having.

Now, one thing to understand is that all I've really done is remapped the shortcut combinations back to what they would have been had the user not been using Kinto. BUT, this is not necessarily correct. It just means that if those physical keys actually did something in Linux with Kinto disabled, they would continue to do whatever that is when Kinto is active. With the bonus that simple things like Shift+Numpad_PgUp actually works in GTK apps like a normal Shift+PgUp, and so on.

I'm interested in any ideas you have to consolidate this with some kind of generic "ignore" functionality that would cover all the combos. But with the shortcuts all laid out like this statically, someone can easily change just one of the specific remap groups to get their Numpad nav or media keys to do what they expect. If this was all lumped into some small algorithm, that would not be so easy.

Or, maybe you have some idea about a way to remap the base keys this is dealing with in such a way that all the individual remaps are no longer necessary. Get the Numpad nav keys to be recognized by everything regardless of any associated combo as the "real" nav keys you'd find on a full keyboard, between the QWERTY section and the Numpad.

Same with the arrow keys. If there could be a basic remap that just said, "Hey, these media functions are actually PgUp/PgDn/Home/End" that might solve the problem.

I hope we're on the same page with what the actual problem is that I'm solving by doing this. Funky GTK apps, and funky keyboards that don't put the right functions on the arrow keys. These remaps made both of those issues go away for me.

@RedBearAK
Copy link
Contributor Author

I just did the Fn+arrow key fix in AHK for the Windows version of Kinto, because that is still an issue in Windows.

rbreaves/kinto#722

But I didn't have to replicate the GTK Numpad nav keys fix since that isn't an issue in Windows (or KDE either). Although with GUI Linux apps coming to Windows with WSL2, it may become an issue at some point.

And of course the Windows version is half as long because I didn't have to compensate for the lack of Super key in terminals.

@RedBearAK
Copy link
Contributor Author

I think you're probably about to tell me I should do a modmap. Perhaps a multipurpose modmap like the Cmd2Esc stuff. I'm trying to look at that to see if it would do what I'm imagining.

@RedBearAK
Copy link
Contributor Author

Looks like adding lines to Kinto's conditional modmaps works (haven't tried a multipurpose modmap), but of course there is a problem with remapping the keypad keys like this. It means the keypad can't be used as a numeric keypad anymore. The keys will act as nav keys at all times.

Remapping the media functions is no big deal since the media functions are separate from the base arrow key functionality. So the remap is only invoked on the keys while using Fn. That seems to work great. Now the question is how to do it in AHK.

# [Global modemap] Change modifier keys as in xmodmap
define_conditional_modmap(lambda wm_class: wm_class.casefold() not in terminals,{
    # Fix arrow keys with media functions instead of PgUp/PgDn/Home/End
    Key.PLAYPAUSE:      Key.PAGE_UP,
    Key.STOPCD:         Key.PAGE_DOWN,
    Key.PREVIOUSSONG:   Key.HOME,
    Key.NEXTSONG:       Key.END,

    # Fix Numpad nav keys and shortcuts in GTK apps
    Key.KP9:    Key.PAGE_UP,
    Key.KP3:    Key.PAGE_DOWN,
    Key.KP7:    Key.HOME,
    Key.KP1:    Key.END,
    Key.KP8:    Key.UP,
    Key.KP2:    Key.DOWN,
    Key.KP4:    Key.LEFT,
    Key.KP6:    Key.RIGHT,

    # Key.CAPSLOCK: Key.RIGHT_CTRL,   # Caps2Cmd
    # Key.LEFT_META: Key.RIGHT_CTRL,  # Caps2Cmd - Chromebook

In order to make this work without breaking keypad number entry, there would need to be alternate labels in key.py for the keypad keys that apply only when Numlock is ON.

@joshgoebel
Copy link
Owner

How is this related to the numlock issue?

@RedBearAK
Copy link
Contributor Author

How is this related to the numlock issue?

Unless I'm mistaken, the keypad keys only have one name in the key list. KP1, KP2, KP3, and so on.

With the arrow keys, the Fn key makes the key emit a different key code, so it's like they are actually different physical keys. I can remap just the media functions that only appear in combination with the Fn key, as shown. The remap doesn't affect the base arrow key functionality.

But when I remap the KP* keys to their navigation counterparts, the keypad can no longer act as a numeric keypad, regardless of the Numlock status. It always acts like nav keys if I activate that remap. Except the 5 key, since it has no nav function.

There is no KP_PAGE_UP, KP_HOME, etc. that can be remapped separately from the numeric function of the keys.

@RedBearAK
Copy link
Contributor Author

You may have noticed that my PR about this has the "base key" lines all commented out. Because uncommenting those lines sacrifices the numeric keypad, turning it into only nav keys. So the keys are only remapped to "real" PgUp/PgDn/Home/End keys when used with a modifier key or combination of modifiers.

And yes, that means I can't use the keypad keys as PgUp/PgDn/Home/End in GTK apps as long as these base key lines are commented out. GTK just completely ignores them. Their key codes are different from "real" PgUp/PgDn/Home/End keys.

    ###  Keypad keys with no modifier keys (base key) 
    # K("KP9"):                   K("Page_Up"),                   # (fix_numpad_nav_keys_base_key)
    # K("KP3"):                   K("Page_Down"),                 # (fix_numpad_nav_keys_base_key)
    # K("KP7"):                   K("Home"),                      # (fix_numpad_nav_keys_base_key)
    # K("KP1"):                   K("End"),                       # (fix_numpad_nav_keys_base_key)
    # K("KP8"):                   K("Up"),                        # (fix_numpad_nav_keys_base_key)
    # K("KP2"):                   K("Down"),                      # (fix_numpad_nav_keys_base_key)
    # K("KP4"):                   K("Left"),                      # (fix_numpad_nav_keys_base_key)
    # K("KP6"):                   K("Right"),                     # (fix_numpad_nav_keys_base_key)

    ###  Keypad keys with 1 modifier key
    K("LC-KP9"):                K("C-Page_Up"),                 # (fix_numpad_nav_keys) 
    K("LC-KP3"):                K("C-Page_Down"),               # (fix_numpad_nav_keys) 
    K("LC-KP7"):                K("C-Home"),                    # (fix_numpad_nav_keys) 
    K("LC-KP1"):                K("C-End"),                     # (fix_numpad_nav_keys) 
    K("LC-KP8"):                K("C-Up"),                      # (fix_numpad_nav_keys) 
    K("LC-KP2"):                K("C-Down"),                    # (fix_numpad_nav_keys) 
    K("LC-KP4"):                K("C-Left"),                    # (fix_numpad_nav_keys) 
    K("LC-KP6"):                K("C-Right"),                   # (fix_numpad_nav_keys) 

@RedBearAK
Copy link
Contributor Author

Event: time 1655895799.694560, -------------- SYN_REPORT ------------
Event: time 1655895831.552167, type 4 (EV_MSC), code 4 (MSC_SCAN), value 45
Event: time 1655895831.552167, type 1 (EV_KEY), code 69 (KEY_NUMLOCK), value 1
Event: time 1655895831.552167, -------------- SYN_REPORT ------------
Event: time 1655895831.552536, type 17 (EV_LED), code 0 (LED_NUML), value 1
Event: time 1655895831.552536, -------------- SYN_REPORT ------------
Event: time 1655895831.743641, type 4 (EV_MSC), code 4 (MSC_SCAN), value 45
Event: time 1655895831.743641, type 1 (EV_KEY), code 69 (KEY_NUMLOCK), value 0
Event: time 1655895831.743641, -------------- SYN_REPORT ------------
Event: time 1655895833.448222, type 4 (EV_MSC), code 4 (MSC_SCAN), value 49
Event: time 1655895833.448222, type 1 (EV_KEY), code 73 (KEY_KP9), value 1
Event: time 1655895833.448222, -------------- SYN_REPORT ------------
9Event: time 1655895833.550839, type 4 (EV_MSC), code 4 (MSC_SCAN), value 49
Event: time 1655895833.550839, type 1 (EV_KEY), code 73 (KEY_KP9), value 0
Event: time 1655895833.550839, -------------- SYN_REPORT ------------
Event: time 1655895839.828679, type 4 (EV_MSC), code 4 (MSC_SCAN), value 45
Event: time 1655895839.828679, type 1 (EV_KEY), code 69 (KEY_NUMLOCK), value 1
Event: time 1655895839.828679, -------------- SYN_REPORT ------------
Event: time 1655895839.991152, type 4 (EV_MSC), code 4 (MSC_SCAN), value 45
Event: time 1655895839.991152, type 1 (EV_KEY), code 69 (KEY_NUMLOCK), value 0
Event: time 1655895839.991152, -------------- SYN_REPORT ------------
Event: time 1655895839.991335, type 17 (EV_LED), code 0 (LED_NUML), value 0
Event: time 1655895839.991335, -------------- SYN_REPORT ------------
Event: time 1655895840.212576, type 4 (EV_MSC), code 4 (MSC_SCAN), value 49
Event: time 1655895840.212576, type 1 (EV_KEY), code 73 (KEY_KP9), value 1
Event: time 1655895840.212576, -------------- SYN_REPORT ------------
^[[5~Event: time 1655895840.338592, type 4 (EV_MSC), code 4 (MSC_SCAN), value 49
Event: time 1655895840.338592, type 1 (EV_KEY), code 73 (KEY_KP9), value 0
Event: time 1655895840.338592, -------------- SYN_REPORT ------------

evtest output from the 9 key, with and without Numlock on. It sees the same key, of course. But there needs to be a way to say, "Only redirect this key's Numlock OFF function."

And it would need to work for just the key alone. Which, as far as I can tell, means that the specific Numlock OFF function of each keypad key needs to have its own name that can be referred to directly.

xbindkeys has some peculiar labels for the keypad keys. The 5 is KP_Begin, and the 9 is KP_Prior. There's KP_Home, KP_End, KP_Up/Down/Left/Right. That label is there whether Numlock is ON or OFF.

"(Scheme function)"
    m:0x10 + c:84
    Mod2 + KP_Begin
"(Scheme function)"
    m:0x0 + c:84
    KP_Begin

@RedBearAK
Copy link
Contributor Author

RedBearAK commented Jun 22, 2022

This is interesting. I will have to go back to an older version of Ubuntu or something to verify this, but it appears that newer GNOME apps in the GNOME 42+ era, presumably all finally using GTK4, don't have the issue anymore of ignoring the Numpad nav keys. If that applies to everything ported to or newly built in GTK4, there's much less of a reason for my "fixes" for that particular issue. The migration seems to be happening fairly quickly.

It was definitely still an issue back when I created the original PR. Hugely irritating since my keyboard had no "real" PgUp/PgDn/Home/End keys anywhere besides the keypad, and I couldn't test shortcuts like Ctrl+PgUp/PgDn. They just wouldn't work. I nearly went crazy before I realized everything worked fine with an external keyboard with the "real" nav keys. It was only the Numpad nav keys that weren't working as expected.

At the time, I tested the issue and verified the issue with multiple external keyboards with Numpads, and with multiple computers running different distros with GTK apps. I just haven't bothered to redo those tests for several months, and it looks like things have changed significantly.

@joshgoebel
Copy link
Owner

joshgoebel commented Jun 22, 2022

But when I remap the KP* keys to their navigation counterparts, the keypad can no longer act as a numeric keypad, regardless of the Numlock status.

I thought the problem was just that the software isn't taking into account the status, why is the following not all that is needed?

modmap("numlock OFF", {
    K("KP9"):                   K("Page_Up"),                   
    K("KP3"):                   K("Page_Down"),                 
    K("KP7"):                   K("Home"),                      
    K("KP1"):                   K("End"),                       
    K("KP8"):                   K("Up"),                        
    K("KP2"):                   K("Down"),                      
    K("KP4"):                   K("Left"),                      
    K("KP6"):                   K("Right") },
    when = numlock_off
    )

I assume you'd only need a single modmap to couter-act the "default" behavior... (whatever it is) So it's possible my above example is backwards.

@RedBearAK
Copy link
Contributor Author

I assume you'd only need a single modmap to couter-act the "default" behavior... (whatever it is) So it's possible my above example is backwards.

No, think that would do it. But we're still talking about a theoretical solution until [I] write the code to make the numlock_off condition work, right?

OK, well, I didn't think about it like that. Remapping the individual keys with K() rather than the Key.KP* syntax. And the Readme still says the things inside a modmap would be "Key literals (not combos)". So I have to give myself a little bit of a pass on that. Just a little one. 🤏🏽

Aside from being distracted by xkeysnail being so uncooperative when trying to send a modifier key by itself, remapping a key by itself rather than a safer "combo" would generally produce undesired results. So I kind of blocked that idea out mentally, I guess. I never encountered any other situation where remapping a single key (outside of very limited conditions) would have been helpful. Whereas this would be a thing I'd want to be global to work in all apps.

Would those K() remaps also still remap the key as part of combos? Guessing yes. For instance, Ctrl+Shift+KP1 or Ctrl+KP1 (when NL_OFF) would become Ctrl+Shift+End or Ctrl+End, without needing to explicitly list each combo? It would be like the base modifier remaps that Kinto does? If so, that would definitely solve the issue. But only when the numlock_off criteria becomes a thing.

And then, in another K() somewhere, if you wanted to remap the Shift+Ctrl+Alt+PgUp function of the keypad key to something after the base keypad_key+NL_OFF remap, you'd need to do something like this:

K("Shift-RC+Alt+Page_Up"): K("test-launch-script"),

Instead of:

K("Shift-RC+Alt+KP9"): K("test-launch-script"),

Correct? So like with the remapped modifiers, if I want (physical) Alt+key to do something in Kinto, I have to remember that it's actually (logical) RC+key after the remap.

Or, you'd need to include the when = numlock_off condition each time you used the KP9 name in a shortcut, but actually wanted the PgUp state of the key. But then the shortcut would only apply to the keypad nav key, not a "real" PgUp key.

Hope I have all that clear in my mind.

I can confirm that at least one app that I know is still GTK3-based is still having this issue when my remaps are inactive. GNOME Terminal. They are replacing it with GNOME Console at some point, which is being created on GTK4. (Still in beta.) So any app that remains on GTK3 will always have this issue with the keypad nav keys. On any keyboard.

And once again I'd need to go back to an older GNOME desktop install with more older GTK3 apps to be certain, but I think the actual heart of the issue was that they keypad nav keys wouldn't work as part of any combos, even as innocuous as Shift. As in, they would work as expected until I tried to pair them with any modifier key as a "shortcut". So I think the fact that I wasn't remapping the "base" keys on the keypad wasn't really a big problem. GNOME Terminal does something that seems to comply with the KP_Prior label when I hit the 9 key with Numlock OFF, rather than typing some odd sequence like 5~ which is what it does for combos with the keypad PgUp/PgDn keys.

I forgot how annoying it was to troubleshoot this in the first place. 😩

@joshgoebel
Copy link
Owner

joshgoebel commented Jun 22, 2022

For instance, Ctrl+Shift+KP1 or Ctrl+KP1 (when NL_OFF) would become Ctrl+Shift+End or Ctrl+End, without needing to explicitly list each combo?

That's what modmaps do... they happen before any of the other processing and rewrite the keys entirely.. it's as if KP1 is now the END key and always has been...

K("Shift-RC+Alt+Page_Up"): K("test-launch-script"),

Yes, after the modmap happens there is no more KP9... only page_up...

Or, you'd need to include the when = numlock_off condition each time you used the KP9 name in a shortcut, but actually wanted the PgUp state of the key. But then the shortcut would only apply to the keypad nav key, not a "real" PgUp key.

You may have lost me here.


I forgot how annoying it was to troubleshoot this in the first place. 

The nice thing about being so low-level though is you can just run evtest native (with your real KB)... write down the outputs... and then all you have to do is reproduce those keystrokes with keyszer... there is no guessing or wondering what is what... if you can reproduce the output, you will the same result...

But we're still talking about a theoretical solution until [I] write the code to make the numlock_off condition work, right?

Yes, but it's such a trivial feature. I'd focus on figuring that out rather than building 200 lines of complex mappings...

@RedBearAK
Copy link
Contributor Author

Yes, after the modmap happens there is no more KP9... only page_up...

I see now. So it's a "There is no Dana, only Zuuuuuul," type situation.

You may have lost me here.

Sorry, bad assumptions. So there would not be a simple way to refer to the original key name anymore, in reference to its numlock_off state. Only the numlock_on state (the numbers), which wouldn't be remapped by the modmap with the when = numlock_off.

The nice thing about being so low-level though is you can just run evtest native (with your real KB)...

At the time the most advanced thing I knew to look at was xbindkeys. Mainly what I was trying to figure out was why the GTK apps specifically didn't like those keys. That's what made it so confusing. Because they would work fine in other kinds of apps, so obviously there was technically nothing wrong with the keys themselves, and at the time also I didn't even realize some of the apps were GTK and some were using Qt or other non-GTK frameworks.

I'd focus on figuring that out rather than building 200 lines of complex mappings...

Yes, well. The "complex" things are already done, and from my perspective they were merely tedious, rather than beyond my capacity to understand. But I can at least replace the "media arrows" stuff now with a simple optional (disabled by default) modmap, thanks to your prodding. I think I even have a line on how to do the same thing in AHK. So I can fix up the Windows PR with a much simpler version. I'll have to get back into Windows and test my new assumptions.

Just to clear something up, if I wanted to leave the base function of say, the media arrow keys alone (i.e., retain the Fn+Play/Stop/Prev/Next), but remap those functions to PgUp/PgDn/Home/End only when used with at least one modifier key, could that be done with a currently available modmap when condition?

@RedBearAK
Copy link
Contributor Author

RedBearAK commented Jun 23, 2022

Think I just replaced about a hundred lines of AHK shortcuts with seven lines. Found the right syntax that seems to produce a modmap type result, rather than just an explicit shortcut remap:

#If !WinActive("ahk_group remotes") && media_arrows_fix = 1
    ; Fix for media functions on laptop arrow keys
    $Media_Play_Pause::PgUp
    $Media_Stop::PgDn
    $Media_Prev::Home
    $Media_Next::End
#If

As opposed to:

$Media_Play_Pause::Send, {PgUp}

Which would just work with the base key, not when adding modifiers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants