Skip to content

Commit 8b01930

Browse files
committed
Compose UI for Linux
1 parent d9d4565 commit 8b01930

File tree

60 files changed

+1754
-11
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+1754
-11
lines changed

Diff for: buildSrc/src/main/kotlin/ComposePlatforms.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ enum class ComposePlatforms(vararg val alternativeNames: String) {
111111
val GENERATE_KLIB = WEB + LINUX_NATIVE + WINDOWS_NATIVE + DARWIN
112112

113113
val SKIKO_SUPPORT =
114-
EnumSet.of(KotlinMultiplatform) + JVM_BASED + UI_KIT + MACOS_NATIVE + WEB
114+
EnumSet.of(KotlinMultiplatform) + JVM_BASED + UI_KIT + MACOS_NATIVE + LINUX_NATIVE + WEB
115115

116116
val ALL = EnumSet.allOf(ComposePlatforms::class.java) - IOS
117117
val ALL_AOSP = EnumSet.allOf(ComposePlatforms::class.java) - UI_KIT

Diff for: compose/animation/animation-core/build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ if (AndroidXComposePlugin.isMultiplatformEnabled(project)) {
7474
darwin()
7575
js()
7676
wasm()
77+
linux()
7778
}
7879

7980
kotlin {

Diff for: compose/animation/animation-graphics/build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ if(AndroidXComposePlugin.isMultiplatformEnabled(project)) {
7171
darwin()
7272
js()
7373
wasm()
74+
linux()
7475
}
7576

7677
kotlin {

Diff for: compose/animation/animation/build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ if(AndroidXComposePlugin.isMultiplatformEnabled(project)) {
7272
darwin()
7373
js()
7474
wasm()
75+
linux()
7576
}
7677

7778
kotlin {

Diff for: compose/foundation/foundation-layout/build.gradle

+2
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ if(AndroidXComposePlugin.isMultiplatformEnabled(project)) {
7878
darwin()
7979
js()
8080
wasm()
81+
linux()
8182
}
8283

8384
kotlin {
@@ -122,6 +123,7 @@ if(AndroidXComposePlugin.isMultiplatformEnabled(project)) {
122123
desktopMain.dependsOn(notMobileMain)
123124
macosMain.dependsOn(notMobileMain)
124125
jsWasmMain.dependsOn(notMobileMain)
126+
linuxMain.dependsOn(notMobileMain)
125127

126128
jsMain {
127129
dependsOn(jsWasmMain)

Diff for: compose/foundation/foundation/build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ if (AndroidXComposePlugin.isMultiplatformEnabled(project)) {
9494
darwin()
9595
js()
9696
wasm()
97+
linux()
9798

9899
configureDarwinFlags()
99100
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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.foundation
18+
19+
// TODO: b/168524931 - should this depend on the input device?
20+
internal actual val TapIndicationDelay: Long = 0L
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright 2023 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
18+
19+
import androidx.compose.runtime.Composable
20+
import androidx.compose.runtime.CompositionLocalAccessorScope
21+
22+
@Composable
23+
internal actual fun rememberPlatformOverscrollEffect(): OverscrollEffect? =
24+
null
25+
26+
internal actual fun CompositionLocalAccessorScope.defaultOverscrollFactory(): OverscrollFactory? =
27+
null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright 2023 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
18+
19+
internal actual fun isRequestFocusOnClickEnabled(): Boolean = true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright 2022 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.gestures
18+
19+
import androidx.compose.ui.geometry.Offset
20+
import androidx.compose.ui.input.pointer.PointerEvent
21+
import androidx.compose.ui.node.CompositionLocalConsumerModifierNode
22+
import androidx.compose.ui.unit.Density
23+
import androidx.compose.ui.unit.IntSize
24+
import androidx.compose.ui.unit.dp
25+
import androidx.compose.ui.util.fastFold
26+
import kotlin.math.sqrt
27+
28+
internal actual fun CompositionLocalConsumerModifierNode.platformScrollConfig(): ScrollConfig =
29+
LinuxScrollConfig
30+
31+
private object LinuxScrollConfig : ScrollConfig {
32+
// See https://developer.apple.com/documentation/appkit/nsevent/1535387-scrollingdeltay
33+
override fun Density.calculateMouseWheelScroll(event: PointerEvent, bounds: IntSize): Offset {
34+
// 64 dp value is taken from ViewConfiguration.java, replace with better solution
35+
36+
val verticalScrollFactor = -64.dp.toPx()
37+
38+
val horizontalScrollFactor = -64.dp.toPx()
39+
40+
return event.changes
41+
.fastFold(Offset.Zero) { acc, c -> acc + c.scrollDelta }
42+
.let { Offset(it.x * horizontalScrollFactor, it.y * verticalScrollFactor) }
43+
}
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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.foundation.gestures
18+
19+
import androidx.compose.animation.SplineBasedFloatDecayAnimationSpec
20+
import androidx.compose.animation.core.generateDecayAnimationSpec
21+
import androidx.compose.animation.rememberSplineBasedDecay
22+
import androidx.compose.runtime.Composable
23+
import androidx.compose.runtime.remember
24+
25+
internal actual fun platformDefaultFlingBehavior(): ScrollableDefaultFlingBehavior =
26+
DefaultFlingBehavior(
27+
SplineBasedFloatDecayAnimationSpec(UnityDensity).generateDecayAnimationSpec()
28+
)
29+
30+
@Composable
31+
internal actual fun rememberPlatformDefaultFlingBehavior(): FlingBehavior {
32+
val flingSpec = rememberSplineBasedDecay<Float>()
33+
return remember(flingSpec) {
34+
DefaultFlingBehavior(flingSpec)
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright 2025 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+
@file:OptIn(ExperimentalComposeUiApi::class)
18+
19+
package androidx.compose.foundation.internal
20+
21+
import androidx.compose.ui.ExperimentalComposeUiApi
22+
import androidx.compose.ui.platform.ClipEntry
23+
import androidx.compose.ui.text.AnnotatedString
24+
25+
26+
internal actual suspend fun ClipEntry.readText(): String? {
27+
return null
28+
}
29+
30+
internal actual suspend fun ClipEntry.readAnnotatedString(): AnnotatedString? {
31+
return null
32+
}
33+
34+
internal actual fun AnnotatedString?.toClipEntry(): ClipEntry? {
35+
return null
36+
}
37+
38+
internal actual fun ClipEntry?.hasText(): Boolean = false
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright 2025 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.lazy
18+
19+
import androidx.compose.runtime.Composable
20+
21+
@Composable internal actual fun defaultLazyListBeyondBoundsItemCount(): Int = 0
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright 2022 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+
internal actual val platformDefaultKeyMapping: KeyMapping = defaultSkikoKeyMapping
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright 2022 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.KeyEvent
20+
import androidx.compose.ui.input.key.KeyEventType
21+
import androidx.compose.ui.input.key.isCtrlPressed
22+
import androidx.compose.ui.input.key.isMetaPressed
23+
import androidx.compose.ui.input.key.type
24+
import androidx.compose.ui.input.key.utf16CodePoint
25+
26+
actual val KeyEvent.isTypedEvent: Boolean
27+
get() = type == KeyEventType.KeyDown &&
28+
!isISOControl(utf16CodePoint) &&
29+
!isMetaPressed &&
30+
!isCtrlPressed
31+
32+
private fun isISOControl(codePoint: Int): Boolean =
33+
codePoint in 0x00..0x1F ||
34+
codePoint in 0x7F..0x9F
35+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright 2023 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.foundation.interaction.MutableInteractionSource
20+
import androidx.compose.foundation.text.selection.TextFieldSelectionManager
21+
import androidx.compose.runtime.Composable
22+
import androidx.compose.ui.Modifier
23+
import androidx.compose.ui.focus.FocusRequester
24+
import androidx.compose.ui.text.input.OffsetMapping
25+
26+
@Composable
27+
internal actual fun Modifier.textFieldPointer(
28+
manager: TextFieldSelectionManager,
29+
enabled: Boolean,
30+
interactionSource: MutableInteractionSource?,
31+
state: LegacyTextFieldState,
32+
focusRequester: FocusRequester,
33+
readOnly: Boolean,
34+
offsetMapping: OffsetMapping
35+
): Modifier = Modifier.defaultTextFieldPointer(
36+
manager,
37+
enabled,
38+
interactionSource,
39+
state,
40+
focusRequester,
41+
readOnly,
42+
offsetMapping,
43+
)

0 commit comments

Comments
 (0)