From 8abd5318b36880b7aa036c19edb0cc6b4d9c7034 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 25 Jun 2025 21:39:33 +0800 Subject: [PATCH] Add window key registeration --- Flow.Launcher.Core/Plugin/PluginManager.cs | 39 ++++++++- Flow.Launcher/Helper/HotKeyMapper.cs | 97 ++++++++++++++++++++++ Flow.Launcher/Languages/en.xaml | 2 + 3 files changed, 137 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 96787bab5..6620ba578 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Text.Json; using System.Threading; using System.Threading.Tasks; +using System.Windows.Input; using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Core.ExternalPlugins; using Flow.Launcher.Infrastructure; @@ -39,6 +40,7 @@ namespace Flow.Launcher.Core.Plugin private static PluginsSettings Settings; private static List _metadatas; private static readonly List _modifiedPlugins = new(); + private static readonly Dictionary> _windowPluginHotkeys = new(); /// /// Directories that will hold Flow Launcher plugin directory @@ -252,7 +254,9 @@ namespace Flow.Launcher.Core.Plugin _contextMenuPlugins = GetPluginsForInterface(); _homePlugins = GetPluginsForInterface(); _hotkeyPlugins = GetPluginsForInterface(); - Settings.UpdatePluginHotkeyInfo(GetPluginHotkeyInfo()); + var pluginHotkeyInfo = GetPluginHotkeyInfo(); + Settings.UpdatePluginHotkeyInfo(pluginHotkeyInfo); + InitializeWindowPluginHotkeys(pluginHotkeyInfo); foreach (var plugin in AllPlugins) { @@ -457,6 +461,39 @@ namespace Flow.Launcher.Core.Plugin return hotkeyPluginInfos; } + public static Dictionary> GetWindowPluginHotkeys() + { + return _windowPluginHotkeys; + } + + private static void InitializeWindowPluginHotkeys(Dictionary> pluginHotkeyInfo) + { + foreach (var info in pluginHotkeyInfo) + { + var pluginPair = info.Key; + var hotkeyInfo = info.Value; + var metadata = pluginPair.Metadata; + foreach (var hotkey in hotkeyInfo) + { + if (hotkey.HotkeyType == HotkeyType.SearchWindow && hotkey is SearchWindowPluginHotkey searchWindowHotkey) + { + var hotkeySetting = metadata.PluginHotkeys.Find(h => h.Id == hotkey.Id)?.Hotkey ?? hotkey.DefaultHotkey; + var converter = new KeyGestureConverter(); + var keyGesture = (KeyGesture)converter.ConvertFromString(hotkeySetting); + if (keyGesture != null) + { + if (!_windowPluginHotkeys.TryGetValue(keyGesture, out var list)) + { + list = new List<(PluginMetadata, SearchWindowPluginHotkey)>(); + _windowPluginHotkeys[keyGesture] = list; + } + list.Add((pluginPair.Metadata, searchWindowHotkey)); + } + } + } + } + } + public static bool ActionKeywordRegistered(string actionKeyword) { // this method is only checking for action keywords (defined as not '*') registration diff --git a/Flow.Launcher/Helper/HotKeyMapper.cs b/Flow.Launcher/Helper/HotKeyMapper.cs index de1933520..8a9c07d9a 100644 --- a/Flow.Launcher/Helper/HotKeyMapper.cs +++ b/Flow.Launcher/Helper/HotKeyMapper.cs @@ -1,6 +1,11 @@ using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows; +using System.Windows.Input; using ChefKeys; using CommunityToolkit.Mvvm.DependencyInjection; +using CommunityToolkit.Mvvm.Input; using Flow.Launcher.Core.Plugin; using Flow.Launcher.Infrastructure.Hotkey; using Flow.Launcher.Infrastructure.UserSettings; @@ -26,6 +31,7 @@ internal static class HotKeyMapper SetHotkey(_settings.Hotkey, OnToggleHotkey); LoadCustomPluginHotkey(); LoadGlobalPluginHotkey(); + LoadWindowPluginHotkey(); } internal static void OnToggleHotkey(object sender, HotkeyEventArgs args) @@ -175,6 +181,97 @@ internal static class HotKeyMapper }); } + internal static void LoadWindowPluginHotkey() + { + var windowPluginHotkeys = PluginManager.GetWindowPluginHotkeys(); + foreach (var hotkey in windowPluginHotkeys) + { + var keyGesture = hotkey.Key; + SetWindowHotkey(keyGesture, hotkey.Value); + } + } + + private static void SetWindowHotkey(KeyGesture keyGesture, List<(PluginMetadata Metadata, SearchWindowPluginHotkey PluginHotkey)> hotkeyModels) + { + try + { + if (Application.Current?.MainWindow is MainWindow window) + { + var command = BuildCommand(hotkeyModels); + + // Remove any existing key binding with the same gesture to avoid duplication + var existingBinding = window.InputBindings + .OfType() + .FirstOrDefault(kb => kb.Gesture == keyGesture); + + if (existingBinding != null) + { + throw new InvalidOperationException($"Key binding with gesture {keyGesture} already exists"); + } + + // Create and add the new key binding + var keyBinding = new KeyBinding(command, keyGesture); + window.InputBindings.Add(keyBinding); + } + } + catch (Exception e) + { + App.API.LogError(ClassName, + string.Format("Error registering window hotkey {2}: {0} \nStackTrace:{1}", + e.Message, + e.StackTrace, + keyGesture.DisplayString)); + string errorMsg = string.Format(App.API.GetTranslation("registerWindowHotkeyFailed"), keyGesture.DisplayString); + string errorMsgTitle = App.API.GetTranslation("MessageBoxTitle"); + App.API.ShowMsgBox(errorMsg, errorMsgTitle); + } + } + + private static ICommand BuildCommand(List<(PluginMetadata Metadata, SearchWindowPluginHotkey PluginHotkey)> hotkeyModels) + { + return new RelayCommand(() => + { + foreach (var hotkeyModel in hotkeyModels) + { + var metadata = hotkeyModel.Metadata; + if (metadata.Disabled) + continue; + + var pluginHotkey = hotkeyModel.PluginHotkey; + if (pluginHotkey.Action?.Invoke(_mainViewModel.Results.SelectedItem?.Result) ?? false) + App.API.HideMainWindow(); + } + }); + } + + internal static void RemoveWindowHotkey(KeyGesture keyGesture) + { + try + { + if (Application.Current?.MainWindow is MainWindow window) + { + // Find and remove the key binding with the specified gesture + var existingBinding = window.InputBindings + .OfType() + .FirstOrDefault(kb => kb.Gesture == keyGesture); + if (existingBinding != null) + { + window.InputBindings.Remove(existingBinding); + } + } + } + catch (Exception e) + { + App.API.LogError(ClassName, + string.Format("Error removing window hotkey: {0} \nStackTrace:{1}", + e.Message, + e.StackTrace)); + string errorMsg = string.Format(App.API.GetTranslation("unregisterWindowHotkeyFailed"), keyGesture.DisplayString); + string errorMsgTitle = App.API.GetTranslation("MessageBoxTitle"); + App.API.ShowMsgBox(errorMsg, errorMsgTitle); + } + } + internal static bool CheckAvailability(HotkeyModel currentHotkey) { try diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 3769adbe0..365215307 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -21,6 +21,8 @@ Failed to register hotkey "{0}". The hotkey may be in use by another program. Change to a different hotkey, or exit another program. Failed to unregister hotkey "{0}". Please try again or see log for details + Failed to register window hotkey "{0}". The hotkey may be in use by another program. Change to a different hotkey, or exit another program. + Failed to unregister window hotkey "{0}". Please try again or see log for details Flow Launcher Could not start {0} Invalid Flow Launcher plugin file format