diff --git a/src/Ursa.Themes.Semi/Controls/KeyGestureInput.axaml b/src/Ursa.Themes.Semi/Controls/KeyGestureInput.axaml
new file mode 100644
index 0000000..7a72b5d
--- /dev/null
+++ b/src/Ursa.Themes.Semi/Controls/KeyGestureInput.axaml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Ursa.Themes.Semi/Controls/_index.axaml b/src/Ursa.Themes.Semi/Controls/_index.axaml
index bbf2752..7444554 100644
--- a/src/Ursa.Themes.Semi/Controls/_index.axaml
+++ b/src/Ursa.Themes.Semi/Controls/_index.axaml
@@ -6,6 +6,7 @@
+
diff --git a/src/Ursa.Themes.Semi/Ursa.Themes.Semi.csproj b/src/Ursa.Themes.Semi/Ursa.Themes.Semi.csproj
index 5bb0d73..88fc18f 100644
--- a/src/Ursa.Themes.Semi/Ursa.Themes.Semi.csproj
+++ b/src/Ursa.Themes.Semi/Ursa.Themes.Semi.csproj
@@ -1,6 +1,6 @@
-
+
netstandard2.0
@@ -13,11 +13,11 @@
-
+
-
+
diff --git a/src/Ursa/Controls/KeyGestureInput.cs b/src/Ursa/Controls/KeyGestureInput.cs
new file mode 100644
index 0000000..af43eb3
--- /dev/null
+++ b/src/Ursa/Controls/KeyGestureInput.cs
@@ -0,0 +1,83 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Controls.Converters;
+using Avalonia.Controls.Primitives;
+using Avalonia.Input;
+
+namespace Ursa.Controls;
+
+public class KeyGestureInput: TemplatedControl
+{
+ static KeyGestureInput()
+ {
+ InputElement.FocusableProperty.OverrideDefaultValue(true);
+ }
+
+ public static readonly StyledProperty GestureProperty = AvaloniaProperty.Register(
+ nameof(Gesture));
+
+ public KeyGesture Gesture
+ {
+ get => GetValue(GestureProperty);
+ set => SetValue(GestureProperty, value);
+ }
+
+ public static readonly StyledProperty> AcceptableKeysProperty = AvaloniaProperty.Register>(
+ nameof(AcceptableKeys));
+
+ public IList AcceptableKeys
+ {
+ get => GetValue(AcceptableKeysProperty);
+ set => SetValue(AcceptableKeysProperty, value);
+ }
+
+ public static readonly StyledProperty ConsiderKeyModifiersProperty = AvaloniaProperty.Register(
+ nameof(ConsiderKeyModifiers));
+
+ public bool ConsiderKeyModifiers
+ {
+ get => GetValue(ConsiderKeyModifiersProperty);
+ set => SetValue(ConsiderKeyModifiersProperty, value);
+ }
+
+ protected override void OnKeyDown(KeyEventArgs e)
+ {
+ // base.OnKeyDown(e);
+ if (!AcceptableKeys.Contains(e.Key))
+ {
+ return;
+ }
+
+ if (!ConsiderKeyModifiers)
+ {
+ if(e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl || e.Key == Key.LeftAlt || e.Key == Key.RightAlt || e.Key == Key.LeftShift || e.Key == Key.RightShift || e.Key == Key.LWin || e.Key == Key.RWin)
+ {
+ return;
+ }
+ Gesture = new KeyGesture(e.Key);
+ }
+ KeyGesture gesture;
+ if (e.KeyModifiers == KeyModifiers.Control && (e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl))
+ {
+ gesture = new KeyGesture(e.Key);
+ }
+ else if (e.KeyModifiers == KeyModifiers.Alt && (e.Key == Key.LeftAlt || e.Key == Key.RightAlt))
+ {
+ gesture = new KeyGesture(e.Key);
+ }
+ else if (e.KeyModifiers == KeyModifiers.Shift && (e.Key == Key.LeftShift || e.Key == Key.RightShift))
+ {
+ gesture = new KeyGesture(e.Key);
+ }
+ else if (e.KeyModifiers == KeyModifiers.Meta && (e.Key == Key.LWin || e.Key == Key.RWin))
+ {
+ gesture = new KeyGesture(e.Key);
+ }
+ else
+ {
+ gesture = new KeyGesture(e.Key, e.KeyModifiers);
+ }
+ Gesture = gesture;
+ e.Handled = true;
+ }
+}
\ No newline at end of file
diff --git a/src/Ursa/Ursa.csproj b/src/Ursa/Ursa.csproj
index 01a32db..a6c5201 100644
--- a/src/Ursa/Ursa.csproj
+++ b/src/Ursa/Ursa.csproj
@@ -1,6 +1,6 @@
-
+
netstandard2.0
@@ -13,7 +13,7 @@
-
+