From d81d79ea675a9bc4dd6ce3097bd2744f18bb829e Mon Sep 17 00:00:00 2001 From: Aleksandras Kostarevas Date: Mon, 14 Aug 2023 16:53:33 +0300 Subject: [PATCH] Fix inset setting code --- .../org/futo/inputmethod/latin/LatinIME.kt | 87 +++++++++---------- .../inputmethod/latin/LatinIMELegacy.java | 58 +++---------- 2 files changed, 55 insertions(+), 90 deletions(-) diff --git a/java/src/org/futo/inputmethod/latin/LatinIME.kt b/java/src/org/futo/inputmethod/latin/LatinIME.kt index 352261156..ca88c4b22 100644 --- a/java/src/org/futo/inputmethod/latin/LatinIME.kt +++ b/java/src/org/futo/inputmethod/latin/LatinIME.kt @@ -3,55 +3,26 @@ package org.futo.inputmethod.latin import android.content.Context import android.content.res.Configuration import android.inputmethodservice.InputMethodService -import android.os.Build -import android.text.InputType import android.view.KeyEvent import android.view.View import android.view.inputmethod.CompletionInfo import android.view.inputmethod.EditorInfo import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodSubtype -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.wrapContentHeight -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Close -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.drawBehind -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.drawscope.scale -import androidx.compose.ui.graphics.drawscope.translate +import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.ComposeView -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.ViewCompositionStrategy -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView import androidx.lifecycle.Lifecycle -import androidx.lifecycle.LifecycleCoroutineScope import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleRegistry import androidx.lifecycle.ViewModelStore import androidx.lifecycle.ViewModelStoreOwner -import androidx.lifecycle.coroutineScope import androidx.lifecycle.findViewTreeLifecycleOwner import androidx.lifecycle.findViewTreeViewModelStoreOwner import androidx.lifecycle.setViewTreeLifecycleOwner @@ -124,6 +95,7 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save } private var legacyInputView: View? = null + private var touchableHeight: Int = 0 override fun onCreateInputView(): View { legacyInputView = latinIMELegacy.onCreateInputView() composeView = ComposeView(this).apply { @@ -134,14 +106,16 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save } composeView?.setContent { - Surface(color = Color.Blue) { - Column { - Text("Example Compose Element", color = Color.Red) - Text("The keyboard below is wrapped in AndroidView", color = Color.Red) - - AndroidView(factory = { - legacyInputView!! - }, update = { }) + Column { + Spacer(modifier = Modifier.weight(1.0f)) + Surface(modifier = Modifier.onSizeChanged { + touchableHeight = it.height + }, color = MaterialTheme.colorScheme.surface) { + Column { + AndroidView(factory = { + legacyInputView!! + }, update = { }) + } } } } @@ -151,6 +125,7 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save override fun setInputView(view: View?) { super.setInputView(view) + latinIMELegacy.setComposeInputView(composeView!!) latinIMELegacy.setInputView(legacyInputView) } @@ -225,15 +200,37 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save latinIMELegacy.onDisplayCompletions(completions) } - /* - // TODO: This seems to not factor in the dimensions of the Compose elements - // and bottom parts of the keyboard start to pass input through to the app. - // The keyboard seems to work fine without this method. What was it for? override fun onComputeInsets(outInsets: Insets?) { - super.onComputeInsets(outInsets) - latinIMELegacy.onComputeInsets(outInsets) + // This method may be called before {@link #setInputView(View)}. + if (legacyInputView == null) { + return + } + + val inputHeight: Int = composeView!!.height + if (latinIMELegacy.isImeSuppressedByHardwareKeyboard && !legacyInputView!!.isShown) { + // If there is a hardware keyboard and a visible software keyboard view has been hidden, + // no visual element will be shown on the screen. + latinIMELegacy.setInsets(outInsets!!.apply { + contentTopInsets = inputHeight + visibleTopInsets = inputHeight + }) + return + } + + val visibleTopY = inputHeight - touchableHeight + + val touchLeft = 0 + val touchTop = visibleTopY + val touchRight = legacyInputView!!.width + val touchBottom = inputHeight + + latinIMELegacy.setInsets(outInsets!!.apply { + touchableInsets = Insets.TOUCHABLE_INSETS_REGION; + touchableRegion.set(touchLeft, touchTop, touchRight, touchBottom); + contentTopInsets = visibleTopY + visibleTopInsets = visibleTopY + }) } - */ override fun onShowInputRequested(flags: Int, configChange: Boolean): Boolean { return latinIMELegacy.onShowInputRequested(flags, configChange) || super.onShowInputRequested(flags, configChange) diff --git a/java/src/org/futo/inputmethod/latin/LatinIMELegacy.java b/java/src/org/futo/inputmethod/latin/LatinIMELegacy.java index 686418940..8ba7f0536 100644 --- a/java/src/org/futo/inputmethod/latin/LatinIMELegacy.java +++ b/java/src/org/futo/inputmethod/latin/LatinIMELegacy.java @@ -158,6 +158,7 @@ public class LatinIMELegacy implements KeyboardActionListener, // TODO: Move these {@link View}s to {@link KeyboardSwitcher}. private View mInputView; + private View mComposeInputView; private InsetsUpdater mInsetsUpdater; private SuggestionStripView mSuggestionStripView; @@ -762,7 +763,7 @@ public class LatinIMELegacy implements KeyboardActionListener, mInputLogic.recycle(); } - private boolean isImeSuppressedByHardwareKeyboard() { + public boolean isImeSuppressedByHardwareKeyboard() { final KeyboardSwitcher switcher = KeyboardSwitcher.getInstance(); return !onEvaluateInputViewShown() && switcher.isImeSuppressedByHardwareKeyboard( mSettings.getCurrent(), switcher.getKeyboardSwitchState()); @@ -836,10 +837,15 @@ public class LatinIMELegacy implements KeyboardActionListener, mIsHardwareAcceleratedDrawingEnabled); } - public void setInputView(final View view) { - mInputView = view; + + public void setComposeInputView(final View view) { + mComposeInputView = view; mInsetsUpdater = ViewOutlineProviderCompatUtils.setInsetsOutlineProvider(view); updateSoftInputWindowLayoutParameters(); + } + + public void setInputView(final View view) { + mInputView = view; mSuggestionStripView = (SuggestionStripView)view.findViewById(R.id.suggestion_strip_view); if (hasSuggestionStripView()) { mSuggestionStripView.setListener(this, view); @@ -1196,42 +1202,8 @@ public class LatinIMELegacy implements KeyboardActionListener, setSuggestedWords(suggestedWords); } - public void onComputeInsets(final InputMethodService.Insets outInsets) { - // This method may be called before {@link #setInputView(View)}. - if (mInputView == null) { - return; - } - final SettingsValues settingsValues = mSettings.getCurrent(); - final View visibleKeyboardView = mKeyboardSwitcher.getVisibleKeyboardView(); - if (visibleKeyboardView == null || !hasSuggestionStripView()) { - return; - } - final int inputHeight = mInputView.getHeight(); - if (isImeSuppressedByHardwareKeyboard() && !visibleKeyboardView.isShown()) { - // If there is a hardware keyboard and a visible software keyboard view has been hidden, - // no visual element will be shown on the screen. - outInsets.contentTopInsets = inputHeight; - outInsets.visibleTopInsets = inputHeight; - mInsetsUpdater.setInsets(outInsets); - return; - } - final int suggestionsHeight = (!mKeyboardSwitcher.isShowingEmojiPalettes() - && mSuggestionStripView.getVisibility() == View.VISIBLE) - ? mSuggestionStripView.getHeight() : 0; - final int visibleTopY = inputHeight - visibleKeyboardView.getHeight() - suggestionsHeight; - mSuggestionStripView.setMoreSuggestionsHeight(visibleTopY); - // Need to set expanded touchable region only if a keyboard view is being shown. - if (visibleKeyboardView.isShown()) { - final int touchLeft = 0; - final int touchTop = mKeyboardSwitcher.isShowingMoreKeysPanel() ? 0 : visibleTopY; - final int touchRight = visibleKeyboardView.getWidth(); - final int touchBottom = inputHeight; - outInsets.touchableInsets = InputMethodService.Insets.TOUCHABLE_INSETS_REGION; - outInsets.touchableRegion.set(touchLeft, touchTop, touchRight, touchBottom); - } - outInsets.contentTopInsets = visibleTopY; - outInsets.visibleTopInsets = visibleTopY; - mInsetsUpdater.setInsets(outInsets); + public void setInsets(final InputMethodService.Insets insets) { + mInsetsUpdater.setInsets(insets); } public void startShowingInputView(final boolean needsToLoadKeyboard) { @@ -1287,16 +1259,13 @@ public class LatinIMELegacy implements KeyboardActionListener, } private void updateSoftInputWindowLayoutParameters() { - // TODO: This seems to mess with the compose UI a lot, and the keyboard - // works fine without it. What was it for? - /* // Override layout parameters to expand {@link SoftInputWindow} to the entire screen. // See {@link InputMethodService#setinputView(View)} and // {@link SoftInputWindow#updateWidthHeight(WindowManager.LayoutParams)}. final Window window = mInputMethodService.getWindow().getWindow(); ViewLayoutUtils.updateLayoutHeightOf(window, LayoutParams.MATCH_PARENT); // This method may be called before {@link #setInputView(View)}. - if (mInputView != null) { + if (mComposeInputView != null) { // In non-fullscreen mode, {@link InputView} and its parent inputArea should expand to // the entire screen and be placed at the bottom of {@link SoftInputWindow}. // In fullscreen mode, these shouldn't expand to the entire screen and should be @@ -1308,9 +1277,8 @@ public class LatinIMELegacy implements KeyboardActionListener, final View inputArea = window.findViewById(android.R.id.inputArea); ViewLayoutUtils.updateLayoutHeightOf(inputArea, layoutHeight); ViewLayoutUtils.updateLayoutGravityOf(inputArea, Gravity.BOTTOM); - ViewLayoutUtils.updateLayoutHeightOf(mInputView, layoutHeight); + ViewLayoutUtils.updateLayoutHeightOf(mComposeInputView, layoutHeight); } - */ } int getCurrentAutoCapsState() {