Added SDL_GetWindowSafeArea()

Fixes https://github.com/libsdl-org/SDL/issues/3243
This commit is contained in:
Sam Lantinga
2024-07-22 18:59:53 -07:00
parent 1c4cc2b024
commit 457ca3995c
16 changed files with 147 additions and 1 deletions

View File

@@ -163,6 +163,10 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeRotationChanged)(
JNIEnv *env, jclass cls,
jint rotation);
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeInsetsChanged)(
JNIEnv *env, jclass cls,
jint left, jint right, jint top, jint bottom);
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeAddTouch)(
JNIEnv *env, jclass cls,
jint touchId, jstring name);
@@ -212,6 +216,7 @@ static JNINativeMethod SDLActivity_tab[] = {
{ "nativeSetenv", "(Ljava/lang/String;Ljava/lang/String;)V", SDL_JAVA_INTERFACE(nativeSetenv) },
{ "nativeSetNaturalOrientation", "(I)V", SDL_JAVA_INTERFACE(nativeSetNaturalOrientation) },
{ "onNativeRotationChanged", "(I)V", SDL_JAVA_INTERFACE(onNativeRotationChanged) },
{ "onNativeInsetsChanged", "(IIII)V", SDL_JAVA_INTERFACE(onNativeInsetsChanged) },
{ "nativeAddTouch", "(ILjava/lang/String;)V", SDL_JAVA_INTERFACE(nativeAddTouch) },
{ "nativePermissionResult", "(IZ)V", SDL_JAVA_INTERFACE(nativePermissionResult) },
{ "nativeAllowRecreateActivity", "()Z", SDL_JAVA_INTERFACE(nativeAllowRecreateActivity) },
@@ -997,6 +1002,19 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeRotationChanged)(
SDL_UnlockMutex(Android_ActivityMutex);
}
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeInsetsChanged)(
JNIEnv *env, jclass jcls,
jint left, jint right, jint top, jint bottom)
{
SDL_LockMutex(Android_ActivityMutex);
if (Android_Window) {
SDL_SetWindowSafeAreaInsets(Android_Window, left, right, top, bottom);
}
SDL_UnlockMutex(Android_ActivityMutex);
}
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeAddTouch)(
JNIEnv *env, jclass cls,
jint touchId, jstring name)

View File

@@ -484,6 +484,7 @@ SDL3_0.0.0 {
SDL_GetWindowPixelFormat;
SDL_GetWindowPosition;
SDL_GetWindowProperties;
SDL_GetWindowSafeArea;
SDL_GetWindowSize;
SDL_GetWindowSizeInPixels;
SDL_GetWindowSurface;

View File

@@ -509,6 +509,7 @@
#define SDL_GetWindowPixelFormat SDL_GetWindowPixelFormat_REAL
#define SDL_GetWindowPosition SDL_GetWindowPosition_REAL
#define SDL_GetWindowProperties SDL_GetWindowProperties_REAL
#define SDL_GetWindowSafeArea SDL_GetWindowSafeArea_REAL
#define SDL_GetWindowSize SDL_GetWindowSize_REAL
#define SDL_GetWindowSizeInPixels SDL_GetWindowSizeInPixels_REAL
#define SDL_GetWindowSurface SDL_GetWindowSurface_REAL

View File

@@ -529,6 +529,7 @@ SDL_DYNAPI_PROC(float,SDL_GetWindowPixelDensity,(SDL_Window *a),(a),return)
SDL_DYNAPI_PROC(SDL_PixelFormat,SDL_GetWindowPixelFormat,(SDL_Window *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_GetWindowPosition,(SDL_Window *a, int *b, int *c),(a,b,c),return)
SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetWindowProperties,(SDL_Window *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_GetWindowSafeArea,(SDL_Window *a, SDL_Rect *b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_GetWindowSize,(SDL_Window *a, int *b, int *c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_GetWindowSizeInPixels,(SDL_Window *a, int *b, int *c),(a,b,c),return)
SDL_DYNAPI_PROC(SDL_Surface*,SDL_GetWindowSurface,(SDL_Window *a),(a),return)

View File

@@ -497,6 +497,7 @@ static void SDL_LogEvent(const SDL_Event *event)
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MOVED);
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_RESIZED);
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED);
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_SAFE_AREA_CHANGED);
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MINIMIZED);
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MAXIMIZED);
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_RESTORED);

View File

@@ -193,6 +193,7 @@ int SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent,
if (windowevent == SDL_EVENT_WINDOW_MOVED ||
windowevent == SDL_EVENT_WINDOW_RESIZED ||
windowevent == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED ||
windowevent == SDL_EVENT_WINDOW_SAFE_AREA_CHANGED ||
windowevent == SDL_EVENT_WINDOW_EXPOSED ||
windowevent == SDL_EVENT_WINDOW_OCCLUDED) {
SDL_FilterEvents(RemoveSupercededWindowEvents, &event);

View File

@@ -1614,6 +1614,14 @@ static void SDLTest_PrintEvent(const SDL_Event *event)
SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " changed pixel size to %" SDL_PRIs32 "x%" SDL_PRIs32,
event->window.windowID, event->window.data1, event->window.data2);
break;
case SDL_EVENT_WINDOW_SAFE_AREA_CHANGED: {
SDL_Rect rect;
SDL_GetWindowSafeArea(SDL_GetWindowFromID(event->window.windowID), &rect);
SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " changed safe area to: %d,%d %dx%d\n",
event->window.windowID, rect.x, rect.y, rect.w, rect.h);
break;
}
case SDL_EVENT_WINDOW_MINIMIZED:
SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " minimized", event->window.windowID);
break;

View File

@@ -100,6 +100,12 @@ struct SDL_Window
SDL_bool is_destroying;
SDL_bool is_dropping; /* drag/drop in progress, expecting SDL_SendDropComplete(). */
int safe_inset_left;
int safe_inset_right;
int safe_inset_top;
int safe_inset_bottom;
SDL_Rect safe_rect;
SDL_bool text_input_active;
SDL_Rect text_input_rect;
int text_input_cursor;
@@ -526,6 +532,7 @@ extern SDL_DisplayData *SDL_GetDisplayDriverData(SDL_DisplayID display);
extern SDL_DisplayData *SDL_GetDisplayDriverDataForWindow(SDL_Window *window);
extern int SDL_GetMessageBoxCount(void);
extern void SDL_SetWindowHDRProperties(SDL_Window *window, const SDL_HDROutputProperties *HDR, SDL_bool send_event);
extern void SDL_SetWindowSafeAreaInsets(SDL_Window *window, int left, int right, int top, int bottom);
extern void SDL_GL_DeduceMaxSupportedESProfile(int *major, int *minor);

View File

@@ -165,6 +165,7 @@ extern SDL_bool Cocoa_SetWindowFullscreenSpace(SDL_Window *window, SDL_bool stat
static void SDL_CheckWindowDisplayChanged(SDL_Window *window);
static void SDL_CheckWindowDisplayScaleChanged(SDL_Window *window);
static void SDL_CheckWindowSafeAreaChanged(SDL_Window *window);
/* Convenience functions for reading driver flags */
static SDL_bool SDL_ModeSwitchingEmulated(SDL_VideoDevice *_this)
@@ -3789,6 +3790,7 @@ void SDL_OnWindowResized(SDL_Window *window)
{
SDL_CheckWindowDisplayChanged(window);
SDL_CheckWindowPixelSizeChanged(window);
SDL_CheckWindowSafeAreaChanged(window);
if ((window->flags & SDL_WINDOW_TRANSPARENT) && _this->UpdateWindowShape) {
SDL_Surface *surface = (SDL_Surface *)SDL_GetPointerProperty(window->props, SDL_PROP_WINDOW_SHAPE_POINTER, NULL);
@@ -3813,6 +3815,43 @@ void SDL_OnWindowPixelSizeChanged(SDL_Window *window)
window->surface_valid = SDL_FALSE;
}
static void SDL_CheckWindowSafeAreaChanged(SDL_Window *window)
{
SDL_Rect rect;
rect.x = window->safe_inset_left;
rect.y = window->safe_inset_top;
rect.w = window->w - (window->safe_inset_right + window->safe_inset_left);
rect.h = window->h - (window->safe_inset_top + window->safe_inset_bottom);
if (SDL_memcmp(&rect, &window->safe_rect, sizeof(rect)) != 0) {
SDL_copyp(&window->safe_rect, &rect);
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_SAFE_AREA_CHANGED, 0, 0);
}
}
void SDL_SetWindowSafeAreaInsets(SDL_Window *window, int left, int right, int top, int bottom)
{
window->safe_inset_left = left;
window->safe_inset_right = right;
window->safe_inset_top = top;
window->safe_inset_bottom = bottom;
SDL_CheckWindowSafeAreaChanged(window);
}
int SDL_GetWindowSafeArea(SDL_Window *window, SDL_Rect *rect)
{
if (rect) {
SDL_zerop(rect);
}
CHECK_WINDOW_MAGIC(window, -1);
if (rect) {
SDL_copyp(rect, &window->safe_rect);
}
return 0;
}
void SDL_OnWindowMinimized(SDL_Window *window)
{
if (window->flags & SDL_WINDOW_FULLSCREEN) {

View File

@@ -2785,6 +2785,22 @@ int Cocoa_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_Vi
[data.listener resumeVisibleObservation];
}
// Update the safe area insets
// The view never seems to reflect the safe area, so we'll use the screen instead
if (@available(macOS 12.0, *)) {
if (fullscreen) {
NSScreen *screen = [nswindow screen];
SDL_SetWindowSafeAreaInsets(data.window,
(int)SDL_ceilf(screen.safeAreaInsets.left),
(int)SDL_ceilf(screen.safeAreaInsets.right),
(int)SDL_ceilf(screen.safeAreaInsets.top),
(int)SDL_ceilf(screen.safeAreaInsets.bottom));
} else {
SDL_SetWindowSafeAreaInsets(data.window, 0, 0, 0, 0);
}
}
ScheduleContextUpdates(data);
}

View File

@@ -43,4 +43,6 @@
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)safeAreaInsetsDidChange;
@end

View File

@@ -368,6 +368,18 @@ extern int SDL_AppleTVRemoteOpenedAsJoystick;
}
}
- (void)safeAreaInsetsDidChange
{
// Update the safe area insets
if (@available(iOS 11.0, tvOS 11.0, *)) {
SDL_SetWindowSafeAreaInsets(sdlwindow,
(int)SDL_ceilf(self.safeAreaInsets.left),
(int)SDL_ceilf(self.safeAreaInsets.right),
(int)SDL_ceilf(self.safeAreaInsets.top),
(int)SDL_ceilf(self.safeAreaInsets.bottom));
}
}
#if defined(SDL_PLATFORM_TVOS) || defined(__IPHONE_9_1)
- (SDL_Scancode)scancodeFromPress:(UIPress *)press
{