microsoft-ui-xaml icon indicating copy to clipboard operation
microsoft-ui-xaml copied to clipboard

How to remove the flickering of WinUI3 Window on resizing

Open selastingeorge opened this issue 4 years ago • 50 comments

I am new to WinUI3, I have created a sample app and when I resize it, there is a flickering in window, In WPF it was able to fix this flickering issue. but on winUI3 it is not working, is there any way to fix it.

I know that The Content Rendered in the window is created by Direct Composition and all the contents are hosted as a child window in a parent window, and i usually adjust WndProc to adjust the flickering some how I was not even able to override the wndPoc like i did for wpf, is there any way to fix this flickering.

Here is the screenshot of the issue:

Animation

selastingeorge avatar Jun 04 '21 13:06 selastingeorge

We're currently working on fixing this. The plan is that instead of having that background color always be white it will instead be white or black depending on the value of Window.Content.RequestedTheme.

codendone avatar Jun 05 '21 02:06 codendone

The How can i get access to the WndProc, will sub classing work ? Why is it not possible to create a transparent window, i just added used the SetWindowCompositionAttribute() and set it to INVALID_STATE, usually it creates the same effect as the WS_EX_NOREDIRECTIONBITMAP in WPF but in Win UI some white background is covering the window,.

selastingeorge avatar Jun 05 '21 02:06 selastingeorge

@codendone So instead of properly synchronizing the rendering with window sizing events you simply want to hide the issue by coloring? How will it help to eliminate the obvious title bar buttons flicker?

float34 avatar Jun 05 '21 05:06 float34

Agree with @torquerrr - and what if there's a custom image / gradient background set? This doesn't sound like an actual solution to the problem..

niels9001 avatar Jun 05 '21 05:06 niels9001

When i checked the window with Spy++ i found that the child window hosted inside the parent is uses class Microsoft.UI.Hosting.Experimental.ContentWindowBridge, when i checked the caption of window this shows DesktopWindowBridge, which points me to other classes their in which one (Microsoft.UI.Hosting.Experimental.ExpSystemVisualBridge) has background property, will it be helpful, these are undocumented and i don't know what it does ?

And Check out these : image

Here the Child window uses WS_EX_NOREDIRECTIONBITMAP Which means the Child window draws a background using Direct Composition and the Window actually doesn't have a background.

selastingeorge avatar Jun 05 '21 14:06 selastingeorge

We're currently working on fixing this. The plan is that instead of having that background color always be white it will instead be white or black depending on the value of Window.Content.RequestedTheme.

Thats a hack but it's not a solution, why is it rendered when not ready? The window resize is already delayed from the mouse dragging, so why not just syncing it. Windows is the only OS where this still happens. A simple color theme will not help if a sidebar is jumping around like a cat in heat.

llothar avatar Jun 05 '21 14:06 llothar

We're currently working on fixing this. The plan is that instead of having that background color always be white it will instead be white or black depending on the value of Window.Content.RequestedTheme.

Thats a hack but it's not a solution, why is it rendered when not ready? The window resize is already delayed from the mouse dragging, so why not just syncing it. Windows is the only OS where this still happens. A simple color theme will not happen when the sidebar at that location is jumping around like a cat in heat.

I have used Windows.UI.Composition wpf samples, those windows were also having the flickering but i was able to fix it by setting the window style to none and allow transparency to true. i think it won't work here.

Here is a sample wpf app: Animation

selastingeorge avatar Jun 05 '21 14:06 selastingeorge

@SelastinGeorge Seems to be the same issue as https://github.com/microsoft/microsoft-ui-xaml/issues/2506. It is a long standing problem with how Windows handles the window resize. You can read how bad it actually is here. I don't expect it to be fixed ever.

float34 avatar Jun 06 '21 06:06 float34

Actually i fixed the flickering issue in WPF by overriding the WndProc. Responding to WM_NCCALCSIZE with any RECT smaller than the window solves the problem. But i don't know it will work on child windows

selastingeorge avatar Jun 06 '21 06:06 selastingeorge

Lots of good discussion on this thread. I agree with comments that setting a better background color is an incomplete solution, but as @torquerrr said, handling resize well in Windows is difficult. Windows has code to attempt to synchronize window frame redraw with when the app content has finished drawing, but that synchronization code requires Windows to know when the app is finished drawing. WinUI3 draws all app content into a swapchain, which Windows intentionally never synchronizes to favor performance of the swapchain. Window resize is a case where synchronization might be desirable. I think this needs to be investigated, but supporting synchronized resize would be significant work and likely requires an OS update.

Because of all that, a better background color will at least reduce the visible flicker for dark theme apps without waiting for a full synchronized resize solution.

codendone avatar Jun 07 '21 05:06 codendone

I Know this is not the question i should ask in this thread, but it's just a small doubt ,I was also trying to implement transparent background and acrylic effect also in win ui3, i was able to implement both in Win32 using the DWMThumbnail API, but the DWM Thumbnail Api Outputs the Content Behind Window on to IDCompositionVisual2 , is there any way to convert it to Microsoft.UI.Composition.Visual

Here is the demo screen shot:

image

Here the Position i marked using Red Rectangle is not caused by WS_EX_NOREDIRECTIONBITMAP, its dwm thumbnail based, After blurring it will be:

image

If I could get these visual to Microsoft.UI.Composition.Visual, I might be able to bring back Transparency+ Acrylic to win UI 3, I believe So.

selastingeorge avatar Jun 07 '21 05:06 selastingeorge

@codendone As far as I know default Windows 10 apps (News, Maps, Photos) use DirectComposition API, and they don't have the resize issue being discussed. Why WinUI 3 draws to swapchain (with DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL/DXGI_SWAP_EFFECT_FLIP_DISCARD I guess?) instead? To cover the needs of both 2D apps and 3D games (which need maximum performance)?

float34 avatar Jun 08 '21 04:06 float34

@torquerrr WinUI 3 uses Microsoft.UI.Composition, which is part of Project Reunion, rather than Windows.UI.Composition. Using Microsoft.UI.Composition means we can update it when desired, just like we can with the XAML code of WinUI 3, and that those updates are available on all OS versions supported by Project Reunion, rather than only being on the latest OS version.

codendone avatar Jun 09 '21 05:06 codendone

@codendone So, do we need to add "feature-request" label or close it and all relevant stories?

float34 avatar Jun 13 '21 05:06 float34

We should keep this active, and I think just an issue is fine here. This is being tracked internally as a feature due to its cost and complexity.

codendone avatar Jul 30 '21 05:07 codendone

Definitely with everyone else in this thread, syncing the clear color with the Windows theme is not a solution. The proposed hack would look just as bad as it does now if the page:

a. Uses a background color that doesn't perfectly match the windows theme or b. has content anywhere near the edges

etkramer avatar Sep 29 '21 20:09 etkramer

The plan is that instead of having that background color always be white it will instead be white or black depending on the value of Window.Content.RequestedTheme.

I agree with the others that this seems a poor workaround at best. Still, a workaround that makes these artifacts less noticeable is better than no fix at all, at least until a proper fix is available. It would be good, however, to be able to set a custom color for this instead of having white/black hardcoded. My app, for example, uses an orange background, so neither white nor black looks good.

chausner avatar Jan 15 '22 18:01 chausner

Is there an update on this? This is turning me away from wanting to use WinUI 3.

nathanAjacobs avatar Jun 01 '22 22:06 nathanAjacobs

Is there an update on this? This is turning me away from wanting to use WinUI 3.

There is no more flickering :

WinUI3_Resize

castorix avatar Jun 02 '22 06:06 castorix

We should keep this active, and I think just an issue is fine here. This is being tracked internally as a feature due to its cost and complexity.

@codendone May I ask the current status of this internal ticket? Is it ever been worked on since it's created?

wangwenx190 avatar Jun 02 '22 06:06 wangwenx190

Is there an update on this? This is turning me away from wanting to use WinUI 3.

There is no more flickering :

WinUI3_Resize

@castorix That looks a lot better, but can you verify whether the content still flickers or not if you remove the whole window frame (by not modifying the non-client area and returning 0 directly in WM_NCCALCSIZE) ? And from your video it looks like the contents are jumping around because of window resizing, that's really not nice.

wangwenx190 avatar Jun 02 '22 06:06 wangwenx190

@castorix That looks a lot better, but can you verify whether the content still flickers or not if you remove the whole window frame (by not modifying the non-client area and returning 0 directly in WM_NCCALCSIZE) ? And from your video it looks like the contents are jumping around because of window resizing, that's really not nice.

If I remove the frame by subclassing it, the result is the same (I can only resize once as there is no more sizing border...) But the jumping content is clearly not good (if I test resising with WPF for example with also a centered button, it is smoother)

castorix avatar Jun 02 '22 13:06 castorix

There is no more flickering :

https://user-images.githubusercontent.com/37193095/171750464-b4368a38-6a0e-43ad-8ff9-2ac98b23692c.mp4

@castorix I definitely have flickering...

I'm pretty sure the only reason you do not see flickering is because you are using a theme with a dark background and your background is set to black.

I could be wrong, but could this be solved by adding a Background property to the Window control? It currently does not have one.

nathanAjacobs avatar Jun 02 '22 22:06 nathanAjacobs

@nathanAjacobs You can try the WS_EX_NOREDIRECTIONBITMAP style, enabling that style will cause your window doesn't have a background at all (it won't affect the window frame and the title bar), so the flicker may be removed. But that style is only supported on window creation time, that is, when you call the CreateWindow function. If you try to enable or disable that style after the window has been created, it will have no effect.

wangwenx190 avatar Jun 03 '22 04:06 wangwenx190

@nathanAjacobs You can try the WS_EX_NOREDIRECTIONBITMAP style, enabling that style will cause your window doesn't have a background at all (it won't affect the window frame and the title bar), so the flicker may be removed. But that style is only supported on window creation time, that is, when you call the CreateWindow function. If you try to enable or disable that style after the window has been created, it will have no effect.

I'm working in a C# project, so I'm not sure I can even try that. WPF and UWP do not have this problem. This issue prevents any app from using a custom background color that doesn't match close enough to the current system theme. I feel like this issue needs to be properly addressed sooner than later if they want people to adopt WinUI 3 over other frameworks.

nathanAjacobs avatar Jun 03 '22 07:06 nathanAjacobs

@nathanAjacobs You can try the WS_EX_NOREDIRECTIONBITMAP style, enabling that style will cause your window doesn't have a background at all (it won't affect the window frame and the title bar), so the flicker may be removed. But that style is only supported on window creation time, that is, when you call the CreateWindow function. If you try to enable or disable that style after the window has been created, it will have no effect.

But there is a possible way to achieve the same effect using setwindowcompositionattribute(), using ACCENT_INVALID_STATE gives us a transparent window which has same behaviour as WS_EX_NOREDIRECTIONBITMAP.

selastingeorge avatar Jun 03 '22 08:06 selastingeorge

I'm pretty sure the only reason you do not see flickering is because you are using a theme with a dark background and your background is set to black.

I could be wrong, but could this be solved by adding a Background property to the Window control? It currently does not have one.

I use the standard Dark Theme on Windows 10 (21H1) You can change the background color in WM_ERASEBKGND, like I did in some samples I posted, but it is just a workaround

castorix avatar Jun 03 '22 08:06 castorix

Actually you can remove the complete background, like this:

image

Try this :

https://github.com/microsoft/microsoft-ui-xaml/issues/1247#issuecomment-653373428

selastingeorge avatar Jun 03 '22 08:06 selastingeorge

They added a background in 1.1.0 stable version. (which breaks transparency which could be done with ULW_COLORKEY as it is drawn over...) ...which does not solve the problem if you use another background color :

Flickering

castorix avatar Jun 08 '22 07:06 castorix

It's pretty surprising that this issue is still present in 1.1.0 stable release, however I managed to solve it with some help from castorix's interop code in his demo sample from the transparency issue thread.

I basically made a BetterWindow class which inherits from Window that handles all the Win32 interop and added Background, MinWidth, and MinHeight properties to it. Unfortunately, the Background property cannot be bound to a ThemeResource via XAML. I think it's because Window doesn't inherit from DependencyObject, but I'm not entirely sure. It basically just means if you desire the Background property to respect theme changes it has to be handled from code behind. Also, the BetterWindow class I made doesn't support Window transparency, but I'm sure that can be added if you need it.

There's another flickering issue, but I believe it's unrelated to this flickering issue on the edge of windows. You can notice when resizing the window at certain sizes, that the window's content disappears completely for a split second.

I will post the demo project to a repo and link it here shortly, but here is a video of my results in the meantime:

https://user-images.githubusercontent.com/37193095/173190803-f6bf979e-7ae7-4530-9fea-132586895dea.mp4

nathanAjacobs avatar Jun 11 '22 14:06 nathanAjacobs