SDL_SetWindowFullscreen on iOS

I use SDL_SetWindowFullscreen() on both Android and iOS. On Android it works as I would expect: passing zero for the flags value (i.e. switching to ‘windowed’ mode) results in the status bar being enabled and SDL’s canvas* being reduced in size accordingly.

But on iOS it is behaving differently. The status bar is displayed, just as it is on Android, but SDL’s canvas is not reduced in size, with the result that it overlaps the status bar and (more seriously) I get no touch events from that region!

How can I make the behavior in iOS match that in Android, i.e. reduce the size of SDL’s canvas so it doesn’t overlap the status bar?

[*] That is, the size returned by SDL_GL_GetDrawableSize().

Looking at the code, the key seems to be this in SDL_uikitvideo.m:

/* The view should always show behind the status bar in iOS 7+. */

which suggests the behavior is by design. But how in practice are we supposed to work with this? If SDL’s canvas is behind the status bar, no touch events will be received from this region and (it seems) SDL’s output must have a light color here otherwise the status/notification icons won’t be visible anyway!

That’s just how iOS is. The old days of the status bar being a separate area are gone. It was a deliberate design choice in iOS 7 to have the content appear under the status bar. Apps that use UIKit or SwiftUI can get information from the system about how far down the status bar extends so they don’t put anything important underneath it, and apps that use navigation bars mostly automagically get that behavior.

edit: also, somewhere (been a long time since I’ve done a regular iOS app) there is the ability to tell the system whether the content under the status bar is light or dark, so iOS can adjust the color of the status bar text and icons accordingly, but I don’t remember where. IIRC it’s not meant to be something you’re changing every frame, just any time there’s a new view being displayed etc.

Maybe, but SDL is an abstraction layer, its whole purpose is to hide differences between OSes so that the application program, and the user experience, can be as similar as possible.

In Android the status bar is a separate area: if I switch to ‘windowed’ mode in order to display the status/notification bar (and the virtual menu, home and back buttons) SDL’s canvas is automatically resized so as not to overlap them.

I don’t mind if there’s a hint to override it, but in my opinion the default behavior of SDL should be for iOS and Android to work in as similar a way as possible. There’s nothing in the documentation of SDL_SetWindowFullscreen() to suggest otherwise.

So, at the very least, if SDL is going to display its canvas behind the status bar it should expose this information somehow.

Yes, I’ve now changed the status bar content to light via the project settings (although that’s apparently deprecated in favour of doing it in code).

I’ve now hit another issue. In iOS any of my programs which bypass SDL’s renderer and create an OpenGL context (e.g. for 3D or shader graphics) crash if not in fullscreen mode (i.e. the status bar is visible)! In Android everything is fine and those same programs work perfectly even if the status bar (and virtual buttons etc.) are displayed.

There will always be times when differences between operating systems require you to make special cases or handle things yourself.

On iOS the status bar isn’t a separate area. Applications are not only free to display content under it, they are expected to do so, such as when scrolling (the exception is navigation bars, which automatically adjust downward, but scrolling content gets displayed under the navigation bar instead).

The documentation doesn’t make any mention of Android status bar behavior either.

Given that OpenGL is deprecated on iOS, I’m not surprised that there are bugs. OpenGL basically only still exists on iOS and macOS for legacy stuff. On iOS it’s implemented as a layer that sits on top of Metal!

Yes of course, but they should be the exception. As a rule I would expect SDL to make the behavior on different platforms as similar as possible.

There must be many situations when that isn’t appropriate, such as when the scrolling information is selectable (e.g. a text editor) - because touch events don’t register there.

Indeed, which to me implies that the behavior should be the same, or at least as similar as possible, on all platforms. Variation between platforms should always be highlighted in the docs.

Yes, but I have to use it since my application is a programming language - and programs written in that language can contain embedded OpenGL or Shader code! It’s for that reason that I use the OpenGL backend in Windows too.