diff --git a/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java b/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java index 12992b5eaf..f71fbacbf2 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java +++ b/android/KMAPro/kMAPro/src/main/java/com/keyman/android/SystemKeyboard.java @@ -246,21 +246,17 @@ public class SystemKeyboard extends InputMethodService implements OnKeyboardEven inputViewHeight = inputView.getHeight(); } - int navigationHeight = KMManager.getNavigationBarHeight(this); int bannerHeight = KMManager.getBannerHeight(this); int kbHeight = KMManager.getKeyboardHeight(this); - outInsets.contentTopInsets = inputViewHeight - bannerHeight - kbHeight; - - // TODO - design better way to toggle this adjustment - SharedPreferences prefs = this.getSharedPreferences(PreferencesManager.kma_prefs_name, Context.MODE_PRIVATE); - boolean showOSK = prefs.getBoolean(KeymanSettingsActivity.oskWithPhysicalKeyboardKey, false); - if (showOSK) { - outInsets.contentTopInsets -= navigationHeight; - } + int bottomInset = KMManager.getBottomInset(); + outInsets.contentTopInsets = inputViewHeight - bannerHeight - kbHeight - bottomInset; outInsets.visibleTopInsets = outInsets.contentTopInsets; outInsets.touchableInsets = InputMethodService.Insets.TOUCHABLE_INSETS_REGION; outInsets.touchableRegion.set(0, outInsets.contentTopInsets, size.x, size.y); + + //Log.d(TAG, String.format("inputView: %d, , bannerHeight: %d, kbHeight: %d, navigationHeight: %d", + // inputViewHeight, bannerHeight, kbHeight, navigationHeight)); } @Override diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/BaseActivity.java b/android/KMEA/app/src/main/java/com/keyman/engine/BaseActivity.java index c7ecd5bdb9..f239ad366b 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/BaseActivity.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/BaseActivity.java @@ -101,7 +101,7 @@ public class BaseActivity extends AppCompatActivity { insets.bottom); KMManager.applyInsetsToKeyboard( - KMManager.KeyboardType.KEYBOARD_TYPE_INAPP, insets.left, insets.right, insets.bottom); + insets.left, insets.right, insets.bottom); return windowInsets; }); } diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java index cea07df5b9..8aa9eb56cf 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMManager.java @@ -54,6 +54,7 @@ import android.widget.RelativeLayout; import androidx.core.content.ContextCompat; import androidx.core.graphics.Insets; +import androidx.core.view.DisplayCutoutCompat; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; @@ -90,6 +91,7 @@ public final class KMManager { private static final String TAG = "KMManager"; private static ResourcesUpdateTool updateTool; + private static int bottomInset; // Keyboard types public enum KeyboardType { @@ -705,10 +707,6 @@ public final class KMManager { public static RelativeLayout.LayoutParams getKeyboardLayoutParams() { int bannerHeight = getBannerHeight(appContext); int kbHeight = getKeyboardHeight(appContext); - int navigationHeight = getNavigationBarHeight(appContext); - int orientation = getOrientation(appContext); - FormFactor formFactor = getFormFactor(); - RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.MATCH_PARENT, bannerHeight + kbHeight); params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE); @@ -717,25 +715,25 @@ public final class KMManager { /** * Applies padding to the keyboard so it's not covered by system insets - * @param {KeyboardType} keyboard * @param left int padding to account for notch/navigation bar on left side of screen * @param right int padding to account for notch/navigation bar on right side of screen * @param bottom int padding to account for navigation bar on bottom of screen */ - public static void applyInsetsToKeyboard(KeyboardType keyboardType, int left, int right, int bottom) { - if (keyboardType == KeyboardType.KEYBOARD_TYPE_INAPP && InAppKeyboard != null) { + public static void applyInsetsToKeyboard(int left, int right, int bottom) { + if (InAppKeyboard != null) { applyInsetsPaddingToKeyboardView(InAppKeyboard, left, right, bottom); } - if (keyboardType == KeyboardType.KEYBOARD_TYPE_SYSTEM && SystemKeyboard != null) { + if (SystemKeyboard != null) { applyInsetsPaddingToKeyboardView(SystemKeyboard, left, right, bottom); } } private static void applyInsetsPaddingToKeyboardView(KMKeyboard keyboard, int left, int right, int bottom) { View parent = (View) keyboard.getParent(); + bottomInset = bottom; - if (keyboard.keyboardType == KeyboardType.KEYBOARD_TYPE_INAPP && parent != null) { + if (parent != null) { // Keep existing top padding, add bottom padding for the inset parent.setPadding( left, @@ -757,6 +755,10 @@ public final class KMManager { } } + public static int getBottomInset() { + return bottomInset; + } + private static void initKeyboard(Context appContext, KeyboardType keyboardType) { KMKeyboard keyboard = null; KMKeyboardWebViewClient webViewClient = null; @@ -891,40 +893,49 @@ public final class KMManager { mainLayout.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)); if (SystemKeyboard == null) { + installSystemKeyboardInsetsListener(mainLayout); return mainLayout; } - if (mainLayout != null) { - // Update insets - ViewCompat.setOnApplyWindowInsetsListener(mainLayout, - (view, windowInsets) -> { - // Allocate insets for system bars and display cutout (notch) - Insets insets = windowInsets.getInsets( - WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout()); - - view.setPadding( - insets.left, - insets.top, - insets.right, - insets.bottom); - - applyInsetsToKeyboard(KeyboardType.KEYBOARD_TYPE_SYSTEM, insets.left, insets.right, insets.bottom); - return windowInsets; - }); - } - RelativeLayout keyboardLayout = new RelativeLayout(appContext); keyboardLayout.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)); ViewGroup parent = (ViewGroup) SystemKeyboard.getParent(); - if (parent != null) + if (parent != null) { parent.removeView(SystemKeyboard); + } keyboardLayout.addView(SystemKeyboard); mainLayout.addView(keyboardLayout); //mainLayout.addView(overlayLayout); + + installSystemKeyboardInsetsListener(mainLayout); return mainLayout; } + private static void installSystemKeyboardInsetsListener(View anchor) { + ViewCompat.setOnApplyWindowInsetsListener(anchor, (v, insets) -> { + // System bars (status bar and navigation bar) + Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); + + // Cutout (camera notch) safe insets + DisplayCutoutCompat cutout = insets.getDisplayCutout(); + int safeLeft = (cutout != null) ? cutout.getSafeInsetLeft() : 0; + int safeRight = (cutout != null) ? cutout.getSafeInsetRight() : 0; + + int leftInset = Math.max(systemBars.left, safeLeft); + int rightInset = Math.max(systemBars.right, safeRight); + + boolean imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime()); + int bottomInset = systemBars.bottom; + + applyInsetsToKeyboard(leftInset, rightInset, bottomInset); + return insets; + }); + + // Trigger an initial pass + ViewCompat.requestApplyInsets(anchor); + } + public static void onStartInput(EditorInfo attribute, boolean restarting) { if (!restarting && SystemKeyboard != null) { String packageName = attribute.packageName; @@ -2493,6 +2504,15 @@ public final class KMManager { KeyboardHeight_Context_Landscape_Default = (int) newResources.getDimension(R.dimen.keyboard_height); } + public static int getStatusBarHeight(Context context) { + int statusBarHeight = 0; + int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (resourceId > 0) { + statusBarHeight = context.getResources().getDimensionPixelSize(resourceId); + } + return statusBarHeight; + } + /** * Get the navigation bar height (if visible) in pixels * @param context - the context @@ -2506,12 +2526,8 @@ public final class KMManager { if (windowManager != null) { WindowInsets insets = windowManager.getCurrentWindowMetrics().getWindowInsets(); android.graphics.Insets systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()); - android.graphics.Insets gestureInsets = insets.getInsets(WindowInsetsCompat.Type.systemGestures()); - boolean gestureInsetsVisible = insets.isVisible(WindowInsetsCompat.Type.systemGestures()); - android.graphics.Insets navigationInsets = insets.getInsets(WindowInsetsCompat.Type.navigationBars()); - boolean navigationInsetsVisible = insets.isVisible(WindowInsetsCompat.Type.navigationBars()); if (gestureInsets.bottom != navigationInsets.bottom) { navigationBarHeight = gestureInsets.bottom; @@ -2519,11 +2535,8 @@ public final class KMManager { navigationBarHeight = systemBarInsets.bottom; } - Log.d(TAG, String.format("gesture.visible %s, bottom: %d; navigation.visible %s, bottom: %d; systemBar.bottom %d; px density: %f", - gestureInsetsVisible, gestureInsets.bottom, - navigationInsetsVisible, navigationInsets.bottom, - systemBarInsets.bottom, - getWindowDensity(context))); + Log.d(TAG, String.format("gesture.bottom: %d; navigation.bottom: %d; systemBar.bottom %d", + gestureInsets.bottom, navigationInsets.bottom, systemBarInsets.bottom)); } } else { // Determine if navigation bar is visible @@ -2540,7 +2553,7 @@ public final class KMManager { context.getResources().getDimensionPixelSize(resourceId) : 0; } - return (int)(navigationBarHeight); + return navigationBarHeight; } /**