Enable linuxX64 native target for Compose Multiplatform Core libraries#3189
Draft
Aaron Chancey (hi-mod) wants to merge 16 commits into
Draft
Enable linuxX64 native target for Compose Multiplatform Core libraries#3189Aaron Chancey (hi-mod) wants to merge 16 commits into
Aaron Chancey (hi-mod) wants to merge 16 commits into
Conversation
added 10 commits
July 3, 2026 22:29
Skiko now builds a native linuxX64 artifact, so LinuxX64 moves into ComposePlatforms.SKIKO_SUPPORT. The linux() target helper is narrowed to linuxX64 for now: skiko-linuxarm64 klibs are built, but the compose modules have only been compiled and tested for linuxX64. buildSrc and buildSrc-fork carry the same change because the fork build consumes the -fork copies.
Local development configuration, not intended for upstream: the Linux native SkiaLayer lives in a skiko fork published to mavenLocal as 0.0.0-SNAPSHOT, so the version catalogs point at it and repos.gradle adds mavenLocal(). Drop this commit once a skiko release ships the Linux native support.
The published org.jetbrains.androidx.navigationevent artifacts (1.1.0) ship no linuxx64 variant, so ui and ui-backhandler cannot resolve them when the linux target is enabled. Include :navigationevent:* in the fork settings, enable linuxX64 in navigationevent-compose with a nonAndroidMain/linuxMain source-set chain, and swap the published dependency for the project one in ui and ui-backhandler.
These modules need no macos-style platform sources; nativeMain and skikoMain already cover them. The only new actuals are the no-op trace/traceValue in ui-util. Everything else is the linux() target declaration. Test: ./gradlew :compose:ui:ui-graphics:compileKotlinLinuxX64
linuxMain actuals mirror the darwin ones in shape but stay minimal: the default PlatformResolveInterceptor (font loading itself goes through skikoMain's FontMgr.default, backed by fontconfig), platform locale from the posix locale, and a string delegate using the Kotlin stdlib case functions, which ignore the locale argument for now. Test: ./gradlew :compose:ui:ui-text:compileKotlinLinuxX64
The core of the port. linuxMain provides: - window/ComposeWindow.linux.kt: X11 window plus skiko SkiaLayer hosting a CanvasLayersComposeScene, an X11 event loop that pumps events, drains the skiko main-dispatcher queue, and renders on demand, and the Window() entry point. - input/key/Key.linux.kt: X11 keysym to androidx Key map. - platform/: in-memory clipboard stub, UriHandler via xdg-open. - No-op actuals for drag-and-drop, pointer icons, interop views, and focusability, mirroring the macos port's level of support. PostDelayedDispatcher moves from nonJvmMain to per-platform actuals: kotlinx-coroutines has no Dispatchers.Main on linuxX64, so the native actual routes Linux to skiko's SkikoDispatchers.Main, whose queue the X11 event loop drains. Test: ./gradlew :compose:ui:ui:compileKotlinLinuxX64, plus a material3 demo app on linuxX64 (screenshot, synthetic clicks, clean shutdown).
foundation's linuxMain actuals mirror the macos ones: platform text selection, context menus, text field internals, lazy list prefetch, scroll config, and clipboard conversion helpers, each at the same stub-or-minimal level the macos port uses. Test: ./gradlew :compose:foundation:foundation:compileKotlinLinuxX64
animation-core needs a single linuxMain actual (Expect.linux.kt); animation is target declaration only. Test: ./gradlew :compose:animation:animation:compileKotlinLinuxX64
material3 gets linuxMain actuals for CalendarLocale and PlatformDateFormat built on the posix locale; material and material-ripple are target declaration only. Test: ./gradlew :compose:material3:material3:compileKotlinLinuxX64
In AndroidXForkTargetsExtensions.kt (both in buildSrc and buildSrc-fork ), the script was unconditionally trying to fetch iosSimulatorArm64 from testableTargets via getByName. When iOS compilation target groups are disabled, this would crash configuration. - I replaced getByName with findByName(...) and safely configure iOS instrumented tests only if the target is actually enabled/registered.
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
added 6 commits
July 4, 2026 13:19
Key identity now resolves from the effective keysym with an unshifted fallback, covering punctuation, navigation, function, numpad, and modifier keys; unmapped keysyms fall through as Key.Unknown so typed characters still reach text fields. X11 state masks translate to PointerKeyboardModifiers on key and pointer events, and WindowInfo.keyboardModifiers tracks them.
Mirrors MacosTextInputService: tracks the active input session so text fields get a real PlatformTextInputService, with XIM/ibus composition left as a follow-up.
Work scheduled by one event (gesture coroutines, focus moves) now runs before the next event is handled, matching AWT/AppKit loop ordering. A click-then-type burst previously delivered every key before the tap gesture focused the text field, dropping the typed characters.
:compose:ui:ui:linuxX64Test cannot run them yet: the shared skikoTest sources need ui-test, which is not enabled for linuxx64. The file compiles clean; enabling ui-test for linux is tracked as follow-up.
Replaces the in-memory clipboard stub with a real X11 CLIPBOARD selection backend shared by Clipboard and ClipboardManager. Copy claims selection ownership and serves SelectionRequest events (TARGETS, UTF8_STRING, TEXT, STRING) from the window event loop; paste issues XConvertSelection and waits on the display connection for SelectionNotify, preferring UTF8_STRING with a Latin-1 STRING fallback, and short-circuits to in-process text when a window of this process owns the selection. SelectionClear drops stale ownership. INCR (multi-chunk) transfers are not supported yet.
Aaron Chancey (hi-mod)
force-pushed
the
linux-x64
branch
from
July 5, 2026 01:46
1bf723d to
0daa5c0
Compare
|
Seems like a mistake to build anything new on X11. I also don't think we should assume any compositor for the majority of UI. |
Author
|
That makes sense. I will work on supporting Wayland and being compositor agnostic. I think I chose X11 because Mint defaults to that. I tried using Wayland and my screen just blanks so I will need to figure that out. |
Aaron Chancey (hi-mod)
marked this pull request as draft
July 10, 2026 00:58
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Proposed Changes
This pull request enables the
linuxX64compilation and publication target for the Compose Multiplatform Core libraries (ui,ui-text,ui-backhandler,foundation,foundation-layout,animation,animation-core,material,material-ripple, andmaterial3).The implementation connects the Compose UI rendering runtime to the native Linux platform via Skiko:
ComposeWindow.linux.kt: Connects an X11 window to Skiko'sSkiaLayerusing aCanvasLayersComposeScene. It contains an X11 event pump that polls for window input events, handles window resize signals, and invokes redrawing on the canvas.Key.linux.kt.PostDelayedDispatchertoSkikoDispatchers.Mainto handle the lack ofDispatchers.Mainin Kotlin/Native on Linux.xdg-openusing POSIXsystem()calls.:compose:mpp:linux-demosample project configured forlinuxX64target. Added a native Linux entry point atcompose/mpp/linux-demo/src/linuxMain/kotlin/Main.ktthat creates aComposeWindowto render a shared Material3 counter app.getByName("iosSimulatorArm64")with a safefindByName("iosSimulatorArm64")check insideAndroidXForkTargetsExtensions.kt(for bothbuildSrcandbuildSrc-fork).compose/mpp/demo/build.gradle.ktsto conditionally register JS, Wasm, macOS, and iOS targets using platform-enable checks (enableJs(),enableWasmJs(),enableMac()) and configured their source sets only if they are active. This prevents dependency resolution errors (such as missing target variants of:lifecycle:lifecycle-common) when building/syncing with restricted target platforms.Testing
Local Compilation and Publishing
End-to-End Verification
Built and ran the demo application in the consumer repository against the local maven artifacts:
xwdand converted to PNG to verify rendering correctness.xtest.fake_input(simulating button press and release events) to verify target click response.WM_DELETE_WINDOWclient message to close the application window.Standalone Demo Verification
Verified compiling and running the built-in multiplatform demo within this repository:
QA Verification
This change should be tested by QA. Verification steps:
Local Development Tips
Gradle Sync with Local Skiko Snapshots
When syncing the project in IntelliJ or via Gradle against a locally built Skiko snapshot (which typically only contains target variants for JVM and Linux), Gradle dependency resolution will try to download the snapshot versions for all targets (Wasm, JS, macOS, iOS).
To prevent these resolution errors, restrict the active target platforms by adding the following property to your user-level Gradle properties file (
~/.gradle/gradle.properties):androidx.enabled.kmp.target.platforms=-wasm,-js,-mac,-windows,-android_nativeRelease Notes
Features - Desktop
linuxX64target support for Compose Multiplatform Core libraries.linuxX64target in the core multiplatform Gradle configurations.ComposeWindowusing a native X11 window hosted on Skiko'sSkiaLayer.:compose:mpp:linux-demo) showing Material3 integration.