Browse Source

Merge branch 'master' into fix/textBoxColors

pull/9631/head
Benedikt Stebner 4 years ago
committed by GitHub
parent
commit
c347a0843a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      native/Avalonia.Native/src/OSX/WindowImpl.mm
  2. 15
      samples/IntegrationTestApp/MainWindow.axaml
  3. 3
      samples/IntegrationTestApp/MainWindow.axaml.cs
  4. 8
      samples/IntegrationTestApp/ShowWindowTest.axaml
  5. 67
      src/Avalonia.Base/StyledElement.cs
  6. 3
      src/Avalonia.Base/Styling/StyleInstance.cs
  7. 4
      src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml
  8. 2
      src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
  9. 2
      src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs
  10. 2
      src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github
  11. 9
      src/Windows/Avalonia.Win32/TrayIconImpl.cs
  12. 48
      tests/Avalonia.Base.UnitTests/Styling/StyleTests.cs
  13. 51
      tests/Avalonia.Base.UnitTests/Styling/StyledElementTests_Theming.cs
  14. 16
      tests/Avalonia.IntegrationTests.Appium/WindowTests.cs
  15. 74
      tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs
  16. 23
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs

9
native/Avalonia.Native/src/OSX/WindowImpl.mm

@ -137,7 +137,11 @@ void WindowImpl::BringToFront()
for(auto iterator = _children.begin(); iterator != _children.end(); iterator++) for(auto iterator = _children.begin(); iterator != _children.end(); iterator++)
{ {
(*iterator)->BringToFront(); auto window = (*iterator)->Window;
// #9565: Only bring window to front if it's on the currently active space
if ([window isOnActiveSpace])
(*iterator)->BringToFront();
} }
} }
} }
@ -161,6 +165,9 @@ void WindowImpl::StartStateTransition() {
void WindowImpl::EndStateTransition() { void WindowImpl::EndStateTransition() {
_transitioningWindowState = false; _transitioningWindowState = false;
// Ensure correct order of child windows after fullscreen transition.
BringToFront();
} }
SystemDecorations WindowImpl::Decorations() { SystemDecorations WindowImpl::Decorations() {

15
samples/IntegrationTestApp/MainWindow.axaml

@ -17,11 +17,15 @@
</NativeMenuItem> </NativeMenuItem>
<NativeMenuItem Header="View"> <NativeMenuItem Header="View">
<NativeMenu/> <NativeMenu/>
</NativeMenuItem> </NativeMenuItem>
</NativeMenu> </NativeMenu>
</NativeMenu.Menu> </NativeMenu.Menu>
<DockPanel> <DockPanel>
<NativeMenuBar DockPanel.Dock="Top"/> <NativeMenuBar DockPanel.Dock="Top"/>
<StackPanel DockPanel.Dock="Bottom" Margin="4" Orientation="Horizontal">
<TextBlock Margin="0,0,4,0">WindowState:</TextBlock>
<TextBlock Name="MainWindowState" Text="{Binding WindowState}"/>
</StackPanel>
<TabControl TabStripPlacement="Left" Name="MainTabs"> <TabControl TabStripPlacement="Left" Name="MainTabs">
<TabItem Header="Automation"> <TabItem Header="Automation">
@ -129,13 +133,14 @@
<ComboBoxItem>CenterOwner</ComboBoxItem> <ComboBoxItem>CenterOwner</ComboBoxItem>
</ComboBox> </ComboBox>
<ComboBox Name="ShowWindowState" SelectedIndex="0"> <ComboBox Name="ShowWindowState" SelectedIndex="0">
<ComboBoxItem>Normal</ComboBoxItem> <ComboBoxItem Name="ShowWindowStateNormal">Normal</ComboBoxItem>
<ComboBoxItem>Minimized</ComboBoxItem> <ComboBoxItem Name="ShowWindowStateMinimized">Minimized</ComboBoxItem>
<ComboBoxItem>Maximized</ComboBoxItem> <ComboBoxItem Name="ShowWindowStateMaximized">Maximized</ComboBoxItem>
<ComboBoxItem>FullScreen</ComboBoxItem> <ComboBoxItem Name="ShowWindowStateFullScreen">FullScreen</ComboBoxItem>
</ComboBox> </ComboBox>
<Button Name="ShowWindow">Show Window</Button> <Button Name="ShowWindow">Show Window</Button>
<Button Name="SendToBack">Send to Back</Button> <Button Name="SendToBack">Send to Back</Button>
<Button Name="EnterFullscreen">Enter Fullscreen</Button>
<Button Name="ExitFullscreen">Exit Fullscreen</Button> <Button Name="ExitFullscreen">Exit Fullscreen</Button>
<Button Name="RestoreAll">Restore All</Button> <Button Name="RestoreAll">Restore All</Button>
</StackPanel> </StackPanel>

3
samples/IntegrationTestApp/MainWindow.axaml.cs

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Avalonia; using Avalonia;
@ -178,6 +179,8 @@ namespace IntegrationTestApp
ShowWindow(); ShowWindow();
if (source?.Name == "SendToBack") if (source?.Name == "SendToBack")
SendToBack(); SendToBack();
if (source?.Name == "EnterFullscreen")
WindowState = WindowState.FullScreen;
if (source?.Name == "ExitFullscreen") if (source?.Name == "ExitFullscreen")
WindowState = WindowState.Normal; WindowState = WindowState.Normal;
if (source?.Name == "RestoreAll") if (source?.Name == "RestoreAll")

8
samples/IntegrationTestApp/ShowWindowTest.axaml

@ -27,10 +27,10 @@
<Label Grid.Column="0" Grid.Row="7">WindowState</Label> <Label Grid.Column="0" Grid.Row="7">WindowState</Label>
<ComboBox Name="WindowState" Grid.Column="1" Grid.Row="7" SelectedIndex="{Binding WindowState}"> <ComboBox Name="WindowState" Grid.Column="1" Grid.Row="7" SelectedIndex="{Binding WindowState}">
<ComboBoxItem>Normal</ComboBoxItem> <ComboBoxItem Name="WindowStateNormal">Normal</ComboBoxItem>
<ComboBoxItem>Minimized</ComboBoxItem> <ComboBoxItem Name="WindowStateMinimized">Minimized</ComboBoxItem>
<ComboBoxItem>Maximized</ComboBoxItem> <ComboBoxItem Name="WindowStateMaximized">Maximized</ComboBoxItem>
<ComboBoxItem>FullScreen</ComboBoxItem> <ComboBoxItem Name="WindowStateFullScreen">FullScreen</ComboBoxItem>
</ComboBox> </ComboBox>
<Label Grid.Column="0" Grid.Row="8">Order (mac)</Label> <Label Grid.Column="0" Grid.Row="8">Order (mac)</Label>

67
src/Avalonia.Base/StyledElement.cs

@ -81,6 +81,7 @@ namespace Avalonia
private Styles? _styles; private Styles? _styles;
private bool _stylesApplied; private bool _stylesApplied;
private bool _themeApplied; private bool _themeApplied;
private bool _templatedParentThemeApplied;
private AvaloniaObject? _templatedParent; private AvaloniaObject? _templatedParent;
private bool _dataContextUpdating; private bool _dataContextUpdating;
private ControlTheme? _implicitTheme; private ControlTheme? _implicitTheme;
@ -375,6 +376,12 @@ namespace Avalonia
_themeApplied = true; _themeApplied = true;
} }
if (!_templatedParentThemeApplied)
{
ApplyTemplatedParentControlTheme();
_templatedParentThemeApplied = true;
}
if (!_stylesApplied) if (!_stylesApplied)
{ {
ApplyStyles(this); ApplyStyles(this);
@ -613,26 +620,38 @@ namespace Avalonia
base.OnPropertyChanged(change); base.OnPropertyChanged(change);
if (change.Property == ThemeProperty) if (change.Property == ThemeProperty)
{
OnControlThemeChanged(); OnControlThemeChanged();
_themeApplied = false;
}
} }
private protected virtual void OnControlThemeChanged() private protected virtual void OnControlThemeChanged()
{ {
var values = GetValueStore(); var values = GetValueStore();
values.BeginStyling(); values.BeginStyling();
try { values.RemoveFrames(FrameType.Theme); }
finally { values.EndStyling(); } try
{
values.RemoveFrames(FrameType.Theme);
}
finally
{
values.EndStyling();
_themeApplied = false;
}
} }
internal virtual void OnTemplatedParentControlThemeChanged() internal virtual void OnTemplatedParentControlThemeChanged()
{ {
var values = GetValueStore(); var values = GetValueStore();
values.BeginStyling(); values.BeginStyling();
try { values.RemoveFrames(FrameType.TemplatedParentTheme); } try
finally { values.EndStyling(); } {
values.RemoveFrames(FrameType.TemplatedParentTheme);
}
finally
{
values.EndStyling();
_templatedParentThemeApplied = false;
}
} }
internal ControlTheme? GetEffectiveTheme() internal ControlTheme? GetEffectiveTheme()
@ -743,13 +762,13 @@ namespace Avalonia
private void ApplyControlTheme() private void ApplyControlTheme()
{ {
var theme = GetEffectiveTheme(); if (GetEffectiveTheme() is { } theme)
if (theme is not null)
ApplyControlTheme(theme, FrameType.Theme); ApplyControlTheme(theme, FrameType.Theme);
}
if (TemplatedParent is StyledElement styleableParent && private void ApplyTemplatedParentControlTheme()
styleableParent.GetEffectiveTheme() is { } parentTheme) {
if ((TemplatedParent as StyledElement)?.GetEffectiveTheme() is { } parentTheme)
{ {
ApplyControlTheme(parentTheme, FrameType.TemplatedParentTheme); ApplyControlTheme(parentTheme, FrameType.TemplatedParentTheme);
} }
@ -793,6 +812,28 @@ namespace Avalonia
ApplyStyle(child, host, type); ApplyStyle(child, host, type);
} }
private void ReevaluateImplicitTheme()
{
// We only need to check if the theme has changed when Theme isn't set (i.e. when we
// have an implicit theme).
if (Theme is not null)
return;
// Refetch the implicit theme.
var oldImplicitTheme = _implicitTheme == s_invalidTheme ? null : _implicitTheme;
_implicitTheme = null;
GetEffectiveTheme();
var newImplicitTheme = _implicitTheme == s_invalidTheme ? null : _implicitTheme;
// If the implicit theme has changed, detach the existing theme.
if (newImplicitTheme != oldImplicitTheme)
{
OnControlThemeChanged();
_themeApplied = false;
}
}
private void OnAttachedToLogicalTreeCore(LogicalTreeAttachmentEventArgs e) private void OnAttachedToLogicalTreeCore(LogicalTreeAttachmentEventArgs e)
{ {
if (this.GetLogicalParent() == null && !(this is ILogicalRoot)) if (this.GetLogicalParent() == null && !(this is ILogicalRoot))
@ -811,6 +852,7 @@ namespace Avalonia
{ {
_logicalRoot = e.Root; _logicalRoot = e.Root;
ReevaluateImplicitTheme();
ApplyStyling(); ApplyStyling();
NotifyResourcesChanged(propagate: false); NotifyResourcesChanged(propagate: false);
@ -835,7 +877,6 @@ namespace Avalonia
if (_logicalRoot != null) if (_logicalRoot != null)
{ {
_logicalRoot = null; _logicalRoot = null;
_implicitTheme = null;
InvalidateStyles(recurse: false); InvalidateStyles(recurse: false);
OnDetachedFromLogicalTree(e); OnDetachedFromLogicalTree(e);
DetachedFromLogicalTree?.Invoke(this, e); DetachedFromLogicalTree?.Invoke(this, e);

3
src/Avalonia.Base/Styling/StyleInstance.cs

@ -70,6 +70,9 @@ namespace Avalonia.Styling
_animationTrigger ??= new Subject<bool>(); _animationTrigger ??= new Subject<bool>();
foreach (var animation in _animations) foreach (var animation in _animations)
animation.Apply(animatable, null, _animationTrigger); animation.Apply(animatable, null, _animationTrigger);
if (_activator is null)
_animationTrigger.OnNext(true);
} }
} }

4
src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml

@ -6,8 +6,8 @@
<StreamGeometry x:Key="DataGridSortIconDescendingPath">M1875 1011l-787 787v-1798h-128v1798l-787 -787l-90 90l941 941l941 -941z</StreamGeometry> <StreamGeometry x:Key="DataGridSortIconDescendingPath">M1875 1011l-787 787v-1798h-128v1798l-787 -787l-90 90l941 941l941 -941z</StreamGeometry>
<StreamGeometry x:Key="DataGridSortIconAscendingPath">M1965 947l-941 -941l-941 941l90 90l787 -787v1798h128v-1798l787 787z</StreamGeometry> <StreamGeometry x:Key="DataGridSortIconAscendingPath">M1965 947l-941 -941l-941 941l90 90l787 -787v1798h128v-1798l787 787z</StreamGeometry>
<StreamGeometry x:Key="DataGridRowGroupHeaderIconClosedPath">M515 93l930 931l-930 931l90 90l1022 -1021l-1022 -1021z</StreamGeometry> <StreamGeometry x:Key="DataGridRowGroupHeaderIconOpenedPath">M515 93l930 931l-930 931l90 90l1022 -1021l-1022 -1021z</StreamGeometry>
<StreamGeometry x:Key="DataGridRowGroupHeaderIconOpenedPath">M109 486 19 576 1024 1581 2029 576 1939 486 1024 1401z</StreamGeometry> <StreamGeometry x:Key="DataGridRowGroupHeaderIconClosedPath">M109 486 19 576 1024 1581 2029 576 1939 486 1024 1401z</StreamGeometry>
<SolidColorBrush x:Key="DataGridColumnHeaderForegroundBrush" Color="{DynamicResource SystemBaseMediumColor}" /> <SolidColorBrush x:Key="DataGridColumnHeaderForegroundBrush" Color="{DynamicResource SystemBaseMediumColor}" />
<SolidColorBrush x:Key="DataGridColumnHeaderBackgroundBrush" Color="{DynamicResource SystemAltHighColor}" /> <SolidColorBrush x:Key="DataGridColumnHeaderBackgroundBrush" Color="{DynamicResource SystemAltHighColor}" />

2
src/Avalonia.Controls/Primitives/SelectingItemsControl.cs

@ -588,7 +588,7 @@ namespace Avalonia.Controls.Primitives
} }
else if (e.Key == Key.Space || e.Key == Key.Enter) else if (e.Key == Key.Space || e.Key == Key.Enter)
{ {
e.Handled = UpdateSelectionFromEventSource( UpdateSelectionFromEventSource(
e.Source, e.Source,
true, true,
e.KeyModifiers.HasFlag(KeyModifiers.Shift), e.KeyModifiers.HasFlag(KeyModifiers.Shift),

2
src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs

@ -234,7 +234,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
parsedDocuments.Add(new XamlDocumentResource(parsed, document.BaseUri?.ToString(), null, null, parsedDocuments.Add(new XamlDocumentResource(parsed, document.BaseUri?.ToString(), null, null,
builder, builder,
compiler.DefinePopulateMethod(builder, parsed, AvaloniaXamlIlCompiler.PopulateName, true), compiler.DefinePopulateMethod(builder, parsed, AvaloniaXamlIlCompiler.PopulateName, true),
compiler.DefineBuildMethod(builder, parsed, AvaloniaXamlIlCompiler.BuildName, true))); document.RootInstance is null ? compiler.DefineBuildMethod(builder, parsed, AvaloniaXamlIlCompiler.BuildName, true) : null));
originalDocuments.Add(document); originalDocuments.Add(document);
} }

2
src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github

@ -1 +1 @@
Subproject commit 491de981dd4433ee58bc9540e2cd4a5d168f8168 Subproject commit 5e498f8bcca403a34aff5efc825cbb4e12b7fa8e

9
src/Windows/Avalonia.Win32/TrayIconImpl.cs

@ -19,7 +19,6 @@ namespace Avalonia.Win32
public class TrayIconImpl : ITrayIconImpl public class TrayIconImpl : ITrayIconImpl
{ {
private static readonly IntPtr s_emptyIcon = new System.Drawing.Bitmap(32, 32).GetHicon(); private static readonly IntPtr s_emptyIcon = new System.Drawing.Bitmap(32, 32).GetHicon();
private readonly int _uniqueId; private readonly int _uniqueId;
private static int s_nextUniqueId; private static int s_nextUniqueId;
private bool _iconAdded; private bool _iconAdded;
@ -137,6 +136,12 @@ namespace Avalonia.Win32
private void OnRightClicked() private void OnRightClicked()
{ {
var menuItems = _exporter.GetMenu();
if (null == menuItems || menuItems.Count == 0)
{
return;
}
var _trayMenu = new TrayPopupRoot() var _trayMenu = new TrayPopupRoot()
{ {
SystemDecorations = SystemDecorations.None, SystemDecorations = SystemDecorations.None,
@ -145,7 +150,7 @@ namespace Avalonia.Win32
TransparencyLevelHint = WindowTransparencyLevel.Transparent, TransparencyLevelHint = WindowTransparencyLevel.Transparent,
Content = new TrayIconMenuFlyoutPresenter() Content = new TrayIconMenuFlyoutPresenter()
{ {
Items = _exporter.GetMenu() Items = menuItems
} }
}; };

48
tests/Avalonia.Base.UnitTests/Styling/StyleTests.cs

@ -868,7 +868,53 @@ namespace Avalonia.Base.UnitTests.Styling
} }
[Fact] [Fact]
public void Animations_Should_Be_Activated_And_Deactivated() public void Animations_Should_Be_Activated()
{
Style style = new Style(x => x.OfType<Class1>())
{
Animations =
{
new Avalonia.Animation.Animation
{
Duration = TimeSpan.FromSeconds(1),
Children =
{
new KeyFrame
{
Setters =
{
new Setter { Property = Class1.DoubleProperty, Value = 5.0 }
},
},
new KeyFrame
{
Setters =
{
new Setter { Property = Class1.DoubleProperty, Value = 10.0 }
},
Cue = new Cue(1d)
}
},
}
}
};
var clock = new TestClock();
var target = new Class1 { Clock = clock };
StyleHelpers.TryAttach(style, target);
Assert.Equal(0.0, target.Double);
clock.Step(TimeSpan.Zero);
Assert.Equal(5.0, target.Double);
clock.Step(TimeSpan.FromSeconds(0.5));
Assert.Equal(7.5, target.Double);
}
[Fact]
public void Animations_With_Trigger_Should_Be_Activated_And_Deactivated()
{ {
Style style = new Style(x => x.OfType<Class1>().Class("foo")) Style style = new Style(x => x.OfType<Class1>().Class("foo"))
{ {

51
tests/Avalonia.Base.UnitTests/Styling/StyledElementTests_Theming.cs

@ -359,16 +359,49 @@ public class StyledElementTests_Theming
} }
[Fact] [Fact]
public void Implicit_Theme_Is_Cleared_When_Removed_From_Logical_Tree() public void Implicit_Theme_Is_Not_Detached_When_Removed_From_Logical_Tree()
{ {
var target = CreateTarget(); var target = CreateTarget();
var root = CreateRoot(target); var root = CreateRoot(target);
Assert.NotNull(target.GetEffectiveTheme()); Assert.Equal("theme", target.Tag);
root.Child = null; root.Child = null;
Assert.Null(target.GetEffectiveTheme()); var border = Assert.IsType<Border>(target.VisualChild);
Assert.Equal("theme", target.Tag);
Assert.Equal("theme", border.Tag);
}
[Fact]
public void Can_Attach_Then_Reattach_To_Same_Logical_Tree()
{
var target = CreateTarget();
var root = CreateRoot(target);
Assert.Equal("theme", target.Tag);
root.Child = null;
root.Child = target;
Assert.Equal("theme", target.Tag);
}
[Fact]
public void Implicit_Theme_Is_Reevaluated_When_Removed_And_Added_To_Different_Logical_Tree()
{
var target = CreateTarget();
var root1 = CreateRoot(target, "theme1");
var root2 = CreateRoot(null, "theme2");
Assert.Equal("theme1", target.Tag);
root1.Child = null;
root2.Child = target;
var border = Assert.IsType<Border>(target.VisualChild);
Assert.Equal("theme2", target.Tag);
Assert.Equal("theme2", border.Tag);
} }
[Fact] [Fact]
@ -402,10 +435,10 @@ public class StyledElementTests_Theming
private static ThemedControl CreateTarget() => new ThemedControl(); private static ThemedControl CreateTarget() => new ThemedControl();
private static TestRoot CreateRoot(Control child) private static TestRoot CreateRoot(Control? child, string themeTag = "theme")
{ {
var result = new TestRoot(); var result = new TestRoot();
result.Resources.Add(typeof(ThemedControl), CreateTheme()); result.Resources.Add(typeof(ThemedControl), CreateTheme(themeTag));
result.Child = child; result.Child = child;
result.LayoutManager.ExecuteInitialLayoutPass(); result.LayoutManager.ExecuteInitialLayoutPass();
return result; return result;
@ -530,7 +563,7 @@ public class StyledElementTests_Theming
} }
} }
private static ControlTheme CreateTheme() private static ControlTheme CreateTheme(string tag = "theme")
{ {
var template = new FuncControlTemplate<ThemedControl>((o, n) => new Border()); var template = new FuncControlTemplate<ThemedControl>((o, n) => new Border());
@ -539,7 +572,7 @@ public class StyledElementTests_Theming
TargetType = typeof(ThemedControl), TargetType = typeof(ThemedControl),
Setters = Setters =
{ {
new Setter(Control.TagProperty, "theme"), new Setter(Control.TagProperty, tag),
new Setter(TemplatedControl.TemplateProperty, template), new Setter(TemplatedControl.TemplateProperty, template),
new Setter(TemplatedControl.CornerRadiusProperty, new CornerRadius(5)), new Setter(TemplatedControl.CornerRadiusProperty, new CornerRadius(5)),
}, },
@ -550,7 +583,7 @@ public class StyledElementTests_Theming
Setters = Setters =
{ {
new Setter(Border.BackgroundProperty, Brushes.Red), new Setter(Border.BackgroundProperty, Brushes.Red),
new Setter(Control.TagProperty, "theme"), new Setter(Control.TagProperty, tag),
} }
}, },
new Style(x => x.Nesting().Class("foo").Template().OfType<Border>()) new Style(x => x.Nesting().Class("foo").Template().OfType<Border>())

16
tests/Avalonia.IntegrationTests.Appium/WindowTests.cs

@ -90,7 +90,7 @@ namespace Avalonia.IntegrationTests.Appium
try try
{ {
_session.FindElementByAccessibilityId("WindowState").SendClick(); _session.FindElementByAccessibilityId("WindowState").SendClick();
_session.FindElementByName("Normal").SendClick(); _session.FindElementByAccessibilityId("WindowStateNormal").SendClick();
// Wait for animations to run. // Wait for animations to run.
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
@ -155,11 +155,11 @@ namespace Avalonia.IntegrationTests.Appium
Assert.Equal("Normal", windowState.GetComboBoxValue()); Assert.Equal("Normal", windowState.GetComboBoxValue());
windowState.Click(); windowState.Click();
_session.FindElementByName("Maximized").SendClick(); _session.FindElementByAccessibilityId("WindowStateMaximized").SendClick();
Assert.Equal("Maximized", windowState.GetComboBoxValue()); Assert.Equal("Maximized", windowState.GetComboBoxValue());
windowState.Click(); windowState.Click();
_session.FindElementByName("Normal").SendClick(); _session.FindElementByAccessibilityId("WindowStateNormal").SendClick();
var current = GetWindowInfo(); var current = GetWindowInfo();
Assert.Equal(original.Position, current.Position); Assert.Equal(original.Position, current.Position);
@ -169,7 +169,7 @@ namespace Avalonia.IntegrationTests.Appium
if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || mode == ShowWindowMode.NonOwned) if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || mode == ShowWindowMode.NonOwned)
{ {
windowState.Click(); windowState.Click();
_session.FindElementByName("FullScreen").SendClick(); _session.FindElementByAccessibilityId("WindowStateFullScreen").SendClick();
Assert.Equal("FullScreen", windowState.GetComboBoxValue()); Assert.Equal("FullScreen", windowState.GetComboBoxValue());
current = GetWindowInfo(); current = GetWindowInfo();
@ -179,7 +179,7 @@ namespace Avalonia.IntegrationTests.Appium
windowState.SendClick(); windowState.SendClick();
_session.FindElementByName("Normal").SendClick(); _session.FindElementByAccessibilityId("WindowStateNormal").SendClick();
current = GetWindowInfo(); current = GetWindowInfo();
Assert.Equal(original.Position, current.Position); Assert.Equal(original.Position, current.Position);
@ -223,13 +223,13 @@ namespace Avalonia.IntegrationTests.Appium
// Not sure how to handle testing minimized windows currently. // Not sure how to handle testing minimized windows currently.
if (state == Controls.WindowState.Minimized) if (state == Controls.WindowState.Minimized)
continue; continue;
// Child/Modal windows cannot be fullscreen on macOS. // Child/Modal windows cannot be fullscreen on macOS.
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) &&
state == Controls.WindowState.FullScreen && state == Controls.WindowState.FullScreen &&
mode != ShowWindowMode.NonOwned) mode != ShowWindowMode.NonOwned)
continue; continue;
data.Add(size, mode, state); data.Add(size, mode, state);
} }
} }
@ -286,7 +286,7 @@ namespace Avalonia.IntegrationTests.Appium
_session.FindElementByName(location.ToString()).SendClick(); _session.FindElementByName(location.ToString()).SendClick();
stateComboBox.Click(); stateComboBox.Click();
_session.FindElementByName(state.ToString()).SendClick(); _session.FindElementByAccessibilityId($"ShowWindowState{state}").SendClick();
return showButton.OpenWindowWithClick(); return showButton.OpenWindowWithClick();
} }

74
tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Utilities;
using OpenQA.Selenium; using OpenQA.Selenium;
using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Interactions; using OpenQA.Selenium.Interactions;
@ -114,6 +115,79 @@ namespace Avalonia.IntegrationTests.Appium
Assert.Equal(1, secondaryWindowIndex); Assert.Equal(1, secondaryWindowIndex);
} }
} }
[PlatformFact(TestPlatforms.MacOS)]
public void WindowOrder_Owned_Dialog_Stays_InFront_Of_FullScreen_Parent()
{
var mainWindow = _session.FindElementByAccessibilityId("MainWindow");
// Enter fullscreen
mainWindow.FindElementByAccessibilityId("EnterFullscreen").Click();
// Wait for fullscreen transition.
Thread.Sleep(1000);
// Make sure we entered fullscreen.
var windowState = mainWindow.FindElementByAccessibilityId("MainWindowState");
Assert.Equal("FullScreen", windowState.Text);
// Open child window.
using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Owned, WindowStartupLocation.Manual))
{
mainWindow.SendClick();
var secondaryWindowIndex = GetWindowOrder("SecondaryWindow");
Assert.Equal(1, secondaryWindowIndex);
}
// Exit fullscreen by menu shortcut Command+R
mainWindow.FindElementByAccessibilityId("ExitFullscreen").Click();
// Wait for restore transition.
Thread.Sleep(1000);
// Make sure we exited fullscreen.
mainWindow = _session.FindElementByAccessibilityId("MainWindow");
windowState = mainWindow.FindElementByAccessibilityId("MainWindowState");
Assert.Equal("Normal", windowState.Text);
}
[PlatformFact(TestPlatforms.MacOS)]
public void Does_Not_Switch_Space_From_FullScreen_To_Main_Desktop_When_FullScreen_Window_Clicked()
{
// Issue #9565
var mainWindow = _session.FindElementByAccessibilityId("MainWindow");
AppiumWebElement windowState;
// Open child window.
using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Owned, WindowStartupLocation.Manual))
{
// Enter fullscreen
mainWindow.FindElementByAccessibilityId("EnterFullscreen").Click();
// Wait for fullscreen transition.
Thread.Sleep(1000);
// Make sure we entered fullscreen.
mainWindow = _session.FindElementByAccessibilityId("MainWindow");
windowState = mainWindow.FindElementByAccessibilityId("MainWindowState");
Assert.Equal("FullScreen", windowState.Text);
// Click on main window
mainWindow.Click();
// Failed here due to #9565: main window is no longer visible as the main space is now shown instead
// of the fullscreen space.
mainWindow.FindElementByAccessibilityId("ExitFullscreen").Click();
// Wait for restore transition.
Thread.Sleep(1000);
}
// Make sure we exited fullscreen.
mainWindow = _session.FindElementByAccessibilityId("MainWindow");
windowState = mainWindow.FindElementByAccessibilityId("MainWindowState");
Assert.Equal("Normal", windowState.Text);
}
[PlatformFact(TestPlatforms.MacOS)] [PlatformFact(TestPlatforms.MacOS)]
public void WindowOrder_NonOwned_Window_Does_Not_Stay_InFront_Of_Parent() public void WindowOrder_NonOwned_Window_Does_Not_Stay_InFront_Of_Parent()

23
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs

@ -899,6 +899,17 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
Assert.Equal("Foo", target.Text); Assert.Equal("Foo", target.Text);
} }
[Fact]
public void Should_Parse_And_Populate_Type_Without_Public_Ctor()
{
var xaml = @"<ObjectWithoutPublicCtor xmlns='clr-namespace:Avalonia.Markup.Xaml.UnitTests.Xaml' Test2='World' />";
var target = (ObjectWithoutPublicCtor)AvaloniaRuntimeXamlLoader.Load(xaml, rootInstance: new ObjectWithoutPublicCtor("Hello"));
Assert.NotNull(target);
Assert.Equal("World", target.Test2);
Assert.Equal("Hello", target.Test1);
}
private class SelectedItemsViewModel : INotifyPropertyChanged private class SelectedItemsViewModel : INotifyPropertyChanged
{ {
public string[] Items { get; set; } public string[] Items { get; set; }
@ -928,6 +939,18 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
Child = child; Child = child;
} }
} }
public class ObjectWithoutPublicCtor
{
public ObjectWithoutPublicCtor(string param)
{
Test1 = param;
}
public string Test1 { get; set; }
public string Test2 { get; set; }
}
public class ObjectWithAddChildOfT : IAddChild, IAddChild<string> public class ObjectWithAddChildOfT : IAddChild, IAddChild<string>
{ {

Loading…
Cancel
Save