keyboard switching and persistence

All development related issues welcome

Moderator: Moderator Team

Post Reply
hpd
Posts: 9
Joined: Sat Nov 28, 2015 3:49 pm

keyboard switching and persistence

Post by hpd »

I have some questions about the keyboard layout management. A keyboard layout different from the installed language currently is not properly supported. This means for e.g. a German keyboard in English locale:
- after boot the keyboard always is set to EN, regardless of the previous setting
- switching the keybord by tray icon shows random behaviour (icon state differs from active layout)

The MSDN documentation on LoadKeyboardLayout is somewhat inconsistent across versions. Former docs (NT4?) state that the setting applies to all processes, while the current docs restrict the setting to the current thread or process (depending on KLF_SETFORPROCESS). This raises the question, how the system wide (boot...) keyboard layout can be activated, and what is considered the "current" thread or process.

Reality check: usually only one physical keyboard is attached to a machine, so that the physical layout of that keyboard (key count, arrangement and key labels) must be reflected by the default (system wide) keyboard handler. Later on a *user* may specify a different *logical* handling, like Dvorak or EN instead of GE - this setting IMO should be specific to the *user*, not to a process or thread. Finally a *process* may request a different keyboard layout, and *only in this case* the current documentation of LoadKeyboardLayout (API!) makes sense to me.

This suggests to me multiple layers of keyboard handling:
1) system wide setting, reflecting the physical keyboard and default character mapping
2) user specific setting, affects only the translation of scan codes into character codes
3) process specific setting
4) thread specific setting

Now I guess that Microsoft restricted the formerly system-wide scope of LoadKeyboardLayout to API calls only, while a system internal function (NtUserLoad/ActivateKeyboard...?) was added for kernel usage (KPI? ;-). Above settings with different scopes could be implemented by adding further KLF_SETFOR... flags, which are invalidated (cleared) in the API functions.

Another doc change now states: "The input locale identifier specifies a locale as well as the phyiscal layout of the keyboard."
I'm not sure how this should be implemented, regarding two aspects:
1) the phyiscal layout should be changed only when a different physical keyboard is attached. I'm not sure how the caller can know that layout, so that bad changes can be prevented. The user instead should know about the layout of the keyboard he just attached, in this case the change must be honored.
2) how can a user specify above indentifier in a way, that allows to specify *both* the physical layout and a locale? I couldn't find yet an according Windows settings dialog.

I'd like to contribute according patches, but currently I only could scratch the implementation surface. At least I feel a need for more powerful internal functions, usable in configuration dialogs or services (kbswitch.c), which can be implemented without changing the documented API. Such a separation would also allow to emulate different Windows versions, which can be handled transparently in the API functions wrapping the kernel functions.

Any comments or hints?
DoDi

Forever Winter
Posts: 131
Joined: Sun Oct 20, 2013 6:50 am

Re: keyboard switching and persistence

Post by Forever Winter »

To set the system wide keyboard layout, see SystemParametersInfo (with SPI_SETDEFAULTINPUTLANG as the desired action). As for the "current" thread/process, it is normally the thread/process that calls
the function in question (LoadKeyboardLayout in this case).

hpd
Posts: 9
Joined: Sat Nov 28, 2015 3:49 pm

Re: keyboard switching and persistence

Post by hpd »

Many thanks for the keywords :-)
The related documentation clarifies what's wrong with the current implementation. The use of LoadKeyboardLayout in OS code can be considered wrong, at least in kbswitch and during boot. Now I can find the places where the sources should be modified.

This bug is already known, but the issue (CORE-4896) was closed.
SPI_SETDEFAULTINPUTLANG still not implemented?

Forever Winter
Posts: 131
Joined: Sun Oct 20, 2013 6:50 am

Re: keyboard switching and persistence

Post by Forever Winter »

Why can it considered as wrong? At least in kbdswitch.exe/input.dll the call does exactly what is required. That it affects only the current thread/process is by design and the layout is not set
for the entire system is by design. For example consider that you write, at the same time, a letter in chinese, a news article in russian and a bug report in english. If you have to permanently
switch between keyboard layouts manually, it would be a real pain.

SPI_SETDEFAULTINPUTLANG works mostly fine for me. You can test it with "Set Default" from the "Text Services and Input Languages" dialog (You may have to reopen your windows to take effect).
Note that it is the responsibility of the caller to safe the settings to the registry. One of the bugs is that it is not saved in ReactOS. While the code to do it is there, it does not get called (or does fail).
Another bug or unimplemented feature seems to be the fact, that upon logon, the keyboard layout gets not loaded from the user profile settings. Instead, it seems to stick with the one from the
default profile (but changing it manually does not always work for me).

hpd
Posts: 9
Joined: Sat Nov 28, 2015 3:49 pm

Re: keyboard switching and persistence

Post by hpd »

Why can it considered as wrong? At least in kbdswitch.exe/input.dll the call does exactly what is required. That it affects only the current thread/process is by design and the layout is not set for the entire system is by design. For example consider that you write, at the same time, a letter in chinese, a news article in russian and a bug report in english. If you have to permanently switch between keyboard layouts manually, it would be a real pain.
After some more experiments (on WinXP) I agree that the tray icon should affect the *currently active* process only. Then the bug becomes more of a flaw, because the following problems continue to exist (maybe reproducable or random):

1) The "current" thread is not always identified correctly. Changes may or may not be reflected in an application.
2) Changes apply to multiple (all?) currently running processes at once.
3) Switching amongst applications of different settings is not reflected in the tray icon. This may be a consequence of (2).
4) The desktop (user?) process should have its own keyboard setting, which is used for subsequently started processes.

Now I suspect that (at least) the keyboard settings are not managed at process level, instead apply to all applications immediately. These temporary settings IMO should not be reflected in the registry, eventually except for the user/desktop process/thread, see (4).

Once that missing process isolation is implemented, the beforementioned misbehaviour (1-4) can be checked again.

Forever Winter
Posts: 131
Joined: Sun Oct 20, 2013 6:50 am

Re: keyboard switching and persistence

Post by Forever Winter »

Since the desktop is created by the explorer, you would give explorer its own settings. But what would be the advantage over using the ones from the user profile?
As for your flaws 1 - 3, it should be noted that kbswitch from ReactOS does not implement this functionality (corectly), so this could also be a possible source of the
mentioned flaws, besides missing management at the process level. As for saving the settings to the registry, what I meant was to save the choosen default user
profile layout when using SystemParametersInfo in conjunction with SPI_SETDEFAULTINPUTLANG, not the ones for individual processes.

Edit: A quick look at the source of kbswitch sugests, that it indeed does not implement switching the layout on a per-thread basis. For example, when the user
changes the layout, it sends WM_WM_INPUTLANGCHANGEREQUEST to all windows found by EnumWindows.

hpd
Posts: 9
Joined: Sat Nov 28, 2015 3:49 pm

Re: keyboard switching and persistence

Post by hpd »

Correction: the desktop setting does *not* affect the language of subsequently started programs (WinXP).

I'm not sure of the internals yet. How kbswitch is notified of task (active process) switches and how it determines the setting of that task.

How is SystemParametersInfo related to the registry? Where is it implemented? As I understand it, it maps the SPI request to the related registry entry, and after a change can broadcast WM_SETTINGCHANGE.

There seem to exist different handlings in different Windows versions. While I can find e.g. SystemParametersInfo in older Windows docs, current MSDN doesn't find such entries?

Forever Winter
Posts: 131
Joined: Sun Oct 20, 2013 6:50 am

Re: keyboard switching and persistence

Post by Forever Winter »

To see how kbswitch works, you may have a look at SetWindowsHookEx, GetWindowThreadProcessId, and GetKeyboardLayout. Using SystemParametersInfo to change the default keyboard
layout is not a persistent change. If the change should be permanent, the calling application has to save the new default layout itself to the related registry keys.

https://msdn.microsoft.com/en-us/librar ... 85%29.aspx documents SystemParametersInfo, but I guess this is not what you mean?

hpd
Posts: 9
Joined: Sat Nov 28, 2015 3:49 pm

Re: keyboard switching and persistence

Post by hpd »

Sorry, Delphi seems not to be the right tool to search the MSDN :-(
I'll better use an ordinary browser for searching the MSDN.

Now I'll start playing around with the kbswitch implementation. Unfortunately it's not always clear which messages are sent to that window, and what's the correct action to take.

Just another question: what's the fastest way to test modified sources? A bootcd.iso requires an installation in a VM, so I guess it would be better to creaete a livecd.iso?

Forever Winter
Posts: 131
Joined: Sun Oct 20, 2013 6:50 am

Re: keyboard switching and persistence

Post by Forever Winter »

Besides building an image for a live cd, you can use http://svn.reactos.org/packages/samba-tng.exe to copy the modified component from a smb share.
Another option is to mount your virtual harddisk file on your host to replace modified components, if you test in a vm. If your development system is Windows, you
can also just test it on Windows if you keep in mind that the behaviour of some apis has changed in with different Windows versions. Finally, also if you test in a vm,
you may have a look at https://www.reactos.org/wiki/Using_shared_folders.

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest