From 81a46327223596a9cff55bd8ad4e1b332237d997 Mon Sep 17 00:00:00 2001 From: Yusyuriv Date: Sat, 22 Mar 2025 00:27:03 +0600 Subject: [PATCH] Implement auto-switching to English when the option is enabled --- Flow.Launcher/Helper/KeyboardLayoutHelper.cs | 95 ++++++++++++++++++++ Flow.Launcher/ViewModel/MainViewModel.cs | 13 ++- 2 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 Flow.Launcher/Helper/KeyboardLayoutHelper.cs diff --git a/Flow.Launcher/Helper/KeyboardLayoutHelper.cs b/Flow.Launcher/Helper/KeyboardLayoutHelper.cs new file mode 100644 index 000000000..db62ef783 --- /dev/null +++ b/Flow.Launcher/Helper/KeyboardLayoutHelper.cs @@ -0,0 +1,95 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace Flow.Launcher.Helper; + +public static class KeyboardLayoutHelper +{ + #region Windows API + + [DllImport("user32.dll")] + private static extern IntPtr GetKeyboardLayout(uint idThread); + + [DllImport("user32.dll")] + private static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr lpdwProcessId); + + [DllImport("user32.dll")] + private static extern IntPtr ActivateKeyboardLayout(IntPtr hkl, uint flags); + + [DllImport("user32.dll")] + private static extern int GetKeyboardLayoutList(int nBuff, [Out] IntPtr[] lpList); + + [DllImport("kernel32.dll")] + private static extern int GetLocaleInfoA(uint Locale, uint LCType, StringBuilder lpLCData, int cchData); + + [DllImport("user32.dll")] + private static extern IntPtr GetForegroundWindow(); + + // Used to get the language name of the keyboard layout + private const uint LOCALE_SLANGUAGE = 0x00000002; + + // The string to search for in the language name of a keyboard layout + private const string LAYOUT_ENGLISH_SEARCH = "english"; + + private static IntPtr FindEnglishKeyboardLayout() + { + // Get the number of keyboard layouts + var count = GetKeyboardLayoutList(0, null); + if (count <= 0) return IntPtr.Zero; + + // Get all keyboard layouts + var keyboardLayouts = new IntPtr[count]; + GetKeyboardLayoutList(count, keyboardLayouts); + + // Look for any English keyboard layout + foreach (var layout in keyboardLayouts) + { + // The lower word contains the language identifier + var langId = (uint)layout.ToInt32() & 0xFFFF; + + // Get language name for the layout + var sb = new StringBuilder(256); + GetLocaleInfoA(langId, LOCALE_SLANGUAGE, sb, sb.Capacity); + var langName = sb.ToString().ToLowerInvariant(); + + // Check if it's an English layout + if (langName.Contains(LAYOUT_ENGLISH_SEARCH)) + { + return layout; + } + } + + return IntPtr.Zero; + } + + #endregion + + // Query textbox keyboard layout + private static IntPtr _previousLayout; + + public static void SetEnglishKeyboardLayout() + { + // Find an installed English layout + var englishLayout = FindEnglishKeyboardLayout(); + + // No installed English layout found + if (englishLayout == IntPtr.Zero) return; + + var hwnd = GetForegroundWindow(); + var threadId = GetWindowThreadProcessId(hwnd, IntPtr.Zero); + + // Store current keyboard layout + _previousLayout = GetKeyboardLayout(threadId) & 0xFFFF; + + // Switch to English layout + ActivateKeyboardLayout(englishLayout, 0); + } + + public static void SetPreviousKeyboardLayout() + { + if (_previousLayout == IntPtr.Zero) return; + ActivateKeyboardLayout(_previousLayout, 0); + _previousLayout = IntPtr.Zero; + } +} diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 46970a6a1..641825ec6 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -14,6 +14,7 @@ using System.Windows.Threading; using CommunityToolkit.Mvvm.DependencyInjection; using CommunityToolkit.Mvvm.Input; using Flow.Launcher.Core.Plugin; +using Flow.Launcher.Helper; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Hotkey; using Flow.Launcher.Infrastructure.Image; @@ -1373,6 +1374,11 @@ namespace Flow.Launcher.ViewModel MainWindowOpacity = 1; MainWindowVisibilityStatus = true; VisibilityChanged?.Invoke(this, new VisibilityChangedEventArgs { IsVisible = true }); + + if (StartWithEnglishMode) + { + KeyboardLayoutHelper.SetEnglishKeyboardLayout(); + } }); } @@ -1441,7 +1447,12 @@ namespace Flow.Launcher.ViewModel // 📌 Apply DWM Cloak (Completely hide the window) Win32Helper.DWMSetCloakForWindow(mainWindow, true); } - + + if (StartWithEnglishMode) + { + KeyboardLayoutHelper.SetPreviousKeyboardLayout(); + } + await Task.Delay(50); // Update WPF properties