ppy / osu-framework

A game framework written with osu! in mind.
MIT License
1.67k stars 420 forks source link

Tablet output area is not properly configured when moving the window between hdpi and ldpi display #5882

Open AkiSakurai opened 1 year ago

AkiSakurai commented 1 year ago

https://github.com/ppy/osu-framework/assets/75532970/e2326133-5c80-499b-aacc-1c12f5d21968

This issue is observed MacOS with both openGL and metal renderer. I have not tested it on other operating systems.

[runtime] 2023-07-02 00:18:17 [verbose]: fetchWindowSize Size:{Width=1366, Height=768} ClientSize:{Width=1366, Height=768}
[runtime] 2023-07-02 00:18:29 [verbose]: fetchWindowSize Size:{Width=1366, Height=768} ClientSize:{Width=2732, Height=1536}
[runtime] 2023-07-02 00:18:29 [verbose]: UpdateWindowStateAndSize Normal
[runtime] 2023-07-02 00:18:29 [verbose]: fetchWindowSize Size:{Width=1366, Height=768} ClientSize:{Width=2732, Height=1536}
[runtime] 2023-07-02 00:18:29 [verbose]: Updated display mode to desktop resolution: 1792x1120@60, SDL_PIXELFORMAT_ARGB8888
[runtime] 2023-07-02 00:18:29 [verbose]: fetchWindowSize Size:{Width=1366, Height=768} ClientSize:{Width=2732, Height=1536}

These modifications were used to generate the log. Action event is not trigged which is used to update the output area of tablet driver.

diff --git a/osu.Framework/Platform/SDL2Window_Windowing.cs b/osu.Framework/Platform/SDL2Window_Windowing.cs
index debf407df..003351439 100644
--- a/osu.Framework/Platform/SDL2Window_Windowing.cs
+++ b/osu.Framework/Platform/SDL2Window_Windowing.cs
@@ -190,6 +190,7 @@ protected set
                 if (value.Equals(size)) return;

                 size = value;
+                Logger.Log($"Invoke Action Size:{size} ClientSize:{ClientSize}");
                 Resized?.Invoke();
             }
         }
@@ -441,6 +442,7 @@ private void fetchWindowSize()

             Scale = (float)drawableW / w;
             Size = new Size(w, h);
+            Logger.Log($"fetchWindowSize Size:{Size} ClientSize:{ClientSize}");

             // This function may be invoked before the SDL internal states are all changed. (as documented here: https://wiki.libsdl.org/SDL_SetEventFilter)
             // Scheduling the store to config until after the event poll has run will ensure the window is in the correct state.
@@ -574,6 +576,7 @@ private void updateAndFetchWindowSpecifics()
         /// </summary>
         protected virtual void UpdateWindowStateAndSize(WindowState state, Display display, DisplayMode displayMode)
         {
+            Logger.Log($"UpdateWindowStateAndSize {state}");
             switch (state)
             {
                 case WindowState.Normal:
Susko3 commented 1 year ago

The underlying issue here is that Resized is invoked when the SDL2 internal window Size is changed, while the xmldoc requires it to be invoked when ClientSize is changed. (Only ClientSize is publicly exposed in IWindow.)

This is not an issue on Windows, as Size always matches ClientSize.

Susko3 commented 1 year ago

@peppy seems to have run into a similar issue on macOS. Where the size returned from SDL_Metal_GetDrawableSize doesn't match what is expected (returns the old value)

https://discord.com/channels/188630481301012481/188630652340404224/1126093119788699688

From the image in the above discord conversation, it's visible that Scale is equal to 0.5 there. As SDL_Metal_GetDrawableSize returned the old width (half the screen), the divide would result in 0.5.

https://github.com/ppy/osu-framework/blob/2622a689ad880584526833f75a5b05819dda3ab3/osu.Framework/Platform/SDL2Window_Windowing.cs#L435-L443