Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Regression] When using Theme.NoTitleBar (instead of Theme.NoTitleBar.Fullscreen), SDL2 messes up the windowed mode at launch #3102

Closed
SDLBugzilla opened this issue Feb 11, 2021 · 0 comments

Comments

@SDLBugzilla
Copy link
Collaborator

This bug report was migrated from our old Bugzilla tracker.

These attachments are available in the static archive:

Reported in version: 2.0.9
Reported for operating system, platform: Android (All), x86_64

Comments on the original bug report:

On 2018-12-15 00:48:07 +0000, Ellie wrote:

SDL 2.0.9 creates all windows without SDL_WINDOW_FULLSCREEN wrong, aren't properly windowed: instead, they're in this weird semi-immersive in between mode where the top bar and button bar will fade away, but it's not fully fullscreen - which is EXTREMELY annoying.

In 2.0.4 it works fine.

Also, to illustrate this is clearly a bug, the following statement has no effect:

SDL_SetWindowFullscreen(affected_window, 0)

... however, this suddenly makes the bars fully go away (proper fullscreen, onot the annoying bars-kinda-fade-away-sometimes mess):

SDL_SetWindowFullscreen(affected_window, SDL_WINDOW_FULLSCREEN)

... and this will actually go to PROPER windowed (bars are visible and STAY):

SDL_SetWindowFullscreen(affected_window, SDL_WINDOW_FULLSCREEN)
SDL_SetWindowFullscreen(affected_window, 0)

All on a window that never had SDL_WINDOW_FULLSCREEN in the flags of course, so it should be windowed.

I tested this on Android 7.1

On 2018-12-15 00:51:29 +0000, Ellie wrote:

It might also be related to API level, maybe. I built 2.0.9 with NDK API/minimum API 19 and target API 26, and 2.0.4 with NDK API/minimum API 14 and target API 19.

Nevertheless, the windowed mode isn't working right with 2.0.9 (without the make-temporarily-fullscreen-and-make-windowed-again hack)

On 2018-12-15 07:55:37 +0000, Ellie wrote:

I also just noticed that the workaround with SDL_SetWindowFullscreen() only seems to work with an actual delay, and/or after the window has been focused, or some other sort of event. That complicates things...

Is anyone aware of a SIMPLE approach to work around this that doesn't involve delays/timing magic?

On 2018-12-17 01:17:17 +0000, Ellie wrote:

Created attachment 3550
Illustration showing the different states I get (see comment)

The phonediff.png image illustrates the issue:

When I start the windowed app (no SDL_WINDOW_FULLSCREEN flag or similar for SDL_CreateWindow), I get Variant 3(!) - not Variant 1 as expected.

When I use SDL_SetWindowFullscren to switch to fullscreen I get Variant 2, after switching back to windowed I finally get Variant 1 which is what I want - but only if these switches have some delay, I can NOT just do them instantly after SDL_CreateWindow in a row, sadly.

And that's kinda bad, since I really want Variant 1, and that is also what older SDL2 at a lower API level gave me. So why was this changed, and how can I opt out of it/are you going to fix it?

On 2018-12-20 22:26:35 +0000, Ellie wrote:

I did some more research here into what might be going on:

https://discourse.libsdl.org/t/search-for-workaround-for-broken-windowed-mode-on-android/25467/6

It seems like a bug in the native code making incorrect assumptions about the surface size, and always resizing it to the full device screen size, even if 1.) the app uses ""@android:style/Theme.NoTitleBar" (no "Fullscreen!"), and 2.) the app doesn't use SDL_WINDOW_FULLSCREEN with SDL_CreateWindow - both things appear to just be ignored. Since the native code directly resizes the surface without calling the SDLActivity's setWindowStyle(), the top bar & menu/action bar aren't properly hidden and this broken in-between mode appears to be entered.

To reproduce:

  1. Change the AndroidManifest.xml of the example project such that android:theme="@android:style/Theme.NoTitleBar" (note the lacking Fullscreen!)

  2. Write a simple app that uses SDL_CreateWindow() without SDL_WINDOW_FULLSCREEN

I haven't tested with a minimal app yet but I'm fairly certain this should be enough to see the issue

On 2018-12-20 22:30:50 +0000, Ellie wrote:

Addition: I only dug around in SDLActivity.java with additional debug logging to see what is called, and observed what was going on from the outside - so I haven't checked the native code itself yet. But I hope I was able to provide some interesting pointers to someone familiar with it to possibly find out what's going on

On 2018-12-23 10:28:47 +0000, Ellie wrote:

Ok this is kind infuriating!!

I hacked in this into SDLActivity.java's setOrientationBis() with a runOnUIThread(...) runnable to run on the first call of it, since I observed this usually happens right after SDL2 breaks the surface size and ruins everything:

                    Context context = SDL.getContext();
                    if (context != null && context instanceof Activity) {
                        Window window = ((Activity) context).getWindow();
                        if (window != null) {
                            Log.v(TAG, "Setting flags to ensure proper windowed mode");
                            int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
                                View.SYSTEM_UI_FLAG_VISIBLE;
                            window.getDecorView().setSystemUiVisibility(flags);
                            window.addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
                            window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
                            SDLActivity.mFullscreenModeActive = false;
                        }
                    }

... because I thought well, might as well undo that nonsense and maybe that fixes it?

And this is what happens:

12-23 11:20:15.252 18588 18588 V SDL : surfaceChanged()
12-23 11:20:15.252 18588 18588 V SDL : pixel format RGB_565
12-23 11:20:15.259 18588 18588 V SDL : Window size: 2160x1080
12-23 11:20:15.259 18588 18588 V SDL : Device size: 2160x1080
<SDL2 native code launches now, breaks things>
<my hack runs in first setOrientationBis() with above code>
12-23 11:20:27.324 18588 18588 V SDL : surfaceChanged()
12-23 11:20:27.324 18588 18588 V SDL : pixel format RGB_565
12-23 11:20:27.327 18588 18588 V SDL : Window size: 2016x1008
12-23 11:20:27.327 18588 18588 V SDL : Device size: 2160x1080
12-23 11:20:27.327 18588 18621 V SDL : setOrientation() orientation=-1 width=900 height=800 resizable=true hint=
<SDL2 native code thinks it's being smarter than me......>
12-23 11:20:29.436 18588 18588 V SDL : surfaceChanged()
12-23 11:20:29.436 18588 18588 V SDL : pixel format RGB_565
12-23 11:20:29.437 18588 18588 V SDL : Window size: 2160x1080
12-23 11:20:29.437 18588 18588 V SDL : Device size: 2160x1080

So yeah. The native code just appears to be always resetting this BACK to the wrong size. Jeez.

So unless I do SDL_SetWindowFullscreen() twice with a delay in the native code (which in python-for-android I can't MAKE the app do from the outside wrapper, so applying this hack from outside is almost impossible) I have no chance of avoiding this issue, and I'm now 99% certain the SDL2 native code is at fault.

So could someone take a look at this maybe? Because this is really a major problem for windowed mode...

On 2019-01-02 09:40:21 +0000, Ellie wrote:

Ok so I changed SDLActivity.java's corde like this to make it enforce proper windowed mode if fullscreen isn't active:

private final Runnable rehideSystemUi = new Runnable() {
    @Override
    public void run() {
        int flags = View.SYSTEM_UI_FLAG_FULLSCREEN |
                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
                    View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
                    View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
                    View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.INVISIBLE;

        SDLActivity.this.getWindow().getDecorView().setSystemUiVisibility(flags);
    }
};

private final Runnable reshowSystemUi = new Runnable() {
    @Override
    public void run() {
        int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_VISIBLE;
        SDLActivity.this.getWindow().getDecorView().setSystemUiVisibility(flags);
        SDLActivity.this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
        SDLActivity.this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }
};

public void onSystemUiVisibilityChange(int visibility) {
    Log.v(TAG, "onSystemUiVisibilityChange(" + visibility + ")");

    if (SDLActivity.mFullscreenModeActive && (visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0 || (visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) {
        Log.v(TAG, "onSystemUiVisibilityChange(): re-hiding navigation");
        Handler handler = getWindow().getDecorView().getHandler();
        if (handler != null) {
            handler.removeCallbacks(rehideSystemUi); // Prevent a hide loop.
            handler.postDelayed(rehideSystemUi, 2000);
        }
    } else if (!SDLActivity.mFullscreenModeActive && ((visibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) == 0 ||
            (visibility & View.SYSTEM_UI_FLAG_VISIBLE) == 0 ||
            (visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0)) {
        Log.v(TAG, "onSystemUiVisibilityChange(): re-showing navigation");
        Handler handler = getWindow().getDecorView().getHandler();
        if (handler != null) {
            handler.removeCallbacks(reshowSystemUi); // Prevent a hide loop.
            handler.postDelayed(reshowSystemUi, 2000);
        }
    }
}

The result is that I get stuck in a cycle of 1 sec proper windowed mode, 1 sec broken sliding-away-bars-mode constantly changing back and forth, as if some component is fighting me over it.

I would be really happy if someone had an educated guess on what component that is. I already searched through the native code, and outside of the GL stuff, I couldn't find anything that actively enforces a certain surface or window size. Where is this call coming from???

On 2019-01-02 14:16:20 +0000, Ellie wrote:

FOUND THE BUG!!! It's in SDLActivity.java:

  •    if (SDLActivity.mFullscreenModeActive && (visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0 || (visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) {
    
  •    if (SDLActivity.mFullscreenModeActive && ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0 || (visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0)) {
    

Since this issue is so annoying, could this go into a some-time-soon patch release? Windowed mode is pretty much unusable without this fix!

On 2019-01-02 16:12:28 +0000, Sylvain wrote:

Great ! I added your patch, it sounds goods. Seems a typo.

https://hg.libsdl.org/SDL/rev/3b1f484500f0

This initially was here https://hg.libsdl.org/SDL/rev/842dd960769e

Maybe this mFullscreenModeActive is not even needed ?

I am closing the issue. but re-open, if it needs more improvements

On 2019-01-02 16:13:15 +0000, Sylvain wrote:

Fixed!

On 2019-01-02 16:19:04 +0000, Ellie wrote:

For what it's worth, mFullscreenModeActive is definitely needed!

This is what the code does:

  1. It triggers when anything about status bar/action bar changes
  2. It checks if SYSTEM_UI_FLAG_FULLSCREEN is not set, or anything else about the fullscreen layout is broken
  3. It restores the proper layout by setting SYSTEM_UI_FLAG_FULLSCREEN

This is necessary because Android likes to re-show the bars if the user does certain swipes, so this code is supposed to hide them again. However, hiding those bars in WINDOWED mode just breaks everything entirely, which was the bug.

mFullscreenModeActive is changed through setWindowStyle(), which is called by the native code depending on whether the SDL2 window is supposed to be fullscreened or not. So yes, evaluating that is vital for this code part

On 2019-01-02 16:20:15 +0000, Ellie wrote:

Thanks for adding the fix! Looking forward to seeing this work properly in the next release

On 2019-01-02 16:30:01 +0000, Sylvain wrote:

Ok, thanks for the explanation I got it !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant