LCL-WS, Win32: While IME is active (and not custom handled) filter any WM_KeyUp that still come through. Issue #41755

- Known problem is WM_KeyUp for VK_Return which triggers EditDone and select all text.
- Other keys may be handled by some controls, and are meaningless when the IME handled them.
This commit is contained in:
Martin 2025-07-16 14:57:45 +02:00
parent bc9ef8bfa6
commit f5987d2f9f
2 changed files with 40 additions and 5 deletions

View File

@ -2083,11 +2083,20 @@ begin
Application._ProcessAsyncCallQueue;
end;
WM_ENTERIDLE: Application.Idle(False);
WM_ACTIVATE: SetLMessageAndParams(LM_ACTIVATE);
WM_ACTIVATE: begin
if WParam = WA_INACTIVE then
CurrentIMEWindow := 0;
SetLMessageAndParams(LM_ACTIVATE);
end;
WM_DPICHANGED: SetLMessageAndParams(LM_DPICHANGED);
WM_IME_ENDCOMPOSITION:
begin
{IME Windows the composition has finished}
CurrentIMEWindow := 0;
(* IMEComposed:
The IME may send the composed text as sequence WM_Char or it may be retrived via API
After that the IME may send a WM_Keyup for VK_RETURN => this must be ignored.
*)
WindowInfo^.IMEComposed:=True;
SetLMessageAndParams(Msg); //WinProcess := False;
end;
@ -2311,11 +2320,19 @@ begin
WindowInfo^.IMEComposed:=False;
IgnoreNextCharWindow := Window;
IgnoreKeyUp := False;
(* At least Win-10 may sent some keys (WM_KeyDown AND WM_CHar) during IME, e.g. Shift-Return.
Those are also noticeable received by other apps, e.g. MS-Notepad.
Win-11 seems to not do that.
*)
//if Word(WParam) <> VK_PROCESSKEY then
// CurrentIMEWindow := 0;
end;
WM_KEYUP:
begin
DoMsgKeyDownUp(CN_KEYUP, Result);
if WindowInfo^.IMEComposed then
if WindowInfo^.IMEComposed or
( (CurrentIMEWindow <> 0) and (CurrentIMEWindow = Window) )
then
LMKey.Msg:=LM_NULL;
end;
WM_KILLFOCUS:
@ -2323,6 +2340,7 @@ begin
{$ifdef DEBUG_CARET}
DebugLn(['WM_KILLFOCUS received for window ', IntToHex(Window, 8), ' NewFocus = ', IntToHex(WParam, 8), ' Text = ', WndText(WParam)]);
{$endif}
CurrentIMEWindow := 0;
LMessage.Msg := LM_KILLFOCUS;
LMessage.WParam := WParam;
end;
@ -2513,7 +2531,11 @@ begin
WM_IME_SELECT,
WM_IME_SETCONTEXT,
WM_IME_STARTCOMPOSITION:
begin
if msg = WM_IME_STARTCOMPOSITION then
CurrentIMEWindow := Window;
SetLMessageAndParams(Msg, True);
end;
WM_ACTIVATEAPP:
begin
if (Application<>nil) and Application.MainFormOnTaskBar and not Win32WidgetSet.AppMinimizing then
@ -2669,7 +2691,12 @@ begin
WM_IME_REQUEST,
WM_IME_SELECT,
WM_IME_SETCONTEXT,
WM_IME_STARTCOMPOSITION,
WM_IME_STARTCOMPOSITION:
begin
WinProcess := LMessage.Result = 0;
if not WinProcess then
CurrentIMEWindow := 0;
end;
LM_CUT,
LM_COPY,
LM_PASTE,
@ -2717,7 +2744,12 @@ begin
end;
WM_SYSCHAR: SetLMCharData(LM_SYSCHAR);
WM_KEYDOWN: SetLMKeyData(LM_KEYDOWN);
WM_KEYUP: SetLMKeyData(LM_KEYUP);
WM_KEYUP:
begin
SetLMKeyData(LM_KEYUP);
if ( (CurrentIMEWindow <> 0) and (CurrentIMEWindow = Window) ) then
LMKey.Msg:=LM_NULL;
end;
WM_SYSKEYDOWN: SetLMKeyData(LM_SYSKEYDOWN);
WM_SYSKEYUP: SetLMKeyData(LM_SYSKEYUP);
end;
@ -2731,7 +2763,9 @@ begin
// we cannot tell for sure windows didn't want the key
// for WM_CHAR check WM_GETDLGCODE/DLGC_WANTCHARS
// winapi too inconsistent about return value
if (lWinControl <> nil) and (PLMsg^.Result = 0) and CharCodeNotEmpty then
if (lWinControl <> nil) and (PLMsg^.Result = 0) and CharCodeNotEmpty and
(PLMsg^.Msg <> LM_NULL)
then
DeliverMessage(lWinControl, PLMsg^);
// Windows message processing for WM_SYSCHAR not processed (will get WM_MENUCHAR)

View File

@ -334,6 +334,7 @@ var
ComboBoxHandleSizeWindow: HWND = 0;
IgnoreNextCharWindow: HWND = 0; // ignore next WM_(SYS)CHAR message
IgnoreKeyUp: Boolean = True; // ignore KeyUp after application start; issue #30836
CurrentIMEWindow: HWND = 0; // While IME is active the window still receives WM_Keyup. Issue #41755
// set to true, if we are redirecting a WM_MOUSEWHEEL message, to prevent recursion
InMouseWheelRedirection: boolean = false;
OnClipBoardRequest: TClipboardRequestEvent;