mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Support change window hotkey
This commit is contained in:
parent
53e0bc33ab
commit
724b8a72cb
3 changed files with 110 additions and 29 deletions
|
|
@ -10,6 +10,7 @@ using System.Windows.Input;
|
|||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Flow.Launcher.Core.ExternalPlugins;
|
||||
using Flow.Launcher.Infrastructure;
|
||||
using Flow.Launcher.Infrastructure.Hotkey;
|
||||
using Flow.Launcher.Infrastructure.UserSettings;
|
||||
using Flow.Launcher.Plugin;
|
||||
using Flow.Launcher.Plugin.SharedCommands;
|
||||
|
|
@ -40,7 +41,7 @@ namespace Flow.Launcher.Core.Plugin
|
|||
private static PluginsSettings Settings;
|
||||
private static List<PluginMetadata> _metadatas;
|
||||
private static readonly List<string> _modifiedPlugins = new();
|
||||
private static readonly Dictionary<KeyGesture, List<(PluginMetadata, SearchWindowPluginHotkey)>> _windowPluginHotkeys = new();
|
||||
private static readonly Dictionary<HotkeyModel, List<(PluginMetadata, SearchWindowPluginHotkey)>> _windowPluginHotkeys = new();
|
||||
|
||||
/// <summary>
|
||||
/// Directories that will hold Flow Launcher plugin directory
|
||||
|
|
@ -461,7 +462,7 @@ namespace Flow.Launcher.Core.Plugin
|
|||
return hotkeyPluginInfos;
|
||||
}
|
||||
|
||||
public static Dictionary<KeyGesture, List<(PluginMetadata Metadata, SearchWindowPluginHotkey SearchWindowPluginHotkey)>> GetWindowPluginHotkeys()
|
||||
public static Dictionary<HotkeyModel, List<(PluginMetadata Metadata, SearchWindowPluginHotkey SearchWindowPluginHotkey)>> GetWindowPluginHotkeys()
|
||||
{
|
||||
return _windowPluginHotkeys;
|
||||
}
|
||||
|
|
@ -478,22 +479,66 @@ namespace Flow.Launcher.Core.Plugin
|
|||
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)
|
||||
var hotkeyModel = new HotkeyModel(hotkeySetting);
|
||||
if (!_windowPluginHotkeys.TryGetValue(hotkeyModel, out var list))
|
||||
{
|
||||
if (!_windowPluginHotkeys.TryGetValue(keyGesture, out var list))
|
||||
{
|
||||
list = new List<(PluginMetadata, SearchWindowPluginHotkey)>();
|
||||
_windowPluginHotkeys[keyGesture] = list;
|
||||
}
|
||||
list.Add((pluginPair.Metadata, searchWindowHotkey));
|
||||
list = new List<(PluginMetadata, SearchWindowPluginHotkey)>();
|
||||
_windowPluginHotkeys[hotkeyModel] = list;
|
||||
}
|
||||
list.Add((pluginPair.Metadata, searchWindowHotkey));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string ChangePluginHotkey(PluginMetadata plugin, GlobalPluginHotkey pluginHotkey, HotkeyModel newHotkey)
|
||||
{
|
||||
var oldHotkeyItem = plugin.PluginHotkeys.First(h => h.Id == pluginHotkey.Id);
|
||||
var settingHotkeyItem = Settings.GetPluginSettings(plugin.ID).pluginHotkeys.First(h => h.Id == pluginHotkey.Id);
|
||||
var oldHotkey = settingHotkeyItem.Hotkey;
|
||||
var newHotkeyStr = newHotkey.ToString();
|
||||
|
||||
// Update hotkey in plugin metadata & setting
|
||||
oldHotkeyItem.Hotkey = newHotkeyStr;
|
||||
settingHotkeyItem.Hotkey = newHotkeyStr;
|
||||
|
||||
return oldHotkey;
|
||||
}
|
||||
|
||||
public static (HotkeyModel Old, HotkeyModel New) ChangePluginHotkey(PluginMetadata plugin, SearchWindowPluginHotkey pluginHotkey, HotkeyModel newHotkey)
|
||||
{
|
||||
var oldHotkeyItem = plugin.PluginHotkeys.First(h => h.Id == pluginHotkey.Id);
|
||||
var settingHotkeyItem = Settings.GetPluginSettings(plugin.ID).pluginHotkeys.First(h => h.Id == pluginHotkey.Id);
|
||||
var oldHotkey = settingHotkeyItem.Hotkey;
|
||||
var converter = new KeyGestureConverter();
|
||||
var oldHotkeyModel = new HotkeyModel(oldHotkey);
|
||||
var newHotkeyStr = newHotkey.ToString();
|
||||
|
||||
// Update hotkey in plugin metadata & setting
|
||||
oldHotkeyItem.Hotkey = newHotkeyStr;
|
||||
settingHotkeyItem.Hotkey = newHotkeyStr;
|
||||
|
||||
// Update window plugin hotkey dictionary
|
||||
var oldHotkeyModels = _windowPluginHotkeys[oldHotkeyModel];
|
||||
_windowPluginHotkeys[oldHotkeyModel] = oldHotkeyModels.Where(x => x.Item1.ID != plugin.ID || x.Item2.Id != pluginHotkey.Id).ToList();
|
||||
|
||||
if (_windowPluginHotkeys.TryGetValue(newHotkey, out var newHotkeyModels))
|
||||
{
|
||||
var newList = newHotkeyModels.ToList();
|
||||
newList.Add((plugin, pluginHotkey));
|
||||
_windowPluginHotkeys[newHotkey] = newList;
|
||||
}
|
||||
else
|
||||
{
|
||||
_windowPluginHotkeys[newHotkey] = new List<(PluginMetadata, SearchWindowPluginHotkey)>()
|
||||
{
|
||||
(plugin, pluginHotkey)
|
||||
};
|
||||
}
|
||||
|
||||
return (oldHotkeyModel, newHotkey);
|
||||
}
|
||||
|
||||
public static bool ActionKeywordRegistered(string actionKeyword)
|
||||
{
|
||||
// this method is only checking for action keywords (defined as not '*') registration
|
||||
|
|
|
|||
|
|
@ -163,20 +163,27 @@ internal static class HotKeyMapper
|
|||
{
|
||||
if (hotkey.HotkeyType == HotkeyType.Global && hotkey is GlobalPluginHotkey globalHotkey)
|
||||
{
|
||||
var hotkeySetting = metadata.PluginHotkeys.Find(h => h.Id == hotkey.Id)?.Hotkey ?? hotkey.DefaultHotkey;
|
||||
SetGlobalPluginHotkey(globalHotkey, metadata, hotkeySetting);
|
||||
var hotkeyStr = metadata.PluginHotkeys.Find(h => h.Id == hotkey.Id)?.Hotkey ?? hotkey.DefaultHotkey;
|
||||
SetGlobalPluginHotkey(globalHotkey, metadata, hotkeyStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static void SetGlobalPluginHotkey(GlobalPluginHotkey globalHotkey, PluginMetadata metadata, string hotkeySetting)
|
||||
internal static void SetGlobalPluginHotkey(GlobalPluginHotkey globalHotkey, PluginMetadata metadata, string hotkeyStr)
|
||||
{
|
||||
SetHotkey(hotkeySetting, (s, e) =>
|
||||
var hotkey = new HotkeyModel(hotkeyStr);
|
||||
SetGlobalPluginHotkey(globalHotkey, metadata, hotkey);
|
||||
}
|
||||
|
||||
internal static void SetGlobalPluginHotkey(GlobalPluginHotkey globalHotkey, PluginMetadata metadata, HotkeyModel hotkey)
|
||||
{
|
||||
var hotkeyStr = hotkey.ToString();
|
||||
SetHotkey(hotkeyStr, (s, e) =>
|
||||
{
|
||||
if (_mainViewModel.ShouldIgnoreHotkeys() || metadata.Disabled)
|
||||
return;
|
||||
|
||||
|
||||
globalHotkey.Action?.Invoke();
|
||||
});
|
||||
}
|
||||
|
|
@ -186,12 +193,11 @@ internal static class HotKeyMapper
|
|||
var windowPluginHotkeys = PluginManager.GetWindowPluginHotkeys();
|
||||
foreach (var hotkey in windowPluginHotkeys)
|
||||
{
|
||||
var keyGesture = hotkey.Key;
|
||||
SetWindowHotkey(keyGesture, hotkey.Value);
|
||||
SetWindowHotkey(hotkey.Key, hotkey.Value);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void SetWindowHotkey(KeyGesture keyGesture, List<(PluginMetadata Metadata, SearchWindowPluginHotkey PluginHotkey)> hotkeyModels)
|
||||
internal static void SetWindowHotkey(HotkeyModel hotkey, List<(PluginMetadata Metadata, SearchWindowPluginHotkey PluginHotkey)> hotkeyModels)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -201,13 +207,17 @@ internal static class HotKeyMapper
|
|||
var command = BuildCommand(hotkeyModels);
|
||||
|
||||
// Remove any existing key binding with the same gesture to avoid duplication
|
||||
var keyGesture = hotkey.ToKeyGesture();
|
||||
var existingBinding = window.InputBindings
|
||||
.OfType<KeyBinding>()
|
||||
.FirstOrDefault(kb => kb.Gesture == keyGesture);
|
||||
.FirstOrDefault(kb =>
|
||||
kb.Gesture is KeyGesture keyGesture1 &&
|
||||
keyGesture.Key == keyGesture1.Key &&
|
||||
keyGesture.Modifiers == keyGesture1.Modifiers);
|
||||
|
||||
if (existingBinding != null)
|
||||
{
|
||||
throw new InvalidOperationException($"Key binding with gesture {keyGesture} already exists");
|
||||
throw new InvalidOperationException($"Key binding with gesture {hotkey} already exists");
|
||||
}
|
||||
|
||||
// Create and add the new key binding
|
||||
|
|
@ -221,8 +231,8 @@ internal static class HotKeyMapper
|
|||
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);
|
||||
hotkey));
|
||||
string errorMsg = string.Format(App.API.GetTranslation("registerWindowHotkeyFailed"), hotkey);
|
||||
string errorMsgTitle = App.API.GetTranslation("MessageBoxTitle");
|
||||
App.API.ShowMsgBox(errorMsg, errorMsgTitle);
|
||||
}
|
||||
|
|
@ -245,16 +255,20 @@ internal static class HotKeyMapper
|
|||
});
|
||||
}
|
||||
|
||||
internal static void RemoveWindowHotkey(KeyGesture keyGesture)
|
||||
internal static void RemoveWindowHotkey(HotkeyModel hotkey)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Application.Current?.MainWindow is MainWindow window)
|
||||
{
|
||||
// Find and remove the key binding with the specified gesture
|
||||
var keyGesture = hotkey.ToKeyGesture();
|
||||
var existingBinding = window.InputBindings
|
||||
.OfType<KeyBinding>()
|
||||
.FirstOrDefault(kb => kb.Gesture == keyGesture);
|
||||
.FirstOrDefault(kb =>
|
||||
kb.Gesture is KeyGesture keyGesture1 &&
|
||||
keyGesture.Key == keyGesture1.Key &&
|
||||
keyGesture.Modifiers == keyGesture1.Modifiers);
|
||||
if (existingBinding != null)
|
||||
{
|
||||
window.InputBindings.Remove(existingBinding);
|
||||
|
|
@ -267,7 +281,7 @@ internal static class HotKeyMapper
|
|||
string.Format("Error removing window hotkey: {0} \nStackTrace:{1}",
|
||||
e.Message,
|
||||
e.StackTrace));
|
||||
string errorMsg = string.Format(App.API.GetTranslation("unregisterWindowHotkeyFailed"), keyGesture.DisplayString);
|
||||
string errorMsg = string.Format(App.API.GetTranslation("unregisterWindowHotkeyFailed"), hotkey);
|
||||
string errorMsgTitle = App.API.GetTranslation("MessageBoxTitle");
|
||||
App.API.ShowMsgBox(errorMsg, errorMsgTitle);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,11 @@ using System.Windows;
|
|||
using System.Windows.Controls;
|
||||
using System.Windows.Navigation;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Flow.Launcher.Core.Plugin;
|
||||
using Flow.Launcher.Helper;
|
||||
using Flow.Launcher.Infrastructure.Hotkey;
|
||||
using Flow.Launcher.Plugin;
|
||||
using Flow.Launcher.Resources.Controls;
|
||||
using Flow.Launcher.SettingPages.ViewModels;
|
||||
using Flow.Launcher.ViewModel;
|
||||
|
|
@ -65,16 +69,15 @@ public partial class SettingsPaneHotkey
|
|||
var hotkeySetting = metadata.PluginHotkeys.Find(h => h.Id == hotkey.Id)?.Hotkey ?? hotkey.DefaultHotkey;
|
||||
if (hotkey.Editable)
|
||||
{
|
||||
// TODO: Check if this can use
|
||||
var hotkeyControl = new HotkeyControl
|
||||
{
|
||||
Type = HotkeyControl.HotkeyType.CustomQueryHotkey,
|
||||
DefaultHotkey = hotkey.DefaultHotkey,
|
||||
Hotkey = hotkeySetting,
|
||||
ValidateKeyGesture = true
|
||||
};
|
||||
hotkeyControl.SetHotkey(hotkeySetting, true);
|
||||
hotkeyControl.ChangeHotkey = new RelayCommand<HotkeyModel>((m) => ChangePluginHotkey(metadata, hotkey, m));
|
||||
card.Content = hotkeyControl;
|
||||
// TODO: Update metadata & plugin setting hotkey
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -90,4 +93,23 @@ public partial class SettingsPaneHotkey
|
|||
PluginHotkeySettings.Children.Add(excard);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ChangePluginHotkey(PluginMetadata metadata, BasePluginHotkey pluginHotkey, HotkeyModel newHotkey)
|
||||
{
|
||||
if (pluginHotkey is GlobalPluginHotkey globalPluginHotkey)
|
||||
{
|
||||
var oldHotkey = PluginManager.ChangePluginHotkey(metadata, globalPluginHotkey, newHotkey);
|
||||
HotKeyMapper.RemoveHotkey(oldHotkey);
|
||||
HotKeyMapper.SetGlobalPluginHotkey(globalPluginHotkey, metadata, newHotkey);
|
||||
}
|
||||
else if (pluginHotkey is SearchWindowPluginHotkey windowPluginHotkey)
|
||||
{
|
||||
var (oldHotkeyModel, newHotkeyModel) = PluginManager.ChangePluginHotkey(metadata, windowPluginHotkey, newHotkey);
|
||||
var windowPluginHotkeys = PluginManager.GetWindowPluginHotkeys();
|
||||
HotKeyMapper.RemoveWindowHotkey(oldHotkeyModel);
|
||||
HotKeyMapper.RemoveWindowHotkey(newHotkeyModel);
|
||||
HotKeyMapper.SetWindowHotkey(oldHotkeyModel, windowPluginHotkeys[oldHotkeyModel]);
|
||||
HotKeyMapper.SetWindowHotkey(newHotkeyModel, windowPluginHotkeys[newHotkeyModel]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue