Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support the use of Windows key & four-combination hotkey #3157

Draft
wants to merge 8 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 94 additions & 20 deletions Flow.Launcher.Infrastructure/Hotkey/HotkeyModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.ComponentModel;
using System.Linq;
using System.Windows.Input;
using Flow.Launcher.Plugin;

namespace Flow.Launcher.Infrastructure.Hotkey
{
Expand All @@ -13,6 +14,9 @@ public record struct HotkeyModel
public bool Win { get; set; }
public bool Ctrl { get; set; }

public string HotkeyRaw { get; set; } = string.Empty;
public string PreviousHotkey { get; set; } = string.Empty;

public Key CharKey { get; set; } = Key.None;

private static readonly Dictionary<Key, string> specialSymbolDictionary = new Dictionary<Key, string>
Expand Down Expand Up @@ -49,18 +53,56 @@ public ModifierKeys ModifierKeys
}
}

public HotkeyModel(string hotkeyString)
// Used for WPF control only
public void SetHotkeyFromString(string hotkeyString)
{
Clear();
Parse(hotkeyString);
HotkeyRaw = ToChefKeysString();
}

public HotkeyModel(bool alt, bool shift, bool win, bool ctrl, Key key)
internal void SetHotkeyFromWPFControl(SpecialKeyState specialKeyState, Key key)
{
Alt = alt;
Shift = shift;
Win = win;
Ctrl = ctrl;
Alt = specialKeyState.AltPressed;
Shift = specialKeyState.ShiftPressed;
Win = specialKeyState.WinPressed;
Ctrl = specialKeyState.CtrlPressed;
CharKey = key;
HotkeyRaw = ToChefKeysString();
PreviousHotkey = string.Empty;
}

public HotkeyModel(string hotkey)
{
SetHotkeyFromString(hotkey);
}

//public HotkeyModel(bool alt, bool shift, bool win, bool ctrl, Key key)
//{
// Alt = alt;
// Shift = shift;
// Win = win;
// Ctrl = ctrl;
// CharKey = key;
//}

// Use for ChefKeys only
internal void AddString(string key)
{
HotkeyRaw = string.IsNullOrEmpty(HotkeyRaw) ? key : HotkeyRaw + "+" + key;
}

internal bool MaxKeysReached() => DisplayKeysRaw().Count() == 4;

internal void Clear()
{
Alt = false;
Shift = false;
Win = false;
Ctrl = false;
HotkeyRaw = string.Empty;
PreviousHotkey = string.Empty;
CharKey = Key.None;
}

private void Parse(string hotkeyString)
Expand All @@ -71,28 +113,36 @@ private void Parse(string hotkeyString)
}

List<string> keys = hotkeyString.Replace(" ", "").Split('+').ToList();
if (keys.Contains("Alt"))
if (keys.Contains("Alt") || keys.Contains("LeftAlt") || keys.Contains("RightAlt"))
{
Alt = true;
keys.Remove("Alt");
keys.Remove("LeftAlt");
keys.Remove("RightAlt");
}

if (keys.Contains("Shift"))
if (keys.Contains("Shift") || keys.Contains("LeftShift") || keys.Contains("RightShift"))
{
Shift = true;
keys.Remove("Shift");
keys.Remove("LeftShift");
keys.Remove("RightShift");
}

if (keys.Contains("Win"))
if (keys.Contains("Win") || keys.Contains("LWin") || keys.Contains("RWin"))
{
Win = true;
keys.Remove("Win");
keys.Remove("LWin");
keys.Remove("RWin");
}

if (keys.Contains("Ctrl"))
if (keys.Contains("Ctrl") || keys.Contains("LeftCtrl")|| keys.Contains("RightCtrl"))
{
Ctrl = true;
keys.Remove("Ctrl");
keys.Remove("LeftCtrl");
keys.Remove("RightCtrl");
}

if (keys.Count == 1)
Expand All @@ -117,47 +167,71 @@ private void Parse(string hotkeyString)
}
}

public override string ToString()
public string ToChefKeysString()
{
return string.Join(" + ", EnumerateDisplayKeys());
var key = string.Join("+", EnumerateDisplayKeys(true));

return key;
}

public IEnumerable<string> EnumerateDisplayKeys()
public IEnumerable<string> DisplayKeysRaw() => !string.IsNullOrEmpty(HotkeyRaw) ? HotkeyRaw.Split('+') : Array.Empty<string>();

public IEnumerable<string> EnumerateDisplayKeys(bool forChefKeys = false)
{
if (Ctrl && CharKey is not (Key.LeftCtrl or Key.RightCtrl))
{
yield return "Ctrl";
yield return GetKeyString("Ctrl", forChefKeys);
}

if (Alt && CharKey is not (Key.LeftAlt or Key.RightAlt))
{
yield return "Alt";
yield return GetKeyString("Alt", forChefKeys);
}

if (Shift && CharKey is not (Key.LeftShift or Key.RightShift))
{
yield return "Shift";
yield return GetKeyString("Shift", forChefKeys);
}

if (Win && CharKey is not (Key.LWin or Key.RWin))
{
yield return "Win";
yield return GetKeyString("Win", forChefKeys);
}

if (CharKey != Key.None)
{
yield return specialSymbolDictionary.TryGetValue(CharKey, out var value)
? value
: CharKey.ToString();
: GetKeyString(CharKey.ToString(), forChefKeys);
}
}

private string GetKeyString(string key, bool convertToChefKeysString)
{
if (!convertToChefKeysString)
return key;

switch (key)
{
case "Alt":
return "LeftAlt";
case "Ctrl":
return "LeftCtrl";
case "Shift":
return "LeftShift";
case "Win":
return "LWin";
default:
return key;
}
}

/// <summary>
/// Validate hotkey
/// Validate hotkey for WPF control only
/// </summary>
/// <param name="validateKeyGestrue">Try to validate hotkey as a KeyGesture.</param>
/// <returns></returns>
public bool Validate(bool validateKeyGestrue = false)
public bool ValidateForWpf(bool validateKeyGestrue = false)
{
switch (CharKey)
{
Expand Down
5 changes: 3 additions & 2 deletions Flow.Launcher.Infrastructure/KeyConstant.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
{
public static class KeyConstant
{
public const string Ctrl = nameof(Ctrl);
public const string Alt = nameof(Alt);
public const string LeftAlt = nameof(LeftAlt);
public const string Ctrl = nameof(Ctrl);
public const string Space = nameof(Space);
}
}
}
96 changes: 48 additions & 48 deletions Flow.Launcher.Infrastructure/UserSettings/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class Settings : BaseModel, IHotkeySettings
{
private string language = "en";
private string _theme = Constant.DefaultTheme;
public string Hotkey { get; set; } = $"{KeyConstant.Alt} + {KeyConstant.Space}";
public string Hotkey { get; set; } = $"{KeyConstant.LeftAlt} + {KeyConstant.Space}";
public string OpenResultModifiers { get; set; } = KeyConstant.Alt;
public string ColorScheme { get; set; } = "System";
public bool ShowOpenResultHotkey { get; set; } = true;
Expand Down Expand Up @@ -288,32 +288,32 @@ public List<RegisteredHotkeyData> RegisteredHotkeys
// Customizeable hotkeys
if(!string.IsNullOrEmpty(Hotkey))
list.Add(new(Hotkey, "flowlauncherHotkey", () => Hotkey = ""));
if(!string.IsNullOrEmpty(PreviewHotkey))
if (!string.IsNullOrEmpty(PreviewHotkey))
list.Add(new(PreviewHotkey, "previewHotkey", () => PreviewHotkey = ""));
if(!string.IsNullOrEmpty(AutoCompleteHotkey))
if (!string.IsNullOrEmpty(AutoCompleteHotkey))
list.Add(new(AutoCompleteHotkey, "autoCompleteHotkey", () => AutoCompleteHotkey = ""));
if(!string.IsNullOrEmpty(AutoCompleteHotkey2))
if (!string.IsNullOrEmpty(AutoCompleteHotkey2))
list.Add(new(AutoCompleteHotkey2, "autoCompleteHotkey", () => AutoCompleteHotkey2 = ""));
if(!string.IsNullOrEmpty(SelectNextItemHotkey))
if (!string.IsNullOrEmpty(SelectNextItemHotkey))
list.Add(new(SelectNextItemHotkey, "SelectNextItemHotkey", () => SelectNextItemHotkey = ""));
if(!string.IsNullOrEmpty(SelectNextItemHotkey2))
if (!string.IsNullOrEmpty(SelectNextItemHotkey2))
list.Add(new(SelectNextItemHotkey2, "SelectNextItemHotkey", () => SelectNextItemHotkey2 = ""));
if(!string.IsNullOrEmpty(SelectPrevItemHotkey))
if (!string.IsNullOrEmpty(SelectPrevItemHotkey))
list.Add(new(SelectPrevItemHotkey, "SelectPrevItemHotkey", () => SelectPrevItemHotkey = ""));
if(!string.IsNullOrEmpty(SelectPrevItemHotkey2))
if (!string.IsNullOrEmpty(SelectPrevItemHotkey2))
list.Add(new(SelectPrevItemHotkey2, "SelectPrevItemHotkey", () => SelectPrevItemHotkey2 = ""));
if(!string.IsNullOrEmpty(SettingWindowHotkey))
list.Add(new(SettingWindowHotkey, "SettingWindowHotkey", () => SettingWindowHotkey = ""));
if(!string.IsNullOrEmpty(OpenContextMenuHotkey))
list.Add(new(OpenContextMenuHotkey, "OpenContextMenuHotkey", () => OpenContextMenuHotkey = ""));
if(!string.IsNullOrEmpty(SelectNextPageHotkey))
list.Add(new(SelectNextPageHotkey, "SelectNextPageHotkey", () => SelectNextPageHotkey = ""));
if(!string.IsNullOrEmpty(SelectPrevPageHotkey))
list.Add(new(SelectPrevPageHotkey, "SelectPrevPageHotkey", () => SelectPrevPageHotkey = ""));
if (!string.IsNullOrEmpty(CycleHistoryUpHotkey))
list.Add(new(CycleHistoryUpHotkey, "CycleHistoryUpHotkey", () => CycleHistoryUpHotkey = ""));
if (!string.IsNullOrEmpty(CycleHistoryDownHotkey))
list.Add(new(CycleHistoryDownHotkey, "CycleHistoryDownHotkey", () => CycleHistoryDownHotkey = ""));
//if (!string.IsNullOrEmpty(SettingWindowHotkey))
// list.Add(new(SettingWindowHotkey, "SettingWindowHotkey", () => SettingWindowHotkey = ""));
//if (!string.IsNullOrEmpty(OpenContextMenuHotkey))
// list.Add(new(OpenContextMenuHotkey, "OpenContextMenuHotkey", () => OpenContextMenuHotkey = ""));
//if (!string.IsNullOrEmpty(SelectNextPageHotkey))
// list.Add(new(SelectNextPageHotkey, "SelectNextPageHotkey", () => SelectNextPageHotkey = ""));
//if (!string.IsNullOrEmpty(SelectPrevPageHotkey))
// list.Add(new(SelectPrevPageHotkey, "SelectPrevPageHotkey", () => SelectPrevPageHotkey = ""));
//if (!string.IsNullOrEmpty(CycleHistoryUpHotkey))
// list.Add(new(CycleHistoryUpHotkey, "CycleHistoryUpHotkey", () => CycleHistoryUpHotkey = ""));
//if (!string.IsNullOrEmpty(CycleHistoryDownHotkey))
// list.Add(new(CycleHistoryDownHotkey, "CycleHistoryDownHotkey", () => CycleHistoryDownHotkey = ""));

// Custom Query Hotkeys
foreach (var customPluginHotkey in CustomPluginHotkeys)
Expand All @@ -334,34 +334,34 @@ private List<RegisteredHotkeyData> FixedHotkeys()
new("Down", "HotkeyLeftRightDesc"),
new("Left", "HotkeyUpDownDesc"),
new("Right", "HotkeyUpDownDesc"),
new("Escape", "HotkeyESCDesc"),
new("F5", "ReloadPluginHotkey"),
new("Alt+Home", "HotkeySelectFirstResult"),
new("Alt+End", "HotkeySelectLastResult"),
new("Ctrl+R", "HotkeyRequery"),
new("Ctrl+H", "ToggleHistoryHotkey"),
new("Ctrl+OemCloseBrackets", "QuickWidthHotkey"),
new("Ctrl+OemOpenBrackets", "QuickWidthHotkey"),
new("Ctrl+OemPlus", "QuickHeightHotkey"),
new("Ctrl+OemMinus", "QuickHeightHotkey"),
new("Ctrl+Shift+Enter", "HotkeyCtrlShiftEnterDesc"),
new("Shift+Enter", "OpenContextMenuHotkey"),
new("Enter", "HotkeyRunDesc"),
new("Ctrl+Enter", "OpenContainFolderHotkey"),
new("Alt+Enter", "HotkeyOpenResult"),
new("Ctrl+F12", "ToggleGameModeHotkey"),
new("Ctrl+Shift+C", "CopyFilePathHotkey"),

new($"{OpenResultModifiers}+D1", "HotkeyOpenResultN", 1),
new($"{OpenResultModifiers}+D2", "HotkeyOpenResultN", 2),
new($"{OpenResultModifiers}+D3", "HotkeyOpenResultN", 3),
new($"{OpenResultModifiers}+D4", "HotkeyOpenResultN", 4),
new($"{OpenResultModifiers}+D5", "HotkeyOpenResultN", 5),
new($"{OpenResultModifiers}+D6", "HotkeyOpenResultN", 6),
new($"{OpenResultModifiers}+D7", "HotkeyOpenResultN", 7),
new($"{OpenResultModifiers}+D8", "HotkeyOpenResultN", 8),
new($"{OpenResultModifiers}+D9", "HotkeyOpenResultN", 9),
new($"{OpenResultModifiers}+D0", "HotkeyOpenResultN", 10)
//new("Escape", "HotkeyESCDesc"),
//new("F5", "ReloadPluginHotkey"),
//new("Alt+Home", "HotkeySelectFirstResult"),
//new("Alt+End", "HotkeySelectLastResult"),
//new("Ctrl+R", "HotkeyRequery"),
//new("Ctrl+H", "ToggleHistoryHotkey"),
//new("Ctrl+OemCloseBrackets", "QuickWidthHotkey"),
//new("Ctrl+OemOpenBrackets", "QuickWidthHotkey"),
//new("Ctrl+OemPlus", "QuickHeightHotkey"),
//new("Ctrl+OemMinus", "QuickHeightHotkey"),
//new("Ctrl+Shift+Enter", "HotkeyCtrlShiftEnterDesc"),
//new("Shift+Enter", "OpenContextMenuHotkey"),
//new("Enter", "HotkeyRunDesc"),
//new("Ctrl+Enter", "OpenContainFolderHotkey"),
//new("Alt+Enter", "HotkeyOpenResult"),
//new("Ctrl+F12", "ToggleGameModeHotkey"),
//new("Ctrl+Shift+C", "CopyFilePathHotkey"),

//new($"{OpenResultModifiers}+D1", "HotkeyOpenResultN", 1),
//new($"{OpenResultModifiers}+D2", "HotkeyOpenResultN", 2),
//new($"{OpenResultModifiers}+D3", "HotkeyOpenResultN", 3),
//new($"{OpenResultModifiers}+D4", "HotkeyOpenResultN", 4),
//new($"{OpenResultModifiers}+D5", "HotkeyOpenResultN", 5),
//new($"{OpenResultModifiers}+D6", "HotkeyOpenResultN", 6),
//new($"{OpenResultModifiers}+D7", "HotkeyOpenResultN", 7),
//new($"{OpenResultModifiers}+D8", "HotkeyOpenResultN", 8),
//new($"{OpenResultModifiers}+D9", "HotkeyOpenResultN", 9),
//new($"{OpenResultModifiers}+D0", "HotkeyOpenResultN", 10)
};
}
}
Expand Down
3 changes: 2 additions & 1 deletion Flow.Launcher/CustomQueryHotkeySetting.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@
VerticalAlignment="Center"
HorizontalContentAlignment="Left"
HotkeySettings="{Binding Settings}"
DefaultHotkey="" />
DefaultHotkey=""
IsWPFHotkeyControl="False" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
Expand Down
6 changes: 3 additions & 3 deletions Flow.Launcher/CustomQueryHotkeySetting.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ private void btnAdd_OnClick(object sender, RoutedEventArgs e)

var pluginHotkey = new CustomPluginHotkey
{
Hotkey = HotkeyControl.CurrentHotkey.ToString(), ActionKeyword = tbAction.Text
Hotkey = HotkeyControl.CurrentHotkey.HotkeyRaw, ActionKeyword = tbAction.Text
};
Settings.CustomPluginHotkeys.Add(pluginHotkey);

Expand All @@ -47,9 +47,9 @@ private void btnAdd_OnClick(object sender, RoutedEventArgs e)
{
var oldHotkey = updateCustomHotkey.Hotkey;
updateCustomHotkey.ActionKeyword = tbAction.Text;
updateCustomHotkey.Hotkey = HotkeyControl.CurrentHotkey.ToString();
updateCustomHotkey.Hotkey = HotkeyControl.CurrentHotkey.HotkeyRaw;
//remove origin hotkey
HotKeyMapper.RemoveHotkey(oldHotkey);
HotKeyMapper.UnregisterHotkey(oldHotkey);
HotKeyMapper.SetCustomQueryHotkey(updateCustomHotkey);
}

Expand Down
2 changes: 1 addition & 1 deletion Flow.Launcher/Flow.Launcher.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="ChefKeys" Version="0.1.1" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="Fody" Version="6.5.4">
<PrivateAssets>all</PrivateAssets>
Expand All @@ -97,7 +98,6 @@
<!-- ModernWpfUI v0.9.5 introduced WinRT changes that causes Notification platform unavailable error on some machines -->
<!-- https://github.com/Flow-Launcher/Flow.Launcher/issues/1772#issuecomment-1502440801 -->
<PackageReference Include="ModernWpfUI" Version="0.9.4" />
<PackageReference Include="NHotkey.Wpf" Version="3.0.0" />
<PackageReference Include="PropertyChanged.Fody" Version="3.4.0" />
<PackageReference Include="SemanticVersioning" Version="3.0.0-beta2" />
<PackageReference Include="VirtualizingWrapPanel" Version="2.1.0" />
Expand Down
Loading
Loading