diff --git a/src/Avalonia.Controls/ContextRequestedEventArgs.cs b/src/Avalonia.Controls/ContextRequestedEventArgs.cs
new file mode 100644
index 0000000000..8dc798245c
--- /dev/null
+++ b/src/Avalonia.Controls/ContextRequestedEventArgs.cs
@@ -0,0 +1,58 @@
+using Avalonia.Input;
+using Avalonia.Interactivity;
+
+#nullable enable
+
+namespace Avalonia.Controls
+{
+ ///
+ /// Provides event data for the ContextRequested event.
+ ///
+ public class ContextRequestedEventArgs : RoutedEventArgs
+ {
+ private readonly PointerEventArgs? _pointerEventArgs;
+
+ ///
+ /// Initializes a new instance of the ContextRequestedEventArgs class.
+ ///
+ public ContextRequestedEventArgs()
+ : base(Control.ContextRequestedEvent)
+ {
+
+ }
+
+ ///
+ public ContextRequestedEventArgs(PointerEventArgs pointerEventArgs)
+ : this()
+ {
+ _pointerEventArgs = pointerEventArgs;
+ }
+
+ ///
+ /// Gets the x- and y-coordinates of the pointer position, optionally evaluated against a coordinate origin of a supplied .
+ ///
+ ///
+ /// Any -derived object that is connected to the same object tree.
+ /// To specify the object relative to the overall coordinate system, use a relativeTo value of null.
+ ///
+ ///
+ /// A that represents the current x- and y-coordinates of the mouse pointer position.
+ /// If null was passed as relativeTo, this coordinate is for the overall window.
+ /// If a relativeTo value other than null was passed, this coordinate is relative to the object referenced by relativeTo.
+ ///
+ ///
+ /// true if the context request was initiated by a pointer device; otherwise, false.
+ ///
+ public bool TryGetPosition(Control? relativeTo, out Point point)
+ {
+ if (_pointerEventArgs is null)
+ {
+ point = default;
+ return false;
+ }
+
+ point = _pointerEventArgs.GetPosition(relativeTo);
+ return true;
+ }
+ }
+}
diff --git a/src/Avalonia.Controls/Control.cs b/src/Avalonia.Controls/Control.cs
index a7ec7cc5d2..845efd3279 100644
--- a/src/Avalonia.Controls/Control.cs
+++ b/src/Avalonia.Controls/Control.cs
@@ -3,6 +3,7 @@ using System.ComponentModel;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Input;
+using Avalonia.Input.Platform;
using Avalonia.Interactivity;
using Avalonia.Rendering;
using Avalonia.Styling;
@@ -19,6 +20,7 @@ namespace Avalonia.Controls
/// The control class extends and adds the following features:
///
/// - A property to allow user-defined data to be attached to the control.
+ /// - and other context menu related members.
///
public class Control : InputElement, IControl, INamed, IVisualBrushInitialize, ISetterValue
{
@@ -52,6 +54,13 @@ namespace Avalonia.Controls
public static readonly RoutedEvent RequestBringIntoViewEvent =
RoutedEvent.Register("RequestBringIntoView", RoutingStrategies.Bubble);
+ ///
+ /// Provides event data for the event.
+ ///
+ public static readonly RoutedEvent ContextRequestedEvent =
+ RoutedEvent.Register(nameof(ContextRequested),
+ RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
+
private DataTemplates? _dataTemplates;
private IControl? _focusAdorner;
@@ -100,6 +109,15 @@ namespace Avalonia.Controls
set => SetValue(TagProperty, value);
}
+ ///
+ /// Occurs when the user has completed a context input gesture, such as a right-click.
+ ///
+ public event EventHandler ContextRequested
+ {
+ add => AddHandler(ContextRequestedEvent, value);
+ remove => RemoveHandler(ContextRequestedEvent, value);
+ }
+
public new IControl? Parent => (IControl?)base.Parent;
///
@@ -208,5 +226,47 @@ namespace Avalonia.Controls
_focusAdorner = null;
}
}
+
+ protected override void OnPointerReleased(PointerReleasedEventArgs e)
+ {
+ base.OnPointerReleased(e);
+
+ if (!e.Handled
+ && e.InitialPressMouseButton == MouseButton.Right)
+ {
+ var args = new ContextRequestedEventArgs(e);
+ RaiseEvent(args);
+ e.Handled = args.Handled;
+ }
+ }
+
+ protected override void OnKeyUp(KeyEventArgs e)
+ {
+ base.OnKeyUp(e);
+
+ if (!e.Handled)
+ {
+ var keymap = AvaloniaLocator.Current.GetService().OpenContextMenu;
+ var matches = false;
+
+ for (var index = 0; index < keymap.Count; index++)
+ {
+ var key = keymap[index];
+ matches |= key.Matches(e);
+
+ if (matches)
+ {
+ break;
+ }
+ }
+
+ if (matches)
+ {
+ var args = new ContextRequestedEventArgs();
+ RaiseEvent(args);
+ e.Handled = args.Handled;
+ }
+ }
+ }
}
}
diff --git a/src/Avalonia.Input/Platform/PlatformHotkeyConfiguration.cs b/src/Avalonia.Input/Platform/PlatformHotkeyConfiguration.cs
index 053f894755..42ce113345 100644
--- a/src/Avalonia.Input/Platform/PlatformHotkeyConfiguration.cs
+++ b/src/Avalonia.Input/Platform/PlatformHotkeyConfiguration.cs
@@ -73,8 +73,13 @@ namespace Avalonia.Input.Platform
{
new KeyGesture(Key.End, commandModifiers | selectionModifiers)
};
+ OpenContextMenu = new List
+ {
+ new KeyGesture(Key.F10, KeyModifiers.Shift),
+ new KeyGesture(Key.Apps),
+ };
}
-
+
public KeyModifiers CommandModifiers { get; set; }
public KeyModifiers WholeWordTextActionModifiers { get; set; }
public KeyModifiers SelectionModifiers { get; set; }
@@ -92,7 +97,6 @@ namespace Avalonia.Input.Platform
public List MoveCursorToTheEndOfLineWithSelection { get; set; }
public List MoveCursorToTheStartOfDocumentWithSelection { get; set; }
public List MoveCursorToTheEndOfDocumentWithSelection { get; set; }
-
-
+ public List OpenContextMenu { get; set; }
}
}
diff --git a/src/Avalonia.Themes.Default/TextBox.xaml b/src/Avalonia.Themes.Default/TextBox.xaml
index c68355a57d..12df4b6213 100644
--- a/src/Avalonia.Themes.Default/TextBox.xaml
+++ b/src/Avalonia.Themes.Default/TextBox.xaml
@@ -4,7 +4,7 @@
m10.051 7.0032c2.215 0 4.0105 1.7901 4.0105 3.9984s-1.7956 3.9984-4.0105 3.9984c-2.215 0-4.0105-1.7901-4.0105-3.9984s1.7956-3.9984 4.0105-3.9984zm0 1.4994c-1.3844 0-2.5066 1.1188-2.5066 2.499s1.1222 2.499 2.5066 2.499 2.5066-1.1188 2.5066-2.499-1.1222-2.499-2.5066-2.499zm0-5.0026c4.6257 0 8.6188 3.1487 9.7267 7.5613 0.10085 0.40165-0.14399 0.80877-0.54686 0.90931-0.40288 0.10054-0.81122-0.14355-0.91208-0.54521-0.94136-3.7492-4.3361-6.4261-8.2678-6.4261-3.9334 0-7.3292 2.6792-8.2689 6.4306-0.10063 0.40171-0.50884 0.64603-0.91177 0.54571s-0.648-0.5073-0.54737-0.90901c1.106-4.4152 5.1003-7.5667 9.728-7.5667z
m0.21967 0.21965c-0.26627 0.26627-0.29047 0.68293-0.07262 0.97654l0.07262 0.08412 4.0346 4.0346c-1.922 1.3495-3.3585 3.365-3.9554 5.7495-0.10058 0.4018 0.14362 0.8091 0.54543 0.9097 0.40182 0.1005 0.80909-0.1436 0.90968-0.5455 0.52947-2.1151 1.8371-3.8891 3.5802-5.0341l1.8096 1.8098c-0.70751 0.7215-1.1438 1.71-1.1438 2.8003 0 2.2092 1.7909 4 4 4 1.0904 0 2.0788-0.4363 2.8004-1.1438l5.9193 5.9195c0.2929 0.2929 0.7677 0.2929 1.0606 0 0.2663-0.2662 0.2905-0.6829 0.0726-0.9765l-0.0726-0.0841-6.1135-6.1142 0.0012-0.0015-1.2001-1.1979-2.8699-2.8693 2e-3 -8e-4 -2.8812-2.8782 0.0012-0.0018-1.1333-1.1305-4.3064-4.3058c-0.29289-0.29289-0.76777-0.29289-1.0607 0zm7.9844 9.0458 3.5351 3.5351c-0.45 0.4358-1.0633 0.704-1.7392 0.704-1.3807 0-2.5-1.1193-2.5-2.5 0-0.6759 0.26824-1.2892 0.7041-1.7391zm1.7959-5.7655c-1.0003 0-1.9709 0.14807-2.8889 0.425l1.237 1.2362c0.5358-0.10587 1.0883-0.16119 1.6519-0.16119 3.9231 0 7.3099 2.6803 8.2471 6.4332 0.1004 0.4018 0.5075 0.6462 0.9094 0.5459 0.4019-0.1004 0.6463-0.5075 0.5459-0.9094-1.103-4.417-5.0869-7.5697-9.7024-7.5697zm0.1947 3.5093 3.8013 3.8007c-0.1018-2.0569-1.7488-3.7024-3.8013-3.8007z
-
+
diff --git a/src/Avalonia.Themes.Fluent/Controls/TextBox.xaml b/src/Avalonia.Themes.Fluent/Controls/TextBox.xaml
index 855143f592..5db9398448 100644
--- a/src/Avalonia.Themes.Fluent/Controls/TextBox.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/TextBox.xaml
@@ -15,7 +15,7 @@
m10.051 7.0032c2.215 0 4.0105 1.7901 4.0105 3.9984s-1.7956 3.9984-4.0105 3.9984c-2.215 0-4.0105-1.7901-4.0105-3.9984s1.7956-3.9984 4.0105-3.9984zm0 1.4994c-1.3844 0-2.5066 1.1188-2.5066 2.499s1.1222 2.499 2.5066 2.499 2.5066-1.1188 2.5066-2.499-1.1222-2.499-2.5066-2.499zm0-5.0026c4.6257 0 8.6188 3.1487 9.7267 7.5613 0.10085 0.40165-0.14399 0.80877-0.54686 0.90931-0.40288 0.10054-0.81122-0.14355-0.91208-0.54521-0.94136-3.7492-4.3361-6.4261-8.2678-6.4261-3.9334 0-7.3292 2.6792-8.2689 6.4306-0.10063 0.40171-0.50884 0.64603-0.91177 0.54571s-0.648-0.5073-0.54737-0.90901c1.106-4.4152 5.1003-7.5667 9.728-7.5667z
m0.21967 0.21965c-0.26627 0.26627-0.29047 0.68293-0.07262 0.97654l0.07262 0.08412 4.0346 4.0346c-1.922 1.3495-3.3585 3.365-3.9554 5.7495-0.10058 0.4018 0.14362 0.8091 0.54543 0.9097 0.40182 0.1005 0.80909-0.1436 0.90968-0.5455 0.52947-2.1151 1.8371-3.8891 3.5802-5.0341l1.8096 1.8098c-0.70751 0.7215-1.1438 1.71-1.1438 2.8003 0 2.2092 1.7909 4 4 4 1.0904 0 2.0788-0.4363 2.8004-1.1438l5.9193 5.9195c0.2929 0.2929 0.7677 0.2929 1.0606 0 0.2663-0.2662 0.2905-0.6829 0.0726-0.9765l-0.0726-0.0841-6.1135-6.1142 0.0012-0.0015-1.2001-1.1979-2.8699-2.8693 2e-3 -8e-4 -2.8812-2.8782 0.0012-0.0018-1.1333-1.1305-4.3064-4.3058c-0.29289-0.29289-0.76777-0.29289-1.0607 0zm7.9844 9.0458 3.5351 3.5351c-0.45 0.4358-1.0633 0.704-1.7392 0.704-1.3807 0-2.5-1.1193-2.5-2.5 0-0.6759 0.26824-1.2892 0.7041-1.7391zm1.7959-5.7655c-1.0003 0-1.9709 0.14807-2.8889 0.425l1.237 1.2362c0.5358-0.10587 1.0883-0.16119 1.6519-0.16119 3.9231 0 7.3099 2.6803 8.2471 6.4332 0.1004 0.4018 0.5075 0.6462 0.9094 0.5459 0.4019-0.1004 0.6463-0.5075 0.5459-0.9094-1.103-4.417-5.0869-7.5697-9.7024-7.5697zm0.1947 3.5093 3.8013 3.8007c-0.1018-2.0569-1.7488-3.7024-3.8013-3.8007z
-
+