key press -> app list
Some checks failed
Android Main Branch CI / Build, Sign & Upload (push) Has been cancelled
Update CHANGELOG.md / changelog (push) Has been cancelled
Validate Gradle Wrapper / Validation (push) Has been cancelled
Android Release CI / Build, Sign & Release (push) Has been cancelled
Nightly Release / release (push) Has been cancelled
Nightly Release / Build, Sign & Release (push) Has been cancelled
Delete Unused Caches / delete (push) Has been cancelled
Close Inactive Issues & Pull Requests / close-issues (push) Has been cancelled

This commit is contained in:
Jonas H
2026-08-17 11:48:43 +02:00
parent 462ed1b3ae
commit 416766a491
4 changed files with 63 additions and 1 deletions

View File

@@ -13,6 +13,7 @@ import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.KeyEvent
import android.view.Menu
import android.view.MenuItem
import android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
@@ -107,6 +108,43 @@ class MainActivity : AppCompatActivity() {
setLanguage()
}
/**
* When a printable character key is pressed on a physical keyboard while the
* home screen is showing, open the app list (drawer) with that character
* already entered into the search box. The event is consumed so the character
* does not also get sent to the search field on a second pass.
*/
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
if (isTypeToSearchKeyEvent(event)) {
val currentNavController = findNavController(R.id.nav_host_fragment_content_main)
if (currentNavController.currentDestination?.id == R.id.HomeFragment) {
val character = event.unicodeChar.toChar().toString()
val bundle = Bundle().apply {
putString(Constants.INITIAL_SEARCH_QUERY, character)
}
val options: NavOptions? =
if (preferenceHelper.disableAnimations) null
else appHelper.getActionType(Constants.Swipe.Up)
currentNavController.navigate(R.id.DrawFragment, bundle, options)
return true
}
}
return super.dispatchKeyEvent(event)
}
/**
* Returns true for key-down events that produce a printable character and are
* not part of a shortcut combination (ctrl/meta held). Shift and alt are
* allowed so letters, digits, punctuation, and space all trigger the search.
*/
private fun isTypeToSearchKeyEvent(event: KeyEvent): Boolean {
if (event.action != KeyEvent.ACTION_DOWN) return false
if (event.isCtrlPressed || event.isMetaPressed) return false
// Printable characters are code point 0x20 (space) and above.
// This naturally excludes enter, backspace, tab, escape, DPAD keys, etc.
return event.unicodeChar >= 0x20
}
@Suppress("DEPRECATION")
private fun setLanguage() {
val locale = preferenceHelper.appLanguage.locale()

View File

@@ -107,6 +107,24 @@ class DrawFragment : Fragment(),
// Initialize observation of drawer apps
observeDrawerApps()
applyInitialSearchQuery()
}
/**
* When the drawer was opened by typing a character on the physical keyboard
* (see MainActivity.dispatchKeyEvent), pre-fill the search box with that
* character and give the search field focus so the next keystrokes continue
* typing into the search.
*/
private fun applyInitialSearchQuery() {
val query = arguments?.getString(Constants.INITIAL_SEARCH_QUERY).orEmpty()
if (query.isEmpty()) return
binding.searchViewText.setQuery(query, false)
val queryField =
binding.searchViewText.findViewById<android.widget.EditText>(androidx.appcompat.R.id.search_src_text)
queryField?.requestFocus()
}
private fun setupRecyclerView() {

View File

@@ -62,6 +62,7 @@ object Constants {
const val SHOW_APP_ICON = "SHOW_APP_ICON"
const val AUTOMATIC_KEYBOARD = "AUTOMATIC_KEYBOARD"
const val INITIAL_SEARCH_QUERY = "initialSearchQuery"
const val AUTOMATIC_OPEN_APP = "AUTOMATIC_OPEN_APP"
const val SEARCH_FROM_START = "SEARCH_FROM_START"
const val FILTER_STRENGTH = "FILTER_STRENGTH"

View File

@@ -44,7 +44,12 @@
android:id="@+id/DrawFragment"
android:name="com.github.droidworksstudio.launcher.ui.drawer.DrawFragment"
android:label="@string/draw_fragment_label"
tools:layout="@layout/fragment_draw" />
tools:layout="@layout/fragment_draw">
<argument
android:name="initialSearchQuery"
android:defaultValue=""
app:argType="string" />
</fragment>
<fragment
android:id="@+id/FavoriteFragment"