mirror of https://github.com/libsdl-org/SDL
Added SDL_GetWindowSafeArea()
Fixes https://github.com/libsdl-org/SDL/issues/3243
This commit is contained in:
parent
1c4cc2b024
commit
457ca3995c
|
@ -918,6 +918,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
|||
window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
SDLActivity.mFullscreenModeActive = false;
|
||||
}
|
||||
window.getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "error handling message, getContext() returned no Activity");
|
||||
|
@ -1057,6 +1058,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
|||
public static native void nativeSetenv(String name, String value);
|
||||
public static native void nativeSetNaturalOrientation(int orientation);
|
||||
public static native void onNativeRotationChanged(int rotation);
|
||||
public static native void onNativeInsetsChanged(int left, int right, int top, int bottom);
|
||||
public static native void nativeAddTouch(int touchId, String name);
|
||||
public static native void nativePermissionResult(int requestCode, boolean result);
|
||||
public static native void onNativeLocaleChanged();
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.libsdl.app;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.graphics.Insets;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
|
@ -18,6 +19,7 @@ import android.view.Surface;
|
|||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.View;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.WindowManager;
|
||||
|
||||
|
||||
|
@ -28,7 +30,7 @@ import android.view.WindowManager;
|
|||
Because of this, that's where we set up the SDL thread
|
||||
*/
|
||||
public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
||||
View.OnKeyListener, View.OnTouchListener, SensorEventListener {
|
||||
View.OnApplyWindowInsetsListener, View.OnKeyListener, View.OnTouchListener, SensorEventListener {
|
||||
|
||||
// Sensors
|
||||
protected SensorManager mSensorManager;
|
||||
|
@ -48,6 +50,7 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
|||
setFocusable(true);
|
||||
setFocusableInTouchMode(true);
|
||||
requestFocus();
|
||||
setOnApplyWindowInsetsListener(this);
|
||||
setOnKeyListener(this);
|
||||
setOnTouchListener(this);
|
||||
|
||||
|
@ -71,6 +74,7 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
|||
setFocusable(true);
|
||||
setFocusableInTouchMode(true);
|
||||
requestFocus();
|
||||
setOnApplyWindowInsetsListener(this);
|
||||
setOnKeyListener(this);
|
||||
setOnTouchListener(this);
|
||||
enableSensor(Sensor.TYPE_ACCELEROMETER, true);
|
||||
|
@ -187,6 +191,24 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
|||
SDLActivity.handleNativeState();
|
||||
}
|
||||
|
||||
// Window inset
|
||||
@Override
|
||||
public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
|
||||
Insets combined = insets.getInsets(WindowInsets.Type.statusBars() |
|
||||
WindowInsets.Type.navigationBars() |
|
||||
WindowInsets.Type.captionBar() |
|
||||
WindowInsets.Type.systemGestures() |
|
||||
WindowInsets.Type.mandatorySystemGestures() |
|
||||
WindowInsets.Type.tappableElement() |
|
||||
WindowInsets.Type.displayCutout() |
|
||||
WindowInsets.Type.systemOverlays());
|
||||
|
||||
SDLActivity.onNativeInsetsChanged(combined.left, combined.right, combined.top, combined.bottom);
|
||||
|
||||
// Pass these to any child views in case they need them
|
||||
return insets;
|
||||
}
|
||||
|
||||
// Key events
|
||||
@Override
|
||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
||||
|
|
|
@ -142,6 +142,7 @@ typedef enum SDL_EventType
|
|||
SDL_EVENT_WINDOW_ICCPROF_CHANGED, /**< The ICC profile of the window's display has changed */
|
||||
SDL_EVENT_WINDOW_DISPLAY_CHANGED, /**< Window has been moved to display data1 */
|
||||
SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED, /**< Window display scale has been changed */
|
||||
SDL_EVENT_WINDOW_SAFE_AREA_CHANGED, /**< The window safe area has been changed */
|
||||
SDL_EVENT_WINDOW_OCCLUDED, /**< The window has been occluded */
|
||||
SDL_EVENT_WINDOW_ENTER_FULLSCREEN, /**< The window has entered fullscreen mode */
|
||||
SDL_EVENT_WINDOW_LEAVE_FULLSCREEN, /**< The window has left fullscreen mode */
|
||||
|
|
|
@ -1480,6 +1480,20 @@ extern SDL_DECLSPEC int SDLCALL SDL_SetWindowSize(SDL_Window *window, int w, int
|
|||
*/
|
||||
extern SDL_DECLSPEC int SDLCALL SDL_GetWindowSize(SDL_Window *window, int *w, int *h);
|
||||
|
||||
/**
|
||||
* Get the safe area for this window.
|
||||
*
|
||||
* Some devices have portions of the screen which are partially obscured or not interactive, possibly due to on-screen controls, curved edges, camera notches, TV overscan, etc. This function provides the area of the window which is safe to have interactible content. You should continue rendering into the rest of the window, but it should not contain visually important or interactible content.
|
||||
*
|
||||
* \param window the window to query.
|
||||
* \param rect a pointer filled in with the client area that is safe for interactive content.
|
||||
* \returns 0 on success or a negative error code on failure; call
|
||||
* SDL_GetError() for more information.
|
||||
*
|
||||
* \since This function is available since SDL 3.0.0.
|
||||
*/
|
||||
extern SDL_DECLSPEC int SDLCALL SDL_GetWindowSafeArea(SDL_Window *window, SDL_Rect *rect);
|
||||
|
||||
/**
|
||||
* Request that the aspect ratio of a window's client area be set.
|
||||
*
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -484,6 +484,7 @@ SDL3_0.0.0 {
|
|||
SDL_GetWindowPixelFormat;
|
||||
SDL_GetWindowPosition;
|
||||
SDL_GetWindowProperties;
|
||||
SDL_GetWindowSafeArea;
|
||||
SDL_GetWindowSize;
|
||||
SDL_GetWindowSizeInPixels;
|
||||
SDL_GetWindowSurface;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,4 +43,6 @@
|
|||
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
|
||||
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
|
||||
|
||||
- (void)safeAreaInsetsDidChange;
|
||||
|
||||
@end
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue