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,

On Fri, Jun 15, 2001 at 02:35:03PM -0700, Jason Tiller wrote:
> > Actually, some non-US keyboards also do not use AltGr.  I use a
> > nonstandard "Lithuanian (Programmers)" layout which uses dead keys,
> > and I'm quite used to have both Alt keys work as META.
> 
> Hmm.  Sounds like defining the exact conditions (without user input)
> that determine when AltGr should be interpreted as META is more
> challenging than originally thought (but isn't it always that way?).

Unfortunatelly, yes.

> > The best solution would be to see how the selected keyboard layout
> > defines the right Alt key.  I don't know if that's possible.  I'll
> > try to look into this on MSDN.
> 
> Hmm.  I don't know if MapVirtualKey would do it or not.  I'm certainly
> interested in any ideas that you have!  I don't purport to be an
> expert at this, not at all...

Well, I'm not an expert either.

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.  This also does
the right thing if the user actually uses Ctrl + Alt (the left one),
since this combination is treated as equivalent to AltGr both in normal
and in console windows.

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).

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

Possible solution for WinNT:

  Do not use meta_mask.
  In fhandler_console::read change the test from

     /* Determine if the keystroke is modified by META. */
     if (!(input_rec.Event.KeyEvent.dwControlKeyState & meta_mask))

  to

     /* 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.

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?  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 (hey, I can
  use primary language US English with a US English (International)
  keyboard and then I have AltGr).

  Two notes:
  - Ctrl+Alt isn't uniformly treated as equivalent to AltGr by Windows
    itself.
  - It is impossible to change the actual keyboard layout for a console
    window.  I think it's impossible to change the default keyboard
    layout without rebooting (at least I couldn't find a way).

Combined solution:

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

     /* Determine if the keystroke is modified by META. */
     if (!(input_rec.Event.KeyEvent.dwControlKeyState & meta_mask))
       ...

  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?  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?

Marius Gedminas
-- 
If it wasn't for C, we'd be using BASI, PASAL and OBOL

--
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]