diff --git a/api/Avalonia.Diagnostics.nupkg.xml b/api/Avalonia.Diagnostics.nupkg.xml new file mode 100644 index 0000000000..d364618e59 --- /dev/null +++ b/api/Avalonia.Diagnostics.nupkg.xml @@ -0,0 +1,10 @@ + + + + + CP0001 + T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Diagnostics/Views/ConsoleView.xaml + baseline/netstandard2.0/Avalonia.Diagnostics.dll + target/netstandard2.0/Avalonia.Diagnostics.dll + + \ No newline at end of file diff --git a/packages/Avalonia/AvaloniaPrivateApis.targets b/packages/Avalonia/AvaloniaPrivateApis.targets index 5343559c07..5f69187d92 100644 --- a/packages/Avalonia/AvaloniaPrivateApis.targets +++ b/packages/Avalonia/AvaloniaPrivateApis.targets @@ -21,6 +21,6 @@ - + diff --git a/samples/GpuInterop/VulkanDemo/VulkanContent.cs b/samples/GpuInterop/VulkanDemo/VulkanContent.cs index a9a668d10b..fe95db00f4 100644 --- a/samples/GpuInterop/VulkanDemo/VulkanContent.cs +++ b/samples/GpuInterop/VulkanDemo/VulkanContent.cs @@ -182,10 +182,11 @@ unsafe class VulkanContent : IDisposable api.CmdSetScissor(commandBufferHandle, 0, 1, &scissor); - var clearColor = new ClearValue(new ClearColorValue(1, 0, 0, 0.1f), new ClearDepthStencilValue(1, 0)); - - var clearValues = new[] { clearColor, clearColor }; - + var clearValues = new ClearValue[] + { + new() { Color = new ClearColorValue { Float32_0 = 1, Float32_1 = 0, Float32_2 = 0, Float32_3 = 0.1f } }, + new() { DepthStencil = new ClearDepthStencilValue { Depth = 1, Stencil = 0 } } + }; fixed (ClearValue* clearValue = clearValues) { @@ -195,7 +196,7 @@ unsafe class VulkanContent : IDisposable RenderPass = _renderPass, Framebuffer = _framebuffer, RenderArea = new Rect2D(new Offset2D(0, 0), new Extent2D((uint?)image.Size.Width, (uint?)image.Size.Height)), - ClearValueCount = 2, + ClearValueCount = (uint)clearValues.Length, PClearValues = clearValue }; diff --git a/src/Avalonia.Controls/Control.cs b/src/Avalonia.Controls/Control.cs index 13e2a02fe5..d317d972d2 100644 --- a/src/Avalonia.Controls/Control.cs +++ b/src/Avalonia.Controls/Control.cs @@ -380,10 +380,13 @@ namespace Avalonia.Controls private void OnHoldEvent(object? sender, HoldingRoutedEventArgs e) { - if (!e.Handled && e.HoldingState == HoldingState.Started) + if (e.Source == this && !e.Handled && e.HoldingState == HoldingState.Started) { // Trigger ContentRequest when hold has started - RaiseEvent(e.PointerEventArgs is { } ev ? new ContextRequestedEventArgs(ev) : new ContextRequestedEventArgs()); + var contextEvent = e.PointerEventArgs is { } ev ? new ContextRequestedEventArgs(ev) : new ContextRequestedEventArgs(); + RaiseEvent(contextEvent); + + e.Handled = contextEvent.Handled; } } diff --git a/src/Avalonia.Controls/Selection/SelectionModel.cs b/src/Avalonia.Controls/Selection/SelectionModel.cs index 5402499fcf..22d4a371e5 100644 --- a/src/Avalonia.Controls/Selection/SelectionModel.cs +++ b/src/Avalonia.Controls/Selection/SelectionModel.cs @@ -69,6 +69,18 @@ namespace Avalonia.Controls.Selection get => _selectedIndex; set { + if (_operation is not null && _operation.UpdateCount == 0) + { + // An operation is in the process of being committed. In this case, if the new + // value for SelectedIndex is unchanged then we need to ignore it. It could be + // the result of a two-way binding to SelectedIndex writing back to the + // property. The binding system should really be fixed to ensure that it's not + // writing back the same value, but this is a workaround until the binding + // refactor is complete. See #13676. + if (value == _selectedIndex) + return; + } + using var update = BatchUpdate(); Clear(); Select(value); @@ -675,8 +687,6 @@ namespace Avalonia.Controls.Selection } } - - if (raisePropertyChanged) { if (oldSelectedIndex != _selectedIndex) diff --git a/src/Avalonia.Controls/ToggleSwitch.cs b/src/Avalonia.Controls/ToggleSwitch.cs index 49d01d9f65..697dc4c2d0 100644 --- a/src/Avalonia.Controls/ToggleSwitch.cs +++ b/src/Avalonia.Controls/ToggleSwitch.cs @@ -228,6 +228,8 @@ namespace Avalonia.Controls { if (_isDragging) { + e.Handled = true; + bool shouldBecomeChecked = Canvas.GetLeft(_knobsPanel!) >= (_switchKnob!.Bounds.Width / 2); _knobsPanel!.ClearValue(Canvas.LeftProperty); diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 0f535500bc..44c997f555 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -209,6 +209,7 @@ namespace Avalonia.Controls CreatePlatformImplBinding(WindowStateProperty, state => PlatformImpl!.WindowState = state); CreatePlatformImplBinding(ExtendClientAreaToDecorationsHintProperty, hint => PlatformImpl!.SetExtendClientAreaToDecorationsHint(hint)); CreatePlatformImplBinding(ExtendClientAreaChromeHintsProperty, hint => PlatformImpl!.SetExtendClientAreaChromeHints(hint)); + CreatePlatformImplBinding(ExtendClientAreaTitleBarHeightHintProperty, height => PlatformImpl!.SetExtendClientAreaTitleBarHeightHint(height)); CreatePlatformImplBinding(MinWidthProperty, UpdateMinMaxSize); CreatePlatformImplBinding(MaxWidthProperty, UpdateMinMaxSize); diff --git a/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj b/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj index 289f239ec1..dfe2691f96 100644 --- a/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj +++ b/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj @@ -17,10 +17,6 @@ - - - - diff --git a/src/Avalonia.Diagnostics/Diagnostics/Models/ConsoleContext.cs b/src/Avalonia.Diagnostics/Diagnostics/Models/ConsoleContext.cs deleted file mode 100644 index 4fd3de25dd..0000000000 --- a/src/Avalonia.Diagnostics/Diagnostics/Models/ConsoleContext.cs +++ /dev/null @@ -1,36 +0,0 @@ -#pragma warning disable IDE1006 // Naming Styles - -using Avalonia.Diagnostics.ViewModels; - -namespace Avalonia.Diagnostics.Models -{ - internal class ConsoleContext - { - private readonly ConsoleViewModel _owner; - - internal ConsoleContext(ConsoleViewModel owner) => _owner = owner; - - public readonly string help = @"Welcome to Avalonia DevTools. Here you can execute arbitrary C# code using Roslyn scripting. - -The following variables are available: - -e: The control currently selected in the logical or visual tree view -root: The root of the visual tree - -The following commands are available: - -clear(): Clear the output history -"; - - public dynamic? e { get; internal set; } - public dynamic? root { get; internal set; } - - internal static object NoOutput { get; } = new object(); - - public object clear() - { - _owner.History.Clear(); - return NoOutput; - } - } -} diff --git a/src/Avalonia.Diagnostics/Diagnostics/Models/ConsoleHistoryItem.cs b/src/Avalonia.Diagnostics/Diagnostics/Models/ConsoleHistoryItem.cs deleted file mode 100644 index 86da18145a..0000000000 --- a/src/Avalonia.Diagnostics/Diagnostics/Models/ConsoleHistoryItem.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using Avalonia.Media; - -namespace Avalonia.Diagnostics.Models -{ - internal class ConsoleHistoryItem - { - public ConsoleHistoryItem(string input, object output) - { - Input = input; - Output = output; - Foreground = output is Exception ? Brushes.Red : Brushes.Green; - } - - public string Input { get; } - public object Output { get; } - public IBrush Foreground { get; } - } -} diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ConsoleViewModel.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ConsoleViewModel.cs deleted file mode 100644 index 717b49d074..0000000000 --- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ConsoleViewModel.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System; -using System.Reflection; -using System.Threading.Tasks; -using Avalonia.Collections; -using Avalonia.Diagnostics.Models; -using Microsoft.CodeAnalysis.CSharp.Scripting; -using Microsoft.CodeAnalysis.Scripting; - -namespace Avalonia.Diagnostics.ViewModels -{ - internal class ConsoleViewModel : ViewModelBase - { - private readonly ConsoleContext _context; - private readonly Action _updateContext; - private int _historyIndex = -1; - private string _input; - private bool _isVisible; - private ScriptState? _state; - - public ConsoleViewModel(Action updateContext) - { - _context = new ConsoleContext(this); - _input = string.Empty; - _updateContext = updateContext; - } - - public string Input - { - get => _input; - set => RaiseAndSetIfChanged(ref _input, value); - } - - public bool IsVisible - { - get => _isVisible; - set => RaiseAndSetIfChanged(ref _isVisible, value); - } - - public AvaloniaList History { get; } = new AvaloniaList(); - - public async Task Execute() - { - if (string.IsNullOrWhiteSpace(Input)) - { - return; - } - - try - { - var options = ScriptOptions.Default - .AddReferences(Assembly.GetAssembly(typeof(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo))); - - _updateContext(_context); - - if (_state == null) - { - _state = await CSharpScript.RunAsync(Input, options: options, globals: _context); - } - else - { - _state = await _state.ContinueWithAsync(Input); - } - - if (_state.ReturnValue != ConsoleContext.NoOutput) - { - History.Add(new ConsoleHistoryItem(Input, _state.ReturnValue ?? "(null)")); - } - } - catch (Exception ex) - { - History.Add(new ConsoleHistoryItem(Input, ex)); - } - - Input = string.Empty; - _historyIndex = -1; - } - - public void HistoryUp() - { - if (History.Count > 0) - { - if (_historyIndex == -1) - { - _historyIndex = History.Count - 1; - } - else if (_historyIndex > 0) - { - --_historyIndex; - } - - Input = History[_historyIndex].Input; - } - } - - public void HistoryDown() - { - if (History.Count > 0 && _historyIndex >= 0) - { - if (_historyIndex == History.Count - 1) - { - _historyIndex = -1; - Input = string.Empty; - } - else - { - Input = History[++_historyIndex].Input; - } - } - } - - public void ToggleVisibility() => IsVisible = !IsVisible; - } -} diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/MainViewModel.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/MainViewModel.cs index 06e4e06f8a..4cb4162af5 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/MainViewModel.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/MainViewModel.cs @@ -67,7 +67,6 @@ namespace Avalonia.Diagnostics.ViewModels } }); } - Console = new ConsoleViewModel(UpdateConsoleContext); } public bool FreezePopups @@ -152,8 +151,6 @@ namespace Avalonia.Diagnostics.ViewModels public void ToggleRenderTimeGraphOverlay() => ShowRenderTimeGraphOverlay = !ShowRenderTimeGraphOverlay; - public ConsoleViewModel Console { get; } - public ViewModelBase? Content { get { return _content; } @@ -236,16 +233,6 @@ namespace Avalonia.Diagnostics.ViewModels private set => RaiseAndSetIfChanged(ref _pointerOverElementName, value); } - private void UpdateConsoleContext(ConsoleContext context) - { - context.root = _root; - - if (Content is TreePageViewModel tree) - { - context.e = tree.SelectedNode?.Visual; - } - } - public void SelectControl(Control control) { var tree = Content as TreePageViewModel; diff --git a/src/Avalonia.Diagnostics/Diagnostics/Views/ConsoleView.xaml b/src/Avalonia.Diagnostics/Diagnostics/Views/ConsoleView.xaml deleted file mode 100644 index dad87f72fd..0000000000 --- a/src/Avalonia.Diagnostics/Diagnostics/Views/ConsoleView.xaml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Avalonia.Diagnostics/Diagnostics/Views/ConsoleView.xaml.cs b/src/Avalonia.Diagnostics/Diagnostics/Views/ConsoleView.xaml.cs deleted file mode 100644 index 01e8503495..0000000000 --- a/src/Avalonia.Diagnostics/Diagnostics/Views/ConsoleView.xaml.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Collections.Specialized; -using Avalonia.Controls; -using Avalonia.Diagnostics.ViewModels; -using Avalonia.Input; -using Avalonia.LogicalTree; -using Avalonia.Markup.Xaml; -using Avalonia.Threading; - -namespace Avalonia.Diagnostics.Views -{ - internal class ConsoleView : UserControl - { - private readonly ListBox _historyList; - private readonly TextBox _input; - - public ConsoleView() - { - this.InitializeComponent(); - _historyList = this.GetControl("historyList"); - ((ILogical)_historyList).LogicalChildren.CollectionChanged += HistoryChanged; - _input = this.GetControl("input"); - _input.KeyDown += InputKeyDown; - } - - public void FocusInput() => _input.Focus(); - - private void InitializeComponent() - { - AvaloniaXamlLoader.Load(this); - } - - private void HistoryChanged(object? sender, NotifyCollectionChangedEventArgs e) - { - if (e.Action == NotifyCollectionChangedAction.Add && e.NewItems?[0] is Control control) - { - DispatcherTimer.RunOnce(control.BringIntoView, TimeSpan.Zero); - } - } - - private void InputKeyDown(object? sender, KeyEventArgs e) - { - var vm = (ConsoleViewModel?)DataContext; - if (vm is null) - { - return; - } - - switch (e.Key) - { - case Key.Enter: - _ = vm.Execute(); - e.Handled = true; - break; - case Key.Up: - vm.HistoryUp(); - _input.CaretIndex = _input.Text?.Length ?? 0; - e.Handled = true; - break; - case Key.Down: - vm.HistoryDown(); - _input.CaretIndex = _input.Text?.Length ?? 0; - e.Handled = true; - break; - } - } - } -} diff --git a/src/Avalonia.Diagnostics/Diagnostics/Views/MainView.xaml b/src/Avalonia.Diagnostics/Diagnostics/Views/MainView.xaml index f810d8450c..83f17e67e9 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/Views/MainView.xaml +++ b/src/Avalonia.Diagnostics/Diagnostics/Views/MainView.xaml @@ -20,7 +20,7 @@ - + @@ -56,13 +56,6 @@ - - - - - @@ -273,13 +266,7 @@ Background="{DynamicResource ThemeControlMidBrush}" IsVisible="False" /> - - - - diff --git a/src/Avalonia.Diagnostics/Diagnostics/Views/MainView.xaml.cs b/src/Avalonia.Diagnostics/Diagnostics/Views/MainView.xaml.cs index df5188b29b..ac53d3d913 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/Views/MainView.xaml.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/Views/MainView.xaml.cs @@ -8,62 +8,14 @@ namespace Avalonia.Diagnostics.Views { internal class MainView : UserControl { - private readonly ConsoleView _console; - private readonly GridSplitter _consoleSplitter; - private readonly Grid _rootGrid; - private readonly int _consoleRow; - private double _consoleHeight = -1; - public MainView() { InitializeComponent(); - AddHandler(KeyUpEvent, PreviewKeyUp); - _console = this.GetControl("console"); - _consoleSplitter = this.GetControl("consoleSplitter"); - _rootGrid = this.GetControl("rootGrid"); - _consoleRow = Grid.GetRow(_console); - } - - public void ToggleConsole() - { - var vm = (MainViewModel?)DataContext; - if (vm is null) - { - return; - } - - if (_consoleHeight == -1) - { - _consoleHeight = Bounds.Height / 3; - } - - vm.Console.ToggleVisibility(); - _consoleSplitter.IsVisible = vm.Console.IsVisible; - - if (vm.Console.IsVisible) - { - _rootGrid.RowDefinitions[_consoleRow].Height = new GridLength(_consoleHeight, GridUnitType.Pixel); - Dispatcher.UIThread.Post(() => _console.FocusInput(), DispatcherPriority.Background); - } - else - { - _consoleHeight = _rootGrid.RowDefinitions[_consoleRow].Height.Value; - _rootGrid.RowDefinitions[_consoleRow].Height = new GridLength(0, GridUnitType.Pixel); - } } private void InitializeComponent() { AvaloniaXamlLoader.Load(this); } - - private void PreviewKeyUp(object? sender, KeyEventArgs e) - { - if (e.Key == Key.Escape) - { - ToggleConsole(); - e.Handled = true; - } - } } } diff --git a/src/Browser/Avalonia.Browser/BrowserAppBuilder.cs b/src/Browser/Avalonia.Browser/BrowserAppBuilder.cs index dbc5f9f4a9..996faaec58 100644 --- a/src/Browser/Avalonia.Browser/BrowserAppBuilder.cs +++ b/src/Browser/Avalonia.Browser/BrowserAppBuilder.cs @@ -1,6 +1,7 @@ using System; using System.Threading.Tasks; using Avalonia.Browser.Interop; +using Avalonia.Metadata; namespace Avalonia.Browser; @@ -17,6 +18,7 @@ public class BrowserPlatformOptions /// If registered, service worker can work as a save file picker fallback on the browsers that don't support native implementation. /// For more details, see https://github.com/jimmywarting/native-file-system-adapter#a-note-when-downloading-with-the-polyfilled-version. /// + [Unstable("This property might not work reliably.")] public bool RegisterAvaloniaServiceWorker { get; set; } /// diff --git a/src/Browser/Avalonia.Browser/webapp/modules/sw.ts b/src/Browser/Avalonia.Browser/webapp/modules/sw.ts index 2d08ae2c15..9f07eb355c 100644 --- a/src/Browser/Avalonia.Browser/webapp/modules/sw.ts +++ b/src/Browser/Avalonia.Browser/webapp/modules/sw.ts @@ -50,7 +50,7 @@ self.addEventListener("activate", event /* ExtendableEvent */ => { (event as any).waitUntil((self as any).clients.claim()); }); -const map = new Map(); +(self as any).map = new Map(); // This should be called once per download // Each event has a dataChannel that the data will be piped through @@ -61,12 +61,14 @@ globalThis.addEventListener("message", evt => { new MessagePortSource(evt.data.readablePort), new CountQueuingStrategy({ highWaterMark: 4 }) ); + const map = (self as any).map; map.set(data.url, data); } }); globalThis.addEventListener("fetch", evt => { const url = (evt as any).request.url; + const map = (self as any).map; const data = map.get(url); if (!data) return null; map.delete(url); diff --git a/src/Windows/Avalonia.Win32/DirectX/directx.idl b/src/Windows/Avalonia.Win32/DirectX/directx.idl index 120d1d5159..2ad75d18f3 100644 --- a/src/Windows/Avalonia.Win32/DirectX/directx.idl +++ b/src/Windows/Avalonia.Win32/DirectX/directx.idl @@ -215,7 +215,7 @@ interface IDXGIAdapter : IDXGIObject [uuid(310d36a0-d2e7-4c0a-aa04-6a9d23b8886a)] interface IDXGISwapChain : IDXGIDeviceSubObject { - HRESULT Present([in] UINT SyncInterval, [in] UINT Flags); + INT32 Present([in] UINT SyncInterval, [in] UINT Flags); HRESULT GetBuffer([in] UINT Buffer, [in, annotation("_In_")] REFIID riid, [in, out, annotation("_COM_Outptr_")] void** ppSurface); HRESULT SetFullscreenState([in] BOOL Fullscreen, [in, annotation("_In_opt_")] IDXGIOutput* pTarget); HRESULT GetFullscreenState([out, annotation("_Out_opt_")] BOOL* pFullscreen, [out, annotation("_COM_Outptr_opt_result_maybenull_")] IDXGIOutput** ppTarget); diff --git a/src/Windows/Avalonia.Win32/Win32NativeControlHost.cs b/src/Windows/Avalonia.Win32/Win32NativeControlHost.cs index 620cd64e79..a04e52f410 100644 --- a/src/Windows/Avalonia.Win32/Win32NativeControlHost.cs +++ b/src/Windows/Avalonia.Win32/Win32NativeControlHost.cs @@ -137,7 +137,7 @@ namespace Avalonia.Win32 _holder = holder; _child = child; UnmanagedMethods.SetParent(child.Handle, _holder.Handle); - UnmanagedMethods.ShowWindow(child.Handle, UnmanagedMethods.ShowWindowCommand.Show); + UnmanagedMethods.ShowWindow(child.Handle, UnmanagedMethods.ShowWindowCommand.ShowNoActivate); } [MemberNotNull(nameof(_holder))] diff --git a/tests/Avalonia.Controls.UnitTests/ListBoxTests_Multiple.cs b/tests/Avalonia.Controls.UnitTests/ListBoxTests_Multiple.cs index 3a74ee6a7f..1863681030 100644 --- a/tests/Avalonia.Controls.UnitTests/ListBoxTests_Multiple.cs +++ b/tests/Avalonia.Controls.UnitTests/ListBoxTests_Multiple.cs @@ -3,6 +3,7 @@ using System.Linq; using Avalonia.Controls.Presenters; using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; +using Avalonia.Data; using Avalonia.Input; using Avalonia.Input.Platform; using Avalonia.Styling; @@ -577,6 +578,64 @@ namespace Avalonia.Controls.UnitTests Assert.True(target.ContainerFromIndex(3).IsFocused); } + [Fact] + public void SelectAll_Works_From_No_Selection_When_SelectedItem_Is_Bound_TwoWay() + { + // Issue #13676 + using var app = UnitTestApplication.Start(TestServices.RealFocus); + var target = new ListBox + { + Template = new FuncControlTemplate(CreateListBoxTemplate), + ItemsSource = new[] { "Foo", "Bar", "Baz", "Qux" }, + SelectionMode = SelectionMode.Multiple, + Width = 100, + Height = 100, + }; + + var root = new TestRoot(target); + root.LayoutManager.ExecuteInitialLayoutPass(); + + target.Bind(ListBox.SelectedItemProperty, new Binding("Tag") + { + Mode = BindingMode.TwoWay, + RelativeSource = new RelativeSource(RelativeSourceMode.Self), + }); + + target.SelectAll(); + + Assert.Equal(new[] { 0, 1, 2, 3 }, target.Selection.SelectedIndexes); + Assert.Equal(new[] { "Foo", "Bar", "Baz", "Qux" }, target.SelectedItems); + } + + [Fact] + public void SelectAll_Works_From_No_Selection_When_SelectedIndex_Is_Bound_TwoWay() + { + // Issue #13676 + using var app = UnitTestApplication.Start(TestServices.RealFocus); + var target = new ListBox + { + Template = new FuncControlTemplate(CreateListBoxTemplate), + ItemsSource = new[] { "Foo", "Bar", "Baz", "Qux" }, + SelectionMode = SelectionMode.Multiple, + Width = 100, + Height = 100, + }; + + var root = new TestRoot(target); + root.LayoutManager.ExecuteInitialLayoutPass(); + + target.Bind(ListBox.SelectedIndexProperty, new Binding("Tag") + { + Mode = BindingMode.TwoWay, + RelativeSource = new RelativeSource(RelativeSourceMode.Self), + }); + + target.SelectAll(); + + Assert.Equal(new[] { 0, 1, 2, 3 }, target.Selection.SelectedIndexes); + Assert.Equal(new[] { "Foo", "Bar", "Baz", "Qux" }, target.SelectedItems); + } + private Control CreateListBoxTemplate(TemplatedControl parent, INameScope scope) { return new ScrollViewer diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs index 831bce064a..eece0d4c17 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs @@ -205,6 +205,17 @@ namespace Avalonia.IntegrationTests.Appium } } + [Fact] + public void Extended_Client_Window_Shows_With_Requested_Size() + { + var clientSize = new Size(400, 400); + using var window = OpenWindow(clientSize, ShowWindowMode.NonOwned, WindowStartupLocation.CenterScreen, extendClientArea: true); + var windowState = _session.FindElementByAccessibilityId("CurrentWindowState"); + var current = GetWindowInfo(); + + Assert.Equal(current.ClientSize, clientSize); + } + [Fact] public void TransparentWindow() {