From 962f2cc8768711e6145f5c189a7025625572e02f Mon Sep 17 00:00:00 2001 From: Poker Date: Tue, 2 Jan 2024 23:35:38 +0800 Subject: [PATCH] Code Quality: Migrate to InputNonClientPointerSource (#14342) --- .../PropertiesPageNavigationParameter.cs | 4 - src/Files.App/Helpers/UI/DragZoneHelper.cs | 180 ++++-------------- .../Storage/Helpers/FilePropertiesHelpers.cs | 1 - .../Properties/MainPropertiesViewModel.cs | 13 +- src/Files.App/Views/MainPage.xaml.cs | 18 +- .../Properties/CustomizationPage.xaml.cs | 4 +- .../Properties/MainPropertiesPage.xaml.cs | 20 +- 7 files changed, 65 insertions(+), 175 deletions(-) diff --git a/src/Files.App/Data/Parameters/PropertiesPageNavigationParameter.cs b/src/Files.App/Data/Parameters/PropertiesPageNavigationParameter.cs index 1bebf59a2565..12818a144f88 100644 --- a/src/Files.App/Data/Parameters/PropertiesPageNavigationParameter.cs +++ b/src/Files.App/Data/Parameters/PropertiesPageNavigationParameter.cs @@ -1,9 +1,7 @@ // Copyright (c) 2023 Files Community // Licensed under the MIT License. See the LICENSE. -using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; -using System.Threading; namespace Files.App.Data.Parameters { @@ -16,7 +14,5 @@ public class PropertiesPageNavigationParameter public IShellPage AppInstance; public Window Window; - - public AppWindow AppWindow; } } diff --git a/src/Files.App/Helpers/UI/DragZoneHelper.cs b/src/Files.App/Helpers/UI/DragZoneHelper.cs index 8f13359a0a20..17b7de41cce0 100644 --- a/src/Files.App/Helpers/UI/DragZoneHelper.cs +++ b/src/Files.App/Helpers/UI/DragZoneHelper.cs @@ -1,169 +1,59 @@ // Copyright (c) 2023 Files Community // Licensed under the MIT License. See the LICENSE. -using System; -using System.Collections.Generic; -using System.Linq; using Windows.Graphics; -using Microsoft.UI; -using Microsoft.UI.Windowing; +using Microsoft.UI.Input; using Microsoft.UI.Xaml; -using WinRT.Interop; namespace Files.App.Helpers { public static class DragZoneHelper { - /// - /// Get Scale Adjustment - /// - /// - /// scale factor percent - public static double GetScaleAdjustment(Window window) => window.Content.XamlRoot.RasterizationScale; + public delegate int SetTitleBarDragRegionDelegate(InputNonClientPointerSource source, SizeInt32 size, double scaleFactor, Func getScaledRect); /// - /// Calculate dragging-zones of title bar
- /// You MUST transform the rectangles with before calling + /// Informs the bearer to refresh the drag region. + /// will not set, , when titleBarHeight less than 0 ///
- /// - /// - /// - /// - /// - public static IEnumerable GetDragZones(int viewportWidth, int dragZoneHeight, int dragZoneLeftIndent, IEnumerable nonDraggingZones) + /// + /// + /// + public static void RaiseSetTitleBarDragRegion(this Window window, SetTitleBarDragRegionDelegate setTitleBarDragRegion) { - var draggingZonesX = new List { new(dragZoneLeftIndent, viewportWidth) }; - var draggingZonesY = new List> { new[] { new Range(0, dragZoneHeight) } }; - - foreach (var nonDraggingZone in nonDraggingZones) - { - for (var i = 0; i < draggingZonesX.Count; ++i) - { - var x = draggingZonesX[i]; - var y = draggingZonesY[i].ToArray(); - var xSubtrahend = new Range(nonDraggingZone.X, nonDraggingZone.X + nonDraggingZone.Width); - var ySubtrahend = new Range(nonDraggingZone.Y, nonDraggingZone.Y + nonDraggingZone.Height); - var xResult = (x - xSubtrahend).ToArray(); - if (xResult.Length is 1 && xResult[0] == x) - continue; - var yResult = (y - ySubtrahend).ToArray(); - switch (xResult.Length) - { - case 0: - draggingZonesY[i] = yResult; - break; - case 1: - draggingZonesX.RemoveAt(i); - draggingZonesY.RemoveAt(i); - if (xResult[0].Lower == x.Lower) - { - draggingZonesY.InsertRange(i, new[] { y, yResult }); - draggingZonesX.InsertRange(i, new[] - { - x with { Upper = xResult[0].Upper }, - x with { Lower = xSubtrahend.Lower } - }); - } - else // xResult[0].Upper == x.Upper - { - draggingZonesY.InsertRange(i, new[] { yResult, y }); - draggingZonesX.InsertRange(i, new[] - { - x with { Upper = xSubtrahend.Upper }, - x with { Lower = xResult[0].Lower } - }); - } - ++i; - break; - case 2: - draggingZonesX.RemoveAt(i); - draggingZonesY.RemoveAt(i); - draggingZonesY.InsertRange(i, new[] { y, yResult, y }); - draggingZonesX.InsertRange(i, new[] - { - x with { Upper = xResult[0].Upper }, - xSubtrahend, - x with { Lower = xResult[1].Lower } - }); - ++i; - ++i; - break; - } - } - } - - var rects = draggingZonesX - .SelectMany((rangeX, i) => draggingZonesY[i] - .Select(rangeY => new RectInt32(rangeX.Lower, rangeY.Lower, rangeX.Distance, rangeY.Distance))) - .OrderBy(t => t.Y) - .ThenBy(t => t.X).ToList(); - for (var i = 0; i < rects.Count - 1; ++i) + if (!window.AppWindow.IsVisible) + return; + // UIElement.RasterizationScale is always 1 + var source = InputNonClientPointerSource.GetForWindowId(window.AppWindow.Id); + var uiElement = window.Content; + var scaleFactor = uiElement.XamlRoot.RasterizationScale; + var size = window.AppWindow.Size; + // If the number of regions is 0 or 1, AppWindow will automatically reset to the default region next time, but if it is >=2, it will not and need to be manually cleared + source.ClearRegionRects(NonClientRegionKind.Passthrough); + var titleBarHeight = setTitleBarDragRegion(source, size, scaleFactor, GetScaledRect); + if (titleBarHeight >= 0) { - var now = rects[i]; - var next = rects[i + 1]; - if (now.Height == next.Height && now.X + now.Width == next.X) - { - rects.RemoveRange(i, 2); - rects.Insert(i, now with { Width = now.Width + next.Width }); - } + // region under the buttons + const int borderThickness = 5; + source.SetRegionRects(NonClientRegionKind.LeftBorder, [GetScaledRect(uiElement, new(0, 0, borderThickness, titleBarHeight))]); + source.SetRegionRects(NonClientRegionKind.RightBorder, [GetScaledRect(uiElement, new(size.Width, 0, borderThickness, titleBarHeight))]); + source.SetRegionRects(NonClientRegionKind.Caption, [GetScaledRect(uiElement, new(0, 0, size.Width, titleBarHeight))]); } - - return rects; } - /// - /// Set dragging-zones of title bar - /// - /// - /// - /// - /// - public static void SetDragZones(Window window, int dragZoneHeight = 40, int dragZoneLeftIndent = 0, IEnumerable? nonDraggingZones = null) + private static RectInt32 GetScaledRect(this UIElement uiElement, RectInt32? r = null) { - var hWnd = WindowNative.GetWindowHandle(window); - var windowId = Win32Interop.GetWindowIdFromWindow(hWnd); - var appWindow = AppWindow.GetFromWindowId(windowId); - var scaleAdjustment = GetScaleAdjustment(window); - var windowWidth = (int)(appWindow.Size.Width / scaleAdjustment); - nonDraggingZones ??= Array.Empty(); -#if DEBUG - // Subtract the toolbar area (center-top in window), only in DEBUG mode. - nonDraggingZones = nonDraggingZones.Concat(new RectInt32[] { new((windowWidth - DebugToolbarWidth) / 2, 0, DebugToolbarWidth, DebugToolbarHeight) }); -#endif - appWindow.TitleBar.SetDragRectangles( - GetDragZones(windowWidth, dragZoneHeight, dragZoneLeftIndent, nonDraggingZones) - .Select(rect => new RectInt32( - (int)(rect.X * scaleAdjustment), - (int)(rect.Y * scaleAdjustment), - (int)(rect.Width * scaleAdjustment), - (int)(rect.Height * scaleAdjustment))) - .ToArray()); - } - - private const int DebugToolbarWidth = 217; - private const int DebugToolbarHeight = 25; - } - - file record Range(int Lower, int Upper) - { - public int Distance => Upper - Lower; - - private bool Intersects(Range other) => other.Lower <= Upper && other.Upper >= Lower; - - public static IEnumerable operator -(Range minuend, Range subtrahend) - { - if (!minuend.Intersects(subtrahend)) + if (r is { } rect) { - yield return minuend; - yield break; + var scaleFactor = uiElement.XamlRoot.RasterizationScale; + return new((int)(rect.X * scaleFactor), (int)(rect.Y * scaleFactor), (int)(rect.Width * scaleFactor), + (int)(rect.Height * scaleFactor)); + } + else + { + var pos = uiElement.TransformToVisual(null).TransformPoint(new(0, 0)); + rect = new RectInt32((int)pos.X, (int)pos.Y, (int)uiElement.ActualSize.X, (int)uiElement.ActualSize.Y); + return GetScaledRect(uiElement, rect); } - if (minuend.Lower < subtrahend.Lower) - yield return minuend with { Upper = subtrahend.Lower }; - if (minuend.Upper > subtrahend.Upper) - yield return minuend with { Lower = subtrahend.Upper }; } - - public static IEnumerable operator -(IEnumerable minuends, Range subtrahend) - => minuends.SelectMany(minuend => minuend - subtrahend); } } \ No newline at end of file diff --git a/src/Files.App/Utils/Storage/Helpers/FilePropertiesHelpers.cs b/src/Files.App/Utils/Storage/Helpers/FilePropertiesHelpers.cs index 2dc48a613596..a7b40207ba74 100644 --- a/src/Files.App/Utils/Storage/Helpers/FilePropertiesHelpers.cs +++ b/src/Files.App/Utils/Storage/Helpers/FilePropertiesHelpers.cs @@ -128,7 +128,6 @@ public static void OpenPropertiesWindow(object item, IShellPage associatedInstan { Parameter = item, AppInstance = associatedInstance, - AppWindow = appWindow, Window = propertiesWindow }, new SuppressNavigationTransitionInfo()); diff --git a/src/Files.App/ViewModels/Properties/MainPropertiesViewModel.cs b/src/Files.App/ViewModels/Properties/MainPropertiesViewModel.cs index 10f9c1da2587..caab6c3c951d 100644 --- a/src/Files.App/ViewModels/Properties/MainPropertiesViewModel.cs +++ b/src/Files.App/ViewModels/Properties/MainPropertiesViewModel.cs @@ -24,13 +24,12 @@ public NavigationViewItemButtonStyleItem SelectedNavigationViewItem if (SetProperty(ref _SelectedNavigationViewItem, value) && !_selectionChangedAutomatically) { - var parameter = new PropertiesPageNavigationParameter() + var parameter = new PropertiesPageNavigationParameter { AppInstance = _parameter.AppInstance, CancellationTokenSource = ChangedPropertiesCancellationTokenSource, Parameter = _parameter.Parameter, - Window = Window, - AppWindow = AppWindow, + Window = Window }; var page = value.ItemType switch @@ -79,8 +78,7 @@ public NavigationViewItemButtonStyleItem SelectedNavigationViewItem private readonly Window Window; - private readonly AppWindow AppWindow; - + private AppWindow AppWindow => Window.AppWindow; private readonly Frame _mainFrame; private readonly BaseProperties _baseProperties; @@ -93,12 +91,11 @@ public NavigationViewItemButtonStyleItem SelectedNavigationViewItem public IAsyncRelayCommand SaveChangedPropertiesCommand { get; } public IRelayCommand CancelChangedPropertiesCommand { get; } - public MainPropertiesViewModel(Window window, AppWindow appWindow, Frame mainFrame, BaseProperties baseProperties, PropertiesPageNavigationParameter parameter) + public MainPropertiesViewModel(Window window, Frame mainFrame, BaseProperties baseProperties, PropertiesPageNavigationParameter parameter) { ChangedPropertiesCancellationTokenSource = new(); Window = window; - AppWindow = appWindow; _mainFrame = mainFrame; _parameter = parameter; _baseProperties = baseProperties; @@ -108,7 +105,7 @@ public MainPropertiesViewModel(Window window, AppWindow appWindow, Frame mainFra CancelChangedPropertiesCommand = new RelayCommand(ExecuteCancelChangedPropertiesCommand); NavigationViewItems = PropertiesNavigationViewItemFactory.Initialize(parameter.Parameter); - SelectedNavigationViewItem = NavigationViewItems.Where(x => x.ItemType == PropertiesNavigationViewItemType.General).First(); + SelectedNavigationViewItem = NavigationViewItems.First(x => x.ItemType == PropertiesNavigationViewItemType.General); } private void ExecuteDoBackwardNavigationCommand() diff --git a/src/Files.App/Views/MainPage.xaml.cs b/src/Files.App/Views/MainPage.xaml.cs index 763dd30edb50..40079660cb9c 100644 --- a/src/Files.App/Views/MainPage.xaml.cs +++ b/src/Files.App/Views/MainPage.xaml.cs @@ -16,6 +16,7 @@ using Windows.ApplicationModel; using Windows.ApplicationModel.DataTransfer; using Windows.Foundation.Metadata; +using Windows.Graphics; using Windows.Services.Store; using WinRT.Interop; using VirtualKey = Windows.System.VirtualKey; @@ -121,7 +122,7 @@ private async Task AppRunningAsAdminPromptAsync() // WINUI3 private ContentDialog SetContentDialogRoot(ContentDialog contentDialog) { - if (Windows.Foundation.Metadata.ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8)) + if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8)) contentDialog.XamlRoot = MainWindow.Instance.Content.XamlRoot; return contentDialog; @@ -139,9 +140,8 @@ private void UserSettingsService_OnSettingChangedEvent(object? sender, SettingCh private void HorizontalMultitaskingControl_Loaded(object sender, RoutedEventArgs e) { - TabControl.DragArea.SizeChanged += (_, _) => SetRectDragRegion(); - - if (ViewModel.MultitaskingControl is not UserControls.TabBar.TabBar) + TabControl.DragArea.SizeChanged += (_, _) => MainWindow.Instance.RaiseSetTitleBarDragRegion(SetTitleBarDragRegion); + if (ViewModel.MultitaskingControl is not TabBar) { ViewModel.MultitaskingControl = TabControl; ViewModel.MultitaskingControls.Add(TabControl); @@ -149,11 +149,11 @@ private void HorizontalMultitaskingControl_Loaded(object sender, RoutedEventArgs } } - private void SetRectDragRegion() + private int SetTitleBarDragRegion(InputNonClientPointerSource source, SizeInt32 size, double scaleFactor, Func getScaledRect) { - DragZoneHelper.SetDragZones( - MainWindow.Instance, - dragZoneLeftIndent: (int)(TabControl.ActualWidth + TabControl.Margin.Left - TabControl.DragArea.ActualWidth)); + var height = (int)TabControl.ActualHeight; + source.SetRegionRects(NonClientRegionKind.Passthrough, [getScaledRect(this, new RectInt32(0, 0, (int)(TabControl.ActualWidth + TabControl.Margin.Left - TabControl.DragArea.ActualWidth), height))]); + return height; } public async void TabItemContent_ContentChanged(object? sender, CustomTabViewItemParameter e) @@ -289,6 +289,8 @@ protected override void OnLostFocus(RoutedEventArgs e) private void Page_Loaded(object sender, RoutedEventArgs e) { + MainWindow.Instance.AppWindow.Changed += (_, _) => MainWindow.Instance.RaiseSetTitleBarDragRegion(SetTitleBarDragRegion); + // Defers the status bar loading until after the page has loaded to improve startup perf FindName(nameof(StatusBarControl)); FindName(nameof(InnerNavigationToolbar)); diff --git a/src/Files.App/Views/Properties/CustomizationPage.xaml.cs b/src/Files.App/Views/Properties/CustomizationPage.xaml.cs index 442a774a7f7a..9146e6b4af2b 100644 --- a/src/Files.App/Views/Properties/CustomizationPage.xaml.cs +++ b/src/Files.App/Views/Properties/CustomizationPage.xaml.cs @@ -22,10 +22,10 @@ protected override void OnNavigatedTo(NavigationEventArgs e) base.OnNavigatedTo(e); - CustomizationViewModel = new(AppInstance, BaseProperties, parameter.AppWindow); + CustomizationViewModel = new(AppInstance, BaseProperties, parameter.Window.AppWindow); } - public async override Task SaveChangesAsync() + public override async Task SaveChangesAsync() => await CustomizationViewModel.UpdateIcon(); public override void Dispose() diff --git a/src/Files.App/Views/Properties/MainPropertiesPage.xaml.cs b/src/Files.App/Views/Properties/MainPropertiesPage.xaml.cs index b8f2233ea386..ffa59512b238 100644 --- a/src/Files.App/Views/Properties/MainPropertiesPage.xaml.cs +++ b/src/Files.App/Views/Properties/MainPropertiesPage.xaml.cs @@ -1,6 +1,7 @@ // Copyright (c) 2023 Files Community // Licensed under the MIT License. See the LICENSE. +using Windows.Graphics; using Files.App.ViewModels.Properties; using Microsoft.UI; using Microsoft.UI.Windowing; @@ -10,12 +11,13 @@ using Microsoft.UI.Xaml.Navigation; using Windows.System; using Windows.UI; +using Microsoft.UI.Input; namespace Files.App.Views.Properties { public sealed partial class MainPropertiesPage : BasePropertiesPage { - private AppWindow AppWindow; + private AppWindow AppWindow => Window.AppWindow; private Window Window; @@ -35,12 +37,11 @@ protected override void OnNavigatedTo(NavigationEventArgs e) { var parameter = (PropertiesPageNavigationParameter)e.Parameter; - AppWindow = parameter.AppWindow; Window = parameter.Window; base.OnNavigatedTo(e); - MainPropertiesViewModel = new(Window, AppWindow, MainContentFrame, BaseProperties, parameter); + MainPropertiesViewModel = new(Window, MainContentFrame, BaseProperties, parameter); } private void Page_Loaded(object sender, RoutedEventArgs e) @@ -50,6 +51,14 @@ private void Page_Loaded(object sender, RoutedEventArgs e) Window.Closed += Window_Closed; UpdatePageLayout(); + Window.RaiseSetTitleBarDragRegion(SetTitleBarDragRegion); + Window.AppWindow.Changed += (_, _) => Window.RaiseSetTitleBarDragRegion(SetTitleBarDragRegion); + } + + private int SetTitleBarDragRegion(InputNonClientPointerSource source, SizeInt32 size, double scaleFactor, Func getScaledRect) + { + source.SetRegionRects(NonClientRegionKind.Passthrough, [getScaledRect(BackwardNavigationButton, null)]); + return (int)TitlebarArea.ActualHeight; } private void Page_SizeChanged(object sender, SizeChangedEventArgs e) @@ -63,9 +72,6 @@ private void Page_KeyDown(object sender, KeyRoutedEventArgs e) private void UpdatePageLayout() { - // Drag zone - DragZoneHelper.SetDragZones(Window, (int)TitlebarArea.ActualHeight, 40); - // NavigationView Pane Mode MainPropertiesWindowNavigationView.PaneDisplayMode = ActualWidth <= 600 @@ -118,7 +124,7 @@ private void Window_Closed(object sender, WindowEventArgs args) } } - public async override Task SaveChangesAsync() + public override async Task SaveChangesAsync() => await Task.FromResult(false); public override void Dispose()