Mailing-List: contact cygwin-help AT sourceware DOT cygnus DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT sources DOT redhat DOT com Delivered-To: mailing list cygwin AT sources DOT redhat DOT com Date: Tue, 19 Jun 2001 00:59:15 +0200 From: Marius Gedminas To: cygwin AT cygwin DOT com Subject: Re: cygwin 1.3.2 bug on non-us keyboard layouts Message-ID: <20010619005915.A8921@gintaras> Mail-Followup-To: cygwin AT cygwin DOT com Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.3.18i X-URL: http://ice.dammit.lt/~mgedmin/ 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