fix: the Android keyboard opens on the first tap after the system dismissed it (#665)

This commit is contained in:
Kirk authored and GitHub committed 2026-10-13 14:17:31 -04:00
1 parent a12ac8134a
commit 5e23c668f3
2 files changed
+61 -1

No files matched your search

@@ -2,10 +2,12 @@ package com.droiddeck.launcher.input
import android.app.Activity
import android.content.Context
import android.os.Build
import android.text.InputType
import android.view.KeyCharacterMap
import android.view.KeyEvent
import android.view.View
import android.view.WindowInsets
import android.view.inputmethod.BaseInputConnection
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputConnection
@@ -53,7 +55,10 @@ class KeyboardHost(
return KeyConnection()
}
fun toggle() = if (shown) hide() else show()
fun toggle() = if (shown && imeVisible()) hide() else show()
private fun imeVisible() = Build.VERSION.SDK_INT < Build.VERSION_CODES.R ||
rootWindowInsets?.isVisible(WindowInsets.Type.ime()) != false
fun show() {
shown = true
@@ -0,0 +1,55 @@
package com.droiddeck.launcher.input
import android.app.Activity
import android.content.Context
import android.os.Looper
import android.view.inputmethod.InputMethodManager
import android.widget.FrameLayout
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.Robolectric
import org.robolectric.RobolectricTestRunner
import org.robolectric.Shadows.shadowOf
import org.robolectric.annotation.Config
@RunWith(RobolectricTestRunner::class)
@Config(manifest = Config.NONE)
class KeyboardHostTest {
private lateinit var imm: InputMethodManager
private lateinit var host: KeyboardHost
@Before fun setUp() {
val activity = Robolectric.buildActivity(Activity::class.java).setup().get()
imm = activity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
host = KeyboardHost(activity)
activity.setContentView(FrameLayout(activity).apply { addView(host) })
idle()
}
@Config(sdk = [33])
@Test fun toggleShowsAKeyboardTheSystemDismissed() {
host.show()
idle()
imm.hideSoftInputFromWindow(host.windowToken, 0)
idle()
host.toggle()
idle()
assertTrue(shadowOf(imm).isSoftInputVisible)
assertTrue(host.shown)
}
@Config(sdk = [28])
@Test fun toggleHidesAKeyboardThatIsShowing() {
host.show()
idle()
host.toggle()
idle()
assertFalse(shadowOf(imm).isSoftInputVisible)
assertFalse(host.shown)
}
private fun idle() = shadowOf(Looper.getMainLooper()).idle()
}