Add love.window.getSafeArea (resolves issue #1437). Returns a rectangle (x, y, w, h) inside the window which is known to be unobstructed by a system title bar, the iPhone X notch, etc. Useful for making sure UI elements can be seen by the user.

Currently it only has a proper implementation on iOS and will return the window's full size otherwise.
This commit is contained in:
Alex Szpakowski
2018-12-26 00:34:14 -04:00
parent 1c853cbcc3
commit d41aca836e
6 changed files with 81 additions and 3 deletions
+10
View File
@@ -25,8 +25,12 @@
#ifdef LOVE_IOS
#include "common/math.h"
#include <string>
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
+41 -3
View File
@@ -31,6 +31,8 @@
#include <vector>
#include <SDL_events.h>
#include <SDL_video.h>
#include <SDL_syswm.h>
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
+3
View File
@@ -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;
+14
View File
@@ -27,6 +27,10 @@
#include "common/android.h"
#endif
#ifdef LOVE_IOS
#include "common/ios.h"
#endif
// C++
#include <iostream>
#include <vector>
@@ -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;
+2
View File
@@ -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;
+11
View File
@@ -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<image::ImageData>(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 },