https://git.reactos.org/?p=reactos.git;a=commitdiff;h=36f7d1a953698157dddb723506453039b9dcf11d

commit 36f7d1a953698157dddb723506453039b9dcf11d
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Sat Oct 29 07:35:19 2022 +0900
Commit:     GitHub <[email protected]>
CommitDate: Sat Oct 29 07:35:19 2022 +0900

    [KBSWITCH][CPL:INPUT][NTUSER][EXPLORER] Fix keyboard layout icon (#4815)
    
    Fix keyboard layout icon in taskbar notification area. JIRA issue: 
CORE-11700, CORE-2699, CORE-18546
    - Call ActivateKeyboardLayout to select the keyboard layout correctly.
    - Modify WM_INPUTLANGCHANGEREQUEST parameter.
    - Modify BroadcastSystemMessageW parameter.
    - Revert Taskbar Notification Area MA_NOACTIVATE HACK 8344291 . This fixes 
Context Menu display.
    - Load the "IME File" value and set the IME icon if necessary.
    - Correctly implement global hooks.
---
 base/applications/kbswitch/CMakeLists.txt         |   2 +-
 base/applications/kbswitch/kbsdll/kbsdll.c        |  36 ++-
 base/applications/kbswitch/kbswitch.c             | 328 ++++++++++++++++++----
 base/applications/kbswitch/kbswitch.h             |   1 -
 base/shell/explorer/trayntfy.cpp                  |   6 -
 dll/cpl/input/input_list.c                        |   7 +-
 win32ss/user/ntuser/defwnd.c                      |   2 +-
 win32ss/user/winsrv/consrv/frontends/gui/conwnd.c |   5 +
 8 files changed, 317 insertions(+), 70 deletions(-)

diff --git a/base/applications/kbswitch/CMakeLists.txt 
b/base/applications/kbswitch/CMakeLists.txt
index 2b735411437..ede579f6181 100644
--- a/base/applications/kbswitch/CMakeLists.txt
+++ b/base/applications/kbswitch/CMakeLists.txt
@@ -2,7 +2,7 @@
 add_rc_deps(kbswitch.rc ${CMAKE_CURRENT_SOURCE_DIR}/res/kbswitch.ico)
 add_executable(kbswitch kbswitch.c kbswitch.rc)
 set_module_type(kbswitch win32gui UNICODE)
-add_importlibs(kbswitch advapi32 user32 shell32 gdi32 msvcrt kernel32)
+add_importlibs(kbswitch advapi32 imm32 user32 shell32 gdi32 msvcrt kernel32)
 add_cd_file(TARGET kbswitch DESTINATION reactos/system32 FOR all)
 
 add_subdirectory(kbsdll)
diff --git a/base/applications/kbswitch/kbsdll/kbsdll.c 
b/base/applications/kbswitch/kbsdll/kbsdll.c
index 6afb63a08c5..ffcc0344d6d 100644
--- a/base/applications/kbswitch/kbsdll/kbsdll.c
+++ b/base/applications/kbswitch/kbsdll/kbsdll.c
@@ -13,7 +13,7 @@ HINSTANCE hInstance = NULL;
 HWND hKbSwitchWnd = NULL;
 
 static VOID
-SendMessageToMainWnd(UINT Msg, WPARAM wParam, LPARAM lParam)
+PostMessageToMainWnd(UINT Msg, WPARAM wParam, LPARAM lParam)
 {
     PostMessage(hKbSwitchWnd, Msg, wParam, lParam);
 }
@@ -21,36 +21,40 @@ SendMessageToMainWnd(UINT Msg, WPARAM wParam, LPARAM lParam)
 LRESULT CALLBACK
 WinHookProc(int code, WPARAM wParam, LPARAM lParam)
 {
-    int id = GlobalAddAtom(_T("KBSWITCH"));
+    if (code < 0)
+    {
+        return CallNextHookEx(hWinHook, code, wParam, lParam);
+    }
 
     switch (code)
     {
         case HCBT_SETFOCUS:
         {
-            if ((HWND)wParam != NULL)
+            HWND hwndFocus = (HWND)wParam;
+            if (hwndFocus && hwndFocus != hKbSwitchWnd)
             {
-                if ((HWND)wParam != hKbSwitchWnd)
-                {
-                    SendMessageToMainWnd(WM_WINDOW_ACTIVATE, wParam, lParam);
-                }
+                PostMessageToMainWnd(WM_WINDOW_ACTIVATE, wParam, lParam);
             }
         }
         break;
     }
 
-    GlobalDeleteAtom(id);
-
     return CallNextHookEx(hWinHook, code, wParam, lParam);
 }
 
 LRESULT CALLBACK
 ShellHookProc(int code, WPARAM wParam, LPARAM lParam)
 {
+    if (code < 0)
+    {
+        return CallNextHookEx(hShellHook, code, wParam, lParam);
+    }
+
     switch (code)
     {
         case HSHELL_LANGUAGE:
         {
-            SendMessageToMainWnd(WM_LANG_CHANGED, wParam, lParam);
+            PostMessageToMainWnd(WM_LANG_CHANGED, wParam, lParam);
         }
         break;
     }
@@ -75,8 +79,16 @@ KbSwitchSetHooks(VOID)
 VOID WINAPI
 KbSwitchDeleteHooks(VOID)
 {
-    if (hWinHook) UnhookWindowsHookEx(hWinHook);
-    if (hShellHook) UnhookWindowsHookEx(hShellHook);
+    if (hWinHook)
+    {
+        UnhookWindowsHookEx(hWinHook);
+        hWinHook = NULL;
+    }
+    if (hShellHook)
+    {
+        UnhookWindowsHookEx(hShellHook);
+        hShellHook = NULL;
+    }
 }
 
 BOOL WINAPI
diff --git a/base/applications/kbswitch/kbswitch.c 
b/base/applications/kbswitch/kbswitch.c
index 6e301ee5207..5bad013d964 100644
--- a/base/applications/kbswitch/kbswitch.c
+++ b/base/applications/kbswitch/kbswitch.c
@@ -8,6 +8,21 @@
  */
 
 #include "kbswitch.h"
+#include <imm.h>
+
+/*
+ * This program kbswitch is a mimic of Win2k's internat.exe.
+ * However, there are some differences.
+ *
+ * Comparing with WinNT4 ActivateKeyboardLayout, WinXP ActivateKeyboardLayout 
has
+ * process boundary, so we cannot activate the IME keyboard layout from the 
outer process.
+ * It needs special care.
+ *
+ * We use global hook by our kbsdll.dll, to watch the shell and the windows.
+ *
+ * It might not work correctly on Vista+ because keyboard layout change 
notification
+ * won't be generated in Vista+.
+ */
 
 #define WM_NOTIFYICONMSG (WM_USER + 248)
 
@@ -20,6 +35,7 @@ HANDLE    hProcessHeap;
 HMODULE   g_hHookDLL = NULL;
 ULONG     ulCurrentLayoutNum = 1;
 HICON     g_hTrayIcon = NULL;
+HWND      g_hwndLastActive = NULL;
 
 static BOOL
 GetLayoutID(LPCTSTR szLayoutNum, LPTSTR szLCID, SIZE_T LCIDLength)
@@ -65,6 +81,17 @@ GetLayoutID(LPCTSTR szLayoutNum, LPTSTR szLCID, SIZE_T 
LCIDLength)
     return TRUE;
 }
 
+static BOOL
+GetSystemLibraryPath(LPTSTR szPath, SIZE_T cchPath, LPCTSTR FileName)
+{
+    if (!GetSystemDirectory(szPath, cchPath))
+        return FALSE;
+
+    StringCchCat(szPath, cchPath, TEXT("\\"));
+    StringCchCat(szPath, cchPath, FileName);
+    return TRUE;
+}
+
 static BOOL
 GetLayoutName(LPCTSTR szLayoutNum, LPTSTR szName, SIZE_T NameLength)
 {
@@ -131,18 +158,86 @@ GetLayoutName(LPCTSTR szLayoutNum, LPTSTR szName, SIZE_T 
NameLength)
     /* Otherwise, use "Layout Text" value as an entry name */
     dwBufLen = NameLength * sizeof(TCHAR);
     if (RegQueryValueEx(hKey, _T("Layout Text"), NULL, NULL,
-                        (LPBYTE)szName, &dwBufLen) == ERROR_SUCCESS)
+                        (LPBYTE)szName, &dwBufLen) != ERROR_SUCCESS)
     {
         RegCloseKey(hKey);
-        return TRUE;
+        return FALSE;
     }
 
     RegCloseKey(hKey);
-    return FALSE;
+    return TRUE;
+}
+
+static BOOL GetImeFile(LPTSTR szImeFile, SIZE_T cchImeFile, LPCTSTR szLCID)
+{
+    HKEY hKey;
+    DWORD dwBufLen;
+    TCHAR szBuf[MAX_PATH];
+
+    szImeFile[0] = UNICODE_NULL;
+
+    if (_tcslen(szLCID) != CCH_LAYOUT_ID)
+        return FALSE; /* Invalid LCID */
+
+    if (szLCID[0] != TEXT('E') && szLCID[0] != TEXT('e'))
+        return FALSE; /* Not an IME HKL */
+
+    StringCchPrintf(szBuf, ARRAYSIZE(szBuf),
+                    _T("SYSTEM\\CurrentControlSet\\Control\\Keyboard 
Layouts\\%s"), szLCID);
+
+    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuf, 0, KEY_QUERY_VALUE, &hKey) != 
ERROR_SUCCESS)
+    {
+        return FALSE;
+    }
+
+    dwBufLen = cchImeFile * sizeof(TCHAR);
+    if (RegQueryValueEx(hKey, _T("IME File"), NULL, NULL,
+                        (LPBYTE)szImeFile, &dwBufLen) != ERROR_SUCCESS)
+    {
+        szImeFile[0] = UNICODE_NULL;
+    }
+
+    RegCloseKey(hKey);
+
+    return (szImeFile[0] != UNICODE_NULL);
+}
+
+typedef struct tagLOAD_ICON
+{
+    INT cxIcon, cyIcon;
+    HICON hIcon;
+} LOAD_ICON, *PLOAD_ICON;
+
+static BOOL CALLBACK
+EnumResNameProc(
+    HMODULE hModule,
+    LPCTSTR lpszType,
+    LPTSTR lpszName,
+    LPARAM lParam)
+{
+    PLOAD_ICON pLoadIcon = (PLOAD_ICON)lParam;
+    pLoadIcon->hIcon = (HICON)LoadImage(hModule, lpszName, IMAGE_ICON,
+                                        pLoadIcon->cxIcon, pLoadIcon->cyIcon,
+                                        LR_DEFAULTCOLOR);
+    if (pLoadIcon->hIcon)
+        return FALSE; /* Stop enumeration */
+    return TRUE;
+}
+
+static HICON FakeExtractIcon(LPCTSTR szIconPath, INT cxIcon, INT cyIcon)
+{
+    LOAD_ICON LoadIcon = { cxIcon, cyIcon, NULL };
+    HMODULE hImeDLL = LoadLibraryEx(szIconPath, NULL, 
LOAD_LIBRARY_AS_DATAFILE);
+    if (hImeDLL)
+    {
+        EnumResourceNames(hImeDLL, RT_GROUP_ICON, EnumResNameProc, 
(LPARAM)&LoadIcon);
+        FreeLibrary(hImeDLL);
+    }
+    return LoadIcon.hIcon;
 }
 
 static HICON
-CreateTrayIcon(LPTSTR szLCID)
+CreateTrayIcon(LPTSTR szLCID, LPCTSTR szImeFile OPTIONAL)
 {
     LANGID LangID;
     TCHAR szBuf[4];
@@ -155,6 +250,13 @@ CreateTrayIcon(LPTSTR szLCID)
     HICON hIcon;
     INT cxIcon = GetSystemMetrics(SM_CXSMICON);
     INT cyIcon = GetSystemMetrics(SM_CYSMICON);
+    TCHAR szPath[MAX_PATH];
+
+    if (szImeFile && szImeFile[0])
+    {
+        if (GetSystemLibraryPath(szPath, ARRAYSIZE(szPath), szImeFile))
+            return FakeExtractIcon(szPath, cxIcon, cyIcon);
+    }
 
     /* Getting "EN", "FR", etc. from English, French, ... */
     LangID = LANGIDFROMLCID(_tcstoul(szLCID, NULL, 16));
@@ -236,12 +338,14 @@ AddTrayIcon(HWND hwnd)
 {
     NOTIFYICONDATA tnid = { sizeof(tnid), hwnd, 1, NIF_ICON | NIF_MESSAGE | 
NIF_TIP };
     TCHAR szLCID[CCH_LAYOUT_ID + 1], szName[MAX_PATH];
+    TCHAR szImeFile[80];
 
     GetLayoutID(_T("1"), szLCID, ARRAYSIZE(szLCID));
     GetLayoutName(_T("1"), szName, ARRAYSIZE(szName));
+    GetImeFile(szImeFile, ARRAYSIZE(szImeFile), szLCID);
 
     tnid.uCallbackMessage = WM_NOTIFYICONMSG;
-    tnid.hIcon = CreateTrayIcon(szLCID);
+    tnid.hIcon = CreateTrayIcon(szLCID, szImeFile);
     StringCchCopy(tnid.szTip, ARRAYSIZE(tnid.szTip), szName);
 
     Shell_NotifyIcon(NIM_ADD, &tnid);
@@ -268,9 +372,12 @@ static VOID
 UpdateTrayIcon(HWND hwnd, LPTSTR szLCID, LPTSTR szName)
 {
     NOTIFYICONDATA tnid = { sizeof(tnid), hwnd, 1, NIF_ICON | NIF_MESSAGE | 
NIF_TIP };
+    TCHAR szImeFile[80];
+
+    GetImeFile(szImeFile, ARRAYSIZE(szImeFile), szLCID);
 
     tnid.uCallbackMessage = WM_NOTIFYICONMSG;
-    tnid.hIcon = CreateTrayIcon(szLCID);
+    tnid.hIcon = CreateTrayIcon(szLCID, szImeFile);
     StringCchCopy(tnid.szTip, ARRAYSIZE(tnid.szTip), szName);
 
     Shell_NotifyIcon(NIM_MODIFY, &tnid);
@@ -289,12 +396,12 @@ GetLayoutIDByHkl(HKL hKl, LPTSTR szLayoutID, SIZE_T 
LayoutIDLength)
 static BOOL CALLBACK
 EnumWindowsProc(HWND hwnd, LPARAM lParam)
 {
-    PostMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, 0, lParam);
+    PostMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, INPUTLANGCHANGE_SYSCHARSET, 
lParam);
     return TRUE;
 }
 
 static VOID
-ActivateLayout(HWND hwnd, ULONG uLayoutNum)
+ActivateLayout(HWND hwnd, ULONG uLayoutNum, HWND hwndTarget OPTIONAL)
 {
     HKL hKl;
     TCHAR szLayoutNum[CCH_ULONG_DEC + 1], szLCID[CCH_LAYOUT_ID + 1], 
szLangName[MAX_PATH];
@@ -311,10 +418,24 @@ ActivateLayout(HWND hwnd, ULONG uLayoutNum)
     /* Switch to the new keyboard layout */
     GetLocaleInfo(LangID, LOCALE_SLANGUAGE, szLangName, ARRAYSIZE(szLangName));
     UpdateTrayIcon(hwnd, szLCID, szLangName);
+
+    if (hwndTarget)
+        SetForegroundWindow(hwndTarget);
+
     hKl = LoadKeyboardLayout(szLCID, KLF_ACTIVATE);
+    if (hKl)
+        ActivateKeyboardLayout(hKl, KLF_SETFORPROCESS);
 
-    /* Post WM_INPUTLANGCHANGEREQUEST to every top-level window */
-    EnumWindows(EnumWindowsProc, (LPARAM) hKl);
+    /* Post WM_INPUTLANGCHANGEREQUEST */
+    if (hwndTarget)
+    {
+        PostMessage(hwndTarget, WM_INPUTLANGCHANGEREQUEST,
+                    INPUTLANGCHANGE_SYSCHARSET, (LPARAM)hKl);
+    }
+    else
+    {
+        EnumWindows(EnumWindowsProc, (LPARAM) hKl);
+    }
 
     ulCurrentLayoutNum = uLayoutNum;
 }
@@ -411,8 +532,16 @@ SetHooks(VOID)
 VOID
 DeleteHooks(VOID)
 {
-    if (KbSwitchDeleteHooks) KbSwitchDeleteHooks();
-    if (g_hHookDLL) FreeLibrary(g_hHookDLL);
+    if (KbSwitchDeleteHooks)
+    {
+        KbSwitchDeleteHooks();
+        KbSwitchDeleteHooks = NULL;
+    }
+    if (g_hHookDLL)
+    {
+        FreeLibrary(g_hHookDLL);
+        g_hHookDLL = NULL;
+    }
 }
 
 ULONG
@@ -436,7 +565,7 @@ GetNextLayout(VOID)
     return ulCurrentLayoutNum;
 }
 
-LRESULT
+UINT
 UpdateLanguageDisplay(HWND hwnd, HKL hKl)
 {
     TCHAR szLCID[MAX_PATH], szLangName[MAX_PATH];
@@ -450,12 +579,76 @@ UpdateLanguageDisplay(HWND hwnd, HKL hKl)
     return 0;
 }
 
-LRESULT
-UpdateLanguageDisplayCurrent(HWND hwnd, WPARAM wParam)
+HWND
+GetTargetWindow(HWND hwndFore)
+{
+    TCHAR szClass[64];
+    HWND hwndIME;
+    HWND hwndTarget = hwndFore;
+    if (hwndTarget == NULL)
+        hwndTarget = GetForegroundWindow();
+
+    GetClassName(hwndTarget, szClass, ARRAYSIZE(szClass));
+    if (_tcsicmp(szClass, szKbSwitcherName) == 0)
+        hwndTarget = g_hwndLastActive;
+
+    hwndIME = ImmGetDefaultIMEWnd(hwndTarget);
+    return (hwndIME ? hwndIME : hwndTarget);
+}
+
+UINT
+UpdateLanguageDisplayCurrent(HWND hwnd, HWND hwndFore)
 {
-    DWORD dwThreadID = GetWindowThreadProcessId((HWND)wParam, 0);
+    DWORD dwThreadID = GetWindowThreadProcessId(GetTargetWindow(hwndFore), 
NULL);
     HKL hKL = GetKeyboardLayout(dwThreadID);
-    return UpdateLanguageDisplay(hwnd, hKL);
+    UpdateLanguageDisplay(hwnd, hKL);
+
+    if (IsWindow(g_hwndLastActive))
+        SetForegroundWindow(g_hwndLastActive);
+
+    return 0;
+}
+
+static UINT GetCurLayoutNum(HKL hKL)
+{
+    UINT i, nCount;
+    HKL ahKL[256];
+
+    nCount = GetKeyboardLayoutList(ARRAYSIZE(ahKL), ahKL);
+    for (i = 0; i < nCount; ++i)
+    {
+        if (ahKL[i] == hKL)
+            return i + 1;
+    }
+
+    return 0;
+}
+
+static BOOL RememberLastActive(HWND hwnd, HWND hwndFore)
+{
+    TCHAR szClass[64];
+
+    hwndFore = GetAncestor(hwndFore, GA_ROOT);
+
+    if (!IsWindowVisible(hwndFore) || !GetClassName(hwndFore, szClass, 
ARRAYSIZE(szClass)))
+        return FALSE;
+
+    if (_tcsicmp(szClass, szKbSwitcherName) == 0 ||
+        _tcsicmp(szClass, TEXT("Shell_TrayWnd")) == 0)
+    {
+        return FALSE; /* Special window */
+    }
+
+    /* FIXME: CONWND is multithreaded but KLF_SETFORPROCESS and
+              DefWindowProc.WM_INPUTLANGCHANGEREQUEST won't work yet */
+    if (_tcsicmp(szClass, TEXT("ConsoleWindowClass")) == 0)
+    {
+        HKL hKL = GetKeyboardLayout(0);
+        UpdateLanguageDisplay(hwnd, hKL);
+    }
+
+    g_hwndLastActive = hwndFore;
+    return TRUE;
 }
 
 LRESULT CALLBACK
@@ -471,31 +664,30 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM 
lParam)
         case WM_CREATE:
         {
             if (!SetHooks())
+            {
+                MessageBox(NULL, TEXT("SetHooks failed."), NULL, MB_ICONERROR);
                 return -1;
+            }
 
             AddTrayIcon(hwnd);
 
-            ActivateLayout(hwnd, ulCurrentLayoutNum);
+            ActivateLayout(hwnd, ulCurrentLayoutNum, NULL);
             s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
             break;
         }
 
-        case WM_LANG_CHANGED:
-        {
-            return UpdateLanguageDisplay(hwnd, (HKL)lParam);
-        }
-
-        case WM_LOAD_LAYOUT:
+        case WM_LANG_CHANGED: /* Comes from kbsdll.dll and this module */
         {
-            ULONG uNextNum = GetNextLayout();
-            if (ulCurrentLayoutNum != uNextNum)
-                ActivateLayout(hwnd, uNextNum);
+            UpdateLanguageDisplay(hwnd, (HKL)lParam);
             break;
         }
 
-        case WM_WINDOW_ACTIVATE:
+        case WM_WINDOW_ACTIVATE: /* Comes from kbsdll.dll and this module */
         {
-            return UpdateLanguageDisplayCurrent(hwnd, wParam);
+            HWND hwndFore = GetForegroundWindow();
+            if (RememberLastActive(hwnd, hwndFore))
+                return UpdateLanguageDisplayCurrent(hwnd, hwndFore);
+            break;
         }
 
         case WM_NOTIFYICONMSG:
@@ -537,32 +729,73 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM 
lParam)
             {
                 case ID_EXIT:
                 {
-                    SendMessage(hwnd, WM_CLOSE, 0, 0);
+                    PostMessage(hwnd, WM_CLOSE, 0, 0);
                     break;
                 }
 
                 case ID_PREFERENCES:
                 {
-                    SHELLEXECUTEINFO shInputDll = { sizeof(shInputDll) };
-                    shInputDll.hwnd = hwnd;
-                    shInputDll.lpVerb = _T("open");
-                    shInputDll.lpFile = _T("rundll32.exe");
-                    shInputDll.lpParameters = _T("shell32.dll,Control_RunDLL 
input.dll");
-                    if (!ShellExecuteEx(&shInputDll))
-                        MessageBox(hwnd, _T("Can't start input.dll"), NULL, 
MB_OK | MB_ICONERROR);
-
+                    INT_PTR ret = (INT_PTR)ShellExecute(hwnd, NULL,
+                                                        TEXT("control.exe"), 
TEXT("input.dll"),
+                                                        NULL, SW_SHOWNORMAL);
+                    if (ret <= 32)
+                        MessageBox(hwnd, _T("Can't start input.dll"), NULL, 
MB_ICONERROR);
                     break;
                 }
 
                 case ID_NEXTLAYOUT:
                 {
-                    ActivateLayout(hwnd, GetNextLayout());
+                    HWND hwndTarget = (HWND)lParam, hwndTargetSave = NULL;
+                    DWORD dwThreadID;
+                    HKL hKL;
+                    UINT uNum;
+                    TCHAR szClass[64];
+                    BOOL bCONWND = FALSE;
+
+                    if (hwndTarget == NULL)
+                        hwndTarget = g_hwndLastActive;
+
+                    /* FIXME: CONWND is multithreaded but KLF_SETFORPROCESS and
+                              DefWindowProc.WM_INPUTLANGCHANGEREQUEST won't 
work yet */
+                    if (hwndTarget &&
+                        GetClassName(hwndTarget, szClass, ARRAYSIZE(szClass)) 
&&
+                        _tcsicmp(szClass, TEXT("ConsoleWindowClass")) == 0)
+                    {
+                        bCONWND = TRUE;
+                        hwndTargetSave = hwndTarget;
+                        hwndTarget = NULL;
+                    }
+
+                    if (hwndTarget)
+                    {
+                        dwThreadID = GetWindowThreadProcessId(hwndTarget, 
NULL);
+                        hKL = GetKeyboardLayout(dwThreadID);
+                        uNum = GetCurLayoutNum(hKL);
+                        if (uNum != 0)
+                            ulCurrentLayoutNum = uNum;
+                    }
+
+                    ActivateLayout(hwnd, GetNextLayout(), hwndTarget);
+
+                    /* FIXME: CONWND is multithreaded but KLF_SETFORPROCESS and
+                              DefWindowProc.WM_INPUTLANGCHANGEREQUEST won't 
work yet */
+                    if (bCONWND)
+                    {
+                        ActivateLayout(hwnd, ulCurrentLayoutNum, 
hwndTargetSave);
+                    }
                     break;
                 }
 
                 default:
                 {
-                    ActivateLayout(hwnd, LOWORD(wParam));
+                    if (1 <= LOWORD(wParam) && LOWORD(wParam) <= 1000)
+                    {
+                        if (!IsWindow(g_hwndLastActive))
+                        {
+                            g_hwndLastActive = NULL;
+                        }
+                        ActivateLayout(hwnd, LOWORD(wParam), g_hwndLastActive);
+                    }
                     break;
                 }
             }
@@ -570,13 +803,10 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM 
lParam)
 
         case WM_SETTINGCHANGE:
         {
-            if (wParam == SPI_SETDEFAULTINPUTLANG)
-            {
-                //FIXME: Should detect default language changes by CPL applet 
or by other tools and update UI
-            }
             if (wParam == SPI_SETNONCLIENTMETRICS)
             {
-                return UpdateLanguageDisplayCurrent(hwnd, wParam);
+                PostMessage(hwnd, WM_WINDOW_ACTIVATE, wParam, lParam);
+                break;
             }
         }
         break;
@@ -597,9 +827,13 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM 
lParam)
                 AddTrayIcon(hwnd);
                 break;
             }
-            else if (Message == ShellHookMessage && wParam == HSHELL_LANGUAGE)
+            else if (Message == ShellHookMessage)
             {
-                PostMessage(hwnd, WM_LANG_CHANGED, wParam, lParam);
+                if (wParam == HSHELL_LANGUAGE)
+                    PostMessage(hwnd, WM_LANG_CHANGED, wParam, lParam);
+                else if (wParam == HSHELL_WINDOWACTIVATED)
+                    PostMessage(hwnd, WM_WINDOW_ACTIVATE, wParam, lParam);
+
                 break;
             }
             return DefWindowProc(hwnd, Message, wParam, lParam);
diff --git a/base/applications/kbswitch/kbswitch.h 
b/base/applications/kbswitch/kbswitch.h
index 10d295401fb..91906a08e6b 100644
--- a/base/applications/kbswitch/kbswitch.h
+++ b/base/applications/kbswitch/kbswitch.h
@@ -22,7 +22,6 @@
 #define WM_KEY_PRESSED     (WM_USER + 10100)
 #define WM_LANG_CHANGED    (WM_USER + 10200)
 #define WM_WINDOW_ACTIVATE (WM_USER + 10300)
-#define WM_LOAD_LAYOUT     (WM_USER + 10400)
 
 typedef BOOL (WINAPI *PKBSWITCHSETHOOKS) (VOID);
 typedef VOID (WINAPI *PKBSWITCHDELETEHOOKS) (VOID);
diff --git a/base/shell/explorer/trayntfy.cpp b/base/shell/explorer/trayntfy.cpp
index 94dd369103b..9a279240f3c 100644
--- a/base/shell/explorer/trayntfy.cpp
+++ b/base/shell/explorer/trayntfy.cpp
@@ -124,11 +124,6 @@ public:
         return TRUE;
     }
 
-    LRESULT OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled)
-    {
-        return MA_NOACTIVATE;
-    }
-
     BOOL GetMinimumSize(IN OUT PSIZE pSize)
     {
         SIZE szClock = { 0, 0 };
@@ -350,7 +345,6 @@ public:
 
     BEGIN_MSG_MAP(CTrayNotifyWnd)
         MESSAGE_HANDLER(WM_CREATE, OnCreate)
-        MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate)
         MESSAGE_HANDLER(WM_THEMECHANGED, OnThemeChanged)
         MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
         MESSAGE_HANDLER(WM_SIZE, OnSize)
diff --git a/dll/cpl/input/input_list.c b/dll/cpl/input/input_list.c
index ec415b372fe..49347d841dc 100644
--- a/dll/cpl/input/input_list.c
+++ b/dll/cpl/input/input_list.c
@@ -423,6 +423,9 @@ InputList_Process(VOID)
         {
             bRet = InputList_SetFontSubstitutes(pCurrent->pLocale->dwId);
             InputList_AddInputMethodToUserRegistry(hPreloadKey, hSubstKey, 1, 
pCurrent);
+
+            /* Activate the DEFAULT entry */
+            ActivateKeyboardLayout(pCurrent->hkl, KLF_RESET);
             break;
         }
     }
@@ -450,12 +453,12 @@ InputList_Process(VOID)
     /* Change the default keyboard language */
     if (SystemParametersInfoW(SPI_SETDEFAULTINPUTLANG, 0, &pCurrent->hkl, 0))
     {
-        DWORD dwRecipients = BSM_ALLCOMPONENTS | BSM_ALLDESKTOPS;
+        DWORD dwRecipients = BSM_ALLDESKTOPS | BSM_APPLICATIONS;
 
         BroadcastSystemMessageW(BSF_POSTMESSAGE,
                                 &dwRecipients,
                                 WM_INPUTLANGCHANGEREQUEST,
-                                0,
+                                INPUTLANGCHANGE_SYSCHARSET,
                                 (LPARAM)pCurrent->hkl);
     }
 
diff --git a/win32ss/user/ntuser/defwnd.c b/win32ss/user/ntuser/defwnd.c
index 9d2021a70eb..e9a44f44bd9 100644
--- a/win32ss/user/ntuser/defwnd.c
+++ b/win32ss/user/ntuser/defwnd.c
@@ -960,7 +960,7 @@ IntDefWindowProc(
                     if (hwndSwitch)
                     {
 #define ID_NEXTLAYOUT 10003
-                        UserPostMessage(hwndSwitch, WM_COMMAND, ID_NEXTLAYOUT, 
0);
+                        UserPostMessage(hwndSwitch, WM_COMMAND, ID_NEXTLAYOUT, 
(LPARAM)UserHMGetHandle(Wnd));
                     }
                 }
             }
diff --git a/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c 
b/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c
index 8b6f67c7e9d..d265711f261 100644
--- a/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c
+++ b/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c
@@ -2356,6 +2356,11 @@ ConWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM 
lParam)
             {
                 return DefWindowProcW(hWnd, msg, wParam, lParam);
             }
+            /* Detect Alt+Shift */
+            if (wParam == VK_SHIFT && (msg == WM_SYSKEYDOWN || msg == 
WM_SYSKEYUP))
+            {
+                return DefWindowProcW(hWnd, msg, wParam, lParam);
+            }
 
             OnKey(GuiData, msg, wParam, lParam);
             break;

Reply via email to