瀏覽代碼

Fix headless screens (#16348)

* Fix headless screens being null

* Remove unused properties
Max Katz 1 年之前
父節點
當前提交
460a3549d5

+ 0 - 1
src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs

@@ -101,7 +101,6 @@ namespace Avalonia.Android.Platform.SkiaPlatform
         internal InvalidationAwareSurfaceView InternalView => _view;
 
         public double DesktopScaling => RenderScaling;
-        public IScreenImpl? Screen { get; }
         public IPlatformHandle Handle => _view;
 
         public IEnumerable<object> Surfaces { get; }

+ 3 - 1
src/Avalonia.Controls/Screens.cs

@@ -163,7 +163,9 @@ namespace Avalonia.Controls
                 var tl = visual.PointToScreen(visual.Bounds.TopLeft);
                 var br = visual.PointToScreen(visual.Bounds.BottomRight);
 
-                return ScreenFromBounds(new PixelRect(tl, br));
+                // Attempt to get screen from the physical position on any screen first. Fallback to the screen hosting top level.
+                return ScreenFromBounds(new PixelRect(tl, br))
+                    ?? ScreenFromTopLevel(topLevel);
             }
             else
             {

+ 0 - 1
src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs

@@ -125,7 +125,6 @@ namespace Avalonia.Browser
         }
 
         public double DesktopScaling => RenderScaling;
-        public IScreenImpl? Screen { get; }
         public IPlatformHandle? Handle { get; }
         public Size ClientSize => _surface?.ClientSize ?? new Size(1, 1);
         public Size? FrameSize => null;

+ 8 - 2
src/Headless/Avalonia.Headless/HeadlessWindowImpl.cs

@@ -19,6 +19,7 @@ namespace Avalonia.Headless
         private static int _nextGlobalZOrder = 1;
 
         private readonly IKeyboardDevice _keyboard;
+        private readonly IScreenImpl _screen;
         private readonly Stopwatch _st = Stopwatch.StartNew();
         private readonly Pointer _mousePointer;
         private WriteableBitmap? _lastRenderedFrame;
@@ -32,6 +33,7 @@ namespace Avalonia.Headless
             IsPopup = isPopup;
             Surfaces = new object[] { this };
             _keyboard = AvaloniaLocator.Current.GetRequiredService<IKeyboardDevice>();
+            _screen = new HeadlessScreensStub();
             _mousePointer = new Pointer(Pointer.GetNextFreeId(), PointerType.Mouse, true);
             MouseDevice = new MouseDevice(_mousePointer);
             ClientSize = new Size(1024, 768);
@@ -150,7 +152,6 @@ namespace Avalonia.Headless
 
         }
 
-        public IScreenImpl Screen { get; } = new HeadlessScreensStub();
         public WindowState WindowState { get; set; }
         public Action<WindowState>? WindowStateChanged { get; set; }
         public void SetTitle(string? title)
@@ -266,11 +267,16 @@ namespace Avalonia.Headless
         public AcrylicPlatformCompensationLevels AcrylicCompensationLevels => new AcrylicPlatformCompensationLevels(1, 1, 1);
         public object? TryGetFeature(Type featureType)
         {
-        	if(featureType == typeof(IClipboard))
+        	if (featureType == typeof(IClipboard))
             {
                 return AvaloniaLocator.Current.GetRequiredService<IClipboard>();
             }
 
+            if (featureType == typeof(IScreenImpl))
+            {
+                return _screen;
+            }
+
             return null;
         }
 

+ 0 - 1
src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs

@@ -54,7 +54,6 @@ using Avalonia.Rendering.Composition;
         }
 
         public double DesktopScaling => 1;
-        public IScreenImpl Screen { get; }
         public IPlatformHandle Handle { get; }
         public Size ClientSize => ScaledSize;
         public Size? FrameSize => null;

+ 0 - 1
src/Tizen/Avalonia.Tizen/TopLevelImpl.cs

@@ -27,7 +27,6 @@ internal class TopLevelImpl : ITopLevelImpl
     }
 
     public double DesktopScaling => RenderScaling;
-    public IScreenImpl? Screen { get; }
     public IPlatformHandle? Handle { get; }
 
     public Size ClientSize => _view.ClientSize;

+ 0 - 1
src/iOS/Avalonia.iOS/AvaloniaView.cs

@@ -222,7 +222,6 @@ namespace Avalonia.iOS
             }
 
             public double DesktopScaling => RenderScaling;
-            public IScreenImpl? Screen { get; }
             public IPlatformHandle? Handle { get; }
             public Size ClientSize => new Size(_view.Bounds.Width, _view.Bounds.Height);
             public Size? FrameSize => null;

+ 29 - 0
tests/Avalonia.Headless.UnitTests/ServicesTests.cs

@@ -0,0 +1,29 @@
+using System;
+using System.Reactive.Disposables;
+using System.Threading;
+using Avalonia.Controls;
+using Avalonia.Input;
+using Avalonia.Layout;
+using Avalonia.Threading;
+
+namespace Avalonia.Headless.UnitTests;
+
+public class ServicesTests
+{
+#if NUNIT
+    [AvaloniaTest, Timeout(10000)]
+#elif XUNIT
+    [AvaloniaFact(Timeout = 10000)]
+#endif
+    public void Can_Access_Screens()
+    {
+        var window = new Window();
+        var screens = window.Screens;
+        Assert.NotNull(screens);
+
+        var currentScreenFromWindow = screens.ScreenFromWindow(window);
+        var currentScreenFromVisual = screens.ScreenFromVisual(window);
+
+        Assert.True(ReferenceEquals(currentScreenFromWindow, currentScreenFromVisual));
+    }
+}

+ 0 - 1
tests/Avalonia.UnitTests/CompositorTestServices.cs

@@ -159,7 +159,6 @@ public class CompositorTestServices : IDisposable
         }
 
         public double DesktopScaling => 1;
-        public IScreenImpl Screen { get; }
         public IPlatformHandle Handle { get; }
         public Size ClientSize { get; }
         public Size? FrameSize { get; }