1 /*
2  * Copyright 2024 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.ui.focus
18 
19 import androidx.compose.ui.input.InputMode
20 import androidx.compose.ui.node.CompositionLocalConsumerModifierNode
21 import androidx.compose.ui.node.currentValueOf
22 import androidx.compose.ui.platform.LocalInputModeManager
23 import kotlin.jvm.JvmInline
24 
25 /**
26  * Focusability configures whether a focus target can be focused.
27  *
28  * @see Always
29  * @see SystemDefined
30  * @see Never
31  */
32 @JvmInline
33 value class Focusability private constructor(private val value: Int) {
34     companion object {
35         /**
36          * This focus target can always gain focus. This should be used for components that can be
37          * focused regardless of input device / system state, such as text fields.
38          */
39         val Always = Focusability(1)
40 
41         /**
42          * Focusability of this focus target will be defined by the system. This should be used for
43          * clickable components such as buttons and checkboxes: these components should only gain
44          * focus when they are used with certain types of input devices, such as keyboard / d-pad.
45          */
46         val SystemDefined = Focusability(0)
47 
48         /**
49          * This focus target can not gain focus. This should be used for disabled components /
50          * components that are currently not interactive.
51          */
52         val Never = Focusability(2)
53     }
54 
toStringnull55     override fun toString() =
56         when (this) {
57             Always -> "Always"
58             SystemDefined -> "SystemDefined"
59             Never -> "Never"
60             // Should not be reached since the constructor is private
61             else -> error("Unknown Focusability")
62         }
63 
canFocusnull64     internal fun canFocus(node: CompositionLocalConsumerModifierNode): Boolean {
65         return when (this@Focusability) {
66             Always -> true
67             SystemDefined ->
68                 with(node) { currentValueOf(LocalInputModeManager).inputMode != InputMode.Touch }
69             Never -> false
70             else -> error("Unknown Focusability")
71         }
72     }
73 }
74