Commit 85c34e9a39c6351301c6ec7dde6d0319a25feaba

Sam Lantinga 2018-02-01T15:21:01

Added SDL_HINT_IOS_HIDE_HOME_INDICATOR to determine how the home indicator on the iPhone X is handled. This variable can be set to the following values: "0" - The indicator bar is not hidden (default for windowed applications) "1" - The indicator bar is hidden and is shown when the screen is touched (useful for movie playback applications) "2" - The indicator bar is dim and the first swipe makes it visible and the second swipe performs the "home" action (default for fullscreen applications)

diff --git a/include/SDL_hints.h b/include/SDL_hints.h
index e9a0e7c..8c0d722 100644
--- a/include/SDL_hints.h
+++ b/include/SDL_hints.h
@@ -366,6 +366,17 @@ extern "C" {
 #define SDL_HINT_APPLE_TV_REMOTE_SWIPES_AS_ARROW_KEYS "SDL_APPLE_TV_REMOTE_SWIPES_AS_ARROW_KEYS"
 
 /**
+ * \brief  A variable controlling whether the home indicator bar on iPhone X
+ *         should be hidden.
+ *
+ *  This variable can be set to the following values:
+ *    "0"       - The indicator bar is not hidden (default for windowed applications)
+ *    "1"       - The indicator bar is hidden and is shown when the screen is touched (useful for movie playback applications)
+ *    "2"       - The indicator bar is dim and the first swipe makes it visible and the second swipe performs the "home" action (default for fullscreen applications)
+ */
+#define SDL_HINT_IOS_HIDE_HOME_INDICATOR "SDL_IOS_HIDE_HOME_INDICATOR"
+
+/**
  *  \brief  A variable controlling whether the Android / iOS built-in
  *  accelerometer should be listed as a joystick device, rather than listing
  *  actual joysticks only.
@@ -775,7 +786,7 @@ extern "C" {
  *   "0"       - SDL will generate a window-close event when it sees Alt+F4.
  *   "1"       - SDL will only do normal key handling for Alt+F4.
  */
-#define SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4	"SDL_WINDOWS_NO_CLOSE_ON_ALT_F4"
+#define SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4 "SDL_WINDOWS_NO_CLOSE_ON_ALT_F4"
 
 /**
  *  \brief Prevent SDL from using version 4 of the bitmap header when saving BMPs.
diff --git a/src/video/uikit/SDL_uikitmessagebox.m b/src/video/uikit/SDL_uikitmessagebox.m
index d97ff25..7950c8e 100644
--- a/src/video/uikit/SDL_uikitmessagebox.m
+++ b/src/video/uikit/SDL_uikitmessagebox.m
@@ -109,6 +109,18 @@ UIKit_ShowMessageBoxAlertController(const SDL_MessageBoxData *messageboxdata, in
         alertwindow.hidden = YES;
     }
 
+    /* Force the main SDL window to re-evaluate home indicator state */
+    SDL_Window *focus = SDL_GetFocusWindow();
+    if (focus) {
+        SDL_WindowData *data = (__bridge SDL_WindowData *) focus->driverdata;
+        if (data != nil) {
+            if (@available(iOS 11.0, *)) {
+                [data.viewcontroller performSelectorOnMainThread:@selector(setNeedsUpdateOfHomeIndicatorAutoHidden) withObject:nil waitUntilDone:NO];
+                [data.viewcontroller performSelectorOnMainThread:@selector(setNeedsUpdateOfScreenEdgesDeferringSystemGestures) withObject:nil waitUntilDone:NO];
+            }
+        }
+    }
+
     *buttonid = messageboxdata->buttons[clickedindex].buttonid;
     return YES;
 #else
diff --git a/src/video/uikit/SDL_uikitviewcontroller.h b/src/video/uikit/SDL_uikitviewcontroller.h
index 47b1740..fffb142 100644
--- a/src/video/uikit/SDL_uikitviewcontroller.h
+++ b/src/video/uikit/SDL_uikitviewcontroller.h
@@ -58,6 +58,10 @@
 #if !TARGET_OS_TV
 - (NSUInteger)supportedInterfaceOrientations;
 - (BOOL)prefersStatusBarHidden;
+- (BOOL)prefersHomeIndicatorAutoHidden;
+- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures;
+
+@property (nonatomic, assign) int homeIndicatorHidden;
 #endif
 
 #if SDL_IPHONE_KEYBOARD
diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m
index eb8130d..9ee70e8 100644
--- a/src/video/uikit/SDL_uikitviewcontroller.m
+++ b/src/video/uikit/SDL_uikitviewcontroller.m
@@ -50,6 +50,21 @@ SDL_AppleTVControllerUIHintChanged(void *userdata, const char *name, const char 
 }
 #endif
 
+#if !TARGET_OS_TV
+static void SDLCALL
+SDL_HideHomeIndicatorHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
+{
+    @autoreleasepool {
+        SDL_uikitviewcontroller *viewcontroller = (__bridge SDL_uikitviewcontroller *) userdata;
+        viewcontroller.homeIndicatorHidden = (hint && *hint) ? SDL_atoi(hint) : -1;
+        if (@available(iOS 11.0, *)) {
+            [viewcontroller setNeedsUpdateOfHomeIndicatorAutoHidden];
+            [viewcontroller setNeedsUpdateOfScreenEdgesDeferringSystemGestures];
+        }
+    }
+}
+#endif
+
 @implementation SDL_uikitviewcontroller {
     CADisplayLink *displayLink;
     int animationInterval;
@@ -79,7 +94,13 @@ SDL_AppleTVControllerUIHintChanged(void *userdata, const char *name, const char 
                             SDL_AppleTVControllerUIHintChanged,
                             (__bridge void *) self);
 #endif
+
+#if !TARGET_OS_TV
+        SDL_AddHintCallback(SDL_HINT_IOS_HIDE_HOME_INDICATOR,
+                            SDL_HideHomeIndicatorHintChanged,
+                            (__bridge void *) self);
     }
+#endif
     return self;
 }
 
@@ -94,6 +115,12 @@ SDL_AppleTVControllerUIHintChanged(void *userdata, const char *name, const char 
                         SDL_AppleTVControllerUIHintChanged,
                         (__bridge void *) self);
 #endif
+
+#if !TARGET_OS_TV
+    SDL_DelHintCallback(SDL_HINT_IOS_HIDE_HOME_INDICATOR,
+                        SDL_HideHomeIndicatorHintChanged,
+                        (__bridge void *) self);
+#endif
 }
 
 - (void)setAnimationCallback:(int)interval
@@ -179,7 +206,35 @@ SDL_AppleTVControllerUIHintChanged(void *userdata, const char *name, const char 
 
 - (BOOL)prefersStatusBarHidden
 {
-    return (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) != 0;
+    BOOL hidden = (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) != 0;
+    return hidden;
+}
+
+- (BOOL)prefersHomeIndicatorAutoHidden
+{
+    BOOL hidden = NO;
+    if (self.homeIndicatorHidden == 1) {
+        hidden = YES;
+    }
+    return hidden;
+}
+
+- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures
+{
+    if (self.homeIndicatorHidden >= 0) {
+        if (self.homeIndicatorHidden == 2) {
+            return UIRectEdgeAll;
+        } else {
+            return UIRectEdgeNone;
+        }
+    }
+
+    /* By default, fullscreen and borderless windows get all screen gestures */
+    if ((window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) != 0) {
+        return UIRectEdgeAll;
+    } else {
+        return UIRectEdgeNone;
+    }
 }
 #endif