Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 293f2dbf authored by Josh's avatar Josh
Browse files

added Logic to convert UI key event to shortcut key models

This is background work for capturing user's selected key combination
for a shortcuts

Test: CustomShortcutCategoriesRepositoryTest
Flag: com.android.systemui.keyboard_shortcut_helper_shortcut_customizer
Bug: 373638584
Change-Id: I4c1878187a682cad24b995e83946f1d7aeda1e4a
parent 2671b65f
Loading
Loading
Loading
Loading
+81 −0
Original line number Diff line number Diff line
@@ -21,6 +21,14 @@ import android.content.Context.INPUT_SERVICE
import android.hardware.input.fakeInputManager
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.view.KeyEvent.KEYCODE_SLASH
import android.view.KeyEvent.META_ALT_ON
import android.view.KeyEvent.META_CAPS_LOCK_ON
import android.view.KeyEvent.META_CTRL_ON
import android.view.KeyEvent.META_FUNCTION_ON
import android.view.KeyEvent.META_META_ON
import android.view.KeyEvent.META_SHIFT_ON
import android.view.KeyEvent.META_SYM_ON
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.hardware.input.Flags.FLAG_ENABLE_CUSTOMIZABLE_INPUT_GESTURES
@@ -31,8 +39,11 @@ import com.android.systemui.keyboard.shortcut.customShortcutCategoriesRepository
import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.allCustomizableInputGesturesWithSimpleShortcutCombinations
import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.customizableInputGestureWithUnknownKeyGestureType
import com.android.systemui.keyboard.shortcut.data.source.TestShortcuts.expectedShortcutCategoriesWithSimpleShortcutCombination
import com.android.systemui.keyboard.shortcut.shared.model.KeyCombination
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutKey
import com.android.systemui.keyboard.shortcut.shortcutHelperTestHelper
import com.android.systemui.kosmos.testScope
import com.android.systemui.res.R
import com.android.systemui.settings.FakeUserTracker
import com.android.systemui.settings.userTracker
import com.android.systemui.testKosmos
@@ -114,4 +125,74 @@ class CustomShortcutCategoriesRepositoryTest : SysuiTestCase() {
            assertThat(categories).isEmpty()
        }
    }

    @Test
    fun pressedKeys_isEmptyByDefault() {
        testScope.runTest {
            val pressedKeys by collectLastValue(repo.pressedKeys)
            assertThat(pressedKeys).isEmpty()

            helper.toggle(deviceId = 123)
            assertThat(pressedKeys).isEmpty()
        }
    }

    @Test
    fun pressedKeys_recognizesAllSupportedModifiers() {
        testScope.runTest {
            helper.toggle(deviceId = 123)
            val pressedKeys by collectLastValue(repo.pressedKeys)
            repo.updateUserKeyCombination(
                KeyCombination(modifiers = allSupportedModifiers, keyCode = null)
            )

            assertThat(pressedKeys)
                .containsExactly(
                    ShortcutKey.Icon.ResIdIcon(R.drawable.ic_ksh_key_meta),
                    ShortcutKey.Text("Ctrl"),
                    ShortcutKey.Text("Fn"),
                    ShortcutKey.Text("Shift"),
                    ShortcutKey.Text("Alt"),
                    ShortcutKey.Text("Sym"),
                )
        }
    }

    @Test
    fun pressedKeys_ignoresUnsupportedModifiers() {
        testScope.runTest {
            helper.toggle(deviceId = 123)
            val pressedKeys by collectLastValue(repo.pressedKeys)
            repo.updateUserKeyCombination(
                KeyCombination(modifiers = META_CAPS_LOCK_ON, keyCode = null)
            )

            assertThat(pressedKeys).isEmpty()
        }
    }

    @Test
    fun pressedKeys_assertCorrectConversion() {
        testScope.runTest {
            helper.toggle(deviceId = 123)
            val pressedKeys by collectLastValue(repo.pressedKeys)
            repo.updateUserKeyCombination(
                KeyCombination(modifiers = META_META_ON, keyCode = KEYCODE_SLASH)
            )

            assertThat(pressedKeys)
                .containsExactly(
                    ShortcutKey.Icon.ResIdIcon(R.drawable.ic_ksh_key_meta),
                    ShortcutKey.Text("/"),
                )
        }
    }

    private val allSupportedModifiers =
        META_META_ON or
            META_CTRL_ON or
            META_FUNCTION_ON or
            META_SHIFT_ON or
            META_ALT_ON or
            META_SYM_ON
}
+46 −0
Original line number Diff line number Diff line
@@ -23,19 +23,24 @@ import android.hardware.input.InputGestureData.KeyTrigger
import android.hardware.input.InputManager
import android.hardware.input.InputSettings
import android.hardware.input.KeyGestureEvent
import com.android.systemui.Flags.shortcutHelperKeyGlyph
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.keyboard.shortcut.data.model.InternalKeyboardShortcutGroup
import com.android.systemui.keyboard.shortcut.data.model.InternalKeyboardShortcutInfo
import com.android.systemui.keyboard.shortcut.shared.model.KeyCombination
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategory
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutHelperState.Active
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutKey
import com.android.systemui.settings.UserTracker
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.withContext
@@ -60,6 +65,8 @@ constructor(
    private val inputManager: InputManager
        get() = userContext.getSystemService(INPUT_SERVICE) as InputManager

    private val _selectedKeyCombination = MutableStateFlow<KeyCombination?>(null)

    private val activeInputDevice =
        stateRepository.state.map {
            if (it is Active) {
@@ -69,6 +76,41 @@ constructor(
            }
        }

    val pressedKeys =
        _selectedKeyCombination
            .combine(activeInputDevice) { keyCombination, inputDevice ->
                if (inputDevice == null || keyCombination == null) {
                    return@combine emptyList()
                } else {
                    val keyGlyphMap =
                        if (shortcutHelperKeyGlyph()) {
                            inputManager.getKeyGlyphMap(inputDevice.id)
                        } else null
                    val modifiers =
                        shortcutCategoriesUtils.toShortcutModifierKeys(
                            keyCombination.modifiers,
                            keyGlyphMap,
                        )
                    val triggerKey =
                        keyCombination.keyCode?.let {
                            shortcutCategoriesUtils.toShortcutKey(
                                keyGlyphMap,
                                inputDevice.keyCharacterMap,
                                keyCode = it,
                            )
                        }
                    val keys = mutableListOf<ShortcutKey>()
                    modifiers?.let { keys += it }
                    triggerKey?.let { keys += it }
                    return@combine keys
                }
            }
            .stateIn(
                scope = backgroundScope,
                started = SharingStarted.Lazily,
                initialValue = emptyList(),
            )

    override val categories: Flow<List<ShortcutCategory>> =
        activeInputDevice
            .map { inputDevice ->
@@ -104,6 +146,10 @@ constructor(
                started = SharingStarted.Lazily,
            )

    fun updateUserKeyCombination(keyCombination: KeyCombination?) {
        _selectedKeyCombination.value = keyCombination
    }

    private fun toInternalGroupSources(
        inputGestures: List<InputGestureData>
    ): List<InternalGroupsSource> {
+20 −8
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.util.Log
import android.view.InputDevice
import android.view.KeyCharacterMap
import android.view.KeyEvent
import android.view.KeyEvent.META_META_ON
import com.android.systemui.Flags.shortcutHelperKeyGlyph
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.keyboard.shortcut.data.model.InternalKeyboardShortcutGroup
@@ -35,9 +36,9 @@ import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCommand
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutIcon
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutKey
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutSubCategory
import kotlinx.coroutines.withContext
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.withContext

class ShortcutCategoriesUtils
@Inject
@@ -161,7 +162,7 @@ constructor(
        }
        if (remainingModifiers != 0) {
            // There is a remaining modifier we don't support
            Log.wtf(TAG, "Unsupported modifiers remaining: $remainingModifiers")
            Log.w(TAG, "Unsupported modifiers remaining: $remainingModifiers")
            return null
        }
        if (info.keycode != 0 || info.baseCharacter > Char.MIN_VALUE) {
@@ -170,21 +171,32 @@ constructor(
                    ?: return null
        }
        if (keys.isEmpty()) {
            Log.wtf(TAG, "No keys for $info")
            Log.w(TAG, "No keys for $info")
            return null
        }
        return ShortcutCommand(keys = keys, isCustom = info.isCustomShortcut)
    }

    fun toShortcutModifierKeys(modifiers: Int, keyGlyphMap: KeyGlyphMap?): List<ShortcutKey>? {
        val keys: MutableList<ShortcutKey> = mutableListOf()
        var remainingModifiers = modifiers
        SUPPORTED_MODIFIERS.forEach { supportedModifier ->
            if ((supportedModifier and remainingModifiers) != 0) {
                keys += toShortcutModifierKey(keyGlyphMap, supportedModifier) ?: return null
                remainingModifiers = remainingModifiers and supportedModifier.inv()
            }
        }
        return keys
    }

    private fun toShortcutModifierKey(keyGlyphMap: KeyGlyphMap?, modifierMask: Int): ShortcutKey? {
        val modifierDrawable = keyGlyphMap?.getDrawableForModifierState(context, modifierMask)
        if (modifierDrawable != null) {
            return ShortcutKey.Icon.DrawableIcon(drawable = modifierDrawable)
        }

        val iconResId = ShortcutHelperKeys.keyIcons[modifierMask]
        if (iconResId != null) {
            return ShortcutKey.Icon.ResIdIcon(iconResId)
        if (modifierMask == META_META_ON) {
            return ShortcutKey.Icon.ResIdIcon(ShortcutHelperKeys.metaModifierIconResId)
        }

        val modifierLabel = ShortcutHelperKeys.modifierLabels[modifierMask]
@@ -195,7 +207,7 @@ constructor(
        return null
    }

    private fun toShortcutKey(
    fun toShortcutKey(
        keyGlyphMap: KeyGlyphMap?,
        keyCharacterMap: KeyCharacterMap,
        keyCode: Int,
@@ -222,7 +234,7 @@ constructor(
        if (displayLabelCharacter.code != 0) {
            return ShortcutKey.Text(displayLabelCharacter.toString())
        }
        Log.wtf(TAG, "Couldn't find label or icon for key: $keyCode")
        Log.w(TAG, "Couldn't find label or icon for key: $keyCode")
        return null
    }

+2 −1
Original line number Diff line number Diff line
@@ -116,9 +116,10 @@ import com.android.systemui.res.R

object ShortcutHelperKeys {

    val metaModifierIconResId = R.drawable.ic_ksh_key_meta

    val keyIcons =
        mapOf(
            META_META_ON to R.drawable.ic_ksh_key_meta,
            KEYCODE_BACK to R.drawable.ic_arrow_back_2,
            KEYCODE_HOME to R.drawable.ic_radio_button_unchecked,
            KEYCODE_RECENT_APPS to R.drawable.ic_check_box_outline_blank,
+12 −3
Original line number Diff line number Diff line
@@ -16,13 +16,22 @@

package com.android.systemui.keyboard.shortcut.domain.interactor

import android.view.KeyEvent.META_META_ON
import com.android.systemui.keyboard.shortcut.data.repository.CustomShortcutCategoriesRepository
import com.android.systemui.keyboard.shortcut.data.repository.ShortcutHelperKeys
import com.android.systemui.keyboard.shortcut.shared.model.KeyCombination
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutKey
import javax.inject.Inject

class ShortcutCustomizationInteractor @Inject constructor() {
class ShortcutCustomizationInteractor
@Inject
constructor(private val customShortcutRepository: CustomShortcutCategoriesRepository) {
    val pressedKeys = customShortcutRepository.pressedKeys

    fun updateUserSelectedKeyCombination(keyCombination: KeyCombination?) {
        customShortcutRepository.updateUserKeyCombination(keyCombination)
    }

    fun getDefaultCustomShortcutModifierKey(): ShortcutKey.Icon.ResIdIcon {
        return ShortcutKey.Icon.ResIdIcon(ShortcutHelperKeys.keyIcons[META_META_ON]!!)
        return ShortcutKey.Icon.ResIdIcon(ShortcutHelperKeys.metaModifierIconResId)
    }
}
Loading