[KBSWITCH] Refactor on layout numbers (#8052)

We believe the power of simplicity.
JIRA issue: CORE-20142
- Rename g_nCurrentLayoutNum as
  g_iKL for simplicity.
- Make g_iKL zero-based indexing.
- Add ID_LANG_BASE id for language
  menu items and adjust
  ID_EXIT/ID_PREFERENCES values.
- Fix KbSwitch_OnNotifyIconMsg
  function.
This commit is contained in:
Katayama Hirofumi MZ 2025-05-31 21:17:41 +09:00 committed by GitHub
parent c187cf8b9e
commit 51495b1b75
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 44 additions and 61 deletions

View file

@ -38,12 +38,11 @@ FN_KbSwitchSetHooks KbSwitchSetHooks = NULL;
HINSTANCE g_hInst = NULL; HINSTANCE g_hInst = NULL;
HMODULE g_hHookDLL = NULL; HMODULE g_hHookDLL = NULL;
INT g_nCurrentLayoutNum = 1;
HICON g_hTrayIcon = NULL; HICON g_hTrayIcon = NULL;
HWND g_hwndLastActive = NULL; HWND g_hwndLastActive = NULL;
INT g_cKLs = 0; UINT g_iKL = 0;
UINT g_cKLs = 0;
HKL g_ahKLs[64]; HKL g_ahKLs[64];
HMENU g_hPopupMenu = NULL;
UINT g_uTaskbarRestartMsg = 0; UINT g_uTaskbarRestartMsg = 0;
UINT g_uShellHookMessage = 0; UINT g_uShellHookMessage = 0;
@ -150,42 +149,33 @@ static HKL GetActiveKL(VOID)
static VOID UpdateLayoutList(HKL hKL OPTIONAL) static VOID UpdateLayoutList(HKL hKL OPTIONAL)
{ {
INT iKL; UINT iKL;
if (!hKL) if (!hKL)
hKL = GetActiveKL(); hKL = GetActiveKL();
g_cKLs = GetKeyboardLayoutList(_countof(g_ahKLs), g_ahKLs); g_cKLs = GetKeyboardLayoutList(_countof(g_ahKLs), g_ahKLs);
g_nCurrentLayoutNum = -1; g_iKL = 0;
for (iKL = 0; iKL < g_cKLs; ++iKL) for (iKL = 0; iKL < g_cKLs; ++iKL)
{ {
if (g_ahKLs[iKL] == hKL) if (g_ahKLs[iKL] == hKL)
{ {
g_nCurrentLayoutNum = iKL + 1; g_iKL = iKL;
break; break;
} }
} }
if (g_nCurrentLayoutNum == -1 && g_cKLs < _countof(g_ahKLs))
{
g_nCurrentLayoutNum = g_cKLs;
g_ahKLs[g_cKLs++] = hKL;
}
} }
static HKL GetHKLFromLayoutNum(INT nLayoutNum) static HKL GetHKLFromLayoutNum(UINT iKL)
{ {
if (0 <= (nLayoutNum - 1) && (nLayoutNum - 1) < g_cKLs) return (iKL < g_cKLs) ? g_ahKLs[iKL] : GetActiveKL();
return g_ahKLs[nLayoutNum - 1];
else
return GetActiveKL();
} }
static VOID static VOID
GetKLIDFromLayoutNum(INT nLayoutNum, LPTSTR szKLID, SIZE_T KLIDLength) GetKLIDFromLayoutNum(UINT iKL, LPTSTR szKLID, SIZE_T KLIDLength)
{ {
GetKLIDFromHKL(GetHKLFromLayoutNum(nLayoutNum), szKLID, KLIDLength); GetKLIDFromHKL(GetHKLFromLayoutNum(iKL), szKLID, KLIDLength);
} }
static BOOL static BOOL
@ -200,14 +190,14 @@ GetSystemLibraryPath(LPTSTR szPath, SIZE_T cchPath, LPCTSTR FileName)
} }
static BOOL static BOOL
GetLayoutName(INT nLayoutNum, LPTSTR szName, SIZE_T NameLength) GetLayoutName(UINT iKL, LPTSTR szName, SIZE_T NameLength)
{ {
HKEY hKey; HKEY hKey;
HRESULT hr; HRESULT hr;
DWORD dwBufLen; DWORD dwBufLen;
TCHAR szBuf[MAX_PATH], szKLID[CCH_LAYOUT_ID + 1]; TCHAR szBuf[MAX_PATH], szKLID[CCH_LAYOUT_ID + 1];
GetKLIDFromLayoutNum(nLayoutNum, szKLID, _countof(szKLID)); GetKLIDFromLayoutNum(iKL, szKLID, _countof(szKLID));
StringCchPrintf(szBuf, _countof(szBuf), StringCchPrintf(szBuf, _countof(szBuf),
_T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s"), szKLID); _T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s"), szKLID);
@ -426,8 +416,8 @@ AddTrayIcon(HWND hwnd)
NOTIFYICONDATA tnid = { sizeof(tnid), hwnd, 1, NIF_ICON | NIF_MESSAGE | NIF_TIP }; NOTIFYICONDATA tnid = { sizeof(tnid), hwnd, 1, NIF_ICON | NIF_MESSAGE | NIF_TIP };
TCHAR szKLID[CCH_LAYOUT_ID + 1], szName[MAX_PATH], szImeFile[80]; TCHAR szKLID[CCH_LAYOUT_ID + 1], szName[MAX_PATH], szImeFile[80];
GetKLIDFromLayoutNum(g_nCurrentLayoutNum, szKLID, _countof(szKLID)); GetKLIDFromLayoutNum(g_iKL, szKLID, _countof(szKLID));
GetLayoutName(g_nCurrentLayoutNum, szName, _countof(szName)); GetLayoutName(g_iKL, szName, _countof(szName));
GetImeFile(szImeFile, _countof(szImeFile), szKLID); GetImeFile(szImeFile, _countof(szImeFile), szKLID);
tnid.uCallbackMessage = WM_NOTIFYICONMSG; tnid.uCallbackMessage = WM_NOTIFYICONMSG;
@ -481,17 +471,16 @@ EnumWindowsProc(HWND hwnd, LPARAM lParam)
} }
static VOID static VOID
ActivateLayout(HWND hwnd, ULONG uLayoutNum, HWND hwndTarget OPTIONAL, BOOL bNoActivate) ActivateLayout(HWND hwnd, UINT iKL, HWND hwndTarget OPTIONAL, BOOL bNoActivate)
{ {
HKL hKl; HKL hKl;
TCHAR szKLID[CCH_LAYOUT_ID + 1], szLangName[MAX_PATH]; TCHAR szKLID[CCH_LAYOUT_ID + 1], szLangName[MAX_PATH];
LANGID LangID; LANGID LangID;
/* The layout number starts from one. Zero is invalid */ if (iKL >= g_cKLs) /* Invalid */
if (uLayoutNum == 0 || uLayoutNum > 0xFF) /* Invalid */
return; return;
GetKLIDFromLayoutNum(uLayoutNum, szKLID, _countof(szKLID)); GetKLIDFromLayoutNum(iKL, szKLID, _countof(szKLID));
LangID = (LANGID)_tcstoul(szKLID, NULL, 16); LangID = (LANGID)_tcstoul(szKLID, NULL, 16);
/* Switch to the new keyboard layout */ /* Switch to the new keyboard layout */
@ -516,7 +505,7 @@ ActivateLayout(HWND hwnd, ULONG uLayoutNum, HWND hwndTarget OPTIONAL, BOOL bNoAc
EnumWindows(EnumWindowsProc, (LPARAM) hKl); EnumWindows(EnumWindowsProc, (LPARAM) hKl);
} }
g_nCurrentLayoutNum = uLayoutNum; g_iKL = iKL;
} }
static HMENU static HMENU
@ -526,18 +515,18 @@ BuildLeftPopupMenu(VOID)
TCHAR szName[MAX_PATH], szKLID[CCH_LAYOUT_ID + 1], szImeFile[80]; TCHAR szName[MAX_PATH], szKLID[CCH_LAYOUT_ID + 1], szImeFile[80];
HICON hIcon; HICON hIcon;
MENUITEMINFO mii = { sizeof(mii) }; MENUITEMINFO mii = { sizeof(mii) };
INT iKL; UINT iKL;
for (iKL = 0; iKL < g_cKLs; ++iKL) for (iKL = 0; iKL < g_cKLs; ++iKL)
{ {
GetKLIDFromHKL(g_ahKLs[iKL], szKLID, _countof(szKLID)); GetKLIDFromHKL(g_ahKLs[iKL], szKLID, _countof(szKLID));
GetImeFile(szImeFile, _countof(szImeFile), szKLID); GetImeFile(szImeFile, _countof(szImeFile), szKLID);
if (!GetLayoutName(iKL + 1, szName, _countof(szName))) if (!GetLayoutName(iKL, szName, _countof(szName)))
continue; continue;
mii.fMask = MIIM_ID | MIIM_STRING; mii.fMask = MIIM_ID | MIIM_STRING;
mii.wID = iKL + 1; mii.wID = ID_LANG_BASE + iKL;
mii.dwTypeData = szName; mii.dwTypeData = szName;
hIcon = CreateTrayIcon(szKLID, szImeFile); hIcon = CreateTrayIcon(szKLID, szImeFile);
@ -552,12 +541,12 @@ BuildLeftPopupMenu(VOID)
DestroyIcon(hIcon); DestroyIcon(hIcon);
} }
CheckMenuItem(hMenu, g_nCurrentLayoutNum, MF_CHECKED); CheckMenuItem(hMenu, ID_LANG_BASE + g_iKL, MF_CHECKED);
return hMenu; return hMenu;
} }
BOOL static BOOL
SetHooks(VOID) SetHooks(VOID)
{ {
g_hHookDLL = LoadLibrary(_T("kbsdll.dll")); g_hHookDLL = LoadLibrary(_T("kbsdll.dll"));
@ -579,7 +568,7 @@ SetHooks(VOID)
return TRUE; return TRUE;
} }
VOID static VOID
DeleteHooks(VOID) DeleteHooks(VOID)
{ {
if (KbSwitchSetHooks) if (KbSwitchSetHooks)
@ -599,23 +588,17 @@ DeleteHooks(VOID)
static UINT GetLayoutNum(HKL hKL) static UINT GetLayoutNum(HKL hKL)
{ {
INT iKL; UINT iKL;
for (iKL = 0; iKL < g_cKLs; ++iKL) for (iKL = 0; iKL < g_cKLs; ++iKL)
{ {
if (g_ahKLs[iKL] == hKL) if (g_ahKLs[iKL] == hKL)
return iKL + 1; return iKL;
} }
return 0; return 0;
} }
ULONG
GetNextLayout(VOID)
{
return (g_nCurrentLayoutNum % g_cKLs) + 1;
}
UINT UINT
UpdateLanguageDisplay(HWND hwnd, HKL hKL) UpdateLanguageDisplay(HWND hwnd, HKL hKL)
{ {
@ -626,7 +609,7 @@ UpdateLanguageDisplay(HWND hwnd, HKL hKL)
LangID = (LANGID)_tcstoul(szKLID, NULL, 16); LangID = (LANGID)_tcstoul(szKLID, NULL, 16);
GetLocaleInfo(LangID, LOCALE_SLANGUAGE, szLangName, _countof(szLangName)); GetLocaleInfo(LangID, LOCALE_SLANGUAGE, szLangName, _countof(szLangName));
UpdateTrayIcon(hwnd, szKLID, szLangName); UpdateTrayIcon(hwnd, szKLID, szLangName);
g_nCurrentLayoutNum = GetLayoutNum(hKL); g_iKL = GetLayoutNum(hKL);
return 0; return 0;
} }
@ -682,7 +665,7 @@ KbSwitch_OnCreate(HWND hwnd)
UpdateLayoutList(NULL); UpdateLayoutList(NULL);
AddTrayIcon(hwnd); AddTrayIcon(hwnd);
ActivateLayout(hwnd, g_nCurrentLayoutNum, NULL, TRUE); ActivateLayout(hwnd, g_iKL, NULL, TRUE);
g_uTaskbarRestartMsg = RegisterWindowMessage(TEXT("TaskbarCreated")); g_uTaskbarRestartMsg = RegisterWindowMessage(TEXT("TaskbarCreated"));
return 0; /* Success */ return 0; /* Success */
@ -694,8 +677,6 @@ KbSwitch_OnDestroy(HWND hwnd)
{ {
KillTimer(hwnd, TIMER_ID_LANG_CHANGED_DELAYED); KillTimer(hwnd, TIMER_ID_LANG_CHANGED_DELAYED);
DeleteHooks(); DeleteHooks();
if (g_hPopupMenu)
DestroyMenu(g_hPopupMenu);
DeleteTrayIcon(hwnd); DeleteTrayIcon(hwnd);
PostQuitMessage(0); PostQuitMessage(0);
} }
@ -717,7 +698,7 @@ KbSwitch_OnTimer(HWND hwnd, UINT_PTR nTimerID)
static void static void
KbSwitch_OnNotifyIconMsg(HWND hwnd, UINT uMouseMsg) KbSwitch_OnNotifyIconMsg(HWND hwnd, UINT uMouseMsg)
{ {
if (uMouseMsg != WM_LBUTTONUP && uMouseMsg != WM_RBUTTONUP) if (uMouseMsg != WM_LBUTTONUP && uMouseMsg != WM_RBUTTONUP && uMouseMsg != WM_CONTEXTMENU)
return; return;
UpdateLayoutList(NULL); UpdateLayoutList(NULL);
@ -731,17 +712,18 @@ KbSwitch_OnNotifyIconMsg(HWND hwnd, UINT uMouseMsg)
if (uMouseMsg == WM_LBUTTONUP) if (uMouseMsg == WM_LBUTTONUP)
{ {
/* Rebuild the left popup menu on every click to take care of keyboard layout changes */ /* Rebuild the left popup menu on every click to take care of keyboard layout changes */
HMENU hLeftPopupMenu = BuildLeftPopupMenu(); HMENU hPopupMenu = BuildLeftPopupMenu();
nID = TrackPopupMenu(hLeftPopupMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwnd, NULL); nID = TrackPopupMenuEx(hPopupMenu, TPM_LEFTALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON,
DestroyMenu(hLeftPopupMenu); pt.x, pt.y, hwnd, NULL);
DestroyMenu(hPopupMenu);
} }
else /* WM_RBUTTONUP */ else /* WM_RBUTTONUP or WM_CONTEXTMENU */
{ {
if (!g_hPopupMenu) HMENU hPopupMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_POPUP));
g_hPopupMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_POPUP)); HMENU hSubMenu = GetSubMenu(hPopupMenu, 0);
nID = TrackPopupMenuEx(hSubMenu, TPM_LEFTALIGN | TPM_RETURNCMD | TPM_RIGHTBUTTON,
HMENU hSubMenu = GetSubMenu(g_hPopupMenu, 0); pt.x, pt.y, hwnd, NULL);
nID = TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwnd, NULL); DestroyMenu(hPopupMenu);
} }
PostMessage(hwnd, WM_NULL, 0, 0); PostMessage(hwnd, WM_NULL, 0, 0);
@ -772,13 +754,13 @@ KbSwitch_OnCommand(HWND hwnd, UINT nID)
default: default:
{ {
if (1 <= nID && nID <= 1000) if (nID >= ID_LANG_BASE)
{ {
if (!IsWindow(g_hwndLastActive)) if (!IsWindow(g_hwndLastActive))
{ {
g_hwndLastActive = NULL; g_hwndLastActive = NULL;
} }
ActivateLayout(hwnd, nID, g_hwndLastActive, FALSE); ActivateLayout(hwnd, nID - ID_LANG_BASE, g_hwndLastActive, FALSE);
} }
break; break;
} }

View file

@ -4,8 +4,9 @@
#define IDI_MAIN 100 #define IDI_MAIN 100
/* Menus */ /* Menus */
#define IDR_POPUP 12000 #define IDR_POPUP 100
/* Menu items */ /* Menu items */
#define ID_EXIT 10001 #define ID_EXIT 100
#define ID_PREFERENCES 10002 #define ID_PREFERENCES 101
#define ID_LANG_BASE 1000