Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable Chinese input method in the game #30976

Open
gptzm opened this issue Jan 16, 2024 · 9 comments
Open

Disable Chinese input method in the game #30976

gptzm opened this issue Jan 16, 2024 · 9 comments
Labels
Idea-New PowerToy Suggestion for a PowerToy

Comments

@gptzm
Copy link

gptzm commented Jan 16, 2024

Description of the new feature / enhancement

Disable Chinese input method in the game

Scenario when this would be used?

When playing a game, pressing ADWS will always activate the Chinese input method, causing the game window to be out of focus

Supporting information

No response

@gptzm gptzm added the Needs-Triage For issues raised to be triaged and prioritized by internal Microsoft teams label Jan 16, 2024
@stefansjfw stefansjfw added the Idea-New PowerToy Suggestion for a PowerToy label Jan 16, 2024
@TheJoeFin
Copy link
Collaborator

why does pressing WASD trigger the Chinese input method? Do you have a custom shortcut? Windows default is alt + arrow keys or Win + space. /needinfo

@microsoft-github-policy-service microsoft-github-policy-service bot added Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something and removed Needs-Triage For issues raised to be triaged and prioritized by internal Microsoft teams labels Jan 16, 2024
@heerxingen
Copy link

hi I'm Chinese and I'm here to explain things for English users
When typing in Chinse we don't have a keyboard for all the millions of characters LOL so we use PinYin. PinYin is a way of writing Chinese characters' pronunciations. It's a bit like how you type Japanese if you want to learn more about PinYin you can google it.
The author mean that when you use the Chinese inputm method it will recognize WASD as w,a,s,d letters in PinYin. This is doesn't make much because if you use the English method it won't happen at all LOL and powertoys can't do anything to stop the Chinese input method except to detect games and change the input method to English automatically when this thing can be fixed with a simple Win+Space.

@TheJoeFin
Copy link
Collaborator

Understood. So you have your input language set to Chinese and want to automatically switch to English when playing games or just suppress the input pane from popping up when in game mode?

@heerxingen
Copy link

The first way will fix the issuer's(I'm not sure there's such a word lol) problem.
Even if you make the panel disappear I don't think it'll work
Because when you type Chinese it's like this:
image
the things you type goes to your input method first, rather than the screen. If there's no box to put the words in, the box will appear on the screen and takes away all your keyboard actions.

@microsoft-github-policy-service microsoft-github-policy-service bot added the Status-No recent activity no activity in the past 5 days when follow up's are needed label Jan 23, 2024
Copy link
Contributor

This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 5 days. It will be closed if no further activity occurs within 5 days of this comment.

1 similar comment
Copy link
Contributor

This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 5 days. It will be closed if no further activity occurs within 5 days of this comment.

@TheJoeFin TheJoeFin removed Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something Status-No recent activity no activity in the past 5 days when follow up's are needed labels Jan 23, 2024
@gexgd0419
Copy link

Why IMEs can annoy users

Applications are responsible for controlling IMEs

The IME (input method editor) is enabled by default when a new window is opened, and the program is responsible for enabling and disabling the IME when the user moves input focus to different places.

For example, when entering passwords, IMEs are disabled by the password input box, so the user can only type English characters from the keyboard, and cannot use IMEs to enter CJK (Chinese/Japanese/Korean) characters. During this time, the IME will seems to be "locked" to English mode, and won't intercept any keyboard inputs. After that, when the input focus is moved to an input box that accepts CJK text, IMEs will be enabled again.

A well-behaved, IME-aware program will disable IMEs when there's no need to enter CJK text or any text in general, so that users won't accidentally invoke the IME pane when, for example, using WASD keys in a game. But when the user clicks on a text input box (to send chat messages, for example), IMEs should be enabled again.

If the program uses the standard controls provided by Windows, or a UI framework that can handle IMEs correctly, the program can be IME-aware without writing extra code.

Not all programs take this responsibility, though

English-speaking users don't need an IME to input text, so do speakers of most European languages, because the alphabets of those languages often have a limited number of letters, and you can just arrange all different letters/diacritics onto each key.

Program developers who don't know about IMEs might not add code to enable/disable IMEs properly in their programs. As a result, those programs won't care about IMEs at all, if they aren't using an IME-aware UI framework - many games don't.

So what will Windows do when running an IME-unaware program like that? It will leave IMEs enabled. As the program doesn't disable IMEs, CJK users can accidentally invoke the IME pane until they turn off the IME, which is the problem mentioned in this issue. (Disabling IMEs by default is worse in this case, because IME-unaware programs don't enable IMEs either, which will make IMEs totally unusable.)

To demonstrate that, here's a blank C++ program that only shows a window and does nothing else (IME-unaware).

IME invoked in an empty window

You can see that there's nowhere users can type text into, yet the IME is invoked by keyboard inputs. Because IMEs are enabled by default.

Why it wasn't that annoying before (on Windows XP/7)

On Windows XP and Windows 7, this behavior isn't a big issue, because the default keyboard language is English, and users have to manually switch to an IME before typing CJK text. Every program, IME-aware or not, starts with the English keyboard language, so the problems caused by IME-unaware programs are less noticeable.

But on Windows 10/11 (and maybe 8), the Microsoft Pinyin IME becomes the default IME, which makes the problems noticeable for CJK users - or specifically Chinese users. The Microsoft Japanese and Korean IMEs default to English input mode, but the Microsoft Chinese IMEs default to Chinese input mode.

Microsoft Chinese IME settings

This means that every time you launch a program, the Microsoft Pinyin IME will try to set itself to Chinese input mode if it can. The benefit of that is that users can just start typing Chinese right away, without the hassle of manually switching to a Chinese IME. But, if the program is IME-unaware, when users do not want to type Chinese text, they have to switch away from the default Chinese input mode, or even add a second English keyboard language in order to avoid the IME altogether. (IMEs can intercept some key inputs even in English input mode)

Also, there are some places where users are more likely to type English text, so setting English input mode as the default mode will be helpful. Examples are the Run dialog, Command Prompt / PowerShell windows, and Windows Terminal windows. I submitted a feature request to Windows Terminal about that, but unfortunately the fix for that seems to break some Japanese IMEs.

Keyboard layouts and IME input modes

The English keyboard language (or keyboard layout) and the English input mode in an IME are not the same thing.

Keyboard layouts

Keyboard layouts are the thing you can switch using Windows+Space (all layouts), Ctrl+Shift (layouts in the same language), or Alt+Shift (different languages) combination. They define the relations between physical keys and their characters or functions. IMEs are also shown in the keyboard layout list.

On older versions of Windows, each program has its own active keyboard layout (or IME). Each program starts with the default layout (for example English). Users can set each running program to use a different layout, and each program can specify a layout it will use.

Starting from Windows 8, all programs share the same active keyboard layout. Only the user and the active program can change the active layout, and the layout will be used by all other programs. If users want the old behavior, they can go to Advanced keyboard settings, and change the following setting (English: Let me use a different input method for each app window).

advanced keyboard settings

A program can choose its own active keyboard layout by using LoadKeyboardLayout. (Actually, this was a per-thread setting.)

LoadKeyboardLayoutW(L"00000409", KLF_ACTIVATE); // Load the keyboard layout English (US), then activate it

On Windows 8 and later, this will change the shared active keyboard layout, but this only works when the program owns the active window.

If you want to change the active keyboard layout of another program, you can post a WM_INPUTLANGCHANGEREQUEST to its focused window.

// Get the window with keyboard focus
HWND hForegroundWnd = GetForegroundWindow();
GUITHREADINFO info = {};
info.cbSize = sizeof(GUITHREADINFO);
GetGUIThreadInfo(GetWindowThreadProcessId(hForegroundWnd, NULL), &info);

// Load the keyboard layout
HKL hkl = LoadKeyboardLayoutW(L"00000409", 0);
// Request the focused window to change to this layout
PostMessageW(info.hwndFocus, WM_INPUTLANGCHANGEREQUEST, 0, (LPARAM)hkl);

On Windows 8 and later, changing the active keyboard layout will affect all running programs, so you may want to restore the previous active layout before leaving the game window.

IME input modes

IMEs have different input modes (or conversion modes) that controls whether to use Chinese/English punctuations, half-width/full-width letters, simplified/traditional Chinese, Katakana/Hiragana, etc..

One of the most commonly used one is, of course, Chinese/English input mode.

Chinese IMEs often have some hot keys to toggle Chinese/English input mode. For example, "pressing Shift once" is one of them. It is easy to use, but unfortunately, Shift keys are also often used in games, so you will want to switch to an English keyboard layout to avoid the IME switching back to Chinese mode while gaming. (IME-aware games won't have this issue)

Ctrl+Space was the hot key to toggle between IME and non-IME before Windows 8. You could Ctrl+Space to non-IME layout, so that IMEs wouldn't be activated by Shift keys. Now this doesn't work, because Ctrl+Space becomes just another hot key combo to toggle Chinese/English mode; you are not leaving the IME, so Shift keys can still trigger it.

If all games and applications could handle IMEs correctly, we CJK users wouldn't have to deal with the hassle of switching IMEs back and forth. Even Adobe Photoshop isn't doing this well. Sigh.

Back to the topic.

To change the IME to English mode for our own program, we can use ImmSetConversionStatus. The conversion status value uses different bits to represent different modes, but if we just want to switch to English input mode, we can clear all the bits and set it to zero (IME_CMODE_ALPHANUMERIC).

On Windows 8/10/11, changing the keyboard layout (IME) affects all programs, but changing the IME mode doesn't: each program still has its own IME mode setting, so the user can choose to type Chinese in Word, and English in Terminal.

So how can we change the IME mode for another program? We can use ImmGetDefaultIMEWnd to get the hidden IME window associated with the program's focused window, then send WM_IME_CONTROL to the IME window.

// wParam for setting conversion mode (not documented, but still works)
#define IMC_SETCONVERSIONMODE 0x0002

// Get the window with keyboard focus
HWND hForegroundWnd = GetForegroundWindow();
GUITHREADINFO info = {};
info.cbSize = sizeof(GUITHREADINFO);
GetGUIThreadInfo(GetWindowThreadProcessId(hForegroundWnd, NULL), &info);

// Get the IME window for the focused window
HWND hImeWnd = ImmGetDefaultIMEWnd(info.hwndFocus);
// Send control message
SendMessageW(hImeWnd, WM_IME_CONTROL, IMC_SETCONVERSIONMODE, IME_CMODE_ALPHANUMERIC);

Opening/Closing the IME

An IME can be opened/closed, or be turned on/off. When an IME is closed (turned off), it will stop intercepting and converting English inputs, which is basically the English input mode.

So what's the difference between switching the IME input modes and closing the IME? It depends on the IME itself, and not handling this correctly can cause undesired behavior with some IMEs. You can check my comment here about this, but basically:

  • When using Chinese or Korean IMEs, we should switch the input mode.
  • When using Japanese IMEs, we should close the IME instead. Switching input mode still works with Microsoft's Japanese IME, but not Google's IME, because it treats "IME off" and "IME on but alphanumeric" differently.

Opening/closing the IME in our own program can be done via ImmSetOpenStatus. But of course, we are more interested in how to close the IME for another program:

// wParam for setting open status (not documented, but still works)
#define IMC_SETOPENSTATUS 0x0006

// Get the window with keyboard focus
HWND hForegroundWnd = GetForegroundWindow();
GUITHREADINFO info = {};
info.cbSize = sizeof(GUITHREADINFO);
GetGUIThreadInfo(GetWindowThreadProcessId(hForegroundWnd, NULL), &info);

// Get the IME window for the focused window
HWND hImeWnd = ImmGetDefaultIMEWnd(info.hwndFocus);
// Set open status to 0 (closed)
SendMessageW(hImeWnd, WM_IME_CONTROL, IMC_SETOPENSTATUS, 0);

Summary

Switching keyboard layouts:

  • LoadKeyboardLayout, then post WM_INPUTLANGCHANGEREQUEST to the focused window
  • Users should use Windows+Space if they want to switch back to IME
  • On Windows 8 and later, the active keyboard layout is shared, so you may consider restoring the active layout, or give users a hint about how to change the "Let me use a different input method for each app window" setting

Switching IME input modes:

  • ImmGetDefaultIMEWnd for the focused window, then SendMessage(hImeWnd, WM_IME_CONTROL, IMC_SETCONVERSIONMODE, IME_CMODE_ALPHANUMERIC);
  • Users can use hot keys like Shift to switch back to Chinese mode
  • IME statuses are not shared
  • Does not work as intended with some Japanese IMEs

Opening/closing IME:

  • ImmGetDefaultIMEWnd for the focused window, then SendMessageW(hImeWnd, WM_IME_CONTROL, IMC_SETOPENSTATUS, 0);
  • Depending on the IME, this can be the same as "switching input modes", or different
  • May not work as intended with some IMEs

@gexgd0419
Copy link

A more generalized version would be something like an "input language auto-switcher", which can switch keyboard layouts and IME states based on a set of rules. This may be useful not only for Chinese IME users, but also for users who use multiple keyboard layouts.

@heerxingen
Copy link

heerxingen commented Feb 21, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Idea-New PowerToy Suggestion for a PowerToy
Projects
Status: No status
Development

No branches or pull requests

5 participants