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

W32 GUI: Ctrl+[ via Ctrl+dead^ (AZERTY, QWERTZ) #10687

Closed
wants to merge 1 commit into from

Conversation

haron13-2019
Copy link
Contributor

Provide Ctrl+[ via Ctrl+dead_circumflex on AZERTY, QWERTZ

This PR fixes second part (Win32 gvim) of #10454.

This is pretty "brute force" fix for UX regression introduced by
patch "8.2.4807: processing key events in Win32 GUI is not
ideal" (77fc0b0). Starting by
this revision it was not possible any more to generate ESC using
Ctrl+dead_circumflex on AZERTY keyboard layout in Win32 gvim.

Solution is found using trial-and-error approach. After AZERTY
solution was found, to check how generic it is QWERTZ (German)
Ctrl+dead_circumflex solution was found as well (made not big
sense as such but turned out to be good for generalization,
because windows handles Ctrl+dead_circumflex differently for
AZERTY and QWERTZ layouts, first solution for AZERTY was not
working for QWERTZ but QWERTZ was good enough for AZERTY. Hopes
are that other national layouts will be straight forward to add
if handling of CTRL+dead_key will ever be needed for them).

When we detect that Ctrl+dead_key is pressed, we check raw
vk+scan_code to be sure we are talking about specific key on the
keyboard. Condition that it is dead key is computed separately
already. So we restrict triggering of this fix to specific key on
the keyboard and to the fact that it is a dead key and that
now Ctrl is in hold state.

Firstly we inject WM_CHAR='[' into the message queue using
PostMessageW(). This will result in a call of _WndProc()
after this call of process_message() will return (state of
Ctrl is separately dermined by _OnChar(), therefore '[' will be
Ctrl+[). This WM_CHAR will be processed as very next event.

After that gvim will go into waiting state to wait for some
subsequent key presses from the user.

In that moment gvim application is situated into "dead key" state -
next vk+scan_code of the key pressed will be translated by ToUnicode() call
differently from "normal state": preceding "dead key" will produce
"cicrumflex"-variant of the char (a->â,u->û etc), so we need to
"expel" this state. Don't want 'â' if user pressed 'a'.

There is already that boolean^H^H^H^H^H^H^Hint flag "dead_key" in
gui_w32.c to track the "dead key" state. Simple boolean usage of
that flag seems not enough for our needs any more, therefore
"dead_key" meaninig is extended from plain boolean to a
enumeration of several possible values, see below.

Remember there was this preceeding _WndProc()->_OnChar()
call where we feed Ctrl+[ into vim internal event queue
(add_to_input_buf()).

Normally _OnChar() would reset vim variable "dead_key" value to
0. We want however to maintain our special state even after that
_OnChar() call - to be in-sync with windows point of view. To
achieve that, we introduce new value of the global "dead_key"
variable: DEAD_KEY_TRANSIENT_IN_ON_CHAR.

So, back to waiting for further user input. Remember, that
application is marked by windows as "after dead key was press"
and when we obtain this future key press from user we still will
have this knowledge via DEAD_KEY_TRANSIENT_IN_ON_CHAR value of
"dead_key" variable, which was not removed by first _OnChar()
call.

Now we need to expel the dead key status in a special way, which
seems only(?) be possible to accomplish by handling of that
"poisoned" keypress in our _WndProc. We call TranslateMessage()
where we replace the key press of user with ' '(VK_SPACE) - it
will translate to just one WM_CHAR='^' event posted into our
queue. We self-post as well original char as WM_KEYDOWN to be
processed with PostMessage and return from this process_message()
call. (Even if we would skip call of TranslateMessage, Windows
still will force us to confront with that dead char by put in our
queue WM_CHAR = '^' event, seems to default to that even without
us calling TranslateMessage() with VK_SPACE).

That's where second special value of "dead_key" variable is
introduced: DEAD_KEY_SKIP_ON_CHAR. We set it and let "poisoned"
char to go through our _WndProc() ignoring it in _OnChar().

After that we are dealing with self-scheduled WM_KEYDOWN event in
subsequent call of process_message(), which reproduces the
original user key press.

PS/Sidenote: Detected by the way, perhaps already reported. It
seems that CTRL+6 handling is changed as well since 8.2.4807 for
AZERTY layout. Before that patch both CTRL+6 and CTRL+SHIFT+6 has
generated CTRL+^, since 8.2.4807 CTRL+6 generates CTRL+§ (and
CTRL+SHIFT+6 still generates CTRL+^). One can consider this
change to be kind of improvement, and if somebody really need old
behaviour it can easily be achieved by the user per configuration
with mapping CTRL+§.

Provide Ctrl+[ via Ctrl+dead_circumflex on AZERTY, QWERTZ
@codecov
Copy link

codecov bot commented Jul 9, 2022

Codecov Report

Merging #10687 (1d37385) into master (99af91e) will decrease coverage by 0.00%.
The diff coverage is 0.00%.

@@            Coverage Diff             @@
##           master   #10687      +/-   ##
==========================================
- Coverage   81.71%   81.70%   -0.01%     
==========================================
  Files         158      158              
  Lines      185631   185649      +18     
  Branches    41980    41987       +7     
==========================================
+ Hits       151684   151692       +8     
- Misses      21485    21497      +12     
+ Partials    12462    12460       -2     
Flag Coverage Δ
huge-clang-none 82.62% <ø> (+<0.01%) ⬆️
linux 82.62% <ø> (+<0.01%) ⬆️
mingw-x64-HUGE 0.00% <0.00%> (ø)
mingw-x64-HUGE-gui 78.15% <0.00%> (-0.02%) ⬇️
windows 76.93% <0.00%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
src/gui_w32.c 34.64% <0.00%> (-0.23%) ⬇️
src/ui.c 74.33% <0.00%> (-0.27%) ⬇️
src/mbyte.c 72.04% <0.00%> (-0.14%) ⬇️
src/misc2.c 89.19% <0.00%> (-0.10%) ⬇️
src/regexp_nfa.c 89.98% <0.00%> (-0.04%) ⬇️
src/terminal.c 77.06% <0.00%> (+0.02%) ⬆️
src/gui.c 73.10% <0.00%> (+0.04%) ⬆️
src/netbeans.c 72.81% <0.00%> (+0.07%) ⬆️
src/term.c 73.93% <0.00%> (+0.15%) ⬆️
src/os_unix.c 67.91% <0.00%> (+0.17%) ⬆️
... and 1 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 99af91e...1d37385. Read the comment docs.

@brammool brammool closed this in 3f02667 Jul 26, 2022
ant0sha pushed a commit to ant0sha/vim that referenced this pull request Jul 30, 2022
New low-level keypresses testcase relying on "setkblayout"

reproduces problem which failed prior to 9.0.0087 (vim#10687, vim#10454)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants