Skip to content

Compose 1.13.0-alpha01 / Skiko 0.152: what breaks, what moves, what we gain (source-level analysis) #671

Description

@kdroidFilter

Summary

Source-level analysis of what moving Nucleus from Compose Multiplatform 1.12.0 to 1.13.0-alpha01 breaks, what it changes underneath, and what it buys us. Everything below was checked against cloned trees and published artifacts, not against the release notes alone, and re-verified in two further independent passes (the comments below list what each pass corrected):

  • JetBrains/compose-multiplatform-core at v1.12.0 (f29d2f99) and v1.13.0-alpha01 (a9e47e8a)
  • JetBrains/compose-multiplatform (Gradle plugin) at both tags
  • JetBrains/skiko at v0.150.1 and v0.152.0-alpha02, plus a javap diff of the two skiko-awt jars and the entry listing of skiko-awt-runtime-all
  • Maven Central POM / .module metadata for ui-desktop, ui-skiko-desktop, ui-graphics-desktop, foundation-desktop, desktop-jvm, desktop-jvm-macos-arm64, skiko-awt, Jewel, Material3
  • Jewel 0.41.0 jars scanned for the Skiko symbols that changed shape

Verdict: it compiles, but it does not run as-is: Compose 1.13 requires the host to register the Skiko backend (registerSkikoComposeImplementation()), which only the AWT ComposeContainer does. Nucleus builds scenes directly, so every Tao window would fail at construction. That is a one-line fix. After that, what moves is a hidden Skiko bump, an artifact split that changes how natives arrive (fat jar), two API members our Tao layer has to follow, a Pan-classification change that lands on TaoSceneScrollRouter, and packaging / GraalVM metadata rot. Skia Graphite is not in Compose 1.13; it is a separate Skiko module Compose does not consume anywhere.

Nucleus today 1.13.0-alpha01
Compose 1.12.0 1.13.0-alpha01 (Jetpack 1.13.0-alpha02)
Skiko 0.150.1 0.152.0-alpha02
Skia m150 m152
Skiko natives on the classpath skiko-awt-runtime-<os>-<arch> via desktop-jvm-<target> skiko-awt-runtime-all via ui-skiko-desktop (55 MB jar, 130 MB unpacked, all six natives + icudtl.dat)
Kotlin stdlib required 2.4.10 ≥ 2.2.20, fine
kotlinx-coroutines required 1.11.0 ≥ 1.9.0, fine
material3 1.12.0-alpha03 1.13.0-alpha01 published
Compose Hot Reload preferred 1.2.0 1.3.0-alpha01
Jewel, latest on Central 0.39.1 (built on Compose 1.11) 0.41.0-262.10968.63 (built on Compose 1.12.0), nothing for 1.13 yet

Gotcha: gradle/libs.versions.toml in the core repo still says skiko = "0.150.1" at both tags. The published ui-graphics-desktop POM/.module is the truth and says 0.152.0-alpha02.

What breaks or moves in Nucleus

0. Runtime break: the Skiko backend must be registered by the host

ui-graphics and ui-text no longer contain their Skia actuals. The non-Android actuals go through process-wide registries and the Skia implementation lives in the new ui-skiko artifact:

// ui-graphics, nonAndroidMain
internal fun requireCurrent(): PlatformGraphics =
    implementation ?: error("No Compose UI graphics implementation is registered.")
// ui-text, nonAndroidMain
implementation ?: error("No Compose UI text implementation is registered.")

Paint(), Path(), ImageBitmap(...), ColorFilter.tint, every shader, Paragraph(...), findPrecedingBreak, and createFontFamilyResolver() all go through them. The registration entry point is:

// ui-skiko, androidx.compose.ui.platform
@InternalComposeUiApi
fun registerSkikoComposeImplementation() {
    PlatformGraphicsRegistry.register(SkikoGraphics)
    PlatformTextRegistry.register(SkikoText)
    SkikoGraphicsCompatRegistry.register(SkikoGraphicsCompatImpl)
}

It is called from ComposeContainer.desktop.kt (AWT, in init), ImageComposeScene, the iOS / macOS / web containers and the test bases. Nothing in BaseComposeScene, RootNodeOwner, CanvasLayersComposeScene or PlatformLayersComposeScene calls it. Nucleus creates its scenes directly in TaoSceneBundle.kt (canvasLayersSceneBundle / platformLayersSceneBundle), and RootNodeOwner runs fontFamilyResolver = createFontFamilyResolver() in a property initializer → every Tao window throws "No Compose UI text implementation is registered." before its first frame: CanvasLayersComposeScene at construction (eager mainOwner), PlatformLayersComposeScene at first use (mainOwner by lazy). Our 13 direct Compose Paint() / Path() / ImageBitmap() / ColorFilter.tint call sites in main code (8 files: InsideBorderModifier.kt, WindowControlsWindows.kt, WindowControlsLinux.kt, DialogTitleBar.kt, TransferDrag.kt, SpellcheckUnderline.kt, PainterToRgba.kt, ContextMenuFlyout.kt) hit the graphics variant the same way.

Fix: call registerSkikoComposeImplementation() at the top of canvasLayersSceneBundle and platformLayersSceneBundle in TaoSceneBundle.kt. It is idempotent for the same instance and synchronized. Nucleus already opts into InternalComposeUiApi per file (22 files today). Those two factories are also what TaoSceneTestHarness, NativePopupLayersTest and TaoSceneOuterLocalsBridgeTest go through, so the same line covers the tests; the ui-test-junit4 based tests (NucleusWindowHostTest, ContextMenuDividerCapabilityTest, ProvideNucleusSystemThemeE2ETest) self-register through ComposeUiTest.

1. window.v2 clone must follow an upstream rename

WindowGeometryProviders.desktop.kt renames AlignedToScreen → AlignedToScreenAvailableBounds and CenteredOnScreen → CenteredInScreenBounds (core #3291). The latter becomes a val plus a fun CenteredInScreenBounds(offset: DpOffset) that centers on screen.bounds, ignoring insets. No deprecated aliases upstream. Our member-for-member clone in decorated-window-tao/src/main/kotlin/dev/nucleusframework/window/tao/v2/WindowProviders.kt still has the old names. Public API frozen by BCV → keep the old names as @Deprecated aliases, add the new ones, ./gradlew apiDump. The other v2 files (Screen, WindowGeometry, WindowState, DialogState) are unchanged upstream.

2. PlatformContext.taskDispatchers is a new abstract member

interface PlatformContext {
    val taskDispatchers: TaskDispatchers   // no default
    ...
}
open class Empty : PlatformContext {
    override val taskDispatchers: TaskDispatchers = DefaultTaskDispatchers  // Default = Dispatchers.Default, IO = Dispatchers.Default
}

Nucleus does not break: every Tao context extends PlatformContext.Empty() through TaoPlatformContextBase (TaoKeepScreenOn.kt:61), and the EDT-guard wrapper in TaoSceneBundle.kt uses PlatformContext by this. But Empty maps IO to Dispatchers.Default, while the AWT ComposeSceneMediator maps it to Dispatchers.IO. Override taskDispatchers in TaoPlatformContextBase for parity. RootNodeOwner exposes it as Owner.taskDispatchers. Also new with defaults: mediaScope: UiMediaScope (experimental, gated by ComposeUiFlags.isMediaQueryIntegrationEnabled) and hapticFeedback now defaulting to a no-op.

3. Skia graphics and text helpers moved to the new artifact org.jetbrains.compose.ui:ui-skiko

asComposeCanvas, nativeCanvas, toComposeImageBitmap, asSkiaBitmap, toAwtImage, SkiaGraphicsContext, SkiaBackedCanvas, SkikoGraphicsLayer, and on the text side SkikoParagraph, FontLoader, PlatformFont, AwtFontInterop, JetBrainsRuntimeFontFamilies, ReflectionUtil, and the desktop Font(resource = …) / Font(file = …) factories all left ui-graphics-desktop / ui-text-desktop for ui-skiko (src/nonAndroidMain, src/desktopMain). Same packages, same JVM class names (SkiaBackedCanvas_skikoKt, SkiaImageAsset_skikoKt, DesktopImageConverters_desktopKt, DesktopFont_desktopKt, PlatformFont_skikoKt), pulled at compile scope by ui-desktop and foundation-desktop → source and binary compatible. Nucleus call sites: scene/TaoSceneBundle.kt (3), scene/TaoComposeSceneHostLinux.kt (2), nucleus-application/.../contextmenu/ContextMenuFlyout.kt (2), plus compose-demo, tao-demo, benchmark-demo. Nothing to change in code, but one more jar for ProGuard / uber-jar / GraalVM metadata to see, and ui-skiko-desktop is what now carries the Skiko native runtime dependency (see 10).

4. Trackpad Pan events are now classified by Compose

ComposeSceneInputHandler.skiko.kt tags PanStart / PanMove / PanEnd with PointerClassification.Pan + isGestureStart / isGestureEnd (new fields on PointerInputEvent; ComposeScene.sendPointerEvent is unchanged). Effects in common code, unconditional:

  • PointerInputEventProcessor: a Pan event is treated as a hover stream regardless of pressed state (isHover = true).
  • HitPathTracker: no new hit tests during a pan ("prevent entering new items while scrolling"); isIn is still recomputed for existing hit paths; pointer ids are pruned immediately on release during a pan.

Gated by ComposeUiFlags.isTrackpadPanHoverFixEnabled, default false (TODO CMP-10707 "restore to the AOSP value"): the synthesis of Enter / Exit for a Pan event when isIn != hasEntered, i.e. hover Exit for items that scroll out from under a stationary cursor. So today's release changes the hit-path bookkeeping but not yet the Enter/Exit synthesis on desktop.

This is exactly the bookkeeping TaoSceneScrollRouter does by hand since #654 (deliver the deferred PanEnd to the node that received the PanMoves). Needs headful re-testing: hover state during trackpad scroll, deferred PanEnd, NSPanel popups; then try isTrackpadPanHoverFixEnabled = true since it is the behaviour we want. The -Dnucleus.tao.trackpadPanEvents=false path (everything as Scroll) is untouched.

5. Legacy render-node layers removed, picture snapshot cache added

ComposeUiFlags.useLegacyRenderNodeLayers and LegacyRenderNodeLayer.skiko.kt are gone (core #3213). New ComposeUiFlags.useSnapshotCache (default true) feeds Skiko's RenderNodeContext(measureDrawBounds, snapshotCache): every GraphicsLayer records an immutable SkPicture replayed until its content changes (skiko #1022). Nucleus references none of these flags. Memory grows with the number of layers; the known regression in the release is Web-only (CMP-10732), but watch windows with many popup layers.

Other new ComposeUiFlags (Jetpack side): isMinimalistLocalsEnabled (false, lets LocalX fall back to LocalOwner instead of being eagerly provided), isVectorDrawCacheSharingEnabled (true, documented as a no-op for now), isVelocityTrackerMinSampleSizeFixEnabled (true); isClearNestedScrollCoroutineScopeFixEnabled removed.

6. No more snapshot apply between layout and draw

BaseComposeScene.render dropped Snapshot.sendApplyNotifications() between the layout and draw phases. State written during layout is no longer visible to draw in the same frame. Nucleus already pumps Snapshot.sendApplyNotifications() itself around frames (TaoMainDispatcher, TaoApplicationCompose, TaoAccessibility), so only state written during the layout pass is affected. DockLayoutState lives in snapshot state → DockLayoutMonkeyHeadfulCases is the safety net.

7. Window insets plumbing

excludeWindowInsets removed from Popup.skiko.kt / Dialog.skiko.kt, RootWindowInsetsProviderModifierElement removed from RootNodeOwner, foundation-layout's WindowInsetsPadding.skiko.kt now reads LocalPlatformWindowInsets directly. PlatformContext.windowInsets (overridden by our three scene hosts) is still what CompositionLocals.skiko.kt:106 provides. Neutral, but layers that relied on usePlatformInsets exclusion render differently.

8. Friend-package accessors and implemented interfaces survive

  • androidx.compose.ui.draganddrop.TaoTransferableAccess → AwtDragAndDropTransferable.toAwtTransferable() still at DragAndDrop.desktop.kt:122-131.
  • androidx.compose.ui.scene.TaoComposeSceneContextAccess → LocalComposeSceneContext still a top-level internal val in ComposeSceneContext.skiko.kt:33.
  • CanvasLayersComposeScene, PlatformLayersComposeScene, ComposeScene, ComposeSceneLayer, ComposeSceneContext, ComposeSceneDragAndDropNode, PlatformDragAndDropManager, PlatformScreenReader, PlatformClipboard: files byte-identical between the two tags.
  • Every Compose interface Nucleus implements (WindowInfo in TaoWindowInfo / StandalonePopupWindowInfo, TextToolbar in TaoTextToolbar, UriHandler in TaoLinuxUriHandler, anonymous ViewConfiguration, ComposeSceneContext, PlatformContext) only gained explicit public modifiers upstream (explicit API mode). No new abstract members besides PlatformContext.taskDispatchers.
  • Also verified unchanged on the 1.13 sources: SaveableStateRegistry (our RelocatingSaveableStateRegistry), MonotonicFrameClock (TaoFrameClock), Applier (NoOpApplier), ModifierNodeElement, the DragAndDropSourceModifierNode(onStartTransfer) factory and DragAndDropStartTransferScope (TransferDrag), Modifier.dragAndDropTarget (DockTransferTarget, TabStrip), and the old context-menu API we hook (TextContextMenu / LocalTextContextMenu / ContextMenuRepresentation / ContextMenuArea in NativeTextContextMenu, NativeContextMenuRepresentation): ComposeFoundationFlags.isNewContextMenuEnabled stays false on skiko in 1.13, so that path is still the one used. The hapticFeedback default swap is neutral, DefaultHapticFeedback was already empty.

9. Skiko 0.152.0-alpha02, what touches Nucleus

  • FontStyle, FontWeight, FontWidth, FontMetrics became value classes (skiko #1209). Binary break for any jar compiled against 0.150 that calls them (FontMgr.matchFamilyStyle-ooATI1c, Font.getMetrics-l-OL_C8, …). Nucleus imports none of the four. Jewel 0.41.0 jars (jewel-foundation, jewel-ui, jewel-int-ui-standalone, jewel-markdown-*) reference none of org/jetbrains/skia/FontStyle|FontWeight|FontWidth|FontMetrics|FontMgr, nor any Compose scene/PlatformContext/ComposeUiFlags internals → binary-safe with respect to this change, even though built on Compose 1.12.0.
  • org.jetbrains.skiko.context.* (all ContextHandlers) deleted; AWT redrawers reshaped (OnScreenRedrawer, FrameHost, AbstractOpenGLRedrawer, Redrawer.syncBounds → syncBoundsFromPlatformComponent, onLayerComponentResized; SkiaLayer gains fillsWindow). Nucleus mentions SkiaLayer / ContextHandler in comments only. Nothing to do.
  • Skottie + sksg removed from the core binary (skiko-skottie is separate). Nucleus does not use them, but plugin-build/plugin/src/main/resources/nucleus/graalvm/library-metadata/skia-skiko.json and platform-metadata/macos-reachability-metadata.json still declare org.jetbrains.skia.skottie.Logger, skottie.LogLevel and a 15-float FontMetrics.<init> that the 0.152 JNI no longer constructs (interop.cc returns a float[]). Dead entries to remove.
  • DirectContext(ptr, managed): Surface.recordingContext now returns a borrowed context (managed = false); Canvas.recordingContext is new. If any Nucleus code closes a context obtained from a surface, review it.
  • ColorFilter.makeBlend now returns ColorFilter?; Path.updateBoundsCache() is a hidden deprecated no-op. Nucleus calls neither.
  • Rect.fromInteropPointer, SurfaceProps.packToIntArray, LibraryLoader now public @InternalSkikoApi (were internal).
  • Per-OS native size is flat (libskiko-macos-arm64.dylib 21.44 MB → 21.43 MB); the dead-code stripping in #1228 is offset by m152.

10. Packaging: natives now arrive as one fat jar

Verified from metadata:

  • 1.12.0: desktop-jvm-macos-arm64 POM → desktop 1.12.0 + skiko-awt-runtime-macos-arm64 0.150.1.
  • 1.13.0-alpha01: desktop-jvm-macos-arm64 POM → desktop 1.13.0-alpha01 only. ui-skiko-desktop → skiko-awt-runtime-all 0.152.0-alpha02 (compile scope). skiko-awt itself only publishes version constraints on the per-OS runtimes, no dependency. skiko-awt-runtime-all exists on Central at exactly one version, 0.152.0-alpha02.
  • The fat jar: 55.3 MB compressed, 130.8 MB unpacked, entries at the jar root: libskiko-linux-{x64,arm64}.so, libskiko-macos-{x64,arm64}.dylib, skiko-windows-{x64,arm64}.dll, icudtl.dat, plus .sha256 files. Same entry names as the per-OS jars.

Consequences for Nucleus:

  • Our fork of the packaging plugin (AbstractJPackageTask.kt:966, isSkikoForCurrentOS) only recognises jars named skiko-awt-runtime-<os>-<arch>. With 1.13 it recognises nothing, so the 55 MB jar is copied whole into the distributable (all six natives) and the pre-extraction that sets -Dskiko.library.path never runs (Skiko falls back to extracting into ~/.skiko at first start). Port the new skikoUtils.kt filter: jar name skiko-* containing -awt-runtime, keep only entries containing -<os>-<arch> plus icudtl.dat on Windows.
  • The exclude(group = "org.jetbrains.skiko", module = "skiko-awt-runtime-all") in examples/jewel-demo, jewel-tabs-demo, scheduler-demo must go: on 1.13 it removes the only source of natives and the app dies at Skiko load. (Jewel's own POMs declare no Skiko runtime dependency; the exclusion was defensive.)
  • GraalVM uber-jar extraction (include("libskiko-<os>-<arch>.dylib"), .so, .dll + icudtl.dat) keeps working, entry names did not change, but the uber jar grows by ~55 MB unless the other-OS entries are excluded when it is built.
  • The Compose plugin deprecates compose.desktop.currentOs (still resolves to desktop-jvm-<target>); its new compose { dependencyCompatibility { exclude("group[:module]") } } and the runtime-libraries check now also flag Skiko version mismatches. Jewel 0.41 on a 1.13 build will trigger it.
  • New AOT DSL in JvmApplicationBuildType: aot { mode = AotMode.AotPrebuild | AppCdsPrebuild | AppCdsAuto }, training run with -XX:AOTCacheOutput=$APPDIR/app.aot and -Dcompose.aot.training-run=true, runtime -XX:AOTCache=$APPDIR/app.aot, createDistributable split into createDistributableImpl + createAotArchive, stripNativeCommands disabled when generating the JRE CDS archive (generateJreCdsArchive). Same archive name as our aotCache / aotTraining(). No break (fork), but generateJreCdsArchive (a classes.jsa for the jlinked runtime) is worth adopting.
  • --app-image is now always the app dir (<name>.app on macOS, <name> elsewhere) and installers are built from the app image on every OS, not only macOS.
  • Other fork-merge material: AbstractJLinkTask.generateJreCdsArchive (jlink --generate-cds-archive, refused when stripNativeCommands is on), AbstractCheckNativeDistributionRuntime.aotModes (per-mode minimum JDK check), and an executePackagedApp helper that replaces the hand-rolled app-dir lookup in AbstractRunDistributableTask.

Skia Graphite: what it actually is

Zero references in the Compose 1.13.0-alpha01 tree. Graphite exists only as a Skiko module skiko-graphite (org.jetbrains.skia.gpu.graphite: GraphiteContext, Recorder, Recording, InsertRecordingInfo, SurfaceFactory, BackendTexture, BackendSemaphore, VulkanTypes, GraphiteImageProvider.cc), published as Apple klibs since 0.151.0 and as skiko-graphite-awt + per-OS runtime jars (macOS / Linux / Windows, x64 + arm64) since 0.152.0 (skiko #1245, #1261 "Add Graphite Vulkan", #1277). Backends: Metal and Vulkan. No Dawn, no D3D12.

Compose does not need to know about it: GraphicsLayer goes through Skiko's RenderNode, which records SkPictures and replays them onto whatever SkCanvas the host provides. The backend decision lives entirely in the host surface, i.e. in our MetalSceneRenderer / GlSceneRenderer (DirectContext.makeMetal / makeGLWithInterface + Surface.makeFromBackendRenderTarget). Going Graphite would mean GraphiteContext + Recorder + SurfaceFactory on macOS, and a new Vulkan backend on Linux/Windows where we are EGL / ANGLE today; it would also break the Ganesh-based zero-copy TextureView import and the ExternalTexture roadmap (#338). Nothing to do for 1.13. Worth tracking because Ganesh is end-of-life upstream.

What we gain

For free:

  • Linux theme.cc tries libdbus-1.so.3 before libdbus-1.so (skiko #1276) → fixes SystemTheme.UNKNOWN on distros without the dev symlink, which ProvideNucleusSystemTheme reads through currentSystemTheme.
  • RenderNode picture snapshot cache → cheaper static subtrees (dock bands, tab strips, palettes).
  • macOS Ctrl+F / Ctrl+B reversed in text fields, fixed in foundation KeyMapping.skiko.kt (skikoMain, so it applies to Tao).
  • RenderNode.alpha applied at draw (skiko #1227), null-safe ColorFilter (core #3319), Skia m152.

With a little code:

  • Image.adoptTextureFrom(context, texture, origin, colorType, alphaType) → declare premul / opaque properly in TextureView.
  • Canvas.drawAnnotation, Canvas.recordingContext.
  • PlatformContext.mediaScope (experimental): Tao can feed pointerPrecision, keyboardKind, window size.
  • taskDispatchers with a real Dispatchers.IO.
  • ComposeUiFlags.isTrackpadPanHoverFixEnabled = true once validated: upstream hover Exit during trackpad scroll, which is what Tao: distinguish trackpad panning from wheel scrolling in Compose #654 wanted.
  • Upstream AppCDS / AOT DSL validates our aotCache approach; generateJreCdsArchive is portable.

Proposed order (spike branch; v1.13.0-alpha02+dev4828 is already tagged upstream)

  1. Bump compose and material3 to 1.13.0-alpha01, hotReload to 1.3.0-alpha01 (only tao-demo applies it), and navigation3 (only compose-demo, currently 1.1.1 built on Compose 1.10.0) to 1.2.0-beta01 with lifecycle-viewmodel-navigation3 2.11.0.
  2. Call registerSkikoComposeImplementation() before any scene is created (TaoSceneBundle / DecoratedWindow bootstrap) and in TaoSceneTestHarness.
  3. Remove the skiko-awt-runtime-all exclusions from jewel-demo, jewel-tabs-demo, scheduler-demo.
  4. Mirror the v2 rename in tao/v2/WindowProviders.kt with @Deprecated aliases, apiDump.
  5. Override taskDispatchers in TaoPlatformContextBase (Default / IO).
  6. Port the skikoUtils.kt native filter into our AbstractJPackageTask.kt; check the uber jar size for the GraalVM path.
  7. Remove the skottie / 15-arg FontMetrics entries from the plugin's GraalVM metadata.
  8. Headful: trackpad pan + hover (TaoSceneScrollRouter), NSPanel popups, DockLayoutMonkeyHeadfulCases, TextureViewMonkeyHeadfulCases; then evaluate isTrackpadPanHoverFixEnabled.
  9. Optional: Image.adoptTextureFrom(alphaType) in TextureView, feed mediaScope from Tao, exclude Jewel from the plugin's compatibility check until a 1.13 Jewel exists.

Not affected (checked)

ResourceFont / FileFont constructors now @InternalComposeUiApi; PlatformTextInputSession & co only gained explicit public; InteropContainer.scheduleUpdate(holder) new default method; Wrapper.skiko.kt no longer passes uriHandler (now RootNodeOwner.uriHandler lazily); ComposeSceneMediator.boundsOnScreenPx() / drawContentInto(), ComposeDesktopEntryPoint.captureContentToImage() and the Skiko metalSynchronousLiveResize / direct3DSynchronousLiveResize properties are AWT SkiaLayer only. No Nucleus native code includes Skia headers. graalvm-runtime's @TargetClass substitutions target JDK classes only (java.awt.SplashScreen, sun.awt.X11.XToolkit, sun.awt.Win32FontManager, java.awt.Font, sun.awt.FcFontManager). The shipped ProGuard rule -keep class org.jetbrains.skiko.** { *; } is unaffected. Nucleus does not use FontLoader / PlatformFont / Typeface(skia) / FontRasterizationSettings directly.

Foundation's scrolling was refactored (TrackpadScrollingLogic / MouseWheelScrollingLogic generalised into Trackpad1DScrollingLogic / Trackpad2DScrollingLogic over ScrollValueAdapters in NonTouchScrollingLogic.kt); the 45° axis lock moved from atan2(|y|, |x|) >= π/4 in Scrollable.kt to abs(y) >= abs(x) in OneDimensionalScrollValueAdapter.toScrollValue, which is the same rule, so diagonal trackpad pans reaching Modifier.scrollable behave as before. ComposeFoundationFlags: isBasicTextFieldSizeOptimizationEnabled flipped to true, a set of new lazy cache-window flags, isClearNestedScrollCoroutineScopeFixEnabled removed. SaveableStateHolderImpl internals changed (SnapshotStateSet keys, direct performSave()), API identical. Transitive versions unchanged: androidx.collection 1.5.0, lifecycle-runtime-compose 2.9.6, lifecycle-viewmodel 2.11.0, savedstate-compose 1.4.0; runtime-retain 1.12.0 → 1.13.0-alpha02. swing-tao-demo uses no ComposePanel / SwingPanel, so the Swing double-buffering change (#3336) touches nothing.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions