From 59e4daa3582e52a8cd8827c531a4da5010d02d5a Mon Sep 17 00:00:00 2001 From: Handsome08 <409005970@qq.com> Date: Wed, 30 Jul 2025 19:04:21 +0800 Subject: [PATCH] Fix X11Screen info update incorrectly when screen changed. (#19262) --- .../Screens/X11Screen.Providers.cs | 35 ++++++++++++++----- src/Avalonia.X11/Screens/X11Screens.cs | 11 ++++-- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/src/Avalonia.X11/Screens/X11Screen.Providers.cs b/src/Avalonia.X11/Screens/X11Screen.Providers.cs index 82eb21b287..f516e0f44f 100644 --- a/src/Avalonia.X11/Screens/X11Screen.Providers.cs +++ b/src/Avalonia.X11/Screens/X11Screen.Providers.cs @@ -15,22 +15,21 @@ internal partial class X11Screens // Length of a EDID-Block-Length(128 bytes), XRRGetOutputProperty multiplies offset and length by 4 private const int EDIDStructureLength = 32; - public virtual void Refresh() + public virtual void Refresh(MonitorInfo newInfo) { if (scalingProvider == null) return; - var namePtr = XGetAtomName(x11.Display, info.Name); + var namePtr = XGetAtomName(x11.Display, newInfo.Name); var name = Marshal.PtrToStringAnsi(namePtr); XFree(namePtr); DisplayName = name; - IsPrimary = info.IsPrimary; - Bounds = new PixelRect(info.X, info.Y, info.Width, info.Height); - + IsPrimary = newInfo.IsPrimary; + Bounds = new PixelRect(newInfo.X, newInfo.Y, newInfo.Width, newInfo.Height); Size? pSize = null; - for (int o = 0; o < info.Outputs.Length; o++) + for (int o = 0; o < newInfo.Outputs.Length; o++) { - var outputSize = GetPhysicalMonitorSizeFromEDID(info.Outputs[o]); + var outputSize = GetPhysicalMonitorSizeFromEDID(newInfo.Outputs[o]); if (outputSize != null) { pSize = outputSize; @@ -121,7 +120,7 @@ internal partial class X11Screens PhysicalSize = pixelRect.Size.ToSize(Scaling); UpdateWorkArea(); } - public override void Refresh() + public override void Refresh(MonitorInfo newInfo) { } } @@ -131,6 +130,7 @@ internal partial class X11Screens nint[] ScreenKeys { get; } event Action? Changed; X11Screen CreateScreenFromKey(nint key); + MonitorInfo GetMonitorInfoByKey(nint key); } internal unsafe struct MonitorInfo @@ -224,6 +224,20 @@ internal partial class X11Screens throw new ArgumentOutOfRangeException(nameof(key)); } + + public MonitorInfo GetMonitorInfoByKey(nint key) + { + var infos = MonitorInfos; + for (var i = 0; i < infos.Length; i++) + { + if (infos[i].Name == key) + { + return infos[i]; + } + } + + throw new ArgumentOutOfRangeException(nameof(key)); + } } private class FallbackScreensImpl : IX11RawScreenInfoProvider @@ -251,6 +265,11 @@ internal partial class X11Screens return new FallBackScreen(new PixelRect(0, 0, _geo.width, _geo.height), _info); } + public MonitorInfo GetMonitorInfoByKey(nint key) + { + return default; + } + public nint[] ScreenKeys => new[] { IntPtr.Zero }; } } diff --git a/src/Avalonia.X11/Screens/X11Screens.cs b/src/Avalonia.X11/Screens/X11Screens.cs index b8ff80734c..cd6232b6f2 100644 --- a/src/Avalonia.X11/Screens/X11Screens.cs +++ b/src/Avalonia.X11/Screens/X11Screens.cs @@ -15,7 +15,7 @@ namespace Avalonia.X11.Screens _impl = (info.RandrVersion != null && info.RandrVersion >= new Version(1, 5)) ? new Randr15ScreensImpl(platform) : (IX11RawScreenInfoProvider)new FallbackScreensImpl(platform); - _impl.Changed += () => Changed?.Invoke(); + _impl.Changed += OnChanged; } protected override int GetScreenCount() => _impl.ScreenKeys.Length; @@ -24,6 +24,13 @@ namespace Avalonia.X11.Screens protected override X11Screen CreateScreenFromKey(nint key) => _impl.CreateScreenFromKey(key); - protected override void ScreenChanged(X11Screen screen) => screen.Refresh(); + protected override void ScreenChanged(X11Screen screen) + { + var handle = screen.TryGetPlatformHandle()?.Handle; + if (handle != null) + { + screen.Refresh(_impl.GetMonitorInfoByKey(handle.Value)); + } + } } }