diff --git a/app/src/main/java/com/github/droidworksstudio/launcher/ui/activities/MainActivity.kt b/app/src/main/java/com/github/droidworksstudio/launcher/ui/activities/MainActivity.kt index bbf4318..aa4c871 100644 --- a/app/src/main/java/com/github/droidworksstudio/launcher/ui/activities/MainActivity.kt +++ b/app/src/main/java/com/github/droidworksstudio/launcher/ui/activities/MainActivity.kt @@ -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() diff --git a/app/src/main/java/com/github/droidworksstudio/launcher/ui/drawer/DrawFragment.kt b/app/src/main/java/com/github/droidworksstudio/launcher/ui/drawer/DrawFragment.kt index 6c0eef1..c640047 100644 --- a/app/src/main/java/com/github/droidworksstudio/launcher/ui/drawer/DrawFragment.kt +++ b/app/src/main/java/com/github/droidworksstudio/launcher/ui/drawer/DrawFragment.kt @@ -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(androidx.appcompat.R.id.search_src_text) + queryField?.requestFocus() } private fun setupRecyclerView() { diff --git a/app/src/main/java/com/github/droidworksstudio/launcher/utils/Constants.kt b/app/src/main/java/com/github/droidworksstudio/launcher/utils/Constants.kt index 2a7d632..b7ed69e 100644 --- a/app/src/main/java/com/github/droidworksstudio/launcher/utils/Constants.kt +++ b/app/src/main/java/com/github/droidworksstudio/launcher/utils/Constants.kt @@ -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" diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index 7d4a4a4..9220c9d 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -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"> + +