This is the mail archive of the cygwin@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: cygwin 1.3.2 bug on non-us keyboard layouts


Hi, Marius, :)

On Tue, 19 Jun 2001, Marius Gedminas wrote:
> On Fri, Jun 15, 2001 at 02:35:03PM -0700, Jason Tiller wrote:

> AFAIK AltGr is equivalent to both Ctrl an Alt (with some
> exceptions).  For example, kbd.h from Windows NT DDK says:

>    Keyboards using AltGr as a Modifier Key usually translate the
>    Virtual ScanCode to Virtual Keys VK_CTRL + VK_ALT at input time:
>    the Modifier tables should be written to treat Ctrl + Alt as a
>    valid shifter key combination in these cases.

> I've performed some tests on Windows 2000 and Windows 98 with German
> (Standard) and US English (International) both of which use AltGr.
> Microsoft Spy++ indicates that pressing AltGr results in two
> WM_KEYDOWN (and later WM_KEYUP) events sent: one for VK_MENU and
> another for VK_CONTROL.  Besides, all the third level characters
> accessible with AltGr can also be typed by holding (either of) Ctrl
> + left Alt.

> On Windows 2000 the same behavior can be observed with
> ReadConsoleInput: holding down AltGr results in events sent with
> both RIGHT_ALT_PRESSED and LEFT_CTRL_PRESSED bits set in
> dwControlKeyState.  Also note that even with US English 101 keyboard
> layout (which doesn't have AltGr) one cannot input characters with
> Ctrl + Alt -- ReadConsoleInput always returns UnicodeChar == 0 in
> this case (this is also docummented in the kbd.h from WinNT DDK
> mentioned above, under the section `AN EXAMPLE OF VALID AND INVALID
> MODIFIER KEY COMBINATIONS').  Therefore on Win2000 (and I think
> WinNT 4.0 ought to be the same) it is possible to detect AltGr by
> checking if CTRL and ALT flags are both used.

Sounds like you're saying that when uChar.AsciiChar != 0 &&
dwControlKeyState has both the control (LEFT or RIGHT) and alt (LEFT
or RIGHT) set, you can be assured the keystroke is generated via AltGr
and should not be treated as META.  Am I reading that right?

> Unfortunatelly, Windows 98 only passes RIGHT_ALT_PRESSED in
> dwControlKeyState when you use AltGr.  Also, in a console window
> Ctrl+Alt isn't considered to be equivalent to AltGr (while it is in
> all other windows).

Ugh.

> I'm therefore afraid that it is only possible to achieve sane behavior
> on WinNT family of systems.

>      /* Determine if the keystroke is modified by META. */
>      const DWORD key_state = input_rec.Event.KeyEvent.dwControlKeyState;
>      if ((key_state & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) == 0
>          || (key_state & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) != 0)
>
>   This also has the following advantages:
>   - Ctrl+Alt is uniformly treated as equivalent to AltGr uniformly
>     throughought the system
>   - The actual keyboard layout selected at the moment of the keypress is
>     used to determine the behavior of right Alt key

>   Note: since nothing prohibits the keyboard layout to allow
>   Ctrl+Alt+x keystrokes to generate ^x characters, it might be
>   worthvile to add an additional check for (ich >= 0 && ich <= 0x1f
>   || ich == 0x7f) and add META prefix in that case.

*Sounds* good!  Yeah, I think you hinted about that above.  You're
saying that none of the characters generated via AltGr have their
ASCII values in the range of 0->31 or 127 (control characters)?

> Possible solution for Win9x:

>   Do it like it is done now.  So far I've been unable to find a
>   better way to determine if the primary keyboard layout uses right
>   Alt as AltGr, but maybe I just didn't look hard enough?

It might be possible to try to rely on the physical keyboard layout as
opposed to the primary language, as we do now.  The
GetKeyboardLayoutName() API seems to do a better job of indicating the
specific physical keyboard layout than GetKeyboardLayout does.  I
couldn't find any constants or enumerations to reliably translate the
physical keyboard layout values from GKL() (high word) - the various
LANG_ and SUBLANG_ constants don't *really* apply.  However, GKLName()
specifically returns a string indicating physical layout (US English)
and sub-type (Left hand Dvorak, for example).  In fact, you can narrow
the keyboard layout to the various English variants by looking at the
last four characters of the constant returned by GKLName() - the
English variants will always have "0409" as the last four characters.

Bummer that the (International) English variant uses AltGr!  Otherwise
this would have been a reasonable solution, at least for the
brain-dead Win9x problem.

>   Maybe it would be a good idea to add something like the initial
>   proposal for CYGWIN variable to allow the user to override
>   incorrect guesses

That was my original proposal, but Chris vetoed that as he felt adding
to CYGWIN was not an acceptable solution.  I still think this is the
cleanest and simplest method, however...

>   (hey, I can use primary language US English with
>   a US English (International) keyboard and then I have AltGr).

Hmm.  US English (International) uses AltGr?  None of the other US
English layouts do, as far as I can tell.

>   I'm afraid that requires distinguishing between WinNT/Win9x at
>   runtime, and therefore in the combined solution the simple test
>   ... becomes

>      /* Determine if the keystroke is modified by META. */
>      const DWORD key_state = input_rec.Event.KeyEvent.dwControlKeyState;
>      bool meta;
>      if (THIS_IS_WINDOWS_NT)
>          meta = (key_state & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) != 0
>              && (key_state & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) == 0
>              || (ich >= 0 && ich <= 0x1f || ich == 0x7f);
>      else
>          meta = (key_state & meta_mask) != 0;
>      if (!meta)
>        ...

> What do you think?

> Is sane behavior on sane systems (i.e. NT) worth the additional
> complications?

Hmm.  Without testing, it looks good so far.  Sux that it has to get
this complicated.  BTW, when combined with using GKLName() instead of
GKL() when defining the meta_mask, this might be the best of both
worlds.

> If so, I could write a patch to implement the proposed
> combined solution that I described above.  Or maybe I should write a
> small console application that implements this heuristic so that people
> with different keyboard layouts can test it on different systems and see
> how this heuristic performs in practice?

A small app like this would be helpful.  As I've already discovered,
there are *lots* of possible combinations waiting to pounce on overly
simplified code! :)

Thanks for looking into this!

---Jason
Sonos


--
Want to unsubscribe from this list?
Check out: http://cygwin.com/ml/#unsubscribe-simple


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]