From b85bba7d2dbb912cfa88cc9b1bd3ace7ce775cb3 Mon Sep 17 00:00:00 2001 From: Giuseppe Lippolis Date: Wed, 30 Jun 2021 18:51:18 +0200 Subject: [PATCH 01/11] fixes: Dialog cancel consistency on windows --- src/Windows/Avalonia.Win32/SystemDialogImpl.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Windows/Avalonia.Win32/SystemDialogImpl.cs b/src/Windows/Avalonia.Win32/SystemDialogImpl.cs index ad81cc1778..f595a58c91 100644 --- a/src/Windows/Avalonia.Win32/SystemDialogImpl.cs +++ b/src/Windows/Avalonia.Win32/SystemDialogImpl.cs @@ -19,7 +19,7 @@ namespace Avalonia.Win32 var hWnd = parent?.PlatformImpl?.Handle?.Handle ?? IntPtr.Zero; return Task.Factory.StartNew(() => { - var result = Array.Empty(); + string[] result = default; Guid clsid = dialog is OpenFileDialog ? UnmanagedMethods.ShellIds.OpenFileDialog : UnmanagedMethods.ShellIds.SaveFileDialog; Guid iid = UnmanagedMethods.ShellIds.IFileDialog; @@ -100,7 +100,7 @@ namespace Avalonia.Win32 { return Task.Factory.StartNew(() => { - string result = string.Empty; + string result = default; var hWnd = parent?.PlatformImpl?.Handle?.Handle ?? IntPtr.Zero; Guid clsid = UnmanagedMethods.ShellIds.OpenFileDialog; @@ -164,7 +164,7 @@ namespace Avalonia.Win32 } } } - return ""; + return default; } } } From 5df9e5760c8eb76dd6f3b49db77635b4eb3d4619 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 24 Aug 2021 14:04:40 +0200 Subject: [PATCH 02/11] Add #nullable and XML doc comments to system dialogs. --- src/Avalonia.Controls/SystemDialog.cs | 99 ++++++++++++++++++++++++--- 1 file changed, 89 insertions(+), 10 deletions(-) diff --git a/src/Avalonia.Controls/SystemDialog.cs b/src/Avalonia.Controls/SystemDialog.cs index e74b950f23..d81926ecc7 100644 --- a/src/Avalonia.Controls/SystemDialog.cs +++ b/src/Avalonia.Controls/SystemDialog.cs @@ -4,30 +4,65 @@ using System.Linq; using System.Threading.Tasks; using Avalonia.Controls.Platform; +#nullable enable + namespace Avalonia.Controls { + /// + /// Base class for system file dialogs. + /// public abstract class FileDialog : FileSystemDialog { + /// + /// Gets or sets a collection of filters which determine the types of files displayed in an + /// or an . + /// public List Filters { get; set; } = new List(); - public string InitialFileName { get; set; } + + /// + /// Gets or sets initial file name that is displayed when the dialog is opened. + /// + public string? InitialFileName { get; set; } } + /// + /// Base class for system file and directory dialogs. + /// public abstract class FileSystemDialog : SystemDialog { [Obsolete("Use Directory")] - public string InitialDirectory + public string? InitialDirectory { get => Directory; set => Directory = value; } - public string Directory { get; set; } + + /// + /// Gets or sets the initial directory that will be displayed when the file system dialog + /// is opened. + /// + public string? Directory { get; set; } } + /// + /// Represents a system dialog that prompts the user to select a location for saving a file. + /// public class SaveFileDialog : FileDialog { - public string DefaultExtension { get; set; } + /// + /// Gets or sets the default extension to be used to save the file (including the period "."). + /// + public string? DefaultExtension { get; set; } - public async Task ShowAsync(Window parent) + /// + /// Shows the save file dialog. + /// + /// The parent window. + /// + /// A task that on completion contains the full path of the save location, or null if the + /// dialog was canceled. + /// + public async Task ShowAsync(Window parent) { if(parent == null) throw new ArgumentNullException(nameof(parent)); @@ -37,11 +72,25 @@ namespace Avalonia.Controls } } + /// + /// Represents a system dialog that allows the user to select one or more files to open. + /// public class OpenFileDialog : FileDialog { + /// + /// Gets or sets a value indicating whether the user can select multiple files. + /// public bool AllowMultiple { get; set; } - public Task ShowAsync(Window parent) + /// + /// Shows the open file dialog. + /// + /// The parent window. + /// + /// A task that on completion returns an array containing the full path to the selected + /// files, or null if the dialog was canceled. + /// + public Task ShowAsync(Window parent) { if(parent == null) throw new ArgumentNullException(nameof(parent)); @@ -49,15 +98,27 @@ namespace Avalonia.Controls } } + /// + /// Represents a system dialog that allows the user to select a directory. + /// public class OpenFolderDialog : FileSystemDialog { [Obsolete("Use Directory")] - public string DefaultDirectory + public string? DefaultDirectory { get => Directory; set => Directory = value; } - public Task ShowAsync(Window parent) + + /// + /// Shows the open folder dialog. + /// + /// The parent window. + /// + /// A task that on completion returns the full path of the selected directory, or null if the + /// dialog was canceled. + /// + public Task ShowAsync(Window parent) { if(parent == null) throw new ArgumentNullException(nameof(parent)); @@ -65,14 +126,32 @@ namespace Avalonia.Controls } } + + /// + /// Base class for system dialogs. + /// public abstract class SystemDialog { - public string Title { get; set; } + /// + /// Gets or sets the dialog title. + /// + public string? Title { get; set; } } + /// + /// Represents a filter in an or an . + /// public class FileDialogFilter { - public string Name { get; set; } + /// + /// Gets or sets the name of the filter, e.g. ("Text files (.txt)"). + /// + public string? Name { get; set; } + + /// + /// Gets or sets a list of file extensions matched by the filter (e.g. "txt" or "*" for all + /// files). + /// public List Extensions { get; set; } = new List(); } } From 1a95905efe9a3c00f712c0e68c9fefaceb23103e Mon Sep 17 00:00:00 2001 From: Sergey Mikolaytis Date: Wed, 25 Aug 2021 03:37:06 +0300 Subject: [PATCH 03/11] [Menu] [Interaction] Allow end user to change menu show delay globally (#6392) Co-authored-by: Max Katz --- src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs b/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs index 984faa4d60..209feb351c 100644 --- a/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs +++ b/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs @@ -115,7 +115,7 @@ namespace Avalonia.Controls.Platform protected IMenu? Menu { get; private set; } - protected static TimeSpan MenuShowDelay { get; } = TimeSpan.FromMilliseconds(400); + public static TimeSpan MenuShowDelay { get; set; } = TimeSpan.FromMilliseconds(400); protected internal virtual void GotFocus(object sender, GotFocusEventArgs e) { From dcc033f8197dd857ab8b02faef5ce81f3873fb37 Mon Sep 17 00:00:00 2001 From: kaminova <45092470+kaminova@users.noreply.github.com> Date: Wed, 25 Aug 2021 04:13:54 +0200 Subject: [PATCH 04/11] Close popup if combobox is not visible (#6404) * Close popup if combobox is not visible * fix unsupported feature Co-authored-by: kaminova Co-authored-by: Max Katz --- src/Avalonia.Controls/ComboBox.cs | 30 ++++++++++---- .../Mixins/DisposableMixin.cs | 38 +++++++++++++++++ src/Avalonia.Controls/Primitives/Popup.cs | 41 ++++++++----------- 3 files changed, 77 insertions(+), 32 deletions(-) create mode 100644 src/Avalonia.Controls/Mixins/DisposableMixin.cs diff --git a/src/Avalonia.Controls/ComboBox.cs b/src/Avalonia.Controls/ComboBox.cs index 57c07916db..274696d501 100644 --- a/src/Avalonia.Controls/ComboBox.cs +++ b/src/Avalonia.Controls/ComboBox.cs @@ -1,6 +1,8 @@ using System; using System.Linq; +using System.Reactive.Disposables; using Avalonia.Controls.Generators; +using Avalonia.Controls.Mixins; using Avalonia.Controls.Presenters; using Avalonia.Controls.Primitives; using Avalonia.Controls.Shapes; @@ -80,7 +82,7 @@ namespace Avalonia.Controls private bool _isDropDownOpen; private Popup _popup; private object _selectionBoxItem; - private IDisposable _subscriptionsOnOpen; + private readonly CompositeDisposable _subscriptionsOnOpen = new CompositeDisposable(); /// /// Initializes static members of the class. @@ -291,6 +293,7 @@ namespace Avalonia.Controls _popup = e.NameScope.Get("PART_Popup"); _popup.Opened += PopupOpened; + _popup.Closed += PopupClosed; } internal void ItemFocused(ComboBoxItem dropDownItem) @@ -303,8 +306,7 @@ namespace Avalonia.Controls private void PopupClosed(object sender, EventArgs e) { - _subscriptionsOnOpen?.Dispose(); - _subscriptionsOnOpen = null; + _subscriptionsOnOpen.Clear(); if (CanFocus(this)) { @@ -316,20 +318,34 @@ namespace Avalonia.Controls { TryFocusSelectedItem(); - _subscriptionsOnOpen?.Dispose(); - _subscriptionsOnOpen = null; + _subscriptionsOnOpen.Clear(); var toplevel = this.GetVisualRoot() as TopLevel; if (toplevel != null) { - _subscriptionsOnOpen = toplevel.AddDisposableHandler(PointerWheelChangedEvent, (s, ev) => + toplevel.AddDisposableHandler(PointerWheelChangedEvent, (s, ev) => { //eat wheel scroll event outside dropdown popup while it's open if (IsDropDownOpen && (ev.Source as IVisual).GetVisualRoot() == toplevel) { ev.Handled = true; } - }, Interactivity.RoutingStrategies.Tunnel); + }, Interactivity.RoutingStrategies.Tunnel).DisposeWith(_subscriptionsOnOpen); + } + + this.GetObservable(IsVisibleProperty).Subscribe(IsVisibleChanged).DisposeWith(_subscriptionsOnOpen); + + foreach (var parent in this.GetVisualAncestors().OfType()) + { + parent.GetObservable(IsVisibleProperty).Subscribe(IsVisibleChanged).DisposeWith(_subscriptionsOnOpen); + } + } + + private void IsVisibleChanged(bool isVisible) + { + if (!isVisible && IsDropDownOpen) + { + IsDropDownOpen = false; } } diff --git a/src/Avalonia.Controls/Mixins/DisposableMixin.cs b/src/Avalonia.Controls/Mixins/DisposableMixin.cs new file mode 100644 index 0000000000..9b30b4ba4c --- /dev/null +++ b/src/Avalonia.Controls/Mixins/DisposableMixin.cs @@ -0,0 +1,38 @@ +using System; +using System.Reactive.Disposables; + +namespace Avalonia.Controls.Mixins +{ + /// + /// Extension methods associated with the IDisposable interface. + /// + public static class DisposableMixin + { + /// + /// Ensures the provided disposable is disposed with the specified . + /// + /// + /// The type of the disposable. + /// + /// + /// The disposable we are going to want to be disposed by the CompositeDisposable. + /// + /// + /// The to which will be added. + /// + /// + /// The disposable. + /// + public static T DisposeWith(this T item, CompositeDisposable compositeDisposable) + where T : IDisposable + { + if (compositeDisposable is null) + { + throw new ArgumentNullException(nameof(compositeDisposable)); + } + + compositeDisposable.Add(item); + return item; + } + } +} diff --git a/src/Avalonia.Controls/Primitives/Popup.cs b/src/Avalonia.Controls/Primitives/Popup.cs index d5fb69a672..e804c4b4a9 100644 --- a/src/Avalonia.Controls/Primitives/Popup.cs +++ b/src/Avalonia.Controls/Primitives/Popup.cs @@ -2,6 +2,7 @@ using System; using System.ComponentModel; using System.Linq; using System.Reactive.Disposables; +using Avalonia.Controls.Mixins; using Avalonia.Controls.Diagnostics; using Avalonia.Controls.Presenters; using Avalonia.Controls.Primitives.PopupPositioning; @@ -393,18 +394,8 @@ namespace Avalonia.Controls.Primitives var handlerCleanup = new CompositeDisposable(5); - void DeferCleanup(IDisposable? disposable) - { - if (disposable is null) - { - return; - } - - handlerCleanup.Add(disposable); - } - - DeferCleanup(popupHost.BindConstraints(this, WidthProperty, MinWidthProperty, MaxWidthProperty, - HeightProperty, MinHeightProperty, MaxHeightProperty, TopmostProperty)); + popupHost.BindConstraints(this, WidthProperty, MinWidthProperty, MaxWidthProperty, + HeightProperty, MinHeightProperty, MaxHeightProperty, TopmostProperty).DisposeWith(handlerCleanup); popupHost.SetChild(Child); ((ISetLogicalParent)popupHost).SetParent(this); @@ -418,19 +409,19 @@ namespace Avalonia.Controls.Primitives PlacementConstraintAdjustment, PlacementRect); - DeferCleanup(SubscribeToEventHandler>(popupHost, RootTemplateApplied, + SubscribeToEventHandler>(popupHost, RootTemplateApplied, (x, handler) => x.TemplateApplied += handler, - (x, handler) => x.TemplateApplied -= handler)); + (x, handler) => x.TemplateApplied -= handler).DisposeWith(handlerCleanup); if (topLevel is Window window) { - DeferCleanup(SubscribeToEventHandler(window, WindowDeactivated, + SubscribeToEventHandler(window, WindowDeactivated, (x, handler) => x.Deactivated += handler, - (x, handler) => x.Deactivated -= handler)); + (x, handler) => x.Deactivated -= handler).DisposeWith(handlerCleanup); - DeferCleanup(SubscribeToEventHandler(window.PlatformImpl, WindowLostFocus, + SubscribeToEventHandler(window.PlatformImpl, WindowLostFocus, (x, handler) => x.LostFocus += handler, - (x, handler) => x.LostFocus -= handler)); + (x, handler) => x.LostFocus -= handler).DisposeWith(handlerCleanup); } else { @@ -438,13 +429,13 @@ namespace Avalonia.Controls.Primitives if (parentPopupRoot?.Parent is Popup popup) { - DeferCleanup(SubscribeToEventHandler>(popup, ParentClosed, + SubscribeToEventHandler>(popup, ParentClosed, (x, handler) => x.Closed += handler, - (x, handler) => x.Closed -= handler)); + (x, handler) => x.Closed -= handler).DisposeWith(handlerCleanup); } } - DeferCleanup(InputManager.Instance?.Process.Subscribe(ListenForNonClientClick)); + InputManager.Instance?.Process.Subscribe(ListenForNonClientClick).DisposeWith(handlerCleanup); var cleanupPopup = Disposable.Create((popupHost, handlerCleanup), state => { @@ -466,17 +457,17 @@ namespace Avalonia.Controls.Primitives dismissLayer.IsVisible = true; dismissLayer.InputPassThroughElement = _overlayInputPassThroughElement; - DeferCleanup(Disposable.Create(() => + Disposable.Create(() => { dismissLayer.IsVisible = false; dismissLayer.InputPassThroughElement = null; - })); + }).DisposeWith(handlerCleanup); - DeferCleanup(SubscribeToEventHandler>( + SubscribeToEventHandler>( dismissLayer, PointerPressedDismissOverlay, (x, handler) => x.PointerPressed += handler, - (x, handler) => x.PointerPressed -= handler)); + (x, handler) => x.PointerPressed -= handler).DisposeWith(handlerCleanup); } } From cd80536d58834f52e6b2746463dbb2b9c0cc4759 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 25 Aug 2021 18:21:34 +0200 Subject: [PATCH 05/11] Added failing test for #6439. --- .../KeyboardNavigationTests_Tab.cs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/Avalonia.Input.UnitTests/KeyboardNavigationTests_Tab.cs b/tests/Avalonia.Input.UnitTests/KeyboardNavigationTests_Tab.cs index edcbf75a1d..9a117bb71d 100644 --- a/tests/Avalonia.Input.UnitTests/KeyboardNavigationTests_Tab.cs +++ b/tests/Avalonia.Input.UnitTests/KeyboardNavigationTests_Tab.cs @@ -1225,5 +1225,32 @@ namespace Avalonia.Input.UnitTests "Button2", "Button3", "Button5", "Button1", "Button6", "Button4" }, result); } + + [Fact] + public void Cannot_Focus_Child_Of_Disabled_Control() + { + Button start; + Button expected; + + var top = new StackPanel + { + [KeyboardNavigation.TabNavigationProperty] = KeyboardNavigationMode.Cycle, + Children = + { + (start = new Button { Name = "Button1" }), + new Border + { + IsEnabled = false, + Child = new Button { Name = "Button2" }, + }, + (expected = new Button { Name = "Button3" }), + } + }; + + var current = (IInputElement)start; + var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Next); + + Assert.Same(expected, result); + } } } From 341e435321df26178dcaddfea768eaaa65a8b4d6 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 25 Aug 2021 19:10:18 +0200 Subject: [PATCH 06/11] Check enabled state as well as visibility. WPF and Avalonia's `IsEnabled` properties are slightly different. In WPF if reflects both the enabled state of the actual control and the effectively enabled state which comes from ancestor controls. In Avalonia that effectively enabled state is exposed on a different property: `IsEffectivelyEnabled`. When I ported the tab navigation code from WPF, I didn't take that into account. WPF's visibility property however doesn't reflect the state of a control's owners and so tab navigation for invisible controls works correctly. Take advantage of this fact by changing any checks for `IsVisible` to also check `IsEnabled`. --- src/Avalonia.Input/Navigation/TabNavigation.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Avalonia.Input/Navigation/TabNavigation.cs b/src/Avalonia.Input/Navigation/TabNavigation.cs index ed7df67bf2..c8290cb3b7 100644 --- a/src/Avalonia.Input/Navigation/TabNavigation.cs +++ b/src/Avalonia.Input/Navigation/TabNavigation.cs @@ -234,7 +234,7 @@ namespace Avalonia.Input.Navigation // Return the first visible element. var uiElement = e as InputElement; - if (uiElement is null || uiElement.IsVisible) + if (uiElement is null || IsVisibleAndEnabled(uiElement)) { if (e is IVisual elementAsVisual) { @@ -245,7 +245,7 @@ namespace Avalonia.Input.Navigation { if (children[i] is InputElement ie) { - if (ie.IsVisible) + if (IsVisibleAndEnabled(ie)) return ie; else { @@ -270,7 +270,7 @@ namespace Avalonia.Input.Navigation // Return the last visible element. var uiElement = e as InputElement; - if (uiElement == null || uiElement.IsVisible) + if (uiElement == null || IsVisibleAndEnabled(uiElement)) { var elementAsVisual = e as IVisual; @@ -283,7 +283,7 @@ namespace Avalonia.Input.Navigation { if (children[i] is InputElement ie) { - if (ie.IsVisible) + if (IsVisibleAndEnabled(ie)) return ie; else { @@ -600,7 +600,7 @@ namespace Avalonia.Input.Navigation var vchild = children[i]; if (vchild == elementAsVisual) break; - if (vchild.IsVisible == true && vchild is IInputElement ie) + if (vchild is IInputElement ie && IsVisibleAndEnabled(ie)) prev = ie; } return prev; @@ -668,5 +668,6 @@ namespace Avalonia.Input.Navigation } private static bool IsTabStopOrGroup(IInputElement e) => IsTabStop(e) || IsGroup(e); + private static bool IsVisibleAndEnabled(IInputElement e) => e.IsVisible && e.IsEnabled; } } From 8dbf3bf86e2ecdb3432a18ad02ab4c45189f37d2 Mon Sep 17 00:00:00 2001 From: Giuseppe Lippolis Date: Thu, 26 Aug 2021 17:57:35 +0200 Subject: [PATCH 07/11] fixes(Win32.Interop): field 'Direct2DImageSurface._oldDpi' is never assigned to, and will always have its default value --- src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs index 5b04c5d7ff..bc0a399d7f 100644 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs +++ b/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs @@ -150,6 +150,7 @@ namespace Avalonia.Win32.Interop.Wpf if (_image == null || _oldDpi.X != dpi.X || _oldDpi.Y != dpi.Y) { _image = new D3DImage(dpi.X, dpi.Y); + _oldDpi = dpi; } _impl.ImageSource = _image; From 3867a68ade09cd12910afc5256e7b73c05703571 Mon Sep 17 00:00:00 2001 From: Tako <53405089+Takoooooo@users.noreply.github.com> Date: Thu, 26 Aug 2021 22:07:58 +0300 Subject: [PATCH 08/11] Fix EntryPointNotFound on Windows 8 due to missing version check (#6471) * Prevent calls to unavailable entrypoint 'GetDpiForMonitor' on Win8 (#5357) * Introduce Windows8 platform constant * wip Co-authored-by: Tim Schneeberger Co-authored-by: Tim Schneeberger Co-authored-by: Dan Walmsley --- src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj | 1 + src/Windows/Avalonia.Direct2D1/HwndRenderTarget.cs | 3 ++- src/Windows/Avalonia.Win32/FramebufferManager.cs | 2 +- src/Windows/Avalonia.Win32/PlatformConstants.cs | 7 ++++++- src/Windows/Avalonia.Win32/Win32GlManager.cs | 4 +--- src/Windows/Avalonia.Win32/Win32Platform.cs | 2 +- src/Windows/Avalonia.Win32/WindowImpl.cs | 4 ++-- 7 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj b/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj index cda95d2ebb..8533e1e176 100644 --- a/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj +++ b/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj @@ -12,6 +12,7 @@ + diff --git a/src/Windows/Avalonia.Direct2D1/HwndRenderTarget.cs b/src/Windows/Avalonia.Direct2D1/HwndRenderTarget.cs index 589f85f208..0597e88ed6 100644 --- a/src/Windows/Avalonia.Direct2D1/HwndRenderTarget.cs +++ b/src/Windows/Avalonia.Direct2D1/HwndRenderTarget.cs @@ -1,4 +1,5 @@ using Avalonia.Platform; +using Avalonia.Win32; using Avalonia.Win32.Interop; using SharpDX; using SharpDX.DXGI; @@ -21,7 +22,7 @@ namespace Avalonia.Direct2D1 protected override Size2F GetWindowDpi() { - if (UnmanagedMethods.ShCoreAvailable) + if (UnmanagedMethods.ShCoreAvailable && Win32Platform.WindowsVersion > PlatformConstants.Windows8) { uint dpix, dpiy; diff --git a/src/Windows/Avalonia.Win32/FramebufferManager.cs b/src/Windows/Avalonia.Win32/FramebufferManager.cs index 699dc7c25d..0240ac9701 100644 --- a/src/Windows/Avalonia.Win32/FramebufferManager.cs +++ b/src/Windows/Avalonia.Win32/FramebufferManager.cs @@ -87,7 +87,7 @@ namespace Avalonia.Win32 private Vector GetCurrentDpi() { - if (UnmanagedMethods.ShCoreAvailable) + if (UnmanagedMethods.ShCoreAvailable && Win32Platform.WindowsVersion > PlatformConstants.Windows8) { var monitor = UnmanagedMethods.MonitorFromWindow(_hwnd, UnmanagedMethods.MONITOR.MONITOR_DEFAULTTONEAREST); diff --git a/src/Windows/Avalonia.Win32/PlatformConstants.cs b/src/Windows/Avalonia.Win32/PlatformConstants.cs index af1eca29be..9dd4780637 100644 --- a/src/Windows/Avalonia.Win32/PlatformConstants.cs +++ b/src/Windows/Avalonia.Win32/PlatformConstants.cs @@ -1,8 +1,13 @@ +using System; + namespace Avalonia.Win32 { - static class PlatformConstants + public static class PlatformConstants { public const string WindowHandleType = "HWND"; public const string CursorHandleType = "HCURSOR"; + + public static readonly Version Windows8 = new Version(6, 2); + public static readonly Version Windows7 = new Version(6, 1); } } diff --git a/src/Windows/Avalonia.Win32/Win32GlManager.cs b/src/Windows/Avalonia.Win32/Win32GlManager.cs index e159ba3b78..e70ea52106 100644 --- a/src/Windows/Avalonia.Win32/Win32GlManager.cs +++ b/src/Windows/Avalonia.Win32/Win32GlManager.cs @@ -1,4 +1,3 @@ -using System; using Avalonia.OpenGL; using Avalonia.OpenGL.Angle; using Avalonia.OpenGL.Egl; @@ -9,7 +8,6 @@ namespace Avalonia.Win32 { static class Win32GlManager { - private static readonly Version Windows7 = new Version(6, 1); public static void Initialize() { @@ -22,7 +20,7 @@ namespace Avalonia.Win32 return wgl; } - if (opts?.AllowEglInitialization ?? Win32Platform.WindowsVersion > Windows7) + if (opts?.AllowEglInitialization ?? Win32Platform.WindowsVersion > PlatformConstants.Windows7) { var egl = EglPlatformOpenGlInterface.TryCreate(() => new AngleWin32EglDisplay()); diff --git a/src/Windows/Avalonia.Win32/Win32Platform.cs b/src/Windows/Avalonia.Win32/Win32Platform.cs index a881c45cd0..c011a458c3 100644 --- a/src/Windows/Avalonia.Win32/Win32Platform.cs +++ b/src/Windows/Avalonia.Win32/Win32Platform.cs @@ -94,7 +94,7 @@ namespace Avalonia namespace Avalonia.Win32 { - class Win32Platform : IPlatformThreadingInterface, IPlatformSettings, IWindowingPlatform, IPlatformIconLoader, IPlatformLifetimeEventsImpl + public class Win32Platform : IPlatformThreadingInterface, IPlatformSettings, IWindowingPlatform, IPlatformIconLoader, IPlatformLifetimeEventsImpl { private static readonly Win32Platform s_instance = new Win32Platform(); private static Thread _uiThread; diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 0b7bd13082..3b7d3efa2f 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -764,8 +764,8 @@ namespace Avalonia.Win32 RegisterTouchWindow(_hwnd, 0); } - if (ShCoreAvailable) - { + if (ShCoreAvailable && Win32Platform.WindowsVersion > PlatformConstants.Windows8) + { var monitor = MonitorFromWindow( _hwnd, MONITOR.MONITOR_DEFAULTTONEAREST); From 8b6f264379637b3b2c0a770327171765e880edc5 Mon Sep 17 00:00:00 2001 From: Giuseppe Lippolis Date: Fri, 27 Aug 2021 15:50:55 +0200 Subject: [PATCH 09/11] ref(test): removed warning CS0105 The using directive for 'System' appeared previously in this namespace --- tests/Avalonia.Controls.UnitTests/Utils/HotKeyManagerTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Avalonia.Controls.UnitTests/Utils/HotKeyManagerTests.cs b/tests/Avalonia.Controls.UnitTests/Utils/HotKeyManagerTests.cs index 2a3db9992c..b0eb694944 100644 --- a/tests/Avalonia.Controls.UnitTests/Utils/HotKeyManagerTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Utils/HotKeyManagerTests.cs @@ -10,7 +10,6 @@ using Avalonia.Styling; using Avalonia.UnitTests; using Moq; using Xunit; -using System; using Avalonia.Input.Raw; using Factory = System.Func, Avalonia.Controls.Window, Avalonia.AvaloniaObject>; From 7d8e6ea75f908f334f4413af18780f7946ac1a9f Mon Sep 17 00:00:00 2001 From: Giuseppe Lippolis Date: Fri, 27 Aug 2021 15:54:33 +0200 Subject: [PATCH 10/11] ref(tests): warning CS0067 The event 'KeyboardDeviceTests.DelegateCommand.CanExecuteChanged' is never used --- tests/Avalonia.Input.UnitTests/KeyboardDeviceTests.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/Avalonia.Input.UnitTests/KeyboardDeviceTests.cs b/tests/Avalonia.Input.UnitTests/KeyboardDeviceTests.cs index 7730cee78c..c354dbe72e 100644 --- a/tests/Avalonia.Input.UnitTests/KeyboardDeviceTests.cs +++ b/tests/Avalonia.Input.UnitTests/KeyboardDeviceTests.cs @@ -2,7 +2,6 @@ using System.Windows.Input; using Avalonia.Controls; using Avalonia.Input.Raw; -using Avalonia.Interactivity; using Avalonia.UnitTests; using Moq; using Xunit; @@ -126,7 +125,7 @@ namespace Avalonia.Input.UnitTests { private readonly Action _action; public DelegateCommand(Action action) => _action = action; - public event EventHandler CanExecuteChanged; + public event EventHandler CanExecuteChanged { add { } remove { } } public bool CanExecute(object parameter) => true; public void Execute(object parameter) => _action(); } From df5250e155410e7cbb238fdc75a9f7ee71816aaf Mon Sep 17 00:00:00 2001 From: Giuseppe Lippolis Date: Fri, 27 Aug 2021 16:16:06 +0200 Subject: [PATCH 11/11] ref(tests): warning CS0067 The event 'TrackingResourceProvider.OwnerChanged' is never used --- .../MarkupExtensions/DynamicResourceExtensionTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/DynamicResourceExtensionTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/DynamicResourceExtensionTests.cs index e7f0230254..592dbfc0d1 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/DynamicResourceExtensionTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/DynamicResourceExtensionTests.cs @@ -923,7 +923,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions public bool HasResources => true; public List RequestedResources { get; } = new List(); - public event EventHandler OwnerChanged; + public event EventHandler OwnerChanged { add { } remove { } } public void AddOwner(IResourceHost owner) => Owner = owner; public void RemoveOwner(IResourceHost owner) => Owner = null;