Right now keyboard layouts are handled by manually listing out bindings given key presses and modifiers. This is very broken.
Luckily there is movement here which should fix this issue. https://github.com/rust-windowing/winit/pull/1788
Once this lands and looks stable enough. I'm going to pull in some version of winit which uses it, and rewrite our keyboard input handling to use that. Most of the hard work was already done thanks to @j4qfrost, so now its a waiting game. Looks like its moving very quickly though so I'm hopeful we will have motion on this soon.
For now I'm going to comb through our issues looking for any that have to do with keyboard input handling and close them as this should fix them or at least make a fix possible.
Note that IME support is different from keyboard layout, IME uses an external program unlike using a different layout/variant.
Agreed. However IME support in sdl2 is not good either. I think at this point supporting multiple windowing systems is not the way to go, so I'm going to be moving to switch to winit only once the upstream changes land. At that point, we can work with them to get IME support working for real on the relevant platforms.
https://github.com/Kethku/neovide/pull/506 a PR has been contributed targetting the new winit api. It currently only works on windows, but once upstream support for linux and mac lands, we should be in very good shape.
https://github.com/rust-windowing/winit/pull/1890 looks like an upstream macos PR has been created. Very excited
I've set my window manager to swap escape and caps lock but it doesn't work in neovide (they are not swapped), will this fix my issue too 👉👈 ?
I've set my window manager to swap escape and caps lock but it doesn't work in neovide (they are not swapped), will this fix my issue too point_rightpoint_left ?
I did the same but IIRC I don't have this issue, I only have an issue with dvorak keys when used with other combination keys, I even swap my left ctrl and left alt but I think I don't have an issue with that either. Maybe I did but I don't recall.
I believe this would fix both of your problems @p00f @pickfire. At the very least it would unblock addressing those issues.
https://github.com/rust-windowing/winit/pull/1788 PR one of 3 has merged! Shouldn't be long now!!!
12 days ago

But hype!
Note, we need mac and linux support to merge first
I am using uncap, but it doesn't work.. Is this related to this issue also?
@PyGamer0 seems possible.
Linux: https://github.com/rust-windowing/winit/pull/1932
Mac: https://github.com/rust-windowing/winit/pull/1890
There are now PRs for both mac and linux implementations. Making good progress.
For those that need a workaround while this is getting fixed, you can input any character into the current text buffer by typing the following (from Normal mode):
:r!echo 'YOUR CHAR(S)'
Aliasing echo to sth. like e might make the process slightly less annoying
I just can't get enough of these cursor animations :sweat_smile:
I've set my window manager to swap escape and caps lock but it doesn't work in neovide (they are not swapped), will this fix my issue too point_rightpoint_left ?
this seems to have been fixed on the opengl branch now, nice
edit: caps lock works like escape (nice) but when caps lock is enabled using esc, the letters in neovide are still small
I am using uncap, but it doesn't work.. Is this related to this issue also?
this is fixed on opengl branch
Hello!
Will this merge (once a new release comes), also solve the issue with having a Swedish keyboard? Currently when I try to do several different keys it gives me a different character than I expect. E.g. [ turns into something different than it should.
It should
I saw that rust-windowing/winit#1788 is now merged, so I compiled the latest from source on Windows. However, the input still appears to be broken at least with the Swedish layout.
Regular characters like åäö works fine, and so do most special characters. I did not find any broken ones in combination with shift, but alt-gr combinations have a lot of problems.
For example alt-gr+2 should produce @, but it just acts as ESC. On the other hand alt-gr+3 correctly produces £ for example, I don't really see any pattern, just that it's consistent.
Ah, sorry, I did not read everything properly, it needs to be integrated into neovide too
Yeah we need to do integration work on our side first. Theres an open PR which attempts this, but I think there will be some more fiddling on top of that.
https://github.com/Kethku/neovide/issues/691 tagging here. I think it will be necessary to switch to scancodes for linux machines while we wait for the upstream PRs to merge.
Alternatively I may try to make a fork which pulls both the linux and mac versions of the keyboard changes
https://github.com/Kethku/neovide/pull/736
This integrates the new keyboard api by depending on my merged forks of the upstream keyboard pr branches.
This brings us up to the current level of capability. I would appreciate if folks here could try this PR and let me know:
This way I can iterate on the PR a bit. I think the new PRs will let us do something that works how people expect, but it will probably need some fiddling
I can't wait for a new build with this! I love Neovide, but since my default keyboard is a Swedish one I can't use it for everything yet. :D I still do when I code though since I use the US layout for that. But once this is integrated I will be able to use it for all! :)
Thanks for all the good work!
I tried that branch, and I found no issues (Archlinux Gnome/Wayland, standard 105 keys keyboard layout).
(I still cannot use it daily becouse of rendering issues in #723, but at first glance all keys/combinations working as expected)
I’ve tried the branch keyboard-rework and it seems to work.
French (BEPO), which is a dvorak-like layout for French.h, k… are remapped to r, s…w is remapped to éà, ê or <space>àé, ç… in insert modeThis is very promising, thanks a lot for your work on this branch!
dvorak. The bug also happens to me on standard QWERTY.ihello world<S-1> the special k... wait why is everything stuck in caps<ESC>ohow do I exit<ESC><S-;>q<S-1><Return>
(exits)Some additional notes:
@danielrparks I have the same bug as you, except that it happens for all modifier and that I can’t reproduce it as consistently (pressing a modifier rarely triggers it).
Ok that's a valuable hint. I have some ideas
@cljoly, @danielrparks I pushed a small change that I think should address the modifiers issue. Can you try again?
That's fixed the shift-stuck bug, but now I found a new one.
I use auto-pairs to automatically insert closing symbols. In this build, auto-pairs only works on symbols that are not shifted, like ``, [], ''. It does not automatically complete pairs for (), {}, "", <>. On standard terminal neovim, it works as expected.
I’ve tried the branch
keyboard-reworkand it seems to work.
:+1: Extra data point, works here too. Arch, sway, US layout (altgr-intl variant). Thanks for the awesome work!
Agreed. However IME support in sdl2 is not good either. I think at this point supporting multiple windowing systems is not the way to go, so I'm going to be moving to switch to winit only once the upstream changes land. At that point, we can work with them to get IME support working for real on the relevant platforms.
Just want to make sure, is the progress of IME support also being tracked here? I think they are two different issues. The keyboard layout problem seems to be nearly fixed, but I don't know the status of IME support. Perhaps it will be better if we can track the progress of IME support in a different issue. I'm using the US keyboard layout but sometimes use fcitx5 to input Chinese. I subscribed to this issue, but I actually don't care about the progress of the keyboard layout problem.
After #723 is fixed, i'm tried to use this branch again, and found another bug:
When i press % it moves between matching braces, this is works.
But, in raw neovim it also moves between opening/closing html tags, this part is now broken.
Hi, I tried out the keyboard-rework branch, and I've had some interesting results trying out a bunch of key combinations.
I noticed that when I maximize the Neovide window using Win+UpArrow I get some weird character sequences. Here are some examples for some key combinations:
AltGr Shift è (should output {) --> <S-D-{>AltGr Shift + (should output {) --> <S-D-}>Tab (should output a tab character) --> <D-Tab>Alt Tab (should switch to another window) --> <M-D-Tab> and switches to normal mode.If I instead don't maximize the window or I maximize it using the title bar button I get the correct keys.
OS: Ubuntu 20.04
Keyboard layout: QWERTY Italian
In the same vein as what @last-partizan noticed, using % to move between begin/end environment statements in vimtex is also not working. Instead, it tries to move between the curly braces.
For example, instead of moving from |\begin{enumerate} (pipe represents the cursor) to \end{enumerate|}, it moves from |\begin{enumerate} to \begin{enumerate|} (it moves to the curly brace on the same line).
I tested it on Windows with the Swedish keyboard layout, and the dead keys don't seem to work correctly. But it's a big improvement from the previous version, since everything else seems to work.
More specifically dead keys followed by a space or an unsupported character don't work. For example
¨ followed by e correctly outputs ë
¨ followed by <space> incorrectly outputs <space>, but it should output ¨ (notice that the space should not be output in this case)
¨ followed by d incorrectly outputs just d, it should be ¨d
¨ followed by another ¨ incorrectly outputs nothing, it should be ¨¨
All the dead keys ¨^~´` behave the same way
Especially the second case with space is very important since that's the only way to ouptut common symbols like `~^, althought I suspect that some people who don't know better might rely on the last case and press the dead key twice and then delete the extra character.
That's fixed the shift-stuck bug, but now I found a new one.
I use auto-pairs to automatically insert closing symbols. In this build, auto-pairs only works on symbols that are not shifted, like ``, [], ''. It does not automatically complete pairs for (), {}, "", <>. On standard terminal neovim, it works as expected.
Same for me on those two points.
OS: Arch Linux with Sway (wayland)
I tested it on Windows with the Swedish keyboard layout, and the dead keys don't seem to work correctly.
@fredizzimo I have the same behavior on Sway (wayland) with Arch Linux.
@fredizzimo @cljoly I suspected this would be an issue with dead keys. The problem is that I don't know what the correct behavior should be for handling both bindings in normal mode and text input in input mode. I think the PRs upstream give us tools which should make the problem tractable, but I don't know enough about common keyboard patterns with non qwerty keyboards to be confident in what changes are necessary.
A couple questions (I'll have more):
Answers to these questions would go a long way toward helping me know what the correct implementation of this stuff should be. I'm very much not an expert in this area, so fixing this would require some time and commitment to help me understand. Alternatively I would be happy to assist somebody if they want to dive in. Either way works for me
@Kethku,
Yes, dead keys can be a bit hard to understand until you have actually used them. But the behaviour we are looking for here is quite simple. Normally the terminal handles the dead keys, and Vim will only see the end result, so that's what should happen here too.
So to answer your questions,
^ (go to first non blank on the line), and the backtick ` for marks. To use them you would have to press the the dead key followed by space. So to go to the start of the line I would press shift+^ and then <space>. I don't know how common it is, but it's also possible to map things like nmap ë ihello, which would enter insert mode and type hello if I press ¨ followed by e. It's also possible to map the other way around, and I guess many people do that for example map ö ^, so that they can press the dedicated ö key instead.
Personally I have a programmable QMK keyboard, so I work around the problem by having a keymap that sends the space combination by default, with the actual dead keys are on another layer.
altgr+~ and then shift+a for Ã. I'm also fairly sure that you should pass the modifiers that were held down at the moment the second key was pressed to Vim. A final note. Most keyboard layouts have simple dead keys with just two key presses, but some layouts have chainable dead keys, where you can press two or more dead keys in any order followed by the key to modify. I don't know how popular those are, and if they need to be supported, but the principle for supporting them is the same, wait for the final modified character and pass that to Vim along with the modifiers. But it can go even beyond that, for example, I know that the Vietnamese keyboard layout has a slightly more complex variant of the dead keys, and that the Japanese and Chinese input methods are completely different.
I don't know how common it is, but it's also possible to map things like nmap ë ihello, which would enter insert mode and type hello if I press ¨ followed by e.
I have a few mappings on things with dead-keys, it works quite well in the terminal. I’m not saying it is hugely popular though.
I'm also fairly sure that you should pass the modifiers that were held down at the moment the second key was pressed to Vim.
That’s the behavior I have with Alacritty.
Ok I've made another stab at better dead key handling: https://github.com/Kethku/neovide/tree/keyboard-deadkey-handling
Can you try this and let me know if it works how you would expect? I don't have time now, but I will explain the logic later if that would help. The important logic is here: https://github.com/Kethku/neovide/blob/keyboard-deadkey-handling/src/window/window_wrapper/keyboard_manager.rs#L155-L170
@danielrparks I think the keyboard-deadkey-handling branch may address your shift key-auto pair problem. Could you try again on that branch?
Everything seems to be working properly for me now, including auto-pairs and using % to move between html tags / latex environment begin & end. Note that I don't use dead keys, but I do use the compose key. Input using the compose key worked as expected, including custom mappings from ~/.XCompose, and I was even able to map compose key combinations to neovim commands.
Thanks for putting so much effort into making sure neovide works for everyone!
Thank you @Kethku,
The dead keys seem to work perfectly now, at least for the cases I can think of.
Here's my (non-working) setup:
If I type option-8 (which is { in my layout), I just get dropped out of insert mode. The relevant log events are
TRACE [neovide::channel_utils] ui_command Keyboard("<M-8>")
TRACE [neovide::redraw_scheduler] Next frame queued
TRACE [neovide::bridge::ui_commands] Keyboard Input Sent: <M-8>
Thanks @Kethku, in every way I could think of, dead keys work for me as well, in particular the mappings on dead keys.
@clason what happens in terminal vim for your use case. Alt in base vim escapes from insert mode. Its possible that your use case will need some setting for langmap :(
Well, obviously in terminals it works as expected, or I would never have started using neovim :)
(To be honest, that's the first time I heard that alt is not a modifier key but escapes insert mode on US keyboards...)
But, yes, input handling needs to be language (or layout) specific, I'm afraid. Since the base keys work now (which was not the case until recently), I had assumed that the plumbing for that was already in?
According to the wikipedia page linked by @clason, those additional characters are accessed with AltGr. I think the problem is that neovide is seeing it as plain Alt and not AltGr.
Well, AltGr is the German name on the classical Windows keyboard. (I no longer have access to a Linux workstation, sorry.)
On macOS it's just the Option key, either left or right (M- in the log above).
So it's maybe less a problem of being language-specific (which seems to be taken care of now) and more of (also) being OS-specific.
What I mean is that to work correctly, I think neovide needs to treat it like AltGr in that situation. I agree that this is probably a macOS-specific thing, as both Windows and Linux separate AltGr from Alt.
Right, yes, that's pretty much what I meant, too ;)
Ok so I think the thing I have to do now is get a version of the winit keyboard tester app compiled using the macos keyboard rework branch https://github.com/maroider/winit_keyboard_tester so that we can report the issue upstream
Specifically we would report the issue here: https://github.com/rust-windowing/winit/pull/1890
Specifically, you want to distinguish Alt and Meta on macOS (with Option mapping to Meta).
@clason I've commented on the relevant PR upstream. On windows holding the right alt and pressing 8 correctly reports { when using a german keyboard layout. So I think the mac version of the upstream keyboard api rework has a bug.
https://github.com/rust-windowing/winit/pull/1890 to be specific, I commented here
I found another bug on Linux/Wayland:
In terminal neovim Shift + Right Arrow moves cursor to the end of the word, in neovide - it doesn't.
Interestingly, Ctrl + Arrow, which does the same, _does_ work.
I've investigated and made a fix for the shift+arrow key issue. Also some awesome folks (@clason @smolck) have been helping me debug and fix macos specific issues.
Could folks here try again on main to see if any new issues have cropped up? I think we're getting close!
At least on macOS, the latest commit behaves the same as in terminal neovim (shift-right arrow jumps to the _beginning_ of the next word, same as w).
Could folks here try again on main to see if any new issues have cropped up? I think we're getting close!
Everything is still working correctly for me, AFAICT.
For me as well, everything still works correctly! 👏🏽
Shift + Arrow is fixed, i found no other issues today.
OK i think this is fixed! Thanks for the help everyone!
I think this can be unpinned now
Everything's working just fine, except that I can't use my compose key... (it seems like it just ignores the rwin press and inserts the compose sequence's characters verbatim)
I set it with setxkbmap -option compose:rwin
Since f0a46dbff9da43694ecff89a37bacd635788b653 I have some keybindings that use Shift in a sequence with
map <Leader><tab> :bn<cr>
map <Leader><S-tab> :bp<cr>
The Binding for next buffer works, for previous buffer does not. However, for me this is not a high priority issue, as I tend to have few buffers open anyway and usually :bn cyclically.
@jsosulski what's your OS?
Apologies if this is the an issue with the upstream PR mentioned above–is it a known issue that Neovim doesn't receive the "meta" modifier at all after these changes? For example, Alt + x Bash shortcuts don't work inside a term. I'm on macOS and I'm honestly not sure what the correct behavior is. The built-in terminal app has a "use option as meta" preference for this reason.
Yeah, I think that is the price to pay here -- you can't have option as both input and command modifier, and _not_ having the former makes the GUI unusable for people with certain keyboard layouts.
Only thing I can think of is to turn this into an opt-out feature by adding a configuration option. Not ideal, but /shrug.
@tpict Right, as clason said, that's intended; I was under the impression that there wasn't really a way of doing alt or meta mappings normally in the TUI nvim, and so it wasn't an issue to break them to fix this issue, because they were never supposed to work (pressing option+5 for example on US layout enters a character, ∞, and so can't really be used as a keybinding; or so I thought).
If you don't use that macOS-specific functionality though, I could see how providing such a "option as meta" binding/setting could work/be useful. It would come with the caveat of not being able to type characters with option or option+shift as is usually the case on macOS, though (and might actually break dead keys as well).
@smolck I'm using KUbuntu 20.04 with Plasma/KWin 5.18 on Kernel 5.8.0 and nvim on nightly, i.e. 0.5.0
@clason @smolck Thanks both. I think the configuration option is the de facto solution considering it's what Apple did for Terminal.app. I have a bunch of Neovim mappings that use the M- modifier, so I'm definitely biased, but I don't think it's particularly uncommon to do so.
@tpict mind giving https://github.com/smolck/neovide/tree/alt-as-meta a test, with cargo run --features alt-as-meta? Should provide the functionality you're looking for I think.
@smolck Wow, thanks for the quick turnaround!
M- Vim bindings work as expectedAlt + t to swap words in a terminal worksAlt + e for "edit current line in $EDITOR" in a terminal does _not_ workI think Alt + e is behaving as a dead key?
@tpict Fixed now?
@jsosulski Mind giving https://github.com/smolck/neovide/tree/shift-tab-mappings a test? Should fix <S-Tab> mappings (seems to work for me from a quick test, at least).
@smolck almost–the shell receives the Alt + e event, but Neovim ignores the next keypress.
@tpict Hmm, so this is a more difficult issue . . . on US layout, pressing option+e results in the dead key ´, which then waits for the next keypress to see if it should enter a character like é. I have no idea how to disable that.
Since the macOS terminal is written in Obj-C or Swift, it can probably do some OS tricks that disable that waiting or even just disable the whole option+key to type something different altogether; regardless, I don't know how it achieves that functionality, so I can't even see if it's possible to do here.
Now, iTerm2 does have the same functionality and it's open-source, so I could look there, but I'm a little hesitant because it's licensed GPLv2 and I don't know if there are license issues with getting inspired by/using a derivative of the code it has to do that, so . . . kinda stuck right now.
An easy workaround is to just use a different key for the keybinding, but I know that's of course not ideal.
Actually, I think this is an upstream issue/feature that winit needs to deal with: https://github.com/rust-windowing/winit/issues/768
@smolck Hm, the fix does not work for me. I tried both <S-Tab> and <S-tab> if that would make a difference. But at least in my shortcut with a leader sequence it does not work. My leader is space if that is relevant.
Ok I was worried about this issue. I believe that most of the problems can be explained by an inconsistency between macos handling of keyboard inputs and windows/linux handling. With the amazing help of @smolck and @clason we iterated on the current approach and decided that meta on macos should be ignored for certain keypresses in favor of handling keyboard layouts better. I'm now convinced that the solution is just to fix the issue in the upstream PRs. I've created an comment on the relevant PR which captures the disconnect https://github.com/rust-windowing/winit/pull/1890#issuecomment-869165792. However it appears that movement on that PR is understandably slow.
I don't have the cycles at the moment to dig in to the winit codebase right now and understand whats going on from their side. Especially since I don't have mac hardware to test with. So I think the solution for the moment is to wait to see if movement happens on their side.
@smolck @clason I'm adding you two as collaborators to the project (no responsibilities here, just trying to give flexibility). I'm going on a couple day trip so I won't be around for a bit to more directly help out here. When I get back though I'm going to take another stab at this.
@jsosulski your issue is a different problem though that should be addressable. Just need to find the time to figure it out. We may need to special case text characters that don't have a capital variant (such as tab) and send shift for those characters even when we don't for alphanumerics.
@smolck Hm, the fix does not work for me. I tried both
<S-Tab>and<S-tab>if that would make a difference. But at least in my shortcut with a leader sequence it does not work. My leader is space if that is relevant.
@jsosulski Hmm, that's weird, I tested using :map <Leader><S-Tab> <cmd>lua print('works')<cr> and it works fine for me. My leader is different from yours though, ;, maybe that makes a difference? I don't see why it would though . . . could also be because I'm on macOS, but I really doubt that . . .
@jsosulski your issue is a different problem though that should be addressable. Just need to find the time to figure it out. We may need to special case text characters that don't have a capital variant (such as tab) and send shift for those characters even when we don't for alphanumerics.
That's exactly how I'm fixing that issue with https://github.com/smolck/neovide/commit/4a9377565d1d6ccf97aa1b9ad8b71b6bf1489856, just have to see why it's only working locally if that's indeed the case. I can't think of any other keys like tab that aren't changed with shift but I could add those if there are any.
@smolck @clason I'm adding you two as collaborators to the project (no responsibilities here, just trying to give flexibility). I'm going on a couple day trip so I won't be around for a bit to more directly help out here. When I get back though I'm going to take another stab at this.
Awesome, thank you!
Also, @Kethku maybe a new issue should be made for these remaining problems? Obviously it works/is easier to just keep things here, but the issue in the title, trying to input text with other keyboard layouts, is fixed; all that remains are weird edge cases with keybindings, it seems.
@smolck Hm for what it's worth, it seems the issue was with my vimrc. With a blank one containing only the one
Most helpful comment
OK i think this is fixed! Thanks for the help everyone!