From bb0a8b698567addeb835341504c2a8aff2125bc2 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Mon, 23 Nov 2020 23:19:16 -0500 Subject: [PATCH 01/16] Fix compiled PropertyElement.ToString() for first Property element --- .../CompiledBindings/CompiledBindingPath.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CompiledBindingPath.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CompiledBindingPath.cs index f6636664c1..11489c39aa 100644 --- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CompiledBindingPath.cs +++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CompiledBindingPath.cs @@ -72,7 +72,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings internal object RawSource { get; } public override string ToString() - => string.Concat(_elements.Select(e => e.ToString())); + => string.Concat(_elements); } public class CompiledBindingPathBuilder @@ -88,7 +88,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings public CompiledBindingPathBuilder Property(IPropertyInfo info, Func, IPropertyInfo, IPropertyAccessor> accessorFactory) { - _elements.Add(new PropertyElement(info, accessorFactory)); + _elements.Add(new PropertyElement(info, accessorFactory, _elements.Count == 0)); return this; } @@ -161,10 +161,13 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings internal class PropertyElement : ICompiledBindingPathElement { - public PropertyElement(IPropertyInfo property, Func, IPropertyInfo, IPropertyAccessor> accessorFactory) + private readonly bool _isFirstElement; + + public PropertyElement(IPropertyInfo property, Func, IPropertyInfo, IPropertyAccessor> accessorFactory, bool isFirstElement) { Property = property; AccessorFactory = accessorFactory; + _isFirstElement = isFirstElement; } public IPropertyInfo Property { get; } @@ -172,7 +175,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings public Func, IPropertyInfo, IPropertyAccessor> AccessorFactory { get; } public override string ToString() - => $".{Property.Name}"; + => _isFirstElement ? Property.Name : $".{Property.Name}"; } internal interface IStronglyTypedStreamElement : ICompiledBindingPathElement From 14e3799641fc55a8c7fd9dd183bd3a718fa570f6 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Mon, 23 Nov 2020 23:20:51 -0500 Subject: [PATCH 02/16] Use BindingBase in DataGrid instead of Binding and support CompiledBinding --- .../DataGridBoundColumn.cs | 21 ++++++++++++------- .../DataGridColumn.cs | 16 ++++++++------ .../DataGridColumns.cs | 5 +++-- 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/Avalonia.Controls.DataGrid/DataGridBoundColumn.cs b/src/Avalonia.Controls.DataGrid/DataGridBoundColumn.cs index 1e72a07760..90401a00a2 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridBoundColumn.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridBoundColumn.cs @@ -10,7 +10,8 @@ using System.Reactive.Disposables; using System.Reactive.Subjects; using Avalonia.Reactive; using System.Diagnostics; -using Avalonia.Controls.Utils; +using Avalonia.Controls.Utils; +using Avalonia.Markup.Xaml.MarkupExtensions; namespace Avalonia.Controls { @@ -47,14 +48,15 @@ namespace Avalonia.Controls if (_binding != null) { - if(_binding is Avalonia.Data.Binding binding) + if(_binding is BindingBase binding) { if (binding.Mode == BindingMode.OneWayToSource) { throw new InvalidOperationException("DataGridColumn doesn't support BindingMode.OneWayToSource. Use BindingMode.TwoWay instead."); } - if (!String.IsNullOrEmpty(binding.Path) && binding.Mode == BindingMode.Default) + var path = (binding as Binding)?.Path ?? (binding as CompiledBindingExtension)?.Path.ToString(); + if (!string.IsNullOrEmpty(path) && binding.Mode == BindingMode.Default) { binding.Mode = BindingMode.TwoWay; } @@ -136,13 +138,16 @@ namespace Avalonia.Controls internal void SetHeaderFromBinding() { if (OwningGrid != null && OwningGrid.DataConnection.DataType != null - && Header == null && Binding != null && Binding is Binding binding - && !String.IsNullOrWhiteSpace(binding.Path)) + && Header == null && Binding != null && Binding is BindingBase binding) { - string header = OwningGrid.DataConnection.DataType.GetDisplayName(binding.Path); - if (header != null) + var path = (binding as Binding)?.Path ?? (binding as CompiledBindingExtension)?.Path.ToString(); + if (!string.IsNullOrWhiteSpace(path)) { - Header = header; + var header = OwningGrid.DataConnection.DataType.GetDisplayName(path); + if (header != null) + { + Header = header; + } } } } diff --git a/src/Avalonia.Controls.DataGrid/DataGridColumn.cs b/src/Avalonia.Controls.DataGrid/DataGridColumn.cs index 92ddd4e736..407d6ff058 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridColumn.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridColumn.cs @@ -12,6 +12,7 @@ using System; using System.Linq; using System.Diagnostics; using Avalonia.Controls.Utils; +using Avalonia.Markup.Xaml.MarkupExtensions; namespace Avalonia.Controls { @@ -1033,13 +1034,16 @@ namespace Avalonia.Controls if (String.IsNullOrEmpty(result)) { - - if(this is DataGridBoundColumn boundColumn && - boundColumn.Binding != null && - boundColumn.Binding is Binding binding && - binding.Path != null) + if (this is DataGridBoundColumn boundColumn) { - result = binding.Path; + if (boundColumn.Binding is Binding binding) + { + result = binding.Path; + } + else if (boundColumn.Binding is CompiledBindingExtension compiledBinding) + { + result = compiledBinding.Path.ToString(); + } } } diff --git a/src/Avalonia.Controls.DataGrid/DataGridColumns.cs b/src/Avalonia.Controls.DataGrid/DataGridColumns.cs index 46bcd0d347..a4577ee952 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridColumns.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridColumns.cs @@ -5,6 +5,7 @@ using Avalonia.Controls.Utils; using Avalonia.Data; +using Avalonia.Markup.Xaml.MarkupExtensions; using Avalonia.Utilities; using System; using System.Collections.Generic; @@ -141,9 +142,9 @@ namespace Avalonia.Controls Debug.Assert(dataGridColumn != null); if (dataGridColumn is DataGridBoundColumn dataGridBoundColumn && - dataGridBoundColumn.Binding is Binding binding) + dataGridBoundColumn.Binding is BindingBase binding) { - string path = binding.Path; + var path = (binding as Binding)?.Path ?? (binding as CompiledBindingExtension)?.Path.ToString(); if (string.IsNullOrWhiteSpace(path)) { From 26fa71bddce33848565dfd4c42df314364d7cec3 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Mon, 23 Nov 2020 23:23:55 -0500 Subject: [PATCH 03/16] DataGrid add CompiledBinding example --- samples/ControlCatalog/Pages/DataGridPage.xaml | 5 +++-- samples/ControlCatalog/Pages/DataGridPage.xaml.cs | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/samples/ControlCatalog/Pages/DataGridPage.xaml b/samples/ControlCatalog/Pages/DataGridPage.xaml index cacc2204bd..6dc50087f8 100644 --- a/samples/ControlCatalog/Pages/DataGridPage.xaml +++ b/samples/ControlCatalog/Pages/DataGridPage.xaml @@ -1,5 +1,5 @@ @@ -26,7 +26,8 @@ - + + diff --git a/samples/ControlCatalog/Pages/DataGridPage.xaml.cs b/samples/ControlCatalog/Pages/DataGridPage.xaml.cs index 2a30f4d91b..dc5cc49a90 100644 --- a/samples/ControlCatalog/Pages/DataGridPage.xaml.cs +++ b/samples/ControlCatalog/Pages/DataGridPage.xaml.cs @@ -24,8 +24,10 @@ namespace ControlCatalog.Pages dg1.LoadingRow += Dg1_LoadingRow; dg1.Sorting += (s, a) => { - var property = ((a.Column as DataGridBoundColumn)?.Binding as Binding).Path; - if (property == dataGridSortDescription.PropertyPath + var binding = (a.Column as DataGridBoundColumn)?.Binding as Binding; + + if (binding?.Path is string property + && property == dataGridSortDescription.PropertyPath && !collectionView1.SortDescriptions.Contains(dataGridSortDescription)) { collectionView1.SortDescriptions.Add(dataGridSortDescription); From b8d3f85636d15b39c05e5b3cd2869dfd20532047 Mon Sep 17 00:00:00 2001 From: MichalPetryka <35800402+MichalPetryka@users.noreply.github.com> Date: Thu, 28 Jan 2021 19:57:49 +0100 Subject: [PATCH 04/16] Correct RtlGetVersion usage --- src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index b21741453c..1559c7e794 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -1432,15 +1432,15 @@ namespace Avalonia.Win32.Interop } [DllImport("ntdll")] - private static extern int RtlGetVersion(out RTL_OSVERSIONINFOEX lpVersionInformation); + private static extern int RtlGetVersion(ref RTL_OSVERSIONINFOEX lpVersionInformation); internal static Version RtlGetVersion() { RTL_OSVERSIONINFOEX v = new RTL_OSVERSIONINFOEX(); v.dwOSVersionInfoSize = (uint)Marshal.SizeOf(v); - if (RtlGetVersion(out v) == 0) + if (RtlGetVersion(ref v) == 0) { - return new Version((int)v.dwMajorVersion, (int)v.dwMinorVersion, (int)v.dwBuildNumber, (int)v.dwPlatformId); + return new Version((int)v.dwMajorVersion, (int)v.dwMinorVersion, (int)v.dwBuildNumber); } else { From 1abf9964e6f6cdd52be1e6f24da50f84559ab8c2 Mon Sep 17 00:00:00 2001 From: Peter Davis Date: Wed, 10 Feb 2021 11:13:41 +1030 Subject: [PATCH 05/16] Set initial input focus using LinuxFrameBufferPlatform --- .../Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs b/src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs index 340d10517d..3c8d3b5e06 100644 --- a/src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs +++ b/src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Diagnostics; using System.Threading; using Avalonia.Controls; @@ -79,6 +79,11 @@ namespace Avalonia.LinuxFramebuffer tl.Prepare(); _topLevel = tl; _topLevel.Renderer.Start(); + + if (_topLevel is IFocusScope scope) + { + FocusManager.Instance?.SetFocusScope(scope); + } } _topLevel.Content = value; From 0a7ca87e3bb386943c7af516f31beff955442763 Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Thu, 15 Oct 2020 21:21:13 +0300 Subject: [PATCH 06/16] HasFlagCustom made safe and supports all enums --- src/Avalonia.Base/EnumExtensions.cs | 30 ++++++++++-- src/Avalonia.Base/Utilities/TypeUtilities.cs | 4 +- .../Collections/DataGridCollectionView.cs | 2 +- src/Avalonia.Controls/ComboBox.cs | 2 +- src/Avalonia.Controls/Grid.cs | 45 +++++++---------- src/Avalonia.Controls/ListBox.cs | 8 ++-- .../Platform/InProcessDragSource.cs | 12 ++--- .../PopupPositioning/IPopupPositioner.cs | 21 ++++---- .../ManagedPopupPositioner.cs | 48 ++++++++----------- .../Primitives/SelectingItemsControl.cs | 8 ++-- .../Repeater/RepeaterLayoutContext.cs | 4 +- src/Avalonia.Controls/TextBox.cs | 4 +- src/Avalonia.Controls/TreeView.cs | 12 ++--- src/Avalonia.FreeDesktop/DBusMenuExporter.cs | 8 ++-- .../HeadlessVncFramebufferSource.cs | 4 +- src/Avalonia.Input/AccessKeyHandler.cs | 2 +- src/Avalonia.X11/X11Window.Ime.cs | 4 +- src/Avalonia.X11/X11Window.cs | 18 +++---- src/Avalonia.X11/XI2Manager.cs | 10 ++-- .../Output/DrmBindings.cs | 2 +- .../Wpf/WpfTopLevelImpl.cs | 8 ++-- src/Windows/Avalonia.Win32/DataObject.cs | 6 +-- src/Windows/Avalonia.Win32/OleDropTarget.cs | 24 +++++----- .../WindowImpl.CustomCaptionProc.cs | 4 +- src/Windows/Avalonia.Win32/WindowImpl.cs | 10 ++-- 25 files changed, 150 insertions(+), 150 deletions(-) diff --git a/src/Avalonia.Base/EnumExtensions.cs b/src/Avalonia.Base/EnumExtensions.cs index 1e4864283f..bc1f8d36a9 100644 --- a/src/Avalonia.Base/EnumExtensions.cs +++ b/src/Avalonia.Base/EnumExtensions.cs @@ -11,10 +11,32 @@ namespace Avalonia [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe bool HasFlagCustom(this T value, T flag) where T : unmanaged, Enum { - var intValue = *(int*)&value; - var intFlag = *(int*)&flag; - - return (intValue & intFlag) == intFlag; + if (sizeof(T) == 1) + { + var byteValue = Unsafe.As(ref value); + var byteFlag = Unsafe.As(ref flag); + return (byteValue & byteFlag) == byteFlag; + } + else if (sizeof(T) == 2) + { + var shortValue = Unsafe.As(ref value); + var shortFlag = Unsafe.As(ref flag); + return (shortValue & shortFlag) == shortFlag; + } + else if (sizeof(T) == 4) + { + var intValue = Unsafe.As(ref value); + var intFlag = Unsafe.As(ref flag); + return (intValue & intFlag) == intFlag; + } + else if (sizeof(T) == 8) + { + var longValue = Unsafe.As(ref value); + var longFlag = Unsafe.As(ref flag); + return (longValue & longFlag) == longFlag; + } + else + throw new NotSupportedException("Enum with size of " + Unsafe.SizeOf() + " are not supported"); } } } diff --git a/src/Avalonia.Base/Utilities/TypeUtilities.cs b/src/Avalonia.Base/Utilities/TypeUtilities.cs index d0d88166a7..097731bc60 100644 --- a/src/Avalonia.Base/Utilities/TypeUtilities.cs +++ b/src/Avalonia.Base/Utilities/TypeUtilities.cs @@ -372,8 +372,8 @@ namespace Avalonia.Utilities const string implicitName = "op_Implicit"; const string explicitName = "op_Explicit"; - bool allowImplicit = (operatorType & OperatorType.Implicit) != 0; - bool allowExplicit = (operatorType & OperatorType.Explicit) != 0; + bool allowImplicit = operatorType.HasFlagCustom(OperatorType.Implicit); + bool allowExplicit = operatorType.HasFlagCustom(OperatorType.Explicit); foreach (MethodInfo method in fromType.GetMethods()) { diff --git a/src/Avalonia.Controls.DataGrid/Collections/DataGridCollectionView.cs b/src/Avalonia.Controls.DataGrid/Collections/DataGridCollectionView.cs index 92734b128d..b97f2a2bcb 100644 --- a/src/Avalonia.Controls.DataGrid/Collections/DataGridCollectionView.cs +++ b/src/Avalonia.Controls.DataGrid/Collections/DataGridCollectionView.cs @@ -2595,7 +2595,7 @@ namespace Avalonia.Collections /// Whether the specified flag is set private bool CheckFlag(CollectionViewFlags flags) { - return (_flags & flags) != 0; + return _flags.HasFlagCustom(flags); } /// diff --git a/src/Avalonia.Controls/ComboBox.cs b/src/Avalonia.Controls/ComboBox.cs index 7f2acb58fe..20ca41bc57 100644 --- a/src/Avalonia.Controls/ComboBox.cs +++ b/src/Avalonia.Controls/ComboBox.cs @@ -188,7 +188,7 @@ namespace Avalonia.Controls return; if (e.Key == Key.F4 || - ((e.Key == Key.Down || e.Key == Key.Up) && ((e.KeyModifiers & KeyModifiers.Alt) != 0))) + ((e.Key == Key.Down || e.Key == Key.Up) && e.KeyModifiers.HasFlagCustom(KeyModifiers.Alt))) { IsDropDownOpen = !IsDropDownOpen; e.Handled = true; diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs index 6357ec98a8..66266c3b61 100644 --- a/src/Avalonia.Controls/Grid.cs +++ b/src/Avalonia.Controls/Grid.cs @@ -637,7 +637,7 @@ namespace Avalonia.Controls /// internal bool MeasureOverrideInProgress { - get { return (CheckFlagsAnd(Flags.MeasureOverrideInProgress)); } + get { return CheckFlags(Flags.MeasureOverrideInProgress); } set { SetFlags(value, Flags.MeasureOverrideInProgress); } } @@ -646,7 +646,7 @@ namespace Avalonia.Controls /// internal bool ArrangeOverrideInProgress { - get { return (CheckFlagsAnd(Flags.ArrangeOverrideInProgress)); } + get { return CheckFlags(Flags.ArrangeOverrideInProgress); } set { SetFlags(value, Flags.ArrangeOverrideInProgress); } } @@ -2350,25 +2350,12 @@ namespace Avalonia.Controls } /// - /// CheckFlagsAnd returns true if all the flags in the + /// CheckFlags returns true if all the flags in the /// given bitmask are set on the object. /// - private bool CheckFlagsAnd(Flags flags) + private bool CheckFlags(Flags flags) { - return ((_flags & flags) == flags); - } - - /// - /// CheckFlagsOr returns true if at least one flag in the - /// given bitmask is set. - /// - /// - /// If no bits are set in the given bitmask, the method returns - /// true. - /// - private bool CheckFlagsOr(Flags flags) - { - return (flags == 0 || (_flags & flags) != 0); + return _flags.HasFlagCustom(flags); } private static void OnShowGridLinesPropertyChanged(AvaloniaObject d, AvaloniaPropertyChangedEventArgs e) @@ -2535,7 +2522,7 @@ namespace Avalonia.Controls /// private bool CellsStructureDirty { - get { return (!CheckFlagsAnd(Flags.ValidCellsStructure)); } + get { return !CheckFlags(Flags.ValidCellsStructure); } set { SetFlags(!value, Flags.ValidCellsStructure); } } @@ -2544,7 +2531,7 @@ namespace Avalonia.Controls /// private bool ListenToNotifications { - get { return (CheckFlagsAnd(Flags.ListenToNotifications)); } + get { return CheckFlags(Flags.ListenToNotifications); } set { SetFlags(value, Flags.ListenToNotifications); } } @@ -2553,7 +2540,7 @@ namespace Avalonia.Controls /// private bool SizeToContentU { - get { return (CheckFlagsAnd(Flags.SizeToContentU)); } + get { return CheckFlags(Flags.SizeToContentU); } set { SetFlags(value, Flags.SizeToContentU); } } @@ -2562,7 +2549,7 @@ namespace Avalonia.Controls /// private bool SizeToContentV { - get { return (CheckFlagsAnd(Flags.SizeToContentV)); } + get { return CheckFlags(Flags.SizeToContentV); } set { SetFlags(value, Flags.SizeToContentV); } } @@ -2571,7 +2558,7 @@ namespace Avalonia.Controls /// private bool HasStarCellsU { - get { return (CheckFlagsAnd(Flags.HasStarCellsU)); } + get { return CheckFlags(Flags.HasStarCellsU); } set { SetFlags(value, Flags.HasStarCellsU); } } @@ -2580,7 +2567,7 @@ namespace Avalonia.Controls /// private bool HasStarCellsV { - get { return (CheckFlagsAnd(Flags.HasStarCellsV)); } + get { return CheckFlags(Flags.HasStarCellsV); } set { SetFlags(value, Flags.HasStarCellsV); } } @@ -2589,7 +2576,7 @@ namespace Avalonia.Controls /// private bool HasGroup3CellsInAutoRows { - get { return (CheckFlagsAnd(Flags.HasGroup3CellsInAutoRows)); } + get { return CheckFlags(Flags.HasGroup3CellsInAutoRows); } set { SetFlags(value, Flags.HasGroup3CellsInAutoRows); } } @@ -2803,10 +2790,10 @@ namespace Avalonia.Controls internal LayoutTimeSizeType SizeTypeU; internal LayoutTimeSizeType SizeTypeV; internal int Next; - internal bool IsStarU { get { return ((SizeTypeU & LayoutTimeSizeType.Star) != 0); } } - internal bool IsAutoU { get { return ((SizeTypeU & LayoutTimeSizeType.Auto) != 0); } } - internal bool IsStarV { get { return ((SizeTypeV & LayoutTimeSizeType.Star) != 0); } } - internal bool IsAutoV { get { return ((SizeTypeV & LayoutTimeSizeType.Auto) != 0); } } + internal bool IsStarU => SizeTypeU.HasFlagCustom(LayoutTimeSizeType.Star); + internal bool IsAutoU => SizeTypeU.HasFlagCustom(LayoutTimeSizeType.Auto); + internal bool IsStarV => SizeTypeV.HasFlagCustom(LayoutTimeSizeType.Star); + internal bool IsAutoV => SizeTypeV.HasFlagCustom(LayoutTimeSizeType.Auto); } /// diff --git a/src/Avalonia.Controls/ListBox.cs b/src/Avalonia.Controls/ListBox.cs index d1b8038581..b6b3cc786c 100644 --- a/src/Avalonia.Controls/ListBox.cs +++ b/src/Avalonia.Controls/ListBox.cs @@ -135,8 +135,8 @@ namespace Avalonia.Controls e.Handled = UpdateSelectionFromEventSource( e.Source, true, - (e.KeyModifiers & KeyModifiers.Shift) != 0, - (e.KeyModifiers & KeyModifiers.Control) != 0); + e.KeyModifiers.HasFlagCustom(KeyModifiers.Shift), + e.KeyModifiers.HasFlagCustom(KeyModifiers.Control)); } } @@ -154,8 +154,8 @@ namespace Avalonia.Controls e.Handled = UpdateSelectionFromEventSource( e.Source, true, - (e.KeyModifiers & KeyModifiers.Shift) != 0, - (e.KeyModifiers & KeyModifiers.Control) != 0, + e.KeyModifiers.HasFlagCustom(KeyModifiers.Shift), + e.KeyModifiers.HasFlagCustom(KeyModifiers.Control), point.Properties.IsRightButtonPressed); } } diff --git a/src/Avalonia.Controls/Platform/InProcessDragSource.cs b/src/Avalonia.Controls/Platform/InProcessDragSource.cs index 9d644aaa00..7e1a7378c7 100644 --- a/src/Avalonia.Controls/Platform/InProcessDragSource.cs +++ b/src/Avalonia.Controls/Platform/InProcessDragSource.cs @@ -73,20 +73,20 @@ namespace Avalonia.Platform { if (effect == DragDropEffects.Copy || effect == DragDropEffects.Move || effect == DragDropEffects.Link || effect == DragDropEffects.None) return effect; // No need to check for the modifiers. - if (effect.HasFlag(DragDropEffects.Link) && modifiers.HasFlag(RawInputModifiers.Alt)) + if (effect.HasFlagCustom(DragDropEffects.Link) && modifiers.HasFlagCustom(RawInputModifiers.Alt)) return DragDropEffects.Link; - if (effect.HasFlag(DragDropEffects.Copy) && modifiers.HasFlag(RawInputModifiers.Control)) + if (effect.HasFlagCustom(DragDropEffects.Copy) && modifiers.HasFlagCustom(RawInputModifiers.Control)) return DragDropEffects.Copy; return DragDropEffects.Move; } private StandardCursorType GetCursorForDropEffect(DragDropEffects effects) { - if (effects.HasFlag(DragDropEffects.Copy)) + if (effects.HasFlagCustom(DragDropEffects.Copy)) return StandardCursorType.DragCopy; - if (effects.HasFlag(DragDropEffects.Move)) + if (effects.HasFlagCustom(DragDropEffects.Move)) return StandardCursorType.DragMove; - if (effects.HasFlag(DragDropEffects.Link)) + if (effects.HasFlagCustom(DragDropEffects.Link)) return StandardCursorType.DragLink; return StandardCursorType.No; } @@ -161,7 +161,7 @@ namespace Avalonia.Platform void CheckDraggingAccepted(RawInputModifiers changedMouseButton) { - if (_initialInputModifiers.Value.HasFlag(changedMouseButton)) + if (_initialInputModifiers.Value.HasFlagCustom(changedMouseButton)) { var result = RaiseEventAndUpdateCursor(RawDragEventType.Drop, e.Root, e.Position, e.InputModifiers); UpdateCursor(null, DragDropEffects.None); diff --git a/src/Avalonia.Controls/Primitives/PopupPositioning/IPopupPositioner.cs b/src/Avalonia.Controls/Primitives/PopupPositioning/IPopupPositioner.cs index aed7dff0fe..545034239f 100644 --- a/src/Avalonia.Controls/Primitives/PopupPositioning/IPopupPositioner.cs +++ b/src/Avalonia.Controls/Primitives/PopupPositioning/IPopupPositioner.cs @@ -253,9 +253,8 @@ namespace Avalonia.Controls.Primitives.PopupPositioning { public static void ValidateEdge(this PopupAnchor edge) { - if (((edge & PopupAnchor.Left) != 0 && (edge & PopupAnchor.Right) != 0) - || - ((edge & PopupAnchor.Top) != 0 && (edge & PopupAnchor.Bottom) != 0)) + if (edge.HasFlagCustom(PopupAnchor.Left) && edge.HasFlagCustom(PopupAnchor.Right) || + edge.HasFlagCustom(PopupAnchor.Top) && edge.HasFlagCustom(PopupAnchor.Bottom)) throw new ArgumentException("Opposite edges specified"); } @@ -266,25 +265,25 @@ namespace Avalonia.Controls.Primitives.PopupPositioning public static PopupAnchor Flip(this PopupAnchor edge) { - var hmask = PopupAnchor.Left | PopupAnchor.Right; - var vmask = PopupAnchor.Top | PopupAnchor.Bottom; - if ((edge & hmask) != 0) - edge ^= hmask; - if ((edge & vmask) != 0) - edge ^= vmask; + if (edge.HasFlagCustom(PopupAnchor.HorizontalMask)) + edge ^= PopupAnchor.HorizontalMask; + + if (edge.HasFlagCustom(PopupAnchor.VerticalMask)) + edge ^= PopupAnchor.VerticalMask; + return edge; } public static PopupAnchor FlipX(this PopupAnchor edge) { - if ((edge & PopupAnchor.HorizontalMask) != 0) + if (edge.HasFlagCustom(PopupAnchor.HorizontalMask)) edge ^= PopupAnchor.HorizontalMask; return edge; } public static PopupAnchor FlipY(this PopupAnchor edge) { - if ((edge & PopupAnchor.VerticalMask) != 0) + if (edge.HasFlagCustom(PopupAnchor.VerticalMask)) edge ^= PopupAnchor.VerticalMask; return edge; } diff --git a/src/Avalonia.Controls/Primitives/PopupPositioning/ManagedPopupPositioner.cs b/src/Avalonia.Controls/Primitives/PopupPositioning/ManagedPopupPositioner.cs index 7f1dbdf592..80b32b5ef8 100644 --- a/src/Avalonia.Controls/Primitives/PopupPositioning/ManagedPopupPositioner.cs +++ b/src/Avalonia.Controls/Primitives/PopupPositioning/ManagedPopupPositioner.cs @@ -42,16 +42,16 @@ namespace Avalonia.Controls.Primitives.PopupPositioning private static Point GetAnchorPoint(Rect anchorRect, PopupAnchor edge) { double x, y; - if ((edge & PopupAnchor.Left) != 0) + if (edge.HasFlagCustom(PopupAnchor.Left)) x = anchorRect.X; - else if ((edge & PopupAnchor.Right) != 0) + else if (edge.HasFlagCustom(PopupAnchor.Right)) x = anchorRect.Right; else x = anchorRect.X + anchorRect.Width / 2; - if ((edge & PopupAnchor.Top) != 0) + if (edge.HasFlagCustom(PopupAnchor.Top)) y = anchorRect.Y; - else if ((edge & PopupAnchor.Bottom) != 0) + else if (edge.HasFlagCustom(PopupAnchor.Bottom)) y = anchorRect.Bottom; else y = anchorRect.Y + anchorRect.Height / 2; @@ -61,16 +61,16 @@ namespace Avalonia.Controls.Primitives.PopupPositioning private static Point Gravitate(Point anchorPoint, Size size, PopupGravity gravity) { double x, y; - if ((gravity & PopupGravity.Left) != 0) + if (gravity.HasFlagCustom(PopupGravity.Left)) x = -size.Width; - else if ((gravity & PopupGravity.Right) != 0) + else if (gravity.HasFlagCustom(PopupGravity.Right)) x = 0; else x = -size.Width / 2; - if ((gravity & PopupGravity.Top) != 0) + if (gravity.HasFlagCustom(PopupGravity.Top)) y = -size.Height; - else if ((gravity & PopupGravity.Bottom) != 0) + else if (gravity.HasFlagCustom(PopupGravity.Bottom)) y = 0; else y = -size.Height / 2; @@ -125,21 +125,13 @@ namespace Avalonia.Controls.Primitives.PopupPositioning bool FitsInBounds(Rect rc, PopupAnchor edge = PopupAnchor.AllMask) { - if ((edge & PopupAnchor.Left) != 0 - && rc.X < bounds.X) - return false; - - if ((edge & PopupAnchor.Top) != 0 - && rc.Y < bounds.Y) - return false; - - if ((edge & PopupAnchor.Right) != 0 - && rc.Right > bounds.Right) - return false; - - if ((edge & PopupAnchor.Bottom) != 0 - && rc.Bottom > bounds.Bottom) + if (edge.HasFlagCustom(PopupAnchor.Left) && rc.X < bounds.X || + edge.HasFlagCustom(PopupAnchor.Top) && rc.Y < bounds.Y || + edge.HasFlagCustom(PopupAnchor.Right) && rc.Right > bounds.Right || + edge.HasFlagCustom(PopupAnchor.Bottom) && rc.Bottom > bounds.Bottom) + { return false; + } return true; } @@ -155,7 +147,7 @@ namespace Avalonia.Controls.Primitives.PopupPositioning // If flipping geometry and anchor is allowed and helps, use the flipped one, // otherwise leave it as is if (!FitsInBounds(geo, PopupAnchor.HorizontalMask) - && (constraintAdjustment & PopupPositionerConstraintAdjustment.FlipX) != 0) + && constraintAdjustment.HasFlagCustom(PopupPositionerConstraintAdjustment.FlipX)) { var flipped = GetUnconstrained(anchor.FlipX(), gravity.FlipX()); if (FitsInBounds(flipped, PopupAnchor.HorizontalMask)) @@ -163,7 +155,7 @@ namespace Avalonia.Controls.Primitives.PopupPositioning } // If sliding is allowed, try moving the rect into the bounds - if ((constraintAdjustment & PopupPositionerConstraintAdjustment.SlideX) != 0) + if (constraintAdjustment.HasFlagCustom(PopupPositionerConstraintAdjustment.SlideX)) { geo = geo.WithX(Math.Max(geo.X, bounds.X)); if (geo.Right > bounds.Right) @@ -171,7 +163,7 @@ namespace Avalonia.Controls.Primitives.PopupPositioning } // Resize the rect horizontally if allowed. - if ((constraintAdjustment & PopupPositionerConstraintAdjustment.ResizeX) != 0) + if (constraintAdjustment.HasFlagCustom(PopupPositionerConstraintAdjustment.ResizeX)) { var unconstrainedRect = geo; @@ -194,7 +186,7 @@ namespace Avalonia.Controls.Primitives.PopupPositioning // If flipping geometry and anchor is allowed and helps, use the flipped one, // otherwise leave it as is if (!FitsInBounds(geo, PopupAnchor.VerticalMask) - && (constraintAdjustment & PopupPositionerConstraintAdjustment.FlipY) != 0) + && constraintAdjustment.HasFlagCustom(PopupPositionerConstraintAdjustment.FlipY)) { var flipped = GetUnconstrained(anchor.FlipY(), gravity.FlipY()); if (FitsInBounds(flipped, PopupAnchor.VerticalMask)) @@ -202,7 +194,7 @@ namespace Avalonia.Controls.Primitives.PopupPositioning } // If sliding is allowed, try moving the rect into the bounds - if ((constraintAdjustment & PopupPositionerConstraintAdjustment.SlideY) != 0) + if (constraintAdjustment.HasFlagCustom(PopupPositionerConstraintAdjustment.SlideY)) { geo = geo.WithY(Math.Max(geo.Y, bounds.Y)); if (geo.Bottom > bounds.Bottom) @@ -210,7 +202,7 @@ namespace Avalonia.Controls.Primitives.PopupPositioning } // Resize the rect vertically if allowed. - if ((constraintAdjustment & PopupPositionerConstraintAdjustment.ResizeY) != 0) + if (constraintAdjustment.HasFlagCustom(PopupPositionerConstraintAdjustment.ResizeY)) { var unconstrainedRect = geo; diff --git a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs index 280f46be9f..2cd69793dc 100644 --- a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs +++ b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs @@ -321,7 +321,7 @@ namespace Avalonia.Controls.Primitives /// /// Gets a value indicating whether is set. /// - protected bool AlwaysSelected => (SelectionMode & SelectionMode.AlwaysSelected) != 0; + protected bool AlwaysSelected => SelectionMode.HasFlagCustom(SelectionMode.AlwaysSelected); /// public override void BeginInit() @@ -487,7 +487,7 @@ namespace Avalonia.Controls.Primitives if (ItemCount > 0 && Match(keymap.SelectAll) && - SelectionMode.HasFlag(SelectionMode.Multiple)) + SelectionMode.HasFlagCustom(SelectionMode.Multiple)) { Selection.SelectAll(); e.Handled = true; @@ -577,8 +577,8 @@ namespace Avalonia.Controls.Primitives } var mode = SelectionMode; - var multi = (mode & SelectionMode.Multiple) != 0; - var toggle = (toggleModifier || (mode & SelectionMode.Toggle) != 0); + var multi = mode.HasFlagCustom(SelectionMode.Multiple); + var toggle = toggleModifier || mode.HasFlagCustom(SelectionMode.Toggle); var range = multi && rangeModifier; if (!select) diff --git a/src/Avalonia.Controls/Repeater/RepeaterLayoutContext.cs b/src/Avalonia.Controls/Repeater/RepeaterLayoutContext.cs index fd33eeaf39..4eadced423 100644 --- a/src/Avalonia.Controls/Repeater/RepeaterLayoutContext.cs +++ b/src/Avalonia.Controls/Repeater/RepeaterLayoutContext.cs @@ -53,8 +53,8 @@ namespace Avalonia.Controls { return _owner.GetElementImpl( index, - (options & ElementRealizationOptions.ForceCreate) != 0, - (options & ElementRealizationOptions.SuppressAutoRecycle) != 0); + options.HasFlagCustom(ElementRealizationOptions.ForceCreate), + options.HasFlagCustom(ElementRealizationOptions.SuppressAutoRecycle)); } protected override object GetItemAtCore(int index) => _owner.ItemsSourceView.GetAt(index); diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index 90064fad57..54d3af9b59 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -585,7 +585,7 @@ namespace Avalonia.Controls var keymap = AvaloniaLocator.Current.GetService(); bool Match(List gestures) => gestures.Any(g => g.Matches(e)); - bool DetectSelection() => e.KeyModifiers.HasFlag(keymap.SelectionModifiers); + bool DetectSelection() => e.KeyModifiers.HasFlagCustom(keymap.SelectionModifiers); if (Match(keymap.SelectAll)) { @@ -703,7 +703,7 @@ namespace Avalonia.Controls } else { - bool hasWholeWordModifiers = modifiers.HasFlag(keymap.WholeWordTextActionModifiers); + bool hasWholeWordModifiers = modifiers.HasFlagCustom(keymap.WholeWordTextActionModifiers); switch (e.Key) { case Key.Left: diff --git a/src/Avalonia.Controls/TreeView.cs b/src/Avalonia.Controls/TreeView.cs index 09742412d9..c8150cc200 100644 --- a/src/Avalonia.Controls/TreeView.cs +++ b/src/Avalonia.Controls/TreeView.cs @@ -412,7 +412,7 @@ namespace Avalonia.Controls e.Handled = UpdateSelectionFromEventSource( e.Source, true, - (e.KeyModifiers & KeyModifiers.Shift) != 0); + e.KeyModifiers.HasFlagCustom(KeyModifiers.Shift)); } } @@ -521,8 +521,8 @@ namespace Avalonia.Controls e.Handled = UpdateSelectionFromEventSource( e.Source, true, - (e.KeyModifiers & KeyModifiers.Shift) != 0, - (e.KeyModifiers & KeyModifiers.Control) != 0, + e.KeyModifiers.HasFlagCustom(KeyModifiers.Shift), + e.KeyModifiers.HasFlagCustom(KeyModifiers.Control), point.Properties.IsRightButtonPressed); } } @@ -558,9 +558,9 @@ namespace Avalonia.Controls } var mode = SelectionMode; - var toggle = toggleModifier || (mode & SelectionMode.Toggle) != 0; - var multi = (mode & SelectionMode.Multiple) != 0; - var range = multi && selectedContainer != null && rangeModifier; + var toggle = toggleModifier || mode.HasFlagCustom(SelectionMode.Toggle); + var multi = mode.HasFlagCustom(SelectionMode.Multiple); + var range = multi && rangeModifier && selectedContainer != null; if (rightButton) { diff --git a/src/Avalonia.FreeDesktop/DBusMenuExporter.cs b/src/Avalonia.FreeDesktop/DBusMenuExporter.cs index e93ca64d3a..2cf533195e 100644 --- a/src/Avalonia.FreeDesktop/DBusMenuExporter.cs +++ b/src/Avalonia.FreeDesktop/DBusMenuExporter.cs @@ -223,13 +223,13 @@ namespace Avalonia.FreeDesktop return null; var lst = new List(); var mod = item.Gesture; - if ((mod.KeyModifiers & KeyModifiers.Control) != 0) + if (mod.KeyModifiers.HasFlagCustom(KeyModifiers.Control)) lst.Add("Control"); - if ((mod.KeyModifiers & KeyModifiers.Alt) != 0) + if (mod.KeyModifiers.HasFlagCustom(KeyModifiers.Alt)) lst.Add("Alt"); - if ((mod.KeyModifiers & KeyModifiers.Shift) != 0) + if (mod.KeyModifiers.HasFlagCustom(KeyModifiers.Shift)) lst.Add("Shift"); - if ((mod.KeyModifiers & KeyModifiers.Meta) != 0) + if (mod.KeyModifiers.HasFlagCustom(KeyModifiers.Meta)) lst.Add("Super"); lst.Add(item.Gesture.Key.ToString()); return new[] { lst.ToArray() }; diff --git a/src/Avalonia.Headless.Vnc/HeadlessVncFramebufferSource.cs b/src/Avalonia.Headless.Vnc/HeadlessVncFramebufferSource.cs index 32f9f99709..fb61f25cea 100644 --- a/src/Avalonia.Headless.Vnc/HeadlessVncFramebufferSource.cs +++ b/src/Avalonia.Headless.Vnc/HeadlessVncFramebufferSource.cs @@ -33,11 +33,11 @@ namespace Avalonia.Headless.Vnc { Window?.MouseMove(pt); foreach (var btn in CheckedButtons) - if (_previousButtons.HasFlag(btn) && !buttons.HasFlag(btn)) + if (_previousButtons.HasFlagCustom(btn) && !buttons.HasFlagCustom(btn)) Window?.MouseUp(pt, TranslateButton(btn), modifiers); foreach (var btn in CheckedButtons) - if (!_previousButtons.HasFlag(btn) && buttons.HasFlag(btn)) + if (!_previousButtons.HasFlagCustom(btn) && buttons.HasFlagCustom(btn)) Window?.MouseDown(pt, TranslateButton(btn), modifiers); _previousButtons = buttons; }, DispatcherPriority.Input); diff --git a/src/Avalonia.Input/AccessKeyHandler.cs b/src/Avalonia.Input/AccessKeyHandler.cs index 660584e2ed..731a409090 100644 --- a/src/Avalonia.Input/AccessKeyHandler.cs +++ b/src/Avalonia.Input/AccessKeyHandler.cs @@ -177,7 +177,7 @@ namespace Avalonia.Input { bool menuIsOpen = MainMenu?.IsOpen == true; - if ((e.KeyModifiers & KeyModifiers.Alt) != 0 || menuIsOpen) + if (e.KeyModifiers.HasFlagCustom(KeyModifiers.Alt) || menuIsOpen) { // If any other key is pressed with the Alt key held down, or the main menu is open, // find all controls who have registered that access key. diff --git a/src/Avalonia.X11/X11Window.Ime.cs b/src/Avalonia.X11/X11Window.Ime.cs index f469ff7455..ac626f5825 100644 --- a/src/Avalonia.X11/X11Window.Ime.cs +++ b/src/Avalonia.X11/X11Window.Ime.cs @@ -96,14 +96,14 @@ namespace Avalonia.X11 void HandleKeyEvent(ref XEvent ev) { - var index = ev.KeyEvent.state.HasFlag(XModifierMask.ShiftMask); + var index = ev.KeyEvent.state.HasFlagCustom(XModifierMask.ShiftMask); // We need the latin key, since it's mainly used for hotkeys, we use a different API for text anyway var key = (X11Key)XKeycodeToKeysym(_x11.Display, ev.KeyEvent.keycode, index ? 1 : 0).ToInt32(); // Manually switch the Shift index for the keypad, // there should be a proper way to do this - if (ev.KeyEvent.state.HasFlag(XModifierMask.Mod2Mask) + if (ev.KeyEvent.state.HasFlagCustom(XModifierMask.Mod2Mask) && key > X11Key.Num_Lock && key <= X11Key.KP_9) key = (X11Key)XKeycodeToKeysym(_x11.Display, ev.KeyEvent.keycode, index ? 0 : 1).ToInt32(); diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 92d1e37efe..8f3f412578 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -639,23 +639,23 @@ namespace Avalonia.X11 RawInputModifiers TranslateModifiers(XModifierMask state) { var rv = default(RawInputModifiers); - if (state.HasFlag(XModifierMask.Button1Mask)) + if (state.HasFlagCustom(XModifierMask.Button1Mask)) rv |= RawInputModifiers.LeftMouseButton; - if (state.HasFlag(XModifierMask.Button2Mask)) + if (state.HasFlagCustom(XModifierMask.Button2Mask)) rv |= RawInputModifiers.RightMouseButton; - if (state.HasFlag(XModifierMask.Button3Mask)) + if (state.HasFlagCustom(XModifierMask.Button3Mask)) rv |= RawInputModifiers.MiddleMouseButton; - if (state.HasFlag(XModifierMask.Button4Mask)) + if (state.HasFlagCustom(XModifierMask.Button4Mask)) rv |= RawInputModifiers.XButton1MouseButton; - if (state.HasFlag(XModifierMask.Button5Mask)) + if (state.HasFlagCustom(XModifierMask.Button5Mask)) rv |= RawInputModifiers.XButton2MouseButton; - if (state.HasFlag(XModifierMask.ShiftMask)) + if (state.HasFlagCustom(XModifierMask.ShiftMask)) rv |= RawInputModifiers.Shift; - if (state.HasFlag(XModifierMask.ControlMask)) + if (state.HasFlagCustom(XModifierMask.ControlMask)) rv |= RawInputModifiers.Control; - if (state.HasFlag(XModifierMask.Mod1Mask)) + if (state.HasFlagCustom(XModifierMask.Mod1Mask)) rv |= RawInputModifiers.Alt; - if (state.HasFlag(XModifierMask.Mod4Mask)) + if (state.HasFlagCustom(XModifierMask.Mod4Mask)) rv |= RawInputModifiers.Meta; return rv; } diff --git a/src/Avalonia.X11/XI2Manager.cs b/src/Avalonia.X11/XI2Manager.cs index 8cdf24cc7b..2874c517a9 100644 --- a/src/Avalonia.X11/XI2Manager.cs +++ b/src/Avalonia.X11/XI2Manager.cs @@ -342,13 +342,13 @@ namespace Avalonia.X11 Type = ev->evtype; Timestamp = (ulong)ev->time.ToInt64(); var state = (XModifierMask)ev->mods.Effective; - if (state.HasFlag(XModifierMask.ShiftMask)) + if (state.HasFlagCustom(XModifierMask.ShiftMask)) Modifiers |= RawInputModifiers.Shift; - if (state.HasFlag(XModifierMask.ControlMask)) + if (state.HasFlagCustom(XModifierMask.ControlMask)) Modifiers |= RawInputModifiers.Control; - if (state.HasFlag(XModifierMask.Mod1Mask)) + if (state.HasFlagCustom(XModifierMask.Mod1Mask)) Modifiers |= RawInputModifiers.Alt; - if (state.HasFlag(XModifierMask.Mod4Mask)) + if (state.HasFlagCustom(XModifierMask.Mod4Mask)) Modifiers |= RawInputModifiers.Meta; Modifiers |= ParseButtonState(ev->buttons.MaskLen, ev->buttons.Mask); @@ -364,7 +364,7 @@ namespace Avalonia.X11 if (Type == XiEventType.XI_ButtonPress || Type == XiEventType.XI_ButtonRelease) Button = ev->detail; Detail = ev->detail; - Emulated = ev->flags.HasFlag(XiDeviceEventFlags.XIPointerEmulated); + Emulated = ev->flags.HasFlagCustom(XiDeviceEventFlags.XIPointerEmulated); } } diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmBindings.cs b/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmBindings.cs index b5ebc4bcb7..34cc261187 100644 --- a/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmBindings.cs +++ b/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmBindings.cs @@ -54,7 +54,7 @@ namespace Avalonia.LinuxFramebuffer.Output } public PixelSize Resolution => new PixelSize(Mode.hdisplay, Mode.vdisplay); - public bool IsPreferred => Mode.type.HasFlag(DrmModeType.DRM_MODE_TYPE_PREFERRED); + public bool IsPreferred => Mode.type.HasFlagCustom(DrmModeType.DRM_MODE_TYPE_PREFERRED); public string Name { get; } } diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs index 3bb29f4e23..7d86116f38 100644 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs +++ b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs @@ -147,13 +147,13 @@ namespace Avalonia.Win32.Interop.Wpf { var state = Keyboard.Modifiers; var rv = default(RawInputModifiers); - if (state.HasFlag(ModifierKeys.Windows)) + if (state.HasFlagCustom(ModifierKeys.Windows)) rv |= RawInputModifiers.Meta; - if (state.HasFlag(ModifierKeys.Alt)) + if (state.HasFlagCustom(ModifierKeys.Alt)) rv |= RawInputModifiers.Alt; - if (state.HasFlag(ModifierKeys.Control)) + if (state.HasFlagCustom(ModifierKeys.Control)) rv |= RawInputModifiers.Control; - if (state.HasFlag(ModifierKeys.Shift)) + if (state.HasFlagCustom(ModifierKeys.Shift)) rv |= RawInputModifiers.Shift; if (e != null) { diff --git a/src/Windows/Avalonia.Win32/DataObject.cs b/src/Windows/Avalonia.Win32/DataObject.cs index 6c1b4ef5d9..5f02796d30 100644 --- a/src/Windows/Avalonia.Win32/DataObject.cs +++ b/src/Windows/Avalonia.Win32/DataObject.cs @@ -181,7 +181,7 @@ namespace Avalonia.Win32 ole.GetData(ref format, out medium); return; } - if(!format.tymed.HasFlag(TYMED.TYMED_HGLOBAL)) + if(!format.tymed.HasFlagCustom(TYMED.TYMED_HGLOBAL)) Marshal.ThrowExceptionForHR(DV_E_TYMED); if (format.dwAspect != DVASPECT.DVASPECT_CONTENT) @@ -205,7 +205,7 @@ namespace Avalonia.Win32 return; } - if (medium.tymed != TYMED.TYMED_HGLOBAL || !format.tymed.HasFlag(TYMED.TYMED_HGLOBAL)) + if (medium.tymed != TYMED.TYMED_HGLOBAL || !format.tymed.HasFlagCustom(TYMED.TYMED_HGLOBAL)) Marshal.ThrowExceptionForHR(DV_E_TYMED); if (format.dwAspect != DVASPECT.DVASPECT_CONTENT) @@ -228,7 +228,7 @@ namespace Avalonia.Win32 return ole.QueryGetData(ref format); if (format.dwAspect != DVASPECT.DVASPECT_CONTENT) return DV_E_DVASPECT; - if (!format.tymed.HasFlag(TYMED.TYMED_HGLOBAL)) + if (!format.tymed.HasFlagCustom(TYMED.TYMED_HGLOBAL)) return DV_E_TYMED; string dataFormat = ClipboardFormats.GetFormat(format.cfFormat); diff --git a/src/Windows/Avalonia.Win32/OleDropTarget.cs b/src/Windows/Avalonia.Win32/OleDropTarget.cs index 37d047689c..d038e341b8 100644 --- a/src/Windows/Avalonia.Win32/OleDropTarget.cs +++ b/src/Windows/Avalonia.Win32/OleDropTarget.cs @@ -24,11 +24,11 @@ namespace Avalonia.Win32 public static DropEffect ConvertDropEffect(DragDropEffects operation) { DropEffect result = DropEffect.None; - if (operation.HasFlag(DragDropEffects.Copy)) + if (operation.HasFlagCustom(DragDropEffects.Copy)) result |= DropEffect.Copy; - if (operation.HasFlag(DragDropEffects.Move)) + if (operation.HasFlagCustom(DragDropEffects.Move)) result |= DropEffect.Move; - if (operation.HasFlag(DragDropEffects.Link)) + if (operation.HasFlagCustom(DragDropEffects.Link)) result |= DropEffect.Link; return result; } @@ -36,11 +36,11 @@ namespace Avalonia.Win32 public static DragDropEffects ConvertDropEffect(DropEffect effect) { DragDropEffects result = DragDropEffects.None; - if (effect.HasFlag(DropEffect.Copy)) + if (effect.HasFlagCustom(DropEffect.Copy)) result |= DragDropEffects.Copy; - if (effect.HasFlag(DropEffect.Move)) + if (effect.HasFlagCustom(DropEffect.Move)) result |= DragDropEffects.Move; - if (effect.HasFlag(DropEffect.Link)) + if (effect.HasFlagCustom(DropEffect.Link)) result |= DragDropEffects.Link; return result; } @@ -50,17 +50,17 @@ namespace Avalonia.Win32 var modifiers = RawInputModifiers.None; var state = (UnmanagedMethods.ModifierKeys)grfKeyState; - if (state.HasFlag(UnmanagedMethods.ModifierKeys.MK_LBUTTON)) + if (state.HasFlagCustom(UnmanagedMethods.ModifierKeys.MK_LBUTTON)) modifiers |= RawInputModifiers.LeftMouseButton; - if (state.HasFlag(UnmanagedMethods.ModifierKeys.MK_MBUTTON)) + if (state.HasFlagCustom(UnmanagedMethods.ModifierKeys.MK_MBUTTON)) modifiers |= RawInputModifiers.MiddleMouseButton; - if (state.HasFlag(UnmanagedMethods.ModifierKeys.MK_RBUTTON)) + if (state.HasFlagCustom(UnmanagedMethods.ModifierKeys.MK_RBUTTON)) modifiers |= RawInputModifiers.RightMouseButton; - if (state.HasFlag(UnmanagedMethods.ModifierKeys.MK_SHIFT)) + if (state.HasFlagCustom(UnmanagedMethods.ModifierKeys.MK_SHIFT)) modifiers |= RawInputModifiers.Shift; - if (state.HasFlag(UnmanagedMethods.ModifierKeys.MK_CONTROL)) + if (state.HasFlagCustom(UnmanagedMethods.ModifierKeys.MK_CONTROL)) modifiers |= RawInputModifiers.Control; - if (state.HasFlag(UnmanagedMethods.ModifierKeys.MK_ALT)) + if (state.HasFlagCustom(UnmanagedMethods.ModifierKeys.MK_ALT)) modifiers |= RawInputModifiers.Alt; return modifiers; } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.CustomCaptionProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.CustomCaptionProc.cs index 68bd40da79..0a8648aa9a 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.CustomCaptionProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.CustomCaptionProc.cs @@ -23,13 +23,13 @@ namespace Avalonia.Win32 AdjustWindowRectEx(ref rcFrame, (uint)(WindowStyles.WS_OVERLAPPEDWINDOW & ~WindowStyles.WS_CAPTION), false, 0); var borderThickness = new RECT(); - if (GetStyle().HasFlag(WindowStyles.WS_THICKFRAME)) + if (GetStyle().HasFlagCustom(WindowStyles.WS_THICKFRAME)) { AdjustWindowRectEx(ref borderThickness, (uint)(GetStyle()), false, 0); borderThickness.left *= -1; borderThickness.top *= -1; } - else if (GetStyle().HasFlag(WindowStyles.WS_BORDER)) + else if (GetStyle().HasFlagCustom(WindowStyles.WS_BORDER)) { borderThickness = new RECT { bottom = 1, left = 1, right = 1, top = 1 }; } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 5e67c0d7f3..2f980cfe86 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -836,7 +836,7 @@ namespace Avalonia.Win32 borderCaptionThickness.left *= -1; borderCaptionThickness.top *= -1; - bool wantsTitleBar = _extendChromeHints.HasFlag(ExtendClientAreaChromeHints.SystemChrome) || _extendTitleBarHint == -1; + bool wantsTitleBar = _extendChromeHints.HasFlagCustom(ExtendClientAreaChromeHints.SystemChrome) || _extendTitleBarHint == -1; if (!wantsTitleBar) { @@ -853,7 +853,7 @@ namespace Avalonia.Win32 borderCaptionThickness.top = (int)(_extendTitleBarHint * RenderScaling); } - margins.cyTopHeight = _extendChromeHints.HasFlag(ExtendClientAreaChromeHints.SystemChrome) && !_extendChromeHints.HasFlag(ExtendClientAreaChromeHints.PreferSystemChrome) ? borderCaptionThickness.top : 1; + margins.cyTopHeight = _extendChromeHints.HasFlagCustom(ExtendClientAreaChromeHints.SystemChrome) && !_extendChromeHints.HasFlagCustom(ExtendClientAreaChromeHints.PreferSystemChrome) ? borderCaptionThickness.top : 1; if (WindowState == WindowState.Maximized) { @@ -901,8 +901,8 @@ namespace Avalonia.Win32 _extendedMargins = new Thickness(); } - if(!_isClientAreaExtended || (_extendChromeHints.HasFlag(ExtendClientAreaChromeHints.SystemChrome) && - !_extendChromeHints.HasFlag(ExtendClientAreaChromeHints.PreferSystemChrome))) + if(!_isClientAreaExtended || (_extendChromeHints.HasFlagCustom(ExtendClientAreaChromeHints.SystemChrome) && + !_extendChromeHints.HasFlagCustom(ExtendClientAreaChromeHints.PreferSystemChrome))) { EnableCloseButton(_hwnd); } @@ -1239,7 +1239,7 @@ namespace Avalonia.Win32 public Action ExtendClientAreaToDecorationsChanged { get; set; } /// - public bool NeedsManagedDecorations => _isClientAreaExtended && _extendChromeHints.HasFlag(ExtendClientAreaChromeHints.PreferSystemChrome); + public bool NeedsManagedDecorations => _isClientAreaExtended && _extendChromeHints.HasFlagCustom(ExtendClientAreaChromeHints.PreferSystemChrome); /// public Thickness ExtendedMargins => _extendedMargins; From 4003b1e40d2c17bb51ed48c58189da0dc33d8817 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 15 Feb 2021 13:37:26 +0100 Subject: [PATCH 07/16] Pass clicked control as placement target. Moved the implementation of `ContextMenu.Open` into a private method that accepts a control and a placement target. When calling `Open` due to a right-click in `ControlPointerReleased`, call this method with the clicked control as the placement target. Fixes #5101 --- src/Avalonia.Controls/ContextMenu.cs | 77 ++++++++++++++-------------- 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/src/Avalonia.Controls/ContextMenu.cs b/src/Avalonia.Controls/ContextMenu.cs index fb8080f0d4..bf8db9a4ec 100644 --- a/src/Avalonia.Controls/ContextMenu.cs +++ b/src/Avalonia.Controls/ContextMenu.cs @@ -269,7 +269,43 @@ namespace Avalonia.Controls } control ??= _attachedControls![0]; + Open(control, control); + } + + /// + /// Closes the menu. + /// + public override void Close() + { + if (!IsOpen) + { + return; + } + if (_popup != null && _popup.IsVisible) + { + _popup.IsOpen = false; + } + } + + void ISetterValue.Initialize(ISetter setter) + { + // ContextMenu can be assigned to the ContextMenu property in a setter. This overrides + // the behavior defined in Control which requires controls to be wrapped in a