From a5134cdf3fb96629b60f3fa6dc9f05db42ef1740 Mon Sep 17 00:00:00 2001 From: DominusExult Date: Fri, 13 Feb 2026 16:09:22 +0100 Subject: [PATCH 1/3] Adding SDL_HINT_IME_PAN_PADDING "SDL_IME_PAN_PADDING". Controls the padding between TextInputArea and IME and defaults to 0. --- .../main/java/org/libsdl/app/SDLActivity.java | 19 +++++++++++++++---- include/SDL3/SDL_hints.h | 17 +++++++++++++++++ src/video/uikit/SDL_uikitviewcontroller.m | 10 +++++++++- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java index a8ae227b84..d72ac52f24 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java @@ -1388,10 +1388,20 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh * the bottom edge of the input region and the top edge of an input * method (soft keyboard) */ - static final int HEIGHT_PADDING = 15; + static int getPanPadding() { + try { + String hint = nativeGetHint("SDL_IME_PAN_PADDING"); + if (hint != null) { + return Integer.parseInt(hint); + } + } catch (NumberFormatException ignored) { + } + return 0; + } public int input_type; public int x, y, w, h; + private final int panPadding; public ShowTextInputTask(int input_type, int x, int y, int w, int h) { this.input_type = input_type; @@ -1399,19 +1409,20 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh this.y = y; this.w = w; this.h = h; + this.panPadding = getPanPadding(); /* Minimum size of 1 pixel, so it takes focus. */ if (this.w <= 0) { this.w = 1; } - if (this.h + HEIGHT_PADDING <= 0) { - this.h = 1 - HEIGHT_PADDING; + if (this.h + panPadding <= 0) { + this.h = 1 - panPadding; } } @Override public void run() { - RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(w, h + HEIGHT_PADDING); + RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(w, h + panPadding); params.leftMargin = x; params.topMargin = y; diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index 992243853f..158ea3185b 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -1219,6 +1219,23 @@ extern "C" { */ #define SDL_HINT_IME_IMPLEMENTED_UI "SDL_IME_IMPLEMENTED_UI" +/** + * A variable controlling the padding in pixels added above the on-screen + * keyboard to keep the text input area visible. + * + * This padding is used on platforms with on-screen keyboards (iOS, Android) + * to ensure there is extra breathing room between the text input area and + * the top of the keyboard when panning the view. + * + * The variable can be set to a number representing the padding in pixels. + * The default value is "0". + * + * This hint can be set anytime. + * + * \since This hint is available since SDL 3.6.0. + */ +#define SDL_HINT_IME_PAN_PADDING "SDL_IME_PAN_PADDING" + /** * A variable controlling whether the home indicator bar on iPhone X and later * should be hidden. diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m index ffb822d919..5e272a27fa 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.m +++ b/src/video/uikit/SDL_uikitviewcontroller.m @@ -642,7 +642,15 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char #endif if (self.keyboardHeight && self.textInputRect.h) { - int rectbottom = (int)(self.textInputRect.y + self.textInputRect.h); + /* Get the pan padding from the hint (in pixels). The text input rect + * and view bounds are in UIKit points, so divide by the scale factor + * to keep the visual gap consistent across platforms. + * The iOS IME seems to apply a 15 pixel padding, so to keep it consistent + * with Android we subtract 15 pixels here. */ + const char *hint = SDL_GetHint(SDL_HINT_IME_PAN_PADDING); + int panPadding = (hint && *hint) ? SDL_atoi(hint) : 0; + int padding = (int)((panPadding - 15) / self.view.contentScaleFactor); + int rectbottom = (int)(self.textInputRect.y + self.textInputRect.h + padding); int keybottom = (int)(self.view.bounds.size.height - self.keyboardHeight); if (keybottom < rectbottom) { offset.y = keybottom - rectbottom; From d6ddc84e562088a63f6f7cca4c8c70b1319ceba4 Mon Sep 17 00:00:00 2001 From: DominusExult Date: Fri, 13 Feb 2026 18:01:49 +0100 Subject: [PATCH 2/3] The default value of SDL_HINT_IME_PAN_PADDING is 15 to keep consistent with previous look. Also seems that I was mistaken about the padding automatically applied by iOS. --- .../app/src/main/java/org/libsdl/app/SDLActivity.java | 2 +- include/SDL3/SDL_hints.h | 2 +- src/video/uikit/SDL_uikitviewcontroller.m | 8 +++----- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java index d72ac52f24..7e5efbe650 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java @@ -1396,7 +1396,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh } } catch (NumberFormatException ignored) { } - return 0; + return 15; } public int input_type; diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index 158ea3185b..39c63721fa 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -1228,7 +1228,7 @@ extern "C" { * the top of the keyboard when panning the view. * * The variable can be set to a number representing the padding in pixels. - * The default value is "0". + * The default value is "15". * * This hint can be set anytime. * diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m index 5e272a27fa..d20b783493 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.m +++ b/src/video/uikit/SDL_uikitviewcontroller.m @@ -644,12 +644,10 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char if (self.keyboardHeight && self.textInputRect.h) { /* Get the pan padding from the hint (in pixels). The text input rect * and view bounds are in UIKit points, so divide by the scale factor - * to keep the visual gap consistent across platforms. - * The iOS IME seems to apply a 15 pixel padding, so to keep it consistent - * with Android we subtract 15 pixels here. */ + * to keep the visual gap consistent across platforms.*/ const char *hint = SDL_GetHint(SDL_HINT_IME_PAN_PADDING); - int panPadding = (hint && *hint) ? SDL_atoi(hint) : 0; - int padding = (int)((panPadding - 15) / self.view.contentScaleFactor); + int panPadding = (hint && *hint) ? SDL_atoi(hint) : 15; + int padding = (int)(panPadding / self.view.contentScaleFactor); int rectbottom = (int)(self.textInputRect.y + self.textInputRect.h + padding); int keybottom = (int)(self.view.bounds.size.height - self.keyboardHeight); if (keybottom < rectbottom) { From ac90fa0879274379637fb680937f2c2baf408423 Mon Sep 17 00:00:00 2001 From: DominusExult Date: Sat, 14 Feb 2026 14:03:35 +0100 Subject: [PATCH 3/3] The padding is in windows coordinates not pixels, so you need to convert for Android. Default is now 10 window coordinates (slightly more than 15 pixels). --- .../app/src/main/java/org/libsdl/app/SDLActivity.java | 8 ++++++-- include/SDL3/SDL_hints.h | 6 ++++-- src/video/uikit/SDL_uikitviewcontroller.m | 7 ++----- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java index 7e5efbe650..e3dc219d4e 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java @@ -1389,14 +1389,18 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh * method (soft keyboard) */ static int getPanPadding() { + /* The hint is in window coordinates. Convert to pixels by + * multiplying by density. */ + int defaultPadding = 10; try { String hint = nativeGetHint("SDL_IME_PAN_PADDING"); if (hint != null) { - return Integer.parseInt(hint); + defaultPadding = Integer.parseInt(hint); } } catch (NumberFormatException ignored) { } - return 15; + float density = getContext().getResources().getDisplayMetrics().density; + return (int)(defaultPadding * density); } public int input_type; diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index 39c63721fa..bd8fd6fa4e 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -1227,8 +1227,10 @@ extern "C" { * to ensure there is extra breathing room between the text input area and * the top of the keyboard when panning the view. * - * The variable can be set to a number representing the padding in pixels. - * The default value is "15". + * The variable can be set to a number representing the padding in window + * coordinates. + * + * The default value is "10". * * This hint can be set anytime. * diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m index d20b783493..c7beeb8895 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.m +++ b/src/video/uikit/SDL_uikitviewcontroller.m @@ -642,12 +642,9 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char #endif if (self.keyboardHeight && self.textInputRect.h) { - /* Get the pan padding from the hint (in pixels). The text input rect - * and view bounds are in UIKit points, so divide by the scale factor - * to keep the visual gap consistent across platforms.*/ + /// Get the pan padding from the hint (in window coordinates). const char *hint = SDL_GetHint(SDL_HINT_IME_PAN_PADDING); - int panPadding = (hint && *hint) ? SDL_atoi(hint) : 15; - int padding = (int)(panPadding / self.view.contentScaleFactor); + int padding = (hint && *hint) ? SDL_atoi(hint) : 10; int rectbottom = (int)(self.textInputRect.y + self.textInputRect.h + padding); int keybottom = (int)(self.view.bounds.size.height - self.keyboardHeight); if (keybottom < rectbottom) {