diff --git a/src/common/ios.h b/src/common/ios.h index 1b9730948..5ff272d5d 100644 --- a/src/common/ios.h +++ b/src/common/ios.h @@ -25,8 +25,12 @@ #ifdef LOVE_IOS +#include "common/math.h" + #include +struct SDL_Window; + namespace love { namespace ios @@ -74,6 +78,12 @@ void setAudioMixWithOthers(bool mixEnabled); **/ bool hasBackgroundMusic(); +/** + * Gets the area in the window that is safe for UI to render to (not covered by + * the status bar, notch, etc.) + **/ +Rect getSafeArea(SDL_Window *window); + } // ios } // love diff --git a/src/common/ios.mm b/src/common/ios.mm index ff5406206..337ba4788 100644 --- a/src/common/ios.mm +++ b/src/common/ios.mm @@ -31,6 +31,8 @@ #include #include +#include +#include static NSArray *getLovesInDocuments(); static bool deleteFileInDocuments(NSString *filename); @@ -362,9 +364,45 @@ void setAudioMixWithOthers(bool mixEnabled) bool hasBackgroundMusic() { - if ([[AVAudioSession sharedInstance] respondsToSelector:@selector(secondaryAudioShouldBeSilencedHint)]) - return [[AVAudioSession sharedInstance] secondaryAudioShouldBeSilencedHint]; - return false; + @autoreleasepool + { + AVAudioSession *session = [AVAudioSession sharedInstance]; + if ([session respondsToSelector:@selector(secondaryAudioShouldBeSilencedHint)]) + return session.secondaryAudioShouldBeSilencedHint; + return false; + } +} + +Rect getSafeArea(SDL_Window *window) +{ + @autoreleasepool + { + Rect rect = {}; + SDL_GetWindowSize(window, &rect.w, &rect.h); + + SDL_SysWMinfo info = {}; + SDL_VERSION(&info.version); + if (SDL_GetWindowWMInfo(window, &info)) + { + UIView *view = info.info.uikit.window.rootViewController.view; + if (@available(iOS 11.0, tvOS 11.0, *)) + { + UIEdgeInsets insets = view.safeAreaInsets; + + rect.x += insets.left; + rect.w -= insets.left; + + rect.w -= insets.right; + + rect.y += insets.top; + rect.h -= insets.top; + + rect.h -= insets.bottom; + } + } + + return rect; + } } } // ios diff --git a/src/modules/window/Window.h b/src/modules/window/Window.h index cc4d2a34b..c3ed8ca3b 100644 --- a/src/modules/window/Window.h +++ b/src/modules/window/Window.h @@ -24,6 +24,7 @@ // LOVE #include "common/Module.h" #include "common/StringMap.h" +#include "common/math.h" #include "image/ImageData.h" // C++ @@ -151,6 +152,8 @@ public: virtual void setPosition(int x, int y, int displayindex) = 0; virtual void getPosition(int &x, int &y, int &displayindex) = 0; + virtual Rect getSafeArea() const = 0; + virtual bool isOpen() const = 0; virtual void setWindowTitle(const std::string &title) = 0; diff --git a/src/modules/window/sdl/Window.cpp b/src/modules/window/sdl/Window.cpp index d6b06b465..be4f21d06 100644 --- a/src/modules/window/sdl/Window.cpp +++ b/src/modules/window/sdl/Window.cpp @@ -27,6 +27,10 @@ #include "common/android.h" #endif +#ifdef LOVE_IOS +#include "common/ios.h" +#endif + // C++ #include #include @@ -839,6 +843,16 @@ void Window::getPosition(int &x, int &y, int &displayindex) } } +Rect Window::getSafeArea() const +{ +#ifdef LOVE_IOS + if (window != nullptr) + return love::ios::getSafeArea(window); +#endif + + return {0, 0, getWidth(), getHeight()}; +} + bool Window::isOpen() const { return open; diff --git a/src/modules/window/sdl/Window.h b/src/modules/window/sdl/Window.h index 83483c057..ebdfd496d 100644 --- a/src/modules/window/sdl/Window.h +++ b/src/modules/window/sdl/Window.h @@ -66,6 +66,8 @@ public: void setPosition(int x, int y, int displayindex) override; void getPosition(int &x, int &y, int &displayindex) override; + Rect getSafeArea() const override; + bool isOpen() const override; void setWindowTitle(const std::string &title) override; diff --git a/src/modules/window/wrap_Window.cpp b/src/modules/window/wrap_Window.cpp index f188066b0..8c67359af 100644 --- a/src/modules/window/wrap_Window.cpp +++ b/src/modules/window/wrap_Window.cpp @@ -365,6 +365,16 @@ int w_getPosition(lua_State *L) return 3; } +int w_getSafeArea(lua_State *L) +{ + Rect area = instance()->getSafeArea(); + lua_pushnumber(L, area.x); + lua_pushnumber(L, area.y); + lua_pushnumber(L, area.w); + lua_pushnumber(L, area.h); + return 4; +} + int w_setIcon(lua_State *L) { image::ImageData *i = luax_checktype(L, 1); @@ -607,6 +617,7 @@ static const luaL_Reg functions[] = { "getDesktopDimensions", w_getDesktopDimensions }, { "setPosition", w_setPosition }, { "getPosition", w_getPosition }, + { "getSafeArea", w_getSafeArea }, { "setIcon", w_setIcon }, { "getIcon", w_getIcon }, { "setVSync", w_setVSync },