diff --git a/buildSrc/public/src/main/kotlin/org/jetbrains/androidx/build/ComposePlatforms.kt b/buildSrc/public/src/main/kotlin/org/jetbrains/androidx/build/ComposePlatforms.kt index 4e2be5059c6bb..af27a9a682065 100644 --- a/buildSrc/public/src/main/kotlin/org/jetbrains/androidx/build/ComposePlatforms.kt +++ b/buildSrc/public/src/main/kotlin/org/jetbrains/androidx/build/ComposePlatforms.kt @@ -111,7 +111,7 @@ enum class ComposePlatforms(vararg val alternativeNames: String) { val GENERATE_KLIB = WEB + LINUX_NATIVE + WINDOWS_NATIVE + DARWIN val SKIKO_SUPPORT = - EnumSet.of(KotlinMultiplatform) + JVM_BASED + UI_KIT + MACOS_NATIVE + WEB + EnumSet.of(KotlinMultiplatform) + JVM_BASED + UI_KIT + MACOS_NATIVE + LINUX_NATIVE + WEB val ALL = EnumSet.allOf(ComposePlatforms::class.java) - IOS val ALL_AOSP = EnumSet.allOf(ComposePlatforms::class.java) - UI_KIT diff --git a/compose/animation/animation-core/build.gradle b/compose/animation/animation-core/build.gradle index 1818b56e4e4a9..7aeb0fa4e9503 100644 --- a/compose/animation/animation-core/build.gradle +++ b/compose/animation/animation-core/build.gradle @@ -73,6 +73,7 @@ if (AndroidXComposePlugin.isMultiplatformEnabled(project)) { darwin() js() wasm() + linux() } kotlin { diff --git a/compose/animation/animation-graphics/build.gradle b/compose/animation/animation-graphics/build.gradle index 246cd35527601..fc5a57f2ef0fc 100644 --- a/compose/animation/animation-graphics/build.gradle +++ b/compose/animation/animation-graphics/build.gradle @@ -70,6 +70,7 @@ if(AndroidXComposePlugin.isMultiplatformEnabled(project)) { darwin() js() wasm() + linux() } kotlin { diff --git a/compose/animation/animation/build.gradle b/compose/animation/animation/build.gradle index d34b9a414f168..96feb3c8f5560 100644 --- a/compose/animation/animation/build.gradle +++ b/compose/animation/animation/build.gradle @@ -71,6 +71,7 @@ if(AndroidXComposePlugin.isMultiplatformEnabled(project)) { darwin() js() wasm() + linux() } kotlin { diff --git a/compose/foundation/foundation-layout/build.gradle b/compose/foundation/foundation-layout/build.gradle index b1b630d6df0f0..54cec39ec9829 100644 --- a/compose/foundation/foundation-layout/build.gradle +++ b/compose/foundation/foundation-layout/build.gradle @@ -77,6 +77,7 @@ if(AndroidXComposePlugin.isMultiplatformEnabled(project)) { darwin() js() wasm() + linux() } kotlin { @@ -120,6 +121,7 @@ if(AndroidXComposePlugin.isMultiplatformEnabled(project)) { desktopMain.dependsOn(skikoMain) macosMain.dependsOn(skikoMain) webMain.dependsOn(skikoMain) + linuxMain.dependsOn(skikoMain) jsMain { dependsOn(webMain) diff --git a/compose/foundation/foundation/build.gradle b/compose/foundation/foundation/build.gradle index a9ef5a0e06c30..c3298a790e111 100644 --- a/compose/foundation/foundation/build.gradle +++ b/compose/foundation/foundation/build.gradle @@ -93,6 +93,7 @@ if (AndroidXComposePlugin.isMultiplatformEnabled(project)) { darwin() js() wasm() + linux() configureDarwinFlags() } diff --git a/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/Clickable.linux.kt b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/Clickable.linux.kt new file mode 100644 index 0000000000000..1b5491b5a2ffd --- /dev/null +++ b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/Clickable.linux.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.foundation + +// TODO: b/168524931 - should this depend on the input device? +internal actual val TapIndicationDelay: Long = 100L diff --git a/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/Overscroll.linux.kt b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/Overscroll.linux.kt new file mode 100644 index 0000000000000..d79b2c666175d --- /dev/null +++ b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/Overscroll.linux.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.foundation + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalAccessorScope + +@Composable +internal actual fun rememberPlatformOverscrollEffect(): OverscrollEffect? = + null + +internal actual fun CompositionLocalAccessorScope.defaultOverscrollFactory(): OverscrollFactory? = + null diff --git a/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/RequestFocusOnClick.linux.kt b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/RequestFocusOnClick.linux.kt new file mode 100644 index 0000000000000..706b2f9e40855 --- /dev/null +++ b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/RequestFocusOnClick.linux.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.foundation + +internal actual fun isRequestFocusOnClickEnabled(): Boolean = false diff --git a/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/gestures/LinuxScrollable.linux.kt b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/gestures/LinuxScrollable.linux.kt new file mode 100644 index 0000000000000..5c6e5be530214 --- /dev/null +++ b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/gestures/LinuxScrollable.linux.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.foundation.gestures + +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.input.pointer.PointerEvent +import androidx.compose.ui.node.CompositionLocalConsumerModifierNode +import androidx.compose.ui.unit.Density +import androidx.compose.ui.unit.IntSize +import androidx.compose.ui.unit.dp +import androidx.compose.ui.util.fastFold +import kotlin.math.sqrt + +internal actual fun CompositionLocalConsumerModifierNode.platformScrollConfig(): ScrollConfig = + LinuxScrollConfig + +private object LinuxScrollConfig : ScrollConfig { + // See https://developer.apple.com/documentation/appkit/nsevent/1535387-scrollingdeltay + override fun Density.calculateMouseWheelScroll(event: PointerEvent, bounds: IntSize): Offset { + // 64 dp value is taken from ViewConfiguration.java, replace with better solution + + val verticalScrollFactor = -64.dp.toPx() + + val horizontalScrollFactor = -64.dp.toPx() + + return event.changes + .fastFold(Offset.Zero) { acc, c -> acc + c.scrollDelta } + .let { Offset(it.x * horizontalScrollFactor, it.y * verticalScrollFactor) } + } +} diff --git a/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/gestures/Scrollable.linux.kt b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/gestures/Scrollable.linux.kt new file mode 100644 index 0000000000000..1e4e0d8a3f5cd --- /dev/null +++ b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/gestures/Scrollable.linux.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.foundation.gestures + +import androidx.compose.animation.SplineBasedFloatDecayAnimationSpec +import androidx.compose.animation.core.generateDecayAnimationSpec +import androidx.compose.animation.rememberSplineBasedDecay +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember + +internal actual fun platformScrollableDefaultFlingBehavior(): ScrollableDefaultFlingBehavior = + DefaultFlingBehavior( + SplineBasedFloatDecayAnimationSpec(UnityDensity).generateDecayAnimationSpec() + ) + +@Composable +internal actual fun rememberPlatformDefaultFlingBehavior(): FlingBehavior { + val flingSpec = rememberSplineBasedDecay() + return remember(flingSpec) { + DefaultFlingBehavior(flingSpec) + } +} diff --git a/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/internal/ClipboardUtils.linux.kt b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/internal/ClipboardUtils.linux.kt new file mode 100644 index 0000000000000..3b29cd0b01b44 --- /dev/null +++ b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/internal/ClipboardUtils.linux.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:OptIn(ExperimentalComposeUiApi::class) + +package androidx.compose.foundation.internal + +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.platform.ClipEntry +import androidx.compose.ui.platform.Clipboard +import androidx.compose.ui.text.AnnotatedString + + +internal actual suspend fun ClipEntry.readText(): String? { + return null +} + +internal actual suspend fun ClipEntry.readAnnotatedString(): AnnotatedString? { + return null +} + +internal actual fun AnnotatedString?.toClipEntry(): ClipEntry? { + return null +} + +internal actual fun ClipEntry?.hasText(): Boolean = false + +internal actual fun Clipboard.isReadSupported(): Boolean = false +internal actual fun Clipboard.isWriteSupported(): Boolean = false \ No newline at end of file diff --git a/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/lazy/LazyList.linux.kt b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/lazy/LazyList.linux.kt new file mode 100644 index 0000000000000..d10fbc59e23a3 --- /dev/null +++ b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/lazy/LazyList.linux.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.foundation.lazy + +import androidx.compose.runtime.Composable + +@Composable internal actual fun defaultLazyListBeyondBoundsItemCount(): Int = 0 diff --git a/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/ContextMenu.linux.kt b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/ContextMenu.linux.kt new file mode 100644 index 0000000000000..59a407e950677 --- /dev/null +++ b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/ContextMenu.linux.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.foundation.text + +import androidx.compose.foundation.text.input.internal.selection.TextFieldSelectionState +import androidx.compose.foundation.text.selection.SelectionManager +import androidx.compose.foundation.text.selection.TextFieldSelectionManager +import androidx.compose.runtime.Composable + +@Composable +internal actual fun ContextMenuArea( + manager: TextFieldSelectionManager, + content: @Composable () -> Unit +) = CommonContextMenuArea(manager, content) + +@Composable +internal actual fun ContextMenuArea( + selectionState: TextFieldSelectionState, + enabled: Boolean, + content: @Composable () -> Unit +) = CommonContextMenuArea(selectionState, enabled, content) + +@Composable +internal actual fun ContextMenuArea( + manager: SelectionManager, + content: @Composable () -> Unit +) = CommonContextMenuArea(manager, content) diff --git a/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/KeyMapping.linux.kt b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/KeyMapping.linux.kt new file mode 100644 index 0000000000000..e18c3f5cad5de --- /dev/null +++ b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/KeyMapping.linux.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.foundation.text + +internal actual val platformDefaultKeyMapping: KeyMapping = defaultSkikoKeyMapping diff --git a/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/TextFieldKeyInput.linux.kt b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/TextFieldKeyInput.linux.kt new file mode 100644 index 0000000000000..82f809f942c2f --- /dev/null +++ b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/TextFieldKeyInput.linux.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.foundation.text + +import androidx.compose.ui.input.key.KeyEvent +import androidx.compose.ui.input.key.KeyEventType +import androidx.compose.ui.input.key.isCtrlPressed +import androidx.compose.ui.input.key.isMetaPressed +import androidx.compose.ui.input.key.type +import androidx.compose.ui.input.key.utf16CodePoint + +actual val KeyEvent.isTypedEvent: Boolean + get() = type == KeyEventType.KeyDown && + !isISOControl(utf16CodePoint) && + !isMetaPressed && + !isCtrlPressed + +private fun isISOControl(codePoint: Int): Boolean = + codePoint in 0x00..0x1F || + codePoint in 0x7F..0x9F + diff --git a/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/TextFieldPointerModifier.linux.kt b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/TextFieldPointerModifier.linux.kt new file mode 100644 index 0000000000000..3a594714e9dc3 --- /dev/null +++ b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/TextFieldPointerModifier.linux.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.foundation.text + +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.text.selection.TextFieldSelectionManager +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.text.input.OffsetMapping + +@Composable +internal actual fun Modifier.textFieldPointer( + manager: TextFieldSelectionManager, + enabled: Boolean, + interactionSource: MutableInteractionSource?, + state: LegacyTextFieldState, + focusRequester: FocusRequester, + readOnly: Boolean, + offsetMapping: OffsetMapping +): Modifier = Modifier.defaultTextFieldPointer( + manager, + enabled, + interactionSource, + state, + focusRequester, + readOnly, + offsetMapping, +) diff --git a/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/TextFieldScroll.linux.kt b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/TextFieldScroll.linux.kt new file mode 100644 index 0000000000000..fadeee5536351 --- /dev/null +++ b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/TextFieldScroll.linux.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.foundation.text + +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.OverscrollEffect +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.text.input.VisualTransformation + +@ExperimentalFoundationApi +@Composable +internal actual fun rememberTextFieldOverscrollEffect(): OverscrollEffect? = null + +internal actual fun Modifier.textFieldScroll( + scrollerPosition: TextFieldScrollerPosition, + textFieldValue: TextFieldValue, + visualTransformation: VisualTransformation, + textLayoutResultProvider: () -> TextLayoutResultProxy? +): Modifier = defaultTextFieldScroll( + scrollerPosition, + textFieldValue, + visualTransformation, + textLayoutResultProvider, +) diff --git a/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/TouchMode.linux.kt b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/TouchMode.linux.kt new file mode 100644 index 0000000000000..bb44e0b1a930c --- /dev/null +++ b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/TouchMode.linux.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.foundation.text + +internal actual val isInTouchMode = true diff --git a/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/input/internal/selection/TextFieldKeyEventHandler.linux.kt b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/input/internal/selection/TextFieldKeyEventHandler.linux.kt new file mode 100644 index 0000000000000..928428b94cee4 --- /dev/null +++ b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/input/internal/selection/TextFieldKeyEventHandler.linux.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.foundation.text.input.internal + +/** Factory function to create a platform specific [TextFieldKeyEventHandler]. */ +internal actual fun createTextFieldKeyEventHandler() = createSkikoTextFieldKeyEventHandler() \ No newline at end of file diff --git a/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/input/internal/selection/TextFieldMagnifierNode.linux.kt b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/input/internal/selection/TextFieldMagnifierNode.linux.kt new file mode 100644 index 0000000000000..3a64a3c92fbe5 --- /dev/null +++ b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/input/internal/selection/TextFieldMagnifierNode.linux.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.foundation.text.input.internal.selection + +import androidx.compose.foundation.text.input.internal.TextLayoutState +import androidx.compose.foundation.text.input.internal.TransformedTextFieldState + +/** + * Initializes either an actual TextFieldMagnifierNode implementation or No-op node according to + * whether magnifier is supported. + */ +internal actual fun textFieldMagnifierNode( + textFieldState: TransformedTextFieldState, + textFieldSelectionState: TextFieldSelectionState, + textLayoutState: TextLayoutState, + visible: Boolean +): TextFieldMagnifierNode { + return object : TextFieldMagnifierNode() { + override fun update( + textFieldState: TransformedTextFieldState, + textFieldSelectionState: TextFieldSelectionState, + textLayoutState: TextLayoutState, + visible: Boolean + ) {} + } +} \ No newline at end of file diff --git a/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/input/internal/selection/TextFieldSelectionState.linux.kt b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/input/internal/selection/TextFieldSelectionState.linux.kt new file mode 100644 index 0000000000000..0c6283c3d16e9 --- /dev/null +++ b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/input/internal/selection/TextFieldSelectionState.linux.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.foundation.text.input.internal.selection + +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.text.TextDragObserver +import androidx.compose.foundation.text.selection.MouseSelectionObserver +import androidx.compose.ui.Modifier +import androidx.compose.ui.input.pointer.PointerInputScope +import androidx.compose.ui.platform.Clipboard +import kotlinx.coroutines.CoroutineScope + +/** Runs platform-specific text tap gestures logic. */ +internal actual suspend fun TextFieldSelectionState.detectTextFieldTapGestures( + pointerInputScope: PointerInputScope, + interactionSource: MutableInteractionSource?, + requestFocus: () -> Unit, + showKeyboard: () -> Unit, +) = defaultDetectTextFieldTapGestures(pointerInputScope, interactionSource, requestFocus, showKeyboard) + +/** Runs platform-specific text selection gestures logic. */ +internal actual suspend fun TextFieldSelectionState.textFieldSelectionGestures( + pointerInputScope: PointerInputScope, + mouseSelectionObserver: MouseSelectionObserver, + textDragObserver: TextDragObserver +) = pointerInputScope.defaultTextFieldSelectionGestures(mouseSelectionObserver, textDragObserver) + +internal actual fun Modifier.addBasicTextFieldTextContextMenuComponents( + state: TextFieldSelectionState, + coroutineScope: CoroutineScope +): Modifier = this + +internal actual class ClipboardPasteState actual constructor(private val clipboard: Clipboard) { + actual val hasText = false + actual val hasClip = false + actual suspend fun update() {} +} diff --git a/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/modifiers/SelectionController.linux.kt b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/modifiers/SelectionController.linux.kt new file mode 100644 index 0000000000000..8126304b06842 --- /dev/null +++ b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/modifiers/SelectionController.linux.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.foundation.text.modifiers + +import androidx.compose.foundation.text.selection.SelectionRegistrar +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.LayoutCoordinates + +internal actual fun SelectionRegistrar.makeSelectionModifier( + selectableId: Long, + layoutCoordinates: () -> LayoutCoordinates? +): Modifier = makeDefaultSelectionModifier(selectableId, layoutCoordinates) \ No newline at end of file diff --git a/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/selection/DefaultTextSelectionColors.linux.kt b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/selection/DefaultTextSelectionColors.linux.kt new file mode 100644 index 0000000000000..5e7dddbd66437 --- /dev/null +++ b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/selection/DefaultTextSelectionColors.linux.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.foundation.text.selection + +import androidx.compose.runtime.Stable +import androidx.compose.ui.graphics.Color + +private val DefaultSelectionColor = Color(0xFF4286F4) + +@Stable +internal actual val DefaultTextSelectionColors = TextSelectionColors( + handleColor = DefaultSelectionColor, + backgroundColor = DefaultSelectionColor.copy(alpha = 0.4f) +) diff --git a/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.linux.kt b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.linux.kt new file mode 100644 index 0000000000000..6783cf888a6e3 --- /dev/null +++ b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.linux.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.foundation.text.selection + +import androidx.compose.foundation.text.MappedKeys +import androidx.compose.ui.Modifier +import androidx.compose.ui.input.key.KeyEvent +import androidx.compose.ui.input.key.isCtrlPressed +import androidx.compose.ui.input.key.isMetaPressed +import androidx.compose.ui.input.key.key + +// this doesn't sounds very sustainable +// it would end up being a function for any conceptual keyevent (selectall, cut, copy, paste) +// TODO(b/1564937) +internal actual fun isCopyKeyEvent(keyEvent: KeyEvent): Boolean = + keyEvent.key == MappedKeys.C && keyEvent.isCtrlPressed || keyEvent.key == MappedKeys.Copy + +/** + * Magnification is not supported on desktop. + */ +internal actual fun Modifier.selectionMagnifier(manager: SelectionManager): Modifier = this + +// TODO https://youtrack.jetbrains.com/issue/CMP-7819 +internal actual fun Modifier.addSelectionContainerTextContextMenuComponents( + selectionManager: SelectionManager +): Modifier = this diff --git a/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/selection/TextFieldSelectionManager.linux.kt b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/selection/TextFieldSelectionManager.linux.kt new file mode 100644 index 0000000000000..0a274ebc14563 --- /dev/null +++ b/compose/foundation/foundation/src/linuxMain/kotlin/androidx/compose/foundation/text/selection/TextFieldSelectionManager.linux.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.foundation.text.selection + +import androidx.compose.ui.Modifier +import kotlinx.coroutines.CoroutineScope + +/** + * Magnification is not supported on desktop. + */ +internal actual fun Modifier.textFieldMagnifier(manager: TextFieldSelectionManager): Modifier = this + +/** + * Whether the selection handle is in the visible bound of the TextField. + */ +internal actual fun TextFieldSelectionManager.isSelectionHandleInVisibleBound( + isStartHandle: Boolean +): Boolean = isSelectionHandleInVisibleBoundDefault(isStartHandle) + +// TODO: https://youtrack.jetbrains.com/issue/CMP-7819 +internal actual fun Modifier.addBasicTextFieldTextContextMenuComponents( + manager: TextFieldSelectionManager, + coroutineScope: CoroutineScope, +): Modifier = this diff --git a/compose/material/material-navigation/build.gradle b/compose/material/material-navigation/build.gradle index 00ac30724a2a9..f830756583af2 100644 --- a/compose/material/material-navigation/build.gradle +++ b/compose/material/material-navigation/build.gradle @@ -35,22 +35,16 @@ androidXComposeMultiplatform { darwin() js() wasm() + linux() } kotlin { sourceSets { commonMain { dependencies { - implementation("org.jetbrains.androidx.navigation:navigation-compose:2.9.0-rc01") + implementation(project(":navigation:navigation-compose")) implementation(project(":compose:material:material")) implementation(libs.kotlinStdlib) - - // Align navigation dependencies with Compose ones - // https://youtrack.jetbrains.com/issue/CMP-8704 workaround - implementation(project(":lifecycle:lifecycle-runtime-compose")) - implementation(project(":lifecycle:lifecycle-viewmodel-compose")) - implementation(project(":lifecycle:lifecycle-viewmodel-savedstate")) - implementation(project(":savedstate:savedstate-compose")) } } diff --git a/compose/material/material-ripple/build.gradle b/compose/material/material-ripple/build.gradle index 9f1901aed1b32..5dd30178edd47 100644 --- a/compose/material/material-ripple/build.gradle +++ b/compose/material/material-ripple/build.gradle @@ -62,6 +62,7 @@ if(AndroidXComposePlugin.isMultiplatformEnabled(project)) { darwin() js() wasm() + linux() } kotlin { diff --git a/compose/material/material/build.gradle b/compose/material/material/build.gradle index 354102855b8ab..ef90f575b5c85 100644 --- a/compose/material/material/build.gradle +++ b/compose/material/material/build.gradle @@ -86,6 +86,7 @@ if(AndroidXComposePlugin.isMultiplatformEnabled(project)) { darwin() js() wasm() + linux() } kotlin { diff --git a/compose/material3/adaptive/adaptive-layout/build.gradle b/compose/material3/adaptive/adaptive-layout/build.gradle index ce4844b15522b..eeea321875b53 100644 --- a/compose/material3/adaptive/adaptive-layout/build.gradle +++ b/compose/material3/adaptive/adaptive-layout/build.gradle @@ -44,6 +44,7 @@ androidXComposeMultiplatform { darwin() wasm() js() + linux() } kotlin { diff --git a/compose/material3/adaptive/adaptive-navigation/build.gradle b/compose/material3/adaptive/adaptive-navigation/build.gradle index 88de752ac6d38..608b017eaa80c 100644 --- a/compose/material3/adaptive/adaptive-navigation/build.gradle +++ b/compose/material3/adaptive/adaptive-navigation/build.gradle @@ -43,6 +43,7 @@ androidXComposeMultiplatform { darwin() wasm() js() + linux() } kotlin { diff --git a/compose/material3/adaptive/adaptive/build.gradle b/compose/material3/adaptive/adaptive/build.gradle index b160d05d2da16..484a66c055f16 100644 --- a/compose/material3/adaptive/adaptive/build.gradle +++ b/compose/material3/adaptive/adaptive/build.gradle @@ -43,6 +43,7 @@ androidXComposeMultiplatform { darwin() wasm() js() + linux() } kotlin { diff --git a/compose/material3/material3-adaptive-navigation-suite/build.gradle b/compose/material3/material3-adaptive-navigation-suite/build.gradle index 3a86ff6e364b6..d1b37c7ce3713 100644 --- a/compose/material3/material3-adaptive-navigation-suite/build.gradle +++ b/compose/material3/material3-adaptive-navigation-suite/build.gradle @@ -42,6 +42,7 @@ androidXComposeMultiplatform { darwin() wasm() js() + linux() } kotlin { diff --git a/compose/material3/material3-window-size-class/build.gradle b/compose/material3/material3-window-size-class/build.gradle index 6a496b6d18824..8466ce4233a5a 100644 --- a/compose/material3/material3-window-size-class/build.gradle +++ b/compose/material3/material3-window-size-class/build.gradle @@ -34,6 +34,7 @@ androidXComposeMultiplatform { darwin() wasm() js() + linux() } kotlin { diff --git a/compose/material3/material3/build.gradle b/compose/material3/material3/build.gradle index fa9f1e631ccea..da776767c9b94 100644 --- a/compose/material3/material3/build.gradle +++ b/compose/material3/material3/build.gradle @@ -88,6 +88,7 @@ if(AndroidXComposePlugin.isMultiplatformEnabled(project)) { darwin() wasm() js() + linux() } kotlin { diff --git a/compose/material3/material3/src/linuxMain/kotlin/androidx/compose/material3/CalendarLocale.linux.kt b/compose/material3/material3/src/linuxMain/kotlin/androidx/compose/material3/CalendarLocale.linux.kt new file mode 100644 index 0000000000000..4bfce9ff11f05 --- /dev/null +++ b/compose/material3/material3/src/linuxMain/kotlin/androidx/compose/material3/CalendarLocale.linux.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.material3 + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.ReadOnlyComposable + + +actual typealias CalendarLocale = Any // TODO + +@Composable +@ReadOnlyComposable +internal actual fun defaultLocale(): CalendarLocale = TODO("not implemented") diff --git a/compose/material3/material3/src/linuxMain/kotlin/androidx/compose/material3/internal/PlatformDateFormat.linux.kt b/compose/material3/material3/src/linuxMain/kotlin/androidx/compose/material3/internal/PlatformDateFormat.linux.kt new file mode 100644 index 0000000000000..839113f8748e7 --- /dev/null +++ b/compose/material3/material3/src/linuxMain/kotlin/androidx/compose/material3/internal/PlatformDateFormat.linux.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.material3.internal + +import androidx.compose.material3.CalendarLocale + +internal actual class PlatformDateFormat actual constructor(private val locale: CalendarLocale) { + + actual val firstDayOfWeek: Int + get() = TODO("not implemented") + + actual fun formatWithPattern( + utcTimeMillis: Long, + pattern: String, + cache: MutableMap + ): String { + TODO("not implemented") + } + + actual fun formatWithSkeleton( + utcTimeMillis: Long, + skeleton: String, + cache: MutableMap + ): String { + TODO("not implemented") + } + + actual fun parse( + date: String, + pattern: String, + locale: CalendarLocale, + cache: MutableMap + ): CalendarDate? { + TODO("not implemented") + } + + actual fun getDateInputFormat(): DateInputFormat { + TODO("not implemented") + } + + actual val weekdayNames: List> get() { + TODO("not implemented") + } + + actual fun is24HourFormat(): Boolean { + TODO("not implemented") + } +} diff --git a/compose/ui/ui-backhandler/build.gradle b/compose/ui/ui-backhandler/build.gradle index a04f0823c3f0b..51e0769d3afde 100644 --- a/compose/ui/ui-backhandler/build.gradle +++ b/compose/ui/ui-backhandler/build.gradle @@ -35,6 +35,7 @@ androidXComposeMultiplatform { darwin() js() wasm() + linux() } kotlin { diff --git a/compose/ui/ui-geometry/build.gradle b/compose/ui/ui-geometry/build.gradle index f1f87e8eb97b4..704d04c0ffc2e 100644 --- a/compose/ui/ui-geometry/build.gradle +++ b/compose/ui/ui-geometry/build.gradle @@ -54,6 +54,7 @@ if(AndroidXComposePlugin.isMultiplatformEnabled(project)) { darwin() js() wasm() + linux() } kotlin { diff --git a/compose/ui/ui-graphics/build.gradle b/compose/ui/ui-graphics/build.gradle index 969dee918912a..03ba61b73cbba 100644 --- a/compose/ui/ui-graphics/build.gradle +++ b/compose/ui/ui-graphics/build.gradle @@ -70,6 +70,7 @@ if(AndroidXComposePlugin.isMultiplatformEnabled(project)) { js() wasm() darwin() + linux() configureDarwinFlags() } diff --git a/compose/ui/ui-test-junit4/build.gradle b/compose/ui/ui-test-junit4/build.gradle index f54f01fa55128..1c76c677ece30 100644 --- a/compose/ui/ui-test-junit4/build.gradle +++ b/compose/ui/ui-test-junit4/build.gradle @@ -84,6 +84,7 @@ if(AndroidXComposePlugin.isMultiplatformEnabled(project)) { darwin() js() wasm() + linux() configureDarwinFlags() } diff --git a/compose/ui/ui-test/build.gradle b/compose/ui/ui-test/build.gradle index dad7ab2d4ac4b..6d653f6295086 100644 --- a/compose/ui/ui-test/build.gradle +++ b/compose/ui/ui-test/build.gradle @@ -89,6 +89,7 @@ if (AndroidXComposePlugin.isMultiplatformEnabled(project)) { darwin() js() wasm() + linux() } kotlin { diff --git a/compose/ui/ui-test/src/linuxMain/kotlin/androidx/compose/ui/test/Actions.linuxMain.kt b/compose/ui/ui-test/src/linuxMain/kotlin/androidx/compose/ui/test/Actions.linuxMain.kt new file mode 100644 index 0000000000000..b0b58fbbedb1a --- /dev/null +++ b/compose/ui/ui-test/src/linuxMain/kotlin/androidx/compose/ui/test/Actions.linuxMain.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.ui.test + +@OptIn(ExperimentalTestApi::class) +internal actual fun SemanticsNodeInteraction.performClickImpl(): SemanticsNodeInteraction { + return performMouseInput { + click() + } +} diff --git a/compose/ui/ui-test/src/linuxMain/kotlin/androidx/compose/ui/test/Synchronization.linuxMain.kt b/compose/ui/ui-test/src/linuxMain/kotlin/androidx/compose/ui/test/Synchronization.linuxMain.kt new file mode 100644 index 0000000000000..0f647a496ec1c --- /dev/null +++ b/compose/ui/ui-test/src/linuxMain/kotlin/androidx/compose/ui/test/Synchronization.linuxMain.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.ui.test + +import androidx.compose.ui.platform.ComposeUiMainDispatcher +import kotlinx.cinterop.ExperimentalForeignApi +import kotlinx.cinterop.cValue +import kotlinx.coroutines.runBlocking +import platform.posix.nanosleep +import platform.posix.timespec + +/** + * Runs the given action on the UI thread. + * + * This method is blocking until the action is complete. + */ +internal actual fun runOnUiThread(action: () -> T): T { + return if (isOnUiThread()) { + action() + } else { + runBlocking(ComposeUiMainDispatcher) { + action() + } + } +} + +/** + * Returns if the call is made on the main thread. + */ +internal actual fun isOnUiThread(): Boolean = false // TODO + +/** + * Blocks the calling thread for [timeMillis] milliseconds. + */ +@OptIn(ExperimentalForeignApi::class) +internal actual fun sleep(timeMillis: Long) { + val time = cValue { + tv_sec = timeMillis / 1000 + tv_nsec = timeMillis.mod(1000L) * NanoSecondsPerMilliSecond + } + + nanosleep(time, null) +} diff --git a/compose/ui/ui-text/build.gradle b/compose/ui/ui-text/build.gradle index e83c7f7df4102..ed3155d2a826f 100644 --- a/compose/ui/ui-text/build.gradle +++ b/compose/ui/ui-text/build.gradle @@ -93,6 +93,7 @@ if(AndroidXComposePlugin.isMultiplatformEnabled(project)) { darwin() js() wasm() + linux() } kotlin { diff --git a/compose/ui/ui-text/src/linuxMain/kotlin/androidx/compose/ui/text/font/FontFamilyResolver.skiko.linux.kt b/compose/ui/ui-text/src/linuxMain/kotlin/androidx/compose/ui/text/font/FontFamilyResolver.skiko.linux.kt new file mode 100644 index 0000000000000..9942cbdc63caf --- /dev/null +++ b/compose/ui/ui-text/src/linuxMain/kotlin/androidx/compose/ui/text/font/FontFamilyResolver.skiko.linux.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.ui.text.font + +internal actual fun createPlatformResolveInterceptor(): PlatformResolveInterceptor = + PlatformResolveInterceptor.Default diff --git a/compose/ui/ui-text/src/linuxMain/kotlin/androidx/compose/ui/text/intl/NativePlatformLocale.linux.kt b/compose/ui/ui-text/src/linuxMain/kotlin/androidx/compose/ui/text/intl/NativePlatformLocale.linux.kt new file mode 100644 index 0000000000000..b2c7b28035f74 --- /dev/null +++ b/compose/ui/ui-text/src/linuxMain/kotlin/androidx/compose/ui/text/intl/NativePlatformLocale.linux.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.ui.text.intl + +actual class PlatformLocale { } + +internal actual val PlatformLocale.language: String + get() = "en" + +internal actual val PlatformLocale.script: String + get() = "" + +internal actual val PlatformLocale.region: String + get() = "US" + +internal actual fun PlatformLocale.getLanguageTag(): String = "en-US" + +internal actual fun createPlatformLocaleDelegate(): PlatformLocaleDelegate = + object : PlatformLocaleDelegate { + override val current get() = LocaleList(listOf(Locale(PlatformLocale()))) + override fun parseLanguageTag(languageTag: String) = PlatformLocale() + } + +internal actual fun PlatformLocale.isRtl(): Boolean = false diff --git a/compose/ui/ui-text/src/linuxMain/kotlin/androidx/compose/ui/text/platform/NativeStringDelegate.linux.kt b/compose/ui/ui-text/src/linuxMain/kotlin/androidx/compose/ui/text/platform/NativeStringDelegate.linux.kt new file mode 100644 index 0000000000000..2b026713d1a53 --- /dev/null +++ b/compose/ui/ui-text/src/linuxMain/kotlin/androidx/compose/ui/text/platform/NativeStringDelegate.linux.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.ui.text.platform + +import androidx.compose.ui.text.PlatformStringDelegate +import androidx.compose.ui.text.intl.PlatformLocale + +internal object NativeStringDelegate : PlatformStringDelegate { + override fun toUpperCase(string: String, locale: PlatformLocale) = string.uppercase() + override fun toLowerCase(string: String, locale: PlatformLocale) = string.lowercase() + override fun capitalize(string: String, locale: PlatformLocale) = string.capitalize() + override fun decapitalize(string: String, locale: PlatformLocale) = string.decapitalize() +} + +internal actual fun ActualStringDelegate(): PlatformStringDelegate = + NativeStringDelegate diff --git a/compose/ui/ui-tooling-preview/build.gradle b/compose/ui/ui-tooling-preview/build.gradle index 90645432a93e1..56f1c53edb35e 100644 --- a/compose/ui/ui-tooling-preview/build.gradle +++ b/compose/ui/ui-tooling-preview/build.gradle @@ -34,6 +34,7 @@ androidXComposeMultiplatform { darwin() js() wasm() + linux() } kotlin { @@ -107,6 +108,10 @@ kotlin { dependsOn(jvmTest) dependsOn(desktopMain) } + + linuxMain { + dependsOn(nonJvmMain) + } } } diff --git a/compose/ui/ui-unit/build.gradle b/compose/ui/ui-unit/build.gradle index 0bdcc67d980fa..01dd9a0ee298a 100644 --- a/compose/ui/ui-unit/build.gradle +++ b/compose/ui/ui-unit/build.gradle @@ -63,6 +63,7 @@ if(AndroidXComposePlugin.isMultiplatformEnabled(project)) { darwin() js() wasm() + linux() } kotlin { diff --git a/compose/ui/ui-util/build.gradle b/compose/ui/ui-util/build.gradle index eb670411d0dbf..9522b07923cb3 100644 --- a/compose/ui/ui-util/build.gradle +++ b/compose/ui/ui-util/build.gradle @@ -50,6 +50,7 @@ if(AndroidXComposePlugin.isMultiplatformEnabled(project)) { darwin() js() wasm() + linux() } kotlin { diff --git a/compose/ui/ui-util/src/linuxMain/kotlin/androidx/compose/ui/util/Trace.linux.kt b/compose/ui/ui-util/src/linuxMain/kotlin/androidx/compose/ui/util/Trace.linux.kt new file mode 100644 index 0000000000000..9c7fb1d8f9ec0 --- /dev/null +++ b/compose/ui/ui-util/src/linuxMain/kotlin/androidx/compose/ui/util/Trace.linux.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.ui.util + +actual inline fun trace(sectionName: String, block: () -> T): T { + return block() +} + +actual fun traceValue(tag: String, value: Long) { +} diff --git a/compose/ui/ui/build.gradle b/compose/ui/ui/build.gradle index 79b928517190a..7653e08ff99de 100644 --- a/compose/ui/ui/build.gradle +++ b/compose/ui/ui/build.gradle @@ -145,6 +145,7 @@ if(AndroidXComposePlugin.isMultiplatformEnabled(project)) { darwin() js() wasm() + linux() iosInstrumentedTest() configureDarwinFlags() @@ -240,6 +241,7 @@ if(AndroidXComposePlugin.isMultiplatformEnabled(project)) { webMain.dependsOn(nonJvmMain) webMain.dependsOn(skikoMain) macosMain.dependsOn(skikoMain) + linuxMain.dependsOn(skikoMain) jsMain { kotlin.srcDir("src/webCommonW3C/kotlin") diff --git a/compose/ui/ui/src/darwinMain/kotlin/androidx/compose/ui/Actuals.darwin.kt b/compose/ui/ui/src/darwinMain/kotlin/androidx/compose/ui/Actuals.darwin.kt new file mode 100644 index 0000000000000..fe357aa296cb2 --- /dev/null +++ b/compose/ui/ui/src/darwinMain/kotlin/androidx/compose/ui/Actuals.darwin.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.ui + +import kotlin.coroutines.CoroutineContext +import kotlinx.coroutines.Dispatchers + +internal actual val PostDelayedDispatcher: CoroutineContext + get() = Dispatchers.Main diff --git a/compose/ui/ui/src/nativeMain/kotlin/androidx/compose/ui/platform/GlobalSnapshotManager.native.kt b/compose/ui/ui/src/darwinMain/kotlin/androidx/compose/ui/platform/GlobalSnapshotManager.darwin.kt similarity index 100% rename from compose/ui/ui/src/nativeMain/kotlin/androidx/compose/ui/platform/GlobalSnapshotManager.native.kt rename to compose/ui/ui/src/darwinMain/kotlin/androidx/compose/ui/platform/GlobalSnapshotManager.darwin.kt diff --git a/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/Actuals.linux.kt b/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/Actuals.linux.kt new file mode 100644 index 0000000000000..ac9bede2986c2 --- /dev/null +++ b/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/Actuals.linux.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.ui + +import androidx.compose.ui.platform.ComposeUiMainDispatcher +import kotlin.coroutines.CoroutineContext + +internal actual val PostDelayedDispatcher: CoroutineContext + get() = ComposeUiMainDispatcher diff --git a/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/draganddrop/DragAndDrop.linux.kt b/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/draganddrop/DragAndDrop.linux.kt new file mode 100644 index 0000000000000..507b000555cb1 --- /dev/null +++ b/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/draganddrop/DragAndDrop.linux.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.ui.draganddrop + +import androidx.compose.ui.geometry.Offset + +/** + * A representation of an event sent by the platform during a drag and drop operation. + */ +actual class DragAndDropEvent + +/** + * Returns the position of this [DragAndDropEvent] relative to the root Compose View in the + * layout hierarchy. + */ +internal actual val DragAndDropEvent.positionInRoot: Offset + get() = TODO("Not yet implemented") + +/** + * Definition for a type representing transferable data. It could be a remote URI, + * rich text data on the clip board, a local file, or more. + */ +actual class DragAndDropTransferData \ No newline at end of file diff --git a/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/focus/Focusability.linux.kt b/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/focus/Focusability.linux.kt new file mode 100644 index 0000000000000..84f683f753fdc --- /dev/null +++ b/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/focus/Focusability.linux.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.ui.focus + +import androidx.compose.ui.node.CompositionLocalConsumerModifierNode + +internal actual fun systemDefinedCanFocus(node: CompositionLocalConsumerModifierNode) = + mobilePlatformSystemDefinedCanFocus(node) \ No newline at end of file diff --git a/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/input/key/Key.linux.kt b/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/input/key/Key.linux.kt new file mode 100644 index 0000000000000..6ce34cf8ab959 --- /dev/null +++ b/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/input/key/Key.linux.kt @@ -0,0 +1,559 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.ui.input.key + +import androidx.compose.ui.input.key.Key.Companion.Number + +/** + * Actual implementation of [Key] for JS and Native. + * + * @param keyCode an integer code representing the key pressed. Note: This keycode can be used to + * uniquely identify a hardware key. + */ +actual value class Key(val keyCode: Long) { + actual companion object { + /** Unknown key. */ + actual val Unknown = Key(-1) + + /** + * Home key. + * + * This key is handled by the framework and is never delivered to applications. + */ + actual val Home = Key(115) + + /** + * Up Arrow Key / Directional Pad Up key. + * + * May also be synthesized from trackball motions. + */ + actual val DirectionUp = Key(126) + + /** + * Down Arrow Key / Directional Pad Down key. + * + * May also be synthesized from trackball motions. + */ + actual val DirectionDown = Key(125) + + /** + * Left Arrow Key / Directional Pad Left key. + * + * May also be synthesized from trackball motions. + */ + actual val DirectionLeft = Key(123) + + /** + * Right Arrow Key / Directional Pad Right key. + * + * May also be synthesized from trackball motions. + */ + actual val DirectionRight = Key(124) + + /** '0' key. */ + actual val Zero = Key(29) + + /** '1' key. */ + actual val One = Key(18) + + /** '2' key. */ + actual val Two = Key(19) + + /** '3' key. */ + actual val Three = Key(20) + + /** '4' key. */ + actual val Four = Key(21) + + /** '5' key. */ + actual val Five = Key(23) + + /** '6' key. */ + actual val Six = Key(22) + + /** '7' key. */ + actual val Seven = Key(26) + + /** '8' key. */ + actual val Eight = Key(28) + + /** '9' key. */ + actual val Nine = Key(25) + + /** '-' key. */ + actual val Minus = Key(27) + + /** '=' key. */ + actual val Equals = Key(24) + + /** 'A' key. */ + actual val A = Key(0) + + /** 'B' key. */ + actual val B = Key(11) + + /** 'C' key. */ + actual val C = Key(8) + + /** 'D' key. */ + actual val D = Key(2) + + /** 'E' key. */ + actual val E = Key(14) + + /** 'F' key. */ + actual val F = Key(3) + + /** 'G' key. */ + actual val G = Key(5) + + /** 'H' key. */ + actual val H = Key(4) + + /** 'I' key. */ + actual val I = Key(34) + + /** 'J' key. */ + actual val J = Key(38) + + /** 'K' key. */ + actual val K = Key(40) + + /** 'L' key. */ + actual val L = Key(37) + + /** 'M' key. */ + actual val M = Key(46) + + /** 'N' key. */ + actual val N = Key(45) + + /** 'O' key. */ + actual val O = Key(31) + + /** 'P' key. */ + actual val P = Key(35) + + /** 'Q' key. */ + actual val Q = Key(12) + + /** 'R' key. */ + actual val R = Key(15) + + /** 'S' key. */ + actual val S = Key(1) + + /** 'T' key. */ + actual val T = Key(17) + + /** 'U' key. */ + actual val U = Key(32) + + /** 'V' key. */ + actual val V = Key(9) + + /** 'W' key. */ + actual val W = Key(13) + + /** 'X' key. */ + actual val X = Key(7) + + /** 'Y' key. */ + actual val Y = Key(16) + + /** 'Z' key. */ + actual val Z = Key(6) + + /** ',' key. */ + actual val Comma = Key(43) + + /** '.' key. */ + actual val Period = Key(47) + + /** Left Alt modifier key. */ + actual val AltLeft = Key(58) + + /** Right Alt modifier key. */ + actual val AltRight = Key(61) + + /** Left Shift modifier key. */ + actual val ShiftLeft = Key(56) + + /** Right Shift modifier key. */ + actual val ShiftRight = Key(60) + + /** Tab key. */ + actual val Tab = Key(48) + + /** Space key. */ + actual val Spacebar = Key(49) + + /** Enter key. */ + actual val Enter = Key(36) + + /** + * Backspace key. + * + * Deletes characters before the insertion point, unlike [Delete]. + */ + actual val Backspace = Key(51) + + /** + * Delete key. + * + * Deletes characters ahead of the insertion point, unlike [Backspace]. + */ + actual val Delete = Key(117) + + /** Escape key. */ + actual val Escape = Key(53) + + /** Left Control modifier key. */ + actual val CtrlLeft = Key(59) + + /** Right Control modifier key. */ + actual val CtrlRight = Key(62) + + /** Caps Lock key. */ + actual val CapsLock = Key(57) + + /** Scroll Lock key. */ + actual val ScrollLock = Key(107) + + /** Left Meta modifier key. */ + actual val MetaLeft = Key(55) + + /** Right Meta modifier key. */ + actual val MetaRight = Key(54) + + /** System Request / Print Screen key. */ + actual val PrintScreen = Key(105) + + /** + * Insert key. + * + * Toggles insert / overwrite edit mode. + */ + actual val Insert = Key(114) + + /** '`' (backtick) key. */ + actual val Grave = Key(50) + + /** '[' key. */ + actual val LeftBracket = Key(33) + + /** ']' key. */ + actual val RightBracket = Key(30) + + /** '/' key. */ + actual val Slash = Key(42) + + /** '\' key. */ + actual val Backslash = Key(44) + + /** ';' key. */ + actual val Semicolon = Key(41) + + /** Page Up key. */ + actual val PageUp = Key(116) + + /** Page Down key. */ + actual val PageDown = Key(121) + + /** F1 key. */ + actual val F1 = Key(122) + + /** F2 key. */ + actual val F2 = Key(120) + + /** F3 key. */ + actual val F3 = Key(99) + + /** F4 key. */ + actual val F4 = Key(118) + + /** F5 key. */ + actual val F5 = Key(96) + + /** F6 key. */ + actual val F6 = Key(97) + + /** F7 key. */ + actual val F7 = Key(98) + + /** F8 key. */ + actual val F8 = Key(100) + + /** F9 key. */ + actual val F9 = Key(101) + + /** F10 key. */ + actual val F10 = Key(109) + + /** F11 key. */ + actual val F11 = Key(103) + + /** F12 key. */ + actual val F12 = Key(111) + + /** + * Num Lock key. + * + * This is the Num Lock key; it is different from [Number]. + * This key alters the behavior of other keys on the numeric keypad. + */ + actual val NumLock = Key(71) + + /** Numeric keypad '0' key. */ + actual val NumPad0 = Key(82) + + /** Numeric keypad '1' key. */ + actual val NumPad1 = Key(83) + + /** Numeric keypad '2' key. */ + actual val NumPad2 = Key(84) + + /** Numeric keypad '3' key. */ + actual val NumPad3 = Key(85) + + /** Numeric keypad '4' key. */ + actual val NumPad4 = Key(86) + + /** Numeric keypad '5' key. */ + actual val NumPad5 = Key(87) + + /** Numeric keypad '6' key. */ + actual val NumPad6 = Key(88) + + /** Numeric keypad '7' key. */ + actual val NumPad7 = Key(89) + + /** Numeric keypad '8' key. */ + actual val NumPad8 = Key(91) + + /** Numeric keypad '9' key. */ + actual val NumPad9 = Key(92) + + /** Numeric keypad '/' key (for division). */ + actual val NumPadDivide = Key(75) + + /** Numeric keypad '*' key (for multiplication). */ + actual val NumPadMultiply = Key(67) + + /** Numeric keypad '-' key (for subtraction). */ + actual val NumPadSubtract = Key(78) + + /** Numeric keypad '+' key (for addition). */ + actual val NumPadAdd = Key(69) + + /** Numeric keypad Enter key. */ + actual val NumPadEnter = Key(76) + + actual val MoveHome = Key(115) + + actual val MoveEnd = Key(119) + + // Unsupported Keys + actual val SoftLeft = Key(-1000000001) + actual val SoftRight = Key(-1000000002) + actual val Back = Key(-1000000003) + actual val NavigatePrevious = Key(-1000000004) + actual val NavigateNext = Key(-1000000005) + actual val NavigateIn = Key(-1000000006) + actual val NavigateOut = Key(-1000000007) + actual val SystemNavigationUp = Key(-1000000008) + actual val SystemNavigationDown = Key(-1000000009) + actual val SystemNavigationLeft = Key(-1000000010) + actual val SystemNavigationRight = Key(-1000000011) + actual val Call = Key(-1000000012) + actual val EndCall = Key(-1000000013) + actual val DirectionCenter = Key(-1000000014) + actual val DirectionUpLeft = Key(-1000000015) + actual val DirectionDownLeft = Key(-1000000016) + actual val DirectionUpRight = Key(-1000000017) + actual val DirectionDownRight = Key(-1000000018) + actual val VolumeUp = Key(-1000000019) + actual val VolumeDown = Key(-1000000020) + actual val Power = Key(-1000000021) + actual val Camera = Key(-1000000022) + actual val Clear = Key(-1000000023) + actual val Symbol = Key(-1000000024) + actual val Browser = Key(-1000000025) + actual val Envelope = Key(-1000000026) + actual val Function = Key(-1000000027) + actual val Break = Key(-1000000028) + actual val Number = Key(-1000000031) + actual val HeadsetHook = Key(-1000000032) + actual val Focus = Key(-1000000033) + actual val Menu = Key(-1000000034) + actual val Notification = Key(-1000000035) + actual val Search = Key(-1000000036) + actual val PictureSymbols = Key(-1000000037) + actual val SwitchCharset = Key(-1000000038) + actual val ButtonA = Key(-1000000039) + actual val ButtonB = Key(-1000000040) + actual val ButtonC = Key(-1000000041) + actual val ButtonX = Key(-1000000042) + actual val ButtonY = Key(-1000000043) + actual val ButtonZ = Key(-1000000044) + actual val ButtonL1 = Key(-1000000045) + actual val ButtonR1 = Key(-1000000046) + actual val ButtonL2 = Key(-1000000047) + actual val ButtonR2 = Key(-1000000048) + actual val ButtonThumbLeft = Key(-1000000049) + actual val ButtonThumbRight = Key(-1000000050) + actual val ButtonStart = Key(-1000000051) + actual val ButtonSelect = Key(-1000000052) + actual val ButtonMode = Key(-1000000053) + actual val Button1 = Key(-1000000054) + actual val Button2 = Key(-1000000055) + actual val Button3 = Key(-1000000056) + actual val Button4 = Key(-1000000057) + actual val Button5 = Key(-1000000058) + actual val Button6 = Key(-1000000059) + actual val Button7 = Key(-1000000060) + actual val Button8 = Key(-1000000061) + actual val Button9 = Key(-1000000062) + actual val Button10 = Key(-1000000063) + actual val Button11 = Key(-1000000064) + actual val Button12 = Key(-1000000065) + actual val Button13 = Key(-1000000066) + actual val Button14 = Key(-1000000067) + actual val Button15 = Key(-1000000068) + actual val Button16 = Key(-1000000069) + actual val Forward = Key(-1000000070) + actual val MediaPlay = Key(-1000000071) + actual val MediaPause = Key(-1000000072) + actual val MediaPlayPause = Key(-1000000073) + actual val MediaStop = Key(-1000000074) + actual val MediaRecord = Key(-1000000075) + actual val MediaNext = Key(-1000000076) + actual val MediaPrevious = Key(-1000000077) + actual val MediaRewind = Key(-1000000078) + actual val MediaFastForward = Key(-1000000079) + actual val MediaClose = Key(-1000000080) + actual val MediaAudioTrack = Key(-1000000081) + actual val MediaEject = Key(-1000000082) + actual val MediaTopMenu = Key(-1000000083) + actual val MediaSkipForward = Key(-1000000084) + actual val MediaSkipBackward = Key(-1000000085) + actual val MediaStepForward = Key(-1000000086) + actual val MediaStepBackward = Key(-1000000087) + actual val MicrophoneMute = Key(-1000000088) + actual val VolumeMute = Key(-1000000089) + actual val Info = Key(-1000000090) + actual val ChannelUp = Key(-1000000091) + actual val ChannelDown = Key(-1000000092) + actual val ZoomIn = Key(-1000000093) + actual val ZoomOut = Key(-1000000094) + actual val Tv = Key(-1000000095) + actual val Window = Key(-1000000096) + actual val Guide = Key(-1000000097) + actual val Dvr = Key(-1000000098) + actual val Bookmark = Key(-1000000099) + actual val Captions = Key(-1000000100) + actual val Settings = Key(-1000000101) + actual val TvPower = Key(-1000000102) + actual val TvInput = Key(-1000000103) + actual val SetTopBoxPower = Key(-1000000104) + actual val SetTopBoxInput = Key(-1000000105) + actual val AvReceiverPower = Key(-1000000106) + actual val AvReceiverInput = Key(-1000000107) + actual val ProgramRed = Key(-1000000108) + actual val ProgramGreen = Key(-1000000109) + actual val ProgramYellow = Key(-1000000110) + actual val ProgramBlue = Key(-1000000111) + actual val AppSwitch = Key(-1000000112) + actual val LanguageSwitch = Key(-1000000113) + actual val MannerMode = Key(-1000000114) + actual val Toggle2D3D = Key(-1000000125) + actual val Contacts = Key(-1000000126) + actual val Calendar = Key(-1000000127) + actual val Music = Key(-1000000128) + actual val Calculator = Key(-1000000129) + actual val ZenkakuHankaru = Key(-1000000130) + actual val Eisu = Key(-1000000131) + actual val Muhenkan = Key(-1000000132) + actual val Henkan = Key(-1000000133) + actual val KatakanaHiragana = Key(-1000000134) + actual val Yen = Key(-1000000135) + actual val Ro = Key(-1000000136) + actual val Kana = Key(-1000000137) + actual val Assist = Key(-1000000138) + actual val BrightnessDown = Key(-1000000139) + actual val BrightnessUp = Key(-1000000140) + actual val Sleep = Key(-1000000141) + actual val WakeUp = Key(-1000000142) + actual val SoftSleep = Key(-1000000143) + actual val Pairing = Key(-1000000144) + actual val LastChannel = Key(-1000000145) + actual val TvDataService = Key(-1000000146) + actual val VoiceAssist = Key(-1000000147) + actual val TvRadioService = Key(-1000000148) + actual val TvTeletext = Key(-1000000149) + actual val TvNumberEntry = Key(-1000000150) + actual val TvTerrestrialAnalog = Key(-1000000151) + actual val TvTerrestrialDigital = Key(-1000000152) + actual val TvSatellite = Key(-1000000153) + actual val TvSatelliteBs = Key(-1000000154) + actual val TvSatelliteCs = Key(-1000000155) + actual val TvSatelliteService = Key(-1000000156) + actual val TvNetwork = Key(-1000000157) + actual val TvAntennaCable = Key(-1000000158) + actual val TvInputHdmi1 = Key(-1000000159) + actual val TvInputHdmi2 = Key(-1000000160) + actual val TvInputHdmi3 = Key(-1000000161) + actual val TvInputHdmi4 = Key(-1000000162) + actual val TvInputComposite1 = Key(-1000000163) + actual val TvInputComposite2 = Key(-1000000164) + actual val TvInputComponent1 = Key(-1000000165) + actual val TvInputComponent2 = Key(-1000000166) + actual val TvInputVga1 = Key(-1000000167) + actual val TvAudioDescription = Key(-1000000168) + actual val TvAudioDescriptionMixingVolumeUp = Key(-1000000169) + actual val TvAudioDescriptionMixingVolumeDown = Key(-1000000170) + actual val TvZoomMode = Key(-1000000171) + actual val TvContentsMenu = Key(-1000000172) + actual val TvMediaContextMenu = Key(-1000000173) + actual val TvTimerProgramming = Key(-1000000174) + actual val StemPrimary = Key(-1000000175) + actual val Stem1 = Key(-1000000176) + actual val Stem2 = Key(-1000000177) + actual val Stem3 = Key(-1000000178) + actual val AllApps = Key(-1000000179) + actual val Refresh = Key(-1000000180) + actual val ThumbsUp = Key(-1000000181) + actual val ThumbsDown = Key(-1000000182) + actual val ProfileSwitch = Key(-1000000183) + actual val Help = Key(-1000000184) + actual val Plus = Key(-1000000185) + actual val Multiply = Key(-1000000186) + actual val Pound = Key(-1000000187) + actual val Cut = Key(-1000000188) + actual val Copy = Key(-1000000189) + actual val Paste = Key(-1000000190) + actual val Apostrophe = Key(-1000000191) + actual val At = Key(-10000001902) + actual val NumPadDot = Key(-1000000193) + actual val NumPadComma = Key(-1000000194) + actual val NumPadEquals = Key(-1000000195) + actual val NumPadLeftParenthesis = Key(-1000000196) + actual val NumPadRightParenthesis = Key(-1000000197) + } + + actual override fun toString() = "Key keyCode: $keyCode" +} \ No newline at end of file diff --git a/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/input/pointer/PointerIcon.linux.kt b/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/input/pointer/PointerIcon.linux.kt new file mode 100644 index 0000000000000..5622ee19925e8 --- /dev/null +++ b/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/input/pointer/PointerIcon.linux.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.ui.input.pointer + +internal data class LinuxCursor(val cursor: String): PointerIcon + +internal actual val pointerIconDefault: PointerIcon = LinuxCursor("default") +internal actual val pointerIconCrosshair: PointerIcon = LinuxCursor("crosshair") +internal actual val pointerIconText: PointerIcon = LinuxCursor("text") +internal actual val pointerIconHand: PointerIcon = LinuxCursor("hand") diff --git a/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/input/pointer/util/PlatformVelocityTracker.linux.kt b/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/input/pointer/util/PlatformVelocityTracker.linux.kt new file mode 100644 index 0000000000000..2fe26999454da --- /dev/null +++ b/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/input/pointer/util/PlatformVelocityTracker.linux.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.ui.input.pointer.util + +internal actual fun PlatformVelocityTracker(): PlatformVelocityTracker = DefaultVelocityTracker() diff --git a/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/platform/ComposeUiMainDispatcher.linux.kt b/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/platform/ComposeUiMainDispatcher.linux.kt new file mode 100644 index 0000000000000..e47537db684f1 --- /dev/null +++ b/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/platform/ComposeUiMainDispatcher.linux.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.ui.platform + +import kotlinx.coroutines.CoroutineDispatcher + +lateinit var ComposeUiMainDispatcher: CoroutineDispatcher // TODO: https://github.com/Kotlin/kotlinx.coroutines/issues/4286 diff --git a/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/platform/GlobalSnapshotManager.linux.kt b/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/platform/GlobalSnapshotManager.linux.kt new file mode 100644 index 0000000000000..a6f46e7f0cb7e --- /dev/null +++ b/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/platform/GlobalSnapshotManager.linux.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.ui.platform + +import kotlinx.coroutines.CoroutineDispatcher + +internal actual val GlobalSnapshotManagerDispatcher: CoroutineDispatcher get() = ComposeUiMainDispatcher diff --git a/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/platform/LinuxTextInputService.linux.kt b/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/platform/LinuxTextInputService.linux.kt new file mode 100644 index 0000000000000..013fc0e991488 --- /dev/null +++ b/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/platform/LinuxTextInputService.linux.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.ui.platform + +import androidx.compose.ui.text.input.EditCommand +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.ImeOptions +import androidx.compose.ui.text.input.PlatformTextInputService +import androidx.compose.ui.text.input.TextFieldValue + +internal class LinuxTextInputService : PlatformTextInputService { + + data class CurrentInput( + var value: TextFieldValue, + val onEditCommand: ((List) -> Unit), + ) + + private var currentInput: CurrentInput? = null + + override fun startInput( + value: TextFieldValue, + imeOptions: ImeOptions, + onEditCommand: (List) -> Unit, + onImeActionPerformed: (ImeAction) -> Unit + ) { + currentInput = CurrentInput( + value, + onEditCommand + ) + } + + override fun stopInput() { + currentInput = null + } + + override fun showSoftwareKeyboard() { + //do nothing + } + + override fun hideSoftwareKeyboard() { + //do nothing + } + + override fun updateState(oldValue: TextFieldValue?, newValue: TextFieldValue) { + currentInput?.let { input -> + input.value = newValue + } + } +} diff --git a/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/platform/PlatformClipboard.linux.kt b/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/platform/PlatformClipboard.linux.kt new file mode 100644 index 0000000000000..79f930bbc9825 --- /dev/null +++ b/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/platform/PlatformClipboard.linux.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.ui.platform + +actual typealias NativeClipboard = Any // TODO + +internal class LinuxClipboard : Clipboard { + override suspend fun getClipEntry(): ClipEntry? { + TODO("getClipEntry") + } + + override suspend fun setClipEntry(clipEntry: ClipEntry?) { + TODO("setClipEntry") + } + + override val nativeClipboard: NativeClipboard + get() = TODO("nativeClipboard") +} + +internal actual fun createPlatformClipboard(): Clipboard { + return LinuxClipboard() +} + +actual class ClipEntry internal constructor() { + + // TODO https://youtrack.jetbrains.com/issue/CMP-1260/ClipboardManager.-Implement-getClip-getClipMetadata-setClip + actual val clipMetadata: ClipMetadata + get() = TODO("ClipMetadata is not implemented. Consider using nativeClipboard") + +} diff --git a/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/viewinterop/InteropView.linux.kt b/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/viewinterop/InteropView.linux.kt new file mode 100644 index 0000000000000..a1eda09e4259a --- /dev/null +++ b/compose/ui/ui/src/linuxMain/kotlin/androidx/compose/ui/viewinterop/InteropView.linux.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.ui.viewinterop + +actual typealias InteropView = Any + +@Suppress("ACTUAL_WITHOUT_EXPECT") // https://youtrack.jetbrains.com/issue/KT-37316 +internal actual typealias InteropViewGroup = Any diff --git a/compose/ui/ui/src/nonJvmMain/kotlin/androidx/compose/ui/Actuals.nonJvm.kt b/compose/ui/ui/src/nonJvmMain/kotlin/androidx/compose/ui/Actuals.nonJvm.kt index d79080dbde46b..7965966c54130 100644 --- a/compose/ui/ui/src/nonJvmMain/kotlin/androidx/compose/ui/Actuals.nonJvm.kt +++ b/compose/ui/ui/src/nonJvmMain/kotlin/androidx/compose/ui/Actuals.nonJvm.kt @@ -18,8 +18,6 @@ package androidx.compose.ui import androidx.compose.ui.node.ModifierNodeElement import androidx.compose.ui.platform.InspectorInfo -import kotlin.coroutines.CoroutineContext -import kotlinx.coroutines.Dispatchers internal actual fun classKeyForObject(a: Any): Any { return a::class @@ -32,6 +30,3 @@ internal actual fun InspectorInfo.tryPopulateReflectively( element: ModifierNodeElement<*> ) { } - -internal actual val PostDelayedDispatcher: CoroutineContext - get() = Dispatchers.Main diff --git a/compose/ui/ui/src/webMain/kotlin/androidx/compose/ui/Actuals.web.kt b/compose/ui/ui/src/webMain/kotlin/androidx/compose/ui/Actuals.web.kt new file mode 100644 index 0000000000000..fe357aa296cb2 --- /dev/null +++ b/compose/ui/ui/src/webMain/kotlin/androidx/compose/ui/Actuals.web.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.ui + +import kotlin.coroutines.CoroutineContext +import kotlinx.coroutines.Dispatchers + +internal actual val PostDelayedDispatcher: CoroutineContext + get() = Dispatchers.Main diff --git a/lifecycle/lifecycle-viewmodel-compose/build.gradle b/lifecycle/lifecycle-viewmodel-compose/build.gradle index 57a787096ee27..d3854defc0ed6 100644 --- a/lifecycle/lifecycle-viewmodel-compose/build.gradle +++ b/lifecycle/lifecycle-viewmodel-compose/build.gradle @@ -43,6 +43,7 @@ androidXComposeMultiplatform { darwin() js() wasm() + linux() } kotlin { diff --git a/navigation/navigation-compose/build.gradle b/navigation/navigation-compose/build.gradle index 5da6e2bd836f0..542414743a6b3 100644 --- a/navigation/navigation-compose/build.gradle +++ b/navigation/navigation-compose/build.gradle @@ -36,6 +36,7 @@ androidXComposeMultiplatform { darwin() js() wasm() + linux() } kotlin { @@ -50,19 +51,19 @@ kotlin { api(project(":navigation:navigation-runtime")) api(project(":navigation:navigation-common")) - api "org.jetbrains.compose.animation:animation:1.8.2" - api "org.jetbrains.compose.runtime:runtime:1.8.2" - api "org.jetbrains.compose.runtime:runtime-saveable:1.8.2" + api(project(":compose:runtime:runtime")) + api(project(":compose:animation:animation")) + api(project(":compose:runtime:runtime-saveable")) - implementation "org.jetbrains.compose.animation:animation-core:1.8.2" - implementation "org.jetbrains.compose.foundation:foundation-layout:1.8.2" + implementation(project(":compose:animation:animation-core")) + implementation(project(":compose:foundation:foundation-layout")) implementation(project(":lifecycle:lifecycle-common")) implementation(project(":lifecycle:lifecycle-runtime-compose")) + implementation(project(":lifecycle:lifecycle-viewmodel-savedstate")) implementation(project(":lifecycle:lifecycle-viewmodel")) implementation(project(":lifecycle:lifecycle-viewmodel-compose")) - implementation(project(":lifecycle:lifecycle-viewmodel-savedstate")) - implementation project(":savedstate:savedstate") - implementation project(":savedstate:savedstate-compose") + implementation(project(":savedstate:savedstate")) + implementation(project(":savedstate:savedstate-compose")) } } diff --git a/navigation/navigation-compose/src/linuxMain/kotlin/androidx/navigation/compose/NavHost.linux.kt b/navigation/navigation-compose/src/linuxMain/kotlin/androidx/navigation/compose/NavHost.linux.kt new file mode 100644 index 0000000000000..14c1f0ad4c19a --- /dev/null +++ b/navigation/navigation-compose/src/linuxMain/kotlin/androidx/navigation/compose/NavHost.linux.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.navigation.compose + +import androidx.compose.animation.AnimatedContentTransitionScope +import androidx.compose.animation.EnterTransition +import androidx.compose.animation.ExitTransition +import androidx.compose.animation.SizeTransform +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.navigation.NavBackStackEntry +import androidx.navigation.NavGraph +import androidx.navigation.NavHostController + +@Composable +public actual fun NavHost( + navController: NavHostController, + graph: NavGraph, + modifier: Modifier, + contentAlignment: Alignment, + enterTransition: (AnimatedContentTransitionScope.() -> EnterTransition), + exitTransition: (AnimatedContentTransitionScope.() -> ExitTransition), + popEnterTransition: (AnimatedContentTransitionScope.() -> EnterTransition), + popExitTransition: (AnimatedContentTransitionScope.() -> ExitTransition), + sizeTransform: (AnimatedContentTransitionScope.() -> SizeTransform?)? +) { + NavHost( + navController, + graph, + modifier, + contentAlignment, + enterTransition, + exitTransition, + popEnterTransition, + popExitTransition, + sizeTransform, + null, + null + ) +} \ No newline at end of file diff --git a/navigation/navigation-compose/src/linuxMain/kotlin/androidx/navigation/compose/internal/NavHostInternals.linux.kt b/navigation/navigation-compose/src/linuxMain/kotlin/androidx/navigation/compose/internal/NavHostInternals.linux.kt new file mode 100644 index 0000000000000..a8009ee5a522d --- /dev/null +++ b/navigation/navigation-compose/src/linuxMain/kotlin/androidx/navigation/compose/internal/NavHostInternals.linux.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.navigation.compose.internal + +internal actual typealias DefaultNavTransitions = StandardDefaultNavTransitions diff --git a/navigation/navigation-runtime/build.gradle b/navigation/navigation-runtime/build.gradle index 45cfade0bffc2..eea1465e65c57 100644 --- a/navigation/navigation-runtime/build.gradle +++ b/navigation/navigation-runtime/build.gradle @@ -51,7 +51,7 @@ androidXMultiplatform { commonMain { dependencies { api "androidx.annotation:annotation:1.9.1" - api "androidx.collection:collection:1.5.0" + api "androidx.collection:collection:1.5.0-beta01" api project(":lifecycle:lifecycle-common") api project(":lifecycle:lifecycle-runtime") api project(":lifecycle:lifecycle-viewmodel") diff --git a/navigation3/navigation3-ui/build.gradle b/navigation3/navigation3-ui/build.gradle index 83d2c12825ec3..da3bb7efe8715 100644 --- a/navigation3/navigation3-ui/build.gradle +++ b/navigation3/navigation3-ui/build.gradle @@ -43,6 +43,7 @@ androidXComposeMultiplatform { darwin() js() wasm() + linux() } kotlin { diff --git a/navigation3/navigation3-ui/src/linuxMain/kotlin/androidx/navigation3/ui/NavDisplay.linux.kt b/navigation3/navigation3-ui/src/linuxMain/kotlin/androidx/navigation3/ui/NavDisplay.linux.kt new file mode 100644 index 0000000000000..e0fbb65e9a124 --- /dev/null +++ b/navigation3/navigation3-ui/src/linuxMain/kotlin/androidx/navigation3/ui/NavDisplay.linux.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.navigation3.ui + +import androidx.compose.animation.AnimatedContentTransitionScope +import androidx.compose.animation.ContentTransform +import androidx.compose.animation.core.tween +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.navigation3.scene.Scene +import androidx.navigationevent.NavigationEvent.SwipeEdge + +private const val DEFAULT_TRANSITION_DURATION_MILLISECOND = 700 + +public actual fun defaultTransitionSpec(): + AnimatedContentTransitionScope>.() -> ContentTransform = { + ContentTransform( + fadeIn(animationSpec = tween(DEFAULT_TRANSITION_DURATION_MILLISECOND)), + fadeOut(animationSpec = tween(DEFAULT_TRANSITION_DURATION_MILLISECOND)), + ) +} + +public actual fun defaultPopTransitionSpec(): + AnimatedContentTransitionScope>.() -> ContentTransform = { + ContentTransform( + fadeIn(animationSpec = tween(DEFAULT_TRANSITION_DURATION_MILLISECOND)), + fadeOut(animationSpec = tween(DEFAULT_TRANSITION_DURATION_MILLISECOND)), + ) +} + +public actual fun defaultPredictivePopTransitionSpec(): + AnimatedContentTransitionScope>.(@SwipeEdge Int) -> ContentTransform = { + ContentTransform( + fadeIn(animationSpec = tween(DEFAULT_TRANSITION_DURATION_MILLISECOND)), + fadeOut(animationSpec = tween(DEFAULT_TRANSITION_DURATION_MILLISECOND)), + ) +} diff --git a/navigationevent/navigationevent-compose/build.gradle b/navigationevent/navigationevent-compose/build.gradle index 84abb7e9ea6ed..e73fb822d15c2 100644 --- a/navigationevent/navigationevent-compose/build.gradle +++ b/navigationevent/navigationevent-compose/build.gradle @@ -43,6 +43,7 @@ androidXComposeMultiplatform { darwin() js() wasm() + linux() } kotlin {