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

Support logical modifier keys #124

Closed
nullbyto opened this issue Jul 1, 2022 · 24 comments · Fixed by #146
Closed

Support logical modifier keys #124

nullbyto opened this issue Jul 1, 2022 · 24 comments · Fixed by #146

Comments

@nullbyto
Copy link

nullbyto commented Jul 1, 2022

Hello,

I'm trying to map capslock + ijkl keys to arrow keys and extra: o -> end, u -> home, p -> pageup, ; -> pagedown.
The mapping should be compatible with (shift, alt, ctrl, shift+ctrl and shift+alt) + Arrow for editing in vscode for example.

What i tried:

  • Mapping capslock to hyper(super) but on KDE Plasma super(which is the win key) opens app menu.
  • Using capslock as Alt_R as a workaround but i use it for my (EurKey) layout to use üöäß, therefore Alt_R wont work for me.

In xmodmap i used to use mode_switch which works fine with win key:

clear Lock
keycode 66 = Mode_switch
keysym h = h H Left
keysym l = l L Right
keysym k = k K Up
keysym j = j J Down

Is there maybe an extra layer of modifier i didn't find? Any suggestions on how i can do it?
This is a common used mapping navigation. Would appreciate anyones help. :)

Extra: xremap ❤ Rust

@k0kubun
Copy link
Contributor

k0kubun commented Jul 2, 2022

Using capslock as Alt_R as a workaround but i use it for my (EurKey) layout to use üöäß, therefore Alt_R wont work for me.

One workaround that seems already possible is:

modmap:
  CapsLock: Alt_R
  Alt_R: Alt_L
keymap:
  Alt_R-i: Up
  Alt_R-j: Left
  Alt_R-k: Down
  Alt_R-l: Right
  Alt_R-o: End
  Alt_R-u: Home
  Alt_R-p: PageUp
  Alt_R-Semicolon: PageDown

where physical Alt_R and Alt_L are used as actual Alt as Alt_L and virtual Alt_R is used as an extra modifier.

If the above workaround works for you, please do. However, I understand that it's just a workaround and it makes configuration hard. As somebody else also mentioned the necessity of a virtual modifier when he tried xremap, I plan to have an official implementation for it in the future. But I have an in-progress development for another OSS and I'd like to work on the feature after it. So I need you to use a workaround for now.

@nullbyto
Copy link
Author

nullbyto commented Jul 2, 2022

Firstly thank you for your good work. :)
No problem i hope to see that be added in the future.

As for that workaround it remaps my Alt_R which i use for pressing Alt_R + a = ä for example, so it doesn't work for me that well.

I ended up with the best workaround so far if someone needs that (i had to disable win(super) key to open application menu in KDE Plasma [like this] to use caps lock as super):

modmap:
  - name: Global
    remap:
      CapsLock:
        alone: Esc
        held: Super_L

keymap:
  - name: Global
    remap:
      # ijkl -> Arrow keys
      Super_L-I: Up
      Super_L-J: Left
      Super_L-K: Down
      Super_L-L: Right

      Shift-Super_L-I: Shift-Up
      Shift-Super_L-J: Shift-Left
      Shift-Super_L-K: Shift-Down
      Shift-Super_L-L: Shift-Right

      Alt_L-Super_L-I: Alt_L-Up
      Alt_L-Super_L-J: Alt_L-Left
      Alt_L-Super_L-K: Alt_L-Down
      Alt_L-Super_L-L: Alt_L-Right

      Shift-Alt_L-Super_L-I: Shift-Alt_L-Up
      Shift-Alt_L-Super_L-J: Shift-Alt_L-Left
      Shift-Alt_L-Super_L-K: Shift-Alt_L-Down
      Shift-Alt_L-Super_L-L: Shift-Alt_L-Right
      
      Ctrl-Super_L-I: Ctrl-Up
      Ctrl-Super_L-J: Ctrl-Left
      Ctrl-Super_L-K: Ctrl-Down
      Ctrl-Super_L-L: Ctrl-Right

      Shift-Ctrl-Super_L-I: Shift-Ctrl-Up
      Shift-Ctrl-Super_L-J: Shift-Ctrl-Left
      Shift-Ctrl-Super_L-K: Shift-Ctrl-Down
      Shift-Ctrl-Super_L-L: Shift-Ctrl-Right

      ##########################################

      # uop; -> Home End PageUp PageDown
      Super_L-U: Home
      Super_L-O: End
      Super_L-P: PageUp
      Super_L-SEMICOLON: PageDown

      Shift-Super_L-U: Shift-Home
      Shift-Super_L-O: Shift-End
      Shift-Super_L-P: Shift-PageUp
      Shift-Super_L-SEMICOLON: Shift-PageDown

      Ctrl-Super_L-U: Ctrl-Home
      Ctrl-Super_L-O: Ctrl-End
      Ctrl-Super_L-P: Ctrl-PageUp
      Ctrl-Super_L-SEMICOLON: Ctrl-PageDown

      Shift-Ctrl-Super_L-U: Shift-Ctrl-Home
      Shift-Ctrl-Super_L-O: Shift-Ctrl-End
      Shift-Ctrl-Super_L-P: Shift-Ctrl-PageUp
      Shift-Ctrl-Super_L-SEMICOLON: Shift-Ctrl-PageDown

As you see i had to add all the necessary extra modifiers for editing, since without them if i shift+capslock+i it just acts as shift+i.
Isn't it possible to just write this for example:

Super_L-I: Up
Super_L-J: Left
Super_L-K: Down
Super_L-L: Right

without the need to add all the clutter modifiers?

Another last question: is it possible in modmap to remap a key to multiple keys? for example:

modmap:
  remap:
    Super_L: Alt_R-F1 # <<<<<<<

which will then act as a macro maybe. It would be a good feature to add a macro kindof system.

@k0kubun
Copy link
Contributor

k0kubun commented Jul 2, 2022

As for that workaround it remaps my Alt_R which i use for pressing Alt_R + a = ä for example, so it doesn't work for me that well.

What's your expected behavior for that case? Just output a, or nothing?

Another last question: is it possible in modmap to remap a key to multiple keys?

Sending a key combination is for keymap, and remapping a modifier key alone is supported only by modmap. I can also work on supporting it later, but what you could do for now would be to pick a key you don't use/have (e.g. KEY_MUHENKAN) and do something like:

modmap:
  - remap:
      Super_L: Muhenkan
keymap:
  - remap:
      Muhenkan: Alt-F1

@nullbyto
Copy link
Author

nullbyto commented Jul 2, 2022

What's your expected behavior for that case? Just output a, or nothing?

In the workaround you gave me i can access the german layer only with capslock since its bound to Alt_R and the actual right Alt key is bound to Alt_L. The problem with binding capslock to Alt_R is that with that specific layout i need u and o keys for ü, ö resp. with the combination with Alt_R. And i need them as well for Home and End. So at the end i need Alt_R and another extra modifier layer to achieve that. But for now i think i can live with my last solution i found using super until an extra layer gets added.

modmap:
  - remap:
      Super_L: Muhenkan
keymap:
  - remap:
      Muhenkan: Alt-F1

Great that works!
Thank you for your help.

@k0kubun
Copy link
Contributor

k0kubun commented Jul 3, 2022

The problem with binding capslock to Alt_R is that with that specific layout i need u and o keys for ü, ö resp. with the combination with Alt_R.

I read your explanation, but it feels inexhaustive and I didn't get why my suggestion doesn't work for you. Can you just describe expected input and output key combinations? For example,

  • input: CapsLock+u, output: Home
  • input: Alt_R+u, output: Alt_L+u
  • input: Alt_L+u, output: Alt_L+u

I believe #124 (comment) works like the above, so you can still output ü using actual Alt_R or Alt_L as if nothing happened to Alt and CapsLock works like an extra modifier.

@nullbyto
Copy link
Author

nullbyto commented Jul 3, 2022

Sorry for my bad explaination.
So what i exactly need is:
Input -> output:

  • CapsLock+u -> Home
  • CapsLock+o -> End
  • CapsLock+p -> PageUp
  • CapsLock+; -> PageDown
  • CapsLock+i,j,k,l -> up,left,down,right

For better clarification the (EurKey) layout provides the european letters using the (Alt_Gr)Alt_R+[letter]. Better shown how it works in this picture from the website:

image

I need to be able to:
Input -> output:

  • Alt_R+a -> Alt_R+a (ä)
  • Alt_R+s -> Alt_R+s (ß)
  • Alt_R+u -> Alt_R+u (ü)
  • Alt_R+o -> Alt_R+o (ö)

I hope this time it is clear.

@k0kubun
Copy link
Contributor

k0kubun commented Jul 4, 2022

CapsLock+u -> Home
CapsLock+o -> End
CapsLock+p -> PageUp
CapsLock+; -> PageDown
CapsLock+i,j,k,l -> up,left,down,right
Alt_R+a -> Alt_R+a (ä)
Alt_R+s -> Alt_R+s (ß)
Alt_R+u -> Alt_R+u (ü)
Alt_R+o -> Alt_R+o (ö)

My idea should be still applicable (though I haven't actually tested it) even if you want to output Alt_R instead of Alt_L for some reason, e.g.

modmap:
  CapsLock: Alt_L
  Alt_L: Alt_R # optional for what you described
keymap:
  Alt_L-i: Up
  Alt_L-j: Left
  Alt_L-k: Down
  Alt_L-l: Right
  Alt_L-o: End
  Alt_L-u: Home
  Alt_L-p: PageUp
  Alt_L-Semicolon: PageDown

I expect this config to generate what you described.

@nullbyto
Copy link
Author

nullbyto commented Jul 4, 2022

I expect this config to generate what you described.

It does work but this time i have other issues:

  • Alt tabbing doesn't work because of Alt_L: Alt_R (because Alt_R is Alt_Gr which is different as a normal alt in this layout) I just removed that and it works but other issues with having alt as a modifier:
  • is Alt-Arrow for example to move line up and down in vscode, doing:
    Alt_L-Alt_L-i: Alt_L-Up
    isn't working because it presses Alt_L-Up when pressing capslock-i.

What also should work is: (shift/alt/ctrl/shift-alt/ctrl-shift)-Capslock-(i/j/k/l) to work as expected as if im using normal arrows.

@nullbyto
Copy link
Author

nullbyto commented Jul 4, 2022

What i managed to do is this config which should be the best solution with Super_R but it has a weird behaviour:

modmap:
  - name: Global
    remap:
      CapsLock:
        alone: Esc
        held: Super_R

keymap:
  - name: Global
    remap:
      ##########################################
      # CapsLock ijkl -> Arrow keys

      Super_R-I: Up
      Super_R-J: Left
      Super_R-K: Down
      Super_R-L: Right

      Shift-Super_R-I: Shift-Up
      Shift-Super_R-J: Shift-Left
      Shift-Super_R-K: Shift-Down
      Shift-Super_R-L: Shift-Right

      Alt_L-Super_R-I: Alt_L-Up
      Alt_L-Super_R-J: Alt_L-Left
      Alt_L-Super_R-K: Alt_L-Down
      Alt_L-Super_R-L: Alt_L-Right

      Shift-Alt_L-Super_R-I: Shift-Alt_L-Up
      Shift-Alt_L-Super_R-J: Shift-Alt_L-Left
      Shift-Alt_L-Super_R-K: Shift-Alt_L-Down
      Shift-Alt_L-Super_R-L: Shift-Alt_L-Right
      
      Ctrl-Super_R-I: Ctrl-Up
      Ctrl-Super_R-J: Ctrl-Left
      Ctrl-Super_R-K: Ctrl-Down
      Ctrl-Super_R-L: Ctrl-Right

      Shift-Ctrl-Super_R-I: Shift-Ctrl-Up
      Shift-Ctrl-Super_R-J: Shift-Ctrl-Left
      Shift-Ctrl-Super_R-K: Shift-Ctrl-Down
      Shift-Ctrl-Super_R-L: Shift-Ctrl-Right

      ##########################################
      # CapsLock + uop; -> Home End PageUp PageDown

      Super_R-U: Home
      Super_R-O: End
      Super_R-P: PageUp
      Super_R-SEMICOLON: PageDown

      Shift-Super_R-U: Shift-Home
      Shift-Super_R-O: Shift-End
      Shift-Super_R-P: Shift-PageUp
      Shift-Super_R-SEMICOLON: Shift-PageDown

      Ctrl-Super_R-U: Ctrl-Home
      Ctrl-Super_R-O: Ctrl-End
      Ctrl-Super_R-P: Ctrl-PageUp
      Ctrl-Super_R-SEMICOLON: Ctrl-PageDown

      Shift-Ctrl-Super_R-U: Shift-Ctrl-Home
      Shift-Ctrl-Super_R-O: Shift-Ctrl-End
      Shift-Ctrl-Super_R-P: Shift-Ctrl-PageUp
      Shift-Ctrl-Super_R-SEMICOLON: Shift-Ctrl-PageDown

      ##########################################
      # CapsLock + BackSpace -> Delete

      Super_R-BackSpace: Delete
      Shift-Super_R-BackSpace: Shift-Delete
      Ctrl-Super_R-BackSpace: Ctrl-Delete

If i press: Caps_Lock+j,i,k,l or other combination, it sends the right keys but at the same time it sends also Super_R(R win) which opens the application menu as show in the video:

What i simply do is pressing Caps_Lock + j

2022-07-04.19-12-09.mp4

I suspect that it has something to do with how it sends out the keys as i see it sends rightmeta 1 then 0 means it presses and releases right after i press j as shown in the debug.

@k0kubun
Copy link
Contributor

k0kubun commented Jul 4, 2022

Alt_R is Alt_Gr which is different as a normal alt in this layout
is Alt-Arrow for example to move line up and down in vscode

Thanks. This explains everything I wanted to know about my suggestion.

What also should work is: (shift/alt/ctrl/shift-alt/ctrl-shift)-Capslock-(i/j/k/l) to work as expected as if im using normal arrows.

Right, I think it's the same thing as #102. I'll work on those once what I'm currently working on is finished.

If i press: Caps_Lock+j,i,k,l or other combination, it sends the right keys but at the same time it sends also Super_R(R win) which opens the application menu as show in the video:

This seems intentional. When you remap Super_R+j to Left and Left is emitted, it has to release Super_R because otherwise it would be Super_R+Left. If you want to keep holding Super_R, then you could remap Super_R+j to Super_R+Left. To simply fix this problem by just not using Super_R, please wait until I get time to work on virtual modifiers.

@nullbyto
Copy link
Author

nullbyto commented Jul 4, 2022

Thank you a lot for your time and effort you put into helping and good luck for your work. Ofcourse i will wait for that. I come along with one of the solutions for now.

@k0kubun
Copy link
Contributor

k0kubun commented Jul 29, 2022

Update: As I'm currently focusing on a big change for another OSS, I'm planning to work on this issue on Aug 13th. If I receive a pull request before that, I can take a look at that too.

@Cruising0904
Copy link

It would be really great if the problem fixed.
By the way isn't there ISO_Level3_SHIFT which I use it with xkb. It works fine working itself, combination thing isn't though. I thought it would be a good solution if possible

@k0kubun
Copy link
Contributor

k0kubun commented Aug 12, 2022

Can you show the output of RUST_LOG=debug xremap when you input ISO_Level3_SHIFT? I don't know what ISO_Level3_SHIFT is, but reading it would help my understanding.

I'd also appreciate your code or command to use xkb for making ISO_Level3_SHIFT work.

@nullbyto
Copy link
Author

nullbyto commented Aug 12, 2022

I think if I'm not mistaken this won't work with eu layout since Alt_R is actually set to ISO_Level3_Shift Afaik.

@k0kubun
Copy link
Contributor

k0kubun commented Aug 13, 2022

Thanks. I might support keyboard layout features in the future, but to know my knowledge, xkb is an X-specific interface, so we need to investigate how to make that work for Wayland. Meanwhile, you may emit a key event that corresponds to ISO_Level3_SHIFT with xremap and then anything beyond that is for another layer on top of it.

@k0kubun k0kubun changed the title CapsLock + ijkl -> arrow keys mapping Support logical modifier keys Aug 13, 2022
@k0kubun
Copy link
Contributor

k0kubun commented Aug 14, 2022

Released #146 in v0.6.1.

@nullbyto
Copy link
Author

Nice. Thanks for your work!
I tried the example shown in the #146.

Tapping it doesn't do anything as intended but when pressing the combinations in keymap the arrows work but it turns on Caps-Lock and doesn't turn off. I tried assigning alone to Esc doesn't work either.
Maybe i'm not doing something right.

k0kubun added a commit that referenced this issue Aug 14, 2022
when adjusting modifiers on KeyPress

addresses #124 (comment)
@k0kubun
Copy link
Contributor

k0kubun commented Aug 14, 2022

Thanks for the report and for sponsoring me :) I fixed the issue in v0.6.2.

@nullbyto
Copy link
Author

nullbyto commented Aug 14, 2022

You are welcome, i have to thank you for your great work in this project and others as well!

Works now. Unfortunately binding alone to a key in modmap isn't doing anything anymore, while modifier is set to true.
This would be useful in my example when using capslock as a modifier plus tapping it would emit Esc.

@k0kubun
Copy link
Contributor

k0kubun commented Aug 14, 2022

Sorry, can you share your current config? I'm a bit confused now.

@nullbyto
Copy link
Author

modmap:
  - name: Global
    remap:
      CapsLock:
        modifier: true
        alone: Esc

keymap:
  - name: Global
    remap:
      CapsLock-i: Up
      CapsLock-j: Left
      CapsLock-k: Down
      CapsLock-l: Right

      CapsLock-o: End
      CapsLock-u: Home
      CapsLock-p: PageUp
      CapsLock-SemiColon: PageDown

Simply what i want to do is while holding be a modifier and tapping alone Esc

@k0kubun
Copy link
Contributor

k0kubun commented Aug 14, 2022

OK, I wasn't aware that you could parse modifier and alone in a single HashMap with the implementation, which was unexpected and the thing that confused me. The actual problem is, however, not that loose validation but the feature's design. I tried to cover some corner cases like application-specific logical modifiers, but it came with the cost of slipping the held/alone use case.

I changed it. modifier: true is now gone, and virtual_modifiers is added at the top level. You may try #147 in v0.7.0.

@nullbyto
Copy link
Author

I understand.
Works perfectly now! Thanks.

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

Successfully merging a pull request may close this issue.

3 participants