Friday, July 21, 2006 12:16 AM
Michael S. Kaplan
The complexities of keyboard layout switching
Chris was thinking about how keyboard layouts work on Windows, and suggested:
Windows allows a user to set up multiple keyboards within an input language, and switch between them either by a keyboard shortcut or by clicking an icon on the taskbar. However, when the keyboard layout is changed, the change is only applied to the current window.
This behaviour is extremely confusing to users, as the characters that appear as they type then vary from window to window. By default, using the keyboard shortcut or clicking the taskbar icon to select another keyboard, the new keyboard should be used in all windows.
If it is necessary to keep the old behaviour, this should be done via a (non-default) check-box on the "Language Bar" tab of the "Text Services and Input Languages" applet.
It is an interesting idea, and also a difficult one. The list of installed keyboards (which actually means the list of enabled keyboards) is a per user setting on a machine. And, as Chris mentioned, every language can have more than one keyboard attached to it.
So, let's say that I have English and Korean enabled, with multiple input methods on each:

If I look at the Language Bar, I have the option of choosing the language:

and then also the keyboard layout under the language once it is selected:


Thankfully, the selection mechanism is smart enough to remember the selection in each language. So that if I
- switch to Korean,
- switch to the Korean Input System (IME 2002),
- switch to English,
- switch back to Korean
It is smart enough to remember that I switched to that specific IME. This is as good thing.
Now we move to the complicated part -- the fact that actual, specific combination of language and layout is a per thread setting. This has been the design for a long time and it usually leads to two potentially non-intuitive behaviors:
- If you change the language, it will only apply to that one specific thread, and switching to any other UI thread in any other process will not follow the original thread's change.
- If you change the keyboard layout within a language, it will once again only apply to that one specific thread, and switching to any other UI thread in any other process with the same language will not follow the original thread's change.
Now that first point is longstanding behavior that is often relied on by people (including me!), and although it is not immediately intuitive it does kind of make sense, especially when one finds oneself e.g. typing a document in a particular language and not expecting that to lead to changes in one's email program....
The secone point is the one that Chris is talking about. Any time one changes the keyboard layout for a language, then isn't it often more likely that you would perhaps expect that switch to be applied to all other UI threads in the session that use this language?
Clearly there are exceptions here (plus there is a legacy expectation that some people may be used to), but that is also why Chris is suggesting some kind of configurable switch. I tend to agree with Chris that the change here is more likely to meet the intuitive expectations of customers, don't you?
This kind of change is complicated for someone to do themselves -- there would need to be a call to SetWindowsHookEx to inject a DLL into every thread to run code to check GetKeyboardLayout -- and if the languages (in the LOWORD) match and the device (in the HIWORD) do not then make a call to ActivateKeyboardLayout to make the switch.
Yuck.
But if you look at the Language Bar and the Text Services Framework, it already has a little something running in every thread, managing this information. So it is in a much better position to architect the kind of cross-thread, cross-process communication that might be required here.
Not an easy change, by any means. But an excellent feature request that is definitely worth considering for a future version of Windows. Good idea, Chris! :-)
This post brought to you by ђ (U+0452, a.k.a. CYRILLIC SMALL LETTER DJE)