Skip to content

Commit 27ccd3b

Browse files
committed
add new hotkey support for win and four combo keys
1 parent 21f22e6 commit 27ccd3b

File tree

14 files changed

+334
-177
lines changed

14 files changed

+334
-177
lines changed

Flow.Launcher.Infrastructure/Hotkey/HotkeyModel.cs

Lines changed: 94 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.ComponentModel;
44
using System.Linq;
55
using System.Windows.Input;
6+
using Flow.Launcher.Plugin;
67

78
namespace Flow.Launcher.Infrastructure.Hotkey
89
{
@@ -13,6 +14,9 @@ public record struct HotkeyModel
1314
public bool Win { get; set; }
1415
public bool Ctrl { get; set; }
1516

17+
public string HotkeyRaw { get; set; } = string.Empty;
18+
public string PreviousHotkey { get; set; } = string.Empty;
19+
1620
public Key CharKey { get; set; } = Key.None;
1721

1822
private static readonly Dictionary<Key, string> specialSymbolDictionary = new Dictionary<Key, string>
@@ -49,18 +53,56 @@ public ModifierKeys ModifierKeys
4953
}
5054
}
5155

52-
public HotkeyModel(string hotkeyString)
56+
// Used for WPF control only
57+
public void SetHotkeyFromString(string hotkeyString)
5358
{
59+
Clear();
5460
Parse(hotkeyString);
61+
HotkeyRaw = ToChefKeysString();
5562
}
5663

57-
public HotkeyModel(bool alt, bool shift, bool win, bool ctrl, Key key)
64+
internal void SetHotkeyFromWPFControl(SpecialKeyState specialKeyState, Key key)
5865
{
59-
Alt = alt;
60-
Shift = shift;
61-
Win = win;
62-
Ctrl = ctrl;
66+
Alt = specialKeyState.AltPressed;
67+
Shift = specialKeyState.ShiftPressed;
68+
Win = specialKeyState.WinPressed;
69+
Ctrl = specialKeyState.CtrlPressed;
6370
CharKey = key;
71+
HotkeyRaw = ToChefKeysString();
72+
PreviousHotkey = string.Empty;
73+
}
74+
75+
public HotkeyModel(string hotkey)
76+
{
77+
SetHotkeyFromString(hotkey);
78+
}
79+
80+
//public HotkeyModel(bool alt, bool shift, bool win, bool ctrl, Key key)
81+
//{
82+
// Alt = alt;
83+
// Shift = shift;
84+
// Win = win;
85+
// Ctrl = ctrl;
86+
// CharKey = key;
87+
//}
88+
89+
// Use for ChefKeys only
90+
internal void AddString(string key)
91+
{
92+
HotkeyRaw = string.IsNullOrEmpty(HotkeyRaw) ? key : HotkeyRaw + "+" + key;
93+
}
94+
95+
internal bool MaxKeysReached() => DisplayKeysRaw().Count() == 4;
96+
97+
internal void Clear()
98+
{
99+
Alt = false;
100+
Shift = false;
101+
Win = false;
102+
Ctrl = false;
103+
HotkeyRaw = string.Empty;
104+
PreviousHotkey = string.Empty;
105+
CharKey = Key.None;
64106
}
65107

66108
private void Parse(string hotkeyString)
@@ -71,28 +113,36 @@ private void Parse(string hotkeyString)
71113
}
72114

73115
List<string> keys = hotkeyString.Replace(" ", "").Split('+').ToList();
74-
if (keys.Contains("Alt"))
116+
if (keys.Contains("Alt") || keys.Contains("LeftAlt") || keys.Contains("RightAlt"))
75117
{
76118
Alt = true;
77119
keys.Remove("Alt");
120+
keys.Remove("LeftAlt");
121+
keys.Remove("RightAlt");
78122
}
79123

80-
if (keys.Contains("Shift"))
124+
if (keys.Contains("Shift") || keys.Contains("LeftShift") || keys.Contains("RightShift"))
81125
{
82126
Shift = true;
83127
keys.Remove("Shift");
128+
keys.Remove("LeftShift");
129+
keys.Remove("RightShift");
84130
}
85131

86-
if (keys.Contains("Win"))
132+
if (keys.Contains("Win") || keys.Contains("LWin") || keys.Contains("RWin"))
87133
{
88134
Win = true;
89135
keys.Remove("Win");
136+
keys.Remove("LWin");
137+
keys.Remove("RWin");
90138
}
91139

92-
if (keys.Contains("Ctrl"))
140+
if (keys.Contains("Ctrl") || keys.Contains("LeftCtrl")|| keys.Contains("RightCtrl"))
93141
{
94142
Ctrl = true;
95143
keys.Remove("Ctrl");
144+
keys.Remove("LeftCtrl");
145+
keys.Remove("RightCtrl");
96146
}
97147

98148
if (keys.Count == 1)
@@ -117,47 +167,71 @@ private void Parse(string hotkeyString)
117167
}
118168
}
119169

120-
public override string ToString()
170+
public string ToChefKeysString()
121171
{
122-
return string.Join(" + ", EnumerateDisplayKeys());
172+
var key = string.Join("+", EnumerateDisplayKeys(true));
173+
174+
return key;
123175
}
124176

125-
public IEnumerable<string> EnumerateDisplayKeys()
177+
public IEnumerable<string> DisplayKeysRaw() => !string.IsNullOrEmpty(HotkeyRaw) ? HotkeyRaw.Split('+') : Array.Empty<string>();
178+
179+
public IEnumerable<string> EnumerateDisplayKeys(bool forChefKeys = false)
126180
{
127181
if (Ctrl && CharKey is not (Key.LeftCtrl or Key.RightCtrl))
128182
{
129-
yield return "Ctrl";
183+
yield return GetKeyString("Ctrl", forChefKeys);
130184
}
131185

132186
if (Alt && CharKey is not (Key.LeftAlt or Key.RightAlt))
133187
{
134-
yield return "Alt";
188+
yield return GetKeyString("Alt", forChefKeys);
135189
}
136190

137191
if (Shift && CharKey is not (Key.LeftShift or Key.RightShift))
138192
{
139-
yield return "Shift";
193+
yield return GetKeyString("Shift", forChefKeys);
140194
}
141195

142196
if (Win && CharKey is not (Key.LWin or Key.RWin))
143197
{
144-
yield return "Win";
198+
yield return GetKeyString("Win", forChefKeys);
145199
}
146200

147201
if (CharKey != Key.None)
148202
{
149203
yield return specialSymbolDictionary.TryGetValue(CharKey, out var value)
150204
? value
151-
: CharKey.ToString();
205+
: GetKeyString(CharKey.ToString(), forChefKeys);
206+
}
207+
}
208+
209+
private string GetKeyString(string key, bool convertToChefKeysString)
210+
{
211+
if (!convertToChefKeysString)
212+
return key;
213+
214+
switch (key)
215+
{
216+
case "Alt":
217+
return "LeftAlt";
218+
case "Ctrl":
219+
return "LeftCtrl";
220+
case "Shift":
221+
return "LeftShift";
222+
case "Win":
223+
return "LWin";
224+
default:
225+
return key;
152226
}
153227
}
154228

155229
/// <summary>
156-
/// Validate hotkey
230+
/// Validate hotkey for WPF control only
157231
/// </summary>
158232
/// <param name="validateKeyGestrue">Try to validate hotkey as a KeyGesture.</param>
159233
/// <returns></returns>
160-
public bool Validate(bool validateKeyGestrue = false)
234+
public bool ValidateForWpf(bool validateKeyGestrue = false)
161235
{
162236
switch (CharKey)
163237
{

Flow.Launcher.Infrastructure/KeyConstant.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
{
33
public static class KeyConstant
44
{
5-
public const string Ctrl = nameof(Ctrl);
65
public const string Alt = nameof(Alt);
6+
public const string LeftAlt = nameof(LeftAlt);
7+
public const string Ctrl = nameof(Ctrl);
78
public const string Space = nameof(Space);
89
}
9-
}
10+
}

Flow.Launcher.Infrastructure/UserSettings/Settings.cs

Lines changed: 48 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public class Settings : BaseModel, IHotkeySettings
1515
{
1616
private string language = "en";
1717
private string _theme = Constant.DefaultTheme;
18-
public string Hotkey { get; set; } = $"{KeyConstant.Alt} + {KeyConstant.Space}";
18+
public string Hotkey { get; set; } = $"{KeyConstant.LeftAlt} + {KeyConstant.Space}";
1919
public string OpenResultModifiers { get; set; } = KeyConstant.Alt;
2020
public string ColorScheme { get; set; } = "System";
2121
public bool ShowOpenResultHotkey { get; set; } = true;
@@ -288,32 +288,32 @@ public List<RegisteredHotkeyData> RegisteredHotkeys
288288
// Customizeable hotkeys
289289
if(!string.IsNullOrEmpty(Hotkey))
290290
list.Add(new(Hotkey, "flowlauncherHotkey", () => Hotkey = ""));
291-
if(!string.IsNullOrEmpty(PreviewHotkey))
291+
if (!string.IsNullOrEmpty(PreviewHotkey))
292292
list.Add(new(PreviewHotkey, "previewHotkey", () => PreviewHotkey = ""));
293-
if(!string.IsNullOrEmpty(AutoCompleteHotkey))
293+
if (!string.IsNullOrEmpty(AutoCompleteHotkey))
294294
list.Add(new(AutoCompleteHotkey, "autoCompleteHotkey", () => AutoCompleteHotkey = ""));
295-
if(!string.IsNullOrEmpty(AutoCompleteHotkey2))
295+
if (!string.IsNullOrEmpty(AutoCompleteHotkey2))
296296
list.Add(new(AutoCompleteHotkey2, "autoCompleteHotkey", () => AutoCompleteHotkey2 = ""));
297-
if(!string.IsNullOrEmpty(SelectNextItemHotkey))
297+
if (!string.IsNullOrEmpty(SelectNextItemHotkey))
298298
list.Add(new(SelectNextItemHotkey, "SelectNextItemHotkey", () => SelectNextItemHotkey = ""));
299-
if(!string.IsNullOrEmpty(SelectNextItemHotkey2))
299+
if (!string.IsNullOrEmpty(SelectNextItemHotkey2))
300300
list.Add(new(SelectNextItemHotkey2, "SelectNextItemHotkey", () => SelectNextItemHotkey2 = ""));
301-
if(!string.IsNullOrEmpty(SelectPrevItemHotkey))
301+
if (!string.IsNullOrEmpty(SelectPrevItemHotkey))
302302
list.Add(new(SelectPrevItemHotkey, "SelectPrevItemHotkey", () => SelectPrevItemHotkey = ""));
303-
if(!string.IsNullOrEmpty(SelectPrevItemHotkey2))
303+
if (!string.IsNullOrEmpty(SelectPrevItemHotkey2))
304304
list.Add(new(SelectPrevItemHotkey2, "SelectPrevItemHotkey", () => SelectPrevItemHotkey2 = ""));
305-
if(!string.IsNullOrEmpty(SettingWindowHotkey))
306-
list.Add(new(SettingWindowHotkey, "SettingWindowHotkey", () => SettingWindowHotkey = ""));
307-
if(!string.IsNullOrEmpty(OpenContextMenuHotkey))
308-
list.Add(new(OpenContextMenuHotkey, "OpenContextMenuHotkey", () => OpenContextMenuHotkey = ""));
309-
if(!string.IsNullOrEmpty(SelectNextPageHotkey))
310-
list.Add(new(SelectNextPageHotkey, "SelectNextPageHotkey", () => SelectNextPageHotkey = ""));
311-
if(!string.IsNullOrEmpty(SelectPrevPageHotkey))
312-
list.Add(new(SelectPrevPageHotkey, "SelectPrevPageHotkey", () => SelectPrevPageHotkey = ""));
313-
if (!string.IsNullOrEmpty(CycleHistoryUpHotkey))
314-
list.Add(new(CycleHistoryUpHotkey, "CycleHistoryUpHotkey", () => CycleHistoryUpHotkey = ""));
315-
if (!string.IsNullOrEmpty(CycleHistoryDownHotkey))
316-
list.Add(new(CycleHistoryDownHotkey, "CycleHistoryDownHotkey", () => CycleHistoryDownHotkey = ""));
305+
//if (!string.IsNullOrEmpty(SettingWindowHotkey))
306+
// list.Add(new(SettingWindowHotkey, "SettingWindowHotkey", () => SettingWindowHotkey = ""));
307+
//if (!string.IsNullOrEmpty(OpenContextMenuHotkey))
308+
// list.Add(new(OpenContextMenuHotkey, "OpenContextMenuHotkey", () => OpenContextMenuHotkey = ""));
309+
//if (!string.IsNullOrEmpty(SelectNextPageHotkey))
310+
// list.Add(new(SelectNextPageHotkey, "SelectNextPageHotkey", () => SelectNextPageHotkey = ""));
311+
//if (!string.IsNullOrEmpty(SelectPrevPageHotkey))
312+
// list.Add(new(SelectPrevPageHotkey, "SelectPrevPageHotkey", () => SelectPrevPageHotkey = ""));
313+
//if (!string.IsNullOrEmpty(CycleHistoryUpHotkey))
314+
// list.Add(new(CycleHistoryUpHotkey, "CycleHistoryUpHotkey", () => CycleHistoryUpHotkey = ""));
315+
//if (!string.IsNullOrEmpty(CycleHistoryDownHotkey))
316+
// list.Add(new(CycleHistoryDownHotkey, "CycleHistoryDownHotkey", () => CycleHistoryDownHotkey = ""));
317317

318318
// Custom Query Hotkeys
319319
foreach (var customPluginHotkey in CustomPluginHotkeys)
@@ -334,34 +334,34 @@ private List<RegisteredHotkeyData> FixedHotkeys()
334334
new("Down", "HotkeyLeftRightDesc"),
335335
new("Left", "HotkeyUpDownDesc"),
336336
new("Right", "HotkeyUpDownDesc"),
337-
new("Escape", "HotkeyESCDesc"),
338-
new("F5", "ReloadPluginHotkey"),
339-
new("Alt+Home", "HotkeySelectFirstResult"),
340-
new("Alt+End", "HotkeySelectLastResult"),
341-
new("Ctrl+R", "HotkeyRequery"),
342-
new("Ctrl+H", "ToggleHistoryHotkey"),
343-
new("Ctrl+OemCloseBrackets", "QuickWidthHotkey"),
344-
new("Ctrl+OemOpenBrackets", "QuickWidthHotkey"),
345-
new("Ctrl+OemPlus", "QuickHeightHotkey"),
346-
new("Ctrl+OemMinus", "QuickHeightHotkey"),
347-
new("Ctrl+Shift+Enter", "HotkeyCtrlShiftEnterDesc"),
348-
new("Shift+Enter", "OpenContextMenuHotkey"),
349-
new("Enter", "HotkeyRunDesc"),
350-
new("Ctrl+Enter", "OpenContainFolderHotkey"),
351-
new("Alt+Enter", "HotkeyOpenResult"),
352-
new("Ctrl+F12", "ToggleGameModeHotkey"),
353-
new("Ctrl+Shift+C", "CopyFilePathHotkey"),
354-
355-
new($"{OpenResultModifiers}+D1", "HotkeyOpenResultN", 1),
356-
new($"{OpenResultModifiers}+D2", "HotkeyOpenResultN", 2),
357-
new($"{OpenResultModifiers}+D3", "HotkeyOpenResultN", 3),
358-
new($"{OpenResultModifiers}+D4", "HotkeyOpenResultN", 4),
359-
new($"{OpenResultModifiers}+D5", "HotkeyOpenResultN", 5),
360-
new($"{OpenResultModifiers}+D6", "HotkeyOpenResultN", 6),
361-
new($"{OpenResultModifiers}+D7", "HotkeyOpenResultN", 7),
362-
new($"{OpenResultModifiers}+D8", "HotkeyOpenResultN", 8),
363-
new($"{OpenResultModifiers}+D9", "HotkeyOpenResultN", 9),
364-
new($"{OpenResultModifiers}+D0", "HotkeyOpenResultN", 10)
337+
//new("Escape", "HotkeyESCDesc"),
338+
//new("F5", "ReloadPluginHotkey"),
339+
//new("Alt+Home", "HotkeySelectFirstResult"),
340+
//new("Alt+End", "HotkeySelectLastResult"),
341+
//new("Ctrl+R", "HotkeyRequery"),
342+
//new("Ctrl+H", "ToggleHistoryHotkey"),
343+
//new("Ctrl+OemCloseBrackets", "QuickWidthHotkey"),
344+
//new("Ctrl+OemOpenBrackets", "QuickWidthHotkey"),
345+
//new("Ctrl+OemPlus", "QuickHeightHotkey"),
346+
//new("Ctrl+OemMinus", "QuickHeightHotkey"),
347+
//new("Ctrl+Shift+Enter", "HotkeyCtrlShiftEnterDesc"),
348+
//new("Shift+Enter", "OpenContextMenuHotkey"),
349+
//new("Enter", "HotkeyRunDesc"),
350+
//new("Ctrl+Enter", "OpenContainFolderHotkey"),
351+
//new("Alt+Enter", "HotkeyOpenResult"),
352+
//new("Ctrl+F12", "ToggleGameModeHotkey"),
353+
//new("Ctrl+Shift+C", "CopyFilePathHotkey"),
354+
355+
//new($"{OpenResultModifiers}+D1", "HotkeyOpenResultN", 1),
356+
//new($"{OpenResultModifiers}+D2", "HotkeyOpenResultN", 2),
357+
//new($"{OpenResultModifiers}+D3", "HotkeyOpenResultN", 3),
358+
//new($"{OpenResultModifiers}+D4", "HotkeyOpenResultN", 4),
359+
//new($"{OpenResultModifiers}+D5", "HotkeyOpenResultN", 5),
360+
//new($"{OpenResultModifiers}+D6", "HotkeyOpenResultN", 6),
361+
//new($"{OpenResultModifiers}+D7", "HotkeyOpenResultN", 7),
362+
//new($"{OpenResultModifiers}+D8", "HotkeyOpenResultN", 8),
363+
//new($"{OpenResultModifiers}+D9", "HotkeyOpenResultN", 9),
364+
//new($"{OpenResultModifiers}+D0", "HotkeyOpenResultN", 10)
365365
};
366366
}
367367
}

Flow.Launcher/CustomQueryHotkeySetting.xaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@
107107
VerticalAlignment="Center"
108108
HorizontalContentAlignment="Left"
109109
HotkeySettings="{Binding Settings}"
110-
DefaultHotkey="" />
110+
DefaultHotkey=""
111+
IsWPFHotkeyControl="False" />
111112
<TextBlock
112113
Grid.Row="1"
113114
Grid.Column="0"

Flow.Launcher/CustomQueryHotkeySetting.xaml.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ private void btnAdd_OnClick(object sender, RoutedEventArgs e)
3737

3838
var pluginHotkey = new CustomPluginHotkey
3939
{
40-
Hotkey = HotkeyControl.CurrentHotkey.ToString(), ActionKeyword = tbAction.Text
40+
Hotkey = HotkeyControl.CurrentHotkey.HotkeyRaw, ActionKeyword = tbAction.Text
4141
};
4242
Settings.CustomPluginHotkeys.Add(pluginHotkey);
4343

@@ -47,9 +47,9 @@ private void btnAdd_OnClick(object sender, RoutedEventArgs e)
4747
{
4848
var oldHotkey = updateCustomHotkey.Hotkey;
4949
updateCustomHotkey.ActionKeyword = tbAction.Text;
50-
updateCustomHotkey.Hotkey = HotkeyControl.CurrentHotkey.ToString();
50+
updateCustomHotkey.Hotkey = HotkeyControl.CurrentHotkey.HotkeyRaw;
5151
//remove origin hotkey
52-
HotKeyMapper.RemoveHotkey(oldHotkey);
52+
HotKeyMapper.UnregisterHotkey(oldHotkey);
5353
HotKeyMapper.SetCustomQueryHotkey(updateCustomHotkey);
5454
}
5555

Flow.Launcher/Flow.Launcher.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
</ItemGroup>
8484

8585
<ItemGroup>
86+
<PackageReference Include="ChefKeys" Version="0.1.1" />
8687
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
8788
<PackageReference Include="Fody" Version="6.5.4">
8889
<PrivateAssets>all</PrivateAssets>
@@ -93,7 +94,6 @@
9394
<!-- ModernWpfUI v0.9.5 introduced WinRT changes that causes Notification platform unavailable error on some machines -->
9495
<!-- https://github.com/Flow-Launcher/Flow.Launcher/issues/1772#issuecomment-1502440801 -->
9596
<PackageReference Include="ModernWpfUI" Version="0.9.4" />
96-
<PackageReference Include="NHotkey.Wpf" Version="3.0.0" />
9797
<PackageReference Include="PropertyChanged.Fody" Version="3.4.0" />
9898
<PackageReference Include="SemanticVersioning" Version="3.0.0-beta2" />
9999
<PackageReference Include="VirtualizingWrapPanel" Version="2.1.0" />

0 commit comments

Comments
 (0)