From e0b8da8e8559e7347276a43b2d5d7216504ea9d0 Mon Sep 17 00:00:00 2001 From: walterlv Date: Thu, 12 Sep 2024 18:01:10 +0800 Subject: [PATCH] Fix an issue that if WindowState is been set in the constructor, the contents that not been layouted or rendered will be shown. --- src/Avalonia.X11/X11Window.cs | 59 +++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 556dbdfec1..bc159087b3 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -686,7 +686,7 @@ namespace Avalonia.X11 ChangeWMAtoms(false, _x11.Atoms._NET_WM_STATE_FULLSCREEN); ChangeWMAtoms(true, _x11.Atoms._NET_WM_STATE_MAXIMIZED_VERT, _x11.Atoms._NET_WM_STATE_MAXIMIZED_HORZ); - MapWindow(); + MapOrActiveWindow(); } else if (value == WindowState.FullScreen) { @@ -694,7 +694,7 @@ namespace Avalonia.X11 ChangeWMAtoms(true, _x11.Atoms._NET_WM_STATE_FULLSCREEN); ChangeWMAtoms(false, _x11.Atoms._NET_WM_STATE_MAXIMIZED_VERT, _x11.Atoms._NET_WM_STATE_MAXIMIZED_HORZ); - MapWindow(); + MapOrActiveWindow(); } else { @@ -702,7 +702,7 @@ namespace Avalonia.X11 ChangeWMAtoms(false, _x11.Atoms._NET_WM_STATE_FULLSCREEN); ChangeWMAtoms(false, _x11.Atoms._NET_WM_STATE_MAXIMIZED_VERT, _x11.Atoms._NET_WM_STATE_MAXIMIZED_HORZ); - MapWindow(); + MapOrActiveWindow(); } WindowStateChanged?.Invoke(value); } @@ -1206,33 +1206,38 @@ namespace Avalonia.X11 } - /// - /// Map the window to the screen. - /// - /// - /// Why we map the window using XMapRequestEvent instead of XMapWindow or SendNetWMMessage?
- /// See details at https://github.com/AvaloniaUI/Avalonia/pull/16922 - ///
- private void MapWindow() + private void MapOrActiveWindow() { - var e = new XEvent + if (_wasMappedAtLeastOnce) { - MapRequestEvent = new XMapRequestEvent + // If the window has been mapped at least once, we should use XMapRequestEvent instead of XMapWindow or SendNetWMMessage. + // See details at https://github.com/AvaloniaUI/Avalonia/pull/16922 + var e = new XEvent { - type = XEventName.MapRequest, - serial = new IntPtr(0), - display = _x11.Display, - send_event = 1, - parent = _x11.RootWindow, - window = _handle, - }, - }; - XSendEvent( - _x11.Display, - _x11.RootWindow, - false, - new IntPtr((int)EventMask.SubstructureRedirectMask), - ref e); + MapRequestEvent = new XMapRequestEvent + { + type = XEventName.MapRequest, + serial = new IntPtr(0), + display = _x11.Display, + send_event = 1, + parent = _x11.RootWindow, + window = _handle, + }, + }; + XSendEvent( + _x11.Display, + _x11.RootWindow, + false, + new IntPtr((int)EventMask.SubstructureRedirectMask), + ref e); + } + else + { + // If the window has never been mapped, we should send _NET_ACTIVE_WINDOW message. + // Otherwise, the window will show too early so that content that not been layouted or rendered will be shown. + SendNetWMMessage(_x11.Atoms._NET_ACTIVE_WINDOW, (IntPtr)1, _x11.LastActivityTimestamp, + IntPtr.Zero); + } } private void BeginMoveResize(NetWmMoveResize side, PointerPressedEventArgs e)