| Summary: | Black bar at top of screen on Android in fullscreen mode | ||
|---|---|---|---|
| Product: | SDL | Reporter: | Joe LeVeque <joeleveque> |
| Component: | video | Assignee: | Sylvain <sylvain.becker> |
| Status: | RESOLVED INVALID | QA Contact: | Sam Lantinga <slouken> |
| Severity: | normal | ||
| Priority: | P2 | Keywords: | target-2.0.10 |
| Version: | 2.0.10 | ||
| Hardware: | All | ||
| OS: | Android (All) | ||
| Attachments: |
Logcat of app startup
test case |
||
Sylvain, can you look at this for 2.0.10? The desired behavior for windowed applications is that the status bar shows, and the application window is resized to fit. I wonder wether this is similar to bug 4256 or bug 4300. The size changes until the app actually goes to fullscreen. Hi Sylvain. After looking over the bugs you linked, I do believe this issue is related to them. Those bugs led me to do a bit more debugging and I found the following. I'm not sure that this is the root cause, but after reading the comments in SDLActivity.java, this logic/behavior seems broken and related: In sendCommand(), you call SDLActivity.getContext().wait(500); to wait for the surface to get resized before exiting. However, I noticed that this timeout is always reached; it never gets notified by surfaceChanged(). surfaceChanged() does not get called until this function finally times out and exits. I even increased the wait time to 10 seconds and the behavior persists. If it is necessary for surfaceChanged() to be called before sendCommand() completes for the display size to be updated correctly, then this will never happen. I haven't traced down what causes surfaceChanged() to be called, but it seems that it won't happen while sendCommand() is blocked waiting for it. - just to make sure, do you use the latest source code. Java + C. - nativePause() shouldn't be called at start-up (only if you turn the screen off, or go to background), or if the surfaceView gets modified. Can you Please can you attached an adb log cat. (grep SDL) ? - Do you have a notch/camera on your status bar ? ( I have one, and it's not draw under the status neither. even with the flags: WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES and not: LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER If this is about notch, I make it draw on the status/notch bar by adding in AndroidManifest.xml the line: <meta-data android:name="android.max_aspect" android:value="2.3" /> Created attachment 3871 [details]
Logcat of app startup
Hi Sylvain. To answer your questions above:
- Yes, I'm using the same SDL source code (Java + C) from changeset 12927
- Logcat of app startup is attached (startup_logcat.txt)
- I'm testing on two devices, one with a camera in the status bar (Galaxy S10e, running Android P) and one without (HTC 10, running Android N). Both devices exhibit this behavior. Also, my app runs in landscape mode, so the black bar at the top of my screen is actually along the side of the device, so a camera/notch shouldn't have any effect.
Ok. I am not sure if I can reproduce it or not can you try both: 1/ It seems, from your log, you're using ARGB888, can you try with 565: SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); (that should remove the intermediate sequence pause/resume at init) 2/ to set the orientation in at the end of onCreate() setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); - Switching to RGB565 as you suggested did eliminate the intermediate nativePause()/nativeResume() calls, but it did not solve the black bar issue. This is because the surface is still created with the "windowed" size of 2560x1344, then it is resized to 2560x1440, but since it was created at the "windowed" size it never actually resizes to fill the screen. - Adding "setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);" at the end of onCreate() had no effect whatsoever. It seems that the window is fixed to the size that it was initially created at the first time through the "COMMAND_CHANGE_WINDOW_STYLE" case of SDLCommandHandler.handleMessage(), even though SDL *thinks* it has changed it later on. You seem to say this is because of the window size that gets updated after going to full screen. but, I think (but I may be wrong), this would lead to a bigger or smaller height. with a black back at bottom. (which is also an issue but different). Here, it seems that it starts to draw after the status bar. the status bar is removed, but the window is not shifted to the top. - Does it happen with a minimal testcase ? createwindow / createrenderer / polling event + clear. - do you have the setting screen rotation enable or not ? - and does it happens with the phone in rotation landscape and/or inversed landscape. What I know is that the window size is initially created at the "windowed" size (with the black bar on top), and then it does not properly resize to fill the screen once SDL switches to fullscreen mode. What I see is a brief "jerk" during the transition from windowed to fullscreen, where it appears the screen quickly shifts to the top and then shifts back to where the black bar is displayed. This happens too quickly to determine if the window is also scaled up to fill the screen or if there is a black bar at the bottom of the screen for the duration of the "jerk." - I do not currently have a minimal testcase, and I'm not sure how long it would take to create one for you. - Screen rotation is enabled. - The black bar is displayed in both landscape and inverted landscape orientations. Created attachment 3874 [details]
test case
I mean, can you reproduce the issue with this file / test-case.
Or modify it so that it shows the issue
I created a simple Android project with the test case code you provided, and I am unable to reproduce the issue (however, the transitions between windowed and fullscreen mode are a bit jerky, but this is a separate topic). I believe the difference is that I am not using SDL_Renderer in my program; I'm rendering using OpenGL calls directly. I need to prove this is the root cause, but I'm fairly certain the issue boils down to this: 1. SDL initially creates the window in "windowed" mode 2. At the time I call SDL_CreateWindow() and pass the resulting SDL_Window to SDL_GL_CreateContext(), I am creating a GL context with the dimensions of the "windowed" window. 3. SDL then changes the window to "fullscreen" mode. However, since I've never cared to handle resizing the window on any platform, my program doesn't listen to changes in window size, so I never attempt resize my OpenGL context. The SDL behavior on Android has changed (the window is now created in "windowed" mode, then later resized when (if) changed to fullscreen mode), but my program's behavior hasn't changed; it assumes the original window size is the permanent window size. Thus, it seems there are two possible solutions: 1. SDL initially creates the window in the mode specified by the flags passed to SDL_CreateWindow(). If SDL creates the window in fullscreen mode, I do not have to modify my program to listen for window size changes, because there will be no behavior change with regards to previous versions of SDL. 2. I modify my program to listen for window size changes and resize my OpenGL context (and maybe other things?) accordingly. I think the proper solution is solution #1. On desktop platforms, SDL doesn't initially create a "windowed" window then change to fullscreen mode shortly thereafter. I feel that this behavior should be consistent on all platforms. However, if the SDL team deems that this behavior is acceptable on Android, I will need to modify my app to react accordingly. If so, do you have any advice for listening for Window size changes and resizing an OpenGL context accordingly using SDL? I also have issue to handle real full screen, so I can tell what is correct. I'd say, if you request at a point the display to fullscreen, it's normal that the size changes with a transition. (and it's not immediate to handle this in the code). The bad thing with android, is that when you create the window with fullscreen, it does the transition, whereas one could expect the windows created already in fullscreen. About the issue. I think the first step is maybe to reproduce on a test-case to make sure. 1/ you can drop the C test-case. in your app first, so that we make sure there is not issue with some modified java files ? 2/ try to add just a create context maybe ?! SDL_GLContext context = SDL_GL_CreateContext(the_window); 3/ if you this it has really to be a GLES2 testcase. you can pick some https://hg.libsdl.org/SDL/file/7e37d3b5e7a3/test 4/ you can also starts from your app, and comment out everything till you get a small testcase I was able to "fix" this issue by listening for SDL_WINDOWEVENT_RESIZED events and resizing my glViewport and FrameBuffer attachments accordingly. This is functionality that I would most likely need to add at some point in the future anyway, so at least it doesn't feel like a total hack or waste of time. However, it still feels like this Android behavior (starting in windowed mode then transitioning to fullscreen) isn't appropriate, but if there's no way to prevent it in SDL, then so be it. OK. I mark this resolved/invalid since SSL tenderer correctly handles it. |
On Android with the latest SDL code (changeset 12927), my fullscreen app starts up with a black bar at the top of the screen, the height of which is the height of the status bar, even though the status bar is hidden due to being in immersive mode. A little debugging shows that upon starting the app, the window style is toggled between non-fullscreen and fullscreen twice via the following calls: 1. onCreate() calls setWindowStyle(false); 2. nativeRunMain() calls setWindowStyle(true); 3. nativePause() calls setWindowStyle(false); 4. nativeResume() calls setWindowStyle(true); [Off-topic but related questions: Is this fullscreen toggling at startup expected behavior? Does onCreate() always call setWindowStyle(false)? Why is nativePause() called at startup, and why does nativePause() call setWindowStyle(false)?] It appears as though the problem occurs when switching to fullscreen mode from non-fullscreen mode. The problem seems to be related to clearing/resetting the "window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN" flag. I can make fullscreen work by commenting out the line "window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);" (line 617 of SDLActivity.java). However, this breaks non-fullscreen mode, because there is no black bar under the status bar in non-fullscreen mode; the status bar icons are overlayed on top of the fullscreen app. From the research I've done, it appears that setting/clearing the WindowManager.LayoutParams.FLAG_FULLSCREEN and WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN are now deprecated methods of toggling fullscreen mode which have been supplanted by the following: decorView.setSystemUiVisibility( // Hide the navigation bar | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // Hide the status bar | View.SYSTEM_UI_FLAG_FULLSCREEN); Reference: - https://developer.android.com/training/system-ui/immersive#EnableFullscreen - https://developer.android.com/training/system-ui/status#41 - https://stackoverflow.com/a/21273541/9919008 But apparently this doesn't seem to work properly with SDL becuase you're already setting these flags on lines 603-609 but without the window.addFlags()/window.clearFlags() calls, non-fullscreen mode doesn't work properly. I'm wondering if there is an Android call somewhere else in the SDL codebase which prevents this from working by itself without the need to call any of the window.addFlags()/window.clearFlags() functions? I'm having trouble finding a combination of calls which allows the app to cleanly toggle between fullscreen and non-fullscreen modes, resizing to allow for the presence/absence of the status and nav bars. I guess a prerequisite question that must be answered is, "What is the intended behavior when switching between fullscreen and non-fullscreen modes on Android?" Clearly fullscreen means the app occupies the entire screen; no status bar, no nav bar. When switching to non-fullscreen, should the app resize to allow for black bars under the status bar and nav bar, or should the status bar icons and nav bar icons appear over the app with a transparent? translucent? background?