win-vind icon indicating copy to clipboard operation
win-vind copied to clipboard

[Bug] Can't map <capslock>

Open mrjackphil opened this issue 2 years ago • 15 comments

Describe the bug As an example, I'm trying to remap <capslock> by doing:

imap <capslock> <f15>
inoremap <f15> to_edi_normal

Also, I tried to remap <capslock> in other modes without success:

gnnoremap <capslock> j

I can remap all other keys except capslock.

Environment (please complete the following information):

  • Windows 11 Home Single Language
  • OS Type: 64bit
  • OS Version: 21H2
  • OS Build: 21H2
  • win-vind Version: 4.2.1
  • win-vind Type: installer
  • Is it reproducible?: Yes

mrjackphil avatar Nov 12 '21 09:11 mrjackphil

Thanks for using it.

I have not been able to reproduce it. However, I am using a multi-language IME, so the keycode of <capslock> recognized by Windows may be different from the single language.

I will first build a single language environment and try it. Please wait for a while.

pit-ray avatar Nov 12 '21 19:11 pit-ray

I have installed and tested Windows 10 Home Single Language 21H1 Build19043.1348 and found the same behavior. I will now work on fixing the bug.

Thanks for the report.

pit-ray avatar Nov 17 '21 04:11 pit-ray

Hi.

I found the factor of the problem, but I didn't know its solution.

In Windows10, if absorb the input message of some toggle keys (e.g. <CapsLock>, <Kana>) to low-level, these state is always pressing. Thus, win-vind periodically releases the state of such toggle keys with SendInput function (https://github.com/pit-ray/win-vind/blob/master/src/core/key_absorber.cpp#L197-L219). However, in Single Language Edition, the key-up message via SendInput does not seem to work and it was left pressed. Therefore, it seems that it cannot be remapped. This can be reproduced visually by writing like imap <CapsLock> a.

This is due to the API not working, so I don't know the solution. If there is an open-source remapping tool that can handle CapsLock, let me know. I will refer them for a solution.

Thanks.

pit-ray avatar Nov 20 '21 18:11 pit-ray

I've seen to have hit a similar issue. Currently trying to map AltGr + ' as a to_command. It works, but when i come back, windows seems to think that AltGr is in KeyDown position.

In regards to refering to another solution: Maybe AutoHotkeys can shed a light in this? I use it to implement Extend-Layer, as seen in https://dreymar.colemak.org/.

That means that my pressing my caps-lock key acts just as another keyboard layer. It works pretty well. Maybe you could refer to othem? Attached, the piece of AHK code that enables the caps-lock remapping.

image

canelhasmateus avatar Apr 04 '22 19:04 canelhasmateus

Thanks for sponsoring and information.

Is the problem with AltGr, in Single Language Edition? Otherwise, AltGr may be caused by another fact that AltGr is LCtrl + RAlt compound key code internally.

I am not familiar with extend-layer, in other words, AHK can disable the original function of CapsLock with SetCapsLockState, AlwaysOff even if Single Language Edition? If so, I'll refer SetCapsLockState implementation.

Thanks.

pit-ray avatar Apr 05 '22 07:04 pit-ray

I am not sure if it would work in the single-language edition: i wasn't even aware it existed until now. I believe i do not use the single language edition. How could i confirm?

exploring further : this "AltGr stuck" Doesn't happen in every mode transition, strangely. Those are the keybinds i'm using to test. Mind that ralt here is representing the AltGr key. I also tried doing <ralt-rctrl-*> but that didn't trigger.

inoremap <ralt-'> to_gui_normal
inoremap <ralt-v> to_gui_visual
gnnoremap <ralt-esc> to_insert
gnnoremap <esc> to_insert

In more details:

going from insert_mode to gui_normal , using AltGr + ' ; then immediately < esc > to come back to insert_mode triggers the problem: Some applications start to dispatch the commands as if i was holding the alt key. Pressing AltGr takes us back to normal functionality. I will call this condition as "stuck" from now on.

What i tested was: doing commands while in stuck mode. Doing this inside sublime text meant that pressing the up and down keys triggered the alt+up and alt+down commands. Doing this inside vscode meant that pressing the up and down keys did not trigger the alt up and alt down commands, just up and down. This is probably due to differences on how each program handles its modifiers.

To further explore, i turned on the trace-level logging on vscode, to inspect what he was dispatching on , as well as the screencast mode. On a side screen, i turned KeyboardStateViewer on.

While in stuck mode, doing the following keystrokes result in the following actions :

Keystroke Vscode Log Vscode Screencast KeyState Viewer
UP Up Key Up Key Up Key
Alt + UP Up alt + Up alt + up
Ctrl + UP Up Ctrl + UP Ctrl + UP
Shift + UP Shift + UP Shift + up Shift + UP

From this point of view, it looks like the problem is the way programs handle the KeyDown -> Key Up transition. However, and this is the place where i got very confused.

going from insert_mode to visual, using AltGr + v ; then immediately < esc > to come back to insert_mode does not trigger stuck mode.

Some other observations:

I also have other altgr shortcuts mapped by autohotkeys ( switches desktops, for example ), and they don't trigger stuck mode either. From my testing, this is because autohotkeys stops the propagation of key-events as soon as it hits a mapped shortcut, while you seen to only stop propagating after. That is:

Keypress Win-Vind VSCode Screencast AHK VSCode Screencast
AltGr < no match > Alt < no match > Alt
AltGr + ' < Match to_gui > Alt + ' < match > Alt

( While testing these out, i found a similar bug in autohotkeys. Won't post now because this post is already long enough. We can discuss it below, if you want to. )

Pressing altgr + esc to exit insert mode works as a way of preventing stuck mode from happening. This is likely due to the ergonomics: when pressing altgr i most likely do the sequence altgr down -> esc down -> esc up -> altgr up. If this is the case , altgr down -> esc down -> esc up would come back to insert_mode, allowing the active window to just receive altgr up, ending stuck mode ( just like pressing altgr does ).

TLDR:

  • Not sure what my windows edition is
  • Stuck happens while transitioning between some modes, but not all.
  • Autohotkeys seems to handle things different.

canelhasmateus avatar Apr 05 '22 14:04 canelhasmateus

Sorry for my late reply.

As discussed above, I assume that imap <CapsLock> does not work well because of the differences in the API specification for the Single Language Edition.

If you are using the Single Language Edition, it will be shown as such in the log files. If win-vind is not a portable, there are in ~/.win-vind/log.

Like this.

========== System Infomation ==========
[Windows]
      Edition: Windows 10 Home Single Language
      Version: 21H2
Build Numbers: 10.0.19044
 Architecture: x64

[win-vind]
      Version: 4.3.3
=======================================

I am trying to reproduce what you call AltGr stuck. I will let you know when I can confirm it.

Just to be sure, is your keyboard French or something else?

Thanks for your contribution.

pit-ray avatar Apr 12 '22 14:04 pit-ray

After verifying, i do not use the single language edition. My physical keyboard uses US QWERTY. My Layout is usually configured as Portuguese ABNT 2 , or as Standard Colemak. I have tested this interaction only on the abnt layout ( '0409:00010416' as in the Get-WinUserLanguageList InputMethodTips )

canelhasmateus avatar Apr 13 '22 00:04 canelhasmateus

Hi,

Probably just a small addition, but I'm having the same issue, although I'm not on a single-language edition. I'm copying the log file below. I'm on a Hungarian system with Hungarian keyboard layout.

On a side note, I also tried to remap jk to to_edi_normal, and it kind of worked, but the problem was that it also wrote out the two characters. The same happened with Tab: pressing it caused the program to go to normal mode, but it also meant that the system reacted as if I wanted to press Tab.

I tried to swap CapsLock and Insert with PowerToys, but to no avail.

As a temporary solution, Insert without remapping seems to work now, but it is, of course, less comfy.

By the way, the log also shows a different kind of problem; there seems to be a bug with switch character case in my system.

========== System Infomation ========== [Windows] Edition: Windows 10 Home Version: 21H2 Build Numbers: 10.0.19044 Architecture: x64

[win-vind] Version: 4.3.3

[Message] E: Not a command

[Error] switch_char_case failed. An runtime exception occurred from bool __cdecl vind::bind::SmartClipboard::get_as_str(class std::basic_string<char,struct std::char_traits,class std::allocator > &). the current clipboard data is not supported unicode (void __cdecl vind::bind::BindedFunc::error_process(const class std::exception &) const)

[Error] switch_char_case failed. An runtime exception occurred from bool __cdecl vind::bind::SmartClipboard::get_as_str(class std::basic_string<char,struct std::char_traits,class std::allocator > &). the current clipboard data is not supported unicode (void __cdecl vind::bind::BindedFunc::error_process(const class std::exception &) const)

pukkancsanyo avatar Apr 14 '22 03:04 pukkancsanyo

@canelhasmateus Hi. I was able to reproduce AltGr Stuck. This happens with noremap mapping using <ralt> regardless of system language or keyboard layout.

Key states observed from win-vind

I inserted code in the source code of win-vind to check the status of the key code, and after rebuilding, I did the following mapping.

inoremap <ralt> to_gui_normal

At that time, I found that win-vind recognizes <alt> and <ralt> keys and sends key-up messages with SendInput function to release <alt> and <ralt> just before transitioning to GUI Normal. Thus, it may be the same problem in Single Lang Edition where the SendInput function for CapsLock does not work.

win-vind does not stop key propagation?

Internally, win-vind performs three types of mapping. ref. https://pit-ray.github.io/win-vind/usage/#3-customize-win-vind

  • {mode}noremap {in-cmd} {out-cmd} It is performed after key input is recognized. Thus, if noremap is used in insert mode, the triggering key is propagated to other applications.

  • {mode}map {in-cmd} {out-cmd} It recognizes the command matching with {in-cmd} and then generates commands for {out-cmd}. The triggering {in-cmd} and generated {out-cmd} commands are propagated to other applications. For example, imap ab <ctrl-s>.

  • {mode}map {in-key} {out-keyset} If the trigger is a standalone key and the output is key or keyset, the mapping is done without propagating the trigger to other applications. For example, in imap a <shift-b>, a is not propagated to other applications.

In the specification, noremap is for internal mapping and map is for external mapping, so the former does not result in a recursive mapping, the latter may result in a recursive mapping.

Solution for mapping AltGr

{mode}map {in-key} {out-keyset} can be used to disable the trigger message. If you won't use AltGr's original feature, the following mapping works.

imap <ralt> <f20>
inoremap <f20-'> to_gui_normal
gnnoremap <ralt-esc> to_insert
gnnoremap <esc> to_insert

Thanks.

pit-ray avatar Apr 17 '22 13:04 pit-ray

@pukkancsanyo As mentioned above, mapping jk, etc. in inoremap will propagate to other applications.

About the log, it seems that switch_char_case was used for an application where Unicode is not available, so the character could not be read. Various encodings can be supported with patches.

You seem to want to map something about Insert mode, can you be more specific? Thanks.

pit-ray avatar Apr 17 '22 14:04 pit-ray

@pit-ray OK, thanks, I see now why jk cannot work for going back to normal mode. Switch_char_case does not work in other applications, either, but maybe it is because the Hungarian layout I use (~ can only be typed with AltGr).

Sorry if I was not specific enough with the core of my comment. I wanted to map CapsLock as an alternative way to have to_edi_normal when I am in Insert mode (Esc + arrows feel a bit unergonomic for me on my keyboard). I wanted to apply something that was mentioned in the original comment:

imap inoremap to_edi_normal

However, it does not seem to work; it is as if CapsLock were not be pressed at all, and I cant switch back to edi_normal this way, although I am not on a single-language edition.

So I just wanted to added this observation of mine to the thread that maybe not only single-language editions are affected by this issue.

pukkancsanyo avatar Apr 20 '22 11:04 pukkancsanyo

My edition from win-vind logs says Edition: Windows 10 Pro and I'm also facing this issue.

serranomorante avatar Mar 25 '23 17:03 serranomorante

On a side note, I also tried to remap jk to to_edi_normal, and it kind of worked, but the problem was that it also wrote out the two characters. The same happened with Tab: pressing it caused the program to go to normal mode, but it also meant that the system reacted as if I wanted to press Tab.

for 'jk', i use 'imap jk <to_edi_normal>hhxx' to

imshenwei avatar Aug 18 '23 12:08 imshenwei