1 /* <lambda>null2 * Copyright 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.compose.foundation.text 18 19 import androidx.compose.ui.input.key.Key 20 import androidx.compose.ui.input.key.KeyEvent 21 import androidx.compose.ui.input.key.isAltPressed 22 import androidx.compose.ui.input.key.isCtrlPressed 23 import androidx.compose.ui.input.key.isShiftPressed 24 import androidx.compose.ui.input.key.key 25 26 internal interface KeyMapping { 27 fun map(event: KeyEvent): KeyCommand? 28 } 29 30 // each platform can define its own key mapping, on Android its just defaultKeyMapping, but on 31 // desktop, the value depends on the current OS 32 internal expect val platformDefaultKeyMapping: KeyMapping 33 34 /** Copied from [Key] as the constants there are experimental */ 35 internal expect object MappedKeys { 36 val A: Key 37 val C: Key 38 val H: Key 39 val V: Key 40 val X: Key 41 val Y: Key 42 val Z: Key 43 val Backslash: Key 44 val DirectionLeft: Key 45 val DirectionRight: Key 46 val DirectionUp: Key 47 val DirectionDown: Key 48 val PageUp: Key 49 val PageDown: Key 50 val MoveHome: Key 51 val MoveEnd: Key 52 val Insert: Key 53 val Enter: Key 54 val NumPadEnter: Key 55 val Backspace: Key 56 val Delete: Key 57 val Paste: Key 58 val Cut: Key 59 val Copy: Key 60 val Tab: Key 61 } 62 63 // It's common for all platforms key mapping commonKeyMappingnull64internal fun commonKeyMapping(shortcutModifier: (KeyEvent) -> Boolean): KeyMapping { 65 return object : KeyMapping { 66 override fun map(event: KeyEvent): KeyCommand? { 67 return when { 68 shortcutModifier(event) && event.isShiftPressed -> 69 when (event.key) { 70 MappedKeys.Z -> KeyCommand.REDO 71 else -> null 72 } 73 shortcutModifier(event) -> 74 when (event.key) { 75 MappedKeys.C, 76 MappedKeys.Insert -> KeyCommand.COPY 77 MappedKeys.V -> KeyCommand.PASTE 78 MappedKeys.X -> KeyCommand.CUT 79 MappedKeys.A -> KeyCommand.SELECT_ALL 80 MappedKeys.Y -> KeyCommand.REDO 81 MappedKeys.Z -> KeyCommand.UNDO 82 else -> null 83 } 84 event.isCtrlPressed -> null 85 event.isShiftPressed -> 86 when (event.key) { 87 MappedKeys.DirectionLeft -> KeyCommand.SELECT_LEFT_CHAR 88 MappedKeys.DirectionRight -> KeyCommand.SELECT_RIGHT_CHAR 89 MappedKeys.DirectionUp -> KeyCommand.SELECT_UP 90 MappedKeys.DirectionDown -> KeyCommand.SELECT_DOWN 91 MappedKeys.PageUp -> KeyCommand.SELECT_PAGE_UP 92 MappedKeys.PageDown -> KeyCommand.SELECT_PAGE_DOWN 93 MappedKeys.MoveHome -> KeyCommand.SELECT_LINE_START 94 MappedKeys.MoveEnd -> KeyCommand.SELECT_LINE_END 95 MappedKeys.Insert -> KeyCommand.PASTE 96 else -> null 97 } 98 else -> 99 when (event.key) { 100 MappedKeys.DirectionLeft -> KeyCommand.LEFT_CHAR 101 MappedKeys.DirectionRight -> KeyCommand.RIGHT_CHAR 102 MappedKeys.DirectionUp -> KeyCommand.UP 103 MappedKeys.DirectionDown -> KeyCommand.DOWN 104 MappedKeys.PageUp -> KeyCommand.PAGE_UP 105 MappedKeys.PageDown -> KeyCommand.PAGE_DOWN 106 MappedKeys.MoveHome -> KeyCommand.LINE_START 107 MappedKeys.MoveEnd -> KeyCommand.LINE_END 108 MappedKeys.Enter, 109 MappedKeys.NumPadEnter -> KeyCommand.NEW_LINE 110 MappedKeys.Backspace -> KeyCommand.DELETE_PREV_CHAR 111 MappedKeys.Delete -> KeyCommand.DELETE_NEXT_CHAR 112 MappedKeys.Paste -> KeyCommand.PASTE 113 MappedKeys.Cut -> KeyCommand.CUT 114 MappedKeys.Copy -> KeyCommand.COPY 115 MappedKeys.Tab -> KeyCommand.TAB 116 else -> null 117 } 118 } 119 } 120 } 121 } 122 123 // It's "default" or actually "non macOS" key mapping 124 internal val defaultKeyMapping: KeyMapping = commonnull125 commonKeyMapping(KeyEvent::isCtrlPressed).let { common -> 126 object : KeyMapping { 127 override fun map(event: KeyEvent): KeyCommand? { 128 return when { 129 event.isShiftPressed && event.isCtrlPressed -> 130 when (event.key) { 131 MappedKeys.DirectionLeft -> KeyCommand.SELECT_LEFT_WORD 132 MappedKeys.DirectionRight -> KeyCommand.SELECT_RIGHT_WORD 133 MappedKeys.DirectionUp -> KeyCommand.SELECT_PREV_PARAGRAPH 134 MappedKeys.DirectionDown -> KeyCommand.SELECT_NEXT_PARAGRAPH 135 else -> null 136 } 137 event.isCtrlPressed -> 138 when (event.key) { 139 MappedKeys.DirectionLeft -> KeyCommand.LEFT_WORD 140 MappedKeys.DirectionRight -> KeyCommand.RIGHT_WORD 141 MappedKeys.DirectionUp -> KeyCommand.PREV_PARAGRAPH 142 MappedKeys.DirectionDown -> KeyCommand.NEXT_PARAGRAPH 143 MappedKeys.H -> KeyCommand.DELETE_PREV_CHAR 144 MappedKeys.Delete -> KeyCommand.DELETE_NEXT_WORD 145 MappedKeys.Backspace -> KeyCommand.DELETE_PREV_WORD 146 MappedKeys.Backslash -> KeyCommand.DESELECT 147 else -> null 148 } 149 event.isShiftPressed -> 150 when (event.key) { 151 MappedKeys.MoveHome -> KeyCommand.SELECT_LINE_START 152 MappedKeys.MoveEnd -> KeyCommand.SELECT_LINE_END 153 else -> null 154 } 155 event.isAltPressed -> 156 when (event.key) { 157 MappedKeys.Backspace -> KeyCommand.DELETE_FROM_LINE_START 158 MappedKeys.Delete -> KeyCommand.DELETE_TO_LINE_END 159 else -> null 160 } 161 else -> null 162 } ?: common.map(event) 163 } 164 } 165 } 166