Closed GoogleCodeExporter closed 9 years ago
Ok, should be relatively easy. The second number is produced by calling:
UINT key2 = MapVirtualKey('Q', MAPVK_VK_TO_VSC);
...etc.
I changed the layout to "French" (manually) between the two dialog boxes; both
still output positional keys. Yay~
We _could_ add support for MSKLC. But perhaps I'll just build a profile and
automatically update KeyMagic to a "US" layout. I don't think this is terribly
wrong; it'll actually INCREASE compatibility for the next release.
We should be able to update the Virtual Keyboard too, eventually. For now, at
least we should "auto-US" the keyboard when typing in KeyMagic.
Original comment by seth.h...@gmail.com
on 18 Jun 2010 at 9:02
Attachments:
We can detect when the input language has changed by processing:
WM_INPUTLANGCHANGE. We can also compare:
LOWORD(GetKeyboardLayout(0))
..to:
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)
At this point, we can generate an "input map" between keys. For example, 'a' on
the French keyboard maps to 'q' on our "assumed" US keyboard.
Note that, for the en_US encoding, we should ALWAYS return the default key. (In
other words, en_US should NOT try to use MapVirtualKey). This way, if there's
some bizarre conglomerate keyboard install which crashes WaitZar, we can simply
instruct users to switch to a US keyboard layout first.
Note that RomanInputManagers should not transform keys, since we want users to
type with whichever layout they are most comfortable.
Original comment by seth.h...@gmail.com
on 18 Jun 2010 at 9:17
Here's what I propose:
Promote VirtKey into a full class.
Add a static method, VirtKey::SetLocale(). This is called every time the locale is switched.
Add a function (or alternative constructor) which takes the current Locale() into account and changes the alphanum value based on this.
If the Locale is en_US, then don't perform any changes.
That way, we can basically just sprinkle convert() functions on our existing
vkeys.
But this will have to wait until after the help keyboard is fixed.
Original comment by seth.h...@gmail.com
on 18 Jun 2010 at 9:49
[deleted comment]
Thanks for the links. I'll make sure that different layouts won't crash
WaitZar.
Anyway, thanks for pointing this out; this is the first version of WaitZar that
uses virtual key codes for letter-based input, so I can fix this bug before the
official release. :)
Original comment by seth.h...@gmail.com
on 18 Jun 2010 at 11:02
Note: Our approach assumes that the keyboard layout cannot change for the life
of a VirtKey. This is true (since changing the layout requires generating a
message) but it also means that we can't hold on to virtual keys past a single
processing. (This makes sense).
Original comment by seth.h...@gmail.com
on 21 Jun 2010 at 11:10
Fixed. Filed a new issue for cleaning up VirtKey a little, but for now our
solution works just fine.
Original comment by seth.h...@gmail.com
on 21 Jun 2010 at 6:33
Re-opening. Apparently GetKeyboardLayout() doesn't work for console programs.
(This is documented in a few places.)
We have to figure out why, and how to get around it.
Original comment by seth.h...@gmail.com
on 21 Jun 2010 at 6:36
Update, after some fiddling:
We can't use AttachThreadInput() and just pump the console's messages for it (I
think, because the Locale-changing event will have already passed, and in
general it seems like the kind of idea that won't work.)
We can't use a system-wide hook for HSHELL_LANGUAGE events, since that will
require a DLL (and system hooks are non-ideal anyway for other reasons).
Nonetheless, the local is detected SOMEHOW, since the console receives updated
keystrokes. So... is there some way to detect "the current locale as seen by
windows" ?
Original comment by seth.h...@gmail.com
on 21 Jun 2010 at 7:00
We _might_ be able to use "AttachConsole" to borrow the console and add it to
WaitZar, then retrieve its STDIN handle, then call "ReadConsoleInput", and
finally process KEY_EVENT_RECORDs, which contain scancodes.
This is a bit of a long shot, though, along with being a pain for debugging.
Perhaps there's a better way?
Original comment by seth.h...@gmail.com
on 21 Jun 2010 at 8:23
Interesting fact: Myanmar text won't work in a console anyway. So users
shouldn't be using both.
Still, that's not an excuse. The icon in the lower-right clearly states that
the Layout has changed. I'm sure it uses the equivalent of a hook, but there
should be a way to access this exposed _somewhere_. It seems like a sensible
thing to be able to do! I will spend some time looking for this... perhaps I
can enumerate the current "layout" of ALL active windows; maybe the IME has its
own specific Window that it changes over time? (I remember seeing an IME window
waaaay back when working on WZ 0.1).... Even something experimental (with a
config option, of course) is better than nothing.
Nonetheless, we won't be attaching to consoles; it's not worth the effort if WZ
won't be able to input text there anyway...
Original comment by seth.h...@gmail.com
on 21 Jun 2010 at 8:31
Scanning for all non-English IMEs and then following the chain backwards
through their parents shows that an "MSCTFIME UI" window with a parent of
"Default IME" is attached to each Console, and the language for either of these
is correct.
It appears that all windows have these as children. I remember that "Default
IME" might not appear in Windows when only the default typing method is
installed. Still, we can do a child-window search for "Default IME" OR
"MSCTFIME UI", and just return the top-level window's locale if this fails.
Definitely better than nothing, especially since our users will likely have at
least one keyboard/IME installed.
Original comment by seth.h...@gmail.com
on 21 Jun 2010 at 9:34
Attachments:
Technically (using GetAncestor()) the Console isn't a PARENT of the IME; it's
an OWNER. This makes it more likely that we're on the right track (but now it's
slightly harder to track ownership...)
Original comment by seth.h...@gmail.com
on 21 Jun 2010 at 10:27
Got it! You have to use ImmGetDefaultIMEWnd() to get the WINDOW which acts as
the IME to this process. Attached is a log of checking that value against the
(known) value I found manually; they match if there's a "Y". Suffice to say,
this'll work fine.
It's a one-line fix, but I'm delaying it till later. I want to write up a full
solution so that others can find the answer if they search on Google.
Original comment by seth.h...@gmail.com
on 21 Jun 2010 at 10:47
Attachments:
Fixed. So, basically:
Preconditions: Calling:
HKL input = GetKeyboardLayout(GetWindowThreadProcessId(GetForegroundWindow()))
...will get the layout (locale, etc.) of the window WaitZar is considering.
This is the same window that the lower-right icon depicts ("EN", "FR", etc.).
Problem: If the top window happens to be a Console App, then it doesn't pump
its messages, so the Layout returned will be the one that the Console started
in. However, it WILL react to the current input, so typing, e.g. "q" in a
French layout will get you "a" with no obvious way to convert it back. (I.e.,
GetKeyboardLayout() will return "en_US".)
Solution: Each window clones a "Default IM" window (and sub-window, "MSCTFIME
UI" --or just "M" in earlier versions of Windows) when it's created. These are
"owned" windows, so enumerating child windows won't give you anything.
Enumerating backwards from top-level windows will get you to the Console app,
but a better way of doing this is to call:
HKL input = GetKeyboardLayout(GetWindowThreadProcessId(ImmGetDefaultIMEWnd(GetForegroundWindow())))
...or, if you're cautious:
HWND wnd = GetForegroundWindow()
HWND wnd2 = ImmGetDefaultIMEWnd(wnd)
HWND wnd3 = wnd2 ? wnd2 : wnd;
HKL input = GetKeyboardLayout(GetWindowThreadProcessId(wnd3)
...since ImmGetDefaultIMEWnd() can potentially return NULL. The IME Window is
always kept up-to-date on its owner window, so through a bit of mild irony, the
"child" knows more than the "parent" about what is going on.
Caveats: IM Windows aren't maintained unless East-Asian languages are
installed. But this seems odd, since a French keyboard layout should be saved
somewhere on a non-Asian computer anyway. I would guess that the "Default IM"
window (or something similar) is maintained on these systems too. However, I
wouldn't be surprised if WaitZar can't detect console layouts on
single-keyboard systems. I need to find a way to test this. At worst, it will
only cause consoles to malfunction on single-language systems (where the
language is non-Asian) but that's far better than "malfunctioning on all
systems" --and, again, it'll work in non-Console apps by falling back to the
owner window.
Marking fixed.
Original comment by seth.h...@gmail.com
on 22 Jun 2010 at 9:45
Original issue reported on code.google.com by
seth.h...@gmail.com
on 18 Jun 2010 at 5:30