Skip to content

Commit d2cc576

Browse files
authored
Merge pull request #1770 from VictoriousRaptor/FixPreviewHotkey
Validate hotkey when setting it
2 parents 9ee1eee + 3a8162b commit d2cc576

File tree

4 files changed

+105
-48
lines changed

4 files changed

+105
-48
lines changed

Flow.Launcher.Infrastructure/Hotkey/HotkeyModel.cs

Lines changed: 57 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Generic;
33
using System.Linq;
44
using System.Windows.Input;
5+
using System.Windows.Navigation;
56

67
namespace Flow.Launcher.Infrastructure.Hotkey
78
{
@@ -11,10 +12,10 @@ public class HotkeyModel
1112
public bool Shift { get; set; }
1213
public bool Win { get; set; }
1314
public bool Ctrl { get; set; }
14-
public Key CharKey { get; set; }
1515

16+
public Key CharKey { get; set; } = Key.None;
1617

17-
Dictionary<Key, string> specialSymbolDictionary = new Dictionary<Key, string>
18+
private static readonly Dictionary<Key, string> specialSymbolDictionary = new Dictionary<Key, string>
1819
{
1920
{Key.Space, "Space"},
2021
{Key.Oem3, "~"}
@@ -27,19 +28,19 @@ public ModifierKeys ModifierKeys
2728
ModifierKeys modifierKeys = ModifierKeys.None;
2829
if (Alt)
2930
{
30-
modifierKeys = ModifierKeys.Alt;
31+
modifierKeys |= ModifierKeys.Alt;
3132
}
3233
if (Shift)
3334
{
34-
modifierKeys = modifierKeys | ModifierKeys.Shift;
35+
modifierKeys |= ModifierKeys.Shift;
3536
}
3637
if (Win)
3738
{
38-
modifierKeys = modifierKeys | ModifierKeys.Windows;
39+
modifierKeys |= ModifierKeys.Windows;
3940
}
4041
if (Ctrl)
4142
{
42-
modifierKeys = modifierKeys | ModifierKeys.Control;
43+
modifierKeys |= ModifierKeys.Control;
4344
}
4445
return modifierKeys;
4546
}
@@ -86,7 +87,7 @@ private void Parse(string hotkeyString)
8687
Ctrl = true;
8788
keys.Remove("Ctrl");
8889
}
89-
if (keys.Count > 0)
90+
if (keys.Count == 1)
9091
{
9192
string charKey = keys[0];
9293
KeyValuePair<Key, string>? specialSymbolPair = specialSymbolDictionary.FirstOrDefault(pair => pair.Value == charKey);
@@ -110,36 +111,75 @@ private void Parse(string hotkeyString)
110111

111112
public override string ToString()
112113
{
113-
string text = string.Empty;
114+
List<string> keys = new List<string>();
114115
if (Ctrl)
115116
{
116-
text += "Ctrl + ";
117+
keys.Add("Ctrl");
117118
}
118119
if (Alt)
119120
{
120-
text += "Alt + ";
121+
keys.Add("Alt");
121122
}
122123
if (Shift)
123124
{
124-
text += "Shift + ";
125+
keys.Add("Shift");
125126
}
126127
if (Win)
127128
{
128-
text += "Win + ";
129+
keys.Add("Win");
129130
}
130131

131132
if (CharKey != Key.None)
132133
{
133-
text += specialSymbolDictionary.ContainsKey(CharKey)
134+
keys.Add(specialSymbolDictionary.ContainsKey(CharKey)
134135
? specialSymbolDictionary[CharKey]
135-
: CharKey.ToString();
136+
: CharKey.ToString());
136137
}
137-
else if (!string.IsNullOrEmpty(text))
138+
return string.Join(" + ", keys);
139+
}
140+
141+
public bool Validate()
142+
{
143+
switch (CharKey)
144+
{
145+
case Key.LeftAlt:
146+
case Key.RightAlt:
147+
case Key.LeftCtrl:
148+
case Key.RightCtrl:
149+
case Key.LeftShift:
150+
case Key.RightShift:
151+
case Key.LWin:
152+
case Key.RWin:
153+
return false;
154+
default:
155+
if (ModifierKeys == ModifierKeys.None)
156+
{
157+
return !((CharKey >= Key.A && CharKey <= Key.Z) ||
158+
(CharKey >= Key.D0 && CharKey <= Key.D9) ||
159+
(CharKey >= Key.NumPad0 && CharKey <= Key.NumPad9));
160+
}
161+
else
162+
{
163+
return CharKey != Key.None;
164+
}
165+
}
166+
}
167+
168+
public override bool Equals(object obj)
169+
{
170+
if (obj is HotkeyModel other)
138171
{
139-
text = text.Remove(text.Length - 3);
172+
return ModifierKeys == other.ModifierKeys && CharKey == other.CharKey;
140173
}
174+
else
175+
{
176+
return false;
177+
}
178+
}
141179

142-
return text;
180+
public override int GetHashCode()
181+
{
182+
return HashCode.Combine(ModifierKeys, CharKey);
143183
}
144184
}
145185
}

Flow.Launcher/HotkeyControl.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
Margin="0,0,18,0"
4949
VerticalContentAlignment="Center"
5050
input:InputMethod.IsInputMethodEnabled="False"
51+
GotFocus="tbHotkey_GotFocus"
5152
LostFocus="tbHotkey_LostFocus"
5253
PreviewKeyDown="TbHotkey_OnPreviewKeyDown"
5354
TabIndex="100" />

Flow.Launcher/HotkeyControl.xaml.cs

Lines changed: 45 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,11 @@
99
using Flow.Launcher.Infrastructure.Hotkey;
1010
using Flow.Launcher.Plugin;
1111
using System.Threading;
12-
using System.Windows.Interop;
1312

1413
namespace Flow.Launcher
1514
{
1615
public partial class HotkeyControl : UserControl
1716
{
18-
private Brush tbMsgForegroundColorOriginal;
19-
20-
private string tbMsgTextOriginal;
21-
2217
public HotkeyModel CurrentHotkey { get; private set; }
2318
public bool CurrentHotkeyAvailable { get; private set; }
2419

@@ -29,8 +24,6 @@ public partial class HotkeyControl : UserControl
2924
public HotkeyControl()
3025
{
3126
InitializeComponent();
32-
tbMsgTextOriginal = tbMsg.Text;
33-
tbMsgForegroundColorOriginal = tbMsg.Foreground;
3427
}
3528

3629
private CancellationTokenSource hotkeyUpdateSource;
@@ -55,9 +48,7 @@ private void TbHotkey_OnPreviewKeyDown(object sender, KeyEventArgs e)
5548
specialKeyState.CtrlPressed,
5649
key);
5750

58-
var hotkeyString = hotkeyModel.ToString();
59-
60-
if (hotkeyString == tbHotkey.Text)
51+
if (hotkeyModel.Equals(CurrentHotkey))
6152
{
6253
return;
6354
}
@@ -72,33 +63,32 @@ private void TbHotkey_OnPreviewKeyDown(object sender, KeyEventArgs e)
7263

7364
public async Task SetHotkeyAsync(HotkeyModel keyModel, bool triggerValidate = true)
7465
{
75-
CurrentHotkey = keyModel;
76-
77-
tbHotkey.Text = CurrentHotkey.ToString();
66+
tbHotkey.Text = keyModel.ToString();
7867
tbHotkey.Select(tbHotkey.Text.Length, 0);
7968

8069
if (triggerValidate)
8170
{
82-
CurrentHotkeyAvailable = CheckHotkeyAvailability();
83-
if (!CurrentHotkeyAvailable)
84-
{
85-
tbMsg.Foreground = new SolidColorBrush(Colors.Red);
86-
tbMsg.Text = InternationalizationManager.Instance.GetTranslation("hotkeyUnavailable");
87-
}
88-
else
89-
{
90-
tbMsg.Foreground = new SolidColorBrush(Colors.Green);
91-
tbMsg.Text = InternationalizationManager.Instance.GetTranslation("success");
92-
}
93-
tbMsg.Visibility = Visibility.Visible;
71+
bool hotkeyAvailable = CheckHotkeyAvailability(keyModel);
72+
CurrentHotkeyAvailable = hotkeyAvailable;
73+
SetMessage(hotkeyAvailable);
9474
OnHotkeyChanged();
9575

9676
var token = hotkeyUpdateSource.Token;
9777
await Task.Delay(500, token);
9878
if (token.IsCancellationRequested)
9979
return;
100-
FocusManager.SetFocusedElement(FocusManager.GetFocusScope(this), null);
101-
Keyboard.ClearFocus();
80+
81+
if (CurrentHotkeyAvailable)
82+
{
83+
CurrentHotkey = keyModel;
84+
// To trigger LostFocus
85+
FocusManager.SetFocusedElement(FocusManager.GetFocusScope(this), null);
86+
Keyboard.ClearFocus();
87+
}
88+
}
89+
else
90+
{
91+
CurrentHotkey = keyModel;
10292
}
10393
}
10494

@@ -107,14 +97,40 @@ public Task SetHotkeyAsync(string keyStr, bool triggerValidate = true)
10797
return SetHotkeyAsync(new HotkeyModel(keyStr), triggerValidate);
10898
}
10999

110-
private bool CheckHotkeyAvailability() => HotKeyMapper.CheckAvailability(CurrentHotkey);
100+
private static bool CheckHotkeyAvailability(HotkeyModel hotkey) => hotkey.Validate() && HotKeyMapper.CheckAvailability(hotkey);
111101

112102
public new bool IsFocused => tbHotkey.IsFocused;
113103

114104
private void tbHotkey_LostFocus(object sender, RoutedEventArgs e)
115105
{
116-
tbMsg.Text = tbMsgTextOriginal;
106+
tbHotkey.Text = CurrentHotkey.ToString();
107+
tbHotkey.Select(tbHotkey.Text.Length, 0);
108+
}
109+
110+
private void tbHotkey_GotFocus(object sender, RoutedEventArgs e)
111+
{
112+
ResetMessage();
113+
}
114+
115+
private void ResetMessage()
116+
{
117+
tbMsg.Text = InternationalizationManager.Instance.GetTranslation("flowlauncherPressHotkey");
117118
tbMsg.SetResourceReference(TextBox.ForegroundProperty, "Color05B");
118119
}
120+
121+
private void SetMessage(bool hotkeyAvailable)
122+
{
123+
if (!hotkeyAvailable)
124+
{
125+
tbMsg.Foreground = new SolidColorBrush(Colors.Red);
126+
tbMsg.Text = InternationalizationManager.Instance.GetTranslation("hotkeyUnavailable");
127+
}
128+
else
129+
{
130+
tbMsg.Foreground = new SolidColorBrush(Colors.Green);
131+
tbMsg.Text = InternationalizationManager.Instance.GetTranslation("success");
132+
}
133+
tbMsg.Visibility = Visibility.Visible;
134+
}
119135
}
120136
}

Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ protected override void OnNavigatedTo(NavigationEventArgs e)
2727
tbMsgTextOriginal = HotkeyControl.tbMsg.Text;
2828
tbMsgForegroundColorOriginal = HotkeyControl.tbMsg.Foreground;
2929

30-
HotkeyControl.SetHotkeyAsync(new Infrastructure.Hotkey.HotkeyModel(Settings.Hotkey), false);
30+
HotkeyControl.SetHotkeyAsync(Settings.Hotkey, false);
3131
}
3232
private void HotkeyControl_OnGotFocus(object sender, RoutedEventArgs args)
3333
{
@@ -49,4 +49,4 @@ private void HotkeyControl_OnLostFocus(object sender, RoutedEventArgs args)
4949
HotkeyControl.tbMsg.Foreground = tbMsgForegroundColorOriginal;
5050
}
5151
}
52-
}
52+
}

0 commit comments

Comments
 (0)