mirror of
https://github.com/bitsycore/compose-desktop-native.git
synced 2026-10-05 18:57:26 +00:00
Compare commits
20
Commits
10380e5422
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c76f629971 | ||
|
|
c4564b3a10 | ||
|
|
fb8e97b74d | ||
|
|
6c3bfd8679 | ||
|
|
ec2d9b06ad | ||
|
|
1d6e5a76de | ||
|
|
eb44db915e | ||
|
|
1120abc488 | ||
|
|
9d2656f905 | ||
|
|
48cfa5da4d | ||
|
|
856cbe5ef3 | ||
|
|
5c7308c614 | ||
|
|
2fb322776a | ||
|
|
7c7bb63cae | ||
|
|
02fb2ddf4e | ||
|
|
126e83c056 | ||
|
|
0c09109e6e | ||
|
|
5804128e1d | ||
|
|
04d1df58de | ||
|
|
a87ff2d7f6 |
@@ -96,7 +96,30 @@ compose/
|
|||||||
│ ├── foundation/ → :compose:foundation:foundation - androidx.compose.foundation.*
|
│ ├── foundation/ → :compose:foundation:foundation - androidx.compose.foundation.*
|
||||||
│ └── foundation-layout/ → :compose:foundation:foundation-layout - androidx.compose.foundation.layout.*
|
│ └── foundation-layout/ → :compose:foundation:foundation-layout - androidx.compose.foundation.layout.*
|
||||||
├── material3/
|
├── material3/
|
||||||
│ └── material3/ → :compose:material3:material3 - androidx.compose.material3.*
|
│ ├── material3/ → :compose:material3:material3 - androidx.compose.material3.*
|
||||||
|
│ └── adaptive/ → the material3-adaptive family, VENDORED VERBATIM.
|
||||||
|
│ │ org.jetbrains.compose.material3.adaptive:* publishes
|
||||||
|
│ │ ios + macosArm64 ONLY - no linux, no mingw (issue #4).
|
||||||
|
│ │ Nothing in the sources blocks those targets: every
|
||||||
|
│ │ actual the native legs need already exists upstream
|
||||||
|
│ │ (nonAndroidMain / skikoMain / nativeMain), and the one
|
||||||
|
│ │ real dependency, androidx.window:window-core, ALREADY
|
||||||
|
│ │ publishes linux + mingw + macos. The artifacts were
|
||||||
|
│ │ missing purely because upstream never enabled the
|
||||||
|
│ │ targets - so this port is vendor-only, ZERO source
|
||||||
|
│ │ edits. Upstream's skikoMain (the ~75 l10n tables +
|
||||||
|
│ │ Strings / drag-handle actuals) lands in src/vendor/
|
||||||
|
│ │ native/ next to upstream's own nativeMain actuals;
|
||||||
|
│ │ they actualise disjoint expects so they coexist.
|
||||||
|
│ │ com.bitsycore.compose.material3.adaptive:<module>.
|
||||||
|
│ ├── adaptive/ → :compose:material3:adaptive:adaptive - WindowAdaptiveInfo /
|
||||||
|
│ │ Posture / window size class. api-exposes window-core.
|
||||||
|
│ ├── adaptive-layout/ → :compose:material3:adaptive:adaptive-layout - ListDetail /
|
||||||
|
│ │ SupportingPane / ThreePane scaffolds + pane motion
|
||||||
|
│ ├── adaptive-navigation/ → :compose:material3:adaptive:adaptive-navigation -
|
||||||
|
│ │ ThreePaneScaffoldNavigator + back behaviour
|
||||||
|
│ └── adaptive-navigation3/ → :compose:material3:adaptive:adaptive-navigation3 -
|
||||||
|
│ SceneStrategy bindings for nav3 (→ :navigation3-ui)
|
||||||
├── material/
|
├── material/
|
||||||
│ └── material-ripple/ → :compose:material:material-ripple - androidx.compose.material.ripple.*
|
│ └── material-ripple/ → :compose:material:material-ripple - androidx.compose.material.ripple.*
|
||||||
└── desktop/native/desktop-native-window/ → :compose:desktop:native:desktop-native-window - nativeComposeApp { Window(...) {} }
|
└── desktop/native/desktop-native-window/ → :compose:desktop:native:desktop-native-window - nativeComposeApp { Window(...) {} }
|
||||||
@@ -184,10 +207,14 @@ pulse/ → Pulse MVI. Upstream (bitsycore/pulse-mvi, PULSE_REF) ta
|
|||||||
├── pulse-viewmodel/ → :pulse:pulse-viewmodel - ViewModel binding
|
├── pulse-viewmodel/ → :pulse:pulse-viewmodel - ViewModel binding
|
||||||
├── pulse-savedstate/ → :pulse:pulse-savedstate - SavedStateHandle persistence
|
├── pulse-savedstate/ → :pulse:pulse-savedstate - SavedStateHandle persistence
|
||||||
└── pulse-compose/ → :pulse:pulse-compose - Compose bindings
|
└── pulse-compose/ → :pulse:pulse-compose - Compose bindings
|
||||||
Published as com.bitsycore.pulse:<module>, NOT
|
Published as com.bitsycore.compose.desktop.native
|
||||||
upstream's com.bitsycore.lib:<module> - the two
|
.pulse:<module>, NOT upstream's com.bitsycore.lib:
|
||||||
must not collide; the bridge substitutes the
|
<module>. Pulse is the one vendored dep that is
|
||||||
upstream coord on native configs.
|
ITSELF a com.bitsycore library, so the republish is
|
||||||
|
namespaced under this project rather than a bare
|
||||||
|
com.bitsycore.pulse that would read like upstream;
|
||||||
|
the bridge substitutes the upstream coord on
|
||||||
|
native configs.
|
||||||
|
|
||||||
navigation3/
|
navigation3/
|
||||||
└── navigation3-ui/ → :navigation3:navigation3-ui - androidx.navigation3.ui.* + scene machinery,
|
└── navigation3-ui/ → :navigation3:navigation3-ui - androidx.navigation3.ui.* + scene machinery,
|
||||||
@@ -304,6 +331,14 @@ sees the split modules. Full DAG: `:ui-util → collection`; `:ui-geometry → :
|
|||||||
`:foundation → :animation, :foundation-layout, :animation-core, :ui`;
|
`:foundation → :animation, :foundation-layout, :animation-core, :ui`;
|
||||||
`:material-ripple → :foundation, :animation-core`;
|
`:material-ripple → :foundation, :animation-core`;
|
||||||
`:material3 → :foundation, :material-ripple, :animation-core, :foundation-layout`.
|
`:material3 → :foundation, :material-ripple, :animation-core, :foundation-layout`.
|
||||||
|
The adaptive family sits beside material3 rather than under it - it depends on
|
||||||
|
`:ui` / `:foundation` / `:animation-core`, NOT on `:material3`:
|
||||||
|
`:adaptive → :ui, :foundation, window-core`;
|
||||||
|
`:adaptive-layout → :adaptive, :ui, :animation-core, :animation, :foundation,
|
||||||
|
:foundation-layout, :ui-geometry, collection, window-core`;
|
||||||
|
`:adaptive-navigation → :adaptive-layout, :foundation, :ui-util`;
|
||||||
|
`:adaptive-navigation3 → :adaptive-navigation, :navigation3-ui, collection,
|
||||||
|
navigationevent-compose`.
|
||||||
|
|
||||||
`:ui` is the Compose core + the Skia RenderBackend + the SDL↔Compose bridges; it
|
`:ui` is the Compose core + the Skia RenderBackend + the SDL↔Compose bridges; it
|
||||||
sits on `:ui-graphics` / `:ui-text` (the graphics/text primitives + their skiko
|
sits on `:ui-graphics` / `:ui-text` (the graphics/text primitives + their skiko
|
||||||
@@ -566,8 +601,18 @@ drift / vendor-clean guardrails are in
|
|||||||
## Key files by area - start here when you need to find something
|
## Key files by area - start here when you need to find something
|
||||||
|
|
||||||
### Renderer + main loop
|
### Renderer + main loop
|
||||||
- `compose/desktop/native/desktop-native-window/src/nativeMain/…/ComposeWindow.kt` - main loop,
|
- `compose/desktop/native/desktop-native-window/src/nativeMain/…/` - the window
|
||||||
recomposer lifecycle, SDL event dispatch, composition-local seeding.
|
module, one concern per file:
|
||||||
|
- `ComposeWindow.kt` - the PUBLIC surface (`ApplicationScope`, `Window()`,
|
||||||
|
`nativeComposeApp`, `nativeComposeWindow`) + the main loop.
|
||||||
|
- `WindowInstance.kt` - one SDL window: backend + render backend + root host +
|
||||||
|
its own recomposer/composition, event handling, frame pump, teardown. This is
|
||||||
|
where composition-local seeding lives.
|
||||||
|
- `AppRuntime.kt` - the live-window registry + create/destroy lifecycle.
|
||||||
|
- `WindowAttributes.kt` - the Compose Desktop `Window()` attribute bundle.
|
||||||
|
- `FrameTiming.kt` - deterministic/virtual frame clocks and the
|
||||||
|
probe-quiescence hooks (`disableInfiniteAnimations`, `useVirtualFrameTime`,
|
||||||
|
`windowHasInvalidations`).
|
||||||
- `compose/ui/ui/src/nativeMain/…/RenderBackend.kt` - the interface.
|
- `compose/ui/ui/src/nativeMain/…/RenderBackend.kt` - the interface.
|
||||||
- `compose/ui/ui/src/nativeMain/…/GpuMode.kt` - sealed driver picker
|
- `compose/ui/ui/src/nativeMain/…/GpuMode.kt` - sealed driver picker
|
||||||
(`Auto` / `Software` / `Skia.OpenGL` / `Skia.Metal`).
|
(`Auto` / `Software` / `Skia.OpenGL` / `Skia.Metal`).
|
||||||
@@ -632,9 +677,23 @@ Open renderer / fidelity / release work is tracked in [PLAN.md](PLAN.md).
|
|||||||
|
|
||||||
## Conventions
|
## Conventions
|
||||||
|
|
||||||
Kotlin standard style - plain `camelCase` for parameters, local variables,
|
Kotlin standard style for formatting (braces, wrapping, indentation).
|
||||||
and fields. **No `f`/`in`/`v` prefixes**, no SPIRTECH scheme (see the global
|
|
||||||
CLAUDE.md - that scheme is C-only).
|
Naming, as the code actually is - this paragraph used to claim "no prefixes",
|
||||||
|
which had not been true for a long time:
|
||||||
|
|
||||||
|
- **`m` for private/protected members** - `mWidth`, `mSurface`, `mCache`. NOT
|
||||||
|
`f`: the `f` prefix was retired across the project, so do not reintroduce it.
|
||||||
|
- **`v` for local variables** - `vWindow`, `vResult`.
|
||||||
|
- **`in` for function parameters** - `inTitle`, `inWidth`. Note Compose
|
||||||
|
`@Composable` parameters are the exception: they stay plain, because the name
|
||||||
|
is part of the call-site API (`title = `, `onCloseRequest = `).
|
||||||
|
- **`k` for private file-level constants** - `kMaxFrames`, `kIsWindows`.
|
||||||
|
- Public API surface is plain `camelCase` - prefixes are for implementation
|
||||||
|
detail only, and nothing prefixed should ever reach the klib dump.
|
||||||
|
|
||||||
|
VENDORED code under `src/vendor/` follows UPSTREAM's naming, untouched - it is
|
||||||
|
copied byte-for-byte, so never re-prefix anything in it.
|
||||||
|
|
||||||
Section headers inside a file, when useful:
|
Section headers inside a file, when useful:
|
||||||
|
|
||||||
@@ -725,6 +784,11 @@ Verified in-tree (api-exposed by `:ui` unless noted):
|
|||||||
- `androidx.navigationevent:navigationevent-compose` 1.1.2 - predictive-back
|
- `androidx.navigationevent:navigationevent-compose` 1.1.2 - predictive-back
|
||||||
event plumbing (BackHandler, NavDisplay gestures).
|
event plumbing (BackHandler, NavDisplay gestures).
|
||||||
- `androidx.collection:collection` - plain Maven dep, not a module.
|
- `androidx.collection:collection` - plain Maven dep, not a module.
|
||||||
|
- `androidx.window:window-core` **1.5.0** - WindowSizeClass / the adaptive
|
||||||
|
window model. Publishes mingwX64 + linux + macos under BOTH coordinate sets;
|
||||||
|
the port takes the google one like the rest of the androidx stack. This is
|
||||||
|
what makes the material3-adaptive vendoring a pure re-target: the dependency
|
||||||
|
everybody assumed was the blocker was never missing.
|
||||||
- `io.insert-koin:koin-core` **4.2.2** - the DI container itself publishes
|
- `io.insert-koin:koin-core` **4.2.2** - the DI container itself publishes
|
||||||
mingwX64 + linux + macos. Only Koin's viewmodel / compose layers stop at
|
mingwX64 + linux + macos. Only Koin's viewmodel / compose layers stop at
|
||||||
apple+android and are vendored (`koin/`).
|
apple+android and are vendored (`koin/`).
|
||||||
@@ -752,7 +816,7 @@ Caveats that make these work here (all already wired - listed so nobody
|
|||||||
- The google `LocalViewModelStoreOwner` / `LocalSavedStateRegistryOwner` /
|
- The google `LocalViewModelStoreOwner` / `LocalSavedStateRegistryOwner` /
|
||||||
`LocalLifecycleOwner` are PLAIN composition locals - the JB HostDefault
|
`LocalLifecycleOwner` are PLAIN composition locals - the JB HostDefault
|
||||||
mechanism (`compositionLocalWithHostDefaultOf`) does not exist in google
|
mechanism (`compositionLocalWithHostDefaultOf`) does not exist in google
|
||||||
artifacts. `WindowArchitectureOwner` (ComposeWindow.kt) provides all three
|
artifacts. `WindowArchitectureOwner` (WindowInstance.kt) provides all three
|
||||||
per window, mirrors upstream desktop's DefaultArchitectureComponentsOwner,
|
per window, mirrors upstream desktop's DefaultArchitectureComponentsOwner,
|
||||||
calls `enableSavedStateHandles()` at construction, and follows SDL focus /
|
calls `enableSavedStateHandles()` at construction, and follows SDL focus /
|
||||||
visibility (focused → RESUMED, unfocused → STARTED, minimised → CREATED).
|
visibility (focused → RESUMED, unfocused → STARTED, minimised → CREATED).
|
||||||
|
|||||||
@@ -391,21 +391,21 @@ re-vendoring.** The debt is **completing native-actual stubs**.
|
|||||||
### P0 - blocks fidelity/correctness
|
### P0 - blocks fidelity/correctness
|
||||||
|
|
||||||
- [~] **P0** Text context menu (right-click copy/paste/select-all) - **RECONCILED: already
|
- [~] **P0** Text context menu (right-click copy/paste/select-all) - **RECONCILED: already
|
||||||
works, no reimplementation.** Static trace confirmed the menu is wired end-to-end
|
works, no reimplementation.** Static trace confirmed the menu is wired end-to-end
|
||||||
through the vendored LEGACY path: text-level `ContextMenuArea` (`ContextMenu.native.kt`)
|
through the vendored LEGACY path: text-level `ContextMenuArea` (`ContextMenu.native.kt`)
|
||||||
→ `CommonContextMenuArea` (`vendor/common/.../text/CommonContextMenuArea.kt`) → (native
|
→ `CommonContextMenuArea` (`vendor/common/.../text/CommonContextMenuArea.kt`) → (native
|
||||||
`ComposeFoundationFlags.isNewContextMenuEnabled = false`, so the legacy branch) →
|
`ComposeFoundationFlags.isNewContextMenuEnabled = false`, so the legacy branch) →
|
||||||
`contextmenu.ContextMenuArea` → `contextMenuGestures`/`onRightClickDown`
|
`contextmenu.ContextMenuArea` → `contextMenuGestures`/`onRightClickDown`
|
||||||
(`isSecondaryPressed`) → `ContextMenuPopup` → `Popup.native.kt` (hosted by
|
(`isSecondaryPressed`) → `ContextMenuPopup` → `Popup.native.kt` (hosted by
|
||||||
`LocalPopupHost` at the app root). Items are real: `TextFieldSelectionManager` /
|
`LocalPopupHost` at the app root). Items are real: `TextFieldSelectionManager` /
|
||||||
`SelectionManager.contextMenuBuilder` emit Cut/Copy/Paste/SelectAll with real actions.
|
`SelectionManager.contextMenuBuilder` emit Cut/Copy/Paste/SelectAll with real actions.
|
||||||
SDL right-click → `PointerButton.Secondary` (`SDL3EventMapper.kt`) →
|
SDL right-click → `PointerButton.Secondary` (`AppEvent.kt`) →
|
||||||
`isSecondaryPressed` (`PointerEventBridge`). The three "NOP" seams belong to the
|
`isSecondaryPressed` (`PointerEventBridge`). The three "NOP" seams belong to the
|
||||||
DISABLED *new* context-menu API and are unreachable - **DONE:** their misleading
|
DISABLED *new* context-menu API and are unreachable - **DONE:** their misleading
|
||||||
`TODO(CMP-7819)` comments corrected to say so, in all three files.
|
`TODO(CMP-7819)` comments corrected to say so, in all three files.
|
||||||
**REMAINING:** an interactive right-click smoke check (no headless driver here - fold
|
**REMAINING:** an interactive right-click smoke check (no headless driver here - fold
|
||||||
into manual/WIN-SMOKE). Known limitation, not a breakage: Paste enablement is
|
into manual/WIN-SMOKE). Known limitation, not a breakage: Paste enablement is
|
||||||
plain-text-only (`ClipboardPasteState.hasClip = hasText`, see P2 below).
|
plain-text-only (`ClipboardPasteState.hasClip = hasText`, see P2 below).
|
||||||
- [ ] **P1** DatePicker/TimePicker localization - VERIFIED current state:
|
- [ ] **P1** DatePicker/TimePicker localization - VERIFIED current state:
|
||||||
`material3/.../internal/PlatformDateFormat.native.kt` is a real kotlinx-datetime
|
`material3/.../internal/PlatformDateFormat.native.kt` is a real kotlinx-datetime
|
||||||
formatter that DOES honor CLDR patterns/skeletons (renders "Jul 29, 2026" /
|
formatter that DOES honor CLDR patterns/skeletons (renders "Jul 29, 2026" /
|
||||||
@@ -417,14 +417,14 @@ re-vendoring.** The debt is **completing native-actual stubs**.
|
|||||||
(author):** bundle a CLDR subset or K/N i18n lib for localized names + locale-aware
|
(author):** bundle a CLDR subset or K/N i18n lib for localized names + locale-aware
|
||||||
first-day/24h; also unblocks `CalendarLocale.native.kt:20` (fixed `"en"`). Ships
|
first-day/24h; also unblocks `CalendarLocale.native.kt:20` (fixed `"en"`). Ships
|
||||||
readable English dates today - polish, not a P0 gate.
|
readable English dates today - polish, not a P0 gate.
|
||||||
- [x] **P0** Float pointer coordinates - `SDL3EventMapper.kt` `.toInt()`-truncated SDL's
|
- [x] **P0** Float pointer coordinates - `AppEvent.kt` `.toInt()`-truncated SDL's
|
||||||
Float `mb.x`/`mb.y`/`mm.x`/`mm.y` and the wheel `mouse_x/y` before the DPR multiply in
|
Float `mb.x`/`mb.y`/`mm.x`/`mm.y` and the wheel `mouse_x/y` before the DPR multiply in
|
||||||
`ComposeWindow.kt`. On 2× displays a click at logical 100.9 → physical 200 not ~201,
|
`ComposeWindow.kt`. On 2× displays a click at logical 100.9 → physical 200 not ~201,
|
||||||
quantizing the caret to 2px steps near glyph edges. **DONE:** widened
|
quantizing the caret to 2px steps near glyph edges. **DONE:** widened
|
||||||
`LegacyPointerEvent.x/y` and `AppEvent.MouseWheel.x/y` to `Float`, dropped the
|
`LegacyPointerEvent.x/y` and `AppEvent.MouseWheel.x/y` to `Float`, dropped the
|
||||||
`.toInt()` at the three mapper construction sites, and removed the now-redundant
|
`.toInt()` at the three mapper construction sites, and removed the now-redundant
|
||||||
`.toFloat()` at the two `ComposeWindow` read sites. Consumers fully contained (verified
|
`.toFloat()` at the two `ComposeWindow` read sites. Consumers fully contained (verified
|
||||||
by grep). Builds + runs clean on macosArm64.
|
by grep). Builds + runs clean on macosArm64.
|
||||||
|
|
||||||
### P1 - quality / parity
|
### P1 - quality / parity
|
||||||
|
|
||||||
@@ -521,7 +521,7 @@ re-vendoring.** The debt is **completing native-actual stubs**.
|
|||||||
Static lib built from source per host (`scripts/build-sdl/build-all.py`, ref
|
Static lib built from source per host (`scripts/build-sdl/build-all.py`, ref
|
||||||
`release-3.4.12`); linked into the exe via `sdl3.def` (`staticLibraries=libSDL3.a`). Today
|
`release-3.4.12`); linked into the exe via `sdl3.def` (`staticLibraries=libSDL3.a`). Today
|
||||||
only tests/examples + Windows D3D12/GPU are off (`build-all.py:311-319`). `SDL_Init` uses
|
only tests/examples + Windows D3D12/GPU are off (`build-all.py:311-319`). `SDL_Init` uses
|
||||||
**`SDL_INIT_VIDEO` only** (`SDL3Backend.kt:49`).
|
**`SDL_INIT_VIDEO` only** (`Sdl3Backend.kt:49`).
|
||||||
|
|
||||||
**USED (keep ON):** Video/window, Events, Clipboard, Dialog (file open/save - no cheaper
|
**USED (keep ON):** Video/window, Events, Clipboard, Dialog (file open/save - no cheaper
|
||||||
substitute; Linux uses portal/zenity, keep deps), OpenGL + Metal contexts, Render (2D CPU-
|
substitute; Linux uses portal/zenity, keep deps), OpenGL + Metal contexts, Render (2D CPU-
|
||||||
@@ -554,7 +554,7 @@ joystick.
|
|||||||
disabled SDL subsystems.)
|
disabled SDL subsystems.)
|
||||||
- [ ] **P2** (higher-risk, flag-don't-apply) Render-driver pruning to software-only. Only
|
- [ ] **P2** (higher-risk, flag-don't-apply) Render-driver pruning to software-only. Only
|
||||||
the CPU-raster fallback uses `SDL_Render`; GL/Metal go direct. But
|
the CPU-raster fallback uses `SDL_Render`; GL/Metal go direct. But
|
||||||
`SDL_CreateRenderer(window, null)` (`SDL3Backend.kt:117`) lets SDL pick the first
|
`SDL_CreateRenderer(window, null)` (`Sdl3Backend.kt:117`) lets SDL pick the first
|
||||||
driver - with only software present it picks software (fine) but couples the fallback
|
driver - with only software present it picks software (fine) but couples the fallback
|
||||||
to that assumption. **Conservative: leave render drivers alone.**
|
to that assumption. **Conservative: leave render drivers alone.**
|
||||||
|
|
||||||
@@ -727,6 +727,30 @@ A read-only feasibility map (no code changed) found two layers:
|
|||||||
proves infeasible, fall back to keeping the seam but at least converting the hand files to tracked
|
proves infeasible, fall back to keeping the seam but at least converting the hand files to tracked
|
||||||
Rule-3 vendors (like `FontRasterizationSettings.native.kt` now has a `VENDOR-BASE` line).
|
Rule-3 vendors (like `FontRasterizationSettings.native.kt` now has a `VENDOR-BASE` line).
|
||||||
|
|
||||||
|
### 7c. `demo --multiwintest` segfault on mingwX64 - ✅ FIXED
|
||||||
|
|
||||||
|
The multi-window probe exited 139 with no output, so it had silently been
|
||||||
|
asserting nothing. Root cause: an OpenGL context is per-WINDOW but "current" is
|
||||||
|
per-THREAD, and `SDL_GL_MakeCurrent` ran only once at creation
|
||||||
|
(`Sdl3Backend.init`) with nothing re-binding it per frame. With two windows open,
|
||||||
|
whichever initialised last owned the thread - so window A issued its draw and
|
||||||
|
swap against window B's context (silent corruption while both lived), and
|
||||||
|
destroying B left the current context dangling, faulting in `present()`.
|
||||||
|
|
||||||
|
Fixed in `SkiaGLBridge` by binding the window's own context at every entry point
|
||||||
|
that touches GL: `init`, `ensureSize` (before its unchanged-size early return -
|
||||||
|
this is the per-frame bind that covers the draw phase), `present`, and `destroy`
|
||||||
|
(so a window frees its GPU objects against its own context). Purely additive, 29
|
||||||
|
lines.
|
||||||
|
|
||||||
|
Single-window rendering is bit-identical before and after (same mean RGB
|
||||||
|
[46.6 44.4 51.5] and 167 distinct colours on the Buttons screenshot), which is
|
||||||
|
expected: SDL short-circuits a redundant bind. `--multiwintest` now PASSes.
|
||||||
|
|
||||||
|
NOTE the multi-window path was never correct, not just at teardown - two live
|
||||||
|
windows were sharing one context. Anything that looked like flicker or
|
||||||
|
cross-window corruption before this is explained by it.
|
||||||
|
|
||||||
## Accepted 1.0.0 gaps (documented, not fixed)
|
## Accepted 1.0.0 gaps (documented, not fixed)
|
||||||
|
|
||||||
Drag-OUT of window (SDL platform limit; drop-IN works), full accessibility pipeline (out of
|
Drag-OUT of window (SDL platform limit; drop-IN works), full accessibility pipeline (out of
|
||||||
@@ -735,6 +759,52 @@ hand-rolled text engine as an architectural deviation (§2 P1), per-focus
|
|||||||
`SDL_StartTextInput/StopTextInput`, `loadImageBitmap`/`loadSvgPainter` (JVM `InputStream`
|
`SDL_StartTextInput/StopTextInput`, `loadImageBitmap`/`loadSvgPainter` (JVM `InputStream`
|
||||||
signatures, N/A on K/N).
|
signatures, N/A on K/N).
|
||||||
|
|
||||||
|
## 8. material3-adaptive ported to desktop native (2026-09-22) - ✅ LANDED
|
||||||
|
|
||||||
|
Asked for in [issue #4](https://github.com/bitsycore/compose-desktop-native/issues/4):
|
||||||
|
`org.jetbrains.compose.material3.adaptive:*` 1.3.0-rc01 publishes `ios_arm64
|
||||||
|
ios_simulator_arm64 macos_arm64` and nothing else - no linux, no mingw. (It DOES
|
||||||
|
carry macosArm64, which answers the reporter's open question.)
|
||||||
|
|
||||||
|
**The port needed zero source edits.** Two things made it a pure re-target:
|
||||||
|
|
||||||
|
1. Every platform actual the native legs want already exists upstream -
|
||||||
|
`adaptive/nonAndroidMain` (`calculatePosture`), `adaptive-layout/skikoMain`
|
||||||
|
(the ~75 l10n tables + `Strings` + the drag handle) and
|
||||||
|
`adaptive-layout/nativeMain` (`identityHashCode`, `isGraphicsLayerElement`).
|
||||||
|
2. `androidx.window:window-core` - the dependency `adaptive` api-exposes, and the
|
||||||
|
obvious suspect for why the artifacts stop at apple - has published
|
||||||
|
`linux_x64 linux_arm64 mingw_x64 macos_arm64` klibs all along, under BOTH the
|
||||||
|
google and jetbrains coordinates.
|
||||||
|
|
||||||
|
So the artifacts were missing purely because upstream never enabled the targets.
|
||||||
|
|
||||||
|
**Landed** as four modules under `compose/material3/adaptive/`
|
||||||
|
(`com.bitsycore.compose.material3.adaptive:*`), 125 files vendored verbatim off the
|
||||||
|
existing `COMPOSE_CORE_REF` pin - no new SET_REPO. Upstream's `skikoMain` lands in
|
||||||
|
`src/vendor/native/` beside upstream's own `nativeMain`; they actualise disjoint
|
||||||
|
expects so they share one source set. Both bridges substitute all four. `demo --screen=Adaptive` renders a
|
||||||
|
`ListDetailPaneScaffold`, and `demo --adaptivetest` drives one window
|
||||||
|
wide -> narrow -> wide and asserts the scaffold folds and unfolds, which is what
|
||||||
|
actually proves the resize chain end to end (SDL resize -> the owner's
|
||||||
|
snapshot-backed containerSize -> recomposition -> BoxWithConstraints re-measure ->
|
||||||
|
a new PaneScaffoldDirective -> a new scaffold value).
|
||||||
|
|
||||||
|
The demo screen computes its directive from the width IT gets rather than taking
|
||||||
|
the `rememberListDetailPaneScaffoldNavigator` default, which is the window size
|
||||||
|
class: the shell spends 190dp on the sidebar plus 48dp of padding, so defaulting
|
||||||
|
folds ~240dp too late and leaves two panes in a region already too cramped for
|
||||||
|
them. Pane-hosting apps that are not full-window should do the same.
|
||||||
|
|
||||||
|
One wrinkle worth remembering, and a textbook case of the granular-metadata trap
|
||||||
|
already documented in CLAUDE.md: because `adaptive` is SUBSTITUTED on native
|
||||||
|
configs, KGP drops its transitives from the commonMain metadata classpath, so the
|
||||||
|
shared demo screen could not see `WindowSizeClass` until `window-core` was declared
|
||||||
|
DIRECTLY in `demo`'s commonMain.
|
||||||
|
|
||||||
|
Not yet exercised: `adaptive-navigation3` builds and dumps API but has no demo
|
||||||
|
screen - the nav3 SceneStrategy path is unproven at runtime.
|
||||||
|
|
||||||
## 7. Post-1.12.0 open items (opened 2026-09-12)
|
## 7. Post-1.12.0 open items (opened 2026-09-12)
|
||||||
|
|
||||||
### 7a. JVM parity reference used a DIFFERENT default font than native - ✅ FIXED
|
### 7a. JVM parity reference used a DIFFERENT default font than native - ✅ FIXED
|
||||||
@@ -813,6 +883,18 @@ Two residuals, neither a text-metrics bug:
|
|||||||
(0.29% at +0px vs 2.13% at +1px), where before +2px halved the error. The residual 0.29%
|
(0.29% at +0px vs 2.13% at +1px), where before +2px halved the error. The residual 0.29%
|
||||||
is rasterizer AA.
|
is rasterizer AA.
|
||||||
|
|
||||||
|
- **Icon-font glyphs rendered LOW - ✅ FIXED.** Material Symbols sat 2-4px lower on native
|
||||||
|
than on jvm, the offset scaling with icon size (~13% of it). Cause: the JVM actual centres
|
||||||
|
the glyph explicitly (`y = height/2 - (ascent+descent)/2`), while `IconFontIcon` placed
|
||||||
|
`IconText` in a Box at the DEFAULT TopStart alignment - and the glyph's natural text box is
|
||||||
|
taller than the nominal icon size. Fixed by centring, with
|
||||||
|
`wrapContentSize(unbounded = true)` so the text measures at its natural size first:
|
||||||
|
`Modifier.size()` imposes FIXED constraints, so without it nothing overflows and
|
||||||
|
contentAlignment is a no-op (a first attempt without it changed literally nothing).
|
||||||
|
gear/download/lock are now pixel-exact; the eye is 1px off from half-pixel rounding (odd
|
||||||
|
glyph height centred in an even box; jvm draws at a float y, native placement is integer).
|
||||||
|
Whole-window >32/255 drift 0.29% -> 0.17%.
|
||||||
|
|
||||||
- **Missing glyph in the session header.** The leading icon next to "Untitled session"
|
- **Missing glyph in the session header.** The leading icon next to "Untitled session"
|
||||||
renders as a `.notdef` TOFU on jvm and as NOTHING on native - so the glyph is absent from
|
renders as a `.notdef` TOFU on jvm and as NOTHING on native - so the glyph is absent from
|
||||||
the subsetted Material Symbols font on both, and the two stacks just disagree on how to
|
the subsetted Material Symbols font on both, and the two stacks just disagree on how to
|
||||||
@@ -850,7 +932,7 @@ WRONG - both coordinate sets publish mingwX64 + linux + macos, and the port alre
|
|||||||
CLAUDE.md, exercised by `demo --backtest`). Nothing to vendor there.
|
CLAUDE.md, exercised by `demo --backtest`). Nothing to vendor there.
|
||||||
|
|
||||||
**Landed** as `koin/` (4 modules, `com.bitsycore.koin`), `coil/` (7 modules,
|
**Landed** as `koin/` (4 modules, `com.bitsycore.koin`), `coil/` (7 modules,
|
||||||
`com.bitsycore.coil3`) and `pulse/` (4 modules, `com.bitsycore.pulse`) - 202 files vendored
|
`com.bitsycore.coil3`) and `pulse/` (4 modules, `com.bitsycore.compose.desktop.native.pulse`) - 202 files vendored
|
||||||
verbatim across three new pinned repos (`KOIN_REF=4.2.2`, `COIL_REF=3.6.2`,
|
verbatim across three new pinned repos (`KOIN_REF=4.2.2`, `COIL_REF=3.6.2`,
|
||||||
`PULSE_REF=0.3.7`), ZERO local source edits. All build for mingwX64 + linuxX64/arm64, are
|
`PULSE_REF=0.3.7`), ZERO local source edits. All build for mingwX64 + linuxX64/arm64, are
|
||||||
BCV-dumped, publish, and carry bridge substitution rules so consumers keep declaring the
|
BCV-dumped, publish, and carry bridge substitution rules so consumers keep declaring the
|
||||||
|
|||||||
@@ -71,6 +71,23 @@ Each window gets its own `Lifecycle`, `ViewModelStore`, and `SavedStateRegistry`
|
|||||||
owners, driven by real SDL focus and visibility events, so ViewModels and
|
owners, driven by real SDL focus and visibility events, so ViewModels and
|
||||||
saved state behave as they do on Android.
|
saved state behave as they do on Android.
|
||||||
|
|
||||||
|
`Window()` takes the same attributes as Compose Desktop's - `undecorated`,
|
||||||
|
`transparent`, `resizable`, `enabled`, `focusable`, `alwaysOnTop`,
|
||||||
|
`onPreviewKeyEvent` and `onKeyEvent` - and re-applies them when they change.
|
||||||
|
(`transparent` is the one exception: SDL needs it at window-creation time, so it
|
||||||
|
is fixed for the window's life.)
|
||||||
|
|
||||||
|
When the Compose-level API doesn't reach far enough, drop to SDL directly:
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val handles = window.rawSdlHandles() // SDL_Window* / SDL_Renderer* / GL / Metal
|
||||||
|
handles.window?.let { sdl3.SDL_FlashWindow(it.reinterpret(), SDL_FLASH_BRIEFLY) }
|
||||||
|
```
|
||||||
|
|
||||||
|
The pointers are a snapshot valid only while the window lives, and which ones
|
||||||
|
are non-null depends on the resolved renderer (`glContext` for Skia OpenGL,
|
||||||
|
`metalView` for Metal, `renderer` for CPU raster).
|
||||||
|
|
||||||
### Building in this repo
|
### Building in this repo
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
@@ -101,11 +118,21 @@ plugins {
|
|||||||
|
|
||||||
commonMain.dependencies {
|
commonMain.dependencies {
|
||||||
// The plugin exposes the exact Compose versions the port tracks, so you
|
// The plugin exposes the exact Compose versions the port tracks, so you
|
||||||
// never hand-match them (material3 is versioned separately upstream).
|
// never hand-match them (material3 and material3-adaptive each ride their
|
||||||
|
// own release train upstream).
|
||||||
implementation("org.jetbrains.compose.runtime:runtime:${composeDesktopNative.composeRuntime}")
|
implementation("org.jetbrains.compose.runtime:runtime:${composeDesktopNative.composeRuntime}")
|
||||||
implementation("org.jetbrains.compose.ui:ui:${composeDesktopNative.compose}")
|
implementation("org.jetbrains.compose.ui:ui:${composeDesktopNative.compose}")
|
||||||
implementation("org.jetbrains.compose.foundation:foundation:${composeDesktopNative.compose}")
|
implementation("org.jetbrains.compose.foundation:foundation:${composeDesktopNative.compose}")
|
||||||
implementation("org.jetbrains.compose.material3:material3:${composeDesktopNative.composeMaterial3}")
|
implementation("org.jetbrains.compose.material3:material3:${composeDesktopNative.composeMaterial3}")
|
||||||
|
|
||||||
|
// material3-adaptive, which upstream publishes for apple targets only.
|
||||||
|
// Note adaptive api-exposes androidx.window:window-core - declare it
|
||||||
|
// DIRECTLY if your commonMain touches WindowSizeClass, since substituted
|
||||||
|
// modules hide their transitives from the common metadata classpath.
|
||||||
|
val vAdaptive = composeDesktopNative.composeMaterial3Adaptive
|
||||||
|
implementation("org.jetbrains.compose.material3.adaptive:adaptive:$vAdaptive")
|
||||||
|
implementation("org.jetbrains.compose.material3.adaptive:adaptive-layout:$vAdaptive")
|
||||||
|
implementation("androidx.window:window-core:1.5.0")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -168,7 +195,8 @@ targets, so you keep writing against the official coordinates:
|
|||||||
| `components-resources`, `navigation3-ui` | no mingwX64 / linux klibs | `com.bitsycore.compose.components`, `com.bitsycore.navigation3` |
|
| `components-resources`, `navigation3-ui` | no mingwX64 / linux klibs | `com.bitsycore.compose.components`, `com.bitsycore.navigation3` |
|
||||||
| **Koin** viewmodel + compose modules | apple + android only upstream (`koin-core` itself is fine) | `com.bitsycore.koin` |
|
| **Koin** viewmodel + compose modules | apple + android only upstream (`koin-core` itself is fine) | `com.bitsycore.koin` |
|
||||||
| **Coil 3** (whole stack) | no mingwX64 anywhere; no desktop native at all for its compose layer | `com.bitsycore.coil3` |
|
| **Coil 3** (whole stack) | no mingwX64 anywhere; no desktop native at all for its compose layer | `com.bitsycore.coil3` |
|
||||||
| **Pulse MVI** | no desktop-native artifact upstream | `com.bitsycore.pulse` |
|
| **Pulse MVI** | no desktop-native artifact upstream | `com.bitsycore.compose.desktop.native.pulse` |
|
||||||
|
| **material3-adaptive** (all four) | ios + macosArm64 only upstream - no linux, no mingw | `com.bitsycore.compose.material3.adaptive` |
|
||||||
|
|
||||||
The bridge plugin substitutes each of these on native desktop configurations, so
|
The bridge plugin substitutes each of these on native desktop configurations, so
|
||||||
app code declares `io.insert-koin:koin-compose`, `io.coil-kt.coil3:coil-compose`
|
app code declares `io.insert-koin:koin-compose`, `io.coil-kt.coil3:coil-compose`
|
||||||
@@ -196,8 +224,8 @@ one (`savedstate`, below).
|
|||||||
|
|
||||||
| | Version | Notes |
|
| | Version | Notes |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| Kotlin | **2.4.20** | Newer than the 2.3.20 CMP 1.12.0 is built with. Kotlin/Native consumes older klibs fine, and the whole port builds clean on 2.4.20 with no klib API diff, so there is no reason to hold back. |
|
| Kotlin | **2.4.20** | Newer than the 2.3.20 CMP 1.12.1 is built with. Kotlin/Native consumes older klibs fine, and the whole port builds clean on 2.4.20 with no klib API diff, so there is no reason to hold back. |
|
||||||
| Compose Multiplatform | **1.12.0** | The vendored sources are the `v1.12.0` tag of both upstream repos, and the JVM parity leg forces the same version - no dev-build skew. |
|
| Compose Multiplatform | **1.12.1** | The vendored sources are the `v1.12.1` tag of both upstream repos, and the JVM parity leg forces the same version - no dev-build skew. skiko is unchanged at 0.150.1, so the mingwX64 fork still matches its Skia base. |
|
||||||
| SDL3 | **release-3.4.16** | Built from source as a static lib per host (`scripts/build-sdl/build-all.py`), linked into the executable. |
|
| SDL3 | **release-3.4.16** | Built from source as a static lib per host (`scripts/build-sdl/build-all.py`), linked into the executable. |
|
||||||
| Skiko | **0.150.1** | macOS / Linux use the official `org.jetbrains.skiko`. |
|
| Skiko | **0.150.1** | macOS / Linux use the official `org.jetbrains.skiko`. |
|
||||||
| Skiko (Windows fork) | **0.150.1-mingw.2** | `com.bitsycore.skiko:skiko` - Skiko + Skia in `skiko-windows-x64.dll`. Same Skia base as the official build. Public repo, no auth. |
|
| Skiko (Windows fork) | **0.150.1-mingw.2** | `com.bitsycore.skiko:skiko` - Skiko + Skia in `skiko-windows-x64.dll`. Same Skia base as the official build. Public repo, no auth. |
|
||||||
@@ -210,19 +238,31 @@ the bridge plugin and you keep declaring the **official** coordinate.
|
|||||||
|
|
||||||
| Library | Official coordinate | Port coordinate |
|
| Library | Official coordinate | Port coordinate |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| Runtime | `org.jetbrains.compose.runtime:runtime*:1.12.0` | *not forked - the official klibs serve every target* |
|
| Runtime | `org.jetbrains.compose.runtime:runtime*:1.12.1` | *not forked - the official klibs serve every target* |
|
||||||
| UI | `org.jetbrains.compose.ui:ui*:1.12.0` | `com.bitsycore.compose.ui:ui*` |
|
| UI | `org.jetbrains.compose.ui:ui*:1.12.1` | `com.bitsycore.compose.ui:ui*` |
|
||||||
| Foundation | `org.jetbrains.compose.foundation:foundation*:1.12.0` | `com.bitsycore.compose.foundation:foundation*` |
|
| Foundation | `org.jetbrains.compose.foundation:foundation*:1.12.1` | `com.bitsycore.compose.foundation:foundation*` |
|
||||||
| Animation | `org.jetbrains.compose.animation:animation*:1.12.0` | `com.bitsycore.compose.animation:animation*` |
|
| Animation | `org.jetbrains.compose.animation:animation*:1.12.1` | `com.bitsycore.compose.animation:animation*` |
|
||||||
| Material Ripple | `org.jetbrains.compose.material:material-ripple:1.12.0` | `com.bitsycore.compose.material:material-ripple` |
|
| Material Ripple | `org.jetbrains.compose.material:material-ripple:1.12.1` | `com.bitsycore.compose.material:material-ripple` |
|
||||||
| Material3 | `org.jetbrains.compose.material3:material3:1.12.0-alpha03` | `com.bitsycore.compose.material3:material3` |
|
| Material3 | `org.jetbrains.compose.material3:material3:1.12.0-alpha03` | `com.bitsycore.compose.material3:material3` |
|
||||||
| Resources | `org.jetbrains.compose.components:components-resources:1.12.0` | `com.bitsycore.compose.components:components-resources` |
|
| Material3 Adaptive | `org.jetbrains.compose.material3.adaptive:adaptive*:1.3.0-rc01` | `com.bitsycore.compose.material3.adaptive:adaptive*` |
|
||||||
|
| Resources | `org.jetbrains.compose.components:components-resources:1.12.1` | `com.bitsycore.compose.components:components-resources` |
|
||||||
| Navigation3 UI | `org.jetbrains.androidx.navigation3:navigation3-ui` | `com.bitsycore.navigation3:navigation3-ui` |
|
| Navigation3 UI | `org.jetbrains.androidx.navigation3:navigation3-ui` | `com.bitsycore.navigation3:navigation3-ui` |
|
||||||
| Window shell | *no upstream equivalent* | `com.bitsycore.compose:desktop-native-window` |
|
| Window shell | *no upstream equivalent* | `com.bitsycore.compose:desktop-native-window` |
|
||||||
| SDL layer | *no upstream equivalent* | `com.bitsycore.compose.sdl:sdl-core` |
|
| SDL layer | *no upstream equivalent* | `com.bitsycore.compose.sdl:sdl-core` |
|
||||||
|
|
||||||
Material3 rides its own release train upstream: `1.12.0-alpha03` **is** the
|
Material3 rides its own release train upstream: `1.12.0-alpha03` **is** the
|
||||||
version Compose Multiplatform 1.12.0 ships (Jetpack Material3 1.5.0-alpha22).
|
version Compose Multiplatform 1.12.1 ships (Jetpack Material3 1.5.0-alpha22).
|
||||||
|
material3-adaptive rides a third train again.
|
||||||
|
|
||||||
|
**material3-adaptive** (`adaptive`, `adaptive-layout`, `adaptive-navigation`,
|
||||||
|
`adaptive-navigation3`) is published upstream for ios and macosArm64 only - no
|
||||||
|
linux, no mingw. This port ships all four for every desktop-native target. It
|
||||||
|
needed no source changes at all: every platform actual the native legs want is
|
||||||
|
already in upstream's `nonAndroidMain` / `skikoMain` / `nativeMain`, and
|
||||||
|
`androidx.window:window-core` - the one dependency involved - has published
|
||||||
|
linux, mingw and macos klibs the whole time. The artifacts were missing only
|
||||||
|
because upstream never turned the targets on. `demo --screen=Adaptive` renders
|
||||||
|
a live `ListDetailPaneScaffold`.
|
||||||
|
|
||||||
### Ecosystem libraries
|
### Ecosystem libraries
|
||||||
|
|
||||||
@@ -233,8 +273,8 @@ substitutes them on native desktop targets only.
|
|||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| Koin | `io.insert-koin:koin-compose*:4.2.2` | `com.bitsycore.koin:*` | apple + android only upstream |
|
| Koin | `io.insert-koin:koin-compose*:4.2.2` | `com.bitsycore.koin:*` | apple + android only upstream |
|
||||||
| Koin core | `io.insert-koin:koin-core:4.2.2` | *not forked* | already ships mingwX64 + linux |
|
| Koin core | `io.insert-koin:koin-core:4.2.2` | *not forked* | already ships mingwX64 + linux |
|
||||||
| Coil 3 | `io.coil-kt.coil3:coil*:3.6.2` | `com.bitsycore.coil3:*` | no mingwX64 anywhere; no desktop native at all for the compose layer |
|
| Coil 3 | `io.coil-kt.coil3:coil*:3.6.3` | `com.bitsycore.coil3:*` | no mingwX64 anywhere; no desktop native at all for the compose layer |
|
||||||
| Pulse MVI | `com.bitsycore.lib:pulse*:0.3.7` | `com.bitsycore.pulse:*` | no desktop-native artifact upstream |
|
| Pulse MVI | `com.bitsycore.lib:pulse*:0.3.7` | `com.bitsycore.compose.desktop.native.pulse:*` | no desktop-native artifact upstream - and Pulse is itself a `com.bitsycore` library, so the republish is namespaced under this project |
|
||||||
|
|
||||||
Koin's `koin-compose-viewmodel-navigation` is deliberately **not** provided: it
|
Koin's `koin-compose-viewmodel-navigation` is deliberately **not** provided: it
|
||||||
needs Navigation 2's `navigation-compose`, which has no mingwX64 or linux klibs
|
needs Navigation 2's `navigation-compose`, which has no mingwX64 or linux klibs
|
||||||
@@ -251,22 +291,11 @@ mirrors or you will have every class twice.
|
|||||||
|---|---|
|
|---|---|
|
||||||
| Lifecycle / ViewModel | `androidx.lifecycle:lifecycle-*:2.11.0` |
|
| Lifecycle / ViewModel | `androidx.lifecycle:lifecycle-*:2.11.0` |
|
||||||
| SavedState | `androidx.savedstate:savedstate*:1.5.0` (CMP builds against 1.4.0; lifecycle 2.11.0 requires it only as a *minimum*, so 1.5.0 resolves cleanly and gives consumers the newer API) |
|
| SavedState | `androidx.savedstate:savedstate*:1.5.0` (CMP builds against 1.4.0; lifecycle 2.11.0 requires it only as a *minimum*, so 1.5.0 resolves cleanly and gives consumers the newer API) |
|
||||||
| Navigation3 runtime | `androidx.navigation3:navigation3-runtime:1.2.0-alpha04` |
|
| Navigation3 runtime | `androidx.navigation3:navigation3-runtime:1.1.7` |
|
||||||
| Navigation Event | `androidx.navigationevent:navigationevent-compose:1.1.2` |
|
| Navigation Event | `androidx.navigationevent:navigationevent-compose:1.1.2` |
|
||||||
| Collection | `androidx.collection:collection:1.5.0` |
|
| Collection | `androidx.collection:collection:1.5.0` |
|
||||||
| Graphics Shapes | `androidx.graphics:graphics-shapes:1.1.0` |
|
| Graphics Shapes | `androidx.graphics:graphics-shapes:1.1.0` |
|
||||||
|
|
||||||
### Infrastructure
|
|
||||||
|
|
||||||
| Library | Version |
|
|
||||||
|---|---|
|
|
||||||
| kotlinx-coroutines | 1.11.0 |
|
|
||||||
| kotlinx-serialization | 1.11.0 |
|
|
||||||
| kotlinx-datetime | 0.8.0 |
|
|
||||||
| kotlinx-io-okio | 0.9.1 |
|
|
||||||
| Okio | 3.18.2 |
|
|
||||||
| Ktor | 3.5.2 |
|
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
Build the native libraries once per machine, then build any app target:
|
Build the native libraries once per machine, then build any app target:
|
||||||
@@ -281,6 +310,10 @@ command line tools; Linux needs gcc/g++ and the X11 / Wayland / audio dev
|
|||||||
headers; Windows needs a mingw-w64 g++ on PATH. See [TOOLING.md](TOOLING.md) for
|
headers; Windows needs a mingw-w64 g++ on PATH. See [TOOLING.md](TOOLING.md) for
|
||||||
the full build and verification workflow.
|
the full build and verification workflow.
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
[Bitsycore's Discord](https://discord.gg/kGnraVAtDR)
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
- [TOOLING.md](TOOLING.md): building the native libs, vendoring, and verification.
|
- [TOOLING.md](TOOLING.md): building the native libs, vendoring, and verification.
|
||||||
|
|||||||
+2
-1
@@ -154,6 +154,7 @@ demo.kexe --backtest # predictive-back / BackHandler
|
|||||||
demo.kexe --clicktest # pointer -> upstream clickable
|
demo.kexe --clicktest # pointer -> upstream clickable
|
||||||
demo.kexe --scrolltest # wheel -> scrollable
|
demo.kexe --scrolltest # wheel -> scrollable
|
||||||
demo.kexe --multiwintest # multi-window lifecycle
|
demo.kexe --multiwintest # multi-window lifecycle
|
||||||
|
demo.kexe --adaptivetest # material3-adaptive folds/unfolds on a LIVE window resize
|
||||||
demo.kexe --soaktest # memory soak (CDN_SOAK_SCREEN, CDN_SOAK_STATIC, CDN_SOAK_CYCLES)
|
demo.kexe --soaktest # memory soak (CDN_SOAK_SCREEN, CDN_SOAK_STATIC, CDN_SOAK_CYCLES)
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -194,7 +195,7 @@ single file to edit; know which axis you are changing.
|
|||||||
| Project release version | The git tag `vX.Y.Z`. `PUBLISH_VERSION` (from the tag) feeds `vPublishVersion` in `build.gradle.kts`, which strips the leading `v`. Groups mirror upstream per area (`com.bitsycore.compose.<area>:<module>`, e.g. `com.bitsycore.compose.ui:ui`); project-only modules use `com.bitsycore.compose.sdl` and `:desktop-native-window` is `com.bitsycore.compose` - see `groupFor()` in the root build. | Set by the tag, not edited by hand. A non-publish build is `0.0.0-SNAPSHOT`. |
|
| Project release version | The git tag `vX.Y.Z`. `PUBLISH_VERSION` (from the tag) feeds `vPublishVersion` in `build.gradle.kts`, which strips the leading `v`. Groups mirror upstream per area (`com.bitsycore.compose.<area>:<module>`, e.g. `com.bitsycore.compose.ui:ui`); project-only modules use `com.bitsycore.compose.sdl` and `:desktop-native-window` is `com.bitsycore.compose` - see `groupFor()` in the root build. | Set by the tag, not edited by hand. A non-publish build is `0.0.0-SNAPSHOT`. |
|
||||||
| Vendored Compose (native side) | `COMPOSE_CORE_REF` and `COMPOSE_REF` in `scripts/compose-fork/compose.properties`, plus `compose` in `gradle/libs.versions.toml`. | Pin to a durable tag (not a `+dev` commit upstream may GC). Re-sync after changing. |
|
| Vendored Compose (native side) | `COMPOSE_CORE_REF` and `COMPOSE_REF` in `scripts/compose-fork/compose.properties`, plus `compose` in `gradle/libs.versions.toml`. | Pin to a durable tag (not a `+dev` commit upstream may GC). Re-sync after changing. |
|
||||||
| Vendored ecosystem libs | `KOIN_REF`, `COIL_REF`, `PULSE_REF` in the same file, plus `koin` / `coil` in `gradle/libs.versions.toml`. | Same rule: durable tags. Each repo gets its own sibling sparse clone (`../cmp-ref-koin`, `../cmp-ref-coil`, `../cmp-ref-pulse-mvi`). Re-sync, then `apiDump` - these modules are BCV-validated like the rest. |
|
| Vendored ecosystem libs | `KOIN_REF`, `COIL_REF`, `PULSE_REF` in the same file, plus `koin` / `coil` in `gradle/libs.versions.toml`. | Same rule: durable tags. Each repo gets its own sibling sparse clone (`../cmp-ref-koin`, `../cmp-ref-coil`, `../cmp-ref-pulse-mvi`). Re-sync, then `apiDump` - these modules are BCV-validated like the rest. |
|
||||||
| JVM parity forcing | `compose` / `composeMaterial3` / `composeRuntime` in `gradle/libs.versions.toml` (read by `demo`, `apidemo`, `material-symbols` and the root build's forcing map). | Must be a version PUBLISHED to Maven Central. It may lag the vendored native ref (a documented skew) until the matching version is published; at v1.12.0 they are in lockstep. |
|
| JVM parity forcing | `compose` / `composeMaterial3` / `composeRuntime` in `gradle/libs.versions.toml` (read by `demo`, `apidemo`, `material-symbols` and the root build's forcing map). | Must be a version PUBLISHED to Maven Central. It may lag the vendored native ref (a documented skew) until the matching version is published; at v1.12.1 they are in lockstep. |
|
||||||
| Skiko | `skiko` (official) and `skikoMingw` (the fork) in `gradle/libs.versions.toml`; keep the fork's `-mingw.N` base equal to `skiko`. | macOS/Linux use official Skiko (`org.jetbrains.skiko`); mingwX64 uses the bitsycore fork (`com.bitsycore.skiko:skiko:0.150.1-mingw.2` from the public maven.bitsycore.com), published out of band by the fork repo's own workflow. Must expose the `org.jetbrains.skiko.node` `RenderNode` / `GraphicsContext` API the vendored compose-core uses (the fork keeps upstream's `org.jetbrains.skiko.*` package names; only the Maven coord is rebranded). Verify with a throwaway `skikoRendererMain` compile if unsure. |
|
| Skiko | `skiko` (official) and `skikoMingw` (the fork) in `gradle/libs.versions.toml`; keep the fork's `-mingw.N` base equal to `skiko`. | macOS/Linux use official Skiko (`org.jetbrains.skiko`); mingwX64 uses the bitsycore fork (`com.bitsycore.skiko:skiko:0.150.1-mingw.2` from the public maven.bitsycore.com), published out of band by the fork repo's own workflow. Must expose the `org.jetbrains.skiko.node` `RenderNode` / `GraphicsContext` API the vendored compose-core uses (the fork keeps upstream's `org.jetbrains.skiko.*` package names; only the Maven coord is rebranded). Verify with a throwaway `skikoRendererMain` compile if unsure. |
|
||||||
| SDL3 | `scripts/build-sdl/build-sdl.properties`. | Rebuild `libs/` with `build-all.py` after any change. |
|
| SDL3 | `scripts/build-sdl/build-sdl.properties`. | Rebuild `libs/` with `build-all.py` after any change. |
|
||||||
| Bridge substituted version | Defaults to the bridge plugin's own published version; consumers override with the `composeDesktopNative.version` Gradle property. | The plugin publishes with the release tag, so a consumer on the matching plugin version resolves the right klibs automatically. |
|
| Bridge substituted version | Defaults to the bridge plugin's own published version; consumers override with the `composeDesktopNative.version` Gradle property. | The plugin publishes with the release tag, so a consumer on the matching plugin version resolves the right klibs automatically. |
|
||||||
|
|||||||
@@ -56,11 +56,11 @@ internal class PackState(
|
|||||||
// A linked copy mirrors its source's requests read-only; non-linked packs own
|
// A linked copy mirrors its source's requests read-only; non-linked packs own
|
||||||
// their requests. `requests` resolves to whichever applies.
|
// their requests. `requests` resolves to whichever applies.
|
||||||
var linkedSource by mutableStateOf<PackState?>(null)
|
var linkedSource by mutableStateOf<PackState?>(null)
|
||||||
private val fOwnRequests = mutableStateListOf<ReqState>().apply {
|
private val mOwnRequests = mutableStateListOf<ReqState>().apply {
|
||||||
inPack.requests.forEach { add(ReqState(it)) } // packs (and the loose root) may be empty
|
inPack.requests.forEach { add(ReqState(it)) } // packs (and the loose root) may be empty
|
||||||
}
|
}
|
||||||
val requests: androidx.compose.runtime.snapshots.SnapshotStateList<ReqState>
|
val requests: androidx.compose.runtime.snapshots.SnapshotStateList<ReqState>
|
||||||
get() = linkedSource?.requests ?: fOwnRequests
|
get() = linkedSource?.requests ?: mOwnRequests
|
||||||
val isLinked: Boolean get() = linkedSource != null
|
val isLinked: Boolean get() = linkedSource != null
|
||||||
var parent: PackState? =
|
var parent: PackState? =
|
||||||
null // enclosing pack (null = top-level / root)
|
null // enclosing pack (null = top-level / root)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import kotlinx.serialization.json.JsonElement
|
|||||||
// respects the editor's "tab size" (TextLayoutConfig.tabWidth), exactly like
|
// respects the editor's "tab size" (TextLayoutConfig.tabWidth), exactly like
|
||||||
// typed tabs. Lenient so slightly-off JSON (single quotes, trailing commas)
|
// typed tabs. Lenient so slightly-off JSON (single quotes, trailing commas)
|
||||||
// still reformats instead of failing.
|
// still reformats instead of failing.
|
||||||
private val fPrettyJson = Json {
|
private val mPrettyJson = Json {
|
||||||
prettyPrint = true
|
prettyPrint = true
|
||||||
prettyPrintIndent = "\t"
|
prettyPrintIndent = "\t"
|
||||||
isLenient = true
|
isLenient = true
|
||||||
@@ -23,7 +23,7 @@ private val fPrettyJson = Json {
|
|||||||
fun formatBody(inText: String, inFormat: BodyFormat): String =
|
fun formatBody(inText: String, inFormat: BodyFormat): String =
|
||||||
when (inFormat) {
|
when (inFormat) {
|
||||||
BodyFormat.JSON -> runCatching {
|
BodyFormat.JSON -> runCatching {
|
||||||
fPrettyJson.encodeToString(JsonElement.serializer(), fPrettyJson.parseToJsonElement(inText))
|
mPrettyJson.encodeToString(JsonElement.serializer(), mPrettyJson.parseToJsonElement(inText))
|
||||||
}.getOrDefault(inText)
|
}.getOrDefault(inText)
|
||||||
|
|
||||||
BodyFormat.XML -> runCatching { formatXml(inText) }.getOrDefault(inText)
|
BodyFormat.XML -> runCatching { formatXml(inText) }.getOrDefault(inText)
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ macOS/Linux). Same TLS stack as the client-cert path in CurlMtls.kt.
|
|||||||
run() is a suspend fun - call it off the UI dispatcher. */
|
run() is a suspend fun - call it off the UI dispatcher. */
|
||||||
class HttpRunner {
|
class HttpRunner {
|
||||||
|
|
||||||
private val fClient = createApiHttpClient()
|
private val mClient = createApiHttpClient()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// Clear any temporary client certs a prior crash left in the Windows
|
// Clear any temporary client certs a prior crash left in the Windows
|
||||||
@@ -36,7 +36,7 @@ class HttpRunner {
|
|||||||
if (inReq.hasClientCert) return curlSendWithClientCert(inReq)
|
if (inReq.hasClientCert) return curlSendWithClientCert(inReq)
|
||||||
val vMark = TimeSource.Monotonic.markNow()
|
val vMark = TimeSource.Monotonic.markNow()
|
||||||
return try {
|
return try {
|
||||||
val vResp: HttpResponse = fClient.request(inReq.url.trim()) {
|
val vResp: HttpResponse = mClient.request(inReq.url.trim()) {
|
||||||
method = HttpMethod.parse(inReq.method.name)
|
method = HttpMethod.parse(inReq.method.name)
|
||||||
inReq.params
|
inReq.params
|
||||||
.filter { it.enabled && it.key.isNotBlank() }
|
.filter { it.enabled && it.key.isNotBlank() }
|
||||||
@@ -113,7 +113,7 @@ class HttpRunner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun close() = fClient.close()
|
fun close() = mClient.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Heuristic for a non-text body: textual content types (text, json, xml, html,
|
/** Heuristic for a non-text body: textual content types (text, json, xml, html,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import okio.Path.Companion.toPath
|
|||||||
// MARK: Pack persistence (okio + kotlinx.serialization)
|
// MARK: Pack persistence (okio + kotlinx.serialization)
|
||||||
// ==================
|
// ==================
|
||||||
|
|
||||||
private val fJson = Json {
|
private val mJson = Json {
|
||||||
prettyPrint = true
|
prettyPrint = true
|
||||||
prettyPrintIndent = " "
|
prettyPrintIndent = " "
|
||||||
ignoreUnknownKeys = true
|
ignoreUnknownKeys = true
|
||||||
@@ -20,7 +20,7 @@ private val fJson = Json {
|
|||||||
error message. */
|
error message. */
|
||||||
fun exportPack(inPack: Pack, inPath: String): String? = try {
|
fun exportPack(inPack: Pack, inPath: String): String? = try {
|
||||||
systemFileSystem.write(inPath.trim().toPath()) {
|
systemFileSystem.write(inPath.trim().toPath()) {
|
||||||
writeUtf8(fJson.encodeToString(inPack))
|
writeUtf8(mJson.encodeToString(inPack))
|
||||||
}
|
}
|
||||||
null
|
null
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
@@ -30,7 +30,7 @@ fun exportPack(inPack: Pack, inPath: String): String? = try {
|
|||||||
/** Read a pack back from inPath. */
|
/** Read a pack back from inPath. */
|
||||||
fun importPack(inPath: String): Result<Pack> = try {
|
fun importPack(inPath: String): Result<Pack> = try {
|
||||||
val vText = systemFileSystem.read(inPath.trim().toPath()) { readUtf8() }
|
val vText = systemFileSystem.read(inPath.trim().toPath()) { readUtf8() }
|
||||||
Result.success(fJson.decodeFromString<Pack>(vText))
|
Result.success(mJson.decodeFromString<Pack>(vText))
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
Result.failure(e)
|
Result.failure(e)
|
||||||
}
|
}
|
||||||
@@ -38,7 +38,7 @@ fun importPack(inPath: String): Result<Pack> = try {
|
|||||||
/** Write a whole self-contained session to inPath. Returns null on success. */
|
/** Write a whole self-contained session to inPath. Returns null on success. */
|
||||||
fun exportSession(inSession: Session, inPath: String): String? = try {
|
fun exportSession(inSession: Session, inPath: String): String? = try {
|
||||||
systemFileSystem.write(inPath.trim().toPath()) {
|
systemFileSystem.write(inPath.trim().toPath()) {
|
||||||
writeUtf8(fJson.encodeToString(inSession))
|
writeUtf8(mJson.encodeToString(inSession))
|
||||||
}
|
}
|
||||||
null
|
null
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
@@ -48,7 +48,7 @@ fun exportSession(inSession: Session, inPath: String): String? = try {
|
|||||||
/** Read a session back from inPath. */
|
/** Read a session back from inPath. */
|
||||||
fun importSession(inPath: String): Result<Session> = try {
|
fun importSession(inPath: String): Result<Session> = try {
|
||||||
val vText = systemFileSystem.read(inPath.trim().toPath()) { readUtf8() }
|
val vText = systemFileSystem.read(inPath.trim().toPath()) { readUtf8() }
|
||||||
Result.success(fJson.decodeFromString<Session>(vText))
|
Result.success(mJson.decodeFromString<Session>(vText))
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
Result.failure(e)
|
Result.failure(e)
|
||||||
}
|
}
|
||||||
@@ -85,7 +85,7 @@ fun writeBytesFile(inPath: String, inBytes: ByteArray): String? = try {
|
|||||||
/** Re-indent a JSON response for display; returns the input unchanged if it
|
/** Re-indent a JSON response for display; returns the input unchanged if it
|
||||||
isn't valid JSON (so plain-text / HTML responses still show). */
|
isn't valid JSON (so plain-text / HTML responses still show). */
|
||||||
fun prettyJsonOrRaw(inText: String): String = try {
|
fun prettyJsonOrRaw(inText: String): String = try {
|
||||||
fJson.encodeToString(JsonElement.serializer(), fJson.parseToJsonElement(inText))
|
mJson.encodeToString(JsonElement.serializer(), mJson.parseToJsonElement(inText))
|
||||||
} catch (_: Throwable) {
|
} catch (_: Throwable) {
|
||||||
inText
|
inText
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ data class Session(
|
|||||||
// MARK: Load / save (app-data dir via okio)
|
// MARK: Load / save (app-data dir via okio)
|
||||||
// ==================
|
// ==================
|
||||||
|
|
||||||
private val fStateJson = Json {
|
private val mStateJson = Json {
|
||||||
ignoreUnknownKeys = true
|
ignoreUnknownKeys = true
|
||||||
encodeDefaults = true
|
encodeDefaults = true
|
||||||
prettyPrint = true
|
prettyPrint = true
|
||||||
@@ -88,7 +88,7 @@ fun loadAppState(): AppState {
|
|||||||
val vPath = stateFilePath() ?: return AppState()
|
val vPath = stateFilePath() ?: return AppState()
|
||||||
return try {
|
return try {
|
||||||
val vText = systemFileSystem.read(vPath.toPath()) { readUtf8() }
|
val vText = systemFileSystem.read(vPath.toPath()) { readUtf8() }
|
||||||
fStateJson.decodeFromString<AppState>(vText)
|
mStateJson.decodeFromString<AppState>(vText)
|
||||||
} catch (_: Throwable) {
|
} catch (_: Throwable) {
|
||||||
AppState()
|
AppState()
|
||||||
}
|
}
|
||||||
@@ -99,7 +99,7 @@ the session, not the user's exported .json packs). */
|
|||||||
fun saveAppState(inState: AppState) {
|
fun saveAppState(inState: AppState) {
|
||||||
val vPath = stateFilePath() ?: return
|
val vPath = stateFilePath() ?: return
|
||||||
try {
|
try {
|
||||||
systemFileSystem.write(vPath.toPath()) { writeUtf8(fStateJson.encodeToString(inState)) }
|
systemFileSystem.write(vPath.toPath()) { writeUtf8(mStateJson.encodeToString(inState)) }
|
||||||
} catch (_: Throwable) {
|
} catch (_: Throwable) {
|
||||||
// ignore - nothing the user can act on, and packs can still be exported
|
// ignore - nothing the user can act on, and packs can still be exported
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,9 +157,9 @@ actual fun wrappedRowCount(inText: String, inFontPx: Int, inMaxWidthPx: Int, inF
|
|||||||
|
|
||||||
/** The jvm parity app only stores the preference - upstream's text pipeline has
|
/** The jvm parity app only stores the preference - upstream's text pipeline has
|
||||||
no global tab-width knob. Backed by state so menu checkmarks recompose. */
|
no global tab-width knob. Backed by state so menu checkmarks recompose. */
|
||||||
private var fTabWidth by mutableStateOf(4)
|
private var mTabWidth by mutableStateOf(4)
|
||||||
actual var editorTabWidth: Int
|
actual var editorTabWidth: Int
|
||||||
get() = fTabWidth
|
get() = mTabWidth
|
||||||
set(value) {
|
set(value) {
|
||||||
fTabWidth = value
|
mTabWidth = value
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-5
@@ -46,6 +46,10 @@ val kAreaGroups = mapOf(
|
|||||||
":compose:animation:animation-core" to "com.bitsycore.compose.animation",
|
":compose:animation:animation-core" to "com.bitsycore.compose.animation",
|
||||||
":compose:animation:animation-graphics" to "com.bitsycore.compose.animation",
|
":compose:animation:animation-graphics" to "com.bitsycore.compose.animation",
|
||||||
":compose:material3:material3" to "com.bitsycore.compose.material3",
|
":compose:material3:material3" to "com.bitsycore.compose.material3",
|
||||||
|
":compose:material3:adaptive:adaptive" to "com.bitsycore.compose.material3.adaptive",
|
||||||
|
":compose:material3:adaptive:adaptive-layout" to "com.bitsycore.compose.material3.adaptive",
|
||||||
|
":compose:material3:adaptive:adaptive-navigation" to "com.bitsycore.compose.material3.adaptive",
|
||||||
|
":compose:material3:adaptive:adaptive-navigation3" to "com.bitsycore.compose.material3.adaptive",
|
||||||
":compose:material:material-ripple" to "com.bitsycore.compose.material",
|
":compose:material:material-ripple" to "com.bitsycore.compose.material",
|
||||||
":components:resources:components-resources" to "com.bitsycore.compose.components",
|
":components:resources:components-resources" to "com.bitsycore.compose.components",
|
||||||
":navigation3:navigation3-ui" to "com.bitsycore.navigation3",
|
":navigation3:navigation3-ui" to "com.bitsycore.navigation3",
|
||||||
@@ -60,10 +64,10 @@ val kAreaGroups = mapOf(
|
|||||||
":coil:coil-svg" to "com.bitsycore.coil3",
|
":coil:coil-svg" to "com.bitsycore.coil3",
|
||||||
":coil:coil-network-core" to "com.bitsycore.coil3",
|
":coil:coil-network-core" to "com.bitsycore.coil3",
|
||||||
":coil:coil-network-ktor3" to "com.bitsycore.coil3",
|
":coil:coil-network-ktor3" to "com.bitsycore.coil3",
|
||||||
":pulse:pulse" to "com.bitsycore.pulse",
|
":pulse:pulse" to "com.bitsycore.compose.desktop.native.pulse",
|
||||||
":pulse:pulse-viewmodel" to "com.bitsycore.pulse",
|
":pulse:pulse-viewmodel" to "com.bitsycore.compose.desktop.native.pulse",
|
||||||
":pulse:pulse-savedstate" to "com.bitsycore.pulse",
|
":pulse:pulse-savedstate" to "com.bitsycore.compose.desktop.native.pulse",
|
||||||
":pulse:pulse-compose" to "com.bitsycore.pulse",
|
":pulse:pulse-compose" to "com.bitsycore.compose.desktop.native.pulse",
|
||||||
":compose:desktop:native:desktop-native-window" to "com.bitsycore.compose",
|
":compose:desktop:native:desktop-native-window" to "com.bitsycore.compose",
|
||||||
)
|
)
|
||||||
fun groupFor(path: String): String = kAreaGroups[path] ?: kDefaultGroup
|
fun groupFor(path: String): String = kAreaGroups[path] ?: kDefaultGroup
|
||||||
@@ -99,6 +103,7 @@ val kPublishedLibs = setOf(
|
|||||||
":compose:animation:animation-graphics",
|
":compose:animation:animation-graphics",
|
||||||
":compose:foundation:foundation", ":compose:foundation:foundation-layout",
|
":compose:foundation:foundation", ":compose:foundation:foundation-layout",
|
||||||
":compose:material3:material3", ":compose:material:material-ripple",
|
":compose:material3:material3", ":compose:material:material-ripple",
|
||||||
|
":compose:material3:adaptive:adaptive", ":compose:material3:adaptive:adaptive-layout", ":compose:material3:adaptive:adaptive-navigation", ":compose:material3:adaptive:adaptive-navigation3",
|
||||||
":compose:desktop:native:desktop-native-window", ":utils:material-symbols",
|
":compose:desktop:native:desktop-native-window", ":utils:material-symbols",
|
||||||
":navigation3:navigation3-ui", ":components:resources:components-resources",
|
":navigation3:navigation3-ui", ":components:resources:components-resources",
|
||||||
":koin:koin-core-viewmodel", ":koin:koin-compose",
|
":koin:koin-core-viewmodel", ":koin:koin-compose",
|
||||||
@@ -222,6 +227,12 @@ allprojects {
|
|||||||
substitute(module("org.jetbrains.compose.animation:animation")).using(project(":compose:animation:animation"))
|
substitute(module("org.jetbrains.compose.animation:animation")).using(project(":compose:animation:animation"))
|
||||||
substitute(module("org.jetbrains.compose.animation:animation-core")).using(project(":compose:animation:animation-core"))
|
substitute(module("org.jetbrains.compose.animation:animation-core")).using(project(":compose:animation:animation-core"))
|
||||||
substitute(module("org.jetbrains.compose.material3:material3")).using(project(":compose:material3:material3"))
|
substitute(module("org.jetbrains.compose.material3:material3")).using(project(":compose:material3:material3"))
|
||||||
|
// material3-adaptive: upstream publishes ios + macosArm64 only - no
|
||||||
|
// linux, no mingw (issues/4). Vendored as :compose:material3:adaptive:*.
|
||||||
|
substitute(module("org.jetbrains.compose.material3.adaptive:adaptive")).using(project(":compose:material3:adaptive:adaptive"))
|
||||||
|
substitute(module("org.jetbrains.compose.material3.adaptive:adaptive-layout")).using(project(":compose:material3:adaptive:adaptive-layout"))
|
||||||
|
substitute(module("org.jetbrains.compose.material3.adaptive:adaptive-navigation")).using(project(":compose:material3:adaptive:adaptive-navigation"))
|
||||||
|
substitute(module("org.jetbrains.compose.material3.adaptive:adaptive-navigation3")).using(project(":compose:material3:adaptive:adaptive-navigation3"))
|
||||||
// navigation3-ui: the JB Maven artifact has no K/N desktop
|
// navigation3-ui: the JB Maven artifact has no K/N desktop
|
||||||
// klibs - the port vendors it as :navigation3-ui.
|
// klibs - the port vendors it as :navigation3-ui.
|
||||||
substitute(module("org.jetbrains.androidx.navigation3:navigation3-ui")).using(project(":navigation3:navigation3-ui"))
|
substitute(module("org.jetbrains.androidx.navigation3:navigation3-ui")).using(project(":navigation3:navigation3-ui"))
|
||||||
@@ -244,7 +255,9 @@ allprojects {
|
|||||||
substitute(module("io.coil-kt.coil3:coil-network-core")).using(project(":coil:coil-network-core"))
|
substitute(module("io.coil-kt.coil3:coil-network-core")).using(project(":coil:coil-network-core"))
|
||||||
substitute(module("io.coil-kt.coil3:coil-network-ktor3")).using(project(":coil:coil-network-ktor3"))
|
substitute(module("io.coil-kt.coil3:coil-network-ktor3")).using(project(":coil:coil-network-ktor3"))
|
||||||
// Pulse MVI: upstream publishes com.bitsycore.lib:* with no desktop
|
// Pulse MVI: upstream publishes com.bitsycore.lib:* with no desktop
|
||||||
// native targets. The port republishes under com.bitsycore.pulse so the
|
// native targets. Pulse is itself a com.bitsycore library, so the port's
|
||||||
|
// republish is namespaced under THIS project rather than a bare
|
||||||
|
// com.bitsycore.pulse, which would read like the upstream artifact. The
|
||||||
// two coordinates never collide, and substitutes the official one here.
|
// two coordinates never collide, and substitutes the official one here.
|
||||||
substitute(module("com.bitsycore.lib:pulse")).using(project(":pulse:pulse"))
|
substitute(module("com.bitsycore.lib:pulse")).using(project(":pulse:pulse"))
|
||||||
substitute(module("com.bitsycore.lib:pulse-viewmodel")).using(project(":pulse:pulse-viewmodel"))
|
substitute(module("com.bitsycore.lib:pulse-viewmodel")).using(project(":pulse:pulse-viewmodel"))
|
||||||
|
|||||||
@@ -11,12 +11,6 @@ plugins {
|
|||||||
alias(libs.plugins.kotlin.plugin.compose)
|
alias(libs.plugins.kotlin.plugin.compose)
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
|
||||||
google()
|
|
||||||
mavenCentral()
|
|
||||||
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
|
|
||||||
}
|
|
||||||
|
|
||||||
val vHostSupportsMingw = rootProject.extra["vHostSupportsMingw"] as Boolean
|
val vHostSupportsMingw = rootProject.extra["vHostSupportsMingw"] as Boolean
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
|
|||||||
+11
-11
@@ -51,20 +51,20 @@ private class SvgPainter(private val bytes: ByteArray) : Painter() {
|
|||||||
|
|
||||||
override val intrinsicSize: Size = svgIntrinsicSize(bytes) ?: Size.Unspecified
|
override val intrinsicSize: Size = svgIntrinsicSize(bytes) ?: Size.Unspecified
|
||||||
|
|
||||||
private var fAlpha: Float = 1f
|
private var mAlpha: Float = 1f
|
||||||
private var fColorFilter: ColorFilter? = null
|
private var mColorFilter: ColorFilter? = null
|
||||||
private var fCacheKey: Long = -1L
|
private var mCacheKey: Long = -1L
|
||||||
private var fCacheBitmap: ImageBitmap? = null
|
private var mCacheBitmap: ImageBitmap? = null
|
||||||
|
|
||||||
override fun applyAlpha(alpha: Float): Boolean { fAlpha = alpha; return true }
|
override fun applyAlpha(alpha: Float): Boolean { mAlpha = alpha; return true }
|
||||||
override fun applyColorFilter(colorFilter: ColorFilter?): Boolean { fColorFilter = colorFilter; return true }
|
override fun applyColorFilter(colorFilter: ColorFilter?): Boolean { mColorFilter = colorFilter; return true }
|
||||||
|
|
||||||
private fun rasterFor(inWidthPx: Int, inHeightPx: Int): ImageBitmap? {
|
private fun rasterFor(inWidthPx: Int, inHeightPx: Int): ImageBitmap? {
|
||||||
val vKey = (inWidthPx.toLong() shl 32) or inHeightPx.toLong()
|
val vKey = (inWidthPx.toLong() shl 32) or inHeightPx.toLong()
|
||||||
if (vKey == fCacheKey && fCacheBitmap != null) return fCacheBitmap
|
if (vKey == mCacheKey && mCacheBitmap != null) return mCacheBitmap
|
||||||
val vBitmap = decodeSvgAt(bytes, inWidthPx, inHeightPx) ?: return null
|
val vBitmap = decodeSvgAt(bytes, inWidthPx, inHeightPx) ?: return null
|
||||||
fCacheKey = vKey
|
mCacheKey = vKey
|
||||||
fCacheBitmap = vBitmap
|
mCacheBitmap = vBitmap
|
||||||
return vBitmap
|
return vBitmap
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,8 +79,8 @@ private class SvgPainter(private val bytes: ByteArray) : Painter() {
|
|||||||
srcSize = IntSize(vBitmap.width, vBitmap.height),
|
srcSize = IntSize(vBitmap.width, vBitmap.height),
|
||||||
dstOffset = IntOffset.Zero,
|
dstOffset = IntOffset.Zero,
|
||||||
dstSize = IntSize(vWpx, vHpx),
|
dstSize = IntSize(vWpx, vHpx),
|
||||||
alpha = fAlpha,
|
alpha = mAlpha,
|
||||||
colorFilter = fColorFilter,
|
colorFilter = mColorFilter,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+47
-47
@@ -16,7 +16,7 @@ package org.jetbrains.compose.resources.vector.xmldom
|
|||||||
CDATA skipping, and the five predefined entities plus numeric character
|
CDATA skipping, and the five predefined entities plus numeric character
|
||||||
references. No DTD expansion, no processing-instruction handling beyond
|
references. No DTD expansion, no processing-instruction handling beyond
|
||||||
skipping - malformed input throws MalformedXMLException like upstream. */
|
skipping - malformed input throws MalformedXMLException like upstream. */
|
||||||
// VENDOR-BASE(COMPOSE_REF): components/resources/library/src/nativeMain/kotlin/org/jetbrains/compose/resources/vector/xmldom/DomXmlParser.kt @ v1.12.0
|
// VENDOR-BASE(COMPOSE_REF): components/resources/library/src/nativeMain/kotlin/org/jetbrains/compose/resources/vector/xmldom/DomXmlParser.kt @ v1.12.1
|
||||||
// (fresh REIMPL, not a copy-edit - the base ref marks the upstream API it tracks)
|
// (fresh REIMPL, not a copy-edit - the base ref marks the upstream API it tracks)
|
||||||
|
|
||||||
internal fun parse(xml: String): Element {
|
internal fun parse(xml: String): Element {
|
||||||
@@ -32,13 +32,13 @@ private class Attr(val prefix: String, val localName: String, val nsUri: String,
|
|||||||
val qualifiedName: String get() = if (prefix.isEmpty()) localName else "$prefix:$localName"
|
val qualifiedName: String get() = if (prefix.isEmpty()) localName else "$prefix:$localName"
|
||||||
}
|
}
|
||||||
|
|
||||||
private class NodeListImpl(private val fNodes: List<Node>) : NodeList {
|
private class NodeListImpl(private val mNodes: List<Node>) : NodeList {
|
||||||
override fun item(i: Int): Node = fNodes[i]
|
override fun item(i: Int): Node = mNodes[i]
|
||||||
override val length: Int get() = fNodes.size
|
override val length: Int get() = mNodes.size
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TextNodeImpl(private val fText: String) : Node {
|
private class TextNodeImpl(private val mText: String) : Node {
|
||||||
override val textContent: String? get() = fText
|
override val textContent: String? get() = mText
|
||||||
override val nodeName: String get() = "#text"
|
override val nodeName: String get() = "#text"
|
||||||
override val localName: String get() = ""
|
override val localName: String get() = ""
|
||||||
override val childNodes: NodeList = NodeListImpl(emptyList())
|
override val childNodes: NodeList = NodeListImpl(emptyList())
|
||||||
@@ -47,16 +47,16 @@ private class TextNodeImpl(private val fText: String) : Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class ElementImpl(
|
private class ElementImpl(
|
||||||
private val fPrefix: String,
|
private val mPrefix: String,
|
||||||
override val localName: String,
|
override val localName: String,
|
||||||
override val namespaceURI: String,
|
override val namespaceURI: String,
|
||||||
private val fAttrs: List<Attr>,
|
private val mAttrs: List<Attr>,
|
||||||
// Innermost-first chain of xmlns scopes: each is prefix -> uri ("" = default ns).
|
// Innermost-first chain of xmlns scopes: each is prefix -> uri ("" = default ns).
|
||||||
private val fNsScope: List<Map<String, String>>,
|
private val mNsScope: List<Map<String, String>>,
|
||||||
) : Element {
|
) : Element {
|
||||||
var children: List<Node> = emptyList()
|
var children: List<Node> = emptyList()
|
||||||
|
|
||||||
override val nodeName: String get() = if (fPrefix.isEmpty()) localName else "$fPrefix:$localName"
|
override val nodeName: String get() = if (mPrefix.isEmpty()) localName else "$mPrefix:$localName"
|
||||||
override val childNodes: NodeList get() = NodeListImpl(children)
|
override val childNodes: NodeList get() = NodeListImpl(children)
|
||||||
|
|
||||||
// Concatenated descendant text - what DOM's textContent does.
|
// Concatenated descendant text - what DOM's textContent does.
|
||||||
@@ -72,7 +72,7 @@ private class ElementImpl(
|
|||||||
|
|
||||||
override fun lookupPrefix(namespaceURI: String): String {
|
override fun lookupPrefix(namespaceURI: String): String {
|
||||||
if (namespaceURI.isEmpty()) return ""
|
if (namespaceURI.isEmpty()) return ""
|
||||||
for (vScope in fNsScope) {
|
for (vScope in mNsScope) {
|
||||||
for ((vPrefix, vUri) in vScope) {
|
for ((vPrefix, vUri) in vScope) {
|
||||||
if (vUri == namespaceURI && vPrefix.isNotEmpty()) return vPrefix
|
if (vUri == namespaceURI && vPrefix.isNotEmpty()) return vPrefix
|
||||||
}
|
}
|
||||||
@@ -81,22 +81,22 @@ private class ElementImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getAttributeNS(nameSpaceURI: String, localName: String): String =
|
override fun getAttributeNS(nameSpaceURI: String, localName: String): String =
|
||||||
fAttrs.firstOrNull { it.nsUri == nameSpaceURI && it.localName == localName }?.value ?: ""
|
mAttrs.firstOrNull { it.nsUri == nameSpaceURI && it.localName == localName }?.value ?: ""
|
||||||
|
|
||||||
override fun getAttribute(name: String): String =
|
override fun getAttribute(name: String): String =
|
||||||
fAttrs.firstOrNull { it.qualifiedName == name }?.value ?: ""
|
mAttrs.firstOrNull { it.qualifiedName == name }?.value ?: ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============
|
// ============
|
||||||
// The parser - one pass over the string with a cursor.
|
// The parser - one pass over the string with a cursor.
|
||||||
private class XmlDomParser(private val fXml: String) {
|
private class XmlDomParser(private val mXml: String) {
|
||||||
private var fPos = 0
|
private var mPos = 0
|
||||||
|
|
||||||
fun skipProlog() {
|
fun skipProlog() {
|
||||||
while (true) {
|
while (true) {
|
||||||
skipWhitespace()
|
skipWhitespace()
|
||||||
when {
|
when {
|
||||||
lookingAt("") -> fPos++
|
lookingAt("") -> mPos++
|
||||||
lookingAt("<?") -> skipUntil("?>")
|
lookingAt("<?") -> skipUntil("?>")
|
||||||
lookingAt("<!--") -> skipUntil("-->")
|
lookingAt("<!--") -> skipUntil("-->")
|
||||||
lookingAt("<!DOCTYPE") -> skipDoctype()
|
lookingAt("<!DOCTYPE") -> skipDoctype()
|
||||||
@@ -112,7 +112,7 @@ private class XmlDomParser(private val fXml: String) {
|
|||||||
if (!lookingAt("<") || lookingAt("</")) return null
|
if (!lookingAt("<") || lookingAt("</")) return null
|
||||||
expect("<")
|
expect("<")
|
||||||
val vQName = readName()
|
val vQName = readName()
|
||||||
if (vQName.isEmpty()) throw MalformedXMLException("empty element name at $fPos")
|
if (vQName.isEmpty()) throw MalformedXMLException("empty element name at $mPos")
|
||||||
|
|
||||||
// Attributes (collect raw first - xmlns declarations shape the scope
|
// Attributes (collect raw first - xmlns declarations shape the scope
|
||||||
// that THIS element's own prefix resolves against).
|
// that THIS element's own prefix resolves against).
|
||||||
@@ -121,7 +121,7 @@ private class XmlDomParser(private val fXml: String) {
|
|||||||
skipWhitespace()
|
skipWhitespace()
|
||||||
if (lookingAt("/>") || lookingAt(">")) break
|
if (lookingAt("/>") || lookingAt(">")) break
|
||||||
val vAttrName = readName()
|
val vAttrName = readName()
|
||||||
if (vAttrName.isEmpty()) throw MalformedXMLException("bad attribute at $fPos")
|
if (vAttrName.isEmpty()) throw MalformedXMLException("bad attribute at $mPos")
|
||||||
skipWhitespace(); expect("="); skipWhitespace()
|
skipWhitespace(); expect("="); skipWhitespace()
|
||||||
vRawAttrs.add(vAttrName to readQuotedValue())
|
vRawAttrs.add(vAttrName to readQuotedValue())
|
||||||
}
|
}
|
||||||
@@ -160,7 +160,7 @@ private class XmlDomParser(private val fXml: String) {
|
|||||||
val vElement = ElementImpl(vPrefix, vLocal, resolveNs(vPrefix), vAttrs, vScope)
|
val vElement = ElementImpl(vPrefix, vLocal, resolveNs(vPrefix), vAttrs, vScope)
|
||||||
|
|
||||||
if (lookingAt("/>")) {
|
if (lookingAt("/>")) {
|
||||||
fPos += 2
|
mPos += 2
|
||||||
return vElement
|
return vElement
|
||||||
}
|
}
|
||||||
expect(">")
|
expect(">")
|
||||||
@@ -169,9 +169,9 @@ private class XmlDomParser(private val fXml: String) {
|
|||||||
val vChildren = ArrayList<Node>()
|
val vChildren = ArrayList<Node>()
|
||||||
while (true) {
|
while (true) {
|
||||||
when {
|
when {
|
||||||
fPos >= fXml.length -> throw MalformedXMLException("unclosed <$vQName>")
|
mPos >= mXml.length -> throw MalformedXMLException("unclosed <$vQName>")
|
||||||
lookingAt("</") -> {
|
lookingAt("</") -> {
|
||||||
fPos += 2
|
mPos += 2
|
||||||
val vClose = readName()
|
val vClose = readName()
|
||||||
skipWhitespace(); expect(">")
|
skipWhitespace(); expect(">")
|
||||||
if (vClose != vQName) throw MalformedXMLException("mismatched </$vClose> for <$vQName>")
|
if (vClose != vQName) throw MalformedXMLException("mismatched </$vClose> for <$vQName>")
|
||||||
@@ -180,18 +180,18 @@ private class XmlDomParser(private val fXml: String) {
|
|||||||
}
|
}
|
||||||
lookingAt("<!--") -> skipUntil("-->")
|
lookingAt("<!--") -> skipUntil("-->")
|
||||||
lookingAt("<![CDATA[") -> {
|
lookingAt("<![CDATA[") -> {
|
||||||
val vEnd = fXml.indexOf("]]>", fPos + 9)
|
val vEnd = mXml.indexOf("]]>", mPos + 9)
|
||||||
if (vEnd < 0) throw MalformedXMLException("unclosed CDATA")
|
if (vEnd < 0) throw MalformedXMLException("unclosed CDATA")
|
||||||
vChildren.add(TextNodeImpl(fXml.substring(fPos + 9, vEnd)))
|
vChildren.add(TextNodeImpl(mXml.substring(mPos + 9, vEnd)))
|
||||||
fPos = vEnd + 3
|
mPos = vEnd + 3
|
||||||
}
|
}
|
||||||
lookingAt("<?") -> skipUntil("?>")
|
lookingAt("<?") -> skipUntil("?>")
|
||||||
lookingAt("<") -> parseElement(vScope)?.let { vChildren.add(it) }
|
lookingAt("<") -> parseElement(vScope)?.let { vChildren.add(it) }
|
||||||
else -> {
|
else -> {
|
||||||
val vNext = fXml.indexOf('<', fPos).let { if (it < 0) fXml.length else it }
|
val vNext = mXml.indexOf('<', mPos).let { if (it < 0) mXml.length else it }
|
||||||
val vText = decodeEntities(fXml.substring(fPos, vNext))
|
val vText = decodeEntities(mXml.substring(mPos, vNext))
|
||||||
if (vText.isNotBlank()) vChildren.add(TextNodeImpl(vText))
|
if (vText.isNotBlank()) vChildren.add(TextNodeImpl(vText))
|
||||||
fPos = vNext
|
mPos = vNext
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -200,28 +200,28 @@ private class XmlDomParser(private val fXml: String) {
|
|||||||
// ============
|
// ============
|
||||||
// Lexing helpers
|
// Lexing helpers
|
||||||
|
|
||||||
private fun lookingAt(inToken: String): Boolean = fXml.startsWith(inToken, fPos)
|
private fun lookingAt(inToken: String): Boolean = mXml.startsWith(inToken, mPos)
|
||||||
|
|
||||||
private fun expect(inToken: String) {
|
private fun expect(inToken: String) {
|
||||||
if (!lookingAt(inToken)) throw MalformedXMLException("expected '$inToken' at $fPos")
|
if (!lookingAt(inToken)) throw MalformedXMLException("expected '$inToken' at $mPos")
|
||||||
fPos += inToken.length
|
mPos += inToken.length
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun skipWhitespace() {
|
private fun skipWhitespace() {
|
||||||
while (fPos < fXml.length && fXml[fPos].isWhitespace()) fPos++
|
while (mPos < mXml.length && mXml[mPos].isWhitespace()) mPos++
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun skipUntil(inToken: String) {
|
private fun skipUntil(inToken: String) {
|
||||||
val vEnd = fXml.indexOf(inToken, fPos)
|
val vEnd = mXml.indexOf(inToken, mPos)
|
||||||
if (vEnd < 0) throw MalformedXMLException("unterminated '$inToken' section")
|
if (vEnd < 0) throw MalformedXMLException("unterminated '$inToken' section")
|
||||||
fPos = vEnd + inToken.length
|
mPos = vEnd + inToken.length
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DOCTYPE may nest an internal subset in [ ] - skip to the matching '>'. */
|
/* DOCTYPE may nest an internal subset in [ ] - skip to the matching '>'. */
|
||||||
private fun skipDoctype() {
|
private fun skipDoctype() {
|
||||||
var vDepth = 0
|
var vDepth = 0
|
||||||
while (fPos < fXml.length) {
|
while (mPos < mXml.length) {
|
||||||
val c = fXml[fPos++]
|
val c = mXml[mPos++]
|
||||||
if (c == '[') vDepth++
|
if (c == '[') vDepth++
|
||||||
else if (c == ']') vDepth--
|
else if (c == ']') vDepth--
|
||||||
else if (c == '>' && vDepth <= 0) return
|
else if (c == '>' && vDepth <= 0) return
|
||||||
@@ -230,24 +230,24 @@ private class XmlDomParser(private val fXml: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun readName(): String {
|
private fun readName(): String {
|
||||||
val vStart = fPos
|
val vStart = mPos
|
||||||
while (fPos < fXml.length) {
|
while (mPos < mXml.length) {
|
||||||
val c = fXml[fPos]
|
val c = mXml[mPos]
|
||||||
if (c.isWhitespace() || c == '=' || c == '>' || c == '/' || c == '<') break
|
if (c.isWhitespace() || c == '=' || c == '>' || c == '/' || c == '<') break
|
||||||
fPos++
|
mPos++
|
||||||
}
|
}
|
||||||
return fXml.substring(vStart, fPos)
|
return mXml.substring(vStart, mPos)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun readQuotedValue(): String {
|
private fun readQuotedValue(): String {
|
||||||
if (fPos >= fXml.length) throw MalformedXMLException("unterminated attribute value")
|
if (mPos >= mXml.length) throw MalformedXMLException("unterminated attribute value")
|
||||||
val vQuote = fXml[fPos]
|
val vQuote = mXml[mPos]
|
||||||
if (vQuote != '"' && vQuote != '\'') throw MalformedXMLException("attribute value must be quoted at $fPos")
|
if (vQuote != '"' && vQuote != '\'') throw MalformedXMLException("attribute value must be quoted at $mPos")
|
||||||
fPos++
|
mPos++
|
||||||
val vEnd = fXml.indexOf(vQuote, fPos)
|
val vEnd = mXml.indexOf(vQuote, mPos)
|
||||||
if (vEnd < 0) throw MalformedXMLException("unterminated attribute value")
|
if (vEnd < 0) throw MalformedXMLException("unterminated attribute value")
|
||||||
val vRaw = fXml.substring(fPos, vEnd)
|
val vRaw = mXml.substring(mPos, vEnd)
|
||||||
fPos = vEnd + 1
|
mPos = vEnd + 1
|
||||||
return decodeEntities(vRaw)
|
return decodeEntities(vRaw)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ final var com.compose.sdl/useVirtualFrameTime // com.compose.sdl/useVirtualFrame
|
|||||||
final fun <get-useVirtualFrameTime>(): kotlin/Boolean // com.compose.sdl/useVirtualFrameTime.<get-useVirtualFrameTime>|<get-useVirtualFrameTime>(){}[0]
|
final fun <get-useVirtualFrameTime>(): kotlin/Boolean // com.compose.sdl/useVirtualFrameTime.<get-useVirtualFrameTime>|<get-useVirtualFrameTime>(){}[0]
|
||||||
final fun <set-useVirtualFrameTime>(kotlin/Boolean) // com.compose.sdl/useVirtualFrameTime.<set-useVirtualFrameTime>|<set-useVirtualFrameTime>(kotlin.Boolean){}[0]
|
final fun <set-useVirtualFrameTime>(kotlin/Boolean) // com.compose.sdl/useVirtualFrameTime.<set-useVirtualFrameTime>|<set-useVirtualFrameTime>(kotlin.Boolean){}[0]
|
||||||
|
|
||||||
final fun (com.compose.sdl/ApplicationScope).com.compose.sdl/Window(kotlin/Function0<kotlin/Unit>, kotlin/String?, kotlin/Int, kotlin/Int, com.compose.sdl/GpuMode?, com.compose.sdl/AppWindowIcon?, kotlin/Function2<com.compose.sdl/RenderBackend, kotlin/Int, kotlin/Boolean>?, kotlin/Function3<com.compose.sdl/ComposeWindowScope, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // com.compose.sdl/Window|Window@com.compose.sdl.ApplicationScope(kotlin.Function0<kotlin.Unit>;kotlin.String?;kotlin.Int;kotlin.Int;com.compose.sdl.GpuMode?;com.compose.sdl.AppWindowIcon?;kotlin.Function2<com.compose.sdl.RenderBackend,kotlin.Int,kotlin.Boolean>?;kotlin.Function3<com.compose.sdl.ComposeWindowScope,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0]
|
final fun (com.compose.sdl/ApplicationScope).com.compose.sdl/Window(kotlin/Function0<kotlin/Unit>, kotlin/String?, kotlin/Int, kotlin/Int, com.compose.sdl/GpuMode?, com.compose.sdl/AppWindowIcon?, kotlin/Boolean, kotlin/Boolean, kotlin/Boolean, kotlin/Boolean, kotlin/Boolean, kotlin/Boolean, kotlin/Function1<androidx.compose.ui.input.key/KeyEvent, kotlin/Boolean>?, kotlin/Function1<androidx.compose.ui.input.key/KeyEvent, kotlin/Boolean>?, kotlin/Function2<com.compose.sdl/RenderBackend, kotlin/Int, kotlin/Boolean>?, kotlin/Function3<com.compose.sdl/ComposeWindowScope, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int, kotlin/Int) // com.compose.sdl/Window|Window@com.compose.sdl.ApplicationScope(kotlin.Function0<kotlin.Unit>;kotlin.String?;kotlin.Int;kotlin.Int;com.compose.sdl.GpuMode?;com.compose.sdl.AppWindowIcon?;kotlin.Boolean;kotlin.Boolean;kotlin.Boolean;kotlin.Boolean;kotlin.Boolean;kotlin.Boolean;kotlin.Function1<androidx.compose.ui.input.key.KeyEvent,kotlin.Boolean>?;kotlin.Function1<androidx.compose.ui.input.key.KeyEvent,kotlin.Boolean>?;kotlin.Function2<com.compose.sdl.RenderBackend,kotlin.Int,kotlin.Boolean>?;kotlin.Function3<com.compose.sdl.ComposeWindowScope,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int;kotlin.Int){}[0]
|
||||||
final fun com.compose.sdl/com_compose_sdl_AppWindowIcon$stableprop_getter(): kotlin/Int // com.compose.sdl/com_compose_sdl_AppWindowIcon$stableprop_getter|com_compose_sdl_AppWindowIcon$stableprop_getter(){}[0]
|
final fun com.compose.sdl/com_compose_sdl_AppWindowIcon$stableprop_getter(): kotlin/Int // com.compose.sdl/com_compose_sdl_AppWindowIcon$stableprop_getter|com_compose_sdl_AppWindowIcon$stableprop_getter(){}[0]
|
||||||
final fun com.compose.sdl/nativeComposeApp(kotlin/Function3<com.compose.sdl/ApplicationScope, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>) // com.compose.sdl/nativeComposeApp|nativeComposeApp(kotlin.Function3<com.compose.sdl.ApplicationScope,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>){}[0]
|
final fun com.compose.sdl/nativeComposeApp(kotlin/Function3<com.compose.sdl/ApplicationScope, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>) // com.compose.sdl/nativeComposeApp|nativeComposeApp(kotlin.Function3<com.compose.sdl.ApplicationScope,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>){}[0]
|
||||||
final fun com.compose.sdl/nativeComposeWindow(kotlin/String = ..., kotlin/Int = ..., kotlin/Int = ..., com.compose.sdl/GpuMode = ..., com.compose.sdl/AppWindowIcon? = ..., kotlin/Function2<com.compose.sdl/RenderBackend, kotlin/Int, kotlin/Boolean>? = ..., kotlin/Function3<com.compose.sdl/ComposeWindowScope, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>) // com.compose.sdl/nativeComposeWindow|nativeComposeWindow(kotlin.String;kotlin.Int;kotlin.Int;com.compose.sdl.GpuMode;com.compose.sdl.AppWindowIcon?;kotlin.Function2<com.compose.sdl.RenderBackend,kotlin.Int,kotlin.Boolean>?;kotlin.Function3<com.compose.sdl.ComposeWindowScope,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>){}[0]
|
final fun com.compose.sdl/nativeComposeWindow(kotlin/String = ..., kotlin/Int = ..., kotlin/Int = ..., com.compose.sdl/GpuMode = ..., com.compose.sdl/AppWindowIcon? = ..., kotlin/Boolean = ..., kotlin/Boolean = ..., kotlin/Boolean = ..., kotlin/Boolean = ..., kotlin/Boolean = ..., kotlin/Boolean = ..., kotlin/Function1<androidx.compose.ui.input.key/KeyEvent, kotlin/Boolean> = ..., kotlin/Function1<androidx.compose.ui.input.key/KeyEvent, kotlin/Boolean> = ..., kotlin/Function2<com.compose.sdl/RenderBackend, kotlin/Int, kotlin/Boolean>? = ..., kotlin/Function3<com.compose.sdl/ComposeWindowScope, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>) // com.compose.sdl/nativeComposeWindow|nativeComposeWindow(kotlin.String;kotlin.Int;kotlin.Int;com.compose.sdl.GpuMode;com.compose.sdl.AppWindowIcon?;kotlin.Boolean;kotlin.Boolean;kotlin.Boolean;kotlin.Boolean;kotlin.Boolean;kotlin.Boolean;kotlin.Function1<androidx.compose.ui.input.key.KeyEvent,kotlin.Boolean>;kotlin.Function1<androidx.compose.ui.input.key.KeyEvent,kotlin.Boolean>;kotlin.Function2<com.compose.sdl.RenderBackend,kotlin.Int,kotlin.Boolean>?;kotlin.Function3<com.compose.sdl.ComposeWindowScope,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>){}[0]
|
||||||
final fun com.compose.sdl/windowHasInvalidations(): kotlin/Boolean // com.compose.sdl/windowHasInvalidations|windowHasInvalidations(){}[0]
|
final fun com.compose.sdl/windowHasInvalidations(): kotlin/Boolean // com.compose.sdl/windowHasInvalidations|windowHasInvalidations(){}[0]
|
||||||
|
|||||||
+88
@@ -0,0 +1,88 @@
|
|||||||
|
@file:OptIn(
|
||||||
|
androidx.compose.ui.InternalComposeUiApi::class,
|
||||||
|
androidx.compose.runtime.InternalComposeApi::class,
|
||||||
|
)
|
||||||
|
|
||||||
|
package com.compose.sdl
|
||||||
|
|
||||||
|
import androidx.compose.runtime.AbstractApplier
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
|
||||||
|
// ==================
|
||||||
|
// MARK: App runtime internals
|
||||||
|
// ==================
|
||||||
|
|
||||||
|
internal class ApplicationScopeImpl(val runtime: AppRuntime) : ApplicationScope {
|
||||||
|
override fun exitApplication() { runtime.exitRequested = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Registry + lifecycle for the live windows. Windows are created by the app
|
||||||
|
composition (Window()'s remember) and destroyed by the LOOP - DisposableEffect
|
||||||
|
onDispose only schedules, because teardown disposes a composition and that
|
||||||
|
must not run re-entrantly inside another composition's apply pass. */
|
||||||
|
internal class AppRuntime {
|
||||||
|
lateinit var scope: CoroutineScope
|
||||||
|
val windows = mutableListOf<WindowInstance>()
|
||||||
|
private val destroyQueue = mutableListOf<WindowInstance>()
|
||||||
|
var exitRequested = false
|
||||||
|
var hadWindow = false
|
||||||
|
|
||||||
|
fun windowFor(inId: UInt): WindowInstance? =
|
||||||
|
if (inId == 0u) windows.firstOrNull()
|
||||||
|
else windows.firstOrNull { it.backend.windowId == inId } ?: windows.firstOrNull()
|
||||||
|
|
||||||
|
fun markAllNeedFrame() {
|
||||||
|
for (vW in windows) vW.needsFrame = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createWindow(
|
||||||
|
inTitle: String,
|
||||||
|
inWidth: Int,
|
||||||
|
inHeight: Int,
|
||||||
|
inGpu: GpuMode,
|
||||||
|
inIcon: AppWindowIcon?,
|
||||||
|
inAttrs: WindowAttributes,
|
||||||
|
inOnFrame: ((RenderBackend, Int) -> Boolean)?,
|
||||||
|
inPreviewKeyHandler: () -> ((androidx.compose.ui.input.key.KeyEvent) -> Boolean),
|
||||||
|
inKeyHandler: () -> ((androidx.compose.ui.input.key.KeyEvent) -> Boolean),
|
||||||
|
inContent: () -> (@Composable ComposeWindowScope.() -> Unit),
|
||||||
|
): WindowInstance {
|
||||||
|
val vWindow = WindowInstance(
|
||||||
|
inTitle, inWidth, inHeight, inGpu, inIcon, inAttrs, inOnFrame,
|
||||||
|
inPreviewKeyHandler, inKeyHandler, inContent,
|
||||||
|
)
|
||||||
|
// A Window() was declared either way - the "exit when the last window
|
||||||
|
// is gone" rule must also fire when every declared window failed to
|
||||||
|
// initialise (otherwise the loop would spin forever with none).
|
||||||
|
hadWindow = true
|
||||||
|
if (vWindow.init(scope)) {
|
||||||
|
windows.add(vWindow)
|
||||||
|
} else {
|
||||||
|
println("nativeComposeApp: window '$inTitle' failed to initialise")
|
||||||
|
}
|
||||||
|
return vWindow
|
||||||
|
}
|
||||||
|
|
||||||
|
fun scheduleDestroy(inWindow: WindowInstance) {
|
||||||
|
if (inWindow in windows && inWindow !in destroyQueue) destroyQueue.add(inWindow)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun reapDestroyed() {
|
||||||
|
while (destroyQueue.isNotEmpty()) {
|
||||||
|
val vW = destroyQueue.removeLast()
|
||||||
|
windows.remove(vW)
|
||||||
|
vW.destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No-op applier for the app-level composition - it emits no UI nodes, only
|
||||||
|
// side effects (each Window() manages a native window).
|
||||||
|
internal class UnitApplier : AbstractApplier<Unit>(Unit) {
|
||||||
|
override fun insertTopDown(index: Int, instance: Unit) {}
|
||||||
|
override fun insertBottomUp(index: Int, instance: Unit) {}
|
||||||
|
override fun remove(index: Int, count: Int) {}
|
||||||
|
override fun move(from: Int, to: Int, count: Int) {}
|
||||||
|
override fun onClear() {}
|
||||||
|
}
|
||||||
+47
-679
@@ -5,46 +5,21 @@
|
|||||||
|
|
||||||
package com.compose.sdl
|
package com.compose.sdl
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.runtime.AbstractApplier
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.input.key.KeyEvent
|
||||||
import androidx.compose.runtime.Composition
|
import androidx.compose.runtime.Composition
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
|
||||||
import androidx.compose.runtime.Recomposer
|
import androidx.compose.runtime.Recomposer
|
||||||
import androidx.compose.runtime.SideEffect
|
import androidx.compose.runtime.SideEffect
|
||||||
import androidx.compose.runtime.DisposableEffect
|
import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberUpdatedState
|
import androidx.compose.runtime.rememberUpdatedState
|
||||||
import androidx.compose.runtime.snapshots.Snapshot
|
import androidx.compose.runtime.snapshots.Snapshot
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.input.key.key
|
|
||||||
import androidx.compose.ui.input.key.type
|
|
||||||
import androidx.compose.ui.input.pointer.PointerButton
|
|
||||||
import androidx.compose.ui.input.pointer.PointerEventType
|
|
||||||
import com.compose.sdl.node.ComposeRootHost
|
|
||||||
import com.compose.sdl.res.currentImageLoader
|
|
||||||
import com.compose.sdl.window.LocalPopupHost
|
|
||||||
import com.compose.sdl.window.PopupLayer
|
|
||||||
import com.compose.sdl.window.createPopupHostState
|
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.test.resetMain
|
import kotlinx.coroutines.test.resetMain
|
||||||
import kotlinx.coroutines.test.setMain
|
import kotlinx.coroutines.test.setMain
|
||||||
import kotlinx.cinterop.toKString
|
|
||||||
import kotlinx.cinterop.reinterpret
|
|
||||||
import kotlinx.cinterop.alloc
|
|
||||||
import kotlinx.cinterop.ptr
|
|
||||||
import kotlinx.cinterop.COpaquePointer
|
|
||||||
import kotlinx.cinterop.pointed
|
|
||||||
import sdl3.SDL_Delay
|
import sdl3.SDL_Delay
|
||||||
import sdl3.SDL_GetCurrentDisplayMode
|
|
||||||
import sdl3.SDL_GetDisplayForWindow
|
|
||||||
import sdl3.SDL_GetPerformanceCounter
|
|
||||||
import sdl3.SDL_GetPerformanceFrequency
|
|
||||||
import sdl3.SDL_GetTicks
|
import sdl3.SDL_GetTicks
|
||||||
import sdl3.SDL_GetTicksNS
|
|
||||||
import sdl3.SDL_Quit
|
import sdl3.SDL_Quit
|
||||||
import sdl3.SDL_SetWindowTitle
|
|
||||||
import sdl3.SDL_WaitEventTimeout
|
import sdl3.SDL_WaitEventTimeout
|
||||||
|
|
||||||
// ==================
|
// ==================
|
||||||
@@ -92,6 +67,14 @@ fun ApplicationScope.Window(
|
|||||||
height: Int = 600,
|
height: Int = 600,
|
||||||
gpu: GpuMode = GpuMode.Auto,
|
gpu: GpuMode = GpuMode.Auto,
|
||||||
icon: AppWindowIcon? = null,
|
icon: AppWindowIcon? = null,
|
||||||
|
undecorated: Boolean = false,
|
||||||
|
transparent: Boolean = false,
|
||||||
|
resizable: Boolean = true,
|
||||||
|
enabled: Boolean = true,
|
||||||
|
focusable: Boolean = true,
|
||||||
|
alwaysOnTop: Boolean = false,
|
||||||
|
onPreviewKeyEvent: (KeyEvent) -> Boolean = { false },
|
||||||
|
onKeyEvent: (KeyEvent) -> Boolean = { false },
|
||||||
onFrame: ((backend: RenderBackend, frameIndex: Int) -> Boolean)? = null,
|
onFrame: ((backend: RenderBackend, frameIndex: Int) -> Boolean)? = null,
|
||||||
content: @Composable ComposeWindowScope.() -> Unit,
|
content: @Composable ComposeWindowScope.() -> Unit,
|
||||||
) {
|
) {
|
||||||
@@ -99,6 +82,16 @@ fun ApplicationScope.Window(
|
|||||||
?: error("Window() must be called inside nativeComposeApp { ... }")
|
?: error("Window() must be called inside nativeComposeApp { ... }")
|
||||||
val vContent = rememberUpdatedState(content)
|
val vContent = rememberUpdatedState(content)
|
||||||
val vClose = rememberUpdatedState(onCloseRequest)
|
val vClose = rememberUpdatedState(onCloseRequest)
|
||||||
|
val vPreviewKey = rememberUpdatedState(onPreviewKeyEvent)
|
||||||
|
val vKey = rememberUpdatedState(onKeyEvent)
|
||||||
|
val vAttrs = WindowAttributes(
|
||||||
|
undecorated = undecorated,
|
||||||
|
transparent = transparent,
|
||||||
|
resizable = resizable,
|
||||||
|
enabled = enabled,
|
||||||
|
focusable = focusable,
|
||||||
|
alwaysOnTop = alwaysOnTop,
|
||||||
|
)
|
||||||
val vWindow = remember {
|
val vWindow = remember {
|
||||||
vScope.runtime.createWindow(
|
vScope.runtime.createWindow(
|
||||||
inTitle = title,
|
inTitle = title,
|
||||||
@@ -106,7 +99,12 @@ fun ApplicationScope.Window(
|
|||||||
inHeight = height,
|
inHeight = height,
|
||||||
inGpu = gpu,
|
inGpu = gpu,
|
||||||
inIcon = icon,
|
inIcon = icon,
|
||||||
|
inAttrs = vAttrs,
|
||||||
inOnFrame = onFrame,
|
inOnFrame = onFrame,
|
||||||
|
// Read through holders so updated lambdas propagate without
|
||||||
|
// recreating the window (same reason as the content holder below).
|
||||||
|
inPreviewKeyHandler = { vPreviewKey.value },
|
||||||
|
inKeyHandler = { vKey.value },
|
||||||
// The window composition reads the holder each recomposition, so
|
// The window composition reads the holder each recomposition, so
|
||||||
// updated content lambdas propagate without recreating the window.
|
// updated content lambdas propagate without recreating the window.
|
||||||
inContent = { vContent.value },
|
inContent = { vContent.value },
|
||||||
@@ -115,6 +113,12 @@ fun ApplicationScope.Window(
|
|||||||
SideEffect {
|
SideEffect {
|
||||||
if (vWindow.facade.title != title) vWindow.facade.setTitle(title)
|
if (vWindow.facade.title != title) vWindow.facade.setTitle(title)
|
||||||
}
|
}
|
||||||
|
// Re-apply only on a real change; `transparent` is creation-only (see
|
||||||
|
// WindowAttributes) so it is deliberately not re-applied here.
|
||||||
|
DisposableEffect(vAttrs) {
|
||||||
|
vWindow.applyAttributes(vAttrs)
|
||||||
|
onDispose { }
|
||||||
|
}
|
||||||
DisposableEffect(Unit) {
|
DisposableEffect(Unit) {
|
||||||
onDispose { vScope.runtime.scheduleDestroy(vWindow) }
|
onDispose { vScope.runtime.scheduleDestroy(vWindow) }
|
||||||
}
|
}
|
||||||
@@ -136,7 +140,7 @@ fun nativeComposeApp(content: @Composable ApplicationScope.() -> Unit) {
|
|||||||
runtime.scope = this
|
runtime.scope = this
|
||||||
|
|
||||||
// App-level composition: no UI tree - it only declares Window()s.
|
// App-level composition: no UI tree - it only declares Window()s.
|
||||||
val appClock = SDL3FrameClock()
|
val appClock = Sdl3FrameClock()
|
||||||
val appRecomposer = Recomposer(coroutineContext + appClock)
|
val appRecomposer = Recomposer(coroutineContext + appClock)
|
||||||
// The clock must be in the collector's context - runRecomposeAndApplyChanges
|
// The clock must be in the collector's context - runRecomposeAndApplyChanges
|
||||||
// awaits parent frames through it.
|
// awaits parent frames through it.
|
||||||
@@ -311,74 +315,6 @@ fun nativeComposeApp(content: @Composable ApplicationScope.() -> Unit) {
|
|||||||
SDL_Quit()
|
SDL_Quit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================
|
|
||||||
// MARK: Probe / screenshot support (render-to-quiescence)
|
|
||||||
// ==================
|
|
||||||
|
|
||||||
/** Set BEFORE nativeComposeApp/nativeComposeWindow: every window's composition then runs
|
|
||||||
under an InfiniteAnimationPolicy that CANCELS infinite animations, so
|
|
||||||
rememberInfiniteTransition & co. freeze at their initial value - the same mechanism
|
|
||||||
upstream's test rules use. Screenshot/parity runs enable it so looping screens can
|
|
||||||
reach quiescence and capture deterministically. */
|
|
||||||
var disableInfiniteAnimations: Boolean = false
|
|
||||||
|
|
||||||
/** The cancelling policy: a coroutine that ends in CancellationException counts as
|
|
||||||
cancelled (not failed), so only the animation coroutine stops - nothing propagates. */
|
|
||||||
private object CancelInfiniteAnimationsPolicy : androidx.compose.ui.platform.InfiniteAnimationPolicy {
|
|
||||||
override suspend fun <R> onInfiniteOperation(block: suspend () -> R): R =
|
|
||||||
throw CancellationException("infinite animations are disabled (disableInfiniteAnimations)")
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set BEFORE nativeComposeApp/nativeComposeWindow: the composition + animation frame
|
|
||||||
clocks advance a VIRTUAL 16.6ms per main-loop iteration instead of reading SDL's
|
|
||||||
real-time ticks - the native mirror of the JVM parity leg's render(nanos) stepping.
|
|
||||||
Animations then progress by exact per-frame deltas, so anything time-raced (e.g. a
|
|
||||||
bring-into-view scroll interrupted mid-flight) resolves identically on every run and
|
|
||||||
screenshots become deterministic. Input timestamps and FPS stay on real time. */
|
|
||||||
var useVirtualFrameTime: Boolean = false
|
|
||||||
|
|
||||||
private var virtualFrameNanos = 0L
|
|
||||||
|
|
||||||
private fun advanceVirtualFrame() {
|
|
||||||
if (useVirtualFrameTime) virtualFrameNanos += 16_666_667L
|
|
||||||
}
|
|
||||||
|
|
||||||
// Timestamp for the composition frame clocks (recomposer + withFrameNanos animations).
|
|
||||||
private fun frameClockNanos(): Long =
|
|
||||||
if (useVirtualFrameTime) virtualFrameNanos else SDL_GetTicksNS().toLong()
|
|
||||||
|
|
||||||
// Timestamp for the owner's node-animation clock - real path keeps the pre-existing
|
|
||||||
// ms-resolution SDL_GetTicks base so non-screenshot behaviour is bit-for-bit unchanged.
|
|
||||||
private fun animationClockNanos(): Long =
|
|
||||||
if (useVirtualFrameTime) virtualFrameNanos else SDL_GetTicks().toLong() * 1_000_000L
|
|
||||||
|
|
||||||
// The window currently inside renderFrame - the loop is single-threaded, so a plain
|
|
||||||
// var is enough for onFrame probes to address "the window I'm being called for".
|
|
||||||
private var renderingWindow: WindowInstance? = null
|
|
||||||
|
|
||||||
/** From inside an onFrame callback: true while the just-rendered window still has pending
|
|
||||||
work (recomposition, layout/draw invalidation, or an animation awaiting the next frame).
|
|
||||||
Screenshot probes capture once this stays false for a few consecutive frames instead of
|
|
||||||
at a fixed frame count. Outside onFrame it answers false. */
|
|
||||||
fun windowHasInvalidations(): Boolean = renderingWindow?.hasInvalidations() ?: false
|
|
||||||
|
|
||||||
/** Trigger a Kotlin/Native GC so Cleaner-managed renderer resources release
|
|
||||||
their native memory (see the main loop's native-memory nudge). */
|
|
||||||
@OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
|
||||||
private fun collectNativeGarbage() = kotlin.native.runtime.GC.collect()
|
|
||||||
|
|
||||||
/** Frame interval (ms) of the window's current display, for the non-vsync
|
|
||||||
fallback pacing (SDL_Delay). Falls back to 16ms (~60Hz) when the mode can't
|
|
||||||
be read, so a 144Hz panel on a non-vsync path isn't capped to 60. */
|
|
||||||
@OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
|
|
||||||
private fun displayFrameDelayMs(window: COpaquePointer?): UInt {
|
|
||||||
val vWindow = window ?: return 16u
|
|
||||||
val vDisplay = SDL_GetDisplayForWindow(vWindow.reinterpret())
|
|
||||||
val vMode = SDL_GetCurrentDisplayMode(vDisplay) ?: return 16u
|
|
||||||
val vHz = vMode.pointed.refresh_rate
|
|
||||||
return if (vHz > 0f) (1000f / vHz).toUInt().coerceAtLeast(1u) else 16u
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Single-window compatibility wrapper - the pre-multi-window entry point.
|
/** Single-window compatibility wrapper - the pre-multi-window entry point.
|
||||||
Closing the window exits the app, exactly as before. */
|
Closing the window exits the app, exactly as before. */
|
||||||
fun nativeComposeWindow(
|
fun nativeComposeWindow(
|
||||||
@@ -387,6 +323,14 @@ fun nativeComposeWindow(
|
|||||||
height: Int = 600,
|
height: Int = 600,
|
||||||
gpu: GpuMode = GpuMode.Auto,
|
gpu: GpuMode = GpuMode.Auto,
|
||||||
icon: AppWindowIcon? = null,
|
icon: AppWindowIcon? = null,
|
||||||
|
undecorated: Boolean = false,
|
||||||
|
transparent: Boolean = false,
|
||||||
|
resizable: Boolean = true,
|
||||||
|
enabled: Boolean = true,
|
||||||
|
focusable: Boolean = true,
|
||||||
|
alwaysOnTop: Boolean = false,
|
||||||
|
onPreviewKeyEvent: (KeyEvent) -> Boolean = { false },
|
||||||
|
onKeyEvent: (KeyEvent) -> Boolean = { false },
|
||||||
onFrame: ((backend: RenderBackend, frameIndex: Int) -> Boolean)? = null,
|
onFrame: ((backend: RenderBackend, frameIndex: Int) -> Boolean)? = null,
|
||||||
content: @Composable ComposeWindowScope.() -> Unit,
|
content: @Composable ComposeWindowScope.() -> Unit,
|
||||||
) {
|
) {
|
||||||
@@ -398,592 +342,16 @@ fun nativeComposeWindow(
|
|||||||
height = height,
|
height = height,
|
||||||
gpu = gpu,
|
gpu = gpu,
|
||||||
icon = icon,
|
icon = icon,
|
||||||
|
undecorated = undecorated,
|
||||||
|
transparent = transparent,
|
||||||
|
resizable = resizable,
|
||||||
|
enabled = enabled,
|
||||||
|
focusable = focusable,
|
||||||
|
alwaysOnTop = alwaysOnTop,
|
||||||
|
onPreviewKeyEvent = onPreviewKeyEvent,
|
||||||
|
onKeyEvent = onKeyEvent,
|
||||||
onFrame = onFrame,
|
onFrame = onFrame,
|
||||||
content = content,
|
content = content,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================
|
|
||||||
// MARK: App runtime internals
|
|
||||||
// ==================
|
|
||||||
|
|
||||||
internal class ApplicationScopeImpl(val runtime: AppRuntime) : ApplicationScope {
|
|
||||||
override fun exitApplication() { runtime.exitRequested = true }
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Registry + lifecycle for the live windows. Windows are created by the app
|
|
||||||
composition (Window()'s remember) and destroyed by the LOOP - DisposableEffect
|
|
||||||
onDispose only schedules, because teardown disposes a composition and that
|
|
||||||
must not run re-entrantly inside another composition's apply pass. */
|
|
||||||
internal class AppRuntime {
|
|
||||||
lateinit var scope: CoroutineScope
|
|
||||||
val windows = mutableListOf<WindowInstance>()
|
|
||||||
private val destroyQueue = mutableListOf<WindowInstance>()
|
|
||||||
var exitRequested = false
|
|
||||||
var hadWindow = false
|
|
||||||
|
|
||||||
fun windowFor(inId: UInt): WindowInstance? =
|
|
||||||
if (inId == 0u) windows.firstOrNull()
|
|
||||||
else windows.firstOrNull { it.backend.windowId == inId } ?: windows.firstOrNull()
|
|
||||||
|
|
||||||
fun markAllNeedFrame() {
|
|
||||||
for (vW in windows) vW.needsFrame = true
|
|
||||||
}
|
|
||||||
|
|
||||||
fun createWindow(
|
|
||||||
inTitle: String,
|
|
||||||
inWidth: Int,
|
|
||||||
inHeight: Int,
|
|
||||||
inGpu: GpuMode,
|
|
||||||
inIcon: AppWindowIcon?,
|
|
||||||
inOnFrame: ((RenderBackend, Int) -> Boolean)?,
|
|
||||||
inContent: () -> (@Composable ComposeWindowScope.() -> Unit),
|
|
||||||
): WindowInstance {
|
|
||||||
val vWindow = WindowInstance(inTitle, inWidth, inHeight, inGpu, inIcon, inOnFrame, inContent)
|
|
||||||
// A Window() was declared either way - the "exit when the last window
|
|
||||||
// is gone" rule must also fire when every declared window failed to
|
|
||||||
// initialise (otherwise the loop would spin forever with none).
|
|
||||||
hadWindow = true
|
|
||||||
if (vWindow.init(scope)) {
|
|
||||||
windows.add(vWindow)
|
|
||||||
} else {
|
|
||||||
println("nativeComposeApp: window '$inTitle' failed to initialise")
|
|
||||||
}
|
|
||||||
return vWindow
|
|
||||||
}
|
|
||||||
|
|
||||||
fun scheduleDestroy(inWindow: WindowInstance) {
|
|
||||||
if (inWindow in windows && inWindow !in destroyQueue) destroyQueue.add(inWindow)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun reapDestroyed() {
|
|
||||||
while (destroyQueue.isNotEmpty()) {
|
|
||||||
val vW = destroyQueue.removeLast()
|
|
||||||
windows.remove(vW)
|
|
||||||
vW.destroy()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// No-op applier for the app-level composition - it emits no UI nodes, only
|
|
||||||
// side effects (each Window() manages a native window).
|
|
||||||
private class UnitApplier : AbstractApplier<Unit>(Unit) {
|
|
||||||
override fun insertTopDown(index: Int, instance: Unit) {}
|
|
||||||
override fun insertBottomUp(index: Int, instance: Unit) {}
|
|
||||||
override fun remove(index: Int, count: Int) {}
|
|
||||||
override fun move(from: Int, to: Int, count: Int) {}
|
|
||||||
override fun onClear() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==================
|
|
||||||
// MARK: WindowInstance - one SDL window + renderer + composition
|
|
||||||
// ==================
|
|
||||||
|
|
||||||
internal class WindowInstance(
|
|
||||||
private val initialTitle: String,
|
|
||||||
inWidth: Int,
|
|
||||||
inHeight: Int,
|
|
||||||
inGpu: GpuMode,
|
|
||||||
inIcon: AppWindowIcon?,
|
|
||||||
private val onFrame: ((RenderBackend, Int) -> Boolean)?,
|
|
||||||
private val contentHolder: () -> (@Composable ComposeWindowScope.() -> Unit),
|
|
||||||
) {
|
|
||||||
// Resolved renderer mode. `var` so init() can fall back GPU → CPU raster when
|
|
||||||
// a Skia GPU context can't be created (RDP / headless / missing GL driver).
|
|
||||||
private var gpuMode = if (inGpu is GpuMode.Auto) rendererPreferredGpuMode() else inGpu
|
|
||||||
private val initialWidth = inWidth
|
|
||||||
private val initialHeight = inHeight
|
|
||||||
private val icon = inIcon
|
|
||||||
// Assigned by init() from the first backend that comes up (see makeBackend()).
|
|
||||||
lateinit var backend: SDL3Backend
|
|
||||||
private set
|
|
||||||
private var renderBackend: RenderBackend? = null
|
|
||||||
lateinit var host: ComposeRootHost
|
|
||||||
private set
|
|
||||||
lateinit var facade: ComposeNativeWindow
|
|
||||||
private set
|
|
||||||
private var popupHost: com.compose.sdl.window.PopupHostState? = null
|
|
||||||
|
|
||||||
val frameClock = SDL3FrameClock()
|
|
||||||
private var recomposer: Recomposer? = null
|
|
||||||
private var recomposeJob: Job? = null
|
|
||||||
private var composition: Composition? = null
|
|
||||||
|
|
||||||
// Set by Window(); the compat wrapper points it at exitApplication().
|
|
||||||
var onCloseRequest: () -> Unit = {}
|
|
||||||
var closeDispatched = false
|
|
||||||
|
|
||||||
// Render-on-demand flag (see the pre-multi-window loop): set by events,
|
|
||||||
// state writes (global observer), resize, expose.
|
|
||||||
var needsFrame = true
|
|
||||||
|
|
||||||
// Hover refresh: last pointer position in PIXEL space, re-dispatched as a
|
|
||||||
// synthetic Move after layout so items scrolled under the cursor hover.
|
|
||||||
private var lastMouseX = -1f
|
|
||||||
private var lastMouseY = -1f
|
|
||||||
private var hasMousePos = false
|
|
||||||
|
|
||||||
private var frameIndex = 0
|
|
||||||
private var fpsEma = 0.0
|
|
||||||
private var fpsLastFrameMs = SDL_GetTicks()
|
|
||||||
private var fpsLastTitleMs = 0uL
|
|
||||||
|
|
||||||
// Escape → back (upstream desktop's BackNavigationEventInput): unconsumed
|
|
||||||
// Escape completes a back navigation on THIS window's dispatcher.
|
|
||||||
private val navigationEventOwner = object : androidx.navigationevent.NavigationEventDispatcherOwner {
|
|
||||||
override val navigationEventDispatcher = androidx.navigationevent.NavigationEventDispatcher()
|
|
||||||
}
|
|
||||||
private val backNavigationInput = BackNavigationInput()
|
|
||||||
|
|
||||||
// WINDOW-scoped architecture-components owner (Lifecycle + ViewModelStore +
|
|
||||||
// SavedStateRegistry) - the same trio upstream desktop's
|
|
||||||
// DefaultArchitectureComponentsOwner supplies through the window
|
|
||||||
// PlatformContext (compose/ui skikoMain PlatformOwnerProvider.skiko.kt).
|
|
||||||
// viewModel(), SavedStateHandle plumbing and navigation3's
|
|
||||||
// rememberViewModelStoreNavEntryDecorator all resolve their parent owners
|
|
||||||
// from this; destroy() moves it to DESTROYED and clears the store.
|
|
||||||
private val architectureOwner = WindowArchitectureOwner()
|
|
||||||
|
|
||||||
// Window focus / visibility → Lifecycle.State, Compose Desktop's mapping:
|
|
||||||
// focused → RESUMED, visible unfocused → STARTED, hidden/minimised →
|
|
||||||
// CREATED. Starts focused+visible (SDL fires FOCUS_GAINED right after
|
|
||||||
// creation anyway; headless probe runs simply stay RESUMED).
|
|
||||||
private var windowFocused = true
|
|
||||||
private var windowVisible = true
|
|
||||||
|
|
||||||
fun onActivationEvent(inEvent: AppEvent.WindowActivation) {
|
|
||||||
inEvent.focused?.let { windowFocused = it }
|
|
||||||
inEvent.visible?.let { windowVisible = it }
|
|
||||||
if (::host.isInitialized) host.setWindowFocused(windowFocused)
|
|
||||||
architectureOwner.setLifecycleState(
|
|
||||||
when {
|
|
||||||
!windowVisible -> androidx.lifecycle.Lifecycle.State.CREATED
|
|
||||||
windowFocused -> androidx.lifecycle.Lifecycle.State.RESUMED
|
|
||||||
else -> androidx.lifecycle.Lifecycle.State.STARTED
|
|
||||||
}
|
|
||||||
)
|
|
||||||
// Shown / restored / focus-gained also invalidate the contents - keep
|
|
||||||
// the pre-lifecycle RedrawNeeded behaviour of these SDL events.
|
|
||||||
needsFrame = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates + initialises an SDL3Backend for [mode] and its RenderBackend. On
|
|
||||||
// success commits `backend` and returns the renderer; else tears everything
|
|
||||||
// down and returns null so the caller can retry with a different mode.
|
|
||||||
private fun makeBackend(mode: GpuMode): RenderBackend? {
|
|
||||||
val vBackend = SDL3Backend(
|
|
||||||
initialTitle, initialWidth, initialHeight, gpuMode = mode,
|
|
||||||
iconLightResourcePaths = icon?.light ?: emptyList(),
|
|
||||||
iconDarkResourcePaths = icon?.dark ?: emptyList(),
|
|
||||||
)
|
|
||||||
if (!vBackend.init()) {
|
|
||||||
vBackend.destroy(inQuitSdl = false)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
vBackend.updateWindowSize()
|
|
||||||
val vRender = createRenderBackend(vBackend, mode)
|
|
||||||
if (vRender == null || !vRender.ensureSize(vBackend.pixelWidth, vBackend.pixelHeight)) {
|
|
||||||
vRender?.destroy()
|
|
||||||
vBackend.destroy(inQuitSdl = false)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
backend = vBackend
|
|
||||||
return vRender
|
|
||||||
}
|
|
||||||
|
|
||||||
fun init(inScope: CoroutineScope): Boolean {
|
|
||||||
// Try the resolved gpuMode; if it's a Skia GPU mode whose context/bridge
|
|
||||||
// can't come up (RDP / headless / missing GL driver), fall back once to
|
|
||||||
// CPU raster (Software) so the window still opens instead of failing.
|
|
||||||
var vRender = makeBackend(gpuMode)
|
|
||||||
if (vRender == null && gpuMode is GpuMode.Skia) {
|
|
||||||
println("GPU renderer ($gpuMode) unavailable - falling back to CPU raster (Software)")
|
|
||||||
gpuMode = GpuMode.Software
|
|
||||||
vRender = makeBackend(gpuMode)
|
|
||||||
}
|
|
||||||
if (vRender == null) {
|
|
||||||
println("Failed to init render backend")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
renderBackend = vRender
|
|
||||||
|
|
||||||
host = ComposeRootHost(inDensity = backend.pixelDensity)
|
|
||||||
host.attach()
|
|
||||||
// A layer whose content changed (OwnedLayer.invalidate) schedules a frame
|
|
||||||
// even when nothing else (recompose / relayout) is pending - retained layers
|
|
||||||
// need this so a draw-only state change still repaints.
|
|
||||||
host.setInvalidationCallback { needsFrame = true }
|
|
||||||
facade = ComposeNativeWindow(backend, gpuMode, initialTitle)
|
|
||||||
navigationEventOwner.navigationEventDispatcher.addInput(backNavigationInput)
|
|
||||||
|
|
||||||
// The render-bridge globals must point at THIS window's renderer while
|
|
||||||
// its content composes/measures (first composition happens inside
|
|
||||||
// setContent below).
|
|
||||||
installGlobals()
|
|
||||||
|
|
||||||
// Effect context for this window's composition - the screenshot flag injects the
|
|
||||||
// infinite-animation-cancelling policy (see disableInfiniteAnimations above).
|
|
||||||
var vEffectContext = inScope.coroutineContext + frameClock
|
|
||||||
if (disableInfiniteAnimations) vEffectContext += CancelInfiniteAnimationsPolicy
|
|
||||||
val vRecomposer = Recomposer(vEffectContext)
|
|
||||||
recomposer = vRecomposer
|
|
||||||
recomposeJob = inScope.launch(frameClock) { vRecomposer.runRecomposeAndApplyChanges() }
|
|
||||||
val vComposition = Composition(host.applier, vRecomposer)
|
|
||||||
composition = vComposition
|
|
||||||
|
|
||||||
val vUriHandler = object : androidx.compose.ui.platform.UriHandler {
|
|
||||||
override fun openUri(uri: String) { openUrl(uri) }
|
|
||||||
}
|
|
||||||
val vPopupHost = createPopupHostState()
|
|
||||||
popupHost = vPopupHost
|
|
||||||
val vWindowScope = object : ComposeWindowScope {
|
|
||||||
override val window: ComposeNativeWindow = facade
|
|
||||||
}
|
|
||||||
|
|
||||||
vComposition.setContent {
|
|
||||||
CompositionLocalProvider(
|
|
||||||
LocalComposeNativeWindow provides facade,
|
|
||||||
LocalPopupHost provides vPopupHost,
|
|
||||||
// Upstream vendored CompositionLocals.kt declares each of these as
|
|
||||||
// `staticCompositionLocalOf<T> { noLocalProvidedFor("…") }` - reading
|
|
||||||
// one without a Provider throws. Seed them all from the ComposeOwner.
|
|
||||||
androidx.compose.ui.platform.LocalDensity provides host.density,
|
|
||||||
androidx.compose.ui.platform.LocalLayoutDirection provides host.layoutDirection,
|
|
||||||
androidx.compose.ui.platform.LocalFocusManager provides host.focusManager,
|
|
||||||
androidx.compose.ui.platform.LocalGraphicsContext provides host.graphicsContext,
|
|
||||||
androidx.compose.ui.platform.LocalViewConfiguration provides host.viewConfiguration,
|
|
||||||
androidx.compose.ui.platform.LocalInputModeManager provides host.inputModeManager,
|
|
||||||
androidx.compose.ui.platform.LocalHapticFeedback provides host.hapticFeedback,
|
|
||||||
androidx.compose.ui.platform.LocalTextToolbar provides host.textToolbar,
|
|
||||||
androidx.compose.ui.platform.LocalWindowInfo provides host.windowInfo,
|
|
||||||
androidx.compose.ui.platform.LocalSoftwareKeyboardController provides host.softwareKeyboardController,
|
|
||||||
androidx.compose.ui.platform.LocalClipboard provides
|
|
||||||
androidx.compose.ui.platform.platformClipboard(),
|
|
||||||
androidx.compose.ui.platform.LocalFontFamilyResolver provides
|
|
||||||
com.compose.sdl.text.font.projectFontFamilyResolver,
|
|
||||||
androidx.compose.ui.platform.LocalUriHandler provides vUriHandler,
|
|
||||||
// Desktop windows have no system bars / notch / IME insets - the
|
|
||||||
// interface's all-zero defaults are exactly right.
|
|
||||||
androidx.compose.ui.platform.LocalPlatformWindowInsets provides
|
|
||||||
object : androidx.compose.ui.platform.PlatformWindowInsets {},
|
|
||||||
// The window's architecture-components owner backs all three arch
|
|
||||||
// locals, exactly like upstream desktop's window PlatformContext:
|
|
||||||
// - LocalLifecycleOwner: RESUMED for the window's whole life;
|
|
||||||
// lifecycle-aware content (NavDisplay, rememberLifecycleOwner, …)
|
|
||||||
// errors without it.
|
|
||||||
// - LocalViewModelStoreOwner: window-scoped ViewModels (google
|
|
||||||
// lifecycle-viewmodel-compose's local is a plain composition
|
|
||||||
// local; the JB HostDefault route doesn't exist in the google
|
|
||||||
// artifacts this port ships).
|
|
||||||
// - LocalSavedStateRegistryOwner: SavedStateHandle / rememberSaveable
|
|
||||||
// registry parent (nav3's ViewModelStoreNavEntryDecorator requires it).
|
|
||||||
androidx.lifecycle.compose.LocalLifecycleOwner provides architectureOwner,
|
|
||||||
androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner provides architectureOwner,
|
|
||||||
androidx.savedstate.compose.LocalSavedStateRegistryOwner provides architectureOwner,
|
|
||||||
// Runtime-level host defaults - this window's navigation-event
|
|
||||||
// owner (SearchBar / sheets back plumbing). The viewmodel store
|
|
||||||
// is provided through the plain LocalViewModelStoreOwner above
|
|
||||||
// instead: the google lifecycle artifacts this port ships have no
|
|
||||||
// HostDefault key for it (that mechanism is JB-variant-only).
|
|
||||||
androidx.compose.runtime.LocalHostDefaultProvider provides
|
|
||||||
remember {
|
|
||||||
object : androidx.compose.runtime.HostDefaultProvider {
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
override fun <T> getHostDefault(key: androidx.compose.runtime.HostDefaultKey<T>): T = when (key) {
|
|
||||||
androidx.navigationevent.compose.NavigationEventDispatcherOwnerHostDefaultKey -> navigationEventOwner
|
|
||||||
else -> null
|
|
||||||
} as T
|
|
||||||
}
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
// Seed the :ui-internal LocalPointerIconService so Modifier.pointerHoverIcon
|
|
||||||
// drives the SDL cursor (the local + service type can't cross the module boundary).
|
|
||||||
host.ProvidePointerIconService {
|
|
||||||
Box(modifier = Modifier.fillMaxSize()) {
|
|
||||||
// Read through the holder so Window() recompositions with a
|
|
||||||
// new content lambda propagate into this composition.
|
|
||||||
val vContent = contentHolder()
|
|
||||||
with(vWindowScope) { vContent() }
|
|
||||||
PopupLayer(vPopupHost)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// First composition done (setContent is synchronous) - promote the
|
|
||||||
// window lifecycle from CREATED to the focus/visibility-derived state.
|
|
||||||
// Composition itself runs at CREATED so enableSavedStateHandles()
|
|
||||||
// callers see a legal state, mirroring upstream desktop's
|
|
||||||
// compose-first-resume-after ordering.
|
|
||||||
architectureOwner.setLifecycleState(
|
|
||||||
when {
|
|
||||||
!windowVisible -> androidx.lifecycle.Lifecycle.State.CREATED
|
|
||||||
windowFocused -> androidx.lifecycle.Lifecycle.State.RESUMED
|
|
||||||
else -> androidx.lifecycle.Lifecycle.State.STARTED
|
|
||||||
}
|
|
||||||
)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Points the render-bridge globals (text measurer / image loader /
|
|
||||||
viewport) at this window's renderer. Must be called before composing,
|
|
||||||
measuring, or drawing this window's tree. */
|
|
||||||
fun installGlobals() {
|
|
||||||
val vRender = renderBackend ?: return
|
|
||||||
currentImageLoader = vRender.imageLoader
|
|
||||||
com.compose.sdl.text.currentViewportWidth = backend.pixelWidth
|
|
||||||
com.compose.sdl.text.currentViewportHeight = backend.pixelHeight
|
|
||||||
// Register bundled generic fonts (FontFamily.Monospace → NotoSansMono) once
|
|
||||||
// data.kres is loadable; idempotent, no-op if the font isn't bundled.
|
|
||||||
com.compose.sdl.text.registerGenericFonts()
|
|
||||||
// Position the OS IME candidate window the moment a field in THIS window
|
|
||||||
// gains focus, not only on the first TEXT_EDITING event (repointed per
|
|
||||||
// window here so multi-window focus targets the right SDL window).
|
|
||||||
com.compose.sdl.text.input.ImeBridge.onSessionActiveChange = { active ->
|
|
||||||
if (active) updateImeArea()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============
|
|
||||||
// Event handling (loop-routed, per window)
|
|
||||||
|
|
||||||
fun onPointerEvent(inEvent: AppEvent.Pointer) {
|
|
||||||
needsFrame = true
|
|
||||||
installGlobals()
|
|
||||||
val vType = when (inEvent.event.type) {
|
|
||||||
PointerEventType.Press -> 1
|
|
||||||
PointerEventType.Release -> 2
|
|
||||||
else -> 0
|
|
||||||
}
|
|
||||||
val vBtn = when (inEvent.event.button) {
|
|
||||||
PointerButton.Secondary -> 1
|
|
||||||
PointerButton.Tertiary -> 2
|
|
||||||
else -> 0
|
|
||||||
}
|
|
||||||
// SDL3 delivers mouse coords in logical points on HiDPI - multiply by
|
|
||||||
// DPR so hit-testing lands in the pixel space layout uses.
|
|
||||||
val vDpr = backend.pixelDensity
|
|
||||||
val vPx = inEvent.event.x * vDpr
|
|
||||||
val vPy = inEvent.event.y * vDpr
|
|
||||||
if (inEvent.event.type == PointerEventType.Press) {
|
|
||||||
popupHost?.notifyOutsidePress(vPx.toInt(), vPy.toInt())
|
|
||||||
}
|
|
||||||
host.onPointerRaw(vPx, vPy, vType, vBtn, SDL_GetTicks().toLong())
|
|
||||||
lastMouseX = vPx
|
|
||||||
lastMouseY = vPy
|
|
||||||
hasMousePos = true
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Pointer left the window (SDL_EVENT_WINDOW_MOUSE_LEAVE). Stop the per-frame
|
|
||||||
synthetic hover re-dispatch and fire one Exit at the last position so a
|
|
||||||
hovered widget clears its highlight instead of sticking forever. */
|
|
||||||
fun onPointerExit() {
|
|
||||||
needsFrame = true
|
|
||||||
if (hasMousePos) {
|
|
||||||
host.onPointerRaw(lastMouseX, lastMouseY, 3, 0, SDL_GetTicks().toLong())
|
|
||||||
}
|
|
||||||
hasMousePos = false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onWheelEvent(inEvent: AppEvent.MouseWheel) {
|
|
||||||
needsFrame = true
|
|
||||||
installGlobals()
|
|
||||||
val vDpr = backend.pixelDensity
|
|
||||||
host.onWheel(inEvent.x * vDpr, inEvent.y * vDpr, inEvent.deltaX, inEvent.deltaY, SDL_GetTicks().toLong())
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onKeyEvent(inEvent: AppEvent.Key) {
|
|
||||||
needsFrame = true
|
|
||||||
installGlobals()
|
|
||||||
// Focused chain → window-level shortcuts → back navigation (Escape).
|
|
||||||
if (!host.dispatchKeyEvent(inEvent.event) && !facade.dispatchKeyShortcut(inEvent.event)) {
|
|
||||||
backNavigationInput.onKeyEvent(inEvent.event)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onTextInputEvent(inEvent: AppEvent.TextInput) {
|
|
||||||
needsFrame = true
|
|
||||||
installGlobals()
|
|
||||||
// A focused text field runs an IME session (ComposeOwner.textInputSession):
|
|
||||||
// commit through it so the text REPLACES any active composition. Falls back
|
|
||||||
// to synthesising typed KeyEvents when no field is focused - SDL key events
|
|
||||||
// carry UNSHIFTED keycodes (no uppercase/numpad/dead keys), so committed
|
|
||||||
// text is the only layout-correct character source.
|
|
||||||
if (!com.compose.sdl.text.input.ImeBridge.commit(inEvent.text)) {
|
|
||||||
dispatchTypedText(host, inEvent.text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onTextEditingEvent(inEvent: AppEvent.TextEditing) {
|
|
||||||
needsFrame = true
|
|
||||||
installGlobals()
|
|
||||||
// IME preedit: show the composing (underlined) region in the focused field.
|
|
||||||
// No-op if no field is focused. Also nudge the OS candidate window to the
|
|
||||||
// field's on-screen rect.
|
|
||||||
com.compose.sdl.text.input.ImeBridge.compose(inEvent.text)
|
|
||||||
updateImeArea()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nudge the OS IME candidate window to the focused field's on-screen rect.
|
|
||||||
// Best-effort: no-op without an active session or a laid-out field.
|
|
||||||
@OptIn(androidx.compose.ui.ExperimentalComposeUiApi::class, kotlinx.cinterop.ExperimentalForeignApi::class)
|
|
||||||
private fun updateImeArea() {
|
|
||||||
val vRequest = com.compose.sdl.text.input.ImeBridge.request ?: return
|
|
||||||
val vRect = vRequest.focusedRectInRoot() ?: return
|
|
||||||
val vWindow = backend.window ?: return
|
|
||||||
val vDpr = backend.pixelDensity
|
|
||||||
kotlinx.cinterop.memScoped {
|
|
||||||
// SDL wants the area in logical window points; layout runs in physical px.
|
|
||||||
val vSdlRect = alloc<sdl3.SDL_Rect>()
|
|
||||||
vSdlRect.x = (vRect.left / vDpr).toInt()
|
|
||||||
vSdlRect.y = (vRect.top / vDpr).toInt()
|
|
||||||
vSdlRect.w = (vRect.width / vDpr).toInt().coerceAtLeast(1)
|
|
||||||
vSdlRect.h = (vRect.height / vDpr).toInt().coerceAtLeast(1)
|
|
||||||
sdl3.SDL_SetTextInputArea(vWindow.reinterpret(), vSdlRect.ptr, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onDropEvent(inEvent: AppEvent.Drop) {
|
|
||||||
needsFrame = true
|
|
||||||
installGlobals()
|
|
||||||
// SDL fires drop coords in logical points at DPR-1; scale to the pixel
|
|
||||||
// space layout runs in (Option-B density flow) so hit-testing lands
|
|
||||||
// where the pointer is.
|
|
||||||
val vDpr = backend.pixelDensity
|
|
||||||
when (inEvent.phase) {
|
|
||||||
AppEvent.DropPhase.BEGIN -> host.onDropBegin()
|
|
||||||
AppEvent.DropPhase.POSITION -> host.onDropPosition(inEvent.x * vDpr, inEvent.y * vDpr)
|
|
||||||
AppEvent.DropPhase.FILE -> inEvent.data?.let { host.onDropFile(it) }
|
|
||||||
AppEvent.DropPhase.TEXT -> inEvent.data?.let { host.onDropText(it) }
|
|
||||||
AppEvent.DropPhase.COMPLETE -> host.onDropComplete()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onResizedEvent() {
|
|
||||||
needsFrame = true
|
|
||||||
backend.updateWindowSize()
|
|
||||||
facade.onResized()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** OS light/dark theme changed - re-pick the theme-appropriate window icon
|
|
||||||
(no-op if this window has no icon configured or the choice is unchanged). */
|
|
||||||
fun onSystemThemeChanged() {
|
|
||||||
backend.applyThemeIcon()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** OS close button / app-level Quit: honour the veto handler, then hand the
|
|
||||||
decision to the Window() declaration. */
|
|
||||||
fun requestClose() {
|
|
||||||
if (closeDispatched) return
|
|
||||||
if (facade.requestCloseFromUser()) {
|
|
||||||
closeDispatched = true
|
|
||||||
onCloseRequest()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============
|
|
||||||
// Frame pump
|
|
||||||
|
|
||||||
fun shouldRender(): Boolean =
|
|
||||||
needsFrame || (recomposer?.hasPendingWork == true) || onFrame != null || kForceRender
|
|
||||||
|
|
||||||
/** True while this window still has pending work: a state/layout/draw invalidation
|
|
||||||
(needsFrame), recomposer work, or a composition/node animation awaiting the next
|
|
||||||
frame. Sampled by windowHasInvalidations() from onFrame probes - the quiescence
|
|
||||||
signal for render-to-settle screenshot capture. */
|
|
||||||
fun hasInvalidations(): Boolean =
|
|
||||||
needsFrame || recomposer?.hasPendingWork == true ||
|
|
||||||
frameClock.hasAwaiters || host.hasAnimationAwaiters()
|
|
||||||
|
|
||||||
fun renderFrame() {
|
|
||||||
val vRender = renderBackend ?: return
|
|
||||||
needsFrame = false
|
|
||||||
if (recomposer?.hasPendingWork == true) needsFrame = true
|
|
||||||
|
|
||||||
backend.updateWindowSize()
|
|
||||||
vRender.ensureSize(backend.pixelWidth, backend.pixelHeight)
|
|
||||||
// Charge the GPU back-buffer acquire to its own phase. On Metal this is
|
|
||||||
// where nextDrawable() blocks on vsync (the natural frame pacing), so
|
|
||||||
// folding it into "layout" made the profiler read the vsync wait as
|
|
||||||
// layout cost - a ~6-7ms phantom that hid the real (tiny) layout time.
|
|
||||||
FrameProfiler.phase(" acquire")
|
|
||||||
host.setConstraints(backend.pixelWidth, backend.pixelHeight)
|
|
||||||
// Deliver any state written by this iteration's frame-clock continuations
|
|
||||||
// (withFrameNanos animations - notably smooth wheel scrolling) BEFORE we lay
|
|
||||||
// out. Those writes happen in the per-window pump's sendFrame()/yield(), which
|
|
||||||
// is AFTER the loop's last sendApplyNotifications() - so without this the
|
|
||||||
// relayout they trigger wasn't registered until the next frame, and the frame
|
|
||||||
// drew last frame's positions. That one-frame trail read as "the clip is a
|
|
||||||
// frame late" when scrolling (content briefly drawn past the viewport edge).
|
|
||||||
Snapshot.sendApplyNotifications()
|
|
||||||
host.measureAndLayout()
|
|
||||||
FrameProfiler.phase(" layout")
|
|
||||||
|
|
||||||
// Hover refresh after layout (upstream skiko: SyntheticEventSender).
|
|
||||||
if (hasMousePos) {
|
|
||||||
host.onPointerRaw(lastMouseX, lastMouseY, 0, 0, SDL_GetTicks().toLong())
|
|
||||||
}
|
|
||||||
|
|
||||||
vRender.beginFrame(1f)
|
|
||||||
vRender.drawRoot { canvas -> host.drawRoot(canvas) }
|
|
||||||
if (onFrame != null) {
|
|
||||||
renderingWindow = this
|
|
||||||
val vContinue = onFrame.invoke(vRender, frameIndex)
|
|
||||||
renderingWindow = null
|
|
||||||
// Probe consumers end the app when their scenario completes.
|
|
||||||
if (!vContinue) facade.close()
|
|
||||||
}
|
|
||||||
FrameProfiler.phase(" draw")
|
|
||||||
vRender.endFrame()
|
|
||||||
FrameProfiler.phase(" present")
|
|
||||||
frameIndex++
|
|
||||||
|
|
||||||
// FPS - instantaneous inter-frame rate, EMA-smoothed, title refreshed
|
|
||||||
// ~4x/sec. This shows within ~2 rendered frames of ANY activity rather
|
|
||||||
// than waiting for a full second of unbroken rendering to accumulate
|
|
||||||
// (the old fixed-window counter never got its first update: bursty
|
|
||||||
// interaction kept idling before 1s elapsed, and the idle-skip reset the
|
|
||||||
// window each time - so FPS only appeared during a long enough page
|
|
||||||
// transition). A dt outside 1..100ms is the first frame or a resume from
|
|
||||||
// idle (the gap isn't a real frame interval), so it's not sampled - the
|
|
||||||
// title just holds the last active rate while idle.
|
|
||||||
val vNowMs = SDL_GetTicks()
|
|
||||||
val vDt = (vNowMs - fpsLastFrameMs).toInt()
|
|
||||||
fpsLastFrameMs = vNowMs
|
|
||||||
if (vDt in 1..100) {
|
|
||||||
val vInst = 1000.0 / vDt
|
|
||||||
fpsEma = if (fpsEma <= 0.0) vInst else fpsEma * 0.9 + vInst * 0.1
|
|
||||||
if ((vNowMs - fpsLastTitleMs).toInt() >= 250) {
|
|
||||||
val vFps = (fpsEma + 0.5).toInt()
|
|
||||||
facade.updateFps(vFps)
|
|
||||||
SDL_SetWindowTitle(backend.window?.reinterpret(), "${facade.title} · $vFps FPS")
|
|
||||||
fpsLastTitleMs = vNowMs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Idle-skip calls this: drop the frame timer so the resume-from-idle frame's
|
|
||||||
// dt (the whole idle gap) isn't sampled as a real interval. The EMA is left
|
|
||||||
// intact so the title keeps showing the last active rate while idle.
|
|
||||||
fun resetFpsWindow() {
|
|
||||||
fpsLastFrameMs = SDL_GetTicks()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun destroy() {
|
|
||||||
composition?.dispose()
|
|
||||||
composition = null
|
|
||||||
// Window gone → DESTROYED lifecycle + ViewModels cleared (onCleared
|
|
||||||
// runs), matching upstream desktop's window-scoped owner lifetime.
|
|
||||||
architectureOwner.destroy()
|
|
||||||
recomposer?.cancel()
|
|
||||||
recomposer = null
|
|
||||||
recomposeJob?.cancel()
|
|
||||||
recomposeJob = null
|
|
||||||
renderBackend?.destroy()
|
|
||||||
renderBackend = null
|
|
||||||
backend.destroy(inQuitSdl = false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WindowArchitectureOwner -> WindowArchitectureOwner.kt
|
|
||||||
// BackNavigationInput / dispatchTypedText -> WindowInputHelpers.kt
|
|
||||||
|
|||||||
+26
-26
@@ -18,56 +18,56 @@ import sdl3.SDL_GetTicks
|
|||||||
@OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
|
@OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
|
||||||
internal object FrameProfiler {
|
internal object FrameProfiler {
|
||||||
// null until first checked; then true/false for the run's lifetime.
|
// null until first checked; then true/false for the run's lifetime.
|
||||||
private var fEnabled: Boolean? = null
|
private var mEnabled: Boolean? = null
|
||||||
// Output file - resolved once from CDN_PROFILE. Writing to a file (not
|
// Output file - resolved once from CDN_PROFILE. Writing to a file (not
|
||||||
// stdout) lets GUI-subsystem apps (the demo links --subsystem,windows, so
|
// stdout) lets GUI-subsystem apps (the demo links --subsystem,windows, so
|
||||||
// it has no console) be profiled too. CDN_PROFILE=1 → "cdn_profile.log" in
|
// it has no console) be profiled too. CDN_PROFILE=1 → "cdn_profile.log" in
|
||||||
// the cwd; CDN_PROFILE=<path> → that path.
|
// the cwd; CDN_PROFILE=<path> → that path.
|
||||||
private var fPath: String = "cdn_profile.log"
|
private var mPath: String = "cdn_profile.log"
|
||||||
val enabled: Boolean
|
val enabled: Boolean
|
||||||
get() = fEnabled ?: run {
|
get() = mEnabled ?: run {
|
||||||
val vEnv = platform.posix.getenv("CDN_PROFILE")?.toKString()
|
val vEnv = platform.posix.getenv("CDN_PROFILE")?.toKString()
|
||||||
if (vEnv != null && vEnv != "1" && vEnv.isNotEmpty()) fPath = vEnv
|
if (vEnv != null && vEnv != "1" && vEnv.isNotEmpty()) mPath = vEnv
|
||||||
(vEnv != null).also { fEnabled = it }
|
(vEnv != null).also { mEnabled = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
private val fFreq = SDL_GetPerformanceFrequency().toDouble()
|
private val mFreq = SDL_GetPerformanceFrequency().toDouble()
|
||||||
// Insertion-ordered so the printed line follows the call order.
|
// Insertion-ordered so the printed line follows the call order.
|
||||||
private val fSum = LinkedHashMap<String, Double>()
|
private val mSum = LinkedHashMap<String, Double>()
|
||||||
private val fMax = LinkedHashMap<String, Double>()
|
private val mMax = LinkedHashMap<String, Double>()
|
||||||
private var fFrames = 0
|
private var mFrames = 0
|
||||||
private var fLastPrintMs = SDL_GetTicks()
|
private var mLastPrintMs = SDL_GetTicks()
|
||||||
private var fMark = 0uL
|
private var mMark = 0uL
|
||||||
|
|
||||||
fun mark() { if (enabled) fMark = SDL_GetPerformanceCounter() }
|
fun mark() { if (enabled) mMark = SDL_GetPerformanceCounter() }
|
||||||
|
|
||||||
fun phase(inName: String) {
|
fun phase(inName: String) {
|
||||||
if (!enabled) return
|
if (!enabled) return
|
||||||
val vNow = SDL_GetPerformanceCounter()
|
val vNow = SDL_GetPerformanceCounter()
|
||||||
val vMs = (vNow - fMark).toDouble() * 1000.0 / fFreq
|
val vMs = (vNow - mMark).toDouble() * 1000.0 / mFreq
|
||||||
fSum[inName] = (fSum[inName] ?: 0.0) + vMs
|
mSum[inName] = (mSum[inName] ?: 0.0) + vMs
|
||||||
if (vMs > (fMax[inName] ?: 0.0)) fMax[inName] = vMs
|
if (vMs > (mMax[inName] ?: 0.0)) mMax[inName] = vMs
|
||||||
fMark = vNow
|
mMark = vNow
|
||||||
}
|
}
|
||||||
|
|
||||||
fun frameDone(inRendered: Boolean) {
|
fun frameDone(inRendered: Boolean) {
|
||||||
if (!enabled) return
|
if (!enabled) return
|
||||||
if (inRendered) fFrames++
|
if (inRendered) mFrames++
|
||||||
val vNowMs = SDL_GetTicks()
|
val vNowMs = SDL_GetTicks()
|
||||||
if (vNowMs - fLastPrintMs >= 2000u && fFrames > 0) {
|
if (vNowMs - mLastPrintMs >= 2000u && mFrames > 0) {
|
||||||
val vParts = fSum.keys.map { vName ->
|
val vParts = mSum.keys.map { vName ->
|
||||||
val vAvg = (fSum[vName] ?: 0.0) / fFrames
|
val vAvg = (mSum[vName] ?: 0.0) / mFrames
|
||||||
"$vName=${(vAvg * 100).toInt() / 100.0}/${((fMax[vName] ?: 0.0) * 100).toInt() / 100.0}ms"
|
"$vName=${(vAvg * 100).toInt() / 100.0}/${((mMax[vName] ?: 0.0) * 100).toInt() / 100.0}ms"
|
||||||
}
|
}
|
||||||
val vLine = "[profile] frames=$fFrames avg/max " + vParts.joinToString(" ") + "\n"
|
val vLine = "[profile] frames=$mFrames avg/max " + vParts.joinToString(" ") + "\n"
|
||||||
val vFile = platform.posix.fopen(fPath, "a")
|
val vFile = platform.posix.fopen(mPath, "a")
|
||||||
if (vFile != null) {
|
if (vFile != null) {
|
||||||
platform.posix.fputs(vLine, vFile)
|
platform.posix.fputs(vLine, vFile)
|
||||||
platform.posix.fclose(vFile)
|
platform.posix.fclose(vFile)
|
||||||
}
|
}
|
||||||
fSum.clear(); fMax.clear()
|
mSum.clear(); mMax.clear()
|
||||||
fFrames = 0
|
mFrames = 0
|
||||||
fLastPrintMs = vNowMs
|
mLastPrintMs = vNowMs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+83
@@ -0,0 +1,83 @@
|
|||||||
|
@file:OptIn(
|
||||||
|
androidx.compose.ui.InternalComposeUiApi::class,
|
||||||
|
androidx.compose.runtime.InternalComposeApi::class,
|
||||||
|
)
|
||||||
|
|
||||||
|
package com.compose.sdl
|
||||||
|
|
||||||
|
import kotlinx.cinterop.COpaquePointer
|
||||||
|
import kotlinx.cinterop.reinterpret
|
||||||
|
import kotlinx.cinterop.pointed
|
||||||
|
import kotlinx.coroutines.CancellationException
|
||||||
|
import sdl3.SDL_GetCurrentDisplayMode
|
||||||
|
import sdl3.SDL_GetDisplayForWindow
|
||||||
|
import sdl3.SDL_GetTicks
|
||||||
|
import sdl3.SDL_GetTicksNS
|
||||||
|
|
||||||
|
// ==================
|
||||||
|
// MARK: Deterministic frame timing + probe/screenshot support
|
||||||
|
// ==================
|
||||||
|
|
||||||
|
/** Set BEFORE nativeComposeApp/nativeComposeWindow: every window's composition then runs
|
||||||
|
under an InfiniteAnimationPolicy that CANCELS infinite animations, so
|
||||||
|
rememberInfiniteTransition & co. freeze at their initial value - the same mechanism
|
||||||
|
upstream's test rules use. Screenshot/parity runs enable it so looping screens can
|
||||||
|
reach quiescence and capture deterministically. */
|
||||||
|
var disableInfiniteAnimations: Boolean = false
|
||||||
|
|
||||||
|
/** The cancelling policy: a coroutine that ends in CancellationException counts as
|
||||||
|
cancelled (not failed), so only the animation coroutine stops - nothing propagates. */
|
||||||
|
internal object CancelInfiniteAnimationsPolicy : androidx.compose.ui.platform.InfiniteAnimationPolicy {
|
||||||
|
override suspend fun <R> onInfiniteOperation(block: suspend () -> R): R =
|
||||||
|
throw CancellationException("infinite animations are disabled (disableInfiniteAnimations)")
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set BEFORE nativeComposeApp/nativeComposeWindow: the composition + animation frame
|
||||||
|
clocks advance a VIRTUAL 16.6ms per main-loop iteration instead of reading SDL's
|
||||||
|
real-time ticks - the native mirror of the JVM parity leg's render(nanos) stepping.
|
||||||
|
Animations then progress by exact per-frame deltas, so anything time-raced (e.g. a
|
||||||
|
bring-into-view scroll interrupted mid-flight) resolves identically on every run and
|
||||||
|
screenshots become deterministic. Input timestamps and FPS stay on real time. */
|
||||||
|
var useVirtualFrameTime: Boolean = false
|
||||||
|
|
||||||
|
private var virtualFrameNanos = 0L
|
||||||
|
|
||||||
|
internal fun advanceVirtualFrame() {
|
||||||
|
if (useVirtualFrameTime) virtualFrameNanos += 16_666_667L
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timestamp for the composition frame clocks (recomposer + withFrameNanos animations).
|
||||||
|
internal fun frameClockNanos(): Long =
|
||||||
|
if (useVirtualFrameTime) virtualFrameNanos else SDL_GetTicksNS().toLong()
|
||||||
|
|
||||||
|
// Timestamp for the owner's node-animation clock - real path keeps the pre-existing
|
||||||
|
// ms-resolution SDL_GetTicks base so non-screenshot behaviour is bit-for-bit unchanged.
|
||||||
|
internal fun animationClockNanos(): Long =
|
||||||
|
if (useVirtualFrameTime) virtualFrameNanos else SDL_GetTicks().toLong() * 1_000_000L
|
||||||
|
|
||||||
|
// The window currently inside renderFrame - the loop is single-threaded, so a plain
|
||||||
|
// var is enough for onFrame probes to address "the window I'm being called for".
|
||||||
|
internal var renderingWindow: WindowInstance? = null
|
||||||
|
|
||||||
|
/** From inside an onFrame callback: true while the just-rendered window still has pending
|
||||||
|
work (recomposition, layout/draw invalidation, or an animation awaiting the next frame).
|
||||||
|
Screenshot probes capture once this stays false for a few consecutive frames instead of
|
||||||
|
at a fixed frame count. Outside onFrame it answers false. */
|
||||||
|
fun windowHasInvalidations(): Boolean = renderingWindow?.hasInvalidations() ?: false
|
||||||
|
|
||||||
|
/** Trigger a Kotlin/Native GC so Cleaner-managed renderer resources release
|
||||||
|
their native memory (see the main loop's native-memory nudge). */
|
||||||
|
@OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||||
|
internal fun collectNativeGarbage() = kotlin.native.runtime.GC.collect()
|
||||||
|
|
||||||
|
/** Frame interval (ms) of the window's current display, for the non-vsync
|
||||||
|
fallback pacing (SDL_Delay). Falls back to 16ms (~60Hz) when the mode can't
|
||||||
|
be read, so a 144Hz panel on a non-vsync path isn't capped to 60. */
|
||||||
|
@OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
|
||||||
|
internal fun displayFrameDelayMs(window: COpaquePointer?): UInt {
|
||||||
|
val vWindow = window ?: return 16u
|
||||||
|
val vDisplay = SDL_GetDisplayForWindow(vWindow.reinterpret())
|
||||||
|
val vMode = SDL_GetCurrentDisplayMode(vDisplay) ?: return 16u
|
||||||
|
val vHz = vMode.pointed.refresh_rate
|
||||||
|
return if (vHz > 0f) (1000f / vHz).toUInt().coerceAtLeast(1u) else 16u
|
||||||
|
}
|
||||||
+1
-1
@@ -20,7 +20,7 @@ import sdl3.SDL_GetTicksNS
|
|||||||
|
|
||||||
Both come from delegating to the runtime's BroadcastFrameClock, which is
|
Both come from delegating to the runtime's BroadcastFrameClock, which is
|
||||||
exactly upstream's dispatch structure. */
|
exactly upstream's dispatch structure. */
|
||||||
internal class SDL3FrameClock : MonotonicFrameClock {
|
internal class Sdl3FrameClock : MonotonicFrameClock {
|
||||||
private val broadcast = BroadcastFrameClock()
|
private val broadcast = BroadcastFrameClock()
|
||||||
|
|
||||||
override suspend fun <R> withFrameNanos(onFrame: (Long) -> R): R =
|
override suspend fun <R> withFrameNanos(onFrame: (Long) -> R): R =
|
||||||
+7
-7
@@ -36,16 +36,16 @@ import sdl3.SDL_GetCurrentThreadID
|
|||||||
writes land at the loop's drainPending(), observable on the same frame. */
|
writes land at the loop's drainPending(), observable on the same frame. */
|
||||||
internal class Sdl3MainDispatcher : MainCoroutineDispatcher() {
|
internal class Sdl3MainDispatcher : MainCoroutineDispatcher() {
|
||||||
|
|
||||||
private val fQueue = Channel<Runnable>(Channel.UNLIMITED)
|
private val mQueue = Channel<Runnable>(Channel.UNLIMITED)
|
||||||
|
|
||||||
// The SDL main thread - the dispatcher is constructed by nativeComposeApp
|
// The SDL main thread - the dispatcher is constructed by nativeComposeApp
|
||||||
// on the thread that then runs the loop.
|
// on the thread that then runs the loop.
|
||||||
private val fMainThreadId = SDL_GetCurrentThreadID()
|
private val mMainThreadId = SDL_GetCurrentThreadID()
|
||||||
|
|
||||||
override val immediate: MainCoroutineDispatcher = ImmediateDispatcher()
|
override val immediate: MainCoroutineDispatcher = ImmediateDispatcher()
|
||||||
|
|
||||||
override fun dispatch(context: CoroutineContext, block: Runnable) {
|
override fun dispatch(context: CoroutineContext, block: Runnable) {
|
||||||
fQueue.trySend(block)
|
mQueue.trySend(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Drains all pending tasks. Called from the SDL3 main loop once per
|
/** Drains all pending tasks. Called from the SDL3 main loop once per
|
||||||
@@ -54,7 +54,7 @@ internal class Sdl3MainDispatcher : MainCoroutineDispatcher() {
|
|||||||
composition. */
|
composition. */
|
||||||
fun drainPending() {
|
fun drainPending() {
|
||||||
while (true) {
|
while (true) {
|
||||||
val vTask = fQueue.tryReceive().getOrNull() ?: break
|
val vTask = mQueue.tryReceive().getOrNull() ?: break
|
||||||
runCatching { vTask.run() }.onFailure { vErr ->
|
runCatching { vTask.run() }.onFailure { vErr ->
|
||||||
println("Sdl3MainDispatcher: dispatched task threw: ${vErr.message}")
|
println("Sdl3MainDispatcher: dispatched task threw: ${vErr.message}")
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,7 @@ internal class Sdl3MainDispatcher : MainCoroutineDispatcher() {
|
|||||||
/** Closes the queue. After this, dispatch() drops new posts silently.
|
/** Closes the queue. After this, dispatch() drops new posts silently.
|
||||||
Called from nativeComposeWindow as part of shutdown. */
|
Called from nativeComposeWindow as part of shutdown. */
|
||||||
fun close() {
|
fun close() {
|
||||||
fQueue.close()
|
mQueue.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String = "Sdl3MainDispatcher"
|
override fun toString(): String = "Sdl3MainDispatcher"
|
||||||
@@ -75,10 +75,10 @@ internal class Sdl3MainDispatcher : MainCoroutineDispatcher() {
|
|||||||
override val immediate: MainCoroutineDispatcher get() = this
|
override val immediate: MainCoroutineDispatcher get() = this
|
||||||
|
|
||||||
override fun isDispatchNeeded(context: CoroutineContext): Boolean =
|
override fun isDispatchNeeded(context: CoroutineContext): Boolean =
|
||||||
SDL_GetCurrentThreadID() != fMainThreadId
|
SDL_GetCurrentThreadID() != mMainThreadId
|
||||||
|
|
||||||
override fun dispatch(context: CoroutineContext, block: Runnable) {
|
override fun dispatch(context: CoroutineContext, block: Runnable) {
|
||||||
fQueue.trySend(block)
|
mQueue.trySend(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String = "Sdl3MainDispatcher.immediate"
|
override fun toString(): String = "Sdl3MainDispatcher.immediate"
|
||||||
|
|||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
package com.compose.sdl
|
||||||
|
|
||||||
|
// ==================
|
||||||
|
// MARK: WindowAttributes
|
||||||
|
// ==================
|
||||||
|
|
||||||
|
/**
|
||||||
|
The Compose Desktop `Window()` attributes this port supports, bundled so they
|
||||||
|
travel as one value from the composable down to [WindowInstance] instead of as
|
||||||
|
six positional booleans.
|
||||||
|
|
||||||
|
[transparent] is creation-only: SDL needs "SDL_WINDOW_TRANSPARENT" at
|
||||||
|
"SDL_CreateWindow" time and offers no setter, so changing it after the window
|
||||||
|
exists has no effect. The rest are re-applied whenever "Window()" recomposes
|
||||||
|
with a new value.
|
||||||
|
*/
|
||||||
|
internal data class WindowAttributes(
|
||||||
|
/** Hides the title bar and border (`SDL_WINDOW_BORDERLESS`). */
|
||||||
|
val undecorated: Boolean = false,
|
||||||
|
/** Per-pixel alpha for the window surface. CREATION-ONLY - see above. */
|
||||||
|
val transparent: Boolean = false,
|
||||||
|
/** Whether the user can resize the window. */
|
||||||
|
val resizable: Boolean = true,
|
||||||
|
/** False drops input (pointer / key / text / wheel / drop) while the window
|
||||||
|
keeps rendering - Compose Desktop's `enabled = false` behaviour. */
|
||||||
|
val enabled: Boolean = true,
|
||||||
|
/** False stops the window taking keyboard focus when clicked or raised. */
|
||||||
|
val focusable: Boolean = true,
|
||||||
|
/** Keeps the window above other windows. */
|
||||||
|
val alwaysOnTop: Boolean = false,
|
||||||
|
)
|
||||||
+575
@@ -0,0 +1,575 @@
|
|||||||
|
@file:OptIn(
|
||||||
|
androidx.compose.ui.InternalComposeUiApi::class,
|
||||||
|
androidx.compose.runtime.InternalComposeApi::class,
|
||||||
|
)
|
||||||
|
|
||||||
|
package com.compose.sdl
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.Composition
|
||||||
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
|
import androidx.compose.runtime.Recomposer
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.snapshots.Snapshot
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.input.key.KeyEvent
|
||||||
|
import androidx.compose.ui.input.pointer.PointerButton
|
||||||
|
import androidx.compose.ui.input.pointer.PointerEventType
|
||||||
|
import com.compose.sdl.node.ComposeRootHost
|
||||||
|
import com.compose.sdl.res.currentImageLoader
|
||||||
|
import com.compose.sdl.window.LocalPopupHost
|
||||||
|
import com.compose.sdl.window.PopupLayer
|
||||||
|
import com.compose.sdl.window.createPopupHostState
|
||||||
|
import kotlinx.cinterop.alloc
|
||||||
|
import kotlinx.cinterop.ptr
|
||||||
|
import kotlinx.cinterop.reinterpret
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import sdl3.SDL_GetTicks
|
||||||
|
import sdl3.SDL_SetWindowTitle
|
||||||
|
|
||||||
|
// ==================
|
||||||
|
// MARK: WindowInstance - one SDL window + renderer + composition
|
||||||
|
// ==================
|
||||||
|
|
||||||
|
internal class WindowInstance(
|
||||||
|
private val initialTitle: String,
|
||||||
|
inWidth: Int,
|
||||||
|
inHeight: Int,
|
||||||
|
inGpu: GpuMode,
|
||||||
|
inIcon: AppWindowIcon?,
|
||||||
|
private val attrs: WindowAttributes,
|
||||||
|
private val onFrame: ((RenderBackend, Int) -> Boolean)?,
|
||||||
|
// Window-level key handlers, read through holders so Window() recompositions
|
||||||
|
// with new lambdas take effect without recreating the window.
|
||||||
|
private val previewKeyHandler: () -> ((KeyEvent) -> Boolean),
|
||||||
|
private val keyHandler: () -> ((KeyEvent) -> Boolean),
|
||||||
|
private val contentHolder: () -> (@Composable ComposeWindowScope.() -> Unit),
|
||||||
|
) {
|
||||||
|
// Resolved renderer mode. `var` so init() can fall back GPU → CPU raster when
|
||||||
|
// a Skia GPU context can't be created (RDP / headless / missing GL driver).
|
||||||
|
private var gpuMode = if (inGpu is GpuMode.Auto) rendererPreferredGpuMode() else inGpu
|
||||||
|
private val initialWidth = inWidth
|
||||||
|
private val initialHeight = inHeight
|
||||||
|
private val icon = inIcon
|
||||||
|
// Assigned by init() from the first backend that comes up (see makeBackend()).
|
||||||
|
lateinit var backend: Sdl3Backend
|
||||||
|
private set
|
||||||
|
private var renderBackend: RenderBackend? = null
|
||||||
|
lateinit var host: ComposeRootHost
|
||||||
|
private set
|
||||||
|
lateinit var facade: ComposeNativeWindow
|
||||||
|
private set
|
||||||
|
private var popupHost: com.compose.sdl.window.PopupHostState? = null
|
||||||
|
|
||||||
|
val frameClock = Sdl3FrameClock()
|
||||||
|
private var recomposer: Recomposer? = null
|
||||||
|
private var recomposeJob: Job? = null
|
||||||
|
private var composition: Composition? = null
|
||||||
|
|
||||||
|
// Set by Window(); the compat wrapper points it at exitApplication().
|
||||||
|
var onCloseRequest: () -> Unit = {}
|
||||||
|
var closeDispatched = false
|
||||||
|
|
||||||
|
// Render-on-demand flag (see the pre-multi-window loop): set by events,
|
||||||
|
// state writes (global observer), resize, expose.
|
||||||
|
var needsFrame = true
|
||||||
|
|
||||||
|
// Hover refresh: last pointer position in PIXEL space, re-dispatched as a
|
||||||
|
// synthetic Move after layout so items scrolled under the cursor hover.
|
||||||
|
private var lastMouseX = -1f
|
||||||
|
private var lastMouseY = -1f
|
||||||
|
private var hasMousePos = false
|
||||||
|
|
||||||
|
private var frameIndex = 0
|
||||||
|
private var fpsEma = 0.0
|
||||||
|
private var fpsLastFrameMs = SDL_GetTicks()
|
||||||
|
private var fpsLastTitleMs = 0uL
|
||||||
|
|
||||||
|
// Escape → back (upstream desktop's BackNavigationEventInput): unconsumed
|
||||||
|
// Escape completes a back navigation on THIS window's dispatcher.
|
||||||
|
private val navigationEventOwner = object : androidx.navigationevent.NavigationEventDispatcherOwner {
|
||||||
|
override val navigationEventDispatcher = androidx.navigationevent.NavigationEventDispatcher()
|
||||||
|
}
|
||||||
|
private val backNavigationInput = BackNavigationInput()
|
||||||
|
|
||||||
|
// WINDOW-scoped architecture-components owner (Lifecycle + ViewModelStore +
|
||||||
|
// SavedStateRegistry) - the same trio upstream desktop's
|
||||||
|
// DefaultArchitectureComponentsOwner supplies through the window
|
||||||
|
// PlatformContext (compose/ui skikoMain PlatformOwnerProvider.skiko.kt).
|
||||||
|
// viewModel(), SavedStateHandle plumbing and navigation3's
|
||||||
|
// rememberViewModelStoreNavEntryDecorator all resolve their parent owners
|
||||||
|
// from this; destroy() moves it to DESTROYED and clears the store.
|
||||||
|
private val architectureOwner = WindowArchitectureOwner()
|
||||||
|
|
||||||
|
// Window focus / visibility → Lifecycle.State, Compose Desktop's mapping:
|
||||||
|
// focused → RESUMED, visible unfocused → STARTED, hidden/minimised →
|
||||||
|
// CREATED. Starts focused+visible (SDL fires FOCUS_GAINED right after
|
||||||
|
// creation anyway; headless probe runs simply stay RESUMED).
|
||||||
|
private var windowFocused = true
|
||||||
|
private var windowVisible = true
|
||||||
|
|
||||||
|
fun onActivationEvent(inEvent: AppEvent.WindowActivation) {
|
||||||
|
inEvent.focused?.let { windowFocused = it }
|
||||||
|
inEvent.visible?.let { windowVisible = it }
|
||||||
|
if (::host.isInitialized) host.setWindowFocused(windowFocused)
|
||||||
|
architectureOwner.setLifecycleState(
|
||||||
|
when {
|
||||||
|
!windowVisible -> androidx.lifecycle.Lifecycle.State.CREATED
|
||||||
|
windowFocused -> androidx.lifecycle.Lifecycle.State.RESUMED
|
||||||
|
else -> androidx.lifecycle.Lifecycle.State.STARTED
|
||||||
|
}
|
||||||
|
)
|
||||||
|
// Shown / restored / focus-gained also invalidate the contents - keep
|
||||||
|
// the pre-lifecycle RedrawNeeded behaviour of these SDL events.
|
||||||
|
needsFrame = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates + initialises an Sdl3Backend for [mode] and its RenderBackend. On
|
||||||
|
// success commits `backend` and returns the renderer; else tears everything
|
||||||
|
// down and returns null so the caller can retry with a different mode.
|
||||||
|
private fun makeBackend(mode: GpuMode): RenderBackend? {
|
||||||
|
val vBackend = Sdl3Backend(
|
||||||
|
initialTitle, initialWidth, initialHeight, gpuMode = mode,
|
||||||
|
iconLightResourcePaths = icon?.light ?: emptyList(),
|
||||||
|
iconDarkResourcePaths = icon?.dark ?: emptyList(),
|
||||||
|
undecorated = attrs.undecorated,
|
||||||
|
transparent = attrs.transparent,
|
||||||
|
resizable = attrs.resizable,
|
||||||
|
alwaysOnTop = attrs.alwaysOnTop,
|
||||||
|
focusable = attrs.focusable,
|
||||||
|
)
|
||||||
|
if (!vBackend.init()) {
|
||||||
|
vBackend.destroy(inQuitSdl = false)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
vBackend.updateWindowSize()
|
||||||
|
val vRender = createRenderBackend(vBackend, mode)
|
||||||
|
if (vRender == null || !vRender.ensureSize(vBackend.pixelWidth, vBackend.pixelHeight)) {
|
||||||
|
vRender?.destroy()
|
||||||
|
vBackend.destroy(inQuitSdl = false)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
backend = vBackend
|
||||||
|
return vRender
|
||||||
|
}
|
||||||
|
|
||||||
|
fun init(inScope: CoroutineScope): Boolean {
|
||||||
|
// Try the resolved gpuMode; if it's a Skia GPU mode whose context/bridge
|
||||||
|
// can't come up (RDP / headless / missing GL driver), fall back once to
|
||||||
|
// CPU raster (Software) so the window still opens instead of failing.
|
||||||
|
var vRender = makeBackend(gpuMode)
|
||||||
|
if (vRender == null && gpuMode.isGpuAccelerated) {
|
||||||
|
println("GPU renderer ($gpuMode) unavailable - falling back to CPU raster (Software)")
|
||||||
|
gpuMode = GpuMode.CpuRaster
|
||||||
|
vRender = makeBackend(gpuMode)
|
||||||
|
}
|
||||||
|
if (vRender == null) {
|
||||||
|
println("Failed to init render backend")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
renderBackend = vRender
|
||||||
|
|
||||||
|
host = ComposeRootHost(inDensity = backend.pixelDensity)
|
||||||
|
host.attach()
|
||||||
|
// A layer whose content changed (OwnedLayer.invalidate) schedules a frame
|
||||||
|
// even when nothing else (recompose / relayout) is pending - retained layers
|
||||||
|
// need this so a draw-only state change still repaints.
|
||||||
|
host.setInvalidationCallback { needsFrame = true }
|
||||||
|
facade = ComposeNativeWindow(backend, gpuMode, initialTitle)
|
||||||
|
// Mirror the creation flags into the facade so isResizable & co. read true
|
||||||
|
// from the start and a later Window() update only fires on a real change.
|
||||||
|
applyAttributes(attrs)
|
||||||
|
navigationEventOwner.navigationEventDispatcher.addInput(backNavigationInput)
|
||||||
|
|
||||||
|
// The render-bridge globals must point at THIS window's renderer while
|
||||||
|
// its content composes/measures (first composition happens inside
|
||||||
|
// setContent below).
|
||||||
|
installGlobals()
|
||||||
|
|
||||||
|
// Effect context for this window's composition - the screenshot flag injects the
|
||||||
|
// infinite-animation-cancelling policy (see disableInfiniteAnimations above).
|
||||||
|
var vEffectContext = inScope.coroutineContext + frameClock
|
||||||
|
if (disableInfiniteAnimations) vEffectContext += CancelInfiniteAnimationsPolicy
|
||||||
|
val vRecomposer = Recomposer(vEffectContext)
|
||||||
|
recomposer = vRecomposer
|
||||||
|
recomposeJob = inScope.launch(frameClock) { vRecomposer.runRecomposeAndApplyChanges() }
|
||||||
|
val vComposition = Composition(host.applier, vRecomposer)
|
||||||
|
composition = vComposition
|
||||||
|
|
||||||
|
val vUriHandler = object : androidx.compose.ui.platform.UriHandler {
|
||||||
|
override fun openUri(uri: String) { openUrl(uri) }
|
||||||
|
}
|
||||||
|
val vPopupHost = createPopupHostState()
|
||||||
|
popupHost = vPopupHost
|
||||||
|
val vWindowScope = object : ComposeWindowScope {
|
||||||
|
override val window: ComposeNativeWindow = facade
|
||||||
|
}
|
||||||
|
|
||||||
|
vComposition.setContent {
|
||||||
|
CompositionLocalProvider(
|
||||||
|
LocalComposeNativeWindow provides facade,
|
||||||
|
LocalPopupHost provides vPopupHost,
|
||||||
|
// Upstream vendored CompositionLocals.kt declares each of these as
|
||||||
|
// `staticCompositionLocalOf<T> { noLocalProvidedFor("…") }` - reading
|
||||||
|
// one without a Provider throws. Seed them all from the ComposeOwner.
|
||||||
|
androidx.compose.ui.platform.LocalDensity provides host.density,
|
||||||
|
androidx.compose.ui.platform.LocalLayoutDirection provides host.layoutDirection,
|
||||||
|
androidx.compose.ui.platform.LocalFocusManager provides host.focusManager,
|
||||||
|
androidx.compose.ui.platform.LocalGraphicsContext provides host.graphicsContext,
|
||||||
|
androidx.compose.ui.platform.LocalViewConfiguration provides host.viewConfiguration,
|
||||||
|
androidx.compose.ui.platform.LocalInputModeManager provides host.inputModeManager,
|
||||||
|
androidx.compose.ui.platform.LocalHapticFeedback provides host.hapticFeedback,
|
||||||
|
androidx.compose.ui.platform.LocalTextToolbar provides host.textToolbar,
|
||||||
|
androidx.compose.ui.platform.LocalWindowInfo provides host.windowInfo,
|
||||||
|
androidx.compose.ui.platform.LocalSoftwareKeyboardController provides host.softwareKeyboardController,
|
||||||
|
androidx.compose.ui.platform.LocalClipboard provides
|
||||||
|
androidx.compose.ui.platform.platformClipboard(),
|
||||||
|
androidx.compose.ui.platform.LocalFontFamilyResolver provides
|
||||||
|
com.compose.sdl.text.font.projectFontFamilyResolver,
|
||||||
|
androidx.compose.ui.platform.LocalUriHandler provides vUriHandler,
|
||||||
|
// Desktop windows have no system bars / notch / IME insets - the
|
||||||
|
// interface's all-zero defaults are exactly right.
|
||||||
|
androidx.compose.ui.platform.LocalPlatformWindowInsets provides
|
||||||
|
object : androidx.compose.ui.platform.PlatformWindowInsets {},
|
||||||
|
// The window's architecture-components owner backs all three arch
|
||||||
|
// locals, exactly like upstream desktop's window PlatformContext:
|
||||||
|
// - LocalLifecycleOwner: RESUMED for the window's whole life;
|
||||||
|
// lifecycle-aware content (NavDisplay, rememberLifecycleOwner, …)
|
||||||
|
// errors without it.
|
||||||
|
// - LocalViewModelStoreOwner: window-scoped ViewModels (google
|
||||||
|
// lifecycle-viewmodel-compose's local is a plain composition
|
||||||
|
// local; the JB HostDefault route doesn't exist in the google
|
||||||
|
// artifacts this port ships).
|
||||||
|
// - LocalSavedStateRegistryOwner: SavedStateHandle / rememberSaveable
|
||||||
|
// registry parent (nav3's ViewModelStoreNavEntryDecorator requires it).
|
||||||
|
androidx.lifecycle.compose.LocalLifecycleOwner provides architectureOwner,
|
||||||
|
androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner provides architectureOwner,
|
||||||
|
androidx.savedstate.compose.LocalSavedStateRegistryOwner provides architectureOwner,
|
||||||
|
// Runtime-level host defaults - this window's navigation-event
|
||||||
|
// owner (SearchBar / sheets back plumbing). The viewmodel store
|
||||||
|
// is provided through the plain LocalViewModelStoreOwner above
|
||||||
|
// instead: the google lifecycle artifacts this port ships have no
|
||||||
|
// HostDefault key for it (that mechanism is JB-variant-only).
|
||||||
|
androidx.compose.runtime.LocalHostDefaultProvider provides
|
||||||
|
remember {
|
||||||
|
object : androidx.compose.runtime.HostDefaultProvider {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override fun <T> getHostDefault(key: androidx.compose.runtime.HostDefaultKey<T>): T = when (key) {
|
||||||
|
androidx.navigationevent.compose.NavigationEventDispatcherOwnerHostDefaultKey -> navigationEventOwner
|
||||||
|
else -> null
|
||||||
|
} as T
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
// Seed the :ui-internal LocalPointerIconService so Modifier.pointerHoverIcon
|
||||||
|
// drives the SDL cursor (the local + service type can't cross the module boundary).
|
||||||
|
host.ProvidePointerIconService {
|
||||||
|
Box(modifier = Modifier.fillMaxSize()) {
|
||||||
|
// Read through the holder so Window() recompositions with a
|
||||||
|
// new content lambda propagate into this composition.
|
||||||
|
val vContent = contentHolder()
|
||||||
|
with(vWindowScope) { vContent() }
|
||||||
|
PopupLayer(vPopupHost)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// First composition done (setContent is synchronous) - promote the
|
||||||
|
// window lifecycle from CREATED to the focus/visibility-derived state.
|
||||||
|
// Composition itself runs at CREATED so enableSavedStateHandles()
|
||||||
|
// callers see a legal state, mirroring upstream desktop's
|
||||||
|
// compose-first-resume-after ordering.
|
||||||
|
architectureOwner.setLifecycleState(
|
||||||
|
when {
|
||||||
|
!windowVisible -> androidx.lifecycle.Lifecycle.State.CREATED
|
||||||
|
windowFocused -> androidx.lifecycle.Lifecycle.State.RESUMED
|
||||||
|
else -> androidx.lifecycle.Lifecycle.State.STARTED
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Points the render-bridge globals (text measurer / image loader /
|
||||||
|
viewport) at this window's renderer. Must be called before composing,
|
||||||
|
measuring, or drawing this window's tree. */
|
||||||
|
fun installGlobals() {
|
||||||
|
val vRender = renderBackend ?: return
|
||||||
|
currentImageLoader = vRender.imageLoader
|
||||||
|
com.compose.sdl.text.currentViewportWidth = backend.pixelWidth
|
||||||
|
com.compose.sdl.text.currentViewportHeight = backend.pixelHeight
|
||||||
|
// Register bundled generic fonts (FontFamily.Monospace → NotoSansMono) once
|
||||||
|
// data.kres is loadable; idempotent, no-op if the font isn't bundled.
|
||||||
|
com.compose.sdl.text.registerGenericFonts()
|
||||||
|
// Position the OS IME candidate window the moment a field in THIS window
|
||||||
|
// gains focus, not only on the first TEXT_EDITING event (repointed per
|
||||||
|
// window here so multi-window focus targets the right SDL window).
|
||||||
|
com.compose.sdl.text.input.ImeBridge.onSessionActiveChange = { active ->
|
||||||
|
if (active) updateImeArea()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============
|
||||||
|
// Event handling (loop-routed, per window)
|
||||||
|
|
||||||
|
fun onPointerEvent(inEvent: AppEvent.Pointer) {
|
||||||
|
if (!facade.isEnabled) return
|
||||||
|
needsFrame = true
|
||||||
|
installGlobals()
|
||||||
|
val vType = when (inEvent.type) {
|
||||||
|
PointerEventType.Press -> 1
|
||||||
|
PointerEventType.Release -> 2
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
val vBtn = when (inEvent.button) {
|
||||||
|
PointerButton.Secondary -> 1
|
||||||
|
PointerButton.Tertiary -> 2
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
// SDL3 delivers mouse coords in logical points on HiDPI - multiply by
|
||||||
|
// DPR so hit-testing lands in the pixel space layout uses.
|
||||||
|
val vDpr = backend.pixelDensity
|
||||||
|
val vPx = inEvent.x * vDpr
|
||||||
|
val vPy = inEvent.y * vDpr
|
||||||
|
if (inEvent.type == PointerEventType.Press) {
|
||||||
|
popupHost?.notifyOutsidePress(vPx.toInt(), vPy.toInt())
|
||||||
|
}
|
||||||
|
host.onPointerRaw(vPx, vPy, vType, vBtn, SDL_GetTicks().toLong())
|
||||||
|
lastMouseX = vPx
|
||||||
|
lastMouseY = vPy
|
||||||
|
hasMousePos = true
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Pointer left the window (SDL_EVENT_WINDOW_MOUSE_LEAVE). Stop the per-frame
|
||||||
|
synthetic hover re-dispatch and fire one Exit at the last position so a
|
||||||
|
hovered widget clears its highlight instead of sticking forever. */
|
||||||
|
fun onPointerExit() {
|
||||||
|
if (!facade.isEnabled) return
|
||||||
|
needsFrame = true
|
||||||
|
if (hasMousePos) {
|
||||||
|
host.onPointerRaw(lastMouseX, lastMouseY, 3, 0, SDL_GetTicks().toLong())
|
||||||
|
}
|
||||||
|
hasMousePos = false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onWheelEvent(inEvent: AppEvent.MouseWheel) {
|
||||||
|
if (!facade.isEnabled) return
|
||||||
|
needsFrame = true
|
||||||
|
installGlobals()
|
||||||
|
val vDpr = backend.pixelDensity
|
||||||
|
host.onWheel(inEvent.x * vDpr, inEvent.y * vDpr, inEvent.deltaX, inEvent.deltaY, SDL_GetTicks().toLong())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onKeyEvent(inEvent: AppEvent.Key) {
|
||||||
|
if (!facade.isEnabled) return
|
||||||
|
needsFrame = true
|
||||||
|
installGlobals()
|
||||||
|
// Compose Desktop's order: window preview → focused content → window
|
||||||
|
// onKeyEvent → app shortcut handler → back navigation (Escape).
|
||||||
|
if (previewKeyHandler().invoke(inEvent.event)) return
|
||||||
|
if (host.dispatchKeyEvent(inEvent.event)) return
|
||||||
|
if (keyHandler().invoke(inEvent.event)) return
|
||||||
|
if (!facade.dispatchKeyShortcut(inEvent.event)) {
|
||||||
|
backNavigationInput.onKeyEvent(inEvent.event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Applies the mutable window attributes. Called at init from the creation
|
||||||
|
flags and again whenever Window() sees one of them change. */
|
||||||
|
fun applyAttributes(inAttrs: WindowAttributes) {
|
||||||
|
facade.setUndecorated(inAttrs.undecorated)
|
||||||
|
facade.setResizable(inAttrs.resizable)
|
||||||
|
facade.setAlwaysOnTop(inAttrs.alwaysOnTop)
|
||||||
|
facade.setFocusable(inAttrs.focusable)
|
||||||
|
facade.setEnabled(inAttrs.enabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onTextInputEvent(inEvent: AppEvent.TextInput) {
|
||||||
|
if (!facade.isEnabled) return
|
||||||
|
needsFrame = true
|
||||||
|
installGlobals()
|
||||||
|
// A focused text field runs an IME session (ComposeOwner.textInputSession):
|
||||||
|
// commit through it so the text REPLACES any active composition. Falls back
|
||||||
|
// to synthesising typed KeyEvents when no field is focused - SDL key events
|
||||||
|
// carry UNSHIFTED keycodes (no uppercase/numpad/dead keys), so committed
|
||||||
|
// text is the only layout-correct character source.
|
||||||
|
if (!com.compose.sdl.text.input.ImeBridge.commit(inEvent.text)) {
|
||||||
|
dispatchTypedText(host, inEvent.text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onTextEditingEvent(inEvent: AppEvent.TextEditing) {
|
||||||
|
if (!facade.isEnabled) return
|
||||||
|
needsFrame = true
|
||||||
|
installGlobals()
|
||||||
|
// IME preedit: show the composing (underlined) region in the focused field.
|
||||||
|
// No-op if no field is focused. Also nudge the OS candidate window to the
|
||||||
|
// field's on-screen rect.
|
||||||
|
com.compose.sdl.text.input.ImeBridge.compose(inEvent.text)
|
||||||
|
updateImeArea()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nudge the OS IME candidate window to the focused field's on-screen rect.
|
||||||
|
// Best-effort: no-op without an active session or a laid-out field.
|
||||||
|
@OptIn(androidx.compose.ui.ExperimentalComposeUiApi::class, kotlinx.cinterop.ExperimentalForeignApi::class)
|
||||||
|
private fun updateImeArea() {
|
||||||
|
val vRequest = com.compose.sdl.text.input.ImeBridge.request ?: return
|
||||||
|
val vRect = vRequest.focusedRectInRoot() ?: return
|
||||||
|
val vWindow = backend.window ?: return
|
||||||
|
val vDpr = backend.pixelDensity
|
||||||
|
kotlinx.cinterop.memScoped {
|
||||||
|
// SDL wants the area in logical window points; layout runs in physical px.
|
||||||
|
val vSdlRect = alloc<sdl3.SDL_Rect>()
|
||||||
|
vSdlRect.x = (vRect.left / vDpr).toInt()
|
||||||
|
vSdlRect.y = (vRect.top / vDpr).toInt()
|
||||||
|
vSdlRect.w = (vRect.width / vDpr).toInt().coerceAtLeast(1)
|
||||||
|
vSdlRect.h = (vRect.height / vDpr).toInt().coerceAtLeast(1)
|
||||||
|
sdl3.SDL_SetTextInputArea(vWindow.reinterpret(), vSdlRect.ptr, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onDropEvent(inEvent: AppEvent.Drop) {
|
||||||
|
if (!facade.isEnabled) return
|
||||||
|
needsFrame = true
|
||||||
|
installGlobals()
|
||||||
|
// SDL fires drop coords in logical points at DPR-1; scale to the pixel
|
||||||
|
// space layout runs in (Option-B density flow) so hit-testing lands
|
||||||
|
// where the pointer is.
|
||||||
|
val vDpr = backend.pixelDensity
|
||||||
|
when (inEvent.phase) {
|
||||||
|
AppEvent.DropPhase.BEGIN -> host.onDropBegin()
|
||||||
|
AppEvent.DropPhase.POSITION -> host.onDropPosition(inEvent.x * vDpr, inEvent.y * vDpr)
|
||||||
|
AppEvent.DropPhase.FILE -> inEvent.data?.let { host.onDropFile(it) }
|
||||||
|
AppEvent.DropPhase.TEXT -> inEvent.data?.let { host.onDropText(it) }
|
||||||
|
AppEvent.DropPhase.COMPLETE -> host.onDropComplete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onResizedEvent() {
|
||||||
|
needsFrame = true
|
||||||
|
backend.updateWindowSize()
|
||||||
|
facade.onResized()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** OS light/dark theme changed - re-pick the theme-appropriate window icon
|
||||||
|
(no-op if this window has no icon configured or the choice is unchanged). */
|
||||||
|
fun onSystemThemeChanged() {
|
||||||
|
backend.applyThemeIcon()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** OS close button / app-level Quit: honour the veto handler, then hand the
|
||||||
|
decision to the Window() declaration. */
|
||||||
|
fun requestClose() {
|
||||||
|
if (closeDispatched) return
|
||||||
|
if (facade.requestCloseFromUser()) {
|
||||||
|
closeDispatched = true
|
||||||
|
onCloseRequest()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============
|
||||||
|
// Frame pump
|
||||||
|
|
||||||
|
fun shouldRender(): Boolean =
|
||||||
|
needsFrame || (recomposer?.hasPendingWork == true) || onFrame != null || kForceRender
|
||||||
|
|
||||||
|
/** True while this window still has pending work: a state/layout/draw invalidation
|
||||||
|
(needsFrame), recomposer work, or a composition/node animation awaiting the next
|
||||||
|
frame. Sampled by windowHasInvalidations() from onFrame probes - the quiescence
|
||||||
|
signal for render-to-settle screenshot capture. */
|
||||||
|
fun hasInvalidations(): Boolean =
|
||||||
|
needsFrame || recomposer?.hasPendingWork == true ||
|
||||||
|
frameClock.hasAwaiters || host.hasAnimationAwaiters()
|
||||||
|
|
||||||
|
fun renderFrame() {
|
||||||
|
val vRender = renderBackend ?: return
|
||||||
|
needsFrame = false
|
||||||
|
if (recomposer?.hasPendingWork == true) needsFrame = true
|
||||||
|
|
||||||
|
backend.updateWindowSize()
|
||||||
|
vRender.ensureSize(backend.pixelWidth, backend.pixelHeight)
|
||||||
|
// Charge the GPU back-buffer acquire to its own phase. On Metal this is
|
||||||
|
// where nextDrawable() blocks on vsync (the natural frame pacing), so
|
||||||
|
// folding it into "layout" made the profiler read the vsync wait as
|
||||||
|
// layout cost - a ~6-7ms phantom that hid the real (tiny) layout time.
|
||||||
|
FrameProfiler.phase(" acquire")
|
||||||
|
host.setConstraints(backend.pixelWidth, backend.pixelHeight)
|
||||||
|
// Deliver any state written by this iteration's frame-clock continuations
|
||||||
|
// (withFrameNanos animations - notably smooth wheel scrolling) BEFORE we lay
|
||||||
|
// out. Those writes happen in the per-window pump's sendFrame()/yield(), which
|
||||||
|
// is AFTER the loop's last sendApplyNotifications() - so without this the
|
||||||
|
// relayout they trigger wasn't registered until the next frame, and the frame
|
||||||
|
// drew last frame's positions. That one-frame trail read as "the clip is a
|
||||||
|
// frame late" when scrolling (content briefly drawn past the viewport edge).
|
||||||
|
Snapshot.sendApplyNotifications()
|
||||||
|
host.measureAndLayout()
|
||||||
|
FrameProfiler.phase(" layout")
|
||||||
|
|
||||||
|
// Hover refresh after layout (upstream skiko: SyntheticEventSender).
|
||||||
|
if (hasMousePos) {
|
||||||
|
host.onPointerRaw(lastMouseX, lastMouseY, 0, 0, SDL_GetTicks().toLong())
|
||||||
|
}
|
||||||
|
|
||||||
|
vRender.beginFrame(1f)
|
||||||
|
vRender.drawRoot { canvas -> host.drawRoot(canvas) }
|
||||||
|
if (onFrame != null) {
|
||||||
|
renderingWindow = this
|
||||||
|
val vContinue = onFrame.invoke(vRender, frameIndex)
|
||||||
|
renderingWindow = null
|
||||||
|
// Probe consumers end the app when their scenario completes.
|
||||||
|
if (!vContinue) facade.close()
|
||||||
|
}
|
||||||
|
FrameProfiler.phase(" draw")
|
||||||
|
vRender.endFrame()
|
||||||
|
FrameProfiler.phase(" present")
|
||||||
|
frameIndex++
|
||||||
|
|
||||||
|
// FPS - instantaneous inter-frame rate, EMA-smoothed, title refreshed
|
||||||
|
// ~4x/sec. This shows within ~2 rendered frames of ANY activity rather
|
||||||
|
// than waiting for a full second of unbroken rendering to accumulate
|
||||||
|
// (the old fixed-window counter never got its first update: bursty
|
||||||
|
// interaction kept idling before 1s elapsed, and the idle-skip reset the
|
||||||
|
// window each time - so FPS only appeared during a long enough page
|
||||||
|
// transition). A dt outside 1..100ms is the first frame or a resume from
|
||||||
|
// idle (the gap isn't a real frame interval), so it's not sampled - the
|
||||||
|
// title just holds the last active rate while idle.
|
||||||
|
val vNowMs = SDL_GetTicks()
|
||||||
|
val vDt = (vNowMs - fpsLastFrameMs).toInt()
|
||||||
|
fpsLastFrameMs = vNowMs
|
||||||
|
if (vDt in 1..100) {
|
||||||
|
val vInst = 1000.0 / vDt
|
||||||
|
fpsEma = if (fpsEma <= 0.0) vInst else fpsEma * 0.9 + vInst * 0.1
|
||||||
|
if ((vNowMs - fpsLastTitleMs).toInt() >= 250) {
|
||||||
|
val vFps = (fpsEma + 0.5).toInt()
|
||||||
|
facade.updateFps(vFps)
|
||||||
|
SDL_SetWindowTitle(backend.window?.reinterpret(), "${facade.title} · $vFps FPS")
|
||||||
|
fpsLastTitleMs = vNowMs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Idle-skip calls this: drop the frame timer so the resume-from-idle frame's
|
||||||
|
// dt (the whole idle gap) isn't sampled as a real interval. The EMA is left
|
||||||
|
// intact so the title keeps showing the last active rate while idle.
|
||||||
|
fun resetFpsWindow() {
|
||||||
|
fpsLastFrameMs = SDL_GetTicks()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun destroy() {
|
||||||
|
composition?.dispose()
|
||||||
|
composition = null
|
||||||
|
// Window gone → DESTROYED lifecycle + ViewModels cleared (onCleared
|
||||||
|
// runs), matching upstream desktop's window-scoped owner lifetime.
|
||||||
|
architectureOwner.destroy()
|
||||||
|
recomposer?.cancel()
|
||||||
|
recomposer = null
|
||||||
|
recomposeJob?.cancel()
|
||||||
|
recomposeJob = null
|
||||||
|
renderBackend?.destroy()
|
||||||
|
renderBackend = null
|
||||||
|
backend.destroy(inQuitSdl = false)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2090,13 +2090,6 @@ final object androidx.compose.foundation/MarqueeDefaults { // androidx.compose.f
|
|||||||
final fun <get-Velocity>(): androidx.compose.ui.unit/Dp // androidx.compose.foundation/MarqueeDefaults.Velocity.<get-Velocity>|<get-Velocity>(){}[0]
|
final fun <get-Velocity>(): androidx.compose.ui.unit/Dp // androidx.compose.foundation/MarqueeDefaults.Velocity.<get-Velocity>|<get-Velocity>(){}[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
final object com.compose.sdl.icons/IconDefaults { // com.compose.sdl.icons/IconDefaults|null[0]
|
|
||||||
final val DefaultIconSize // com.compose.sdl.icons/IconDefaults.DefaultIconSize|{}DefaultIconSize[0]
|
|
||||||
final fun <get-DefaultIconSize>(): androidx.compose.ui.unit/Dp // com.compose.sdl.icons/IconDefaults.DefaultIconSize.<get-DefaultIconSize>|<get-DefaultIconSize>(){}[0]
|
|
||||||
final val LocalContentColor // com.compose.sdl.icons/IconDefaults.LocalContentColor|{}LocalContentColor[0]
|
|
||||||
final fun <get-LocalContentColor>(): androidx.compose.ui.graphics/Color // com.compose.sdl.icons/IconDefaults.LocalContentColor.<get-LocalContentColor>|<get-LocalContentColor>(){}[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
final object com.compose.sdl.widgets/SplitPaneDefaults { // com.compose.sdl.widgets/SplitPaneDefaults|null[0]
|
final object com.compose.sdl.widgets/SplitPaneDefaults { // com.compose.sdl.widgets/SplitPaneDefaults|null[0]
|
||||||
final val DividerThickness // com.compose.sdl.widgets/SplitPaneDefaults.DividerThickness|{}DividerThickness[0]
|
final val DividerThickness // com.compose.sdl.widgets/SplitPaneDefaults.DividerThickness|{}DividerThickness[0]
|
||||||
final fun <get-DividerThickness>(): androidx.compose.ui.unit/Dp // com.compose.sdl.widgets/SplitPaneDefaults.DividerThickness.<get-DividerThickness>|<get-DividerThickness>(){}[0]
|
final fun <get-DividerThickness>(): androidx.compose.ui.unit/Dp // com.compose.sdl.widgets/SplitPaneDefaults.DividerThickness.<get-DividerThickness>|<get-DividerThickness>(){}[0]
|
||||||
@@ -2233,7 +2226,6 @@ final val androidx.compose.foundation/androidx_compose_foundation_MarqueeDefault
|
|||||||
final val androidx.compose.foundation/androidx_compose_foundation_MutatorMutex$stableprop // androidx.compose.foundation/androidx_compose_foundation_MutatorMutex$stableprop|#static{}androidx_compose_foundation_MutatorMutex$stableprop[0]
|
final val androidx.compose.foundation/androidx_compose_foundation_MutatorMutex$stableprop // androidx.compose.foundation/androidx_compose_foundation_MutatorMutex$stableprop|#static{}androidx_compose_foundation_MutatorMutex$stableprop[0]
|
||||||
final val androidx.compose.foundation/androidx_compose_foundation_ScrollState$stableprop // androidx.compose.foundation/androidx_compose_foundation_ScrollState$stableprop|#static{}androidx_compose_foundation_ScrollState$stableprop[0]
|
final val androidx.compose.foundation/androidx_compose_foundation_ScrollState$stableprop // androidx.compose.foundation/androidx_compose_foundation_ScrollState$stableprop|#static{}androidx_compose_foundation_ScrollState$stableprop[0]
|
||||||
final val androidx.compose.foundation/androidx_compose_foundation_ScrollbarStyle$stableprop // androidx.compose.foundation/androidx_compose_foundation_ScrollbarStyle$stableprop|#static{}androidx_compose_foundation_ScrollbarStyle$stableprop[0]
|
final val androidx.compose.foundation/androidx_compose_foundation_ScrollbarStyle$stableprop // androidx.compose.foundation/androidx_compose_foundation_ScrollbarStyle$stableprop|#static{}androidx_compose_foundation_ScrollbarStyle$stableprop[0]
|
||||||
final val com.compose.sdl.icons/com_compose_sdl_icons_IconDefaults$stableprop // com.compose.sdl.icons/com_compose_sdl_icons_IconDefaults$stableprop|#static{}com_compose_sdl_icons_IconDefaults$stableprop[0]
|
|
||||||
final val com.compose.sdl.widgets/com_compose_sdl_widgets_SplitPaneDefaults$stableprop // com.compose.sdl.widgets/com_compose_sdl_widgets_SplitPaneDefaults$stableprop|#static{}com_compose_sdl_widgets_SplitPaneDefaults$stableprop[0]
|
final val com.compose.sdl.widgets/com_compose_sdl_widgets_SplitPaneDefaults$stableprop // com.compose.sdl.widgets/com_compose_sdl_widgets_SplitPaneDefaults$stableprop|#static{}com_compose_sdl_widgets_SplitPaneDefaults$stableprop[0]
|
||||||
|
|
||||||
final fun (androidx.compose.foundation.content/TransferableContent).androidx.compose.foundation.content/hasMediaType(androidx.compose.foundation.content/MediaType): kotlin/Boolean // androidx.compose.foundation.content/hasMediaType|hasMediaType@androidx.compose.foundation.content.TransferableContent(androidx.compose.foundation.content.MediaType){}[0]
|
final fun (androidx.compose.foundation.content/TransferableContent).androidx.compose.foundation.content/hasMediaType(androidx.compose.foundation.content/MediaType): kotlin/Boolean // androidx.compose.foundation.content/hasMediaType|hasMediaType@androidx.compose.foundation.content.TransferableContent(androidx.compose.foundation.content.MediaType){}[0]
|
||||||
@@ -2651,7 +2643,6 @@ final fun androidx.compose.foundation/rememberScrollbarAdapter(androidx.compose.
|
|||||||
final fun androidx.compose.foundation/rememberScrollbarAdapter(androidx.compose.foundation.text/TextFieldScrollState, androidx.compose.runtime/Composer?, kotlin/Int): androidx.compose.foundation.v2/ScrollbarAdapter // androidx.compose.foundation/rememberScrollbarAdapter|rememberScrollbarAdapter(androidx.compose.foundation.text.TextFieldScrollState;androidx.compose.runtime.Composer?;kotlin.Int){}[0]
|
final fun androidx.compose.foundation/rememberScrollbarAdapter(androidx.compose.foundation.text/TextFieldScrollState, androidx.compose.runtime/Composer?, kotlin/Int): androidx.compose.foundation.v2/ScrollbarAdapter // androidx.compose.foundation/rememberScrollbarAdapter|rememberScrollbarAdapter(androidx.compose.foundation.text.TextFieldScrollState;androidx.compose.runtime.Composer?;kotlin.Int){}[0]
|
||||||
final fun androidx.compose.foundation/rememberScrollbarAdapter(androidx.compose.foundation/ScrollState, androidx.compose.runtime/Composer?, kotlin/Int): androidx.compose.foundation.v2/ScrollbarAdapter // androidx.compose.foundation/rememberScrollbarAdapter|rememberScrollbarAdapter(androidx.compose.foundation.ScrollState;androidx.compose.runtime.Composer?;kotlin.Int){}[0]
|
final fun androidx.compose.foundation/rememberScrollbarAdapter(androidx.compose.foundation/ScrollState, androidx.compose.runtime/Composer?, kotlin/Int): androidx.compose.foundation.v2/ScrollbarAdapter // androidx.compose.foundation/rememberScrollbarAdapter|rememberScrollbarAdapter(androidx.compose.foundation.ScrollState;androidx.compose.runtime.Composer?;kotlin.Int){}[0]
|
||||||
final fun com.compose.sdl.icons/IconFontIcon(kotlin/Int, kotlin/String, kotlin/String?, androidx.compose.ui/Modifier?, androidx.compose.ui.graphics/Color, androidx.compose.ui.unit/Dp, kotlin.collections/List<androidx.compose.ui.text.font/FontVariation.Setting>?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // com.compose.sdl.icons/IconFontIcon|IconFontIcon(kotlin.Int;kotlin.String;kotlin.String?;androidx.compose.ui.Modifier?;androidx.compose.ui.graphics.Color;androidx.compose.ui.unit.Dp;kotlin.collections.List<androidx.compose.ui.text.font.FontVariation.Setting>?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0]
|
final fun com.compose.sdl.icons/IconFontIcon(kotlin/Int, kotlin/String, kotlin/String?, androidx.compose.ui/Modifier?, androidx.compose.ui.graphics/Color, androidx.compose.ui.unit/Dp, kotlin.collections/List<androidx.compose.ui.text.font/FontVariation.Setting>?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // com.compose.sdl.icons/IconFontIcon|IconFontIcon(kotlin.Int;kotlin.String;kotlin.String?;androidx.compose.ui.Modifier?;androidx.compose.ui.graphics.Color;androidx.compose.ui.unit.Dp;kotlin.collections.List<androidx.compose.ui.text.font.FontVariation.Setting>?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0]
|
||||||
final fun com.compose.sdl.icons/com_compose_sdl_icons_IconDefaults$stableprop_getter(): kotlin/Int // com.compose.sdl.icons/com_compose_sdl_icons_IconDefaults$stableprop_getter|com_compose_sdl_icons_IconDefaults$stableprop_getter(){}[0]
|
|
||||||
final fun com.compose.sdl.modifier/rememberMutableInteractionSource(androidx.compose.runtime/Composer?, kotlin/Int): androidx.compose.foundation.interaction/MutableInteractionSource // com.compose.sdl.modifier/rememberMutableInteractionSource|rememberMutableInteractionSource(androidx.compose.runtime.Composer?;kotlin.Int){}[0]
|
final fun com.compose.sdl.modifier/rememberMutableInteractionSource(androidx.compose.runtime/Composer?, kotlin/Int): androidx.compose.foundation.interaction/MutableInteractionSource // com.compose.sdl.modifier/rememberMutableInteractionSource|rememberMutableInteractionSource(androidx.compose.runtime.Composer?;kotlin.Int){}[0]
|
||||||
final fun com.compose.sdl.text/IconText(kotlin/String, kotlin/String, androidx.compose.ui/Modifier?, androidx.compose.ui.graphics/Color, androidx.compose.ui.unit/TextUnit, androidx.compose.ui.text.style/TextAlign, kotlin.collections/List<androidx.compose.ui.text.font/FontVariation.Setting>?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // com.compose.sdl.text/IconText|IconText(kotlin.String;kotlin.String;androidx.compose.ui.Modifier?;androidx.compose.ui.graphics.Color;androidx.compose.ui.unit.TextUnit;androidx.compose.ui.text.style.TextAlign;kotlin.collections.List<androidx.compose.ui.text.font.FontVariation.Setting>?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0]
|
final fun com.compose.sdl.text/IconText(kotlin/String, kotlin/String, androidx.compose.ui/Modifier?, androidx.compose.ui.graphics/Color, androidx.compose.ui.unit/TextUnit, androidx.compose.ui.text.style/TextAlign, kotlin.collections/List<androidx.compose.ui.text.font/FontVariation.Setting>?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // com.compose.sdl.text/IconText|IconText(kotlin.String;kotlin.String;androidx.compose.ui.Modifier?;androidx.compose.ui.graphics.Color;androidx.compose.ui.unit.TextUnit;androidx.compose.ui.text.style.TextAlign;kotlin.collections.List<androidx.compose.ui.text.font.FontVariation.Setting>?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0]
|
||||||
final fun com.compose.sdl.text/IconText(kotlin/String, kotlin/String, androidx.compose.ui/Modifier?, androidx.compose.ui.graphics/Color, androidx.compose.ui.unit/TextUnit, androidx.compose.ui.text.style/TextAlign?, kotlin.collections/List<androidx.compose.ui.text.font/FontVariation.Setting>?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // com.compose.sdl.text/IconText|IconText(kotlin.String;kotlin.String;androidx.compose.ui.Modifier?;androidx.compose.ui.graphics.Color;androidx.compose.ui.unit.TextUnit;androidx.compose.ui.text.style.TextAlign?;kotlin.collections.List<androidx.compose.ui.text.font.FontVariation.Setting>?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0]
|
final fun com.compose.sdl.text/IconText(kotlin/String, kotlin/String, androidx.compose.ui/Modifier?, androidx.compose.ui.graphics/Color, androidx.compose.ui.unit/TextUnit, androidx.compose.ui.text.style/TextAlign?, kotlin.collections/List<androidx.compose.ui.text.font/FontVariation.Setting>?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // com.compose.sdl.text/IconText|IconText(kotlin.String;kotlin.String;androidx.compose.ui.Modifier?;androidx.compose.ui.graphics.Color;androidx.compose.ui.unit.TextUnit;androidx.compose.ui.text.style.TextAlign?;kotlin.collections.List<androidx.compose.ui.text.font.FontVariation.Setting>?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0]
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
// VENDOR-BASE: compose/foundation/foundation/src/skikoMain/kotlin/androidx/compose/foundation/Scrollbar.skiko.kt @ v1.12.0
|
// VENDOR-BASE: compose/foundation/foundation/src/skikoMain/kotlin/androidx/compose/foundation/Scrollbar.skiko.kt @ v1.12.1
|
||||||
// MANUAL VENDOR: refused in compose-fork.txt (flat native source set). Only edit vs base is the
|
// MANUAL VENDOR: refused in compose-fork.txt (flat native source set). Only edit vs base is the
|
||||||
// K2 @file:Suppress below - identical to what sync.py injects into src/vendor .kt (this file lives
|
// K2 @file:Suppress below - identical to what sync.py injects into src/vendor .kt (this file lives
|
||||||
// in src/nativeMain so sync doesn't regenerate it). Needed so compileNativeMainKotlinMetadata (the
|
// in src/nativeMain so sync doesn't regenerate it). Needed so compileNativeMainKotlinMetadata (the
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
// VENDOR-BASE: compose/foundation/foundation/src/skikoMain/kotlin/androidx/compose/foundation/v2/Scrollbar.skiko.kt @ v1.12.0
|
// VENDOR-BASE: compose/foundation/foundation/src/skikoMain/kotlin/androidx/compose/foundation/v2/Scrollbar.skiko.kt @ v1.12.1
|
||||||
// MANUAL VENDOR: expect fun runBlockingIfPossible inlined to runBlocking (flat native source set can't hold expect+actual together).
|
// MANUAL VENDOR: expect fun runBlockingIfPossible inlined to runBlocking (flat native source set can't hold expect+actual together).
|
||||||
// Also carries the K2 @file:Suppress below (same as sync.py injects into src/vendor) so the native metadata compile / Windows publish accepts the orphaned JVM annotation.
|
// Also carries the K2 @file:Suppress below (same as sync.py injects into src/vendor) so the native metadata compile / Windows publish accepts the orphaned JVM annotation.
|
||||||
/*
|
/*
|
||||||
|
|||||||
+16
-2
@@ -2,7 +2,9 @@ package com.compose.sdl.icons
|
|||||||
|
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.wrapContentSize
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.text.font.FontVariation
|
import androidx.compose.ui.text.font.FontVariation
|
||||||
@@ -36,9 +38,21 @@ fun IconFontIcon(
|
|||||||
size: Dp = IconDefaults.DefaultIconSize,
|
size: Dp = IconDefaults.DefaultIconSize,
|
||||||
fontVariationSettings: List<FontVariation.Setting>? = null,
|
fontVariationSettings: List<FontVariation.Setting>? = null,
|
||||||
) {
|
) {
|
||||||
Box(modifier = modifier.size(size)) {
|
// CENTER the glyph in the icon box. The glyph's natural text box is TALLER than
|
||||||
|
// `size` - its height is the font's ascent+descent, and Material Symbols' em box
|
||||||
|
// overshoots the nominal icon size - so the glyph used to render ~13% of the icon
|
||||||
|
// size too LOW. This mirrors the JVM actual's explicit baseline math
|
||||||
|
// (`y = height/2 - (ascent+descent)/2` in MaterialSymbolsIcon.jvm.kt): IconText
|
||||||
|
// sets no lineHeight, so its box height IS ascent+descent and centering that box
|
||||||
|
// centers the same span the JVM centers.
|
||||||
|
//
|
||||||
|
// `wrapContentSize(unbounded = true)` is load-bearing: Modifier.size() hands the
|
||||||
|
// child FIXED constraints, so without it the text is measured at exactly `size`,
|
||||||
|
// nothing overflows, and contentAlignment has nothing to align.
|
||||||
|
Box(modifier = modifier.size(size), contentAlignment = Alignment.Center) {
|
||||||
com.compose.sdl.text.IconText(
|
com.compose.sdl.text.IconText(
|
||||||
text = codepointToString(codepoint),
|
text = codepointToString(codepoint),
|
||||||
|
modifier = Modifier.wrapContentSize(Alignment.Center, unbounded = true),
|
||||||
fontFamily = fontFamily,
|
fontFamily = fontFamily,
|
||||||
color = tint,
|
color = tint,
|
||||||
fontSize = size.value.sp,
|
fontSize = size.value.sp,
|
||||||
@@ -47,7 +61,7 @@ fun IconFontIcon(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object IconDefaults {
|
internal object IconDefaults {
|
||||||
val DefaultIconSize: Dp = 24.dp
|
val DefaultIconSize: Dp = 24.dp
|
||||||
/** STATIC fallback tint for direct IconFontIcon use - :foundation cannot
|
/** STATIC fallback tint for direct IconFontIcon use - :foundation cannot
|
||||||
read material3's LocalContentColor (module layering, same as upstream).
|
read material3's LocalContentColor (module layering, same as upstream).
|
||||||
|
|||||||
@@ -0,0 +1,658 @@
|
|||||||
|
// Klib ABI Dump
|
||||||
|
// Targets: [linuxArm64, linuxX64, macosArm64, mingwX64]
|
||||||
|
// Rendering settings:
|
||||||
|
// - Signature version: 2
|
||||||
|
// - Show manifest properties: true
|
||||||
|
// - Show declarations: true
|
||||||
|
|
||||||
|
// Library unique name: <com.bitsycore.compose.material3.adaptive:adaptive-layout>
|
||||||
|
final enum class androidx.compose.material3.adaptive.layout/DockedEdge : kotlin/Enum<androidx.compose.material3.adaptive.layout/DockedEdge> { // androidx.compose.material3.adaptive.layout/DockedEdge|null[0]
|
||||||
|
enum entry Bottom // androidx.compose.material3.adaptive.layout/DockedEdge.Bottom|null[0]
|
||||||
|
enum entry End // androidx.compose.material3.adaptive.layout/DockedEdge.End|null[0]
|
||||||
|
enum entry Start // androidx.compose.material3.adaptive.layout/DockedEdge.Start|null[0]
|
||||||
|
enum entry Top // androidx.compose.material3.adaptive.layout/DockedEdge.Top|null[0]
|
||||||
|
|
||||||
|
final val entries // androidx.compose.material3.adaptive.layout/DockedEdge.entries|#static{}entries[0]
|
||||||
|
final fun <get-entries>(): kotlin.enums/EnumEntries<androidx.compose.material3.adaptive.layout/DockedEdge> // androidx.compose.material3.adaptive.layout/DockedEdge.entries.<get-entries>|<get-entries>#static(){}[0]
|
||||||
|
|
||||||
|
final fun valueOf(kotlin/String): androidx.compose.material3.adaptive.layout/DockedEdge // androidx.compose.material3.adaptive.layout/DockedEdge.valueOf|valueOf#static(kotlin.String){}[0]
|
||||||
|
final fun values(): kotlin/Array<androidx.compose.material3.adaptive.layout/DockedEdge> // androidx.compose.material3.adaptive.layout/DockedEdge.values|values#static(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final enum class androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole : androidx.compose.material3.adaptive.layout/PaneScaffoldRole, kotlin/Enum<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole> { // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole|null[0]
|
||||||
|
enum entry Primary // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole.Primary|null[0]
|
||||||
|
enum entry Secondary // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole.Secondary|null[0]
|
||||||
|
enum entry Tertiary // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole.Tertiary|null[0]
|
||||||
|
|
||||||
|
final val entries // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole.entries|#static{}entries[0]
|
||||||
|
final fun <get-entries>(): kotlin.enums/EnumEntries<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole> // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole.entries.<get-entries>|<get-entries>#static(){}[0]
|
||||||
|
|
||||||
|
final fun valueOf(kotlin/String): androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole.valueOf|valueOf#static(kotlin.String){}[0]
|
||||||
|
final fun values(): kotlin/Array<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole> // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole.values|values#static(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract interface androidx.compose.material3.adaptive.layout/AnimatedPaneOverride { // androidx.compose.material3.adaptive.layout/AnimatedPaneOverride|null[0]
|
||||||
|
abstract fun <#A1: androidx.compose.material3.adaptive.layout/PaneScaffoldRole, #B1: androidx.compose.material3.adaptive.layout/PaneScaffoldValue<#A1>> (androidx.compose.material3.adaptive.layout/AnimatedPaneOverrideScope<#A1, #B1>).AnimatedPane(androidx.compose.runtime/Composer?, kotlin/Int) // androidx.compose.material3.adaptive.layout/AnimatedPaneOverride.AnimatedPane|AnimatedPane@androidx.compose.material3.adaptive.layout.AnimatedPaneOverrideScope<0:0,0:1>(androidx.compose.runtime.Composer?;kotlin.Int){0§<androidx.compose.material3.adaptive.layout.PaneScaffoldRole>;1§<androidx.compose.material3.adaptive.layout.PaneScaffoldValue<0:0>>}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract interface androidx.compose.material3.adaptive.layout/PaneScaffoldRole // androidx.compose.material3.adaptive.layout/PaneScaffoldRole|null[0]
|
||||||
|
|
||||||
|
abstract interface androidx.compose.material3.adaptive.layout/ThreePaneScaffoldOverride { // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldOverride|null[0]
|
||||||
|
abstract fun (androidx.compose.material3.adaptive.layout/ThreePaneScaffoldOverrideScope).ThreePaneScaffold(androidx.compose.runtime/Composer?, kotlin/Int) // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldOverride.ThreePaneScaffold|ThreePaneScaffold@androidx.compose.material3.adaptive.layout.ThreePaneScaffoldOverrideScope(androidx.compose.runtime.Composer?;kotlin.Int){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed interface <#A: androidx.compose.material3.adaptive.layout/PaneScaffoldRole, #B: androidx.compose.material3.adaptive.layout/PaneScaffoldValue<#A>> androidx.compose.material3.adaptive.layout/ExtendedPaneScaffoldPaneScope : androidx.compose.material3.adaptive.layout/ExtendedPaneScaffoldScope<#A, #B>, androidx.compose.material3.adaptive.layout/PaneScaffoldPaneScope<#A> // androidx.compose.material3.adaptive.layout/ExtendedPaneScaffoldPaneScope|null[0]
|
||||||
|
|
||||||
|
sealed interface <#A: androidx.compose.material3.adaptive.layout/PaneScaffoldRole, #B: androidx.compose.material3.adaptive.layout/PaneScaffoldValue<#A>> androidx.compose.material3.adaptive.layout/ExtendedPaneScaffoldScope : androidx.compose.material3.adaptive.layout/PaneScaffoldScope, androidx.compose.material3.adaptive.layout/PaneScaffoldTransitionScope<#A, #B>, androidx.compose.ui.layout/LookaheadScope { // androidx.compose.material3.adaptive.layout/ExtendedPaneScaffoldScope|null[0]
|
||||||
|
abstract val focusRequesters // androidx.compose.material3.adaptive.layout/ExtendedPaneScaffoldScope.focusRequesters|{}focusRequesters[0]
|
||||||
|
abstract fun <get-focusRequesters>(): kotlin.collections/Map<#A, androidx.compose.ui.focus/FocusRequester> // androidx.compose.material3.adaptive.layout/ExtendedPaneScaffoldScope.focusRequesters.<get-focusRequesters>|<get-focusRequesters>(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed interface <#A: androidx.compose.material3.adaptive.layout/PaneScaffoldRole, #B: androidx.compose.material3.adaptive.layout/PaneScaffoldValue<#A>> androidx.compose.material3.adaptive.layout/PaneScaffoldTransitionScope { // androidx.compose.material3.adaptive.layout/PaneScaffoldTransitionScope|null[0]
|
||||||
|
abstract val motionDataProvider // androidx.compose.material3.adaptive.layout/PaneScaffoldTransitionScope.motionDataProvider|{}motionDataProvider[0]
|
||||||
|
abstract fun <get-motionDataProvider>(): androidx.compose.material3.adaptive.layout/PaneScaffoldMotionDataProvider<#A> // androidx.compose.material3.adaptive.layout/PaneScaffoldTransitionScope.motionDataProvider.<get-motionDataProvider>|<get-motionDataProvider>(){}[0]
|
||||||
|
abstract val motionProgress // androidx.compose.material3.adaptive.layout/PaneScaffoldTransitionScope.motionProgress|{}motionProgress[0]
|
||||||
|
abstract fun <get-motionProgress>(): kotlin/Float // androidx.compose.material3.adaptive.layout/PaneScaffoldTransitionScope.motionProgress.<get-motionProgress>|<get-motionProgress>(){}[0]
|
||||||
|
abstract val scaffoldStateTransition // androidx.compose.material3.adaptive.layout/PaneScaffoldTransitionScope.scaffoldStateTransition|{}scaffoldStateTransition[0]
|
||||||
|
abstract fun <get-scaffoldStateTransition>(): androidx.compose.animation.core/Transition<#B> // androidx.compose.material3.adaptive.layout/PaneScaffoldTransitionScope.scaffoldStateTransition.<get-scaffoldStateTransition>|<get-scaffoldStateTransition>(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed interface <#A: androidx.compose.material3.adaptive.layout/PaneScaffoldRole> androidx.compose.material3.adaptive.layout/PaneScaffoldHorizontalOrder { // androidx.compose.material3.adaptive.layout/PaneScaffoldHorizontalOrder|null[0]
|
||||||
|
abstract val size // androidx.compose.material3.adaptive.layout/PaneScaffoldHorizontalOrder.size|{}size[0]
|
||||||
|
abstract fun <get-size>(): kotlin/Int // androidx.compose.material3.adaptive.layout/PaneScaffoldHorizontalOrder.size.<get-size>|<get-size>(){}[0]
|
||||||
|
|
||||||
|
abstract fun forEach(kotlin/Function1<#A, kotlin/Unit>) // androidx.compose.material3.adaptive.layout/PaneScaffoldHorizontalOrder.forEach|forEach(kotlin.Function1<1:0,kotlin.Unit>){}[0]
|
||||||
|
abstract fun forEachIndexed(kotlin/Function2<kotlin/Int, #A, kotlin/Unit>) // androidx.compose.material3.adaptive.layout/PaneScaffoldHorizontalOrder.forEachIndexed|forEachIndexed(kotlin.Function2<kotlin.Int,1:0,kotlin.Unit>){}[0]
|
||||||
|
abstract fun forEachIndexedReversed(kotlin/Function2<kotlin/Int, #A, kotlin/Unit>) // androidx.compose.material3.adaptive.layout/PaneScaffoldHorizontalOrder.forEachIndexedReversed|forEachIndexedReversed(kotlin.Function2<kotlin.Int,1:0,kotlin.Unit>){}[0]
|
||||||
|
abstract fun indexOf(#A): kotlin/Int // androidx.compose.material3.adaptive.layout/PaneScaffoldHorizontalOrder.indexOf|indexOf(1:0){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed interface <#A: androidx.compose.material3.adaptive.layout/PaneScaffoldRole> androidx.compose.material3.adaptive.layout/PaneScaffoldMotionDataProvider { // androidx.compose.material3.adaptive.layout/PaneScaffoldMotionDataProvider|null[0]
|
||||||
|
abstract val count // androidx.compose.material3.adaptive.layout/PaneScaffoldMotionDataProvider.count|{}count[0]
|
||||||
|
abstract fun <get-count>(): kotlin/Int // androidx.compose.material3.adaptive.layout/PaneScaffoldMotionDataProvider.count.<get-count>|<get-count>(){}[0]
|
||||||
|
abstract val scaffoldSize // androidx.compose.material3.adaptive.layout/PaneScaffoldMotionDataProvider.scaffoldSize|{}scaffoldSize[0]
|
||||||
|
abstract fun <get-scaffoldSize>(): androidx.compose.ui.unit/IntSize // androidx.compose.material3.adaptive.layout/PaneScaffoldMotionDataProvider.scaffoldSize.<get-scaffoldSize>|<get-scaffoldSize>(){}[0]
|
||||||
|
|
||||||
|
abstract fun get(#A): androidx.compose.material3.adaptive.layout/PaneMotionData // androidx.compose.material3.adaptive.layout/PaneScaffoldMotionDataProvider.get|get(1:0){}[0]
|
||||||
|
abstract fun get(kotlin/Int): androidx.compose.material3.adaptive.layout/PaneMotionData // androidx.compose.material3.adaptive.layout/PaneScaffoldMotionDataProvider.get|get(kotlin.Int){}[0]
|
||||||
|
abstract fun getRoleAt(kotlin/Int): #A // androidx.compose.material3.adaptive.layout/PaneScaffoldMotionDataProvider.getRoleAt|getRoleAt(kotlin.Int){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed interface <#A: androidx.compose.material3.adaptive.layout/PaneScaffoldRole> androidx.compose.material3.adaptive.layout/PaneScaffoldPaneScope { // androidx.compose.material3.adaptive.layout/PaneScaffoldPaneScope|null[0]
|
||||||
|
abstract val isInteractable // androidx.compose.material3.adaptive.layout/PaneScaffoldPaneScope.isInteractable|{}isInteractable[0]
|
||||||
|
abstract fun <get-isInteractable>(): kotlin/Boolean // androidx.compose.material3.adaptive.layout/PaneScaffoldPaneScope.isInteractable.<get-isInteractable>|<get-isInteractable>(){}[0]
|
||||||
|
abstract val paneMotion // androidx.compose.material3.adaptive.layout/PaneScaffoldPaneScope.paneMotion|{}paneMotion[0]
|
||||||
|
abstract fun <get-paneMotion>(): androidx.compose.material3.adaptive.layout/PaneMotion // androidx.compose.material3.adaptive.layout/PaneScaffoldPaneScope.paneMotion.<get-paneMotion>|<get-paneMotion>(){}[0]
|
||||||
|
abstract val paneRole // androidx.compose.material3.adaptive.layout/PaneScaffoldPaneScope.paneRole|{}paneRole[0]
|
||||||
|
abstract fun <get-paneRole>(): #A // androidx.compose.material3.adaptive.layout/PaneScaffoldPaneScope.paneRole.<get-paneRole>|<get-paneRole>(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed interface <#A: androidx.compose.material3.adaptive.layout/PaneScaffoldRole> androidx.compose.material3.adaptive.layout/PaneScaffoldValue { // androidx.compose.material3.adaptive.layout/PaneScaffoldValue|null[0]
|
||||||
|
abstract fun get(#A): androidx.compose.material3.adaptive.layout/PaneAdaptedValue // androidx.compose.material3.adaptive.layout/PaneScaffoldValue.get|get(1:0){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed interface androidx.compose.material3.adaptive.layout/AdaptStrategy { // androidx.compose.material3.adaptive.layout/AdaptStrategy|null[0]
|
||||||
|
open fun adapt(): androidx.compose.material3.adaptive.layout/PaneAdaptedValue // androidx.compose.material3.adaptive.layout/AdaptStrategy.adapt|adapt(){}[0]
|
||||||
|
|
||||||
|
final class Levitate : androidx.compose.material3.adaptive.layout/AdaptStrategy { // androidx.compose.material3.adaptive.layout/AdaptStrategy.Levitate|null[0]
|
||||||
|
constructor <init>(androidx.compose.ui/Alignment = ..., kotlin/Function2<androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>? = ...) // androidx.compose.material3.adaptive.layout/AdaptStrategy.Levitate.<init>|<init>(androidx.compose.ui.Alignment;kotlin.Function2<androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>?){}[0]
|
||||||
|
constructor <init>(androidx.compose.ui/Alignment = ..., kotlin/Function2<androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>? = ..., androidx.compose.material3.adaptive.layout/DragToResizeState? = ...) // androidx.compose.material3.adaptive.layout/AdaptStrategy.Levitate.<init>|<init>(androidx.compose.ui.Alignment;kotlin.Function2<androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>?;androidx.compose.material3.adaptive.layout.DragToResizeState?){}[0]
|
||||||
|
|
||||||
|
final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.material3.adaptive.layout/AdaptStrategy.Levitate.equals|equals(kotlin.Any?){}[0]
|
||||||
|
final fun hashCode(): kotlin/Int // androidx.compose.material3.adaptive.layout/AdaptStrategy.Levitate.hashCode|hashCode(){}[0]
|
||||||
|
final fun onlyIf(kotlin/Boolean, androidx.compose.runtime/Composer?, kotlin/Int): androidx.compose.material3.adaptive.layout/AdaptStrategy // androidx.compose.material3.adaptive.layout/AdaptStrategy.Levitate.onlyIf|onlyIf(kotlin.Boolean;androidx.compose.runtime.Composer?;kotlin.Int){}[0]
|
||||||
|
final fun onlyIfSinglePane(androidx.compose.material3.adaptive.layout/PaneScaffoldDirective, androidx.compose.runtime/Composer?, kotlin/Int): androidx.compose.material3.adaptive.layout/AdaptStrategy // androidx.compose.material3.adaptive.layout/AdaptStrategy.Levitate.onlyIfSinglePane|onlyIfSinglePane(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective;androidx.compose.runtime.Composer?;kotlin.Int){}[0]
|
||||||
|
final fun toString(): kotlin/String // androidx.compose.material3.adaptive.layout/AdaptStrategy.Levitate.toString|toString(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final class Reflow : androidx.compose.material3.adaptive.layout/AdaptStrategy { // androidx.compose.material3.adaptive.layout/AdaptStrategy.Reflow|null[0]
|
||||||
|
constructor <init>(androidx.compose.material3.adaptive.layout/PaneScaffoldRole) // androidx.compose.material3.adaptive.layout/AdaptStrategy.Reflow.<init>|<init>(androidx.compose.material3.adaptive.layout.PaneScaffoldRole){}[0]
|
||||||
|
|
||||||
|
final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.material3.adaptive.layout/AdaptStrategy.Reflow.equals|equals(kotlin.Any?){}[0]
|
||||||
|
final fun hashCode(): kotlin/Int // androidx.compose.material3.adaptive.layout/AdaptStrategy.Reflow.hashCode|hashCode(){}[0]
|
||||||
|
final fun toString(): kotlin/String // androidx.compose.material3.adaptive.layout/AdaptStrategy.Reflow.toString|toString(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final object Companion { // androidx.compose.material3.adaptive.layout/AdaptStrategy.Companion|null[0]
|
||||||
|
final val Hide // androidx.compose.material3.adaptive.layout/AdaptStrategy.Companion.Hide|{}Hide[0]
|
||||||
|
final fun <get-Hide>(): androidx.compose.material3.adaptive.layout/AdaptStrategy // androidx.compose.material3.adaptive.layout/AdaptStrategy.Companion.Hide.<get-Hide>|<get-Hide>(){}[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed interface androidx.compose.material3.adaptive.layout/AnimatedPaneScope : androidx.compose.animation/AnimatedVisibilityScope { // androidx.compose.material3.adaptive.layout/AnimatedPaneScope|null[0]
|
||||||
|
final object Companion { // androidx.compose.material3.adaptive.layout/AnimatedPaneScope.Companion|null[0]
|
||||||
|
final fun create(androidx.compose.animation/AnimatedVisibilityScope): androidx.compose.material3.adaptive.layout/AnimatedPaneScope // androidx.compose.material3.adaptive.layout/AnimatedPaneScope.Companion.create|create(androidx.compose.animation.AnimatedVisibilityScope){}[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed interface androidx.compose.material3.adaptive.layout/PaneAdaptedValue { // androidx.compose.material3.adaptive.layout/PaneAdaptedValue|null[0]
|
||||||
|
final class Levitated : androidx.compose.material3.adaptive.layout/PaneAdaptedValue { // androidx.compose.material3.adaptive.layout/PaneAdaptedValue.Levitated|null[0]
|
||||||
|
constructor <init>(androidx.compose.ui/Alignment, kotlin/Function2<androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>? = ...) // androidx.compose.material3.adaptive.layout/PaneAdaptedValue.Levitated.<init>|<init>(androidx.compose.ui.Alignment;kotlin.Function2<androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>?){}[0]
|
||||||
|
constructor <init>(androidx.compose.ui/Alignment, kotlin/Function2<androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>? = ..., androidx.compose.material3.adaptive.layout/DragToResizeState? = ...) // androidx.compose.material3.adaptive.layout/PaneAdaptedValue.Levitated.<init>|<init>(androidx.compose.ui.Alignment;kotlin.Function2<androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>?;androidx.compose.material3.adaptive.layout.DragToResizeState?){}[0]
|
||||||
|
|
||||||
|
final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.material3.adaptive.layout/PaneAdaptedValue.Levitated.equals|equals(kotlin.Any?){}[0]
|
||||||
|
final fun hashCode(): kotlin/Int // androidx.compose.material3.adaptive.layout/PaneAdaptedValue.Levitated.hashCode|hashCode(){}[0]
|
||||||
|
final fun toString(): kotlin/String // androidx.compose.material3.adaptive.layout/PaneAdaptedValue.Levitated.toString|toString(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final class Reflowed : androidx.compose.material3.adaptive.layout/PaneAdaptedValue { // androidx.compose.material3.adaptive.layout/PaneAdaptedValue.Reflowed|null[0]
|
||||||
|
constructor <init>(androidx.compose.material3.adaptive.layout/PaneScaffoldRole) // androidx.compose.material3.adaptive.layout/PaneAdaptedValue.Reflowed.<init>|<init>(androidx.compose.material3.adaptive.layout.PaneScaffoldRole){}[0]
|
||||||
|
|
||||||
|
final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.material3.adaptive.layout/PaneAdaptedValue.Reflowed.equals|equals(kotlin.Any?){}[0]
|
||||||
|
final fun hashCode(): kotlin/Int // androidx.compose.material3.adaptive.layout/PaneAdaptedValue.Reflowed.hashCode|hashCode(){}[0]
|
||||||
|
final fun toString(): kotlin/String // androidx.compose.material3.adaptive.layout/PaneAdaptedValue.Reflowed.toString|toString(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final object Companion { // androidx.compose.material3.adaptive.layout/PaneAdaptedValue.Companion|null[0]
|
||||||
|
final val Expanded // androidx.compose.material3.adaptive.layout/PaneAdaptedValue.Companion.Expanded|{}Expanded[0]
|
||||||
|
final fun <get-Expanded>(): androidx.compose.material3.adaptive.layout/PaneAdaptedValue // androidx.compose.material3.adaptive.layout/PaneAdaptedValue.Companion.Expanded.<get-Expanded>|<get-Expanded>(){}[0]
|
||||||
|
final val Hidden // androidx.compose.material3.adaptive.layout/PaneAdaptedValue.Companion.Hidden|{}Hidden[0]
|
||||||
|
final fun <get-Hidden>(): androidx.compose.material3.adaptive.layout/PaneAdaptedValue // androidx.compose.material3.adaptive.layout/PaneAdaptedValue.Companion.Hidden.<get-Hidden>|<get-Hidden>(){}[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed interface androidx.compose.material3.adaptive.layout/PaneExpansionStateKey { // androidx.compose.material3.adaptive.layout/PaneExpansionStateKey|null[0]
|
||||||
|
final object Companion { // androidx.compose.material3.adaptive.layout/PaneExpansionStateKey.Companion|null[0]
|
||||||
|
final val Default // androidx.compose.material3.adaptive.layout/PaneExpansionStateKey.Companion.Default|{}Default[0]
|
||||||
|
final fun <get-Default>(): androidx.compose.material3.adaptive.layout/PaneExpansionStateKey // androidx.compose.material3.adaptive.layout/PaneExpansionStateKey.Companion.Default.<get-Default>|<get-Default>(){}[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed interface androidx.compose.material3.adaptive.layout/PaneExpansionStateKeyProvider { // androidx.compose.material3.adaptive.layout/PaneExpansionStateKeyProvider|null[0]
|
||||||
|
abstract val paneExpansionStateKey // androidx.compose.material3.adaptive.layout/PaneExpansionStateKeyProvider.paneExpansionStateKey|{}paneExpansionStateKey[0]
|
||||||
|
abstract fun <get-paneExpansionStateKey>(): androidx.compose.material3.adaptive.layout/PaneExpansionStateKey // androidx.compose.material3.adaptive.layout/PaneExpansionStateKeyProvider.paneExpansionStateKey.<get-paneExpansionStateKey>|<get-paneExpansionStateKey>(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed interface androidx.compose.material3.adaptive.layout/PaneMargins { // androidx.compose.material3.adaptive.layout/PaneMargins|null[0]
|
||||||
|
open fun (androidx.compose.ui.layout/Placeable.PlacementScope).getPaneBottom(kotlin/Int, kotlin/Int): kotlin/Int // androidx.compose.material3.adaptive.layout/PaneMargins.getPaneBottom|getPaneBottom@androidx.compose.ui.layout.Placeable.PlacementScope(kotlin.Int;kotlin.Int){}[0]
|
||||||
|
open fun (androidx.compose.ui.layout/Placeable.PlacementScope).getPaneLeft(kotlin/Int): kotlin/Int // androidx.compose.material3.adaptive.layout/PaneMargins.getPaneLeft|getPaneLeft@androidx.compose.ui.layout.Placeable.PlacementScope(kotlin.Int){}[0]
|
||||||
|
open fun (androidx.compose.ui.layout/Placeable.PlacementScope).getPaneRight(kotlin/Int, kotlin/Int): kotlin/Int // androidx.compose.material3.adaptive.layout/PaneMargins.getPaneRight|getPaneRight@androidx.compose.ui.layout.Placeable.PlacementScope(kotlin.Int;kotlin.Int){}[0]
|
||||||
|
open fun (androidx.compose.ui.layout/Placeable.PlacementScope).getPaneTop(kotlin/Int): kotlin/Int // androidx.compose.material3.adaptive.layout/PaneMargins.getPaneTop|getPaneTop@androidx.compose.ui.layout.Placeable.PlacementScope(kotlin.Int){}[0]
|
||||||
|
|
||||||
|
final object Companion { // androidx.compose.material3.adaptive.layout/PaneMargins.Companion|null[0]
|
||||||
|
final val Unspecified // androidx.compose.material3.adaptive.layout/PaneMargins.Companion.Unspecified|{}Unspecified[0]
|
||||||
|
final fun <get-Unspecified>(): androidx.compose.material3.adaptive.layout/PaneMargins // androidx.compose.material3.adaptive.layout/PaneMargins.Companion.Unspecified.<get-Unspecified>|<get-Unspecified>(){}[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed interface androidx.compose.material3.adaptive.layout/PaneMotion { // androidx.compose.material3.adaptive.layout/PaneMotion|null[0]
|
||||||
|
abstract val type // androidx.compose.material3.adaptive.layout/PaneMotion.type|{}type[0]
|
||||||
|
abstract fun <get-type>(): androidx.compose.material3.adaptive.layout/PaneMotion.Type // androidx.compose.material3.adaptive.layout/PaneMotion.type.<get-type>|<get-type>(){}[0]
|
||||||
|
|
||||||
|
final value class Type { // androidx.compose.material3.adaptive.layout/PaneMotion.Type|null[0]
|
||||||
|
final val value // androidx.compose.material3.adaptive.layout/PaneMotion.Type.value|{}value[0]
|
||||||
|
final fun <get-value>(): kotlin/Int // androidx.compose.material3.adaptive.layout/PaneMotion.Type.value.<get-value>|<get-value>(){}[0]
|
||||||
|
|
||||||
|
final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.material3.adaptive.layout/PaneMotion.Type.equals|equals(kotlin.Any?){}[0]
|
||||||
|
final fun hashCode(): kotlin/Int // androidx.compose.material3.adaptive.layout/PaneMotion.Type.hashCode|hashCode(){}[0]
|
||||||
|
final fun toString(): kotlin/String // androidx.compose.material3.adaptive.layout/PaneMotion.Type.toString|toString(){}[0]
|
||||||
|
|
||||||
|
final object Companion { // androidx.compose.material3.adaptive.layout/PaneMotion.Type.Companion|null[0]
|
||||||
|
final val Entering // androidx.compose.material3.adaptive.layout/PaneMotion.Type.Companion.Entering|{}Entering[0]
|
||||||
|
final fun <get-Entering>(): androidx.compose.material3.adaptive.layout/PaneMotion.Type // androidx.compose.material3.adaptive.layout/PaneMotion.Type.Companion.Entering.<get-Entering>|<get-Entering>(){}[0]
|
||||||
|
final val EnteringModal // androidx.compose.material3.adaptive.layout/PaneMotion.Type.Companion.EnteringModal|{}EnteringModal[0]
|
||||||
|
final fun <get-EnteringModal>(): androidx.compose.material3.adaptive.layout/PaneMotion.Type // androidx.compose.material3.adaptive.layout/PaneMotion.Type.Companion.EnteringModal.<get-EnteringModal>|<get-EnteringModal>(){}[0]
|
||||||
|
final val Exiting // androidx.compose.material3.adaptive.layout/PaneMotion.Type.Companion.Exiting|{}Exiting[0]
|
||||||
|
final fun <get-Exiting>(): androidx.compose.material3.adaptive.layout/PaneMotion.Type // androidx.compose.material3.adaptive.layout/PaneMotion.Type.Companion.Exiting.<get-Exiting>|<get-Exiting>(){}[0]
|
||||||
|
final val ExitingModal // androidx.compose.material3.adaptive.layout/PaneMotion.Type.Companion.ExitingModal|{}ExitingModal[0]
|
||||||
|
final fun <get-ExitingModal>(): androidx.compose.material3.adaptive.layout/PaneMotion.Type // androidx.compose.material3.adaptive.layout/PaneMotion.Type.Companion.ExitingModal.<get-ExitingModal>|<get-ExitingModal>(){}[0]
|
||||||
|
final val Hidden // androidx.compose.material3.adaptive.layout/PaneMotion.Type.Companion.Hidden|{}Hidden[0]
|
||||||
|
final fun <get-Hidden>(): androidx.compose.material3.adaptive.layout/PaneMotion.Type // androidx.compose.material3.adaptive.layout/PaneMotion.Type.Companion.Hidden.<get-Hidden>|<get-Hidden>(){}[0]
|
||||||
|
final val Shown // androidx.compose.material3.adaptive.layout/PaneMotion.Type.Companion.Shown|{}Shown[0]
|
||||||
|
final fun <get-Shown>(): androidx.compose.material3.adaptive.layout/PaneMotion.Type // androidx.compose.material3.adaptive.layout/PaneMotion.Type.Companion.Shown.<get-Shown>|<get-Shown>(){}[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final object Companion { // androidx.compose.material3.adaptive.layout/PaneMotion.Companion|null[0]
|
||||||
|
final val AnimateBounds // androidx.compose.material3.adaptive.layout/PaneMotion.Companion.AnimateBounds|{}AnimateBounds[0]
|
||||||
|
final fun <get-AnimateBounds>(): androidx.compose.material3.adaptive.layout/PaneMotion // androidx.compose.material3.adaptive.layout/PaneMotion.Companion.AnimateBounds.<get-AnimateBounds>|<get-AnimateBounds>(){}[0]
|
||||||
|
final val EnterAsModal // androidx.compose.material3.adaptive.layout/PaneMotion.Companion.EnterAsModal|{}EnterAsModal[0]
|
||||||
|
final fun <get-EnterAsModal>(): androidx.compose.material3.adaptive.layout/PaneMotion // androidx.compose.material3.adaptive.layout/PaneMotion.Companion.EnterAsModal.<get-EnterAsModal>|<get-EnterAsModal>(){}[0]
|
||||||
|
final val EnterFromLeft // androidx.compose.material3.adaptive.layout/PaneMotion.Companion.EnterFromLeft|{}EnterFromLeft[0]
|
||||||
|
final fun <get-EnterFromLeft>(): androidx.compose.material3.adaptive.layout/PaneMotion // androidx.compose.material3.adaptive.layout/PaneMotion.Companion.EnterFromLeft.<get-EnterFromLeft>|<get-EnterFromLeft>(){}[0]
|
||||||
|
final val EnterFromLeftDelayed // androidx.compose.material3.adaptive.layout/PaneMotion.Companion.EnterFromLeftDelayed|{}EnterFromLeftDelayed[0]
|
||||||
|
final fun <get-EnterFromLeftDelayed>(): androidx.compose.material3.adaptive.layout/PaneMotion // androidx.compose.material3.adaptive.layout/PaneMotion.Companion.EnterFromLeftDelayed.<get-EnterFromLeftDelayed>|<get-EnterFromLeftDelayed>(){}[0]
|
||||||
|
final val EnterFromRight // androidx.compose.material3.adaptive.layout/PaneMotion.Companion.EnterFromRight|{}EnterFromRight[0]
|
||||||
|
final fun <get-EnterFromRight>(): androidx.compose.material3.adaptive.layout/PaneMotion // androidx.compose.material3.adaptive.layout/PaneMotion.Companion.EnterFromRight.<get-EnterFromRight>|<get-EnterFromRight>(){}[0]
|
||||||
|
final val EnterFromRightDelayed // androidx.compose.material3.adaptive.layout/PaneMotion.Companion.EnterFromRightDelayed|{}EnterFromRightDelayed[0]
|
||||||
|
final fun <get-EnterFromRightDelayed>(): androidx.compose.material3.adaptive.layout/PaneMotion // androidx.compose.material3.adaptive.layout/PaneMotion.Companion.EnterFromRightDelayed.<get-EnterFromRightDelayed>|<get-EnterFromRightDelayed>(){}[0]
|
||||||
|
final val EnterWithExpand // androidx.compose.material3.adaptive.layout/PaneMotion.Companion.EnterWithExpand|{}EnterWithExpand[0]
|
||||||
|
final fun <get-EnterWithExpand>(): androidx.compose.material3.adaptive.layout/PaneMotion // androidx.compose.material3.adaptive.layout/PaneMotion.Companion.EnterWithExpand.<get-EnterWithExpand>|<get-EnterWithExpand>(){}[0]
|
||||||
|
final val ExitAsModal // androidx.compose.material3.adaptive.layout/PaneMotion.Companion.ExitAsModal|{}ExitAsModal[0]
|
||||||
|
final fun <get-ExitAsModal>(): androidx.compose.material3.adaptive.layout/PaneMotion // androidx.compose.material3.adaptive.layout/PaneMotion.Companion.ExitAsModal.<get-ExitAsModal>|<get-ExitAsModal>(){}[0]
|
||||||
|
final val ExitToLeft // androidx.compose.material3.adaptive.layout/PaneMotion.Companion.ExitToLeft|{}ExitToLeft[0]
|
||||||
|
final fun <get-ExitToLeft>(): androidx.compose.material3.adaptive.layout/PaneMotion // androidx.compose.material3.adaptive.layout/PaneMotion.Companion.ExitToLeft.<get-ExitToLeft>|<get-ExitToLeft>(){}[0]
|
||||||
|
final val ExitToRight // androidx.compose.material3.adaptive.layout/PaneMotion.Companion.ExitToRight|{}ExitToRight[0]
|
||||||
|
final fun <get-ExitToRight>(): androidx.compose.material3.adaptive.layout/PaneMotion // androidx.compose.material3.adaptive.layout/PaneMotion.Companion.ExitToRight.<get-ExitToRight>|<get-ExitToRight>(){}[0]
|
||||||
|
final val ExitWithShrink // androidx.compose.material3.adaptive.layout/PaneMotion.Companion.ExitWithShrink|{}ExitWithShrink[0]
|
||||||
|
final fun <get-ExitWithShrink>(): androidx.compose.material3.adaptive.layout/PaneMotion // androidx.compose.material3.adaptive.layout/PaneMotion.Companion.ExitWithShrink.<get-ExitWithShrink>|<get-ExitWithShrink>(){}[0]
|
||||||
|
final val NoMotion // androidx.compose.material3.adaptive.layout/PaneMotion.Companion.NoMotion|{}NoMotion[0]
|
||||||
|
final fun <get-NoMotion>(): androidx.compose.material3.adaptive.layout/PaneMotion // androidx.compose.material3.adaptive.layout/PaneMotion.Companion.NoMotion.<get-NoMotion>|<get-NoMotion>(){}[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed interface androidx.compose.material3.adaptive.layout/PaneScaffoldParentData { // androidx.compose.material3.adaptive.layout/PaneScaffoldParentData|null[0]
|
||||||
|
abstract val isAnimatedPane // androidx.compose.material3.adaptive.layout/PaneScaffoldParentData.isAnimatedPane|{}isAnimatedPane[0]
|
||||||
|
abstract fun <get-isAnimatedPane>(): kotlin/Boolean // androidx.compose.material3.adaptive.layout/PaneScaffoldParentData.isAnimatedPane.<get-isAnimatedPane>|<get-isAnimatedPane>(){}[0]
|
||||||
|
abstract val minTouchTargetSize // androidx.compose.material3.adaptive.layout/PaneScaffoldParentData.minTouchTargetSize|{}minTouchTargetSize[0]
|
||||||
|
abstract fun <get-minTouchTargetSize>(): androidx.compose.ui.unit/Dp // androidx.compose.material3.adaptive.layout/PaneScaffoldParentData.minTouchTargetSize.<get-minTouchTargetSize>|<get-minTouchTargetSize>(){}[0]
|
||||||
|
abstract val paneMargins // androidx.compose.material3.adaptive.layout/PaneScaffoldParentData.paneMargins|{}paneMargins[0]
|
||||||
|
abstract fun <get-paneMargins>(): androidx.compose.material3.adaptive.layout/PaneMargins // androidx.compose.material3.adaptive.layout/PaneScaffoldParentData.paneMargins.<get-paneMargins>|<get-paneMargins>(){}[0]
|
||||||
|
abstract val preferredHeight // androidx.compose.material3.adaptive.layout/PaneScaffoldParentData.preferredHeight|{}preferredHeight[0]
|
||||||
|
abstract fun <get-preferredHeight>(): androidx.compose.ui.unit/Dp // androidx.compose.material3.adaptive.layout/PaneScaffoldParentData.preferredHeight.<get-preferredHeight>|<get-preferredHeight>(){}[0]
|
||||||
|
abstract val preferredHeightInProportion // androidx.compose.material3.adaptive.layout/PaneScaffoldParentData.preferredHeightInProportion|{}preferredHeightInProportion[0]
|
||||||
|
abstract fun <get-preferredHeightInProportion>(): kotlin/Float // androidx.compose.material3.adaptive.layout/PaneScaffoldParentData.preferredHeightInProportion.<get-preferredHeightInProportion>|<get-preferredHeightInProportion>(){}[0]
|
||||||
|
abstract val preferredWidth // androidx.compose.material3.adaptive.layout/PaneScaffoldParentData.preferredWidth|{}preferredWidth[0]
|
||||||
|
abstract fun <get-preferredWidth>(): androidx.compose.ui.unit/Dp // androidx.compose.material3.adaptive.layout/PaneScaffoldParentData.preferredWidth.<get-preferredWidth>|<get-preferredWidth>(){}[0]
|
||||||
|
abstract val preferredWidthInProportion // androidx.compose.material3.adaptive.layout/PaneScaffoldParentData.preferredWidthInProportion|{}preferredWidthInProportion[0]
|
||||||
|
abstract fun <get-preferredWidthInProportion>(): kotlin/Float // androidx.compose.material3.adaptive.layout/PaneScaffoldParentData.preferredWidthInProportion.<get-preferredWidthInProportion>|<get-preferredWidthInProportion>(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed interface androidx.compose.material3.adaptive.layout/PaneScaffoldScope { // androidx.compose.material3.adaptive.layout/PaneScaffoldScope|null[0]
|
||||||
|
abstract val saveableStateHolder // androidx.compose.material3.adaptive.layout/PaneScaffoldScope.saveableStateHolder|{}saveableStateHolder[0]
|
||||||
|
abstract fun <get-saveableStateHolder>(): androidx.compose.runtime.saveable/SaveableStateHolder // androidx.compose.material3.adaptive.layout/PaneScaffoldScope.saveableStateHolder.<get-saveableStateHolder>|<get-saveableStateHolder>(){}[0]
|
||||||
|
|
||||||
|
abstract fun (androidx.compose.ui/Modifier).paneExpansionDraggable(androidx.compose.material3.adaptive.layout/PaneExpansionState, androidx.compose.ui.unit/Dp, androidx.compose.foundation.interaction/MutableInteractionSource, kotlin/Function1<androidx.compose.ui.semantics/SemanticsPropertyReceiver, kotlin/Unit>? = ...): androidx.compose.ui/Modifier // androidx.compose.material3.adaptive.layout/PaneScaffoldScope.paneExpansionDraggable|paneExpansionDraggable@androidx.compose.ui.Modifier(androidx.compose.material3.adaptive.layout.PaneExpansionState;androidx.compose.ui.unit.Dp;androidx.compose.foundation.interaction.MutableInteractionSource;kotlin.Function1<androidx.compose.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>?){}[0]
|
||||||
|
abstract fun (androidx.compose.ui/Modifier).paneMargins(androidx.compose.foundation.layout/PaddingValues, kotlin/Array<out androidx.compose.ui.layout/RectRulers>..., androidx.compose.runtime/Composer?, kotlin/Int): androidx.compose.ui/Modifier // androidx.compose.material3.adaptive.layout/PaneScaffoldScope.paneMargins|paneMargins@androidx.compose.ui.Modifier(androidx.compose.foundation.layout.PaddingValues;kotlin.Array<out|androidx.compose.ui.layout.RectRulers>...;androidx.compose.runtime.Composer?;kotlin.Int){}[0]
|
||||||
|
abstract fun (androidx.compose.ui/Modifier).paneMargins(kotlin/Array<out androidx.compose.ui.layout/RectRulers>..., androidx.compose.runtime/Composer?, kotlin/Int): androidx.compose.ui/Modifier // androidx.compose.material3.adaptive.layout/PaneScaffoldScope.paneMargins|paneMargins@androidx.compose.ui.Modifier(kotlin.Array<out|androidx.compose.ui.layout.RectRulers>...;androidx.compose.runtime.Composer?;kotlin.Int){}[0]
|
||||||
|
abstract fun (androidx.compose.ui/Modifier).preferredHeight(androidx.compose.ui.unit/Dp): androidx.compose.ui/Modifier // androidx.compose.material3.adaptive.layout/PaneScaffoldScope.preferredHeight|preferredHeight@androidx.compose.ui.Modifier(androidx.compose.ui.unit.Dp){}[0]
|
||||||
|
abstract fun (androidx.compose.ui/Modifier).preferredHeight(kotlin/Float): androidx.compose.ui/Modifier // androidx.compose.material3.adaptive.layout/PaneScaffoldScope.preferredHeight|preferredHeight@androidx.compose.ui.Modifier(kotlin.Float){}[0]
|
||||||
|
abstract fun (androidx.compose.ui/Modifier).preferredWidth(androidx.compose.ui.unit/Dp): androidx.compose.ui/Modifier // androidx.compose.material3.adaptive.layout/PaneScaffoldScope.preferredWidth|preferredWidth@androidx.compose.ui.Modifier(androidx.compose.ui.unit.Dp){}[0]
|
||||||
|
abstract fun (androidx.compose.ui/Modifier).preferredWidth(kotlin/Float): androidx.compose.ui/Modifier // androidx.compose.material3.adaptive.layout/PaneScaffoldScope.preferredWidth|preferredWidth@androidx.compose.ui.Modifier(kotlin.Float){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed interface androidx.compose.material3.adaptive.layout/ThreePaneScaffoldPaneScope : androidx.compose.material3.adaptive.layout/ExtendedPaneScaffoldPaneScope<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole, androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue>, androidx.compose.material3.adaptive.layout/ThreePaneScaffoldScope // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldPaneScope|null[0]
|
||||||
|
|
||||||
|
sealed interface androidx.compose.material3.adaptive.layout/ThreePaneScaffoldScope : androidx.compose.material3.adaptive.layout/ExtendedPaneScaffoldScope<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole, androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue> // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldScope|null[0]
|
||||||
|
|
||||||
|
abstract class androidx.compose.material3.adaptive.layout/DragToResizeState : androidx.compose.foundation.gestures/DraggableState { // androidx.compose.material3.adaptive.layout/DragToResizeState|null[0]
|
||||||
|
open fun dispatchRawDelta(kotlin/Float) // androidx.compose.material3.adaptive.layout/DragToResizeState.dispatchRawDelta|dispatchRawDelta(kotlin.Float){}[0]
|
||||||
|
open suspend fun drag(androidx.compose.foundation/MutatePriority, kotlin.coroutines/SuspendFunction1<androidx.compose.foundation.gestures/DragScope, kotlin/Unit>) // androidx.compose.material3.adaptive.layout/DragToResizeState.drag|drag(androidx.compose.foundation.MutatePriority;kotlin.coroutines.SuspendFunction1<androidx.compose.foundation.gestures.DragScope,kotlin.Unit>){}[0]
|
||||||
|
|
||||||
|
final object Companion // androidx.compose.material3.adaptive.layout/DragToResizeState.Companion|null[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final class <#A: androidx.compose.material3.adaptive.layout/PaneScaffoldRole, #B: androidx.compose.material3.adaptive.layout/PaneScaffoldValue<#A>> androidx.compose.material3.adaptive.layout/AnimatedPaneOverrideScope { // androidx.compose.material3.adaptive.layout/AnimatedPaneOverrideScope|null[0]
|
||||||
|
final val boundsAnimationSpec // androidx.compose.material3.adaptive.layout/AnimatedPaneOverrideScope.boundsAnimationSpec|{}boundsAnimationSpec[0]
|
||||||
|
final fun <get-boundsAnimationSpec>(): androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.unit/IntRect> // androidx.compose.material3.adaptive.layout/AnimatedPaneOverrideScope.boundsAnimationSpec.<get-boundsAnimationSpec>|<get-boundsAnimationSpec>(){}[0]
|
||||||
|
final val content // androidx.compose.material3.adaptive.layout/AnimatedPaneOverrideScope.content|{}content[0]
|
||||||
|
final fun <get-content>(): kotlin/Function3<androidx.compose.material3.adaptive.layout/AnimatedPaneScope, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit> // androidx.compose.material3.adaptive.layout/AnimatedPaneOverrideScope.content.<get-content>|<get-content>(){}[0]
|
||||||
|
final val dragToResizeHandle // androidx.compose.material3.adaptive.layout/AnimatedPaneOverrideScope.dragToResizeHandle|{}dragToResizeHandle[0]
|
||||||
|
final fun <get-dragToResizeHandle>(): kotlin/Function3<androidx.compose.material3.adaptive.layout/DragToResizeState, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>? // androidx.compose.material3.adaptive.layout/AnimatedPaneOverrideScope.dragToResizeHandle.<get-dragToResizeHandle>|<get-dragToResizeHandle>(){}[0]
|
||||||
|
final val enterTransition // androidx.compose.material3.adaptive.layout/AnimatedPaneOverrideScope.enterTransition|{}enterTransition[0]
|
||||||
|
final fun <get-enterTransition>(): androidx.compose.animation/EnterTransition // androidx.compose.material3.adaptive.layout/AnimatedPaneOverrideScope.enterTransition.<get-enterTransition>|<get-enterTransition>(){}[0]
|
||||||
|
final val exitTransition // androidx.compose.material3.adaptive.layout/AnimatedPaneOverrideScope.exitTransition|{}exitTransition[0]
|
||||||
|
final fun <get-exitTransition>(): androidx.compose.animation/ExitTransition // androidx.compose.material3.adaptive.layout/AnimatedPaneOverrideScope.exitTransition.<get-exitTransition>|<get-exitTransition>(){}[0]
|
||||||
|
final val modifier // androidx.compose.material3.adaptive.layout/AnimatedPaneOverrideScope.modifier|{}modifier[0]
|
||||||
|
final fun <get-modifier>(): androidx.compose.ui/Modifier // androidx.compose.material3.adaptive.layout/AnimatedPaneOverrideScope.modifier.<get-modifier>|<get-modifier>(){}[0]
|
||||||
|
final val scope // androidx.compose.material3.adaptive.layout/AnimatedPaneOverrideScope.scope|{}scope[0]
|
||||||
|
final fun <get-scope>(): androidx.compose.material3.adaptive.layout/ExtendedPaneScaffoldPaneScope<#A, #B> // androidx.compose.material3.adaptive.layout/AnimatedPaneOverrideScope.scope.<get-scope>|<get-scope>(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final class <#A: out kotlin/Any?> androidx.compose.material3.adaptive.layout/ThreePaneScaffoldDestinationItem { // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldDestinationItem|null[0]
|
||||||
|
constructor <init>(androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole, #A? = ...) // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldDestinationItem.<init>|<init>(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole;1:0?){}[0]
|
||||||
|
|
||||||
|
final val contentKey // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldDestinationItem.contentKey|{}contentKey[0]
|
||||||
|
final fun <get-contentKey>(): #A? // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldDestinationItem.contentKey.<get-contentKey>|<get-contentKey>(){}[0]
|
||||||
|
final val pane // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldDestinationItem.pane|{}pane[0]
|
||||||
|
final fun <get-pane>(): androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldDestinationItem.pane.<get-pane>|<get-pane>(){}[0]
|
||||||
|
|
||||||
|
final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldDestinationItem.equals|equals(kotlin.Any?){}[0]
|
||||||
|
final fun hashCode(): kotlin/Int // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldDestinationItem.hashCode|hashCode(){}[0]
|
||||||
|
final fun toString(): kotlin/String // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldDestinationItem.toString|toString(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final class androidx.compose.material3.adaptive.layout/MutableThreePaneScaffoldState : androidx.compose.material3.adaptive.layout/ThreePaneScaffoldState { // androidx.compose.material3.adaptive.layout/MutableThreePaneScaffoldState|null[0]
|
||||||
|
constructor <init>(androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue) // androidx.compose.material3.adaptive.layout/MutableThreePaneScaffoldState.<init>|<init>(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue){}[0]
|
||||||
|
|
||||||
|
final val currentState // androidx.compose.material3.adaptive.layout/MutableThreePaneScaffoldState.currentState|{}currentState[0]
|
||||||
|
final fun <get-currentState>(): androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue // androidx.compose.material3.adaptive.layout/MutableThreePaneScaffoldState.currentState.<get-currentState>|<get-currentState>(){}[0]
|
||||||
|
final val progressFraction // androidx.compose.material3.adaptive.layout/MutableThreePaneScaffoldState.progressFraction|{}progressFraction[0]
|
||||||
|
final fun <get-progressFraction>(): kotlin/Float // androidx.compose.material3.adaptive.layout/MutableThreePaneScaffoldState.progressFraction.<get-progressFraction>|<get-progressFraction>(){}[0]
|
||||||
|
final val targetState // androidx.compose.material3.adaptive.layout/MutableThreePaneScaffoldState.targetState|{}targetState[0]
|
||||||
|
final fun <get-targetState>(): androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue // androidx.compose.material3.adaptive.layout/MutableThreePaneScaffoldState.targetState.<get-targetState>|<get-targetState>(){}[0]
|
||||||
|
|
||||||
|
final var isPredictiveBackInProgress // androidx.compose.material3.adaptive.layout/MutableThreePaneScaffoldState.isPredictiveBackInProgress|{}isPredictiveBackInProgress[0]
|
||||||
|
final fun <get-isPredictiveBackInProgress>(): kotlin/Boolean // androidx.compose.material3.adaptive.layout/MutableThreePaneScaffoldState.isPredictiveBackInProgress.<get-isPredictiveBackInProgress>|<get-isPredictiveBackInProgress>(){}[0]
|
||||||
|
|
||||||
|
final suspend fun animateTo(androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue = ..., androidx.compose.animation.core/FiniteAnimationSpec<kotlin/Float>? = ..., kotlin/Boolean = ...) // androidx.compose.material3.adaptive.layout/MutableThreePaneScaffoldState.animateTo|animateTo(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue;androidx.compose.animation.core.FiniteAnimationSpec<kotlin.Float>?;kotlin.Boolean){}[0]
|
||||||
|
final suspend fun seekTo(kotlin/Float, androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue = ..., kotlin/Boolean = ...) // androidx.compose.material3.adaptive.layout/MutableThreePaneScaffoldState.seekTo|seekTo(kotlin.Float;androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue;kotlin.Boolean){}[0]
|
||||||
|
final suspend fun snapTo(androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue) // androidx.compose.material3.adaptive.layout/MutableThreePaneScaffoldState.snapTo|snapTo(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final class androidx.compose.material3.adaptive.layout/PaneExpansionState { // androidx.compose.material3.adaptive.layout/PaneExpansionState|null[0]
|
||||||
|
final var currentAnchor // androidx.compose.material3.adaptive.layout/PaneExpansionState.currentAnchor|{}currentAnchor[0]
|
||||||
|
final fun <get-currentAnchor>(): androidx.compose.material3.adaptive.layout/PaneExpansionAnchor? // androidx.compose.material3.adaptive.layout/PaneExpansionState.currentAnchor.<get-currentAnchor>|<get-currentAnchor>(){}[0]
|
||||||
|
|
||||||
|
final fun clear() // androidx.compose.material3.adaptive.layout/PaneExpansionState.clear|clear(){}[0]
|
||||||
|
final fun isUnspecified(): kotlin/Boolean // androidx.compose.material3.adaptive.layout/PaneExpansionState.isUnspecified|isUnspecified(){}[0]
|
||||||
|
final fun setFirstPaneProportion(kotlin/Float) // androidx.compose.material3.adaptive.layout/PaneExpansionState.setFirstPaneProportion|setFirstPaneProportion(kotlin.Float){}[0]
|
||||||
|
final fun setFirstPaneWidth(kotlin/Int) // androidx.compose.material3.adaptive.layout/PaneExpansionState.setFirstPaneWidth|setFirstPaneWidth(kotlin.Int){}[0]
|
||||||
|
final suspend fun animateTo(androidx.compose.material3.adaptive.layout/PaneExpansionAnchor, kotlin/Float = ...) // androidx.compose.material3.adaptive.layout/PaneExpansionState.animateTo|animateTo(androidx.compose.material3.adaptive.layout.PaneExpansionAnchor;kotlin.Float){}[0]
|
||||||
|
|
||||||
|
final object Companion { // androidx.compose.material3.adaptive.layout/PaneExpansionState.Companion|null[0]
|
||||||
|
final const val Unspecified // androidx.compose.material3.adaptive.layout/PaneExpansionState.Companion.Unspecified|{}Unspecified[0]
|
||||||
|
final fun <get-Unspecified>(): kotlin/Int // androidx.compose.material3.adaptive.layout/PaneExpansionState.Companion.Unspecified.<get-Unspecified>|<get-Unspecified>(){}[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class androidx.compose.material3.adaptive.layout/PaneMotionData { // androidx.compose.material3.adaptive.layout/PaneMotionData|null[0]
|
||||||
|
final var motion // androidx.compose.material3.adaptive.layout/PaneMotionData.motion|{}motion[0]
|
||||||
|
final fun <get-motion>(): androidx.compose.material3.adaptive.layout/PaneMotion // androidx.compose.material3.adaptive.layout/PaneMotionData.motion.<get-motion>|<get-motion>(){}[0]
|
||||||
|
final var originPosition // androidx.compose.material3.adaptive.layout/PaneMotionData.originPosition|{}originPosition[0]
|
||||||
|
final fun <get-originPosition>(): androidx.compose.ui.unit/IntOffset // androidx.compose.material3.adaptive.layout/PaneMotionData.originPosition.<get-originPosition>|<get-originPosition>(){}[0]
|
||||||
|
final var originSize // androidx.compose.material3.adaptive.layout/PaneMotionData.originSize|{}originSize[0]
|
||||||
|
final fun <get-originSize>(): androidx.compose.ui.unit/IntSize // androidx.compose.material3.adaptive.layout/PaneMotionData.originSize.<get-originSize>|<get-originSize>(){}[0]
|
||||||
|
final var targetPosition // androidx.compose.material3.adaptive.layout/PaneMotionData.targetPosition|{}targetPosition[0]
|
||||||
|
final fun <get-targetPosition>(): androidx.compose.ui.unit/IntOffset // androidx.compose.material3.adaptive.layout/PaneMotionData.targetPosition.<get-targetPosition>|<get-targetPosition>(){}[0]
|
||||||
|
final var targetSize // androidx.compose.material3.adaptive.layout/PaneMotionData.targetSize|{}targetSize[0]
|
||||||
|
final fun <get-targetSize>(): androidx.compose.ui.unit/IntSize // androidx.compose.material3.adaptive.layout/PaneMotionData.targetSize.<get-targetSize>|<get-targetSize>(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final class androidx.compose.material3.adaptive.layout/PaneScaffoldDirective { // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective|null[0]
|
||||||
|
constructor <init>(kotlin/Int, androidx.compose.ui.unit/Dp, kotlin/Int, androidx.compose.ui.unit/Dp, androidx.compose.ui.unit/Dp, androidx.compose.ui.unit/Dp, kotlin.collections/List<androidx.compose.ui.geometry/Rect>) // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.<init>|<init>(kotlin.Int;androidx.compose.ui.unit.Dp;kotlin.Int;androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp;kotlin.collections.List<androidx.compose.ui.geometry.Rect>){}[0]
|
||||||
|
constructor <init>(kotlin/Int, androidx.compose.ui.unit/Dp, kotlin/Int, androidx.compose.ui.unit/Dp, androidx.compose.ui.unit/Dp, androidx.compose.ui.unit/Dp, kotlin.collections/List<androidx.compose.ui.geometry/Rect>, kotlin/Boolean) // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.<init>|<init>(kotlin.Int;androidx.compose.ui.unit.Dp;kotlin.Int;androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp;kotlin.collections.List<androidx.compose.ui.geometry.Rect>;kotlin.Boolean){}[0]
|
||||||
|
constructor <init>(kotlin/Int, androidx.compose.ui.unit/Dp, kotlin/Int, androidx.compose.ui.unit/Dp, androidx.compose.ui.unit/Dp, kotlin.collections/List<androidx.compose.ui.geometry/Rect>) // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.<init>|<init>(kotlin.Int;androidx.compose.ui.unit.Dp;kotlin.Int;androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp;kotlin.collections.List<androidx.compose.ui.geometry.Rect>){}[0]
|
||||||
|
|
||||||
|
final val defaultPanePreferredHeight // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.defaultPanePreferredHeight|{}defaultPanePreferredHeight[0]
|
||||||
|
final fun <get-defaultPanePreferredHeight>(): androidx.compose.ui.unit/Dp // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.defaultPanePreferredHeight.<get-defaultPanePreferredHeight>|<get-defaultPanePreferredHeight>(){}[0]
|
||||||
|
final val defaultPanePreferredWidth // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.defaultPanePreferredWidth|{}defaultPanePreferredWidth[0]
|
||||||
|
final fun <get-defaultPanePreferredWidth>(): androidx.compose.ui.unit/Dp // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.defaultPanePreferredWidth.<get-defaultPanePreferredWidth>|<get-defaultPanePreferredWidth>(){}[0]
|
||||||
|
final val excludedBounds // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.excludedBounds|{}excludedBounds[0]
|
||||||
|
final fun <get-excludedBounds>(): kotlin.collections/List<androidx.compose.ui.geometry/Rect> // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.excludedBounds.<get-excludedBounds>|<get-excludedBounds>(){}[0]
|
||||||
|
final val horizontalPartitionSpacerSize // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.horizontalPartitionSpacerSize|{}horizontalPartitionSpacerSize[0]
|
||||||
|
final fun <get-horizontalPartitionSpacerSize>(): androidx.compose.ui.unit/Dp // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.horizontalPartitionSpacerSize.<get-horizontalPartitionSpacerSize>|<get-horizontalPartitionSpacerSize>(){}[0]
|
||||||
|
final val maxHorizontalPartitions // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.maxHorizontalPartitions|{}maxHorizontalPartitions[0]
|
||||||
|
final fun <get-maxHorizontalPartitions>(): kotlin/Int // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.maxHorizontalPartitions.<get-maxHorizontalPartitions>|<get-maxHorizontalPartitions>(){}[0]
|
||||||
|
final val maxVerticalPartitions // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.maxVerticalPartitions|{}maxVerticalPartitions[0]
|
||||||
|
final fun <get-maxVerticalPartitions>(): kotlin/Int // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.maxVerticalPartitions.<get-maxVerticalPartitions>|<get-maxVerticalPartitions>(){}[0]
|
||||||
|
final val shouldAutoFocusCurrentDestination // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.shouldAutoFocusCurrentDestination|{}shouldAutoFocusCurrentDestination[0]
|
||||||
|
final fun <get-shouldAutoFocusCurrentDestination>(): kotlin/Boolean // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.shouldAutoFocusCurrentDestination.<get-shouldAutoFocusCurrentDestination>|<get-shouldAutoFocusCurrentDestination>(){}[0]
|
||||||
|
final val verticalPartitionSpacerSize // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.verticalPartitionSpacerSize|{}verticalPartitionSpacerSize[0]
|
||||||
|
final fun <get-verticalPartitionSpacerSize>(): androidx.compose.ui.unit/Dp // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.verticalPartitionSpacerSize.<get-verticalPartitionSpacerSize>|<get-verticalPartitionSpacerSize>(){}[0]
|
||||||
|
|
||||||
|
final fun copy(kotlin/Int = ..., androidx.compose.ui.unit/Dp = ..., kotlin/Int = ..., androidx.compose.ui.unit/Dp = ..., androidx.compose.ui.unit/Dp = ..., kotlin.collections/List<androidx.compose.ui.geometry/Rect> = ...): androidx.compose.material3.adaptive.layout/PaneScaffoldDirective // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.copy|copy(kotlin.Int;androidx.compose.ui.unit.Dp;kotlin.Int;androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp;kotlin.collections.List<androidx.compose.ui.geometry.Rect>){}[0]
|
||||||
|
final fun copy(kotlin/Int = ..., androidx.compose.ui.unit/Dp = ..., kotlin/Int = ..., androidx.compose.ui.unit/Dp = ..., androidx.compose.ui.unit/Dp = ..., kotlin.collections/List<androidx.compose.ui.geometry/Rect> = ..., androidx.compose.ui.unit/Dp = ...): androidx.compose.material3.adaptive.layout/PaneScaffoldDirective // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.copy|copy(kotlin.Int;androidx.compose.ui.unit.Dp;kotlin.Int;androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp;kotlin.collections.List<androidx.compose.ui.geometry.Rect>;androidx.compose.ui.unit.Dp){}[0]
|
||||||
|
final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.equals|equals(kotlin.Any?){}[0]
|
||||||
|
final fun hashCode(): kotlin/Int // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.hashCode|hashCode(){}[0]
|
||||||
|
final fun toString(): kotlin/String // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.toString|toString(){}[0]
|
||||||
|
|
||||||
|
final object Companion { // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.Companion|null[0]
|
||||||
|
final val Default // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.Companion.Default|{}Default[0]
|
||||||
|
final fun <get-Default>(): androidx.compose.material3.adaptive.layout/PaneScaffoldDirective // androidx.compose.material3.adaptive.layout/PaneScaffoldDirective.Companion.Default.<get-Default>|<get-Default>(){}[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class androidx.compose.material3.adaptive.layout/ThreePaneMotion { // androidx.compose.material3.adaptive.layout/ThreePaneMotion|null[0]
|
||||||
|
final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.material3.adaptive.layout/ThreePaneMotion.equals|equals(kotlin.Any?){}[0]
|
||||||
|
final fun get(androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole): androidx.compose.material3.adaptive.layout/PaneMotion // androidx.compose.material3.adaptive.layout/ThreePaneMotion.get|get(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole){}[0]
|
||||||
|
final fun hashCode(): kotlin/Int // androidx.compose.material3.adaptive.layout/ThreePaneMotion.hashCode|hashCode(){}[0]
|
||||||
|
final fun toString(): kotlin/String // androidx.compose.material3.adaptive.layout/ThreePaneMotion.toString|toString(){}[0]
|
||||||
|
|
||||||
|
final object Companion { // androidx.compose.material3.adaptive.layout/ThreePaneMotion.Companion|null[0]
|
||||||
|
final val NoMotion // androidx.compose.material3.adaptive.layout/ThreePaneMotion.Companion.NoMotion|{}NoMotion[0]
|
||||||
|
final fun <get-NoMotion>(): androidx.compose.material3.adaptive.layout/ThreePaneMotion // androidx.compose.material3.adaptive.layout/ThreePaneMotion.Companion.NoMotion.<get-NoMotion>|<get-NoMotion>(){}[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class androidx.compose.material3.adaptive.layout/ThreePaneScaffoldAdaptStrategies { // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldAdaptStrategies|null[0]
|
||||||
|
constructor <init>(androidx.compose.material3.adaptive.layout/AdaptStrategy, androidx.compose.material3.adaptive.layout/AdaptStrategy, androidx.compose.material3.adaptive.layout/AdaptStrategy) // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldAdaptStrategies.<init>|<init>(androidx.compose.material3.adaptive.layout.AdaptStrategy;androidx.compose.material3.adaptive.layout.AdaptStrategy;androidx.compose.material3.adaptive.layout.AdaptStrategy){}[0]
|
||||||
|
|
||||||
|
final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldAdaptStrategies.equals|equals(kotlin.Any?){}[0]
|
||||||
|
final fun get(androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole): androidx.compose.material3.adaptive.layout/AdaptStrategy // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldAdaptStrategies.get|get(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole){}[0]
|
||||||
|
final fun hashCode(): kotlin/Int // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldAdaptStrategies.hashCode|hashCode(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final class androidx.compose.material3.adaptive.layout/ThreePaneScaffoldHorizontalOrder : androidx.compose.material3.adaptive.layout/PaneScaffoldHorizontalOrder<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole> { // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldHorizontalOrder|null[0]
|
||||||
|
final val size // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldHorizontalOrder.size|{}size[0]
|
||||||
|
final fun <get-size>(): kotlin/Int // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldHorizontalOrder.size.<get-size>|<get-size>(){}[0]
|
||||||
|
|
||||||
|
final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldHorizontalOrder.equals|equals(kotlin.Any?){}[0]
|
||||||
|
final fun forEach(kotlin/Function1<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole, kotlin/Unit>) // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldHorizontalOrder.forEach|forEach(kotlin.Function1<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole,kotlin.Unit>){}[0]
|
||||||
|
final fun forEachIndexed(kotlin/Function2<kotlin/Int, androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole, kotlin/Unit>) // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldHorizontalOrder.forEachIndexed|forEachIndexed(kotlin.Function2<kotlin.Int,androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole,kotlin.Unit>){}[0]
|
||||||
|
final fun forEachIndexedReversed(kotlin/Function2<kotlin/Int, androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole, kotlin/Unit>) // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldHorizontalOrder.forEachIndexedReversed|forEachIndexedReversed(kotlin.Function2<kotlin.Int,androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole,kotlin.Unit>){}[0]
|
||||||
|
final fun get(kotlin/Int): androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldHorizontalOrder.get|get(kotlin.Int){}[0]
|
||||||
|
final fun hashCode(): kotlin/Int // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldHorizontalOrder.hashCode|hashCode(){}[0]
|
||||||
|
final fun indexOf(androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole): kotlin/Int // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldHorizontalOrder.indexOf|indexOf(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final class androidx.compose.material3.adaptive.layout/ThreePaneScaffoldOverrideScope { // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldOverrideScope|null[0]
|
||||||
|
final val modifier // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldOverrideScope.modifier|{}modifier[0]
|
||||||
|
final fun <get-modifier>(): androidx.compose.ui/Modifier // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldOverrideScope.modifier.<get-modifier>|<get-modifier>(){}[0]
|
||||||
|
final val paneExpansionDragHandle // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldOverrideScope.paneExpansionDragHandle|{}paneExpansionDragHandle[0]
|
||||||
|
final fun <get-paneExpansionDragHandle>(): kotlin/Function3<androidx.compose.material3.adaptive.layout/PaneExpansionState, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>? // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldOverrideScope.paneExpansionDragHandle.<get-paneExpansionDragHandle>|<get-paneExpansionDragHandle>(){}[0]
|
||||||
|
final val paneExpansionState // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldOverrideScope.paneExpansionState|{}paneExpansionState[0]
|
||||||
|
final fun <get-paneExpansionState>(): androidx.compose.material3.adaptive.layout/PaneExpansionState // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldOverrideScope.paneExpansionState.<get-paneExpansionState>|<get-paneExpansionState>(){}[0]
|
||||||
|
final val paneOrder // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldOverrideScope.paneOrder|{}paneOrder[0]
|
||||||
|
final fun <get-paneOrder>(): androidx.compose.material3.adaptive.layout/ThreePaneScaffoldHorizontalOrder // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldOverrideScope.paneOrder.<get-paneOrder>|<get-paneOrder>(){}[0]
|
||||||
|
final val primaryPane // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldOverrideScope.primaryPane|{}primaryPane[0]
|
||||||
|
final fun <get-primaryPane>(): kotlin/Function2<androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit> // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldOverrideScope.primaryPane.<get-primaryPane>|<get-primaryPane>(){}[0]
|
||||||
|
final val scaffoldDirective // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldOverrideScope.scaffoldDirective|{}scaffoldDirective[0]
|
||||||
|
final fun <get-scaffoldDirective>(): androidx.compose.material3.adaptive.layout/PaneScaffoldDirective // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldOverrideScope.scaffoldDirective.<get-scaffoldDirective>|<get-scaffoldDirective>(){}[0]
|
||||||
|
final val scaffoldState // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldOverrideScope.scaffoldState|{}scaffoldState[0]
|
||||||
|
final fun <get-scaffoldState>(): androidx.compose.material3.adaptive.layout/ThreePaneScaffoldState // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldOverrideScope.scaffoldState.<get-scaffoldState>|<get-scaffoldState>(){}[0]
|
||||||
|
final val secondaryPane // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldOverrideScope.secondaryPane|{}secondaryPane[0]
|
||||||
|
final fun <get-secondaryPane>(): kotlin/Function2<androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit> // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldOverrideScope.secondaryPane.<get-secondaryPane>|<get-secondaryPane>(){}[0]
|
||||||
|
final val tertiaryPane // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldOverrideScope.tertiaryPane|{}tertiaryPane[0]
|
||||||
|
final fun <get-tertiaryPane>(): kotlin/Function2<androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>? // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldOverrideScope.tertiaryPane.<get-tertiaryPane>|<get-tertiaryPane>(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final class androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue : androidx.compose.material3.adaptive.layout/PaneExpansionStateKeyProvider, androidx.compose.material3.adaptive.layout/PaneScaffoldValue<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole> { // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue|null[0]
|
||||||
|
constructor <init>(androidx.compose.material3.adaptive.layout/PaneAdaptedValue, androidx.compose.material3.adaptive.layout/PaneAdaptedValue, androidx.compose.material3.adaptive.layout/PaneAdaptedValue) // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue.<init>|<init>(androidx.compose.material3.adaptive.layout.PaneAdaptedValue;androidx.compose.material3.adaptive.layout.PaneAdaptedValue;androidx.compose.material3.adaptive.layout.PaneAdaptedValue){}[0]
|
||||||
|
|
||||||
|
final val paneExpansionStateKey // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue.paneExpansionStateKey|{}paneExpansionStateKey[0]
|
||||||
|
final fun <get-paneExpansionStateKey>(): androidx.compose.material3.adaptive.layout/PaneExpansionStateKey // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue.paneExpansionStateKey.<get-paneExpansionStateKey>|<get-paneExpansionStateKey>(){}[0]
|
||||||
|
final val primary // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue.primary|{}primary[0]
|
||||||
|
final fun <get-primary>(): androidx.compose.material3.adaptive.layout/PaneAdaptedValue // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue.primary.<get-primary>|<get-primary>(){}[0]
|
||||||
|
final val secondary // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue.secondary|{}secondary[0]
|
||||||
|
final fun <get-secondary>(): androidx.compose.material3.adaptive.layout/PaneAdaptedValue // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue.secondary.<get-secondary>|<get-secondary>(){}[0]
|
||||||
|
final val tertiary // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue.tertiary|{}tertiary[0]
|
||||||
|
final fun <get-tertiary>(): androidx.compose.material3.adaptive.layout/PaneAdaptedValue // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue.tertiary.<get-tertiary>|<get-tertiary>(){}[0]
|
||||||
|
|
||||||
|
final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue.equals|equals(kotlin.Any?){}[0]
|
||||||
|
final fun get(androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole): androidx.compose.material3.adaptive.layout/PaneAdaptedValue // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue.get|get(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole){}[0]
|
||||||
|
final fun hashCode(): kotlin/Int // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue.hashCode|hashCode(){}[0]
|
||||||
|
final fun toString(): kotlin/String // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue.toString|toString(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final value class androidx.compose.material3.adaptive.layout/HingePolicy { // androidx.compose.material3.adaptive.layout/HingePolicy|null[0]
|
||||||
|
final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.material3.adaptive.layout/HingePolicy.equals|equals(kotlin.Any?){}[0]
|
||||||
|
final fun hashCode(): kotlin/Int // androidx.compose.material3.adaptive.layout/HingePolicy.hashCode|hashCode(){}[0]
|
||||||
|
final fun toString(): kotlin/String // androidx.compose.material3.adaptive.layout/HingePolicy.toString|toString(){}[0]
|
||||||
|
|
||||||
|
final object Companion { // androidx.compose.material3.adaptive.layout/HingePolicy.Companion|null[0]
|
||||||
|
final val AlwaysAvoid // androidx.compose.material3.adaptive.layout/HingePolicy.Companion.AlwaysAvoid|{}AlwaysAvoid[0]
|
||||||
|
final fun <get-AlwaysAvoid>(): androidx.compose.material3.adaptive.layout/HingePolicy // androidx.compose.material3.adaptive.layout/HingePolicy.Companion.AlwaysAvoid.<get-AlwaysAvoid>|<get-AlwaysAvoid>(){}[0]
|
||||||
|
final val AvoidOccluding // androidx.compose.material3.adaptive.layout/HingePolicy.Companion.AvoidOccluding|{}AvoidOccluding[0]
|
||||||
|
final fun <get-AvoidOccluding>(): androidx.compose.material3.adaptive.layout/HingePolicy // androidx.compose.material3.adaptive.layout/HingePolicy.Companion.AvoidOccluding.<get-AvoidOccluding>|<get-AvoidOccluding>(){}[0]
|
||||||
|
final val AvoidSeparating // androidx.compose.material3.adaptive.layout/HingePolicy.Companion.AvoidSeparating|{}AvoidSeparating[0]
|
||||||
|
final fun <get-AvoidSeparating>(): androidx.compose.material3.adaptive.layout/HingePolicy // androidx.compose.material3.adaptive.layout/HingePolicy.Companion.AvoidSeparating.<get-AvoidSeparating>|<get-AvoidSeparating>(){}[0]
|
||||||
|
final val NeverAvoid // androidx.compose.material3.adaptive.layout/HingePolicy.Companion.NeverAvoid|{}NeverAvoid[0]
|
||||||
|
final fun <get-NeverAvoid>(): androidx.compose.material3.adaptive.layout/HingePolicy // androidx.compose.material3.adaptive.layout/HingePolicy.Companion.NeverAvoid.<get-NeverAvoid>|<get-NeverAvoid>(){}[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class androidx.compose.material3.adaptive.layout/PaneExpansionAnchor { // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor|null[0]
|
||||||
|
abstract val description // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.description|{}description[0]
|
||||||
|
abstract fun <get-description>(androidx.compose.runtime/Composer?, kotlin/Int): kotlin/String // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.description.<get-description>|<get-description>(androidx.compose.runtime.Composer?;kotlin.Int){}[0]
|
||||||
|
|
||||||
|
abstract class Offset : androidx.compose.material3.adaptive.layout/PaneExpansionAnchor { // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Offset|null[0]
|
||||||
|
final val direction // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Offset.direction|{}direction[0]
|
||||||
|
final fun <get-direction>(): androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Offset.Direction // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Offset.direction.<get-direction>|<get-direction>(){}[0]
|
||||||
|
final val offset // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Offset.offset|{}offset[0]
|
||||||
|
final fun <get-offset>(): androidx.compose.ui.unit/Dp // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Offset.offset.<get-offset>|<get-offset>(){}[0]
|
||||||
|
|
||||||
|
open fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Offset.equals|equals(kotlin.Any?){}[0]
|
||||||
|
open fun hashCode(): kotlin/Int // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Offset.hashCode|hashCode(){}[0]
|
||||||
|
open fun toString(): kotlin/String // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Offset.toString|toString(){}[0]
|
||||||
|
|
||||||
|
final value class Direction { // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Offset.Direction|null[0]
|
||||||
|
final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Offset.Direction.equals|equals(kotlin.Any?){}[0]
|
||||||
|
final fun hashCode(): kotlin/Int // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Offset.Direction.hashCode|hashCode(){}[0]
|
||||||
|
final fun toString(): kotlin/String // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Offset.Direction.toString|toString(){}[0]
|
||||||
|
|
||||||
|
final object Companion { // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Offset.Direction.Companion|null[0]
|
||||||
|
final val FromEnd // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Offset.Direction.Companion.FromEnd|{}FromEnd[0]
|
||||||
|
final fun <get-FromEnd>(): androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Offset.Direction // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Offset.Direction.Companion.FromEnd.<get-FromEnd>|<get-FromEnd>(){}[0]
|
||||||
|
final val FromStart // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Offset.Direction.Companion.FromStart|{}FromStart[0]
|
||||||
|
final fun <get-FromStart>(): androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Offset.Direction // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Offset.Direction.Companion.FromStart.<get-FromStart>|<get-FromStart>(){}[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final object Companion { // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Offset.Companion|null[0]
|
||||||
|
final fun fromEnd(androidx.compose.ui.unit/Dp): androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Offset // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Offset.Companion.fromEnd|fromEnd(androidx.compose.ui.unit.Dp){}[0]
|
||||||
|
final fun fromStart(androidx.compose.ui.unit/Dp): androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Offset // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Offset.Companion.fromStart|fromStart(androidx.compose.ui.unit.Dp){}[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class Proportion : androidx.compose.material3.adaptive.layout/PaneExpansionAnchor { // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Proportion|null[0]
|
||||||
|
constructor <init>(kotlin/Float) // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Proportion.<init>|<init>(kotlin.Float){}[0]
|
||||||
|
|
||||||
|
final val description // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Proportion.description|{}description[0]
|
||||||
|
final fun <get-description>(androidx.compose.runtime/Composer?, kotlin/Int): kotlin/String // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Proportion.description.<get-description>|<get-description>(androidx.compose.runtime.Composer?;kotlin.Int){}[0]
|
||||||
|
final val proportion // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Proportion.proportion|{}proportion[0]
|
||||||
|
final fun <get-proportion>(): kotlin/Float // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Proportion.proportion.<get-proportion>|<get-proportion>(){}[0]
|
||||||
|
|
||||||
|
final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Proportion.equals|equals(kotlin.Any?){}[0]
|
||||||
|
final fun hashCode(): kotlin/Int // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Proportion.hashCode|hashCode(){}[0]
|
||||||
|
final fun toString(): kotlin/String // androidx.compose.material3.adaptive.layout/PaneExpansionAnchor.Proportion.toString|toString(){}[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class androidx.compose.material3.adaptive.layout/ThreePaneScaffoldState { // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldState|null[0]
|
||||||
|
abstract val currentState // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldState.currentState|{}currentState[0]
|
||||||
|
abstract fun <get-currentState>(): androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldState.currentState.<get-currentState>|<get-currentState>(){}[0]
|
||||||
|
abstract val isPredictiveBackInProgress // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldState.isPredictiveBackInProgress|{}isPredictiveBackInProgress[0]
|
||||||
|
abstract fun <get-isPredictiveBackInProgress>(): kotlin/Boolean // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldState.isPredictiveBackInProgress.<get-isPredictiveBackInProgress>|<get-isPredictiveBackInProgress>(){}[0]
|
||||||
|
abstract val progressFraction // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldState.progressFraction|{}progressFraction[0]
|
||||||
|
abstract fun <get-progressFraction>(): kotlin/Float // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldState.progressFraction.<get-progressFraction>|<get-progressFraction>(){}[0]
|
||||||
|
abstract val targetState // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldState.targetState|{}targetState[0]
|
||||||
|
abstract fun <get-targetState>(): androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue // androidx.compose.material3.adaptive.layout/ThreePaneScaffoldState.targetState.<get-targetState>|<get-targetState>(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final object androidx.compose.material3.adaptive.layout/LevitatedPaneScrimDefaults { // androidx.compose.material3.adaptive.layout/LevitatedPaneScrimDefaults|null[0]
|
||||||
|
final val Color // androidx.compose.material3.adaptive.layout/LevitatedPaneScrimDefaults.Color|{}Color[0]
|
||||||
|
final fun <get-Color>(): androidx.compose.ui.graphics/Color // androidx.compose.material3.adaptive.layout/LevitatedPaneScrimDefaults.Color.<get-Color>|<get-Color>(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final object androidx.compose.material3.adaptive.layout/ListDetailPaneScaffoldDefaults { // androidx.compose.material3.adaptive.layout/ListDetailPaneScaffoldDefaults|null[0]
|
||||||
|
final fun adaptStrategies(androidx.compose.material3.adaptive.layout/AdaptStrategy = ..., androidx.compose.material3.adaptive.layout/AdaptStrategy = ..., androidx.compose.material3.adaptive.layout/AdaptStrategy = ...): androidx.compose.material3.adaptive.layout/ThreePaneScaffoldAdaptStrategies // androidx.compose.material3.adaptive.layout/ListDetailPaneScaffoldDefaults.adaptStrategies|adaptStrategies(androidx.compose.material3.adaptive.layout.AdaptStrategy;androidx.compose.material3.adaptive.layout.AdaptStrategy;androidx.compose.material3.adaptive.layout.AdaptStrategy){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final object androidx.compose.material3.adaptive.layout/ListDetailPaneScaffoldRole { // androidx.compose.material3.adaptive.layout/ListDetailPaneScaffoldRole|null[0]
|
||||||
|
final val Detail // androidx.compose.material3.adaptive.layout/ListDetailPaneScaffoldRole.Detail|{}Detail[0]
|
||||||
|
final fun <get-Detail>(): androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole // androidx.compose.material3.adaptive.layout/ListDetailPaneScaffoldRole.Detail.<get-Detail>|<get-Detail>(){}[0]
|
||||||
|
final val Extra // androidx.compose.material3.adaptive.layout/ListDetailPaneScaffoldRole.Extra|{}Extra[0]
|
||||||
|
final fun <get-Extra>(): androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole // androidx.compose.material3.adaptive.layout/ListDetailPaneScaffoldRole.Extra.<get-Extra>|<get-Extra>(){}[0]
|
||||||
|
final val List // androidx.compose.material3.adaptive.layout/ListDetailPaneScaffoldRole.List|{}List[0]
|
||||||
|
final fun <get-List>(): androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole // androidx.compose.material3.adaptive.layout/ListDetailPaneScaffoldRole.List.<get-List>|<get-List>(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final object androidx.compose.material3.adaptive.layout/PaneMotionDefaults { // androidx.compose.material3.adaptive.layout/PaneMotionDefaults|null[0]
|
||||||
|
final val AnimationSpec // androidx.compose.material3.adaptive.layout/PaneMotionDefaults.AnimationSpec|{}AnimationSpec[0]
|
||||||
|
final fun <get-AnimationSpec>(): androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.unit/IntRect> // androidx.compose.material3.adaptive.layout/PaneMotionDefaults.AnimationSpec.<get-AnimationSpec>|<get-AnimationSpec>(){}[0]
|
||||||
|
final val DelayedAnimationSpec // androidx.compose.material3.adaptive.layout/PaneMotionDefaults.DelayedAnimationSpec|{}DelayedAnimationSpec[0]
|
||||||
|
final fun <get-DelayedAnimationSpec>(): androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.unit/IntRect> // androidx.compose.material3.adaptive.layout/PaneMotionDefaults.DelayedAnimationSpec.<get-DelayedAnimationSpec>|<get-DelayedAnimationSpec>(){}[0]
|
||||||
|
final val DelayedOffsetAnimationSpec // androidx.compose.material3.adaptive.layout/PaneMotionDefaults.DelayedOffsetAnimationSpec|{}DelayedOffsetAnimationSpec[0]
|
||||||
|
final fun <get-DelayedOffsetAnimationSpec>(): androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.unit/IntOffset> // androidx.compose.material3.adaptive.layout/PaneMotionDefaults.DelayedOffsetAnimationSpec.<get-DelayedOffsetAnimationSpec>|<get-DelayedOffsetAnimationSpec>(){}[0]
|
||||||
|
final val DelayedSizeAnimationSpec // androidx.compose.material3.adaptive.layout/PaneMotionDefaults.DelayedSizeAnimationSpec|{}DelayedSizeAnimationSpec[0]
|
||||||
|
final fun <get-DelayedSizeAnimationSpec>(): androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.unit/IntSize> // androidx.compose.material3.adaptive.layout/PaneMotionDefaults.DelayedSizeAnimationSpec.<get-DelayedSizeAnimationSpec>|<get-DelayedSizeAnimationSpec>(){}[0]
|
||||||
|
final val OffsetAnimationSpec // androidx.compose.material3.adaptive.layout/PaneMotionDefaults.OffsetAnimationSpec|{}OffsetAnimationSpec[0]
|
||||||
|
final fun <get-OffsetAnimationSpec>(): androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.unit/IntOffset> // androidx.compose.material3.adaptive.layout/PaneMotionDefaults.OffsetAnimationSpec.<get-OffsetAnimationSpec>|<get-OffsetAnimationSpec>(){}[0]
|
||||||
|
final val SizeAnimationSpec // androidx.compose.material3.adaptive.layout/PaneMotionDefaults.SizeAnimationSpec|{}SizeAnimationSpec[0]
|
||||||
|
final fun <get-SizeAnimationSpec>(): androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.unit/IntSize> // androidx.compose.material3.adaptive.layout/PaneMotionDefaults.SizeAnimationSpec.<get-SizeAnimationSpec>|<get-SizeAnimationSpec>(){}[0]
|
||||||
|
final val VisibilityAnimationSpec // androidx.compose.material3.adaptive.layout/PaneMotionDefaults.VisibilityAnimationSpec|{}VisibilityAnimationSpec[0]
|
||||||
|
final fun <get-VisibilityAnimationSpec>(): androidx.compose.animation.core/FiniteAnimationSpec<kotlin/Float> // androidx.compose.material3.adaptive.layout/PaneMotionDefaults.VisibilityAnimationSpec.<get-VisibilityAnimationSpec>|<get-VisibilityAnimationSpec>(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final object androidx.compose.material3.adaptive.layout/SupportingPaneScaffoldDefaults { // androidx.compose.material3.adaptive.layout/SupportingPaneScaffoldDefaults|null[0]
|
||||||
|
final fun adaptStrategies(androidx.compose.material3.adaptive.layout/AdaptStrategy = ..., androidx.compose.material3.adaptive.layout/AdaptStrategy = ..., androidx.compose.material3.adaptive.layout/AdaptStrategy = ...): androidx.compose.material3.adaptive.layout/ThreePaneScaffoldAdaptStrategies // androidx.compose.material3.adaptive.layout/SupportingPaneScaffoldDefaults.adaptStrategies|adaptStrategies(androidx.compose.material3.adaptive.layout.AdaptStrategy;androidx.compose.material3.adaptive.layout.AdaptStrategy;androidx.compose.material3.adaptive.layout.AdaptStrategy){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final object androidx.compose.material3.adaptive.layout/SupportingPaneScaffoldRole { // androidx.compose.material3.adaptive.layout/SupportingPaneScaffoldRole|null[0]
|
||||||
|
final val Extra // androidx.compose.material3.adaptive.layout/SupportingPaneScaffoldRole.Extra|{}Extra[0]
|
||||||
|
final fun <get-Extra>(): androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole // androidx.compose.material3.adaptive.layout/SupportingPaneScaffoldRole.Extra.<get-Extra>|<get-Extra>(){}[0]
|
||||||
|
final val Main // androidx.compose.material3.adaptive.layout/SupportingPaneScaffoldRole.Main|{}Main[0]
|
||||||
|
final fun <get-Main>(): androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole // androidx.compose.material3.adaptive.layout/SupportingPaneScaffoldRole.Main.<get-Main>|<get-Main>(){}[0]
|
||||||
|
final val Supporting // androidx.compose.material3.adaptive.layout/SupportingPaneScaffoldRole.Supporting|{}Supporting[0]
|
||||||
|
final fun <get-Supporting>(): androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole // androidx.compose.material3.adaptive.layout/SupportingPaneScaffoldRole.Supporting.<get-Supporting>|<get-Supporting>(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final val androidx.compose.material3.adaptive.layout/LocalAnimatedPaneOverride // androidx.compose.material3.adaptive.layout/LocalAnimatedPaneOverride|{}LocalAnimatedPaneOverride[0]
|
||||||
|
final fun <get-LocalAnimatedPaneOverride>(): androidx.compose.runtime/ProvidableCompositionLocal<androidx.compose.material3.adaptive.layout/AnimatedPaneOverride> // androidx.compose.material3.adaptive.layout/LocalAnimatedPaneOverride.<get-LocalAnimatedPaneOverride>|<get-LocalAnimatedPaneOverride>(){}[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/LocalThreePaneScaffoldOverride // androidx.compose.material3.adaptive.layout/LocalThreePaneScaffoldOverride|{}LocalThreePaneScaffoldOverride[0]
|
||||||
|
final fun <get-LocalThreePaneScaffoldOverride>(): androidx.compose.runtime/ProvidableCompositionLocal<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldOverride> // androidx.compose.material3.adaptive.layout/LocalThreePaneScaffoldOverride.<get-LocalThreePaneScaffoldOverride>|<get-LocalThreePaneScaffoldOverride>(){}[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_AdaptStrategy_Levitate$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_AdaptStrategy_Levitate$stableprop|#static{}androidx_compose_material3_adaptive_layout_AdaptStrategy_Levitate$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_AdaptStrategy_Reflow$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_AdaptStrategy_Reflow$stableprop|#static{}androidx_compose_material3_adaptive_layout_AdaptStrategy_Reflow$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_AnimatedPaneOverrideScope$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_AnimatedPaneOverrideScope$stableprop|#static{}androidx_compose_material3_adaptive_layout_AnimatedPaneOverrideScope$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_DragToResizeState$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_DragToResizeState$stableprop|#static{}androidx_compose_material3_adaptive_layout_DragToResizeState$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_LevitatedPaneScrimDefaults$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_LevitatedPaneScrimDefaults$stableprop|#static{}androidx_compose_material3_adaptive_layout_LevitatedPaneScrimDefaults$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ListDetailPaneScaffoldDefaults$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ListDetailPaneScaffoldDefaults$stableprop|#static{}androidx_compose_material3_adaptive_layout_ListDetailPaneScaffoldDefaults$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ListDetailPaneScaffoldRole$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ListDetailPaneScaffoldRole$stableprop|#static{}androidx_compose_material3_adaptive_layout_ListDetailPaneScaffoldRole$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_MutableThreePaneScaffoldState$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_MutableThreePaneScaffoldState$stableprop|#static{}androidx_compose_material3_adaptive_layout_MutableThreePaneScaffoldState$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneAdaptedValue_Levitated$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneAdaptedValue_Levitated$stableprop|#static{}androidx_compose_material3_adaptive_layout_PaneAdaptedValue_Levitated$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneAdaptedValue_Reflowed$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneAdaptedValue_Reflowed$stableprop|#static{}androidx_compose_material3_adaptive_layout_PaneAdaptedValue_Reflowed$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneExpansionAnchor$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneExpansionAnchor$stableprop|#static{}androidx_compose_material3_adaptive_layout_PaneExpansionAnchor$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneExpansionAnchor_Offset$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneExpansionAnchor_Offset$stableprop|#static{}androidx_compose_material3_adaptive_layout_PaneExpansionAnchor_Offset$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneExpansionAnchor_Proportion$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneExpansionAnchor_Proportion$stableprop|#static{}androidx_compose_material3_adaptive_layout_PaneExpansionAnchor_Proportion$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneExpansionState$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneExpansionState$stableprop|#static{}androidx_compose_material3_adaptive_layout_PaneExpansionState$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneMotionData$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneMotionData$stableprop|#static{}androidx_compose_material3_adaptive_layout_PaneMotionData$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneMotionDefaults$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneMotionDefaults$stableprop|#static{}androidx_compose_material3_adaptive_layout_PaneMotionDefaults$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneScaffoldDirective$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneScaffoldDirective$stableprop|#static{}androidx_compose_material3_adaptive_layout_PaneScaffoldDirective$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_SupportingPaneScaffoldDefaults$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_SupportingPaneScaffoldDefaults$stableprop|#static{}androidx_compose_material3_adaptive_layout_SupportingPaneScaffoldDefaults$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_SupportingPaneScaffoldRole$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_SupportingPaneScaffoldRole$stableprop|#static{}androidx_compose_material3_adaptive_layout_SupportingPaneScaffoldRole$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneMotion$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneMotion$stableprop|#static{}androidx_compose_material3_adaptive_layout_ThreePaneMotion$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneScaffoldAdaptStrategies$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneScaffoldAdaptStrategies$stableprop|#static{}androidx_compose_material3_adaptive_layout_ThreePaneScaffoldAdaptStrategies$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneScaffoldDestinationItem$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneScaffoldDestinationItem$stableprop|#static{}androidx_compose_material3_adaptive_layout_ThreePaneScaffoldDestinationItem$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneScaffoldHorizontalOrder$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneScaffoldHorizontalOrder$stableprop|#static{}androidx_compose_material3_adaptive_layout_ThreePaneScaffoldHorizontalOrder$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneScaffoldOverrideScope$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneScaffoldOverrideScope$stableprop|#static{}androidx_compose_material3_adaptive_layout_ThreePaneScaffoldOverrideScope$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneScaffoldState$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneScaffoldState$stableprop|#static{}androidx_compose_material3_adaptive_layout_ThreePaneScaffoldState$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneScaffoldValue$stableprop // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneScaffoldValue$stableprop|#static{}androidx_compose_material3_adaptive_layout_ThreePaneScaffoldValue$stableprop[0]
|
||||||
|
|
||||||
|
final fun (androidx.compose.material3.adaptive.layout/PaneExpansionState).androidx.compose.material3.adaptive.layout/defaultDragHandleSemantics(androidx.compose.runtime/Composer?, kotlin/Int): kotlin/Function1<androidx.compose.ui.semantics/SemanticsPropertyReceiver, kotlin/Unit> // androidx.compose.material3.adaptive.layout/defaultDragHandleSemantics|defaultDragHandleSemantics@androidx.compose.material3.adaptive.layout.PaneExpansionState(androidx.compose.runtime.Composer?;kotlin.Int){}[0]
|
||||||
|
final fun <#A: androidx.compose.material3.adaptive.layout/PaneScaffoldRole, #B: androidx.compose.material3.adaptive.layout/PaneScaffoldValue<#A>> (androidx.compose.material3.adaptive.layout/ExtendedPaneScaffoldPaneScope<#A, #B>).androidx.compose.material3.adaptive.layout/AnimatedPane(androidx.compose.ui/Modifier?, androidx.compose.animation/EnterTransition?, androidx.compose.animation/ExitTransition?, androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.unit/IntRect>?, kotlin/Function3<androidx.compose.material3.adaptive.layout/AnimatedPaneScope, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // androidx.compose.material3.adaptive.layout/AnimatedPane|AnimatedPane@androidx.compose.material3.adaptive.layout.ExtendedPaneScaffoldPaneScope<0:0,0:1>(androidx.compose.ui.Modifier?;androidx.compose.animation.EnterTransition?;androidx.compose.animation.ExitTransition?;androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntRect>?;kotlin.Function3<androidx.compose.material3.adaptive.layout.AnimatedPaneScope,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){0§<androidx.compose.material3.adaptive.layout.PaneScaffoldRole>;1§<androidx.compose.material3.adaptive.layout.PaneScaffoldValue<0:0>>}[0]
|
||||||
|
final fun <#A: androidx.compose.material3.adaptive.layout/PaneScaffoldRole, #B: androidx.compose.material3.adaptive.layout/PaneScaffoldValue<#A>> (androidx.compose.material3.adaptive.layout/ExtendedPaneScaffoldPaneScope<#A, #B>).androidx.compose.material3.adaptive.layout/AnimatedPane(androidx.compose.ui/Modifier?, androidx.compose.animation/EnterTransition?, androidx.compose.animation/ExitTransition?, androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.unit/IntRect>?, kotlin/Function3<androidx.compose.material3.adaptive.layout/DragToResizeState, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>?, kotlin/Function3<androidx.compose.material3.adaptive.layout/AnimatedPaneScope, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // androidx.compose.material3.adaptive.layout/AnimatedPane|AnimatedPane@androidx.compose.material3.adaptive.layout.ExtendedPaneScaffoldPaneScope<0:0,0:1>(androidx.compose.ui.Modifier?;androidx.compose.animation.EnterTransition?;androidx.compose.animation.ExitTransition?;androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntRect>?;kotlin.Function3<androidx.compose.material3.adaptive.layout.DragToResizeState,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>?;kotlin.Function3<androidx.compose.material3.adaptive.layout.AnimatedPaneScope,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){0§<androidx.compose.material3.adaptive.layout.PaneScaffoldRole>;1§<androidx.compose.material3.adaptive.layout.PaneScaffoldValue<0:0>>}[0]
|
||||||
|
final fun <#A: androidx.compose.material3.adaptive.layout/PaneScaffoldRole> (androidx.compose.material3.adaptive.layout/PaneScaffoldMotionDataProvider<#A>).androidx.compose.material3.adaptive.layout/calculateDefaultEnterTransition(#A): androidx.compose.animation/EnterTransition // androidx.compose.material3.adaptive.layout/calculateDefaultEnterTransition|calculateDefaultEnterTransition@androidx.compose.material3.adaptive.layout.PaneScaffoldMotionDataProvider<0:0>(0:0){0§<androidx.compose.material3.adaptive.layout.PaneScaffoldRole>}[0]
|
||||||
|
final fun <#A: androidx.compose.material3.adaptive.layout/PaneScaffoldRole> (androidx.compose.material3.adaptive.layout/PaneScaffoldMotionDataProvider<#A>).androidx.compose.material3.adaptive.layout/calculateDefaultExitTransition(#A): androidx.compose.animation/ExitTransition // androidx.compose.material3.adaptive.layout/calculateDefaultExitTransition|calculateDefaultExitTransition@androidx.compose.material3.adaptive.layout.PaneScaffoldMotionDataProvider<0:0>(0:0){0§<androidx.compose.material3.adaptive.layout.PaneScaffoldRole>}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/LevitatedPaneScrim(androidx.compose.ui/Modifier?, kotlin/Function0<kotlin/Unit>?, androidx.compose.ui.graphics/Color, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // androidx.compose.material3.adaptive.layout/LevitatedPaneScrim|LevitatedPaneScrim(androidx.compose.ui.Modifier?;kotlin.Function0<kotlin.Unit>?;androidx.compose.ui.graphics.Color;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/ListDetailPaneScaffold(androidx.compose.material3.adaptive.layout/PaneScaffoldDirective, androidx.compose.material3.adaptive.layout/ThreePaneScaffoldState, kotlin/Function3<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldPaneScope, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>, kotlin/Function3<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldPaneScope, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>, androidx.compose.ui/Modifier?, kotlin/Function3<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldPaneScope, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>?, kotlin/Function4<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldScope, androidx.compose.material3.adaptive.layout/PaneExpansionState, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>?, androidx.compose.material3.adaptive.layout/PaneExpansionState?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // androidx.compose.material3.adaptive.layout/ListDetailPaneScaffold|ListDetailPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective;androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState;kotlin.Function3<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>;kotlin.Function3<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>;androidx.compose.ui.Modifier?;kotlin.Function3<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>?;kotlin.Function4<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,androidx.compose.material3.adaptive.layout.PaneExpansionState,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>?;androidx.compose.material3.adaptive.layout.PaneExpansionState?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/ListDetailPaneScaffold(androidx.compose.material3.adaptive.layout/PaneScaffoldDirective, androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue, kotlin/Function3<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldPaneScope, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>, kotlin/Function3<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldPaneScope, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>, androidx.compose.ui/Modifier?, kotlin/Function3<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldPaneScope, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>?, kotlin/Function4<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldScope, androidx.compose.material3.adaptive.layout/PaneExpansionState, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>?, androidx.compose.material3.adaptive.layout/PaneExpansionState?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // androidx.compose.material3.adaptive.layout/ListDetailPaneScaffold|ListDetailPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective;androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue;kotlin.Function3<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>;kotlin.Function3<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>;androidx.compose.ui.Modifier?;kotlin.Function3<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>?;kotlin.Function4<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,androidx.compose.material3.adaptive.layout.PaneExpansionState,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>?;androidx.compose.material3.adaptive.layout.PaneExpansionState?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/SupportingPaneScaffold(androidx.compose.material3.adaptive.layout/PaneScaffoldDirective, androidx.compose.material3.adaptive.layout/ThreePaneScaffoldState, kotlin/Function3<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldPaneScope, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>, kotlin/Function3<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldPaneScope, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>, androidx.compose.ui/Modifier?, kotlin/Function3<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldPaneScope, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>?, kotlin/Function4<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldScope, androidx.compose.material3.adaptive.layout/PaneExpansionState, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>?, androidx.compose.material3.adaptive.layout/PaneExpansionState?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // androidx.compose.material3.adaptive.layout/SupportingPaneScaffold|SupportingPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective;androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState;kotlin.Function3<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>;kotlin.Function3<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>;androidx.compose.ui.Modifier?;kotlin.Function3<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>?;kotlin.Function4<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,androidx.compose.material3.adaptive.layout.PaneExpansionState,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>?;androidx.compose.material3.adaptive.layout.PaneExpansionState?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/SupportingPaneScaffold(androidx.compose.material3.adaptive.layout/PaneScaffoldDirective, androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue, kotlin/Function3<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldPaneScope, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>, kotlin/Function3<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldPaneScope, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>, androidx.compose.ui/Modifier?, kotlin/Function3<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldPaneScope, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>?, kotlin/Function4<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldScope, androidx.compose.material3.adaptive.layout/PaneExpansionState, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>?, androidx.compose.material3.adaptive.layout/PaneExpansionState?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // androidx.compose.material3.adaptive.layout/SupportingPaneScaffold|SupportingPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective;androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue;kotlin.Function3<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>;kotlin.Function3<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>;androidx.compose.ui.Modifier?;kotlin.Function3<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>?;kotlin.Function4<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,androidx.compose.material3.adaptive.layout.PaneExpansionState,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>?;androidx.compose.material3.adaptive.layout.PaneExpansionState?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_AdaptStrategy_Levitate$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_AdaptStrategy_Levitate$stableprop_getter|androidx_compose_material3_adaptive_layout_AdaptStrategy_Levitate$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_AdaptStrategy_Reflow$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_AdaptStrategy_Reflow$stableprop_getter|androidx_compose_material3_adaptive_layout_AdaptStrategy_Reflow$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_AnimatedPaneOverrideScope$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_AnimatedPaneOverrideScope$stableprop_getter|androidx_compose_material3_adaptive_layout_AnimatedPaneOverrideScope$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_DragToResizeState$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_DragToResizeState$stableprop_getter|androidx_compose_material3_adaptive_layout_DragToResizeState$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_LevitatedPaneScrimDefaults$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_LevitatedPaneScrimDefaults$stableprop_getter|androidx_compose_material3_adaptive_layout_LevitatedPaneScrimDefaults$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ListDetailPaneScaffoldDefaults$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ListDetailPaneScaffoldDefaults$stableprop_getter|androidx_compose_material3_adaptive_layout_ListDetailPaneScaffoldDefaults$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ListDetailPaneScaffoldRole$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ListDetailPaneScaffoldRole$stableprop_getter|androidx_compose_material3_adaptive_layout_ListDetailPaneScaffoldRole$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_MutableThreePaneScaffoldState$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_MutableThreePaneScaffoldState$stableprop_getter|androidx_compose_material3_adaptive_layout_MutableThreePaneScaffoldState$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneAdaptedValue_Levitated$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneAdaptedValue_Levitated$stableprop_getter|androidx_compose_material3_adaptive_layout_PaneAdaptedValue_Levitated$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneAdaptedValue_Reflowed$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneAdaptedValue_Reflowed$stableprop_getter|androidx_compose_material3_adaptive_layout_PaneAdaptedValue_Reflowed$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneExpansionAnchor$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneExpansionAnchor$stableprop_getter|androidx_compose_material3_adaptive_layout_PaneExpansionAnchor$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneExpansionAnchor_Offset$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneExpansionAnchor_Offset$stableprop_getter|androidx_compose_material3_adaptive_layout_PaneExpansionAnchor_Offset$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneExpansionAnchor_Proportion$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneExpansionAnchor_Proportion$stableprop_getter|androidx_compose_material3_adaptive_layout_PaneExpansionAnchor_Proportion$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneExpansionState$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneExpansionState$stableprop_getter|androidx_compose_material3_adaptive_layout_PaneExpansionState$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneMotionData$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneMotionData$stableprop_getter|androidx_compose_material3_adaptive_layout_PaneMotionData$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneMotionDefaults$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneMotionDefaults$stableprop_getter|androidx_compose_material3_adaptive_layout_PaneMotionDefaults$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneScaffoldDirective$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_PaneScaffoldDirective$stableprop_getter|androidx_compose_material3_adaptive_layout_PaneScaffoldDirective$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_SupportingPaneScaffoldDefaults$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_SupportingPaneScaffoldDefaults$stableprop_getter|androidx_compose_material3_adaptive_layout_SupportingPaneScaffoldDefaults$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_SupportingPaneScaffoldRole$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_SupportingPaneScaffoldRole$stableprop_getter|androidx_compose_material3_adaptive_layout_SupportingPaneScaffoldRole$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneMotion$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneMotion$stableprop_getter|androidx_compose_material3_adaptive_layout_ThreePaneMotion$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneScaffoldAdaptStrategies$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneScaffoldAdaptStrategies$stableprop_getter|androidx_compose_material3_adaptive_layout_ThreePaneScaffoldAdaptStrategies$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneScaffoldDestinationItem$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneScaffoldDestinationItem$stableprop_getter|androidx_compose_material3_adaptive_layout_ThreePaneScaffoldDestinationItem$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneScaffoldHorizontalOrder$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneScaffoldHorizontalOrder$stableprop_getter|androidx_compose_material3_adaptive_layout_ThreePaneScaffoldHorizontalOrder$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneScaffoldOverrideScope$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneScaffoldOverrideScope$stableprop_getter|androidx_compose_material3_adaptive_layout_ThreePaneScaffoldOverrideScope$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneScaffoldState$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneScaffoldState$stableprop_getter|androidx_compose_material3_adaptive_layout_ThreePaneScaffoldState$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneScaffoldValue$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.layout/androidx_compose_material3_adaptive_layout_ThreePaneScaffoldValue$stableprop_getter|androidx_compose_material3_adaptive_layout_ThreePaneScaffoldValue$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/calculatePaneScaffoldDirective(androidx.compose.material3.adaptive/WindowAdaptiveInfo, androidx.compose.material3.adaptive.layout/HingePolicy = ...): androidx.compose.material3.adaptive.layout/PaneScaffoldDirective // androidx.compose.material3.adaptive.layout/calculatePaneScaffoldDirective|calculatePaneScaffoldDirective(androidx.compose.material3.adaptive.WindowAdaptiveInfo;androidx.compose.material3.adaptive.layout.HingePolicy){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/calculatePaneScaffoldDirectiveWithTwoPanesOnMediumWidth(androidx.compose.material3.adaptive/WindowAdaptiveInfo, androidx.compose.material3.adaptive.layout/HingePolicy = ...): androidx.compose.material3.adaptive.layout/PaneScaffoldDirective // androidx.compose.material3.adaptive.layout/calculatePaneScaffoldDirectiveWithTwoPanesOnMediumWidth|calculatePaneScaffoldDirectiveWithTwoPanesOnMediumWidth(androidx.compose.material3.adaptive.WindowAdaptiveInfo;androidx.compose.material3.adaptive.layout.HingePolicy){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/calculateThreePaneScaffoldValue(kotlin/Int, androidx.compose.material3.adaptive.layout/ThreePaneScaffoldAdaptStrategies, androidx.compose.material3.adaptive.layout/ThreePaneScaffoldDestinationItem<*>?, kotlin/Int = ...): androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue // androidx.compose.material3.adaptive.layout/calculateThreePaneScaffoldValue|calculateThreePaneScaffoldValue(kotlin.Int;androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies;androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<*>?;kotlin.Int){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/calculateThreePaneScaffoldValue(kotlin/Int, androidx.compose.material3.adaptive.layout/ThreePaneScaffoldAdaptStrategies, kotlin.collections/List<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldDestinationItem<*>>, kotlin/Int = ...): androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue // androidx.compose.material3.adaptive.layout/calculateThreePaneScaffoldValue|calculateThreePaneScaffoldValue(kotlin.Int;androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies;kotlin.collections.List<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<*>>;kotlin.Int){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/rememberDragToResizeState(androidx.compose.material3.adaptive.layout/DockedEdge, androidx.compose.ui.unit/Dp, androidx.compose.ui.unit/Dp, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int): androidx.compose.material3.adaptive.layout/DragToResizeState // androidx.compose.material3.adaptive.layout/rememberDragToResizeState|rememberDragToResizeState(androidx.compose.material3.adaptive.layout.DockedEdge;androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/rememberPaneExpansionState(androidx.compose.material3.adaptive.layout/PaneExpansionStateKey?, kotlin.collections/List<androidx.compose.material3.adaptive.layout/PaneExpansionAnchor>?, kotlin/Int, androidx.compose.animation.core/FiniteAnimationSpec<kotlin/Float>?, androidx.compose.foundation.gestures/FlingBehavior?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int): androidx.compose.material3.adaptive.layout/PaneExpansionState // androidx.compose.material3.adaptive.layout/rememberPaneExpansionState|rememberPaneExpansionState(androidx.compose.material3.adaptive.layout.PaneExpansionStateKey?;kotlin.collections.List<androidx.compose.material3.adaptive.layout.PaneExpansionAnchor>?;kotlin.Int;androidx.compose.animation.core.FiniteAnimationSpec<kotlin.Float>?;androidx.compose.foundation.gestures.FlingBehavior?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/rememberPaneExpansionState(androidx.compose.material3.adaptive.layout/PaneExpansionStateKey?, kotlin.collections/List<androidx.compose.material3.adaptive.layout/PaneExpansionAnchor>?, kotlin/Int, androidx.compose.animation.core/FiniteAnimationSpec<kotlin/Float>?, androidx.compose.foundation.gestures/FlingBehavior?, kotlin/Function1<kotlin/Float, kotlin/Float>?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int): androidx.compose.material3.adaptive.layout/PaneExpansionState // androidx.compose.material3.adaptive.layout/rememberPaneExpansionState|rememberPaneExpansionState(androidx.compose.material3.adaptive.layout.PaneExpansionStateKey?;kotlin.collections.List<androidx.compose.material3.adaptive.layout.PaneExpansionAnchor>?;kotlin.Int;androidx.compose.animation.core.FiniteAnimationSpec<kotlin.Float>?;androidx.compose.foundation.gestures.FlingBehavior?;kotlin.Function1<kotlin.Float,kotlin.Float>?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/rememberPaneExpansionState(androidx.compose.material3.adaptive.layout/PaneExpansionStateKeyProvider, kotlin.collections/List<androidx.compose.material3.adaptive.layout/PaneExpansionAnchor>?, kotlin/Int, androidx.compose.animation.core/FiniteAnimationSpec<kotlin/Float>?, androidx.compose.foundation.gestures/FlingBehavior?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int): androidx.compose.material3.adaptive.layout/PaneExpansionState // androidx.compose.material3.adaptive.layout/rememberPaneExpansionState|rememberPaneExpansionState(androidx.compose.material3.adaptive.layout.PaneExpansionStateKeyProvider;kotlin.collections.List<androidx.compose.material3.adaptive.layout.PaneExpansionAnchor>?;kotlin.Int;androidx.compose.animation.core.FiniteAnimationSpec<kotlin.Float>?;androidx.compose.foundation.gestures.FlingBehavior?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.layout/rememberPaneExpansionState(androidx.compose.material3.adaptive.layout/PaneExpansionStateKeyProvider, kotlin.collections/List<androidx.compose.material3.adaptive.layout/PaneExpansionAnchor>?, kotlin/Int, androidx.compose.animation.core/FiniteAnimationSpec<kotlin/Float>?, androidx.compose.foundation.gestures/FlingBehavior?, kotlin/Function1<kotlin/Float, kotlin/Float>?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int): androidx.compose.material3.adaptive.layout/PaneExpansionState // androidx.compose.material3.adaptive.layout/rememberPaneExpansionState|rememberPaneExpansionState(androidx.compose.material3.adaptive.layout.PaneExpansionStateKeyProvider;kotlin.collections.List<androidx.compose.material3.adaptive.layout.PaneExpansionAnchor>?;kotlin.Int;androidx.compose.animation.core.FiniteAnimationSpec<kotlin.Float>?;androidx.compose.foundation.gestures.FlingBehavior?;kotlin.Function1<kotlin.Float,kotlin.Float>?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0]
|
||||||
|
final inline fun <#A: androidx.compose.material3.adaptive.layout/PaneScaffoldRole> (androidx.compose.material3.adaptive.layout/PaneScaffoldMotionDataProvider<#A>).androidx.compose.material3.adaptive.layout/forEach(kotlin/Function2<#A, androidx.compose.material3.adaptive.layout/PaneMotionData, kotlin/Unit>) // androidx.compose.material3.adaptive.layout/forEach|forEach@androidx.compose.material3.adaptive.layout.PaneScaffoldMotionDataProvider<0:0>(kotlin.Function2<0:0,androidx.compose.material3.adaptive.layout.PaneMotionData,kotlin.Unit>){0§<androidx.compose.material3.adaptive.layout.PaneScaffoldRole>}[0]
|
||||||
|
final inline fun <#A: androidx.compose.material3.adaptive.layout/PaneScaffoldRole> (androidx.compose.material3.adaptive.layout/PaneScaffoldMotionDataProvider<#A>).androidx.compose.material3.adaptive.layout/forEachReversed(kotlin/Function2<#A, androidx.compose.material3.adaptive.layout/PaneMotionData, kotlin/Unit>) // androidx.compose.material3.adaptive.layout/forEachReversed|forEachReversed@androidx.compose.material3.adaptive.layout.PaneScaffoldMotionDataProvider<0:0>(kotlin.Function2<0:0,androidx.compose.material3.adaptive.layout.PaneMotionData,kotlin.Unit>){0§<androidx.compose.material3.adaptive.layout.PaneScaffoldRole>}[0]
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
// :adaptive-layout - androidx.compose.material3.adaptive.layout.* (ListDetailPaneScaffold,
|
||||||
|
// SupportingPaneScaffold, ThreePaneScaffold + pane motion / expansion machinery), vendored
|
||||||
|
// VERBATIM from JetBrains/compose-multiplatform-core into src/vendor/. See :adaptive for why
|
||||||
|
// upstream ships no linux / mingw artifact.
|
||||||
|
//
|
||||||
|
// Upstream's `skikoMain` carries the l10n translation tables (~75 files) plus the Strings and
|
||||||
|
// drag-handle actuals; for this port every native target is a skiko target, so it lands in
|
||||||
|
// src/vendor/native/ alongside upstream's own nativeMain actuals. The two sets actualise
|
||||||
|
// disjoint expects, so they coexist in one source set.
|
||||||
|
//
|
||||||
|
// Provenance = compose-fork.txt + scripts/compose-fork/compose.properties. Never hand-edit
|
||||||
|
// src/vendor - change the manifest + `python scripts/compose-fork/sync.py compose/material3/adaptive/adaptive-layout`.
|
||||||
|
plugins {
|
||||||
|
alias(libs.plugins.kotlin.multiplatform)
|
||||||
|
alias(libs.plugins.kotlin.plugin.compose)
|
||||||
|
}
|
||||||
|
|
||||||
|
val vHostSupportsMingw = rootProject.extra["vHostSupportsMingw"] as Boolean
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
linuxArm64(); linuxX64(); macosArm64(); if (vHostSupportsMingw) mingwX64()
|
||||||
|
applyDefaultHierarchyTemplate()
|
||||||
|
sourceSets {
|
||||||
|
commonMain {
|
||||||
|
dependencies {
|
||||||
|
api(project(":compose:material3:adaptive:adaptive"))
|
||||||
|
api(project(":compose:ui:ui"))
|
||||||
|
api(project(":compose:animation:animation-core"))
|
||||||
|
api(libs.androidx.collection)
|
||||||
|
implementation(project(":compose:animation:animation"))
|
||||||
|
implementation(project(":compose:foundation:foundation"))
|
||||||
|
implementation(project(":compose:foundation:foundation-layout"))
|
||||||
|
implementation(project(":compose:ui:ui-geometry"))
|
||||||
|
implementation(libs.androidx.window.core)
|
||||||
|
}
|
||||||
|
kotlin.srcDir("src/vendor/common/kotlin")
|
||||||
|
}
|
||||||
|
nativeMain {
|
||||||
|
kotlin.srcDir("src/vendor/native/kotlin")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compilerOptions {
|
||||||
|
freeCompilerArgs.addAll(
|
||||||
|
"-Xexpect-actual-classes",
|
||||||
|
"-opt-in=androidx.compose.ui.ExperimentalComposeUiApi",
|
||||||
|
"-opt-in=androidx.compose.ui.InternalComposeUiApi",
|
||||||
|
"-opt-in=androidx.compose.animation.ExperimentalAnimationApi",
|
||||||
|
"-opt-in=androidx.compose.animation.ExperimentalSharedTransitionApi",
|
||||||
|
"-opt-in=androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
SET_REPO=https://github.com/JetBrains/compose-multiplatform-core@<COMPOSE_CORE_REF>
|
||||||
|
SET_FOLDER=compose/material3/adaptive/adaptive-layout/src
|
||||||
|
|
||||||
|
commonMain/kotlin/ -> src/vendor/common/kotlin/
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/AdaptStrategy.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/AdaptStrategy.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/AnimateBoundsModifier.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/AnimateBoundsModifier.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/AnimateModifierUtils.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/AnimateModifierUtils.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/AnimateWithFadingModifier.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/AnimateWithFadingModifier.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/DragToResizeState.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/DragToResizeState.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/LevitatedPaneScrim.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/LevitatedPaneScrim.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/ListDetailPaneScaffold.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/ListDetailPaneScaffold.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/Pane.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/Pane.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneAdaptedValue.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/PaneAdaptedValue.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneExpansionDraggableModifier.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/PaneExpansionDraggableModifier.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneExpansionState.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/PaneExpansionState.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneMargins.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/PaneMargins.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneMotion.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/PaneMotion.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffold.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffold.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffoldDirective.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffoldDirective.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffoldHorizontalOrder.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffoldHorizontalOrder.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffoldRole.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffoldRole.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffoldValue.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffoldValue.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/PredictiveBackScaleState.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/PredictiveBackScaleState.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/SupportingPaneScaffold.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/SupportingPaneScaffold.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneMotion.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneMotion.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffold.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffold.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldAdaptStrategies.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldAdaptStrategies.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldDestinationItem.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldDestinationItem.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldHorizontalOrder.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldHorizontalOrder.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldScope.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldScope.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldState.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldState.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldValue.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldValue.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/WindowSizeClassHelper.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/WindowSizeClassHelper.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/internal/DelegableModifier.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/internal/DelegableModifier.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/internal/RememberUtils.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/internal/RememberUtils.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/internal/Strings.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/internal/Strings.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/layout/internal/System.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/layout/internal/System.kt
|
||||||
|
skikoMain/kotlin/ -> src/vendor/native/kotlin/
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Af.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Af.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Am.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Am.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Ar.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Ar.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/As.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/As.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Az.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Az.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Be.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Be.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Bg.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Bg.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Bn.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Bn.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Bs.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Bs.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Ca.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Ca.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Cs.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Cs.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Da.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Da.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/De.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/De.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/El.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/El.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/En.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/En.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Es.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Es.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Et.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Et.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Eu.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Eu.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Fa.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Fa.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Fi.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Fi.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Fr.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Fr.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Gl.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Gl.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Gu.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Gu.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Hi.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Hi.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Hr.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Hr.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Hu.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Hu.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Hy.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Hy.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/In.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/In.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Is.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Is.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/It.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/It.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Iw.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Iw.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Ja.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Ja.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Ka.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Ka.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Kk.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Kk.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Km.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Km.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Kn.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Kn.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Ko.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Ko.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Ky.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Ky.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Lo.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Lo.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Lt.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Lt.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Lv.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Lv.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Mk.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Mk.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Ml.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Ml.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Mn.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Mn.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Mr.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Mr.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Ms.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Ms.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/My.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/My.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Nb.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Nb.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Ne.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Ne.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Nl.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Nl.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Or.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Or.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Pa.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Pa.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Pl.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Pl.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Pt.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Pt.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Ro.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Ro.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Ru.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Ru.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Si.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Si.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Sk.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Sk.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Sl.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Sl.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Sq.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Sq.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Sr.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Sr.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Sv.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Sv.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Sw.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Sw.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Ta.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Ta.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Te.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Te.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Th.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Th.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Tl.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Tl.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Tr.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Tr.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Translations.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Translations.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Uk.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Uk.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Ur.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Ur.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Uz.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Uz.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Vi.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Vi.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Zh.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Zh.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/l10n/Zu.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/l10n/Zu.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/layout/PaneExpansionDragHandle.skiko.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/layout/PaneExpansionDragHandle.skiko.kt
|
||||||
|
# | skikoMain/kotlin/androidx/compose/material3/adaptive/layout/internal/Strings.skiko.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/layout/internal/Strings.skiko.kt
|
||||||
|
nativeMain/kotlin/ -> src/vendor/native/kotlin/
|
||||||
|
# | nativeMain/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffold.native.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffold.native.kt
|
||||||
|
# | nativeMain/kotlin/androidx/compose/material3/adaptive/layout/internal/System.native.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/layout/internal/System.native.kt
|
||||||
|
|
||||||
|
# >>> ---- DIAGNOSTIC GAPS ---- <<<<
|
||||||
|
# androidMain (2)
|
||||||
|
# | androidMain/kotlin/androidx/compose/material3/adaptive/layout/PaneExpansionDraggableModifier.android.kt -> src/vendor/android/kotlin/androidx/compose/material3/adaptive/layout/PaneExpansionDraggableModifier.android.kt
|
||||||
|
# | androidMain/kotlin/androidx/compose/material3/adaptive/layout/internal/Strings.android.kt -> src/vendor/android/kotlin/androidx/compose/material3/adaptive/layout/internal/Strings.android.kt
|
||||||
|
# jsMain (2)
|
||||||
|
# | jsMain/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffold.js.kt -> src/vendor/js/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffold.js.kt
|
||||||
|
# | jsMain/kotlin/androidx/compose/material3/adaptive/layout/internal/System.js.kt -> src/vendor/js/kotlin/androidx/compose/material3/adaptive/layout/internal/System.js.kt
|
||||||
|
# jvmAndAndroidMain (2)
|
||||||
|
# | jvmAndAndroidMain/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffold.jvmAndAndroid.kt -> src/vendor/jvmAndAndroid/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffold.jvmAndAndroid.kt
|
||||||
|
# | jvmAndAndroidMain/kotlin/androidx/compose/material3/adaptive/layout/internal/System.jvmAndAndroid.kt -> src/vendor/jvmAndAndroid/kotlin/androidx/compose/material3/adaptive/layout/internal/System.jvmAndAndroid.kt
|
||||||
|
# wasmJsMain (2)
|
||||||
|
# | wasmJsMain/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffold.wasm.kt -> src/vendor/wasmJs/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffold.wasm.kt
|
||||||
|
# | wasmJsMain/kotlin/androidx/compose/material3/adaptive/layout/internal/System.wasm.kt -> src/vendor/wasmJs/kotlin/androidx/compose/material3/adaptive/layout/internal/System.wasm.kt
|
||||||
|
# <<< ---- DIAGNOSTIC GAPS ---- >>>>
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
// Klib ABI Dump
|
||||||
|
// Targets: [linuxArm64, linuxX64, macosArm64, mingwX64]
|
||||||
|
// Rendering settings:
|
||||||
|
// - Signature version: 2
|
||||||
|
// - Show manifest properties: true
|
||||||
|
// - Show declarations: true
|
||||||
|
|
||||||
|
// Library unique name: <com.bitsycore.compose.material3.adaptive:adaptive-navigation>
|
||||||
|
abstract interface <#A: kotlin/Any?> androidx.compose.material3.adaptive.navigation/ThreePaneScaffoldNavigator { // androidx.compose.material3.adaptive.navigation/ThreePaneScaffoldNavigator|null[0]
|
||||||
|
abstract val currentDestination // androidx.compose.material3.adaptive.navigation/ThreePaneScaffoldNavigator.currentDestination|{}currentDestination[0]
|
||||||
|
abstract fun <get-currentDestination>(): androidx.compose.material3.adaptive.layout/ThreePaneScaffoldDestinationItem<#A>? // androidx.compose.material3.adaptive.navigation/ThreePaneScaffoldNavigator.currentDestination.<get-currentDestination>|<get-currentDestination>(){}[0]
|
||||||
|
abstract val scaffoldDirective // androidx.compose.material3.adaptive.navigation/ThreePaneScaffoldNavigator.scaffoldDirective|{}scaffoldDirective[0]
|
||||||
|
abstract fun <get-scaffoldDirective>(): androidx.compose.material3.adaptive.layout/PaneScaffoldDirective // androidx.compose.material3.adaptive.navigation/ThreePaneScaffoldNavigator.scaffoldDirective.<get-scaffoldDirective>|<get-scaffoldDirective>(){}[0]
|
||||||
|
abstract val scaffoldState // androidx.compose.material3.adaptive.navigation/ThreePaneScaffoldNavigator.scaffoldState|{}scaffoldState[0]
|
||||||
|
abstract fun <get-scaffoldState>(): androidx.compose.material3.adaptive.layout/ThreePaneScaffoldState // androidx.compose.material3.adaptive.navigation/ThreePaneScaffoldNavigator.scaffoldState.<get-scaffoldState>|<get-scaffoldState>(){}[0]
|
||||||
|
abstract val scaffoldValue // androidx.compose.material3.adaptive.navigation/ThreePaneScaffoldNavigator.scaffoldValue|{}scaffoldValue[0]
|
||||||
|
abstract fun <get-scaffoldValue>(): androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue // androidx.compose.material3.adaptive.navigation/ThreePaneScaffoldNavigator.scaffoldValue.<get-scaffoldValue>|<get-scaffoldValue>(){}[0]
|
||||||
|
|
||||||
|
abstract var isDestinationHistoryAware // androidx.compose.material3.adaptive.navigation/ThreePaneScaffoldNavigator.isDestinationHistoryAware|{}isDestinationHistoryAware[0]
|
||||||
|
abstract fun <get-isDestinationHistoryAware>(): kotlin/Boolean // androidx.compose.material3.adaptive.navigation/ThreePaneScaffoldNavigator.isDestinationHistoryAware.<get-isDestinationHistoryAware>|<get-isDestinationHistoryAware>(){}[0]
|
||||||
|
abstract fun <set-isDestinationHistoryAware>(kotlin/Boolean) // androidx.compose.material3.adaptive.navigation/ThreePaneScaffoldNavigator.isDestinationHistoryAware.<set-isDestinationHistoryAware>|<set-isDestinationHistoryAware>(kotlin.Boolean){}[0]
|
||||||
|
|
||||||
|
abstract fun canNavigateBack(androidx.compose.material3.adaptive.navigation/BackNavigationBehavior = ...): kotlin/Boolean // androidx.compose.material3.adaptive.navigation/ThreePaneScaffoldNavigator.canNavigateBack|canNavigateBack(androidx.compose.material3.adaptive.navigation.BackNavigationBehavior){}[0]
|
||||||
|
abstract fun peekPreviousScaffoldValue(androidx.compose.material3.adaptive.navigation/BackNavigationBehavior = ...): androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue // androidx.compose.material3.adaptive.navigation/ThreePaneScaffoldNavigator.peekPreviousScaffoldValue|peekPreviousScaffoldValue(androidx.compose.material3.adaptive.navigation.BackNavigationBehavior){}[0]
|
||||||
|
abstract suspend fun navigateBack(androidx.compose.material3.adaptive.navigation/BackNavigationBehavior = ...): kotlin/Boolean // androidx.compose.material3.adaptive.navigation/ThreePaneScaffoldNavigator.navigateBack|navigateBack(androidx.compose.material3.adaptive.navigation.BackNavigationBehavior){}[0]
|
||||||
|
abstract suspend fun navigateTo(androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole, #A? = ...) // androidx.compose.material3.adaptive.navigation/ThreePaneScaffoldNavigator.navigateTo|navigateTo(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole;1:0?){}[0]
|
||||||
|
abstract suspend fun seekBack(androidx.compose.material3.adaptive.navigation/BackNavigationBehavior = ..., kotlin/Float = ...) // androidx.compose.material3.adaptive.navigation/ThreePaneScaffoldNavigator.seekBack|seekBack(androidx.compose.material3.adaptive.navigation.BackNavigationBehavior;kotlin.Float){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final value class androidx.compose.material3.adaptive.navigation/BackNavigationBehavior { // androidx.compose.material3.adaptive.navigation/BackNavigationBehavior|null[0]
|
||||||
|
final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.material3.adaptive.navigation/BackNavigationBehavior.equals|equals(kotlin.Any?){}[0]
|
||||||
|
final fun hashCode(): kotlin/Int // androidx.compose.material3.adaptive.navigation/BackNavigationBehavior.hashCode|hashCode(){}[0]
|
||||||
|
final fun toString(): kotlin/String // androidx.compose.material3.adaptive.navigation/BackNavigationBehavior.toString|toString(){}[0]
|
||||||
|
|
||||||
|
final object Companion { // androidx.compose.material3.adaptive.navigation/BackNavigationBehavior.Companion|null[0]
|
||||||
|
final val PopLatest // androidx.compose.material3.adaptive.navigation/BackNavigationBehavior.Companion.PopLatest|{}PopLatest[0]
|
||||||
|
final fun <get-PopLatest>(): androidx.compose.material3.adaptive.navigation/BackNavigationBehavior // androidx.compose.material3.adaptive.navigation/BackNavigationBehavior.Companion.PopLatest.<get-PopLatest>|<get-PopLatest>(){}[0]
|
||||||
|
final val PopUntilContentChange // androidx.compose.material3.adaptive.navigation/BackNavigationBehavior.Companion.PopUntilContentChange|{}PopUntilContentChange[0]
|
||||||
|
final fun <get-PopUntilContentChange>(): androidx.compose.material3.adaptive.navigation/BackNavigationBehavior // androidx.compose.material3.adaptive.navigation/BackNavigationBehavior.Companion.PopUntilContentChange.<get-PopUntilContentChange>|<get-PopUntilContentChange>(){}[0]
|
||||||
|
final val PopUntilCurrentDestinationChange // androidx.compose.material3.adaptive.navigation/BackNavigationBehavior.Companion.PopUntilCurrentDestinationChange|{}PopUntilCurrentDestinationChange[0]
|
||||||
|
final fun <get-PopUntilCurrentDestinationChange>(): androidx.compose.material3.adaptive.navigation/BackNavigationBehavior // androidx.compose.material3.adaptive.navigation/BackNavigationBehavior.Companion.PopUntilCurrentDestinationChange.<get-PopUntilCurrentDestinationChange>|<get-PopUntilCurrentDestinationChange>(){}[0]
|
||||||
|
final val PopUntilScaffoldValueChange // androidx.compose.material3.adaptive.navigation/BackNavigationBehavior.Companion.PopUntilScaffoldValueChange|{}PopUntilScaffoldValueChange[0]
|
||||||
|
final fun <get-PopUntilScaffoldValueChange>(): androidx.compose.material3.adaptive.navigation/BackNavigationBehavior // androidx.compose.material3.adaptive.navigation/BackNavigationBehavior.Companion.PopUntilScaffoldValueChange.<get-PopUntilScaffoldValueChange>|<get-PopUntilScaffoldValueChange>(){}[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final fun <#A: kotlin/Any?> androidx.compose.material3.adaptive.navigation/rememberListDetailPaneScaffoldNavigator(androidx.compose.material3.adaptive.layout/PaneScaffoldDirective?, androidx.compose.material3.adaptive.layout/ThreePaneScaffoldAdaptStrategies?, kotlin/Boolean, kotlin.collections/List<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldDestinationItem<#A>>?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int): androidx.compose.material3.adaptive.navigation/ThreePaneScaffoldNavigator<#A> // androidx.compose.material3.adaptive.navigation/rememberListDetailPaneScaffoldNavigator|rememberListDetailPaneScaffoldNavigator(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective?;androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies?;kotlin.Boolean;kotlin.collections.List<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<0:0>>?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){0§<kotlin.Any?>}[0]
|
||||||
|
final fun <#A: kotlin/Any?> androidx.compose.material3.adaptive.navigation/rememberSupportingPaneScaffoldNavigator(androidx.compose.material3.adaptive.layout/PaneScaffoldDirective?, androidx.compose.material3.adaptive.layout/ThreePaneScaffoldAdaptStrategies?, kotlin/Boolean, kotlin.collections/List<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldDestinationItem<#A>>?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int): androidx.compose.material3.adaptive.navigation/ThreePaneScaffoldNavigator<#A> // androidx.compose.material3.adaptive.navigation/rememberSupportingPaneScaffoldNavigator|rememberSupportingPaneScaffoldNavigator(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective?;androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies?;kotlin.Boolean;kotlin.collections.List<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<0:0>>?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){0§<kotlin.Any?>}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.navigation/rememberListDetailPaneScaffoldNavigator(androidx.compose.material3.adaptive.layout/PaneScaffoldDirective?, androidx.compose.material3.adaptive.layout/ThreePaneScaffoldAdaptStrategies?, kotlin/Boolean, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int): androidx.compose.material3.adaptive.navigation/ThreePaneScaffoldNavigator<kotlin/Any> // androidx.compose.material3.adaptive.navigation/rememberListDetailPaneScaffoldNavigator|rememberListDetailPaneScaffoldNavigator(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective?;androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies?;kotlin.Boolean;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.navigation/rememberSupportingPaneScaffoldNavigator(androidx.compose.material3.adaptive.layout/PaneScaffoldDirective?, androidx.compose.material3.adaptive.layout/ThreePaneScaffoldAdaptStrategies?, kotlin/Boolean, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int): androidx.compose.material3.adaptive.navigation/ThreePaneScaffoldNavigator<kotlin/Any> // androidx.compose.material3.adaptive.navigation/rememberSupportingPaneScaffoldNavigator|rememberSupportingPaneScaffoldNavigator(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective?;androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies?;kotlin.Boolean;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0]
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
// :adaptive-navigation - androidx.compose.material3.adaptive.navigation.*
|
||||||
|
// (ThreePaneScaffoldNavigator + back-navigation behaviour), vendored VERBATIM from
|
||||||
|
// JetBrains/compose-multiplatform-core into src/vendor/. See :adaptive for why upstream
|
||||||
|
// ships no linux / mingw artifact. commonMain only - upstream's platform legs are
|
||||||
|
// android-specific.
|
||||||
|
//
|
||||||
|
// Provenance = compose-fork.txt + scripts/compose-fork/compose.properties. Never hand-edit
|
||||||
|
// src/vendor - change the manifest + `python scripts/compose-fork/sync.py compose/material3/adaptive/adaptive-navigation`.
|
||||||
|
plugins {
|
||||||
|
alias(libs.plugins.kotlin.multiplatform)
|
||||||
|
alias(libs.plugins.kotlin.plugin.compose)
|
||||||
|
}
|
||||||
|
|
||||||
|
val vHostSupportsMingw = rootProject.extra["vHostSupportsMingw"] as Boolean
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
linuxArm64(); linuxX64(); macosArm64(); if (vHostSupportsMingw) mingwX64()
|
||||||
|
applyDefaultHierarchyTemplate()
|
||||||
|
sourceSets {
|
||||||
|
commonMain {
|
||||||
|
dependencies {
|
||||||
|
api(project(":compose:material3:adaptive:adaptive-layout"))
|
||||||
|
implementation(project(":compose:foundation:foundation"))
|
||||||
|
implementation(project(":compose:ui:ui-util"))
|
||||||
|
}
|
||||||
|
kotlin.srcDir("src/vendor/common/kotlin")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compilerOptions {
|
||||||
|
freeCompilerArgs.addAll(
|
||||||
|
"-Xexpect-actual-classes",
|
||||||
|
"-opt-in=androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
SET_REPO=https://github.com/JetBrains/compose-multiplatform-core@<COMPOSE_CORE_REF>
|
||||||
|
SET_FOLDER=compose/material3/adaptive/adaptive-navigation/src
|
||||||
|
|
||||||
|
commonMain/kotlin/ -> src/vendor/common/kotlin/
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/navigation/BackNavigationBehavior.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/navigation/BackNavigationBehavior.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/navigation/ThreePaneScaffoldNavigator.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/navigation/ThreePaneScaffoldNavigator.kt
|
||||||
|
|
||||||
|
# >>> ---- DIAGNOSTIC GAPS ---- <<<<
|
||||||
|
# androidMain (2)
|
||||||
|
# | androidMain/kotlin/androidx/compose/material3/adaptive/navigation/AndroidThreePaneScaffold.android.kt -> src/vendor/android/kotlin/androidx/compose/material3/adaptive/navigation/AndroidThreePaneScaffold.android.kt
|
||||||
|
# | androidMain/kotlin/androidx/compose/material3/adaptive/navigation/ThreePaneScaffoldPredictiveBackHandler.android.kt -> src/vendor/android/kotlin/androidx/compose/material3/adaptive/navigation/ThreePaneScaffoldPredictiveBackHandler.android.kt
|
||||||
|
# <<< ---- DIAGNOSTIC GAPS ---- >>>>
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
// Klib ABI Dump
|
||||||
|
// Targets: [linuxArm64, linuxX64, macosArm64, mingwX64]
|
||||||
|
// Rendering settings:
|
||||||
|
// - Signature version: 2
|
||||||
|
// - Show manifest properties: true
|
||||||
|
// - Show declarations: true
|
||||||
|
|
||||||
|
// Library unique name: <com.bitsycore.compose.material3.adaptive:adaptive-navigation3>
|
||||||
|
sealed interface androidx.compose.material3.adaptive.navigation3/ListDetailSceneScope { // androidx.compose.material3.adaptive.navigation3/ListDetailSceneScope|null[0]
|
||||||
|
abstract val scaffoldTransitionScope // androidx.compose.material3.adaptive.navigation3/ListDetailSceneScope.scaffoldTransitionScope|{}scaffoldTransitionScope[0]
|
||||||
|
abstract fun <get-scaffoldTransitionScope>(): androidx.compose.material3.adaptive.layout/PaneScaffoldTransitionScope<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole, androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue> // androidx.compose.material3.adaptive.navigation3/ListDetailSceneScope.scaffoldTransitionScope.<get-scaffoldTransitionScope>|<get-scaffoldTransitionScope>(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed interface androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneScope { // androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneScope|null[0]
|
||||||
|
abstract val scaffoldTransitionScope // androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneScope.scaffoldTransitionScope|{}scaffoldTransitionScope[0]
|
||||||
|
abstract fun <get-scaffoldTransitionScope>(): androidx.compose.material3.adaptive.layout/PaneScaffoldTransitionScope<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldRole, androidx.compose.material3.adaptive.layout/ThreePaneScaffoldValue> // androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneScope.scaffoldTransitionScope.<get-scaffoldTransitionScope>|<get-scaffoldTransitionScope>(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final class <#A: kotlin/Any> androidx.compose.material3.adaptive.navigation3/ListDetailSceneStrategy : androidx.navigation3.scene/SceneStrategy<#A> { // androidx.compose.material3.adaptive.navigation3/ListDetailSceneStrategy|null[0]
|
||||||
|
constructor <init>(kotlin/Boolean, androidx.compose.material3.adaptive.navigation/BackNavigationBehavior, androidx.compose.material3.adaptive.layout/PaneScaffoldDirective, androidx.compose.material3.adaptive.layout/ThreePaneScaffoldAdaptStrategies, kotlin/Function4<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldScope, androidx.compose.material3.adaptive.layout/PaneExpansionState, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>?, androidx.compose.material3.adaptive.layout/PaneExpansionState?) // androidx.compose.material3.adaptive.navigation3/ListDetailSceneStrategy.<init>|<init>(kotlin.Boolean;androidx.compose.material3.adaptive.navigation.BackNavigationBehavior;androidx.compose.material3.adaptive.layout.PaneScaffoldDirective;androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies;kotlin.Function4<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,androidx.compose.material3.adaptive.layout.PaneExpansionState,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>?;androidx.compose.material3.adaptive.layout.PaneExpansionState?){}[0]
|
||||||
|
|
||||||
|
final val adaptStrategies // androidx.compose.material3.adaptive.navigation3/ListDetailSceneStrategy.adaptStrategies|{}adaptStrategies[0]
|
||||||
|
final fun <get-adaptStrategies>(): androidx.compose.material3.adaptive.layout/ThreePaneScaffoldAdaptStrategies // androidx.compose.material3.adaptive.navigation3/ListDetailSceneStrategy.adaptStrategies.<get-adaptStrategies>|<get-adaptStrategies>(){}[0]
|
||||||
|
final val backNavigationBehavior // androidx.compose.material3.adaptive.navigation3/ListDetailSceneStrategy.backNavigationBehavior|{}backNavigationBehavior[0]
|
||||||
|
final fun <get-backNavigationBehavior>(): androidx.compose.material3.adaptive.navigation/BackNavigationBehavior // androidx.compose.material3.adaptive.navigation3/ListDetailSceneStrategy.backNavigationBehavior.<get-backNavigationBehavior>|<get-backNavigationBehavior>(){}[0]
|
||||||
|
final val directive // androidx.compose.material3.adaptive.navigation3/ListDetailSceneStrategy.directive|{}directive[0]
|
||||||
|
final fun <get-directive>(): androidx.compose.material3.adaptive.layout/PaneScaffoldDirective // androidx.compose.material3.adaptive.navigation3/ListDetailSceneStrategy.directive.<get-directive>|<get-directive>(){}[0]
|
||||||
|
final val paneExpansionDragHandle // androidx.compose.material3.adaptive.navigation3/ListDetailSceneStrategy.paneExpansionDragHandle|{}paneExpansionDragHandle[0]
|
||||||
|
final fun <get-paneExpansionDragHandle>(): kotlin/Function4<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldScope, androidx.compose.material3.adaptive.layout/PaneExpansionState, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>? // androidx.compose.material3.adaptive.navigation3/ListDetailSceneStrategy.paneExpansionDragHandle.<get-paneExpansionDragHandle>|<get-paneExpansionDragHandle>(){}[0]
|
||||||
|
final val paneExpansionState // androidx.compose.material3.adaptive.navigation3/ListDetailSceneStrategy.paneExpansionState|{}paneExpansionState[0]
|
||||||
|
final fun <get-paneExpansionState>(): androidx.compose.material3.adaptive.layout/PaneExpansionState? // androidx.compose.material3.adaptive.navigation3/ListDetailSceneStrategy.paneExpansionState.<get-paneExpansionState>|<get-paneExpansionState>(){}[0]
|
||||||
|
final val shouldHandleSinglePaneLayout // androidx.compose.material3.adaptive.navigation3/ListDetailSceneStrategy.shouldHandleSinglePaneLayout|{}shouldHandleSinglePaneLayout[0]
|
||||||
|
final fun <get-shouldHandleSinglePaneLayout>(): kotlin/Boolean // androidx.compose.material3.adaptive.navigation3/ListDetailSceneStrategy.shouldHandleSinglePaneLayout.<get-shouldHandleSinglePaneLayout>|<get-shouldHandleSinglePaneLayout>(){}[0]
|
||||||
|
|
||||||
|
final fun (androidx.navigation3.scene/SceneStrategyScope<#A>).calculateScene(kotlin.collections/List<androidx.navigation3.runtime/NavEntry<#A>>): androidx.navigation3.scene/Scene<#A>? // androidx.compose.material3.adaptive.navigation3/ListDetailSceneStrategy.calculateScene|calculateScene@androidx.navigation3.scene.SceneStrategyScope<1:0>(kotlin.collections.List<androidx.navigation3.runtime.NavEntry<1:0>>){}[0]
|
||||||
|
|
||||||
|
final object Companion { // androidx.compose.material3.adaptive.navigation3/ListDetailSceneStrategy.Companion|null[0]
|
||||||
|
final fun detailPane(kotlin/Any = ...): kotlin.collections/Map<kotlin/String, kotlin/Any> // androidx.compose.material3.adaptive.navigation3/ListDetailSceneStrategy.Companion.detailPane|detailPane(kotlin.Any){}[0]
|
||||||
|
final fun extraPane(kotlin/Any = ...): kotlin.collections/Map<kotlin/String, kotlin/Any> // androidx.compose.material3.adaptive.navigation3/ListDetailSceneStrategy.Companion.extraPane|extraPane(kotlin.Any){}[0]
|
||||||
|
final fun listPane(kotlin/Any = ..., kotlin/Function3<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldScope, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit> = ...): kotlin.collections/Map<kotlin/String, kotlin/Any> // androidx.compose.material3.adaptive.navigation3/ListDetailSceneStrategy.Companion.listPane|listPane(kotlin.Any;kotlin.Function3<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>){}[0]
|
||||||
|
final fun paneAnimation(androidx.compose.animation/EnterTransition? = ..., androidx.compose.animation/ExitTransition? = ..., androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.unit/IntRect>? = ...): kotlin.collections/Map<kotlin/String, kotlin/Any> // androidx.compose.material3.adaptive.navigation3/ListDetailSceneStrategy.Companion.paneAnimation|paneAnimation(androidx.compose.animation.EnterTransition?;androidx.compose.animation.ExitTransition?;androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntRect>?){}[0]
|
||||||
|
final fun preferredPaneSize(androidx.compose.ui.unit/Dp = ..., androidx.compose.ui.unit/Dp = ...): kotlin.collections/Map<kotlin/String, kotlin/Any> // androidx.compose.material3.adaptive.navigation3/ListDetailSceneStrategy.Companion.preferredPaneSize|preferredPaneSize(androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp){}[0]
|
||||||
|
final fun preferredPaneSize(kotlin/Float = ..., kotlin/Float = ...): kotlin.collections/Map<kotlin/String, kotlin/Any> // androidx.compose.material3.adaptive.navigation3/ListDetailSceneStrategy.Companion.preferredPaneSize|preferredPaneSize(kotlin.Float;kotlin.Float){}[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class <#A: kotlin/Any> androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneStrategy : androidx.navigation3.scene/SceneStrategy<#A> { // androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneStrategy|null[0]
|
||||||
|
constructor <init>(kotlin/Boolean, androidx.compose.material3.adaptive.navigation/BackNavigationBehavior, androidx.compose.material3.adaptive.layout/PaneScaffoldDirective, androidx.compose.material3.adaptive.layout/ThreePaneScaffoldAdaptStrategies, kotlin/Function4<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldScope, androidx.compose.material3.adaptive.layout/PaneExpansionState, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>?, androidx.compose.material3.adaptive.layout/PaneExpansionState?) // androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneStrategy.<init>|<init>(kotlin.Boolean;androidx.compose.material3.adaptive.navigation.BackNavigationBehavior;androidx.compose.material3.adaptive.layout.PaneScaffoldDirective;androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies;kotlin.Function4<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,androidx.compose.material3.adaptive.layout.PaneExpansionState,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>?;androidx.compose.material3.adaptive.layout.PaneExpansionState?){}[0]
|
||||||
|
|
||||||
|
final val adaptStrategies // androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneStrategy.adaptStrategies|{}adaptStrategies[0]
|
||||||
|
final fun <get-adaptStrategies>(): androidx.compose.material3.adaptive.layout/ThreePaneScaffoldAdaptStrategies // androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneStrategy.adaptStrategies.<get-adaptStrategies>|<get-adaptStrategies>(){}[0]
|
||||||
|
final val backNavigationBehavior // androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneStrategy.backNavigationBehavior|{}backNavigationBehavior[0]
|
||||||
|
final fun <get-backNavigationBehavior>(): androidx.compose.material3.adaptive.navigation/BackNavigationBehavior // androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneStrategy.backNavigationBehavior.<get-backNavigationBehavior>|<get-backNavigationBehavior>(){}[0]
|
||||||
|
final val directive // androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneStrategy.directive|{}directive[0]
|
||||||
|
final fun <get-directive>(): androidx.compose.material3.adaptive.layout/PaneScaffoldDirective // androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneStrategy.directive.<get-directive>|<get-directive>(){}[0]
|
||||||
|
final val paneExpansionDragHandle // androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneStrategy.paneExpansionDragHandle|{}paneExpansionDragHandle[0]
|
||||||
|
final fun <get-paneExpansionDragHandle>(): kotlin/Function4<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldScope, androidx.compose.material3.adaptive.layout/PaneExpansionState, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>? // androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneStrategy.paneExpansionDragHandle.<get-paneExpansionDragHandle>|<get-paneExpansionDragHandle>(){}[0]
|
||||||
|
final val paneExpansionState // androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneStrategy.paneExpansionState|{}paneExpansionState[0]
|
||||||
|
final fun <get-paneExpansionState>(): androidx.compose.material3.adaptive.layout/PaneExpansionState? // androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneStrategy.paneExpansionState.<get-paneExpansionState>|<get-paneExpansionState>(){}[0]
|
||||||
|
final val shouldHandleSinglePaneLayout // androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneStrategy.shouldHandleSinglePaneLayout|{}shouldHandleSinglePaneLayout[0]
|
||||||
|
final fun <get-shouldHandleSinglePaneLayout>(): kotlin/Boolean // androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneStrategy.shouldHandleSinglePaneLayout.<get-shouldHandleSinglePaneLayout>|<get-shouldHandleSinglePaneLayout>(){}[0]
|
||||||
|
|
||||||
|
final fun (androidx.navigation3.scene/SceneStrategyScope<#A>).calculateScene(kotlin.collections/List<androidx.navigation3.runtime/NavEntry<#A>>): androidx.navigation3.scene/Scene<#A>? // androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneStrategy.calculateScene|calculateScene@androidx.navigation3.scene.SceneStrategyScope<1:0>(kotlin.collections.List<androidx.navigation3.runtime.NavEntry<1:0>>){}[0]
|
||||||
|
|
||||||
|
final object Companion { // androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneStrategy.Companion|null[0]
|
||||||
|
final fun extraPane(kotlin/Any = ...): kotlin.collections/Map<kotlin/String, kotlin/Any> // androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneStrategy.Companion.extraPane|extraPane(kotlin.Any){}[0]
|
||||||
|
final fun mainPane(kotlin/Any = ...): kotlin.collections/Map<kotlin/String, kotlin/Any> // androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneStrategy.Companion.mainPane|mainPane(kotlin.Any){}[0]
|
||||||
|
final fun paneAnimation(androidx.compose.animation/EnterTransition? = ..., androidx.compose.animation/ExitTransition? = ..., androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.unit/IntRect>? = ...): kotlin.collections/Map<kotlin/String, kotlin/Any> // androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneStrategy.Companion.paneAnimation|paneAnimation(androidx.compose.animation.EnterTransition?;androidx.compose.animation.ExitTransition?;androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntRect>?){}[0]
|
||||||
|
final fun preferredPaneSize(androidx.compose.ui.unit/Dp = ..., androidx.compose.ui.unit/Dp = ...): kotlin.collections/Map<kotlin/String, kotlin/Any> // androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneStrategy.Companion.preferredPaneSize|preferredPaneSize(androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp){}[0]
|
||||||
|
final fun preferredPaneSize(kotlin/Float = ..., kotlin/Float = ...): kotlin.collections/Map<kotlin/String, kotlin/Any> // androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneStrategy.Companion.preferredPaneSize|preferredPaneSize(kotlin.Float;kotlin.Float){}[0]
|
||||||
|
final fun supportingPane(kotlin/Any = ...): kotlin.collections/Map<kotlin/String, kotlin/Any> // androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneStrategy.Companion.supportingPane|supportingPane(kotlin.Any){}[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final val androidx.compose.material3.adaptive.navigation3/LocalListDetailSceneScope // androidx.compose.material3.adaptive.navigation3/LocalListDetailSceneScope|{}LocalListDetailSceneScope[0]
|
||||||
|
final fun <get-LocalListDetailSceneScope>(): androidx.compose.runtime/ProvidableCompositionLocal<androidx.compose.material3.adaptive.navigation3/ListDetailSceneScope?> // androidx.compose.material3.adaptive.navigation3/LocalListDetailSceneScope.<get-LocalListDetailSceneScope>|<get-LocalListDetailSceneScope>(){}[0]
|
||||||
|
final val androidx.compose.material3.adaptive.navigation3/LocalSupportingPaneSceneScope // androidx.compose.material3.adaptive.navigation3/LocalSupportingPaneSceneScope|{}LocalSupportingPaneSceneScope[0]
|
||||||
|
final fun <get-LocalSupportingPaneSceneScope>(): androidx.compose.runtime/ProvidableCompositionLocal<androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneScope?> // androidx.compose.material3.adaptive.navigation3/LocalSupportingPaneSceneScope.<get-LocalSupportingPaneSceneScope>|<get-LocalSupportingPaneSceneScope>(){}[0]
|
||||||
|
final val androidx.compose.material3.adaptive.navigation3/androidx_compose_material3_adaptive_navigation3_ListDetailSceneStrategy$stableprop // androidx.compose.material3.adaptive.navigation3/androidx_compose_material3_adaptive_navigation3_ListDetailSceneStrategy$stableprop|#static{}androidx_compose_material3_adaptive_navigation3_ListDetailSceneStrategy$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.navigation3/androidx_compose_material3_adaptive_navigation3_SupportingPaneSceneStrategy$stableprop // androidx.compose.material3.adaptive.navigation3/androidx_compose_material3_adaptive_navigation3_SupportingPaneSceneStrategy$stableprop|#static{}androidx_compose_material3_adaptive_navigation3_SupportingPaneSceneStrategy$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.navigation3/androidx_compose_material3_adaptive_navigation3_ThreePaneScaffoldScene_OnBackResult$stableprop // androidx.compose.material3.adaptive.navigation3/androidx_compose_material3_adaptive_navigation3_ThreePaneScaffoldScene_OnBackResult$stableprop|#static{}androidx_compose_material3_adaptive_navigation3_ThreePaneScaffoldScene_OnBackResult$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.navigation3/androidx_compose_material3_adaptive_navigation3_ThreePaneScaffoldType_ListDetail$stableprop // androidx.compose.material3.adaptive.navigation3/androidx_compose_material3_adaptive_navigation3_ThreePaneScaffoldType_ListDetail$stableprop|#static{}androidx_compose_material3_adaptive_navigation3_ThreePaneScaffoldType_ListDetail$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive.navigation3/androidx_compose_material3_adaptive_navigation3_ThreePaneScaffoldType_SupportingPane$stableprop // androidx.compose.material3.adaptive.navigation3/androidx_compose_material3_adaptive_navigation3_ThreePaneScaffoldType_SupportingPane$stableprop|#static{}androidx_compose_material3_adaptive_navigation3_ThreePaneScaffoldType_SupportingPane$stableprop[0]
|
||||||
|
|
||||||
|
final fun <#A: kotlin/Any> androidx.compose.material3.adaptive.navigation3/rememberListDetailSceneStrategy(kotlin/Boolean, androidx.compose.material3.adaptive.navigation/BackNavigationBehavior, androidx.compose.material3.adaptive.layout/PaneScaffoldDirective, androidx.compose.material3.adaptive.layout/ThreePaneScaffoldAdaptStrategies, kotlin/Function4<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldScope, androidx.compose.material3.adaptive.layout/PaneExpansionState, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>?, androidx.compose.material3.adaptive.layout/PaneExpansionState?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int): androidx.compose.material3.adaptive.navigation3/ListDetailSceneStrategy<#A> // androidx.compose.material3.adaptive.navigation3/rememberListDetailSceneStrategy|rememberListDetailSceneStrategy(kotlin.Boolean;androidx.compose.material3.adaptive.navigation.BackNavigationBehavior;androidx.compose.material3.adaptive.layout.PaneScaffoldDirective;androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies;kotlin.Function4<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,androidx.compose.material3.adaptive.layout.PaneExpansionState,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>?;androidx.compose.material3.adaptive.layout.PaneExpansionState?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){0§<kotlin.Any>}[0]
|
||||||
|
final fun <#A: kotlin/Any> androidx.compose.material3.adaptive.navigation3/rememberListDetailSceneStrategy(kotlin/Boolean, androidx.compose.material3.adaptive.navigation/BackNavigationBehavior?, androidx.compose.material3.adaptive.layout/PaneScaffoldDirective?, androidx.compose.material3.adaptive.layout/ThreePaneScaffoldAdaptStrategies?, kotlin/Function4<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldScope, androidx.compose.material3.adaptive.layout/PaneExpansionState, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>?, androidx.compose.material3.adaptive.layout/PaneExpansionState?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int): androidx.compose.material3.adaptive.navigation3/ListDetailSceneStrategy<#A> // androidx.compose.material3.adaptive.navigation3/rememberListDetailSceneStrategy|rememberListDetailSceneStrategy(kotlin.Boolean;androidx.compose.material3.adaptive.navigation.BackNavigationBehavior?;androidx.compose.material3.adaptive.layout.PaneScaffoldDirective?;androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies?;kotlin.Function4<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,androidx.compose.material3.adaptive.layout.PaneExpansionState,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>?;androidx.compose.material3.adaptive.layout.PaneExpansionState?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){0§<kotlin.Any>}[0]
|
||||||
|
final fun <#A: kotlin/Any> androidx.compose.material3.adaptive.navigation3/rememberSupportingPaneSceneStrategy(kotlin/Boolean, androidx.compose.material3.adaptive.navigation/BackNavigationBehavior, androidx.compose.material3.adaptive.layout/PaneScaffoldDirective, androidx.compose.material3.adaptive.layout/ThreePaneScaffoldAdaptStrategies, kotlin/Function4<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldScope, androidx.compose.material3.adaptive.layout/PaneExpansionState, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>?, androidx.compose.material3.adaptive.layout/PaneExpansionState?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int): androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneStrategy<#A> // androidx.compose.material3.adaptive.navigation3/rememberSupportingPaneSceneStrategy|rememberSupportingPaneSceneStrategy(kotlin.Boolean;androidx.compose.material3.adaptive.navigation.BackNavigationBehavior;androidx.compose.material3.adaptive.layout.PaneScaffoldDirective;androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies;kotlin.Function4<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,androidx.compose.material3.adaptive.layout.PaneExpansionState,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>?;androidx.compose.material3.adaptive.layout.PaneExpansionState?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){0§<kotlin.Any>}[0]
|
||||||
|
final fun <#A: kotlin/Any> androidx.compose.material3.adaptive.navigation3/rememberSupportingPaneSceneStrategy(kotlin/Boolean, androidx.compose.material3.adaptive.navigation/BackNavigationBehavior?, androidx.compose.material3.adaptive.layout/PaneScaffoldDirective?, androidx.compose.material3.adaptive.layout/ThreePaneScaffoldAdaptStrategies?, kotlin/Function4<androidx.compose.material3.adaptive.layout/ThreePaneScaffoldScope, androidx.compose.material3.adaptive.layout/PaneExpansionState, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>?, androidx.compose.material3.adaptive.layout/PaneExpansionState?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int): androidx.compose.material3.adaptive.navigation3/SupportingPaneSceneStrategy<#A> // androidx.compose.material3.adaptive.navigation3/rememberSupportingPaneSceneStrategy|rememberSupportingPaneSceneStrategy(kotlin.Boolean;androidx.compose.material3.adaptive.navigation.BackNavigationBehavior?;androidx.compose.material3.adaptive.layout.PaneScaffoldDirective?;androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies?;kotlin.Function4<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,androidx.compose.material3.adaptive.layout.PaneExpansionState,androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>?;androidx.compose.material3.adaptive.layout.PaneExpansionState?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){0§<kotlin.Any>}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.navigation3/androidx_compose_material3_adaptive_navigation3_ListDetailSceneStrategy$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.navigation3/androidx_compose_material3_adaptive_navigation3_ListDetailSceneStrategy$stableprop_getter|androidx_compose_material3_adaptive_navigation3_ListDetailSceneStrategy$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.navigation3/androidx_compose_material3_adaptive_navigation3_SupportingPaneSceneStrategy$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.navigation3/androidx_compose_material3_adaptive_navigation3_SupportingPaneSceneStrategy$stableprop_getter|androidx_compose_material3_adaptive_navigation3_SupportingPaneSceneStrategy$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.navigation3/androidx_compose_material3_adaptive_navigation3_ThreePaneScaffoldScene_OnBackResult$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.navigation3/androidx_compose_material3_adaptive_navigation3_ThreePaneScaffoldScene_OnBackResult$stableprop_getter|androidx_compose_material3_adaptive_navigation3_ThreePaneScaffoldScene_OnBackResult$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.navigation3/androidx_compose_material3_adaptive_navigation3_ThreePaneScaffoldType_ListDetail$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.navigation3/androidx_compose_material3_adaptive_navigation3_ThreePaneScaffoldType_ListDetail$stableprop_getter|androidx_compose_material3_adaptive_navigation3_ThreePaneScaffoldType_ListDetail$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive.navigation3/androidx_compose_material3_adaptive_navigation3_ThreePaneScaffoldType_SupportingPane$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive.navigation3/androidx_compose_material3_adaptive_navigation3_ThreePaneScaffoldType_SupportingPane$stableprop_getter|androidx_compose_material3_adaptive_navigation3_ThreePaneScaffoldType_SupportingPane$stableprop_getter(){}[0]
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
// :adaptive-navigation3 - androidx.compose.material3.adaptive.navigation3.*
|
||||||
|
// (ListDetail / SupportingPane SceneStrategy for Navigation 3), vendored VERBATIM from
|
||||||
|
// JetBrains/compose-multiplatform-core into src/vendor/. See :adaptive for why upstream
|
||||||
|
// ships no linux / mingw artifact. commonMain only.
|
||||||
|
//
|
||||||
|
// navigation3-ui is the PROJECT module: upstream's org.jetbrains.androidx.navigation3:
|
||||||
|
// navigation3-ui has no K/N desktop artifact either, which is why :navigation3:navigation3-ui
|
||||||
|
// exists. navigationevent-compose is a plain Maven dep (api-exposed by :ui).
|
||||||
|
//
|
||||||
|
// Provenance = compose-fork.txt + scripts/compose-fork/compose.properties. Never hand-edit
|
||||||
|
// src/vendor - change the manifest + `python scripts/compose-fork/sync.py compose/material3/adaptive/adaptive-navigation3`.
|
||||||
|
plugins {
|
||||||
|
alias(libs.plugins.kotlin.multiplatform)
|
||||||
|
alias(libs.plugins.kotlin.plugin.compose)
|
||||||
|
}
|
||||||
|
|
||||||
|
val vHostSupportsMingw = rootProject.extra["vHostSupportsMingw"] as Boolean
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
linuxArm64(); linuxX64(); macosArm64(); if (vHostSupportsMingw) mingwX64()
|
||||||
|
applyDefaultHierarchyTemplate()
|
||||||
|
sourceSets {
|
||||||
|
commonMain {
|
||||||
|
dependencies {
|
||||||
|
api(project(":compose:material3:adaptive:adaptive-navigation"))
|
||||||
|
api(project(":navigation3:navigation3-ui"))
|
||||||
|
implementation(libs.androidx.collection)
|
||||||
|
implementation(libs.androidx.navigationevent.compose)
|
||||||
|
}
|
||||||
|
kotlin.srcDir("src/vendor/common/kotlin")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compilerOptions {
|
||||||
|
freeCompilerArgs.addAll(
|
||||||
|
"-Xexpect-actual-classes",
|
||||||
|
"-opt-in=androidx.compose.ui.ExperimentalComposeUiApi",
|
||||||
|
"-opt-in=androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
SET_REPO=https://github.com/JetBrains/compose-multiplatform-core@<COMPOSE_CORE_REF>
|
||||||
|
SET_FOLDER=compose/material3/adaptive/adaptive-navigation3/src
|
||||||
|
|
||||||
|
commonMain/kotlin/ -> src/vendor/common/kotlin/
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/navigation3/ListDetailSceneScope.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/navigation3/ListDetailSceneScope.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/navigation3/ListDetailSceneStrategy.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/navigation3/ListDetailSceneStrategy.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/navigation3/SupportingPaneSceneScope.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/navigation3/SupportingPaneSceneScope.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/navigation3/SupportingPaneSceneStrategy.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/navigation3/SupportingPaneSceneStrategy.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/navigation3/ThreePaneScaffoldScene.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/navigation3/ThreePaneScaffoldScene.kt
|
||||||
|
|
||||||
|
# >>> ---- DIAGNOSTIC GAPS ---- <<<<
|
||||||
|
# (none - every source set under SET_FOLDER is vendored)
|
||||||
|
# <<< ---- DIAGNOSTIC GAPS ---- >>>>
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
// Klib ABI Dump
|
||||||
|
// Targets: [linuxArm64, linuxX64, macosArm64, mingwX64]
|
||||||
|
// Rendering settings:
|
||||||
|
// - Signature version: 2
|
||||||
|
// - Show manifest properties: true
|
||||||
|
// - Show declarations: true
|
||||||
|
|
||||||
|
// Library unique name: <com.bitsycore.compose.material3.adaptive:adaptive>
|
||||||
|
open annotation class androidx.compose.material3.adaptive/ExperimentalMaterial3AdaptiveApi : kotlin/Annotation { // androidx.compose.material3.adaptive/ExperimentalMaterial3AdaptiveApi|null[0]
|
||||||
|
constructor <init>() // androidx.compose.material3.adaptive/ExperimentalMaterial3AdaptiveApi.<init>|<init>(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
open annotation class androidx.compose.material3.adaptive/ExperimentalMaterial3AdaptiveComponentOverrideApi : kotlin/Annotation { // androidx.compose.material3.adaptive/ExperimentalMaterial3AdaptiveComponentOverrideApi|null[0]
|
||||||
|
constructor <init>() // androidx.compose.material3.adaptive/ExperimentalMaterial3AdaptiveComponentOverrideApi.<init>|<init>(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final class androidx.compose.material3.adaptive/HingeInfo { // androidx.compose.material3.adaptive/HingeInfo|null[0]
|
||||||
|
constructor <init>(androidx.compose.ui.geometry/Rect, kotlin/Boolean, kotlin/Boolean, kotlin/Boolean, kotlin/Boolean) // androidx.compose.material3.adaptive/HingeInfo.<init>|<init>(androidx.compose.ui.geometry.Rect;kotlin.Boolean;kotlin.Boolean;kotlin.Boolean;kotlin.Boolean){}[0]
|
||||||
|
|
||||||
|
final val bounds // androidx.compose.material3.adaptive/HingeInfo.bounds|{}bounds[0]
|
||||||
|
final fun <get-bounds>(): androidx.compose.ui.geometry/Rect // androidx.compose.material3.adaptive/HingeInfo.bounds.<get-bounds>|<get-bounds>(){}[0]
|
||||||
|
final val isFlat // androidx.compose.material3.adaptive/HingeInfo.isFlat|{}isFlat[0]
|
||||||
|
final fun <get-isFlat>(): kotlin/Boolean // androidx.compose.material3.adaptive/HingeInfo.isFlat.<get-isFlat>|<get-isFlat>(){}[0]
|
||||||
|
final val isOccluding // androidx.compose.material3.adaptive/HingeInfo.isOccluding|{}isOccluding[0]
|
||||||
|
final fun <get-isOccluding>(): kotlin/Boolean // androidx.compose.material3.adaptive/HingeInfo.isOccluding.<get-isOccluding>|<get-isOccluding>(){}[0]
|
||||||
|
final val isSeparating // androidx.compose.material3.adaptive/HingeInfo.isSeparating|{}isSeparating[0]
|
||||||
|
final fun <get-isSeparating>(): kotlin/Boolean // androidx.compose.material3.adaptive/HingeInfo.isSeparating.<get-isSeparating>|<get-isSeparating>(){}[0]
|
||||||
|
final val isVertical // androidx.compose.material3.adaptive/HingeInfo.isVertical|{}isVertical[0]
|
||||||
|
final fun <get-isVertical>(): kotlin/Boolean // androidx.compose.material3.adaptive/HingeInfo.isVertical.<get-isVertical>|<get-isVertical>(){}[0]
|
||||||
|
|
||||||
|
final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.material3.adaptive/HingeInfo.equals|equals(kotlin.Any?){}[0]
|
||||||
|
final fun hashCode(): kotlin/Int // androidx.compose.material3.adaptive/HingeInfo.hashCode|hashCode(){}[0]
|
||||||
|
final fun toString(): kotlin/String // androidx.compose.material3.adaptive/HingeInfo.toString|toString(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final class androidx.compose.material3.adaptive/Posture { // androidx.compose.material3.adaptive/Posture|null[0]
|
||||||
|
constructor <init>(kotlin/Boolean = ..., kotlin.collections/List<androidx.compose.material3.adaptive/HingeInfo> = ...) // androidx.compose.material3.adaptive/Posture.<init>|<init>(kotlin.Boolean;kotlin.collections.List<androidx.compose.material3.adaptive.HingeInfo>){}[0]
|
||||||
|
|
||||||
|
final val hingeList // androidx.compose.material3.adaptive/Posture.hingeList|{}hingeList[0]
|
||||||
|
final fun <get-hingeList>(): kotlin.collections/List<androidx.compose.material3.adaptive/HingeInfo> // androidx.compose.material3.adaptive/Posture.hingeList.<get-hingeList>|<get-hingeList>(){}[0]
|
||||||
|
final val isTabletop // androidx.compose.material3.adaptive/Posture.isTabletop|{}isTabletop[0]
|
||||||
|
final fun <get-isTabletop>(): kotlin/Boolean // androidx.compose.material3.adaptive/Posture.isTabletop.<get-isTabletop>|<get-isTabletop>(){}[0]
|
||||||
|
|
||||||
|
final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.material3.adaptive/Posture.equals|equals(kotlin.Any?){}[0]
|
||||||
|
final fun hashCode(): kotlin/Int // androidx.compose.material3.adaptive/Posture.hashCode|hashCode(){}[0]
|
||||||
|
final fun toString(): kotlin/String // androidx.compose.material3.adaptive/Posture.toString|toString(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final class androidx.compose.material3.adaptive/WindowAdaptiveInfo { // androidx.compose.material3.adaptive/WindowAdaptiveInfo|null[0]
|
||||||
|
constructor <init>(androidx.window.core.layout/WindowSizeClass, androidx.compose.material3.adaptive/Posture) // androidx.compose.material3.adaptive/WindowAdaptiveInfo.<init>|<init>(androidx.window.core.layout.WindowSizeClass;androidx.compose.material3.adaptive.Posture){}[0]
|
||||||
|
|
||||||
|
final val windowPosture // androidx.compose.material3.adaptive/WindowAdaptiveInfo.windowPosture|{}windowPosture[0]
|
||||||
|
final fun <get-windowPosture>(): androidx.compose.material3.adaptive/Posture // androidx.compose.material3.adaptive/WindowAdaptiveInfo.windowPosture.<get-windowPosture>|<get-windowPosture>(){}[0]
|
||||||
|
final val windowSizeClass // androidx.compose.material3.adaptive/WindowAdaptiveInfo.windowSizeClass|{}windowSizeClass[0]
|
||||||
|
final fun <get-windowSizeClass>(): androidx.window.core.layout/WindowSizeClass // androidx.compose.material3.adaptive/WindowAdaptiveInfo.windowSizeClass.<get-windowSizeClass>|<get-windowSizeClass>(){}[0]
|
||||||
|
|
||||||
|
final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.material3.adaptive/WindowAdaptiveInfo.equals|equals(kotlin.Any?){}[0]
|
||||||
|
final fun hashCode(): kotlin/Int // androidx.compose.material3.adaptive/WindowAdaptiveInfo.hashCode|hashCode(){}[0]
|
||||||
|
final fun toString(): kotlin/String // androidx.compose.material3.adaptive/WindowAdaptiveInfo.toString|toString(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final val androidx.compose.material3.adaptive/allHorizontalHingeBounds // androidx.compose.material3.adaptive/allHorizontalHingeBounds|@androidx.compose.material3.adaptive.Posture{}allHorizontalHingeBounds[0]
|
||||||
|
final fun (androidx.compose.material3.adaptive/Posture).<get-allHorizontalHingeBounds>(): kotlin.collections/List<androidx.compose.ui.geometry/Rect> // androidx.compose.material3.adaptive/allHorizontalHingeBounds.<get-allHorizontalHingeBounds>|<get-allHorizontalHingeBounds>@androidx.compose.material3.adaptive.Posture(){}[0]
|
||||||
|
final val androidx.compose.material3.adaptive/allVerticalHingeBounds // androidx.compose.material3.adaptive/allVerticalHingeBounds|@androidx.compose.material3.adaptive.Posture{}allVerticalHingeBounds[0]
|
||||||
|
final fun (androidx.compose.material3.adaptive/Posture).<get-allVerticalHingeBounds>(): kotlin.collections/List<androidx.compose.ui.geometry/Rect> // androidx.compose.material3.adaptive/allVerticalHingeBounds.<get-allVerticalHingeBounds>|<get-allVerticalHingeBounds>@androidx.compose.material3.adaptive.Posture(){}[0]
|
||||||
|
final val androidx.compose.material3.adaptive/androidx_compose_material3_adaptive_HingeInfo$stableprop // androidx.compose.material3.adaptive/androidx_compose_material3_adaptive_HingeInfo$stableprop|#static{}androidx_compose_material3_adaptive_HingeInfo$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive/androidx_compose_material3_adaptive_Posture$stableprop // androidx.compose.material3.adaptive/androidx_compose_material3_adaptive_Posture$stableprop|#static{}androidx_compose_material3_adaptive_Posture$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive/androidx_compose_material3_adaptive_WindowAdaptiveInfo$stableprop // androidx.compose.material3.adaptive/androidx_compose_material3_adaptive_WindowAdaptiveInfo$stableprop|#static{}androidx_compose_material3_adaptive_WindowAdaptiveInfo$stableprop[0]
|
||||||
|
final val androidx.compose.material3.adaptive/occludingHorizontalHingeBounds // androidx.compose.material3.adaptive/occludingHorizontalHingeBounds|@androidx.compose.material3.adaptive.Posture{}occludingHorizontalHingeBounds[0]
|
||||||
|
final fun (androidx.compose.material3.adaptive/Posture).<get-occludingHorizontalHingeBounds>(): kotlin.collections/List<androidx.compose.ui.geometry/Rect> // androidx.compose.material3.adaptive/occludingHorizontalHingeBounds.<get-occludingHorizontalHingeBounds>|<get-occludingHorizontalHingeBounds>@androidx.compose.material3.adaptive.Posture(){}[0]
|
||||||
|
final val androidx.compose.material3.adaptive/occludingVerticalHingeBounds // androidx.compose.material3.adaptive/occludingVerticalHingeBounds|@androidx.compose.material3.adaptive.Posture{}occludingVerticalHingeBounds[0]
|
||||||
|
final fun (androidx.compose.material3.adaptive/Posture).<get-occludingVerticalHingeBounds>(): kotlin.collections/List<androidx.compose.ui.geometry/Rect> // androidx.compose.material3.adaptive/occludingVerticalHingeBounds.<get-occludingVerticalHingeBounds>|<get-occludingVerticalHingeBounds>@androidx.compose.material3.adaptive.Posture(){}[0]
|
||||||
|
final val androidx.compose.material3.adaptive/separatingHorizontalHingeBounds // androidx.compose.material3.adaptive/separatingHorizontalHingeBounds|@androidx.compose.material3.adaptive.Posture{}separatingHorizontalHingeBounds[0]
|
||||||
|
final fun (androidx.compose.material3.adaptive/Posture).<get-separatingHorizontalHingeBounds>(): kotlin.collections/List<androidx.compose.ui.geometry/Rect> // androidx.compose.material3.adaptive/separatingHorizontalHingeBounds.<get-separatingHorizontalHingeBounds>|<get-separatingHorizontalHingeBounds>@androidx.compose.material3.adaptive.Posture(){}[0]
|
||||||
|
final val androidx.compose.material3.adaptive/separatingVerticalHingeBounds // androidx.compose.material3.adaptive/separatingVerticalHingeBounds|@androidx.compose.material3.adaptive.Posture{}separatingVerticalHingeBounds[0]
|
||||||
|
final fun (androidx.compose.material3.adaptive/Posture).<get-separatingVerticalHingeBounds>(): kotlin.collections/List<androidx.compose.ui.geometry/Rect> // androidx.compose.material3.adaptive/separatingVerticalHingeBounds.<get-separatingVerticalHingeBounds>|<get-separatingVerticalHingeBounds>@androidx.compose.material3.adaptive.Posture(){}[0]
|
||||||
|
|
||||||
|
final fun androidx.compose.material3.adaptive/androidx_compose_material3_adaptive_HingeInfo$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive/androidx_compose_material3_adaptive_HingeInfo$stableprop_getter|androidx_compose_material3_adaptive_HingeInfo$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive/androidx_compose_material3_adaptive_Posture$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive/androidx_compose_material3_adaptive_Posture$stableprop_getter|androidx_compose_material3_adaptive_Posture$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive/androidx_compose_material3_adaptive_WindowAdaptiveInfo$stableprop_getter(): kotlin/Int // androidx.compose.material3.adaptive/androidx_compose_material3_adaptive_WindowAdaptiveInfo$stableprop_getter|androidx_compose_material3_adaptive_WindowAdaptiveInfo$stableprop_getter(){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive/currentWindowAdaptiveInfo(androidx.compose.runtime/Composer?, kotlin/Int): androidx.compose.material3.adaptive/WindowAdaptiveInfo // androidx.compose.material3.adaptive/currentWindowAdaptiveInfo|currentWindowAdaptiveInfo(androidx.compose.runtime.Composer?;kotlin.Int){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive/currentWindowAdaptiveInfo(kotlin/Boolean, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int): androidx.compose.material3.adaptive/WindowAdaptiveInfo // androidx.compose.material3.adaptive/currentWindowAdaptiveInfo|currentWindowAdaptiveInfo(kotlin.Boolean;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive/currentWindowAdaptiveInfoV2(androidx.compose.runtime/Composer?, kotlin/Int): androidx.compose.material3.adaptive/WindowAdaptiveInfo // androidx.compose.material3.adaptive/currentWindowAdaptiveInfoV2|currentWindowAdaptiveInfoV2(androidx.compose.runtime.Composer?;kotlin.Int){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive/currentWindowDpSize(androidx.compose.runtime/Composer?, kotlin/Int): androidx.compose.ui.unit/DpSize // androidx.compose.material3.adaptive/currentWindowDpSize|currentWindowDpSize(androidx.compose.runtime.Composer?;kotlin.Int){}[0]
|
||||||
|
final fun androidx.compose.material3.adaptive/currentWindowSize(androidx.compose.runtime/Composer?, kotlin/Int): androidx.compose.ui.unit/IntSize // androidx.compose.material3.adaptive/currentWindowSize|currentWindowSize(androidx.compose.runtime.Composer?;kotlin.Int){}[0]
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
// :adaptive - androidx.compose.material3.adaptive.* (WindowAdaptiveInfo / Posture /
|
||||||
|
// window size class helpers), vendored VERBATIM from JetBrains/compose-multiplatform-core
|
||||||
|
// (compose/material3/adaptive/adaptive) into src/vendor/.
|
||||||
|
//
|
||||||
|
// Upstream org.jetbrains.compose.material3.adaptive:* publishes only ios / macosArm64 -
|
||||||
|
// no linux, no mingw (github.com/bitsycore/compose-desktop-native/issues/4). Nothing in
|
||||||
|
// the sources blocks those targets: the whole port is vendor-only, every actual the
|
||||||
|
// native targets need already exists upstream, and the one real dependency
|
||||||
|
// (androidx.window:window-core) ALREADY publishes linux + mingw + macos. The artifacts
|
||||||
|
// are missing purely because upstream did not enable the targets.
|
||||||
|
//
|
||||||
|
// Upstream's `nonAndroidMain` lands in src/vendor/native/ - for this port native IS the
|
||||||
|
// only non-android leg, same treatment coil's nonAndroid sets get.
|
||||||
|
//
|
||||||
|
// Provenance = compose-fork.txt + scripts/compose-fork/compose.properties. Never hand-edit
|
||||||
|
// src/vendor - change the manifest + `python scripts/compose-fork/sync.py compose/material3/adaptive/adaptive`.
|
||||||
|
plugins {
|
||||||
|
alias(libs.plugins.kotlin.multiplatform)
|
||||||
|
alias(libs.plugins.kotlin.plugin.compose)
|
||||||
|
}
|
||||||
|
|
||||||
|
val vHostSupportsMingw = rootProject.extra["vHostSupportsMingw"] as Boolean
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
linuxArm64(); linuxX64(); macosArm64(); if (vHostSupportsMingw) mingwX64()
|
||||||
|
applyDefaultHierarchyTemplate()
|
||||||
|
sourceSets {
|
||||||
|
commonMain {
|
||||||
|
dependencies {
|
||||||
|
api(project(":compose:ui:ui"))
|
||||||
|
api(libs.androidx.window.core)
|
||||||
|
implementation(project(":compose:foundation:foundation"))
|
||||||
|
}
|
||||||
|
kotlin.srcDir("src/vendor/common/kotlin")
|
||||||
|
}
|
||||||
|
nativeMain {
|
||||||
|
kotlin.srcDir("src/vendor/native/kotlin")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compilerOptions {
|
||||||
|
freeCompilerArgs.addAll(
|
||||||
|
"-Xexpect-actual-classes",
|
||||||
|
"-opt-in=androidx.compose.ui.ExperimentalComposeUiApi",
|
||||||
|
"-opt-in=androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
SET_REPO=https://github.com/JetBrains/compose-multiplatform-core@<COMPOSE_CORE_REF>
|
||||||
|
SET_FOLDER=compose/material3/adaptive/adaptive/src
|
||||||
|
|
||||||
|
commonMain/kotlin/ -> src/vendor/common/kotlin/
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/ExperimentalMaterial3AdaptiveApi.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/ExperimentalMaterial3AdaptiveApi.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/ExperimentalMaterial3AdaptiveComponentOverrideApi.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/ExperimentalMaterial3AdaptiveComponentOverrideApi.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/Posture.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/Posture.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/WindowAdaptiveInfo.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/WindowAdaptiveInfo.kt
|
||||||
|
# | commonMain/kotlin/androidx/compose/material3/adaptive/WindowSizeClassHelper.kt -> src/vendor/common/kotlin/androidx/compose/material3/adaptive/WindowSizeClassHelper.kt
|
||||||
|
nonAndroidMain/kotlin/ -> src/vendor/native/kotlin/
|
||||||
|
# | nonAndroidMain/kotlin/androidx/compose/material3/adaptive/WindowAdaptiveInfo.nonAndroid.kt -> src/vendor/native/kotlin/androidx/compose/material3/adaptive/WindowAdaptiveInfo.nonAndroid.kt
|
||||||
|
|
||||||
|
# >>> ---- DIAGNOSTIC GAPS ---- <<<<
|
||||||
|
# androidMain (2)
|
||||||
|
# | androidMain/kotlin/androidx/compose/material3/adaptive/AndroidPosture.android.kt -> src/vendor/android/kotlin/androidx/compose/material3/adaptive/AndroidPosture.android.kt
|
||||||
|
# | androidMain/kotlin/androidx/compose/material3/adaptive/AndroidWindowAdaptiveInfo.android.kt -> src/vendor/android/kotlin/androidx/compose/material3/adaptive/AndroidWindowAdaptiveInfo.android.kt
|
||||||
|
# <<< ---- DIAGNOSTIC GAPS ---- >>>>
|
||||||
@@ -341,18 +341,10 @@ abstract interface com.compose.sdl.graphics/NativeFinishableCanvas { // com.comp
|
|||||||
abstract fun finish() // com.compose.sdl.graphics/NativeFinishableCanvas.finish|finish(){}[0]
|
abstract fun finish() // com.compose.sdl.graphics/NativeFinishableCanvas.finish|finish(){}[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract interface com.compose.sdl.graphics/NativePainterCanvas { // com.compose.sdl.graphics/NativePainterCanvas|null[0]
|
|
||||||
abstract fun drawNativePainter(kotlin/String, com.compose.sdl.res/ResourceKind, kotlin/Float, kotlin/Float, kotlin/Float, kotlin/Float, kotlin/Float) // com.compose.sdl.graphics/NativePainterCanvas.drawNativePainter|drawNativePainter(kotlin.String;com.compose.sdl.res.ResourceKind;kotlin.Float;kotlin.Float;kotlin.Float;kotlin.Float;kotlin.Float){}[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract interface com.compose.sdl.graphics/NativeShadowCanvas { // com.compose.sdl.graphics/NativeShadowCanvas|null[0]
|
abstract interface com.compose.sdl.graphics/NativeShadowCanvas { // com.compose.sdl.graphics/NativeShadowCanvas|null[0]
|
||||||
abstract fun drawDropShadow(androidx.compose.ui.graphics/Outline, kotlin/Float, androidx.compose.ui.graphics/Color, androidx.compose.ui.graphics/Color) // com.compose.sdl.graphics/NativeShadowCanvas.drawDropShadow|drawDropShadow(androidx.compose.ui.graphics.Outline;kotlin.Float;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color){}[0]
|
abstract fun drawDropShadow(androidx.compose.ui.graphics/Outline, kotlin/Float, androidx.compose.ui.graphics/Color, androidx.compose.ui.graphics/Color) // com.compose.sdl.graphics/NativeShadowCanvas.drawDropShadow|drawDropShadow(androidx.compose.ui.graphics.Outline;kotlin.Float;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color){}[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract interface com.compose.sdl.graphics/NativeShapeClipCanvas { // com.compose.sdl.graphics/NativeShapeClipCanvas|null[0]
|
|
||||||
abstract fun clipRoundRect(androidx.compose.ui.geometry/RoundRect) // com.compose.sdl.graphics/NativeShapeClipCanvas.clipRoundRect|clipRoundRect(androidx.compose.ui.geometry.RoundRect){}[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract interface com.compose.sdl.res/ImageLoader { // com.compose.sdl.res/ImageLoader|null[0]
|
abstract interface com.compose.sdl.res/ImageLoader { // com.compose.sdl.res/ImageLoader|null[0]
|
||||||
abstract fun intrinsicSize(kotlin/String, com.compose.sdl.res/ResourceKind): androidx.compose.ui.geometry/Size // com.compose.sdl.res/ImageLoader.intrinsicSize|intrinsicSize(kotlin.String;com.compose.sdl.res.ResourceKind){}[0]
|
abstract fun intrinsicSize(kotlin/String, com.compose.sdl.res/ResourceKind): androidx.compose.ui.geometry/Size // com.compose.sdl.res/ImageLoader.intrinsicSize|intrinsicSize(kotlin.String;com.compose.sdl.res.ResourceKind){}[0]
|
||||||
abstract fun readBytes(kotlin/String): kotlin/ByteArray? // com.compose.sdl.res/ImageLoader.readBytes|readBytes(kotlin.String){}[0]
|
abstract fun readBytes(kotlin/String): kotlin/ByteArray? // com.compose.sdl.res/ImageLoader.readBytes|readBytes(kotlin.String){}[0]
|
||||||
@@ -364,62 +356,6 @@ sealed interface androidx.compose.ui.graphics.shadow/ShadowContext { // androidx
|
|||||||
open fun createInnerShadowPainter(androidx.compose.ui.graphics/Shape, androidx.compose.ui.graphics.shadow/Shadow): androidx.compose.ui.graphics.shadow/InnerShadowPainter // androidx.compose.ui.graphics.shadow/ShadowContext.createInnerShadowPainter|createInnerShadowPainter(androidx.compose.ui.graphics.Shape;androidx.compose.ui.graphics.shadow.Shadow){}[0]
|
open fun createInnerShadowPainter(androidx.compose.ui.graphics/Shape, androidx.compose.ui.graphics.shadow/Shadow): androidx.compose.ui.graphics.shadow/InnerShadowPainter // androidx.compose.ui.graphics.shadow/ShadowContext.createInnerShadowPainter|createInnerShadowPainter(androidx.compose.ui.graphics.Shape;androidx.compose.ui.graphics.shadow.Shadow){}[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed interface com.compose.sdl.graphics/PathCommand { // com.compose.sdl.graphics/PathCommand|null[0]
|
|
||||||
final class CubicTo : com.compose.sdl.graphics/PathCommand { // com.compose.sdl.graphics/PathCommand.CubicTo|null[0]
|
|
||||||
constructor <init>(kotlin/Float, kotlin/Float, kotlin/Float, kotlin/Float, kotlin/Float, kotlin/Float) // com.compose.sdl.graphics/PathCommand.CubicTo.<init>|<init>(kotlin.Float;kotlin.Float;kotlin.Float;kotlin.Float;kotlin.Float;kotlin.Float){}[0]
|
|
||||||
|
|
||||||
final val c1x // com.compose.sdl.graphics/PathCommand.CubicTo.c1x|{}c1x[0]
|
|
||||||
final fun <get-c1x>(): kotlin/Float // com.compose.sdl.graphics/PathCommand.CubicTo.c1x.<get-c1x>|<get-c1x>(){}[0]
|
|
||||||
final val c1y // com.compose.sdl.graphics/PathCommand.CubicTo.c1y|{}c1y[0]
|
|
||||||
final fun <get-c1y>(): kotlin/Float // com.compose.sdl.graphics/PathCommand.CubicTo.c1y.<get-c1y>|<get-c1y>(){}[0]
|
|
||||||
final val c2x // com.compose.sdl.graphics/PathCommand.CubicTo.c2x|{}c2x[0]
|
|
||||||
final fun <get-c2x>(): kotlin/Float // com.compose.sdl.graphics/PathCommand.CubicTo.c2x.<get-c2x>|<get-c2x>(){}[0]
|
|
||||||
final val c2y // com.compose.sdl.graphics/PathCommand.CubicTo.c2y|{}c2y[0]
|
|
||||||
final fun <get-c2y>(): kotlin/Float // com.compose.sdl.graphics/PathCommand.CubicTo.c2y.<get-c2y>|<get-c2y>(){}[0]
|
|
||||||
final val x // com.compose.sdl.graphics/PathCommand.CubicTo.x|{}x[0]
|
|
||||||
final fun <get-x>(): kotlin/Float // com.compose.sdl.graphics/PathCommand.CubicTo.x.<get-x>|<get-x>(){}[0]
|
|
||||||
final val y // com.compose.sdl.graphics/PathCommand.CubicTo.y|{}y[0]
|
|
||||||
final fun <get-y>(): kotlin/Float // com.compose.sdl.graphics/PathCommand.CubicTo.y.<get-y>|<get-y>(){}[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
final class LineTo : com.compose.sdl.graphics/PathCommand { // com.compose.sdl.graphics/PathCommand.LineTo|null[0]
|
|
||||||
constructor <init>(kotlin/Float, kotlin/Float) // com.compose.sdl.graphics/PathCommand.LineTo.<init>|<init>(kotlin.Float;kotlin.Float){}[0]
|
|
||||||
|
|
||||||
final val x // com.compose.sdl.graphics/PathCommand.LineTo.x|{}x[0]
|
|
||||||
final fun <get-x>(): kotlin/Float // com.compose.sdl.graphics/PathCommand.LineTo.x.<get-x>|<get-x>(){}[0]
|
|
||||||
final val y // com.compose.sdl.graphics/PathCommand.LineTo.y|{}y[0]
|
|
||||||
final fun <get-y>(): kotlin/Float // com.compose.sdl.graphics/PathCommand.LineTo.y.<get-y>|<get-y>(){}[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
final class MoveTo : com.compose.sdl.graphics/PathCommand { // com.compose.sdl.graphics/PathCommand.MoveTo|null[0]
|
|
||||||
constructor <init>(kotlin/Float, kotlin/Float) // com.compose.sdl.graphics/PathCommand.MoveTo.<init>|<init>(kotlin.Float;kotlin.Float){}[0]
|
|
||||||
|
|
||||||
final val x // com.compose.sdl.graphics/PathCommand.MoveTo.x|{}x[0]
|
|
||||||
final fun <get-x>(): kotlin/Float // com.compose.sdl.graphics/PathCommand.MoveTo.x.<get-x>|<get-x>(){}[0]
|
|
||||||
final val y // com.compose.sdl.graphics/PathCommand.MoveTo.y|{}y[0]
|
|
||||||
final fun <get-y>(): kotlin/Float // com.compose.sdl.graphics/PathCommand.MoveTo.y.<get-y>|<get-y>(){}[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
final class QuadTo : com.compose.sdl.graphics/PathCommand { // com.compose.sdl.graphics/PathCommand.QuadTo|null[0]
|
|
||||||
constructor <init>(kotlin/Float, kotlin/Float, kotlin/Float, kotlin/Float) // com.compose.sdl.graphics/PathCommand.QuadTo.<init>|<init>(kotlin.Float;kotlin.Float;kotlin.Float;kotlin.Float){}[0]
|
|
||||||
|
|
||||||
final val cx // com.compose.sdl.graphics/PathCommand.QuadTo.cx|{}cx[0]
|
|
||||||
final fun <get-cx>(): kotlin/Float // com.compose.sdl.graphics/PathCommand.QuadTo.cx.<get-cx>|<get-cx>(){}[0]
|
|
||||||
final val cy // com.compose.sdl.graphics/PathCommand.QuadTo.cy|{}cy[0]
|
|
||||||
final fun <get-cy>(): kotlin/Float // com.compose.sdl.graphics/PathCommand.QuadTo.cy.<get-cy>|<get-cy>(){}[0]
|
|
||||||
final val x // com.compose.sdl.graphics/PathCommand.QuadTo.x|{}x[0]
|
|
||||||
final fun <get-x>(): kotlin/Float // com.compose.sdl.graphics/PathCommand.QuadTo.x.<get-x>|<get-x>(){}[0]
|
|
||||||
final val y // com.compose.sdl.graphics/PathCommand.QuadTo.y|{}y[0]
|
|
||||||
final fun <get-y>(): kotlin/Float // com.compose.sdl.graphics/PathCommand.QuadTo.y.<get-y>|<get-y>(){}[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
final object Close : com.compose.sdl.graphics/PathCommand { // com.compose.sdl.graphics/PathCommand.Close|null[0]
|
|
||||||
final fun equals(kotlin/Any?): kotlin/Boolean // com.compose.sdl.graphics/PathCommand.Close.equals|equals(kotlin.Any?){}[0]
|
|
||||||
final fun hashCode(): kotlin/Int // com.compose.sdl.graphics/PathCommand.Close.hashCode|hashCode(){}[0]
|
|
||||||
final fun toString(): kotlin/String // com.compose.sdl.graphics/PathCommand.Close.toString|toString(){}[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class androidx.compose.ui.graphics.colorspace/Adaptation { // androidx.compose.ui.graphics.colorspace/Adaptation|null[0]
|
abstract class androidx.compose.ui.graphics.colorspace/Adaptation { // androidx.compose.ui.graphics.colorspace/Adaptation|null[0]
|
||||||
final object Companion { // androidx.compose.ui.graphics.colorspace/Adaptation.Companion|null[0]
|
final object Companion { // androidx.compose.ui.graphics.colorspace/Adaptation.Companion|null[0]
|
||||||
final val Bradford // androidx.compose.ui.graphics.colorspace/Adaptation.Companion.Bradford|{}Bradford[0]
|
final val Bradford // androidx.compose.ui.graphics.colorspace/Adaptation.Companion.Bradford|{}Bradford[0]
|
||||||
@@ -1111,19 +1047,6 @@ final class com.compose.sdl.renderer.skia/SkiaLeafDrawer { // com.compose.sdl.re
|
|||||||
final fun <get-imageCache>(): com.compose.sdl.renderer.skia/SkiaImageCache // com.compose.sdl.renderer.skia/SkiaLeafDrawer.imageCache.<get-imageCache>|<get-imageCache>(){}[0]
|
final fun <get-imageCache>(): com.compose.sdl.renderer.skia/SkiaImageCache // com.compose.sdl.renderer.skia/SkiaLeafDrawer.imageCache.<get-imageCache>|<get-imageCache>(){}[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
final class com.compose.sdl.res/ResourcePainter : androidx.compose.ui.graphics.painter/Painter { // com.compose.sdl.res/ResourcePainter|null[0]
|
|
||||||
final val intrinsicSize // com.compose.sdl.res/ResourcePainter.intrinsicSize|{}intrinsicSize[0]
|
|
||||||
final fun <get-intrinsicSize>(): androidx.compose.ui.geometry/Size // com.compose.sdl.res/ResourcePainter.intrinsicSize.<get-intrinsicSize>|<get-intrinsicSize>(){}[0]
|
|
||||||
final val kind // com.compose.sdl.res/ResourcePainter.kind|{}kind[0]
|
|
||||||
final fun <get-kind>(): com.compose.sdl.res/ResourceKind // com.compose.sdl.res/ResourcePainter.kind.<get-kind>|<get-kind>(){}[0]
|
|
||||||
final val resourcePath // com.compose.sdl.res/ResourcePainter.resourcePath|{}resourcePath[0]
|
|
||||||
final fun <get-resourcePath>(): kotlin/String // com.compose.sdl.res/ResourcePainter.resourcePath.<get-resourcePath>|<get-resourcePath>(){}[0]
|
|
||||||
|
|
||||||
final fun equals(kotlin/Any?): kotlin/Boolean // com.compose.sdl.res/ResourcePainter.equals|equals(kotlin.Any?){}[0]
|
|
||||||
final fun hashCode(): kotlin/Int // com.compose.sdl.res/ResourcePainter.hashCode|hashCode(){}[0]
|
|
||||||
final fun toString(): kotlin/String // com.compose.sdl.res/ResourcePainter.toString|toString(){}[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
final value class androidx.compose.ui.graphics.colorspace/ColorModel { // androidx.compose.ui.graphics.colorspace/ColorModel|null[0]
|
final value class androidx.compose.ui.graphics.colorspace/ColorModel { // androidx.compose.ui.graphics.colorspace/ColorModel|null[0]
|
||||||
final val componentCount // androidx.compose.ui.graphics.colorspace/ColorModel.componentCount|{}componentCount[0]
|
final val componentCount // androidx.compose.ui.graphics.colorspace/ColorModel.componentCount|{}componentCount[0]
|
||||||
final fun <get-componentCount>(): kotlin/Int // androidx.compose.ui.graphics.colorspace/ColorModel.componentCount.<get-componentCount>|<get-componentCount>(){}[0]
|
final fun <get-componentCount>(): kotlin/Int // androidx.compose.ui.graphics.colorspace/ColorModel.componentCount.<get-componentCount>|<get-componentCount>(){}[0]
|
||||||
@@ -2108,10 +2031,6 @@ final object com.compose.sdl.graphics/NativeReleaseQueue { // com.compose.sdl.gr
|
|||||||
final fun enqueue(kotlin/Function0<kotlin/Unit>) // com.compose.sdl.graphics/NativeReleaseQueue.enqueue|enqueue(kotlin.Function0<kotlin.Unit>){}[0]
|
final fun enqueue(kotlin/Function0<kotlin/Unit>) // com.compose.sdl.graphics/NativeReleaseQueue.enqueue|enqueue(kotlin.Function0<kotlin.Unit>){}[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
final object com.compose.sdl.res/AndroidVectorToSvg { // com.compose.sdl.res/AndroidVectorToSvg|null[0]
|
|
||||||
final fun convert(kotlin/String): kotlin/String // com.compose.sdl.res/AndroidVectorToSvg.convert|convert(kotlin.String){}[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
final object com.compose.sdl.res/Res { // com.compose.sdl.res/Res|null[0]
|
final object com.compose.sdl.res/Res { // com.compose.sdl.res/Res|null[0]
|
||||||
final fun readBytes(kotlin/String): kotlin/ByteArray? // com.compose.sdl.res/Res.readBytes|readBytes(kotlin.String){}[0]
|
final fun readBytes(kotlin/String): kotlin/ByteArray? // com.compose.sdl.res/Res.readBytes|readBytes(kotlin.String){}[0]
|
||||||
|
|
||||||
@@ -2261,11 +2180,9 @@ final val com.compose.sdl.graphics/gradientTileMode // com.compose.sdl.graphics/
|
|||||||
final val com.compose.sdl.renderer.skia/com_compose_sdl_renderer_skia_SkiaEncodedImageDecoder$stableprop // com.compose.sdl.renderer.skia/com_compose_sdl_renderer_skia_SkiaEncodedImageDecoder$stableprop|#static{}com_compose_sdl_renderer_skia_SkiaEncodedImageDecoder$stableprop[0]
|
final val com.compose.sdl.renderer.skia/com_compose_sdl_renderer_skia_SkiaEncodedImageDecoder$stableprop // com.compose.sdl.renderer.skia/com_compose_sdl_renderer_skia_SkiaEncodedImageDecoder$stableprop|#static{}com_compose_sdl_renderer_skia_SkiaEncodedImageDecoder$stableprop[0]
|
||||||
final val com.compose.sdl.renderer.skia/com_compose_sdl_renderer_skia_SkiaImageCache$stableprop // com.compose.sdl.renderer.skia/com_compose_sdl_renderer_skia_SkiaImageCache$stableprop|#static{}com_compose_sdl_renderer_skia_SkiaImageCache$stableprop[0]
|
final val com.compose.sdl.renderer.skia/com_compose_sdl_renderer_skia_SkiaImageCache$stableprop // com.compose.sdl.renderer.skia/com_compose_sdl_renderer_skia_SkiaImageCache$stableprop|#static{}com_compose_sdl_renderer_skia_SkiaImageCache$stableprop[0]
|
||||||
final val com.compose.sdl.renderer.skia/com_compose_sdl_renderer_skia_SkiaLeafDrawer$stableprop // com.compose.sdl.renderer.skia/com_compose_sdl_renderer_skia_SkiaLeafDrawer$stableprop|#static{}com_compose_sdl_renderer_skia_SkiaLeafDrawer$stableprop[0]
|
final val com.compose.sdl.renderer.skia/com_compose_sdl_renderer_skia_SkiaLeafDrawer$stableprop // com.compose.sdl.renderer.skia/com_compose_sdl_renderer_skia_SkiaLeafDrawer$stableprop|#static{}com_compose_sdl_renderer_skia_SkiaLeafDrawer$stableprop[0]
|
||||||
final val com.compose.sdl.res/com_compose_sdl_res_AndroidVectorToSvg$stableprop // com.compose.sdl.res/com_compose_sdl_res_AndroidVectorToSvg$stableprop|#static{}com_compose_sdl_res_AndroidVectorToSvg$stableprop[0]
|
|
||||||
final val com.compose.sdl.res/com_compose_sdl_res_Res$stableprop // com.compose.sdl.res/com_compose_sdl_res_Res$stableprop|#static{}com_compose_sdl_res_Res$stableprop[0]
|
final val com.compose.sdl.res/com_compose_sdl_res_Res$stableprop // com.compose.sdl.res/com_compose_sdl_res_Res$stableprop|#static{}com_compose_sdl_res_Res$stableprop[0]
|
||||||
final val com.compose.sdl.res/com_compose_sdl_res_Res_drawable$stableprop // com.compose.sdl.res/com_compose_sdl_res_Res_drawable$stableprop|#static{}com_compose_sdl_res_Res_drawable$stableprop[0]
|
final val com.compose.sdl.res/com_compose_sdl_res_Res_drawable$stableprop // com.compose.sdl.res/com_compose_sdl_res_Res_drawable$stableprop|#static{}com_compose_sdl_res_Res_drawable$stableprop[0]
|
||||||
final val com.compose.sdl.res/com_compose_sdl_res_Res_files$stableprop // com.compose.sdl.res/com_compose_sdl_res_Res_files$stableprop|#static{}com_compose_sdl_res_Res_files$stableprop[0]
|
final val com.compose.sdl.res/com_compose_sdl_res_Res_files$stableprop // com.compose.sdl.res/com_compose_sdl_res_Res_files$stableprop|#static{}com_compose_sdl_res_Res_files$stableprop[0]
|
||||||
final val com.compose.sdl.res/com_compose_sdl_res_ResourcePainter$stableprop // com.compose.sdl.res/com_compose_sdl_res_ResourcePainter$stableprop|#static{}com_compose_sdl_res_ResourcePainter$stableprop[0]
|
|
||||||
|
|
||||||
final var androidx.compose.ui.graphics/alphaMultiplier // androidx.compose.ui.graphics/alphaMultiplier|@androidx.compose.ui.graphics.Canvas{}alphaMultiplier[0]
|
final var androidx.compose.ui.graphics/alphaMultiplier // androidx.compose.ui.graphics/alphaMultiplier|@androidx.compose.ui.graphics.Canvas{}alphaMultiplier[0]
|
||||||
final fun (androidx.compose.ui.graphics/Canvas).<get-alphaMultiplier>(): kotlin/Float // androidx.compose.ui.graphics/alphaMultiplier.<get-alphaMultiplier>|<get-alphaMultiplier>@androidx.compose.ui.graphics.Canvas(){}[0]
|
final fun (androidx.compose.ui.graphics/Canvas).<get-alphaMultiplier>(): kotlin/Float // androidx.compose.ui.graphics/alphaMultiplier.<get-alphaMultiplier>|<get-alphaMultiplier>@androidx.compose.ui.graphics.Canvas(){}[0]
|
||||||
@@ -2456,14 +2373,11 @@ final fun com.compose.sdl.renderer.skia/com_compose_sdl_renderer_skia_SkiaEncode
|
|||||||
final fun com.compose.sdl.renderer.skia/com_compose_sdl_renderer_skia_SkiaImageCache$stableprop_getter(): kotlin/Int // com.compose.sdl.renderer.skia/com_compose_sdl_renderer_skia_SkiaImageCache$stableprop_getter|com_compose_sdl_renderer_skia_SkiaImageCache$stableprop_getter(){}[0]
|
final fun com.compose.sdl.renderer.skia/com_compose_sdl_renderer_skia_SkiaImageCache$stableprop_getter(): kotlin/Int // com.compose.sdl.renderer.skia/com_compose_sdl_renderer_skia_SkiaImageCache$stableprop_getter|com_compose_sdl_renderer_skia_SkiaImageCache$stableprop_getter(){}[0]
|
||||||
final fun com.compose.sdl.renderer.skia/com_compose_sdl_renderer_skia_SkiaLeafDrawer$stableprop_getter(): kotlin/Int // com.compose.sdl.renderer.skia/com_compose_sdl_renderer_skia_SkiaLeafDrawer$stableprop_getter|com_compose_sdl_renderer_skia_SkiaLeafDrawer$stableprop_getter(){}[0]
|
final fun com.compose.sdl.renderer.skia/com_compose_sdl_renderer_skia_SkiaLeafDrawer$stableprop_getter(): kotlin/Int // com.compose.sdl.renderer.skia/com_compose_sdl_renderer_skia_SkiaLeafDrawer$stableprop_getter|com_compose_sdl_renderer_skia_SkiaLeafDrawer$stableprop_getter(){}[0]
|
||||||
final fun com.compose.sdl.renderer.skia/readBackBgra(org.jetbrains.skia/Surface?, kotlin/Int, kotlin/Int): kotlin/Triple<kotlin/Int, kotlin/Int, kotlin/ByteArray>? // com.compose.sdl.renderer.skia/readBackBgra|readBackBgra(org.jetbrains.skia.Surface?;kotlin.Int;kotlin.Int){}[0]
|
final fun com.compose.sdl.renderer.skia/readBackBgra(org.jetbrains.skia/Surface?, kotlin/Int, kotlin/Int): kotlin/Triple<kotlin/Int, kotlin/Int, kotlin/ByteArray>? // com.compose.sdl.renderer.skia/readBackBgra|readBackBgra(org.jetbrains.skia.Surface?;kotlin.Int;kotlin.Int){}[0]
|
||||||
final fun com.compose.sdl.res/com_compose_sdl_res_AndroidVectorToSvg$stableprop_getter(): kotlin/Int // com.compose.sdl.res/com_compose_sdl_res_AndroidVectorToSvg$stableprop_getter|com_compose_sdl_res_AndroidVectorToSvg$stableprop_getter(){}[0]
|
|
||||||
final fun com.compose.sdl.res/com_compose_sdl_res_Res$stableprop_getter(): kotlin/Int // com.compose.sdl.res/com_compose_sdl_res_Res$stableprop_getter|com_compose_sdl_res_Res$stableprop_getter(){}[0]
|
final fun com.compose.sdl.res/com_compose_sdl_res_Res$stableprop_getter(): kotlin/Int // com.compose.sdl.res/com_compose_sdl_res_Res$stableprop_getter|com_compose_sdl_res_Res$stableprop_getter(){}[0]
|
||||||
final fun com.compose.sdl.res/com_compose_sdl_res_Res_drawable$stableprop_getter(): kotlin/Int // com.compose.sdl.res/com_compose_sdl_res_Res_drawable$stableprop_getter|com_compose_sdl_res_Res_drawable$stableprop_getter(){}[0]
|
final fun com.compose.sdl.res/com_compose_sdl_res_Res_drawable$stableprop_getter(): kotlin/Int // com.compose.sdl.res/com_compose_sdl_res_Res_drawable$stableprop_getter|com_compose_sdl_res_Res_drawable$stableprop_getter(){}[0]
|
||||||
final fun com.compose.sdl.res/com_compose_sdl_res_Res_files$stableprop_getter(): kotlin/Int // com.compose.sdl.res/com_compose_sdl_res_Res_files$stableprop_getter|com_compose_sdl_res_Res_files$stableprop_getter(){}[0]
|
final fun com.compose.sdl.res/com_compose_sdl_res_Res_files$stableprop_getter(): kotlin/Int // com.compose.sdl.res/com_compose_sdl_res_Res_files$stableprop_getter|com_compose_sdl_res_Res_files$stableprop_getter(){}[0]
|
||||||
final fun com.compose.sdl.res/com_compose_sdl_res_ResourcePainter$stableprop_getter(): kotlin/Int // com.compose.sdl.res/com_compose_sdl_res_ResourcePainter$stableprop_getter|com_compose_sdl_res_ResourcePainter$stableprop_getter(){}[0]
|
|
||||||
final fun com.compose.sdl.res/painterResource(kotlin/String): androidx.compose.ui.graphics.painter/Painter // com.compose.sdl.res/painterResource|painterResource(kotlin.String){}[0]
|
final fun com.compose.sdl.res/painterResource(kotlin/String): androidx.compose.ui.graphics.painter/Painter // com.compose.sdl.res/painterResource|painterResource(kotlin.String){}[0]
|
||||||
final fun com.compose.sdl.res/painterResource(kotlin/String, com.compose.sdl.res/ResourceKind): androidx.compose.ui.graphics.painter/Painter // com.compose.sdl.res/painterResource|painterResource(kotlin.String;com.compose.sdl.res.ResourceKind){}[0]
|
final fun com.compose.sdl.res/painterResource(kotlin/String, com.compose.sdl.res/ResourceKind): androidx.compose.ui.graphics.painter/Painter // com.compose.sdl.res/painterResource|painterResource(kotlin.String;com.compose.sdl.res.ResourceKind){}[0]
|
||||||
final fun com.compose.sdl.res/resourceKindForPath(kotlin/String): com.compose.sdl.res/ResourceKind // com.compose.sdl.res/resourceKindForPath|resourceKindForPath(kotlin.String){}[0]
|
|
||||||
final inline fun (androidx.compose.ui.graphics.drawscope/DrawScope).androidx.compose.ui.graphics.drawscope/clipPath(androidx.compose.ui.graphics/Path, androidx.compose.ui.graphics/ClipOp = ..., kotlin/Function1<androidx.compose.ui.graphics.drawscope/DrawScope, kotlin/Unit>) // androidx.compose.ui.graphics.drawscope/clipPath|clipPath@androidx.compose.ui.graphics.drawscope.DrawScope(androidx.compose.ui.graphics.Path;androidx.compose.ui.graphics.ClipOp;kotlin.Function1<androidx.compose.ui.graphics.drawscope.DrawScope,kotlin.Unit>){}[0]
|
final inline fun (androidx.compose.ui.graphics.drawscope/DrawScope).androidx.compose.ui.graphics.drawscope/clipPath(androidx.compose.ui.graphics/Path, androidx.compose.ui.graphics/ClipOp = ..., kotlin/Function1<androidx.compose.ui.graphics.drawscope/DrawScope, kotlin/Unit>) // androidx.compose.ui.graphics.drawscope/clipPath|clipPath@androidx.compose.ui.graphics.drawscope.DrawScope(androidx.compose.ui.graphics.Path;androidx.compose.ui.graphics.ClipOp;kotlin.Function1<androidx.compose.ui.graphics.drawscope.DrawScope,kotlin.Unit>){}[0]
|
||||||
final inline fun (androidx.compose.ui.graphics.drawscope/DrawScope).androidx.compose.ui.graphics.drawscope/clipRect(kotlin/Float = ..., kotlin/Float = ..., kotlin/Float = ..., kotlin/Float = ..., androidx.compose.ui.graphics/ClipOp = ..., kotlin/Function1<androidx.compose.ui.graphics.drawscope/DrawScope, kotlin/Unit>) // androidx.compose.ui.graphics.drawscope/clipRect|clipRect@androidx.compose.ui.graphics.drawscope.DrawScope(kotlin.Float;kotlin.Float;kotlin.Float;kotlin.Float;androidx.compose.ui.graphics.ClipOp;kotlin.Function1<androidx.compose.ui.graphics.drawscope.DrawScope,kotlin.Unit>){}[0]
|
final inline fun (androidx.compose.ui.graphics.drawscope/DrawScope).androidx.compose.ui.graphics.drawscope/clipRect(kotlin/Float = ..., kotlin/Float = ..., kotlin/Float = ..., kotlin/Float = ..., androidx.compose.ui.graphics/ClipOp = ..., kotlin/Function1<androidx.compose.ui.graphics.drawscope/DrawScope, kotlin/Unit>) // androidx.compose.ui.graphics.drawscope/clipRect|clipRect@androidx.compose.ui.graphics.drawscope.DrawScope(kotlin.Float;kotlin.Float;kotlin.Float;kotlin.Float;androidx.compose.ui.graphics.ClipOp;kotlin.Function1<androidx.compose.ui.graphics.drawscope.DrawScope,kotlin.Unit>){}[0]
|
||||||
final inline fun (androidx.compose.ui.graphics.drawscope/DrawScope).androidx.compose.ui.graphics.drawscope/draw(androidx.compose.ui.unit/Density, androidx.compose.ui.unit/LayoutDirection, androidx.compose.ui.graphics/Canvas, androidx.compose.ui.geometry/Size, androidx.compose.ui.graphics.layer/GraphicsLayer? = ..., kotlin/Function1<androidx.compose.ui.graphics.drawscope/DrawScope, kotlin/Unit>) // androidx.compose.ui.graphics.drawscope/draw|draw@androidx.compose.ui.graphics.drawscope.DrawScope(androidx.compose.ui.unit.Density;androidx.compose.ui.unit.LayoutDirection;androidx.compose.ui.graphics.Canvas;androidx.compose.ui.geometry.Size;androidx.compose.ui.graphics.layer.GraphicsLayer?;kotlin.Function1<androidx.compose.ui.graphics.drawscope.DrawScope,kotlin.Unit>){}[0]
|
final inline fun (androidx.compose.ui.graphics.drawscope/DrawScope).androidx.compose.ui.graphics.drawscope/draw(androidx.compose.ui.unit/Density, androidx.compose.ui.unit/LayoutDirection, androidx.compose.ui.graphics/Canvas, androidx.compose.ui.geometry/Size, androidx.compose.ui.graphics.layer/GraphicsLayer? = ..., kotlin/Function1<androidx.compose.ui.graphics.drawscope/DrawScope, kotlin/Unit>) // androidx.compose.ui.graphics.drawscope/draw|draw@androidx.compose.ui.graphics.drawscope.DrawScope(androidx.compose.ui.unit.Density;androidx.compose.ui.unit.LayoutDirection;androidx.compose.ui.graphics.Canvas;androidx.compose.ui.geometry.Size;androidx.compose.ui.graphics.layer.GraphicsLayer?;kotlin.Function1<androidx.compose.ui.graphics.drawscope.DrawScope,kotlin.Unit>){}[0]
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ import com.compose.sdl.res.ResourceKind
|
|||||||
the given rect, and this seam carries no ui-layout (ContentScale) dependency -
|
the given rect, and this seam carries no ui-layout (ContentScale) dependency -
|
||||||
keeping :ui-graphics free of :ui.
|
keeping :ui-graphics free of :ui.
|
||||||
*/
|
*/
|
||||||
interface NativePainterCanvas {
|
internal interface NativePainterCanvas {
|
||||||
fun drawNativePainter(
|
fun drawNativePainter(
|
||||||
inResourcePath: String,
|
inResourcePath: String,
|
||||||
inKind: ResourceKind,
|
inKind: ResourceKind,
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ package com.compose.sdl.graphics
|
|||||||
carries a `commands: List<PathCommand>` that the SDL3 / Skia renderers walk
|
carries a `commands: List<PathCommand>` that the SDL3 / Skia renderers walk
|
||||||
directly. No official equivalent, so lives in com.compose.sdl
|
directly. No official equivalent, so lives in com.compose.sdl
|
||||||
per FIDELITY.md's relocate rule. */
|
per FIDELITY.md's relocate rule. */
|
||||||
sealed interface PathCommand {
|
internal sealed interface PathCommand {
|
||||||
class MoveTo(val x: Float, val y: Float) : PathCommand
|
class MoveTo(val x: Float, val y: Float) : PathCommand
|
||||||
class LineTo(val x: Float, val y: Float) : PathCommand
|
class LineTo(val x: Float, val y: Float) : PathCommand
|
||||||
class QuadTo(val cx: Float, val cy: Float, val x: Float, val y: Float) : PathCommand
|
class QuadTo(val cx: Float, val cy: Float, val x: Float, val y: Float) : PathCommand
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ import androidx.compose.ui.geometry.RoundRect
|
|||||||
`Canvas.restore()` - the backend composites and pops it on the matching
|
`Canvas.restore()` - the backend composites and pops it on the matching
|
||||||
`restore()`.
|
`restore()`.
|
||||||
*/
|
*/
|
||||||
interface NativeShapeClipCanvas {
|
internal interface NativeShapeClipCanvas {
|
||||||
// Pushes a rounded-rect clip for subsequent draws until the matching
|
// Pushes a rounded-rect clip for subsequent draws until the matching
|
||||||
// Canvas.restore(). [inRoundRect] is in the CURRENT canvas-local coordinate
|
// Canvas.restore(). [inRoundRect] is in the CURRENT canvas-local coordinate
|
||||||
// space (the same space draw calls use after the enclosing translate).
|
// space (the same space draw calls use after the enclosing translate).
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ package com.compose.sdl.res
|
|||||||
Not supported: <group> transforms (paths are flattened, transforms ignored),
|
Not supported: <group> transforms (paths are flattened, transforms ignored),
|
||||||
gradients, clip-paths, trim-path. This covers the common single-/multi-path
|
gradients, clip-paths, trim-path. This covers the common single-/multi-path
|
||||||
icon case such as exported Material icons. */
|
icon case such as exported Material icons. */
|
||||||
object AndroidVectorToSvg {
|
internal object AndroidVectorToSvg {
|
||||||
|
|
||||||
// Tag values never contain '>' (pathData is letters/digits/.,- /space) and
|
// Tag values never contain '>' (pathData is letters/digits/.,- /space) and
|
||||||
// quoted attribute values can't either, so [^>] within a tag is safe.
|
// quoted attribute values can't either, so [^>] within a tag is safe.
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ enum class ResourceKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Picks a ResourceKind from a file extension. */
|
/** Picks a ResourceKind from a file extension. */
|
||||||
fun resourceKindForPath(path: String): ResourceKind {
|
internal fun resourceKindForPath(path: String): ResourceKind {
|
||||||
val vExt = path.substringAfterLast('.', "").lowercase()
|
val vExt = path.substringAfterLast('.', "").lowercase()
|
||||||
return when (vExt) {
|
return when (vExt) {
|
||||||
"svg" -> ResourceKind.Svg
|
"svg" -> ResourceKind.Svg
|
||||||
|
|||||||
@@ -27,17 +27,17 @@ import com.compose.sdl.graphics.NativePainterCanvas
|
|||||||
If the Canvas doesn't implement NativePainterCanvas (offscreen layer capture
|
If the Canvas doesn't implement NativePainterCanvas (offscreen layer capture
|
||||||
for graphics-layer effects) the paint is skipped.
|
for graphics-layer effects) the paint is skipped.
|
||||||
*/
|
*/
|
||||||
class ResourcePainter internal constructor(
|
internal class ResourcePainter internal constructor(
|
||||||
val resourcePath: String,
|
val resourcePath: String,
|
||||||
val kind: ResourceKind,
|
val kind: ResourceKind,
|
||||||
) : Painter() {
|
) : Painter() {
|
||||||
|
|
||||||
private var fAlpha: Float = 1f
|
private var mAlpha: Float = 1f
|
||||||
|
|
||||||
override val intrinsicSize: Size
|
override val intrinsicSize: Size
|
||||||
get() = currentImageLoader.intrinsicSize(resourcePath, kind)
|
get() = currentImageLoader.intrinsicSize(resourcePath, kind)
|
||||||
|
|
||||||
override fun applyAlpha(alpha: Float): Boolean { fAlpha = alpha; return true }
|
override fun applyAlpha(alpha: Float): Boolean { mAlpha = alpha; return true }
|
||||||
|
|
||||||
override fun DrawScope.onDraw() {
|
override fun DrawScope.onDraw() {
|
||||||
drawIntoCanvas { vCanvas ->
|
drawIntoCanvas { vCanvas ->
|
||||||
@@ -45,7 +45,7 @@ class ResourcePainter internal constructor(
|
|||||||
// translate + scaledSize, so we paint the resource FillBounds into the
|
// translate + scaledSize, so we paint the resource FillBounds into the
|
||||||
// full DrawScope size. Alpha is threaded via applyAlpha.
|
// full DrawScope size. Alpha is threaded via applyAlpha.
|
||||||
(vCanvas as? NativePainterCanvas)?.drawNativePainter(
|
(vCanvas as? NativePainterCanvas)?.drawNativePainter(
|
||||||
resourcePath, kind, 0f, 0f, size.width, size.height, fAlpha,
|
resourcePath, kind, 0f, 0f, size.width, size.height, mAlpha,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@ import kotlin.math.abs
|
|||||||
// vendored Matrices.skiko.kt and would not be visible up here. Distinct name
|
// vendored Matrices.skiko.kt and would not be visible up here. Distinct name
|
||||||
// avoids clashing with that copy on the Skia leg. (RENDERER.md P1.5 will
|
// avoids clashing with that copy on the Skia leg. (RENDERER.md P1.5 will
|
||||||
// reverse this rename once B2 vendors Matrices.skiko onto the Skia leg.)
|
// reverse this rename once B2 vendors Matrices.skiko onto the Skia leg.)
|
||||||
// VENDOR-BASE: compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/graphics/Matrices.skiko.kt @ v1.12.0
|
// VENDOR-BASE: compose/ui/ui-graphics/src/skikoMain/kotlin/androidx/compose/ui/graphics/Matrices.skiko.kt @ v1.12.1
|
||||||
|
|
||||||
// Builds the layer transform (translation / rotation / scale / camera about a
|
// Builds the layer transform (translation / rotation / scale / camera about a
|
||||||
// pivot) into [matrix]. Matches the skiko copy so hit-testing agrees across legs.
|
// pivot) into [matrix]. Matches the skiko copy so hit-testing agrees across legs.
|
||||||
|
|||||||
+7
-7
@@ -28,12 +28,12 @@ import kotlinx.atomicfu.locks.synchronized
|
|||||||
*/
|
*/
|
||||||
object NativeReleaseQueue {
|
object NativeReleaseQueue {
|
||||||
|
|
||||||
private val fLock = SynchronizedObject()
|
private val mLock = SynchronizedObject()
|
||||||
private var fPending = ArrayList<() -> Unit>()
|
private var mPending = ArrayList<() -> Unit>()
|
||||||
|
|
||||||
/** Enqueue a release action. Safe to call from any thread. */
|
/** Enqueue a release action. Safe to call from any thread. */
|
||||||
fun enqueue(action: () -> Unit) {
|
fun enqueue(action: () -> Unit) {
|
||||||
synchronized(fLock) { fPending.add(action) }
|
synchronized(mLock) { mPending.add(action) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,10 +41,10 @@ object NativeReleaseQueue {
|
|||||||
* renderer APIs that aren't thread-safe. Returns the number drained.
|
* renderer APIs that aren't thread-safe. Returns the number drained.
|
||||||
*/
|
*/
|
||||||
fun drain(): Int {
|
fun drain(): Int {
|
||||||
val vBatch = synchronized(fLock) {
|
val vBatch = synchronized(mLock) {
|
||||||
if (fPending.isEmpty()) return 0
|
if (mPending.isEmpty()) return 0
|
||||||
val vTaken = fPending
|
val vTaken = mPending
|
||||||
fPending = ArrayList()
|
mPending = ArrayList()
|
||||||
vTaken
|
vTaken
|
||||||
}
|
}
|
||||||
for (vAction in vBatch) {
|
for (vAction in vBatch) {
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// DERIVED (copy + edit) from compose-multiplatform-core -- MANUAL VENDOR, NON-IDEMPOTENT.
|
// DERIVED (copy + edit) from compose-multiplatform-core -- MANUAL VENDOR, NON-IDEMPOTENT.
|
||||||
// VENDOR-BASE: compose/ui/ui-graphics/src/skikoMain/kotlin/androidx/compose/ui/graphics/SkiaBackedCanvas.skiko.kt @ v1.12.0
|
// VENDOR-BASE: compose/ui/ui-graphics/src/skikoMain/kotlin/androidx/compose/ui/graphics/SkiaBackedCanvas.skiko.kt @ v1.12.1
|
||||||
// ONLY change vs upstream: this class also implements the port draw contracts
|
// ONLY change vs upstream: this class also implements the port draw contracts
|
||||||
// (NativePainterCanvas / NativeShadowCanvas / NativeFinishableCanvas) so the
|
// (NativePainterCanvas / NativeShadowCanvas / NativeFinishableCanvas) so the
|
||||||
// resource-image cache + elevation shadows keep working on the Skia renderer,
|
// resource-image cache + elevation shadows keep working on the Skia renderer,
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// DERIVED (copy + edit) from compose-multiplatform-core -- MANUAL VENDOR, NON-IDEMPOTENT.
|
// DERIVED (copy + edit) from compose-multiplatform-core -- MANUAL VENDOR, NON-IDEMPOTENT.
|
||||||
// VENDOR-BASE: compose/ui/ui-graphics/src/skikoMain/kotlin/androidx/compose/ui/graphics/SkiaImageAsset.skiko.kt @ v1.12.0
|
// VENDOR-BASE: compose/ui/ui-graphics/src/skikoMain/kotlin/androidx/compose/ui/graphics/SkiaImageAsset.skiko.kt @ v1.12.1
|
||||||
// FLATTENED for our single-native-source-set layout: upstream splits Image.toBitmap /
|
// FLATTENED for our single-native-source-set layout: upstream splits Image.toBitmap /
|
||||||
// ByteArray.putBytesInto into expect (here) + actual (skikoExcludingWebMain / nativeMain).
|
// ByteArray.putBytesInto into expect (here) + actual (skikoExcludingWebMain / nativeMain).
|
||||||
// Those collapse into the same skikoRenderer source set here, which is illegal, so the two
|
// Those collapse into the same skikoRenderer source set here, which is illegal, so the two
|
||||||
|
|||||||
+23
-23
@@ -38,7 +38,7 @@ class SkiaImageCache {
|
|||||||
// (registerMemoryResource - e.g. downloaded PNGs) from growing image memory
|
// (registerMemoryResource - e.g. downloaded PNGs) from growing image memory
|
||||||
// without limit (issue #2). On-screen images stay hot; an evicted one just
|
// without limit (issue #2). On-screen images stay hot; an evicted one just
|
||||||
// re-decodes on next use.
|
// re-decodes on next use.
|
||||||
private val fCache = LinkedHashMap<String, Image?>()
|
private val mCache = LinkedHashMap<String, Image?>()
|
||||||
|
|
||||||
// SVG / Android-vector kinds are RESOLUTION-INDEPENDENT: instead of caching one
|
// SVG / Android-vector kinds are RESOLUTION-INDEPENDENT: instead of caching one
|
||||||
// intrinsic-size raster and letting drawImageRect upscale it (blurry when an icon
|
// intrinsic-size raster and letting drawImageRect upscale it (blurry when an icon
|
||||||
@@ -46,8 +46,8 @@ class SkiaImageCache {
|
|||||||
// destination pixel size and cache that raster keyed by "path@WxH". Mirrors
|
// destination pixel size and cache that raster keyed by "path@WxH". Mirrors
|
||||||
// upstream's size-driven DrawCache for SVGPainter. Intrinsic dims are cached
|
// upstream's size-driven DrawCache for SVGPainter. Intrinsic dims are cached
|
||||||
// separately so the layout pass (intrinsicSize) doesn't force a raster.
|
// separately so the layout pass (intrinsicSize) doesn't force a raster.
|
||||||
private val fSvgRasterCache = LinkedHashMap<String, Image?>()
|
private val mSvgRasterCache = LinkedHashMap<String, Image?>()
|
||||||
private val fSvgIntrinsic = HashMap<String, androidx.compose.ui.geometry.Size>()
|
private val mSvgIntrinsic = HashMap<String, androidx.compose.ui.geometry.Size>()
|
||||||
|
|
||||||
fun intrinsicSize(inPath: String, inKind: ResourceKind): androidx.compose.ui.geometry.Size {
|
fun intrinsicSize(inPath: String, inKind: ResourceKind): androidx.compose.ui.geometry.Size {
|
||||||
if (inKind == ResourceKind.Svg || inKind == ResourceKind.AndroidVector) {
|
if (inKind == ResourceKind.Svg || inKind == ResourceKind.AndroidVector) {
|
||||||
@@ -58,18 +58,18 @@ class SkiaImageCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun get(inPath: String, inKind: ResourceKind): Image? {
|
private fun get(inPath: String, inKind: ResourceKind): Image? {
|
||||||
if (fCache.containsKey(inPath)) {
|
if (mCache.containsKey(inPath)) {
|
||||||
// Re-insert to mark most-recently-used (LinkedHashMap keeps first =
|
// Re-insert to mark most-recently-used (LinkedHashMap keeps first =
|
||||||
// least-recently-used for eviction below).
|
// least-recently-used for eviction below).
|
||||||
val vExisting = fCache.remove(inPath)
|
val vExisting = mCache.remove(inPath)
|
||||||
fCache[inPath] = vExisting
|
mCache[inPath] = vExisting
|
||||||
return vExisting
|
return vExisting
|
||||||
}
|
}
|
||||||
val vImage = decode(inPath, inKind)
|
val vImage = decode(inPath, inKind)
|
||||||
fCache[inPath] = vImage
|
mCache[inPath] = vImage
|
||||||
if (fCache.size > MAX_CACHED_IMAGES) {
|
if (mCache.size > MAX_CACHED_IMAGES) {
|
||||||
val vEldest = fCache.keys.firstOrNull()
|
val vEldest = mCache.keys.firstOrNull()
|
||||||
if (vEldest != null) fCache.remove(vEldest)?.close()
|
if (vEldest != null) mCache.remove(vEldest)?.close()
|
||||||
}
|
}
|
||||||
return vImage
|
return vImage
|
||||||
}
|
}
|
||||||
@@ -136,7 +136,7 @@ class SkiaImageCache {
|
|||||||
|
|
||||||
/** Intrinsic (viewport) size of the vector, parsed once and cached. */
|
/** Intrinsic (viewport) size of the vector, parsed once and cached. */
|
||||||
private fun svgIntrinsicSize(inPath: String, inKind: ResourceKind): androidx.compose.ui.geometry.Size {
|
private fun svgIntrinsicSize(inPath: String, inKind: ResourceKind): androidx.compose.ui.geometry.Size {
|
||||||
fSvgIntrinsic[inPath]?.let { return it }
|
mSvgIntrinsic[inPath]?.let { return it }
|
||||||
val vBytes = svgBytes(inPath, inKind) ?: return androidx.compose.ui.geometry.Size.Unspecified
|
val vBytes = svgBytes(inPath, inKind) ?: return androidx.compose.ui.geometry.Size.Unspecified
|
||||||
val vSize = runCatching {
|
val vSize = runCatching {
|
||||||
val vDom = SVGDOM(Data.makeFromBytes(vBytes))
|
val vDom = SVGDOM(Data.makeFromBytes(vBytes))
|
||||||
@@ -146,7 +146,7 @@ class SkiaImageCache {
|
|||||||
vDom.close()
|
vDom.close()
|
||||||
androidx.compose.ui.geometry.Size(vW, vH)
|
androidx.compose.ui.geometry.Size(vW, vH)
|
||||||
}.getOrDefault(androidx.compose.ui.geometry.Size.Unspecified)
|
}.getOrDefault(androidx.compose.ui.geometry.Size.Unspecified)
|
||||||
fSvgIntrinsic[inPath] = vSize
|
mSvgIntrinsic[inPath] = vSize
|
||||||
return vSize
|
return vSize
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,9 +157,9 @@ class SkiaImageCache {
|
|||||||
val vWpx = inW.roundToInt().coerceAtLeast(1)
|
val vWpx = inW.roundToInt().coerceAtLeast(1)
|
||||||
val vHpx = inH.roundToInt().coerceAtLeast(1)
|
val vHpx = inH.roundToInt().coerceAtLeast(1)
|
||||||
val vKey = "$inPath@${vWpx}x$vHpx"
|
val vKey = "$inPath@${vWpx}x$vHpx"
|
||||||
val vImg = if (fSvgRasterCache.containsKey(vKey)) {
|
val vImg = if (mSvgRasterCache.containsKey(vKey)) {
|
||||||
val vExisting = fSvgRasterCache.remove(vKey)
|
val vExisting = mSvgRasterCache.remove(vKey)
|
||||||
fSvgRasterCache[vKey] = vExisting
|
mSvgRasterCache[vKey] = vExisting
|
||||||
vExisting
|
vExisting
|
||||||
} else {
|
} else {
|
||||||
val vIntrinsic = svgIntrinsicSize(inPath, inKind)
|
val vIntrinsic = svgIntrinsicSize(inPath, inKind)
|
||||||
@@ -167,9 +167,9 @@ class SkiaImageCache {
|
|||||||
val vRaster = if (vBytes != null && vIntrinsic.isSpecified) {
|
val vRaster = if (vBytes != null && vIntrinsic.isSpecified) {
|
||||||
rasterizeSvgAt(vBytes, vIntrinsic.width, vIntrinsic.height, vWpx, vHpx)
|
rasterizeSvgAt(vBytes, vIntrinsic.width, vIntrinsic.height, vWpx, vHpx)
|
||||||
} else null
|
} else null
|
||||||
fSvgRasterCache[vKey] = vRaster
|
mSvgRasterCache[vKey] = vRaster
|
||||||
if (fSvgRasterCache.size > MAX_CACHED_IMAGES) {
|
if (mSvgRasterCache.size > MAX_CACHED_IMAGES) {
|
||||||
fSvgRasterCache.keys.firstOrNull()?.let { fSvgRasterCache.remove(it)?.close() }
|
mSvgRasterCache.keys.firstOrNull()?.let { mSvgRasterCache.remove(it)?.close() }
|
||||||
}
|
}
|
||||||
vRaster
|
vRaster
|
||||||
} ?: return
|
} ?: return
|
||||||
@@ -183,11 +183,11 @@ class SkiaImageCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun destroy() {
|
fun destroy() {
|
||||||
for (vImg in fCache.values) vImg?.close()
|
for (vImg in mCache.values) vImg?.close()
|
||||||
fCache.clear()
|
mCache.clear()
|
||||||
for (vImg in fSvgRasterCache.values) vImg?.close()
|
for (vImg in mSvgRasterCache.values) vImg?.close()
|
||||||
fSvgRasterCache.clear()
|
mSvgRasterCache.clear()
|
||||||
fSvgIntrinsic.clear()
|
mSvgIntrinsic.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
* compose/ui/compose-fork.txt is commented out so this file survives
|
* compose/ui/compose-fork.txt is commented out so this file survives
|
||||||
* `scripts/compose-fork/sync.sh`.
|
* `scripts/compose-fork/sync.sh`.
|
||||||
*/
|
*/
|
||||||
// VENDOR-BASE: compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/platform/Synchronization.kt @ v1.12.0
|
// VENDOR-BASE: compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/platform/Synchronization.kt @ v1.12.1
|
||||||
|
|
||||||
package androidx.compose.ui.text.platform
|
package androidx.compose.ui.text.platform
|
||||||
|
|
||||||
|
|||||||
@@ -18,35 +18,35 @@ package com.compose.sdl.icons
|
|||||||
the renderer where to find the bytes. */
|
the renderer where to find the bytes. */
|
||||||
object IconFont {
|
object IconFont {
|
||||||
|
|
||||||
private val fFonts = mutableMapOf<String, ByteArray>()
|
private val mFonts = mutableMapOf<String, ByteArray>()
|
||||||
// Families that render as single variable-axis glyphs (Material Symbols),
|
// Families that render as single variable-axis glyphs (Material Symbols),
|
||||||
// vs ordinary text fonts - icon families are drawn one codepoint at a time,
|
// vs ordinary text fonts - icon families are drawn one codepoint at a time,
|
||||||
// while text families (e.g. a bundled monospace) go through normal
|
// while text families (e.g. a bundled monospace) go through normal
|
||||||
// full-string rendering.
|
// full-string rendering.
|
||||||
private val fIconFamilies = mutableSetOf<String>()
|
private val mIconFamilies = mutableSetOf<String>()
|
||||||
|
|
||||||
/** Register a TEXT font family's bytes (rendered as full strings; e.g. a
|
/** Register a TEXT font family's bytes (rendered as full strings; e.g. a
|
||||||
bundled monospace). Idempotent - a second call with the same family
|
bundled monospace). Idempotent - a second call with the same family
|
||||||
replaces the previous bytes. */
|
replaces the previous bytes. */
|
||||||
fun register(inFamily: String, inBytes: ByteArray) {
|
fun register(inFamily: String, inBytes: ByteArray) {
|
||||||
fFonts[inFamily] = inBytes
|
mFonts[inFamily] = inBytes
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Register an ICON font family (Material Symbols et al.) - variable-axis.
|
/** Register an ICON font family (Material Symbols et al.) - variable-axis.
|
||||||
Same byte store as register(), but also flags the family as an icon
|
Same byte store as register(), but also flags the family as an icon
|
||||||
font. */
|
font. */
|
||||||
fun registerIcon(inFamily: String, inBytes: ByteArray) {
|
fun registerIcon(inFamily: String, inBytes: ByteArray) {
|
||||||
fFonts[inFamily] = inBytes
|
mFonts[inFamily] = inBytes
|
||||||
fIconFamilies += inFamily
|
mIconFamilies += inFamily
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Bytes for a registered family, or null if not registered. Renderers
|
/** Bytes for a registered family, or null if not registered. Renderers
|
||||||
fall back to the default font when this returns null. */
|
fall back to the default font when this returns null. */
|
||||||
fun bytesFor(inFamily: String): ByteArray? = fFonts[inFamily]
|
fun bytesFor(inFamily: String): ByteArray? = mFonts[inFamily]
|
||||||
|
|
||||||
/** True only for families registered via registerIcon() - icon fonts that
|
/** True only for families registered via registerIcon() - icon fonts that
|
||||||
need single-glyph (variable-axis) rendering, not text fonts. */
|
need single-glyph (variable-axis) rendering, not text fonts. */
|
||||||
fun isIconFamily(inFamily: String): Boolean = inFamily in fIconFamilies
|
fun isIconFamily(inFamily: String): Boolean = inFamily in mIconFamilies
|
||||||
|
|
||||||
val families: Set<String> get() = fFonts.keys
|
val families: Set<String> get() = mFonts.keys
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@ package androidx.compose.ui.text
|
|||||||
|
|
||||||
import kotlin.experimental.ExperimentalNativeApi
|
import kotlin.experimental.ExperimentalNativeApi
|
||||||
|
|
||||||
// VENDOR-BASE: compose/ui/ui-text/src/skikoMain/kotlin/androidx/compose/ui/text/FontRasterizationSettings.skiko.kt @ v1.12.0
|
// VENDOR-BASE: compose/ui/ui-text/src/skikoMain/kotlin/androidx/compose/ui/text/FontRasterizationSettings.skiko.kt @ v1.12.1
|
||||||
|
|
||||||
// ==================
|
// ==================
|
||||||
// MARK: FontRasterizationSettings native actual (Skia-free)
|
// MARK: FontRasterizationSettings native actual (Skia-free)
|
||||||
|
|||||||
+111
-146
@@ -1370,17 +1370,6 @@ abstract interface androidx.compose.ui/UiMediaScope { // androidx.compose.ui/UiM
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract interface com.compose.sdl.renderer.skia/SkiaBridge { // com.compose.sdl.renderer.skia/SkiaBridge|null[0]
|
|
||||||
abstract val canvas // com.compose.sdl.renderer.skia/SkiaBridge.canvas|{}canvas[0]
|
|
||||||
abstract fun <get-canvas>(): org.jetbrains.skia/Canvas // com.compose.sdl.renderer.skia/SkiaBridge.canvas.<get-canvas>|<get-canvas>(){}[0]
|
|
||||||
|
|
||||||
abstract fun destroy() // com.compose.sdl.renderer.skia/SkiaBridge.destroy|destroy(){}[0]
|
|
||||||
abstract fun ensureSize(kotlin/Int, kotlin/Int): kotlin/Boolean // com.compose.sdl.renderer.skia/SkiaBridge.ensureSize|ensureSize(kotlin.Int;kotlin.Int){}[0]
|
|
||||||
abstract fun present() // com.compose.sdl.renderer.skia/SkiaBridge.present|present(){}[0]
|
|
||||||
abstract fun snapshot(): org.jetbrains.skia/Image? // com.compose.sdl.renderer.skia/SkiaBridge.snapshot|snapshot(){}[0]
|
|
||||||
abstract fun snapshotBgra(): kotlin/Triple<kotlin/Int, kotlin/Int, kotlin/ByteArray>? // com.compose.sdl.renderer.skia/SkiaBridge.snapshotBgra|snapshotBgra(){}[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract interface com.compose.sdl/ComposeWindowScope { // com.compose.sdl/ComposeWindowScope|null[0]
|
abstract interface com.compose.sdl/ComposeWindowScope { // com.compose.sdl/ComposeWindowScope|null[0]
|
||||||
abstract val window // com.compose.sdl/ComposeWindowScope.window|{}window[0]
|
abstract val window // com.compose.sdl/ComposeWindowScope.window|{}window[0]
|
||||||
abstract fun <get-window>(): com.compose.sdl/ComposeNativeWindow // com.compose.sdl/ComposeWindowScope.window.<get-window>|<get-window>(){}[0]
|
abstract fun <get-window>(): com.compose.sdl/ComposeNativeWindow // com.compose.sdl/ComposeWindowScope.window.<get-window>|<get-window>(){}[0]
|
||||||
@@ -1392,10 +1381,10 @@ abstract interface com.compose.sdl/RenderBackend { // com.compose.sdl/RenderBack
|
|||||||
|
|
||||||
abstract fun beginFrame(kotlin/Float) // com.compose.sdl/RenderBackend.beginFrame|beginFrame(kotlin.Float){}[0]
|
abstract fun beginFrame(kotlin/Float) // com.compose.sdl/RenderBackend.beginFrame|beginFrame(kotlin.Float){}[0]
|
||||||
abstract fun destroy() // com.compose.sdl/RenderBackend.destroy|destroy(){}[0]
|
abstract fun destroy() // com.compose.sdl/RenderBackend.destroy|destroy(){}[0]
|
||||||
|
abstract fun drawRoot(kotlin/Function1<androidx.compose.ui.graphics/Canvas, kotlin/Unit>) // com.compose.sdl/RenderBackend.drawRoot|drawRoot(kotlin.Function1<androidx.compose.ui.graphics.Canvas,kotlin.Unit>){}[0]
|
||||||
abstract fun endFrame() // com.compose.sdl/RenderBackend.endFrame|endFrame(){}[0]
|
abstract fun endFrame() // com.compose.sdl/RenderBackend.endFrame|endFrame(){}[0]
|
||||||
abstract fun ensureSize(kotlin/Int, kotlin/Int): kotlin/Boolean // com.compose.sdl/RenderBackend.ensureSize|ensureSize(kotlin.Int;kotlin.Int){}[0]
|
abstract fun ensureSize(kotlin/Int, kotlin/Int): kotlin/Boolean // com.compose.sdl/RenderBackend.ensureSize|ensureSize(kotlin.Int;kotlin.Int){}[0]
|
||||||
abstract fun snapshotBgra(): kotlin/Triple<kotlin/Int, kotlin/Int, kotlin/ByteArray>? // com.compose.sdl/RenderBackend.snapshotBgra|snapshotBgra(){}[0]
|
abstract fun snapshotBgra(): kotlin/Triple<kotlin/Int, kotlin/Int, kotlin/ByteArray>? // com.compose.sdl/RenderBackend.snapshotBgra|snapshotBgra(){}[0]
|
||||||
open fun drawRoot(kotlin/Function1<androidx.compose.ui.graphics/Canvas, kotlin/Unit>) // com.compose.sdl/RenderBackend.drawRoot|drawRoot(kotlin.Function1<androidx.compose.ui.graphics.Canvas,kotlin.Unit>){}[0]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed interface androidx.compose.ui.autofill/ContentDataType { // androidx.compose.ui.autofill/ContentDataType|null[0]
|
sealed interface androidx.compose.ui.autofill/ContentDataType { // androidx.compose.ui.autofill/ContentDataType|null[0]
|
||||||
@@ -2788,23 +2777,6 @@ final class androidx.compose.ui/CombinedModifier : androidx.compose.ui/Modifier
|
|||||||
final fun toString(): kotlin/String // androidx.compose.ui/CombinedModifier.toString|toString(){}[0]
|
final fun toString(): kotlin/String // androidx.compose.ui/CombinedModifier.toString|toString(){}[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
final class com.compose.sdl.input/LegacyPointerEvent { // com.compose.sdl.input/LegacyPointerEvent|null[0]
|
|
||||||
constructor <init>(kotlin/Float, kotlin/Float, androidx.compose.ui.input.pointer/PointerEventType, androidx.compose.ui.input.pointer/PointerButton = ...) // com.compose.sdl.input/LegacyPointerEvent.<init>|<init>(kotlin.Float;kotlin.Float;androidx.compose.ui.input.pointer.PointerEventType;androidx.compose.ui.input.pointer.PointerButton){}[0]
|
|
||||||
|
|
||||||
final val button // com.compose.sdl.input/LegacyPointerEvent.button|{}button[0]
|
|
||||||
final fun <get-button>(): androidx.compose.ui.input.pointer/PointerButton // com.compose.sdl.input/LegacyPointerEvent.button.<get-button>|<get-button>(){}[0]
|
|
||||||
final val type // com.compose.sdl.input/LegacyPointerEvent.type|{}type[0]
|
|
||||||
final fun <get-type>(): androidx.compose.ui.input.pointer/PointerEventType // com.compose.sdl.input/LegacyPointerEvent.type.<get-type>|<get-type>(){}[0]
|
|
||||||
final val x // com.compose.sdl.input/LegacyPointerEvent.x|{}x[0]
|
|
||||||
final fun <get-x>(): kotlin/Float // com.compose.sdl.input/LegacyPointerEvent.x.<get-x>|<get-x>(){}[0]
|
|
||||||
final val y // com.compose.sdl.input/LegacyPointerEvent.y|{}y[0]
|
|
||||||
final fun <get-y>(): kotlin/Float // com.compose.sdl.input/LegacyPointerEvent.y.<get-y>|<get-y>(){}[0]
|
|
||||||
|
|
||||||
final fun equals(kotlin/Any?): kotlin/Boolean // com.compose.sdl.input/LegacyPointerEvent.equals|equals(kotlin.Any?){}[0]
|
|
||||||
final fun hashCode(): kotlin/Int // com.compose.sdl.input/LegacyPointerEvent.hashCode|hashCode(){}[0]
|
|
||||||
final fun toString(): kotlin/String // com.compose.sdl.input/LegacyPointerEvent.toString|toString(){}[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
final class com.compose.sdl.node/ComposeRootHost { // com.compose.sdl.node/ComposeRootHost|null[0]
|
final class com.compose.sdl.node/ComposeRootHost { // com.compose.sdl.node/ComposeRootHost|null[0]
|
||||||
constructor <init>(kotlin/Float = ...) // com.compose.sdl.node/ComposeRootHost.<init>|<init>(kotlin.Float){}[0]
|
constructor <init>(kotlin/Float = ...) // com.compose.sdl.node/ComposeRootHost.<init>|<init>(kotlin.Float){}[0]
|
||||||
|
|
||||||
@@ -2850,37 +2822,12 @@ final class com.compose.sdl.node/ComposeRootHost { // com.compose.sdl.node/Compo
|
|||||||
final fun setWindowFocused(kotlin/Boolean) // com.compose.sdl.node/ComposeRootHost.setWindowFocused|setWindowFocused(kotlin.Boolean){}[0]
|
final fun setWindowFocused(kotlin/Boolean) // com.compose.sdl.node/ComposeRootHost.setWindowFocused|setWindowFocused(kotlin.Boolean){}[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
final class com.compose.sdl.renderer.skia/SkiaSurfaceBridge : com.compose.sdl.renderer.skia/SkiaBridge { // com.compose.sdl.renderer.skia/SkiaSurfaceBridge|null[0]
|
|
||||||
constructor <init>(com.compose.sdl/SDL3Backend) // com.compose.sdl.renderer.skia/SkiaSurfaceBridge.<init>|<init>(com.compose.sdl.SDL3Backend){}[0]
|
|
||||||
|
|
||||||
final val canvas // com.compose.sdl.renderer.skia/SkiaSurfaceBridge.canvas|{}canvas[0]
|
|
||||||
final fun <get-canvas>(): org.jetbrains.skia/Canvas // com.compose.sdl.renderer.skia/SkiaSurfaceBridge.canvas.<get-canvas>|<get-canvas>(){}[0]
|
|
||||||
final val height // com.compose.sdl.renderer.skia/SkiaSurfaceBridge.height|{}height[0]
|
|
||||||
final fun <get-height>(): kotlin/Int // com.compose.sdl.renderer.skia/SkiaSurfaceBridge.height.<get-height>|<get-height>(){}[0]
|
|
||||||
final val width // com.compose.sdl.renderer.skia/SkiaSurfaceBridge.width|{}width[0]
|
|
||||||
final fun <get-width>(): kotlin/Int // com.compose.sdl.renderer.skia/SkiaSurfaceBridge.width.<get-width>|<get-width>(){}[0]
|
|
||||||
|
|
||||||
final fun destroy() // com.compose.sdl.renderer.skia/SkiaSurfaceBridge.destroy|destroy(){}[0]
|
|
||||||
final fun ensureSize(kotlin/Int, kotlin/Int): kotlin/Boolean // com.compose.sdl.renderer.skia/SkiaSurfaceBridge.ensureSize|ensureSize(kotlin.Int;kotlin.Int){}[0]
|
|
||||||
final fun present() // com.compose.sdl.renderer.skia/SkiaSurfaceBridge.present|present(){}[0]
|
|
||||||
final fun snapshot(): org.jetbrains.skia/Image? // com.compose.sdl.renderer.skia/SkiaSurfaceBridge.snapshot|snapshot(){}[0]
|
|
||||||
final fun snapshotBgra(): kotlin/Triple<kotlin/Int, kotlin/Int, kotlin/ByteArray>? // com.compose.sdl.renderer.skia/SkiaSurfaceBridge.snapshotBgra|snapshotBgra(){}[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
final class com.compose.sdl.window/PopupExitHandle { // com.compose.sdl.window/PopupExitHandle|null[0]
|
|
||||||
final val isExiting // com.compose.sdl.window/PopupExitHandle.isExiting|{}isExiting[0]
|
|
||||||
final fun <get-isExiting>(): androidx.compose.runtime/State<kotlin/Boolean> // com.compose.sdl.window/PopupExitHandle.isExiting.<get-isExiting>|<get-isExiting>(){}[0]
|
|
||||||
|
|
||||||
final fun enableExitTransition() // com.compose.sdl.window/PopupExitHandle.enableExitTransition|enableExitTransition(){}[0]
|
|
||||||
final fun finish() // com.compose.sdl.window/PopupExitHandle.finish|finish(){}[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
final class com.compose.sdl.window/PopupHostState { // com.compose.sdl.window/PopupHostState|null[0]
|
final class com.compose.sdl.window/PopupHostState { // com.compose.sdl.window/PopupHostState|null[0]
|
||||||
final fun notifyOutsidePress(kotlin/Int, kotlin/Int) // com.compose.sdl.window/PopupHostState.notifyOutsidePress|notifyOutsidePress(kotlin.Int;kotlin.Int){}[0]
|
final fun notifyOutsidePress(kotlin/Int, kotlin/Int) // com.compose.sdl.window/PopupHostState.notifyOutsidePress|notifyOutsidePress(kotlin.Int;kotlin.Int){}[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
final class com.compose.sdl/ComposeNativeWindow { // com.compose.sdl/ComposeNativeWindow|null[0]
|
final class com.compose.sdl/ComposeNativeWindow { // com.compose.sdl/ComposeNativeWindow|null[0]
|
||||||
constructor <init>(com.compose.sdl/SDL3Backend, com.compose.sdl/GpuMode, kotlin/String) // com.compose.sdl/ComposeNativeWindow.<init>|<init>(com.compose.sdl.SDL3Backend;com.compose.sdl.GpuMode;kotlin.String){}[0]
|
constructor <init>(com.compose.sdl/Sdl3Backend, com.compose.sdl/GpuMode, kotlin/String) // com.compose.sdl/ComposeNativeWindow.<init>|<init>(com.compose.sdl.Sdl3Backend;com.compose.sdl.GpuMode;kotlin.String){}[0]
|
||||||
|
|
||||||
final val fps // com.compose.sdl/ComposeNativeWindow.fps|{}fps[0]
|
final val fps // com.compose.sdl/ComposeNativeWindow.fps|{}fps[0]
|
||||||
final fun <get-fps>(): kotlin/Int // com.compose.sdl/ComposeNativeWindow.fps.<get-fps>|<get-fps>(){}[0]
|
final fun <get-fps>(): kotlin/Int // com.compose.sdl/ComposeNativeWindow.fps.<get-fps>|<get-fps>(){}[0]
|
||||||
@@ -2888,14 +2835,24 @@ final class com.compose.sdl/ComposeNativeWindow { // com.compose.sdl/ComposeNati
|
|||||||
final fun <get-gpuMode>(): com.compose.sdl/GpuMode // com.compose.sdl/ComposeNativeWindow.gpuMode.<get-gpuMode>|<get-gpuMode>(){}[0]
|
final fun <get-gpuMode>(): com.compose.sdl/GpuMode // com.compose.sdl/ComposeNativeWindow.gpuMode.<get-gpuMode>|<get-gpuMode>(){}[0]
|
||||||
final val height // com.compose.sdl/ComposeNativeWindow.height|{}height[0]
|
final val height // com.compose.sdl/ComposeNativeWindow.height|{}height[0]
|
||||||
final fun <get-height>(): kotlin/Int // com.compose.sdl/ComposeNativeWindow.height.<get-height>|<get-height>(){}[0]
|
final fun <get-height>(): kotlin/Int // com.compose.sdl/ComposeNativeWindow.height.<get-height>|<get-height>(){}[0]
|
||||||
|
final val isAlwaysOnTop // com.compose.sdl/ComposeNativeWindow.isAlwaysOnTop|{}isAlwaysOnTop[0]
|
||||||
|
final fun <get-isAlwaysOnTop>(): kotlin/Boolean // com.compose.sdl/ComposeNativeWindow.isAlwaysOnTop.<get-isAlwaysOnTop>|<get-isAlwaysOnTop>(){}[0]
|
||||||
final val isCloseRequested // com.compose.sdl/ComposeNativeWindow.isCloseRequested|{}isCloseRequested[0]
|
final val isCloseRequested // com.compose.sdl/ComposeNativeWindow.isCloseRequested|{}isCloseRequested[0]
|
||||||
final fun <get-isCloseRequested>(): kotlin/Boolean // com.compose.sdl/ComposeNativeWindow.isCloseRequested.<get-isCloseRequested>|<get-isCloseRequested>(){}[0]
|
final fun <get-isCloseRequested>(): kotlin/Boolean // com.compose.sdl/ComposeNativeWindow.isCloseRequested.<get-isCloseRequested>|<get-isCloseRequested>(){}[0]
|
||||||
|
final val isEnabled // com.compose.sdl/ComposeNativeWindow.isEnabled|{}isEnabled[0]
|
||||||
|
final fun <get-isEnabled>(): kotlin/Boolean // com.compose.sdl/ComposeNativeWindow.isEnabled.<get-isEnabled>|<get-isEnabled>(){}[0]
|
||||||
|
final val isFocusable // com.compose.sdl/ComposeNativeWindow.isFocusable|{}isFocusable[0]
|
||||||
|
final fun <get-isFocusable>(): kotlin/Boolean // com.compose.sdl/ComposeNativeWindow.isFocusable.<get-isFocusable>|<get-isFocusable>(){}[0]
|
||||||
final val isFullscreen // com.compose.sdl/ComposeNativeWindow.isFullscreen|{}isFullscreen[0]
|
final val isFullscreen // com.compose.sdl/ComposeNativeWindow.isFullscreen|{}isFullscreen[0]
|
||||||
final fun <get-isFullscreen>(): kotlin/Boolean // com.compose.sdl/ComposeNativeWindow.isFullscreen.<get-isFullscreen>|<get-isFullscreen>(){}[0]
|
final fun <get-isFullscreen>(): kotlin/Boolean // com.compose.sdl/ComposeNativeWindow.isFullscreen.<get-isFullscreen>|<get-isFullscreen>(){}[0]
|
||||||
final val isMaximized // com.compose.sdl/ComposeNativeWindow.isMaximized|{}isMaximized[0]
|
final val isMaximized // com.compose.sdl/ComposeNativeWindow.isMaximized|{}isMaximized[0]
|
||||||
final fun <get-isMaximized>(): kotlin/Boolean // com.compose.sdl/ComposeNativeWindow.isMaximized.<get-isMaximized>|<get-isMaximized>(){}[0]
|
final fun <get-isMaximized>(): kotlin/Boolean // com.compose.sdl/ComposeNativeWindow.isMaximized.<get-isMaximized>|<get-isMaximized>(){}[0]
|
||||||
final val isMinimized // com.compose.sdl/ComposeNativeWindow.isMinimized|{}isMinimized[0]
|
final val isMinimized // com.compose.sdl/ComposeNativeWindow.isMinimized|{}isMinimized[0]
|
||||||
final fun <get-isMinimized>(): kotlin/Boolean // com.compose.sdl/ComposeNativeWindow.isMinimized.<get-isMinimized>|<get-isMinimized>(){}[0]
|
final fun <get-isMinimized>(): kotlin/Boolean // com.compose.sdl/ComposeNativeWindow.isMinimized.<get-isMinimized>|<get-isMinimized>(){}[0]
|
||||||
|
final val isResizable // com.compose.sdl/ComposeNativeWindow.isResizable|{}isResizable[0]
|
||||||
|
final fun <get-isResizable>(): kotlin/Boolean // com.compose.sdl/ComposeNativeWindow.isResizable.<get-isResizable>|<get-isResizable>(){}[0]
|
||||||
|
final val isUndecorated // com.compose.sdl/ComposeNativeWindow.isUndecorated|{}isUndecorated[0]
|
||||||
|
final fun <get-isUndecorated>(): kotlin/Boolean // com.compose.sdl/ComposeNativeWindow.isUndecorated.<get-isUndecorated>|<get-isUndecorated>(){}[0]
|
||||||
final val pixelDensity // com.compose.sdl/ComposeNativeWindow.pixelDensity|{}pixelDensity[0]
|
final val pixelDensity // com.compose.sdl/ComposeNativeWindow.pixelDensity|{}pixelDensity[0]
|
||||||
final fun <get-pixelDensity>(): kotlin/Float // com.compose.sdl/ComposeNativeWindow.pixelDensity.<get-pixelDensity>|<get-pixelDensity>(){}[0]
|
final fun <get-pixelDensity>(): kotlin/Float // com.compose.sdl/ComposeNativeWindow.pixelDensity.<get-pixelDensity>|<get-pixelDensity>(){}[0]
|
||||||
final val pixelHeight // com.compose.sdl/ComposeNativeWindow.pixelHeight|{}pixelHeight[0]
|
final val pixelHeight // com.compose.sdl/ComposeNativeWindow.pixelHeight|{}pixelHeight[0]
|
||||||
@@ -2915,50 +2872,79 @@ final class com.compose.sdl/ComposeNativeWindow { // com.compose.sdl/ComposeNati
|
|||||||
final fun minimize() // com.compose.sdl/ComposeNativeWindow.minimize|minimize(){}[0]
|
final fun minimize() // com.compose.sdl/ComposeNativeWindow.minimize|minimize(){}[0]
|
||||||
final fun onResized() // com.compose.sdl/ComposeNativeWindow.onResized|onResized(){}[0]
|
final fun onResized() // com.compose.sdl/ComposeNativeWindow.onResized|onResized(){}[0]
|
||||||
final fun raise() // com.compose.sdl/ComposeNativeWindow.raise|raise(){}[0]
|
final fun raise() // com.compose.sdl/ComposeNativeWindow.raise|raise(){}[0]
|
||||||
|
final fun rawSdlHandles(): com.compose.sdl/RawSdlHandles // com.compose.sdl/ComposeNativeWindow.rawSdlHandles|rawSdlHandles(){}[0]
|
||||||
final fun requestCloseFromUser(): kotlin/Boolean // com.compose.sdl/ComposeNativeWindow.requestCloseFromUser|requestCloseFromUser(){}[0]
|
final fun requestCloseFromUser(): kotlin/Boolean // com.compose.sdl/ComposeNativeWindow.requestCloseFromUser|requestCloseFromUser(){}[0]
|
||||||
final fun restore() // com.compose.sdl/ComposeNativeWindow.restore|restore(){}[0]
|
final fun restore() // com.compose.sdl/ComposeNativeWindow.restore|restore(){}[0]
|
||||||
|
final fun setAlwaysOnTop(kotlin/Boolean) // com.compose.sdl/ComposeNativeWindow.setAlwaysOnTop|setAlwaysOnTop(kotlin.Boolean){}[0]
|
||||||
|
final fun setEnabled(kotlin/Boolean) // com.compose.sdl/ComposeNativeWindow.setEnabled|setEnabled(kotlin.Boolean){}[0]
|
||||||
|
final fun setFocusable(kotlin/Boolean) // com.compose.sdl/ComposeNativeWindow.setFocusable|setFocusable(kotlin.Boolean){}[0]
|
||||||
final fun setFullscreen(kotlin/Boolean) // com.compose.sdl/ComposeNativeWindow.setFullscreen|setFullscreen(kotlin.Boolean){}[0]
|
final fun setFullscreen(kotlin/Boolean) // com.compose.sdl/ComposeNativeWindow.setFullscreen|setFullscreen(kotlin.Boolean){}[0]
|
||||||
final fun setOnCloseRequest(kotlin/Function0<kotlin/Boolean>?) // com.compose.sdl/ComposeNativeWindow.setOnCloseRequest|setOnCloseRequest(kotlin.Function0<kotlin.Boolean>?){}[0]
|
final fun setOnCloseRequest(kotlin/Function0<kotlin/Boolean>?) // com.compose.sdl/ComposeNativeWindow.setOnCloseRequest|setOnCloseRequest(kotlin.Function0<kotlin.Boolean>?){}[0]
|
||||||
final fun setOnKeyShortcut(kotlin/Function1<androidx.compose.ui.input.key/KeyEvent, kotlin/Boolean>?) // com.compose.sdl/ComposeNativeWindow.setOnKeyShortcut|setOnKeyShortcut(kotlin.Function1<androidx.compose.ui.input.key.KeyEvent,kotlin.Boolean>?){}[0]
|
final fun setOnKeyShortcut(kotlin/Function1<androidx.compose.ui.input.key/KeyEvent, kotlin/Boolean>?) // com.compose.sdl/ComposeNativeWindow.setOnKeyShortcut|setOnKeyShortcut(kotlin.Function1<androidx.compose.ui.input.key.KeyEvent,kotlin.Boolean>?){}[0]
|
||||||
|
final fun setOpacity(kotlin/Float) // com.compose.sdl/ComposeNativeWindow.setOpacity|setOpacity(kotlin.Float){}[0]
|
||||||
|
final fun setResizable(kotlin/Boolean) // com.compose.sdl/ComposeNativeWindow.setResizable|setResizable(kotlin.Boolean){}[0]
|
||||||
final fun setSize(kotlin/Int, kotlin/Int) // com.compose.sdl/ComposeNativeWindow.setSize|setSize(kotlin.Int;kotlin.Int){}[0]
|
final fun setSize(kotlin/Int, kotlin/Int) // com.compose.sdl/ComposeNativeWindow.setSize|setSize(kotlin.Int;kotlin.Int){}[0]
|
||||||
final fun setTitle(kotlin/String) // com.compose.sdl/ComposeNativeWindow.setTitle|setTitle(kotlin.String){}[0]
|
final fun setTitle(kotlin/String) // com.compose.sdl/ComposeNativeWindow.setTitle|setTitle(kotlin.String){}[0]
|
||||||
|
final fun setUndecorated(kotlin/Boolean) // com.compose.sdl/ComposeNativeWindow.setUndecorated|setUndecorated(kotlin.Boolean){}[0]
|
||||||
final fun toggleFullscreen() // com.compose.sdl/ComposeNativeWindow.toggleFullscreen|toggleFullscreen(){}[0]
|
final fun toggleFullscreen() // com.compose.sdl/ComposeNativeWindow.toggleFullscreen|toggleFullscreen(){}[0]
|
||||||
final fun updateFps(kotlin/Int) // com.compose.sdl/ComposeNativeWindow.updateFps|updateFps(kotlin.Int){}[0]
|
final fun updateFps(kotlin/Int) // com.compose.sdl/ComposeNativeWindow.updateFps|updateFps(kotlin.Int){}[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
final class com.compose.sdl/SDL3Backend { // com.compose.sdl/SDL3Backend|null[0]
|
final class com.compose.sdl/RawSdlHandles { // com.compose.sdl/RawSdlHandles|null[0]
|
||||||
constructor <init>(kotlin/String = ..., kotlin/Int = ..., kotlin/Int = ..., com.compose.sdl/GpuMode = ..., kotlin.collections/List<kotlin/String> = ..., kotlin.collections/List<kotlin/String> = ...) // com.compose.sdl/SDL3Backend.<init>|<init>(kotlin.String;kotlin.Int;kotlin.Int;com.compose.sdl.GpuMode;kotlin.collections.List<kotlin.String>;kotlin.collections.List<kotlin.String>){}[0]
|
constructor <init>(kotlinx.cinterop/CPointer<out kotlinx.cinterop/CPointed>?, kotlinx.cinterop/CPointer<out kotlinx.cinterop/CPointed>?, kotlinx.cinterop/CPointer<out kotlinx.cinterop/CPointed>?, kotlinx.cinterop/CPointer<out kotlinx.cinterop/CPointed>?) // com.compose.sdl/RawSdlHandles.<init>|<init>(kotlinx.cinterop.CPointer<out|kotlinx.cinterop.CPointed>?;kotlinx.cinterop.CPointer<out|kotlinx.cinterop.CPointed>?;kotlinx.cinterop.CPointer<out|kotlinx.cinterop.CPointed>?;kotlinx.cinterop.CPointer<out|kotlinx.cinterop.CPointed>?){}[0]
|
||||||
|
|
||||||
final val gpuMode // com.compose.sdl/SDL3Backend.gpuMode|{}gpuMode[0]
|
final val glContext // com.compose.sdl/RawSdlHandles.glContext|{}glContext[0]
|
||||||
final fun <get-gpuMode>(): com.compose.sdl/GpuMode // com.compose.sdl/SDL3Backend.gpuMode.<get-gpuMode>|<get-gpuMode>(){}[0]
|
final fun <get-glContext>(): kotlinx.cinterop/CPointer<out kotlinx.cinterop/CPointed>? // com.compose.sdl/RawSdlHandles.glContext.<get-glContext>|<get-glContext>(){}[0]
|
||||||
final val pixelDensity // com.compose.sdl/SDL3Backend.pixelDensity|{}pixelDensity[0]
|
final val metalView // com.compose.sdl/RawSdlHandles.metalView|{}metalView[0]
|
||||||
final fun <get-pixelDensity>(): kotlin/Float // com.compose.sdl/SDL3Backend.pixelDensity.<get-pixelDensity>|<get-pixelDensity>(){}[0]
|
final fun <get-metalView>(): kotlinx.cinterop/CPointer<out kotlinx.cinterop/CPointed>? // com.compose.sdl/RawSdlHandles.metalView.<get-metalView>|<get-metalView>(){}[0]
|
||||||
final val windowId // com.compose.sdl/SDL3Backend.windowId|{}windowId[0]
|
final val renderer // com.compose.sdl/RawSdlHandles.renderer|{}renderer[0]
|
||||||
final fun <get-windowId>(): kotlin/UInt // com.compose.sdl/SDL3Backend.windowId.<get-windowId>|<get-windowId>(){}[0]
|
final fun <get-renderer>(): kotlinx.cinterop/CPointer<out kotlinx.cinterop/CPointed>? // com.compose.sdl/RawSdlHandles.renderer.<get-renderer>|<get-renderer>(){}[0]
|
||||||
|
final val window // com.compose.sdl/RawSdlHandles.window|{}window[0]
|
||||||
|
final fun <get-window>(): kotlinx.cinterop/CPointer<out kotlinx.cinterop/CPointed>? // com.compose.sdl/RawSdlHandles.window.<get-window>|<get-window>(){}[0]
|
||||||
|
|
||||||
final var glContext // com.compose.sdl/SDL3Backend.glContext|{}glContext[0]
|
final fun component1(): kotlinx.cinterop/CPointer<out kotlinx.cinterop/CPointed>? // com.compose.sdl/RawSdlHandles.component1|component1(){}[0]
|
||||||
final fun <get-glContext>(): kotlinx.cinterop/CPointer<out kotlinx.cinterop/CPointed>? // com.compose.sdl/SDL3Backend.glContext.<get-glContext>|<get-glContext>(){}[0]
|
final fun component2(): kotlinx.cinterop/CPointer<out kotlinx.cinterop/CPointed>? // com.compose.sdl/RawSdlHandles.component2|component2(){}[0]
|
||||||
final var metalView // com.compose.sdl/SDL3Backend.metalView|{}metalView[0]
|
final fun component3(): kotlinx.cinterop/CPointer<out kotlinx.cinterop/CPointed>? // com.compose.sdl/RawSdlHandles.component3|component3(){}[0]
|
||||||
final fun <get-metalView>(): kotlinx.cinterop/CPointer<out kotlinx.cinterop/CPointed>? // com.compose.sdl/SDL3Backend.metalView.<get-metalView>|<get-metalView>(){}[0]
|
final fun component4(): kotlinx.cinterop/CPointer<out kotlinx.cinterop/CPointed>? // com.compose.sdl/RawSdlHandles.component4|component4(){}[0]
|
||||||
final var pixelHeight // com.compose.sdl/SDL3Backend.pixelHeight|{}pixelHeight[0]
|
final fun copy(kotlinx.cinterop/CPointer<out kotlinx.cinterop/CPointed>? = ..., kotlinx.cinterop/CPointer<out kotlinx.cinterop/CPointed>? = ..., kotlinx.cinterop/CPointer<out kotlinx.cinterop/CPointed>? = ..., kotlinx.cinterop/CPointer<out kotlinx.cinterop/CPointed>? = ...): com.compose.sdl/RawSdlHandles // com.compose.sdl/RawSdlHandles.copy|copy(kotlinx.cinterop.CPointer<out|kotlinx.cinterop.CPointed>?;kotlinx.cinterop.CPointer<out|kotlinx.cinterop.CPointed>?;kotlinx.cinterop.CPointer<out|kotlinx.cinterop.CPointed>?;kotlinx.cinterop.CPointer<out|kotlinx.cinterop.CPointed>?){}[0]
|
||||||
final fun <get-pixelHeight>(): kotlin/Int // com.compose.sdl/SDL3Backend.pixelHeight.<get-pixelHeight>|<get-pixelHeight>(){}[0]
|
final fun equals(kotlin/Any?): kotlin/Boolean // com.compose.sdl/RawSdlHandles.equals|equals(kotlin.Any?){}[0]
|
||||||
final var pixelWidth // com.compose.sdl/SDL3Backend.pixelWidth|{}pixelWidth[0]
|
final fun hashCode(): kotlin/Int // com.compose.sdl/RawSdlHandles.hashCode|hashCode(){}[0]
|
||||||
final fun <get-pixelWidth>(): kotlin/Int // com.compose.sdl/SDL3Backend.pixelWidth.<get-pixelWidth>|<get-pixelWidth>(){}[0]
|
final fun toString(): kotlin/String // com.compose.sdl/RawSdlHandles.toString|toString(){}[0]
|
||||||
final var renderer // com.compose.sdl/SDL3Backend.renderer|{}renderer[0]
|
}
|
||||||
final fun <get-renderer>(): kotlinx.cinterop/CPointer<out kotlinx.cinterop/CPointed>? // com.compose.sdl/SDL3Backend.renderer.<get-renderer>|<get-renderer>(){}[0]
|
|
||||||
final var vsyncEnabled // com.compose.sdl/SDL3Backend.vsyncEnabled|{}vsyncEnabled[0]
|
|
||||||
final fun <get-vsyncEnabled>(): kotlin/Boolean // com.compose.sdl/SDL3Backend.vsyncEnabled.<get-vsyncEnabled>|<get-vsyncEnabled>(){}[0]
|
|
||||||
final var window // com.compose.sdl/SDL3Backend.window|{}window[0]
|
|
||||||
final fun <get-window>(): kotlinx.cinterop/CPointer<out kotlinx.cinterop/CPointed>? // com.compose.sdl/SDL3Backend.window.<get-window>|<get-window>(){}[0]
|
|
||||||
final var windowHeight // com.compose.sdl/SDL3Backend.windowHeight|{}windowHeight[0]
|
|
||||||
final fun <get-windowHeight>(): kotlin/Int // com.compose.sdl/SDL3Backend.windowHeight.<get-windowHeight>|<get-windowHeight>(){}[0]
|
|
||||||
final var windowWidth // com.compose.sdl/SDL3Backend.windowWidth|{}windowWidth[0]
|
|
||||||
final fun <get-windowWidth>(): kotlin/Int // com.compose.sdl/SDL3Backend.windowWidth.<get-windowWidth>|<get-windowWidth>(){}[0]
|
|
||||||
|
|
||||||
final fun applyThemeIcon() // com.compose.sdl/SDL3Backend.applyThemeIcon|applyThemeIcon(){}[0]
|
final class com.compose.sdl/Sdl3Backend { // com.compose.sdl/Sdl3Backend|null[0]
|
||||||
final fun destroy(kotlin/Boolean = ...) // com.compose.sdl/SDL3Backend.destroy|destroy(kotlin.Boolean){}[0]
|
constructor <init>(kotlin/String = ..., kotlin/Int = ..., kotlin/Int = ..., com.compose.sdl/GpuMode = ..., kotlin.collections/List<kotlin/String> = ..., kotlin.collections/List<kotlin/String> = ..., kotlin/Boolean = ..., kotlin/Boolean = ..., kotlin/Boolean = ..., kotlin/Boolean = ..., kotlin/Boolean = ...) // com.compose.sdl/Sdl3Backend.<init>|<init>(kotlin.String;kotlin.Int;kotlin.Int;com.compose.sdl.GpuMode;kotlin.collections.List<kotlin.String>;kotlin.collections.List<kotlin.String>;kotlin.Boolean;kotlin.Boolean;kotlin.Boolean;kotlin.Boolean;kotlin.Boolean){}[0]
|
||||||
final fun init(): kotlin/Boolean // com.compose.sdl/SDL3Backend.init|init(){}[0]
|
|
||||||
final fun updateWindowSize() // com.compose.sdl/SDL3Backend.updateWindowSize|updateWindowSize(){}[0]
|
final val gpuMode // com.compose.sdl/Sdl3Backend.gpuMode|{}gpuMode[0]
|
||||||
|
final fun <get-gpuMode>(): com.compose.sdl/GpuMode // com.compose.sdl/Sdl3Backend.gpuMode.<get-gpuMode>|<get-gpuMode>(){}[0]
|
||||||
|
final val pixelDensity // com.compose.sdl/Sdl3Backend.pixelDensity|{}pixelDensity[0]
|
||||||
|
final fun <get-pixelDensity>(): kotlin/Float // com.compose.sdl/Sdl3Backend.pixelDensity.<get-pixelDensity>|<get-pixelDensity>(){}[0]
|
||||||
|
final val windowId // com.compose.sdl/Sdl3Backend.windowId|{}windowId[0]
|
||||||
|
final fun <get-windowId>(): kotlin/UInt // com.compose.sdl/Sdl3Backend.windowId.<get-windowId>|<get-windowId>(){}[0]
|
||||||
|
|
||||||
|
final var glContext // com.compose.sdl/Sdl3Backend.glContext|{}glContext[0]
|
||||||
|
final fun <get-glContext>(): kotlinx.cinterop/CPointer<out kotlinx.cinterop/CPointed>? // com.compose.sdl/Sdl3Backend.glContext.<get-glContext>|<get-glContext>(){}[0]
|
||||||
|
final var metalView // com.compose.sdl/Sdl3Backend.metalView|{}metalView[0]
|
||||||
|
final fun <get-metalView>(): kotlinx.cinterop/CPointer<out kotlinx.cinterop/CPointed>? // com.compose.sdl/Sdl3Backend.metalView.<get-metalView>|<get-metalView>(){}[0]
|
||||||
|
final var pixelHeight // com.compose.sdl/Sdl3Backend.pixelHeight|{}pixelHeight[0]
|
||||||
|
final fun <get-pixelHeight>(): kotlin/Int // com.compose.sdl/Sdl3Backend.pixelHeight.<get-pixelHeight>|<get-pixelHeight>(){}[0]
|
||||||
|
final var pixelWidth // com.compose.sdl/Sdl3Backend.pixelWidth|{}pixelWidth[0]
|
||||||
|
final fun <get-pixelWidth>(): kotlin/Int // com.compose.sdl/Sdl3Backend.pixelWidth.<get-pixelWidth>|<get-pixelWidth>(){}[0]
|
||||||
|
final var renderer // com.compose.sdl/Sdl3Backend.renderer|{}renderer[0]
|
||||||
|
final fun <get-renderer>(): kotlinx.cinterop/CPointer<out kotlinx.cinterop/CPointed>? // com.compose.sdl/Sdl3Backend.renderer.<get-renderer>|<get-renderer>(){}[0]
|
||||||
|
final var vsyncEnabled // com.compose.sdl/Sdl3Backend.vsyncEnabled|{}vsyncEnabled[0]
|
||||||
|
final fun <get-vsyncEnabled>(): kotlin/Boolean // com.compose.sdl/Sdl3Backend.vsyncEnabled.<get-vsyncEnabled>|<get-vsyncEnabled>(){}[0]
|
||||||
|
final var window // com.compose.sdl/Sdl3Backend.window|{}window[0]
|
||||||
|
final fun <get-window>(): kotlinx.cinterop/CPointer<out kotlinx.cinterop/CPointed>? // com.compose.sdl/Sdl3Backend.window.<get-window>|<get-window>(){}[0]
|
||||||
|
final var windowHeight // com.compose.sdl/Sdl3Backend.windowHeight|{}windowHeight[0]
|
||||||
|
final fun <get-windowHeight>(): kotlin/Int // com.compose.sdl/Sdl3Backend.windowHeight.<get-windowHeight>|<get-windowHeight>(){}[0]
|
||||||
|
final var windowWidth // com.compose.sdl/Sdl3Backend.windowWidth|{}windowWidth[0]
|
||||||
|
final fun <get-windowWidth>(): kotlin/Int // com.compose.sdl/Sdl3Backend.windowWidth.<get-windowWidth>|<get-windowWidth>(){}[0]
|
||||||
|
|
||||||
|
final fun applyThemeIcon() // com.compose.sdl/Sdl3Backend.applyThemeIcon|applyThemeIcon(){}[0]
|
||||||
|
final fun destroy(kotlin/Boolean = ...) // com.compose.sdl/Sdl3Backend.destroy|destroy(kotlin.Boolean){}[0]
|
||||||
|
final fun init(): kotlin/Boolean // com.compose.sdl/Sdl3Backend.init|init(){}[0]
|
||||||
|
final fun updateWindowSize() // com.compose.sdl/Sdl3Backend.updateWindowSize|updateWindowSize(){}[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
final value class <#A: kotlin/Any?> androidx.compose.ui/SessionMutex { // androidx.compose.ui/SessionMutex|null[0]
|
final value class <#A: kotlin/Any?> androidx.compose.ui/SessionMutex { // androidx.compose.ui/SessionMutex|null[0]
|
||||||
@@ -4161,16 +4147,25 @@ sealed class com.compose.sdl/AppEvent { // com.compose.sdl/AppEvent|null[0]
|
|||||||
}
|
}
|
||||||
|
|
||||||
final class Pointer : com.compose.sdl/AppEvent { // com.compose.sdl/AppEvent.Pointer|null[0]
|
final class Pointer : com.compose.sdl/AppEvent { // com.compose.sdl/AppEvent.Pointer|null[0]
|
||||||
constructor <init>(com.compose.sdl.input/LegacyPointerEvent, kotlin/UInt = ...) // com.compose.sdl/AppEvent.Pointer.<init>|<init>(com.compose.sdl.input.LegacyPointerEvent;kotlin.UInt){}[0]
|
constructor <init>(kotlin/Float, kotlin/Float, androidx.compose.ui.input.pointer/PointerEventType, androidx.compose.ui.input.pointer/PointerButton = ..., kotlin/UInt = ...) // com.compose.sdl/AppEvent.Pointer.<init>|<init>(kotlin.Float;kotlin.Float;androidx.compose.ui.input.pointer.PointerEventType;androidx.compose.ui.input.pointer.PointerButton;kotlin.UInt){}[0]
|
||||||
|
|
||||||
final val event // com.compose.sdl/AppEvent.Pointer.event|{}event[0]
|
final val button // com.compose.sdl/AppEvent.Pointer.button|{}button[0]
|
||||||
final fun <get-event>(): com.compose.sdl.input/LegacyPointerEvent // com.compose.sdl/AppEvent.Pointer.event.<get-event>|<get-event>(){}[0]
|
final fun <get-button>(): androidx.compose.ui.input.pointer/PointerButton // com.compose.sdl/AppEvent.Pointer.button.<get-button>|<get-button>(){}[0]
|
||||||
|
final val type // com.compose.sdl/AppEvent.Pointer.type|{}type[0]
|
||||||
|
final fun <get-type>(): androidx.compose.ui.input.pointer/PointerEventType // com.compose.sdl/AppEvent.Pointer.type.<get-type>|<get-type>(){}[0]
|
||||||
final val windowId // com.compose.sdl/AppEvent.Pointer.windowId|{}windowId[0]
|
final val windowId // com.compose.sdl/AppEvent.Pointer.windowId|{}windowId[0]
|
||||||
final fun <get-windowId>(): kotlin/UInt // com.compose.sdl/AppEvent.Pointer.windowId.<get-windowId>|<get-windowId>(){}[0]
|
final fun <get-windowId>(): kotlin/UInt // com.compose.sdl/AppEvent.Pointer.windowId.<get-windowId>|<get-windowId>(){}[0]
|
||||||
|
final val x // com.compose.sdl/AppEvent.Pointer.x|{}x[0]
|
||||||
|
final fun <get-x>(): kotlin/Float // com.compose.sdl/AppEvent.Pointer.x.<get-x>|<get-x>(){}[0]
|
||||||
|
final val y // com.compose.sdl/AppEvent.Pointer.y|{}y[0]
|
||||||
|
final fun <get-y>(): kotlin/Float // com.compose.sdl/AppEvent.Pointer.y.<get-y>|<get-y>(){}[0]
|
||||||
|
|
||||||
final fun component1(): com.compose.sdl.input/LegacyPointerEvent // com.compose.sdl/AppEvent.Pointer.component1|component1(){}[0]
|
final fun component1(): kotlin/Float // com.compose.sdl/AppEvent.Pointer.component1|component1(){}[0]
|
||||||
final fun component2(): kotlin/UInt // com.compose.sdl/AppEvent.Pointer.component2|component2(){}[0]
|
final fun component2(): kotlin/Float // com.compose.sdl/AppEvent.Pointer.component2|component2(){}[0]
|
||||||
final fun copy(com.compose.sdl.input/LegacyPointerEvent = ..., kotlin/UInt = ...): com.compose.sdl/AppEvent.Pointer // com.compose.sdl/AppEvent.Pointer.copy|copy(com.compose.sdl.input.LegacyPointerEvent;kotlin.UInt){}[0]
|
final fun component3(): androidx.compose.ui.input.pointer/PointerEventType // com.compose.sdl/AppEvent.Pointer.component3|component3(){}[0]
|
||||||
|
final fun component4(): androidx.compose.ui.input.pointer/PointerButton // com.compose.sdl/AppEvent.Pointer.component4|component4(){}[0]
|
||||||
|
final fun component5(): kotlin/UInt // com.compose.sdl/AppEvent.Pointer.component5|component5(){}[0]
|
||||||
|
final fun copy(kotlin/Float = ..., kotlin/Float = ..., androidx.compose.ui.input.pointer/PointerEventType = ..., androidx.compose.ui.input.pointer/PointerButton = ..., kotlin/UInt = ...): com.compose.sdl/AppEvent.Pointer // com.compose.sdl/AppEvent.Pointer.copy|copy(kotlin.Float;kotlin.Float;androidx.compose.ui.input.pointer.PointerEventType;androidx.compose.ui.input.pointer.PointerButton;kotlin.UInt){}[0]
|
||||||
final fun equals(kotlin/Any?): kotlin/Boolean // com.compose.sdl/AppEvent.Pointer.equals|equals(kotlin.Any?){}[0]
|
final fun equals(kotlin/Any?): kotlin/Boolean // com.compose.sdl/AppEvent.Pointer.equals|equals(kotlin.Any?){}[0]
|
||||||
final fun hashCode(): kotlin/Int // com.compose.sdl/AppEvent.Pointer.hashCode|hashCode(){}[0]
|
final fun hashCode(): kotlin/Int // com.compose.sdl/AppEvent.Pointer.hashCode|hashCode(){}[0]
|
||||||
final fun toString(): kotlin/String // com.compose.sdl/AppEvent.Pointer.toString|toString(){}[0]
|
final fun toString(): kotlin/String // com.compose.sdl/AppEvent.Pointer.toString|toString(){}[0]
|
||||||
@@ -4293,22 +4288,23 @@ sealed class com.compose.sdl/AppEvent { // com.compose.sdl/AppEvent|null[0]
|
|||||||
}
|
}
|
||||||
|
|
||||||
sealed class com.compose.sdl/GpuMode { // com.compose.sdl/GpuMode|null[0]
|
sealed class com.compose.sdl/GpuMode { // com.compose.sdl/GpuMode|null[0]
|
||||||
sealed class Skia : com.compose.sdl/GpuMode { // com.compose.sdl/GpuMode.Skia|null[0]
|
final val isGpuAccelerated // com.compose.sdl/GpuMode.isGpuAccelerated|{}isGpuAccelerated[0]
|
||||||
final object Metal : com.compose.sdl/GpuMode.Skia { // com.compose.sdl/GpuMode.Skia.Metal|null[0]
|
final fun <get-isGpuAccelerated>(): kotlin/Boolean // com.compose.sdl/GpuMode.isGpuAccelerated.<get-isGpuAccelerated>|<get-isGpuAccelerated>(){}[0]
|
||||||
final fun toString(): kotlin/String // com.compose.sdl/GpuMode.Skia.Metal.toString|toString(){}[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
final object OpenGL : com.compose.sdl/GpuMode.Skia { // com.compose.sdl/GpuMode.Skia.OpenGL|null[0]
|
|
||||||
final fun toString(): kotlin/String // com.compose.sdl/GpuMode.Skia.OpenGL.toString|toString(){}[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final object Auto : com.compose.sdl/GpuMode { // com.compose.sdl/GpuMode.Auto|null[0]
|
final object Auto : com.compose.sdl/GpuMode { // com.compose.sdl/GpuMode.Auto|null[0]
|
||||||
final fun toString(): kotlin/String // com.compose.sdl/GpuMode.Auto.toString|toString(){}[0]
|
final fun toString(): kotlin/String // com.compose.sdl/GpuMode.Auto.toString|toString(){}[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
final object Software : com.compose.sdl/GpuMode { // com.compose.sdl/GpuMode.Software|null[0]
|
final object CpuRaster : com.compose.sdl/GpuMode { // com.compose.sdl/GpuMode.CpuRaster|null[0]
|
||||||
final fun toString(): kotlin/String // com.compose.sdl/GpuMode.Software.toString|toString(){}[0]
|
final fun toString(): kotlin/String // com.compose.sdl/GpuMode.CpuRaster.toString|toString(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final object Metal : com.compose.sdl/GpuMode { // com.compose.sdl/GpuMode.Metal|null[0]
|
||||||
|
final fun toString(): kotlin/String // com.compose.sdl/GpuMode.Metal.toString|toString(){}[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
final object OpenGL : com.compose.sdl/GpuMode { // com.compose.sdl/GpuMode.OpenGL|null[0]
|
||||||
|
final fun toString(): kotlin/String // com.compose.sdl/GpuMode.OpenGL.toString|toString(){}[0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4520,27 +4516,6 @@ final object androidx.compose.ui/ComposeUiFlags { // androidx.compose.ui/Compose
|
|||||||
final fun <set-isViewFocusFixEnabled>(kotlin/Boolean) // androidx.compose.ui/ComposeUiFlags.isViewFocusFixEnabled.<set-isViewFocusFixEnabled>|<set-isViewFocusFixEnabled>(kotlin.Boolean){}[0]
|
final fun <set-isViewFocusFixEnabled>(kotlin/Boolean) // androidx.compose.ui/ComposeUiFlags.isViewFocusFixEnabled.<set-isViewFocusFixEnabled>|<set-isViewFocusFixEnabled>(kotlin.Boolean){}[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
final object com.compose.sdl.platform/DefaultViewConfiguration : androidx.compose.ui.platform/ViewConfiguration { // com.compose.sdl.platform/DefaultViewConfiguration|null[0]
|
|
||||||
final val doubleTapMinTimeMillis // com.compose.sdl.platform/DefaultViewConfiguration.doubleTapMinTimeMillis|{}doubleTapMinTimeMillis[0]
|
|
||||||
final fun <get-doubleTapMinTimeMillis>(): kotlin/Long // com.compose.sdl.platform/DefaultViewConfiguration.doubleTapMinTimeMillis.<get-doubleTapMinTimeMillis>|<get-doubleTapMinTimeMillis>(){}[0]
|
|
||||||
final val doubleTapTimeoutMillis // com.compose.sdl.platform/DefaultViewConfiguration.doubleTapTimeoutMillis|{}doubleTapTimeoutMillis[0]
|
|
||||||
final fun <get-doubleTapTimeoutMillis>(): kotlin/Long // com.compose.sdl.platform/DefaultViewConfiguration.doubleTapTimeoutMillis.<get-doubleTapTimeoutMillis>|<get-doubleTapTimeoutMillis>(){}[0]
|
|
||||||
final val handwritingGestureLineMargin // com.compose.sdl.platform/DefaultViewConfiguration.handwritingGestureLineMargin|{}handwritingGestureLineMargin[0]
|
|
||||||
final fun <get-handwritingGestureLineMargin>(): kotlin/Float // com.compose.sdl.platform/DefaultViewConfiguration.handwritingGestureLineMargin.<get-handwritingGestureLineMargin>|<get-handwritingGestureLineMargin>(){}[0]
|
|
||||||
final val handwritingSlop // com.compose.sdl.platform/DefaultViewConfiguration.handwritingSlop|{}handwritingSlop[0]
|
|
||||||
final fun <get-handwritingSlop>(): kotlin/Float // com.compose.sdl.platform/DefaultViewConfiguration.handwritingSlop.<get-handwritingSlop>|<get-handwritingSlop>(){}[0]
|
|
||||||
final val longPressTimeoutMillis // com.compose.sdl.platform/DefaultViewConfiguration.longPressTimeoutMillis|{}longPressTimeoutMillis[0]
|
|
||||||
final fun <get-longPressTimeoutMillis>(): kotlin/Long // com.compose.sdl.platform/DefaultViewConfiguration.longPressTimeoutMillis.<get-longPressTimeoutMillis>|<get-longPressTimeoutMillis>(){}[0]
|
|
||||||
final val maximumFlingVelocity // com.compose.sdl.platform/DefaultViewConfiguration.maximumFlingVelocity|{}maximumFlingVelocity[0]
|
|
||||||
final fun <get-maximumFlingVelocity>(): kotlin/Float // com.compose.sdl.platform/DefaultViewConfiguration.maximumFlingVelocity.<get-maximumFlingVelocity>|<get-maximumFlingVelocity>(){}[0]
|
|
||||||
final val minimumFlingVelocity // com.compose.sdl.platform/DefaultViewConfiguration.minimumFlingVelocity|{}minimumFlingVelocity[0]
|
|
||||||
final fun <get-minimumFlingVelocity>(): kotlin/Float // com.compose.sdl.platform/DefaultViewConfiguration.minimumFlingVelocity.<get-minimumFlingVelocity>|<get-minimumFlingVelocity>(){}[0]
|
|
||||||
final val minimumTouchTargetSize // com.compose.sdl.platform/DefaultViewConfiguration.minimumTouchTargetSize|{}minimumTouchTargetSize[0]
|
|
||||||
final fun <get-minimumTouchTargetSize>(): androidx.compose.ui.unit/DpSize // com.compose.sdl.platform/DefaultViewConfiguration.minimumTouchTargetSize.<get-minimumTouchTargetSize>|<get-minimumTouchTargetSize>(){}[0]
|
|
||||||
final val touchSlop // com.compose.sdl.platform/DefaultViewConfiguration.touchSlop|{}touchSlop[0]
|
|
||||||
final fun <get-touchSlop>(): kotlin/Float // com.compose.sdl.platform/DefaultViewConfiguration.touchSlop.<get-touchSlop>|<get-touchSlop>(){}[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
final object com.compose.sdl.text.input/ImeBridge { // com.compose.sdl.text.input/ImeBridge|null[0]
|
final object com.compose.sdl.text.input/ImeBridge { // com.compose.sdl.text.input/ImeBridge|null[0]
|
||||||
final var onSessionActiveChange // com.compose.sdl.text.input/ImeBridge.onSessionActiveChange|{}onSessionActiveChange[0]
|
final var onSessionActiveChange // com.compose.sdl.text.input/ImeBridge.onSessionActiveChange|{}onSessionActiveChange[0]
|
||||||
final fun <get-onSessionActiveChange>(): kotlin/Function1<kotlin/Boolean, kotlin/Unit>? // com.compose.sdl.text.input/ImeBridge.onSessionActiveChange.<get-onSessionActiveChange>|<get-onSessionActiveChange>(){}[0]
|
final fun <get-onSessionActiveChange>(): kotlin/Function1<kotlin/Boolean, kotlin/Unit>? // com.compose.sdl.text.input/ImeBridge.onSessionActiveChange.<get-onSessionActiveChange>|<get-onSessionActiveChange>(){}[0]
|
||||||
@@ -4843,6 +4818,8 @@ final val androidx.compose.ui.semantics/androidx_compose_ui_semantics_SemanticsP
|
|||||||
final val androidx.compose.ui.spatial/androidx_compose_ui_spatial_RelativeLayoutBounds$stableprop // androidx.compose.ui.spatial/androidx_compose_ui_spatial_RelativeLayoutBounds$stableprop|#static{}androidx_compose_ui_spatial_RelativeLayoutBounds$stableprop[0]
|
final val androidx.compose.ui.spatial/androidx_compose_ui_spatial_RelativeLayoutBounds$stableprop // androidx.compose.ui.spatial/androidx_compose_ui_spatial_RelativeLayoutBounds$stableprop|#static{}androidx_compose_ui_spatial_RelativeLayoutBounds$stableprop[0]
|
||||||
final val androidx.compose.ui.window/androidx_compose_ui_window_DialogProperties$stableprop // androidx.compose.ui.window/androidx_compose_ui_window_DialogProperties$stableprop|#static{}androidx_compose_ui_window_DialogProperties$stableprop[0]
|
final val androidx.compose.ui.window/androidx_compose_ui_window_DialogProperties$stableprop // androidx.compose.ui.window/androidx_compose_ui_window_DialogProperties$stableprop|#static{}androidx_compose_ui_window_DialogProperties$stableprop[0]
|
||||||
final val androidx.compose.ui.window/androidx_compose_ui_window_PopupProperties$stableprop // androidx.compose.ui.window/androidx_compose_ui_window_PopupProperties$stableprop|#static{}androidx_compose_ui_window_PopupProperties$stableprop[0]
|
final val androidx.compose.ui.window/androidx_compose_ui_window_PopupProperties$stableprop // androidx.compose.ui.window/androidx_compose_ui_window_PopupProperties$stableprop|#static{}androidx_compose_ui_window_PopupProperties$stableprop[0]
|
||||||
|
final val androidx.compose.ui/LocalSystemTheme // androidx.compose.ui/LocalSystemTheme|{}LocalSystemTheme[0]
|
||||||
|
final fun <get-LocalSystemTheme>(): androidx.compose.runtime/ProvidableCompositionLocal<androidx.compose.ui/SystemTheme> // androidx.compose.ui/LocalSystemTheme.<get-LocalSystemTheme>|<get-LocalSystemTheme>(){}[0]
|
||||||
final val androidx.compose.ui/LocalUiMediaScope // androidx.compose.ui/LocalUiMediaScope|{}LocalUiMediaScope[0]
|
final val androidx.compose.ui/LocalUiMediaScope // androidx.compose.ui/LocalUiMediaScope|{}LocalUiMediaScope[0]
|
||||||
final fun <get-LocalUiMediaScope>(): androidx.compose.runtime/ProvidableCompositionLocal<androidx.compose.ui/UiMediaScope> // androidx.compose.ui/LocalUiMediaScope.<get-LocalUiMediaScope>|<get-LocalUiMediaScope>(){}[0]
|
final fun <get-LocalUiMediaScope>(): androidx.compose.runtime/ProvidableCompositionLocal<androidx.compose.ui/UiMediaScope> // androidx.compose.ui/LocalUiMediaScope.<get-LocalUiMediaScope>|<get-LocalUiMediaScope>(){}[0]
|
||||||
final val androidx.compose.ui/androidx_compose_ui_AbsoluteAlignment$stableprop // androidx.compose.ui/androidx_compose_ui_AbsoluteAlignment$stableprop|#static{}androidx_compose_ui_AbsoluteAlignment$stableprop[0]
|
final val androidx.compose.ui/androidx_compose_ui_AbsoluteAlignment$stableprop // androidx.compose.ui/androidx_compose_ui_AbsoluteAlignment$stableprop|#static{}androidx_compose_ui_AbsoluteAlignment$stableprop[0]
|
||||||
@@ -4854,7 +4831,6 @@ final val androidx.compose.ui/androidx_compose_ui_BiasAlignment_Vertical$stablep
|
|||||||
final val androidx.compose.ui/androidx_compose_ui_CombinedModifier$stableprop // androidx.compose.ui/androidx_compose_ui_CombinedModifier$stableprop|#static{}androidx_compose_ui_CombinedModifier$stableprop[0]
|
final val androidx.compose.ui/androidx_compose_ui_CombinedModifier$stableprop // androidx.compose.ui/androidx_compose_ui_CombinedModifier$stableprop|#static{}androidx_compose_ui_CombinedModifier$stableprop[0]
|
||||||
final val androidx.compose.ui/androidx_compose_ui_ComposeUiFlags$stableprop // androidx.compose.ui/androidx_compose_ui_ComposeUiFlags$stableprop|#static{}androidx_compose_ui_ComposeUiFlags$stableprop[0]
|
final val androidx.compose.ui/androidx_compose_ui_ComposeUiFlags$stableprop // androidx.compose.ui/androidx_compose_ui_ComposeUiFlags$stableprop|#static{}androidx_compose_ui_ComposeUiFlags$stableprop[0]
|
||||||
final val androidx.compose.ui/androidx_compose_ui_Modifier_Node$stableprop // androidx.compose.ui/androidx_compose_ui_Modifier_Node$stableprop|#static{}androidx_compose_ui_Modifier_Node$stableprop[0]
|
final val androidx.compose.ui/androidx_compose_ui_Modifier_Node$stableprop // androidx.compose.ui/androidx_compose_ui_Modifier_Node$stableprop|#static{}androidx_compose_ui_Modifier_Node$stableprop[0]
|
||||||
final val com.compose.sdl.input/com_compose_sdl_input_LegacyPointerEvent$stableprop // com.compose.sdl.input/com_compose_sdl_input_LegacyPointerEvent$stableprop|#static{}com_compose_sdl_input_LegacyPointerEvent$stableprop[0]
|
|
||||||
final val com.compose.sdl.layout/intOffset // com.compose.sdl.layout/intOffset|@androidx.compose.ui.layout.LayoutCoordinates{}intOffset[0]
|
final val com.compose.sdl.layout/intOffset // com.compose.sdl.layout/intOffset|@androidx.compose.ui.layout.LayoutCoordinates{}intOffset[0]
|
||||||
final fun (androidx.compose.ui.layout/LayoutCoordinates).<get-intOffset>(): androidx.compose.ui.unit/IntOffset // com.compose.sdl.layout/intOffset.<get-intOffset>|<get-intOffset>@androidx.compose.ui.layout.LayoutCoordinates(){}[0]
|
final fun (androidx.compose.ui.layout/LayoutCoordinates).<get-intOffset>(): androidx.compose.ui.unit/IntOffset // com.compose.sdl.layout/intOffset.<get-intOffset>|<get-intOffset>@androidx.compose.ui.layout.LayoutCoordinates(){}[0]
|
||||||
final val com.compose.sdl.layout/x // com.compose.sdl.layout/x|@androidx.compose.ui.layout.LayoutCoordinates{}x[0]
|
final val com.compose.sdl.layout/x // com.compose.sdl.layout/x|@androidx.compose.ui.layout.LayoutCoordinates{}x[0]
|
||||||
@@ -4862,14 +4838,9 @@ final val com.compose.sdl.layout/x // com.compose.sdl.layout/x|@androidx.compose
|
|||||||
final val com.compose.sdl.layout/y // com.compose.sdl.layout/y|@androidx.compose.ui.layout.LayoutCoordinates{}y[0]
|
final val com.compose.sdl.layout/y // com.compose.sdl.layout/y|@androidx.compose.ui.layout.LayoutCoordinates{}y[0]
|
||||||
final fun (androidx.compose.ui.layout/LayoutCoordinates).<get-y>(): kotlin/Int // com.compose.sdl.layout/y.<get-y>|<get-y>@androidx.compose.ui.layout.LayoutCoordinates(){}[0]
|
final fun (androidx.compose.ui.layout/LayoutCoordinates).<get-y>(): kotlin/Int // com.compose.sdl.layout/y.<get-y>|<get-y>@androidx.compose.ui.layout.LayoutCoordinates(){}[0]
|
||||||
final val com.compose.sdl.node/com_compose_sdl_node_ComposeRootHost$stableprop // com.compose.sdl.node/com_compose_sdl_node_ComposeRootHost$stableprop|#static{}com_compose_sdl_node_ComposeRootHost$stableprop[0]
|
final val com.compose.sdl.node/com_compose_sdl_node_ComposeRootHost$stableprop // com.compose.sdl.node/com_compose_sdl_node_ComposeRootHost$stableprop|#static{}com_compose_sdl_node_ComposeRootHost$stableprop[0]
|
||||||
final val com.compose.sdl.platform/com_compose_sdl_platform_DefaultViewConfiguration$stableprop // com.compose.sdl.platform/com_compose_sdl_platform_DefaultViewConfiguration$stableprop|#static{}com_compose_sdl_platform_DefaultViewConfiguration$stableprop[0]
|
|
||||||
final val com.compose.sdl.renderer.skia/com_compose_sdl_renderer_skia_SkiaSurfaceBridge$stableprop // com.compose.sdl.renderer.skia/com_compose_sdl_renderer_skia_SkiaSurfaceBridge$stableprop|#static{}com_compose_sdl_renderer_skia_SkiaSurfaceBridge$stableprop[0]
|
|
||||||
final val com.compose.sdl.text.input/com_compose_sdl_text_input_ImeBridge$stableprop // com.compose.sdl.text.input/com_compose_sdl_text_input_ImeBridge$stableprop|#static{}com_compose_sdl_text_input_ImeBridge$stableprop[0]
|
final val com.compose.sdl.text.input/com_compose_sdl_text_input_ImeBridge$stableprop // com.compose.sdl.text.input/com_compose_sdl_text_input_ImeBridge$stableprop|#static{}com_compose_sdl_text_input_ImeBridge$stableprop[0]
|
||||||
final val com.compose.sdl.window/LocalPopupExitHandle // com.compose.sdl.window/LocalPopupExitHandle|{}LocalPopupExitHandle[0]
|
|
||||||
final fun <get-LocalPopupExitHandle>(): androidx.compose.runtime/ProvidableCompositionLocal<com.compose.sdl.window/PopupExitHandle?> // com.compose.sdl.window/LocalPopupExitHandle.<get-LocalPopupExitHandle>|<get-LocalPopupExitHandle>(){}[0]
|
|
||||||
final val com.compose.sdl.window/LocalPopupHost // com.compose.sdl.window/LocalPopupHost|{}LocalPopupHost[0]
|
final val com.compose.sdl.window/LocalPopupHost // com.compose.sdl.window/LocalPopupHost|{}LocalPopupHost[0]
|
||||||
final fun <get-LocalPopupHost>(): androidx.compose.runtime/ProvidableCompositionLocal<com.compose.sdl.window/PopupHostState> // com.compose.sdl.window/LocalPopupHost.<get-LocalPopupHost>|<get-LocalPopupHost>(){}[0]
|
final fun <get-LocalPopupHost>(): androidx.compose.runtime/ProvidableCompositionLocal<com.compose.sdl.window/PopupHostState> // com.compose.sdl.window/LocalPopupHost.<get-LocalPopupHost>|<get-LocalPopupHost>(){}[0]
|
||||||
final val com.compose.sdl.window/com_compose_sdl_window_PopupExitHandle$stableprop // com.compose.sdl.window/com_compose_sdl_window_PopupExitHandle$stableprop|#static{}com_compose_sdl_window_PopupExitHandle$stableprop[0]
|
|
||||||
final val com.compose.sdl.window/com_compose_sdl_window_PopupHostState$stableprop // com.compose.sdl.window/com_compose_sdl_window_PopupHostState$stableprop|#static{}com_compose_sdl_window_PopupHostState$stableprop[0]
|
final val com.compose.sdl.window/com_compose_sdl_window_PopupHostState$stableprop // com.compose.sdl.window/com_compose_sdl_window_PopupHostState$stableprop|#static{}com_compose_sdl_window_PopupHostState$stableprop[0]
|
||||||
final val com.compose.sdl/LocalComposeNativeWindow // com.compose.sdl/LocalComposeNativeWindow|{}LocalComposeNativeWindow[0]
|
final val com.compose.sdl/LocalComposeNativeWindow // com.compose.sdl/LocalComposeNativeWindow|{}LocalComposeNativeWindow[0]
|
||||||
final fun <get-LocalComposeNativeWindow>(): androidx.compose.runtime/ProvidableCompositionLocal<com.compose.sdl/ComposeNativeWindow> // com.compose.sdl/LocalComposeNativeWindow.<get-LocalComposeNativeWindow>|<get-LocalComposeNativeWindow>(){}[0]
|
final fun <get-LocalComposeNativeWindow>(): androidx.compose.runtime/ProvidableCompositionLocal<com.compose.sdl/ComposeNativeWindow> // com.compose.sdl/LocalComposeNativeWindow.<get-LocalComposeNativeWindow>|<get-LocalComposeNativeWindow>(){}[0]
|
||||||
@@ -4890,11 +4861,11 @@ final val com.compose.sdl/com_compose_sdl_AppEvent_WindowResized$stableprop // c
|
|||||||
final val com.compose.sdl/com_compose_sdl_ComposeNativeWindow$stableprop // com.compose.sdl/com_compose_sdl_ComposeNativeWindow$stableprop|#static{}com_compose_sdl_ComposeNativeWindow$stableprop[0]
|
final val com.compose.sdl/com_compose_sdl_ComposeNativeWindow$stableprop // com.compose.sdl/com_compose_sdl_ComposeNativeWindow$stableprop|#static{}com_compose_sdl_ComposeNativeWindow$stableprop[0]
|
||||||
final val com.compose.sdl/com_compose_sdl_GpuMode$stableprop // com.compose.sdl/com_compose_sdl_GpuMode$stableprop|#static{}com_compose_sdl_GpuMode$stableprop[0]
|
final val com.compose.sdl/com_compose_sdl_GpuMode$stableprop // com.compose.sdl/com_compose_sdl_GpuMode$stableprop|#static{}com_compose_sdl_GpuMode$stableprop[0]
|
||||||
final val com.compose.sdl/com_compose_sdl_GpuMode_Auto$stableprop // com.compose.sdl/com_compose_sdl_GpuMode_Auto$stableprop|#static{}com_compose_sdl_GpuMode_Auto$stableprop[0]
|
final val com.compose.sdl/com_compose_sdl_GpuMode_Auto$stableprop // com.compose.sdl/com_compose_sdl_GpuMode_Auto$stableprop|#static{}com_compose_sdl_GpuMode_Auto$stableprop[0]
|
||||||
final val com.compose.sdl/com_compose_sdl_GpuMode_Skia$stableprop // com.compose.sdl/com_compose_sdl_GpuMode_Skia$stableprop|#static{}com_compose_sdl_GpuMode_Skia$stableprop[0]
|
final val com.compose.sdl/com_compose_sdl_GpuMode_CpuRaster$stableprop // com.compose.sdl/com_compose_sdl_GpuMode_CpuRaster$stableprop|#static{}com_compose_sdl_GpuMode_CpuRaster$stableprop[0]
|
||||||
final val com.compose.sdl/com_compose_sdl_GpuMode_Skia_Metal$stableprop // com.compose.sdl/com_compose_sdl_GpuMode_Skia_Metal$stableprop|#static{}com_compose_sdl_GpuMode_Skia_Metal$stableprop[0]
|
final val com.compose.sdl/com_compose_sdl_GpuMode_Metal$stableprop // com.compose.sdl/com_compose_sdl_GpuMode_Metal$stableprop|#static{}com_compose_sdl_GpuMode_Metal$stableprop[0]
|
||||||
final val com.compose.sdl/com_compose_sdl_GpuMode_Skia_OpenGL$stableprop // com.compose.sdl/com_compose_sdl_GpuMode_Skia_OpenGL$stableprop|#static{}com_compose_sdl_GpuMode_Skia_OpenGL$stableprop[0]
|
final val com.compose.sdl/com_compose_sdl_GpuMode_OpenGL$stableprop // com.compose.sdl/com_compose_sdl_GpuMode_OpenGL$stableprop|#static{}com_compose_sdl_GpuMode_OpenGL$stableprop[0]
|
||||||
final val com.compose.sdl/com_compose_sdl_GpuMode_Software$stableprop // com.compose.sdl/com_compose_sdl_GpuMode_Software$stableprop|#static{}com_compose_sdl_GpuMode_Software$stableprop[0]
|
final val com.compose.sdl/com_compose_sdl_RawSdlHandles$stableprop // com.compose.sdl/com_compose_sdl_RawSdlHandles$stableprop|#static{}com_compose_sdl_RawSdlHandles$stableprop[0]
|
||||||
final val com.compose.sdl/com_compose_sdl_SDL3Backend$stableprop // com.compose.sdl/com_compose_sdl_SDL3Backend$stableprop|#static{}com_compose_sdl_SDL3Backend$stableprop[0]
|
final val com.compose.sdl/com_compose_sdl_Sdl3Backend$stableprop // com.compose.sdl/com_compose_sdl_Sdl3Backend$stableprop|#static{}com_compose_sdl_Sdl3Backend$stableprop[0]
|
||||||
final val com.compose.sdl/com_compose_sdl_TextLayoutConfig$stableprop // com.compose.sdl/com_compose_sdl_TextLayoutConfig$stableprop|#static{}com_compose_sdl_TextLayoutConfig$stableprop[0]
|
final val com.compose.sdl/com_compose_sdl_TextLayoutConfig$stableprop // com.compose.sdl/com_compose_sdl_TextLayoutConfig$stableprop|#static{}com_compose_sdl_TextLayoutConfig$stableprop[0]
|
||||||
|
|
||||||
final var androidx.compose.ui.platform/isDebugInspectorInfoEnabled // androidx.compose.ui.platform/isDebugInspectorInfoEnabled|{}isDebugInspectorInfoEnabled[0]
|
final var androidx.compose.ui.platform/isDebugInspectorInfoEnabled // androidx.compose.ui.platform/isDebugInspectorInfoEnabled|{}isDebugInspectorInfoEnabled[0]
|
||||||
@@ -5389,16 +5360,10 @@ final fun androidx.compose.ui/androidx_compose_ui_CombinedModifier$stableprop_ge
|
|||||||
final fun androidx.compose.ui/androidx_compose_ui_ComposeUiFlags$stableprop_getter(): kotlin/Int // androidx.compose.ui/androidx_compose_ui_ComposeUiFlags$stableprop_getter|androidx_compose_ui_ComposeUiFlags$stableprop_getter(){}[0]
|
final fun androidx.compose.ui/androidx_compose_ui_ComposeUiFlags$stableprop_getter(): kotlin/Int // androidx.compose.ui/androidx_compose_ui_ComposeUiFlags$stableprop_getter|androidx_compose_ui_ComposeUiFlags$stableprop_getter(){}[0]
|
||||||
final fun androidx.compose.ui/androidx_compose_ui_Modifier_Node$stableprop_getter(): kotlin/Int // androidx.compose.ui/androidx_compose_ui_Modifier_Node$stableprop_getter|androidx_compose_ui_Modifier_Node$stableprop_getter(){}[0]
|
final fun androidx.compose.ui/androidx_compose_ui_Modifier_Node$stableprop_getter(): kotlin/Int // androidx.compose.ui/androidx_compose_ui_Modifier_Node$stableprop_getter|androidx_compose_ui_Modifier_Node$stableprop_getter(){}[0]
|
||||||
final fun androidx.compose.ui/isUiSystemInDarkTheme(androidx.compose.runtime/Composer?, kotlin/Int): kotlin/Boolean // androidx.compose.ui/isUiSystemInDarkTheme|isUiSystemInDarkTheme(androidx.compose.runtime.Composer?;kotlin.Int){}[0]
|
final fun androidx.compose.ui/isUiSystemInDarkTheme(androidx.compose.runtime/Composer?, kotlin/Int): kotlin/Boolean // androidx.compose.ui/isUiSystemInDarkTheme|isUiSystemInDarkTheme(androidx.compose.runtime.Composer?;kotlin.Int){}[0]
|
||||||
final fun com.compose.sdl.input/com_compose_sdl_input_LegacyPointerEvent$stableprop_getter(): kotlin/Int // com.compose.sdl.input/com_compose_sdl_input_LegacyPointerEvent$stableprop_getter|com_compose_sdl_input_LegacyPointerEvent$stableprop_getter(){}[0]
|
|
||||||
final fun com.compose.sdl.node/com_compose_sdl_node_ComposeRootHost$stableprop_getter(): kotlin/Int // com.compose.sdl.node/com_compose_sdl_node_ComposeRootHost$stableprop_getter|com_compose_sdl_node_ComposeRootHost$stableprop_getter(){}[0]
|
final fun com.compose.sdl.node/com_compose_sdl_node_ComposeRootHost$stableprop_getter(): kotlin/Int // com.compose.sdl.node/com_compose_sdl_node_ComposeRootHost$stableprop_getter|com_compose_sdl_node_ComposeRootHost$stableprop_getter(){}[0]
|
||||||
final fun com.compose.sdl.platform/com_compose_sdl_platform_DefaultViewConfiguration$stableprop_getter(): kotlin/Int // com.compose.sdl.platform/com_compose_sdl_platform_DefaultViewConfiguration$stableprop_getter|com_compose_sdl_platform_DefaultViewConfiguration$stableprop_getter(){}[0]
|
|
||||||
final fun com.compose.sdl.renderer.skia/com_compose_sdl_renderer_skia_SkiaSurfaceBridge$stableprop_getter(): kotlin/Int // com.compose.sdl.renderer.skia/com_compose_sdl_renderer_skia_SkiaSurfaceBridge$stableprop_getter|com_compose_sdl_renderer_skia_SkiaSurfaceBridge$stableprop_getter(){}[0]
|
|
||||||
final fun com.compose.sdl.text.input/com_compose_sdl_text_input_ImeBridge$stableprop_getter(): kotlin/Int // com.compose.sdl.text.input/com_compose_sdl_text_input_ImeBridge$stableprop_getter|com_compose_sdl_text_input_ImeBridge$stableprop_getter(){}[0]
|
final fun com.compose.sdl.text.input/com_compose_sdl_text_input_ImeBridge$stableprop_getter(): kotlin/Int // com.compose.sdl.text.input/com_compose_sdl_text_input_ImeBridge$stableprop_getter|com_compose_sdl_text_input_ImeBridge$stableprop_getter(){}[0]
|
||||||
final fun com.compose.sdl.text/registerGenericFonts() // com.compose.sdl.text/registerGenericFonts|registerGenericFonts(){}[0]
|
final fun com.compose.sdl.text/registerGenericFonts() // com.compose.sdl.text/registerGenericFonts|registerGenericFonts(){}[0]
|
||||||
final fun com.compose.sdl.window/PopupLayer(com.compose.sdl.window/PopupHostState, androidx.compose.runtime/Composer?, kotlin/Int) // com.compose.sdl.window/PopupLayer|PopupLayer(com.compose.sdl.window.PopupHostState;androidx.compose.runtime.Composer?;kotlin.Int){}[0]
|
final fun com.compose.sdl.window/PopupLayer(com.compose.sdl.window/PopupHostState, androidx.compose.runtime/Composer?, kotlin/Int) // com.compose.sdl.window/PopupLayer|PopupLayer(com.compose.sdl.window.PopupHostState;androidx.compose.runtime.Composer?;kotlin.Int){}[0]
|
||||||
final fun com.compose.sdl.window/PopupOutsideDismiss(kotlin/Int, kotlin/Int, kotlin/Int, kotlin/Int, kotlin/Function0<kotlin/Unit>, androidx.compose.runtime/Composer?, kotlin/Int) // com.compose.sdl.window/PopupOutsideDismiss|PopupOutsideDismiss(kotlin.Int;kotlin.Int;kotlin.Int;kotlin.Int;kotlin.Function0<kotlin.Unit>;androidx.compose.runtime.Composer?;kotlin.Int){}[0]
|
|
||||||
final fun com.compose.sdl.window/PositionedPopup(kotlin/Int, kotlin/Int, kotlin/Function0<kotlin/Unit>, kotlin/Function2<androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>, androidx.compose.runtime/Composer?, kotlin/Int) // com.compose.sdl.window/PositionedPopup|PositionedPopup(kotlin.Int;kotlin.Int;kotlin.Function0<kotlin.Unit>;kotlin.Function2<androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>;androidx.compose.runtime.Composer?;kotlin.Int){}[0]
|
|
||||||
final fun com.compose.sdl.window/com_compose_sdl_window_PopupExitHandle$stableprop_getter(): kotlin/Int // com.compose.sdl.window/com_compose_sdl_window_PopupExitHandle$stableprop_getter|com_compose_sdl_window_PopupExitHandle$stableprop_getter(){}[0]
|
|
||||||
final fun com.compose.sdl.window/com_compose_sdl_window_PopupHostState$stableprop_getter(): kotlin/Int // com.compose.sdl.window/com_compose_sdl_window_PopupHostState$stableprop_getter|com_compose_sdl_window_PopupHostState$stableprop_getter(){}[0]
|
final fun com.compose.sdl.window/com_compose_sdl_window_PopupHostState$stableprop_getter(): kotlin/Int // com.compose.sdl.window/com_compose_sdl_window_PopupHostState$stableprop_getter|com_compose_sdl_window_PopupHostState$stableprop_getter(){}[0]
|
||||||
final fun com.compose.sdl.window/createPopupHostState(): com.compose.sdl.window/PopupHostState // com.compose.sdl.window/createPopupHostState|createPopupHostState(){}[0]
|
final fun com.compose.sdl.window/createPopupHostState(): com.compose.sdl.window/PopupHostState // com.compose.sdl.window/createPopupHostState|createPopupHostState(){}[0]
|
||||||
final fun com.compose.sdl/appDataDir(kotlin/String, kotlin/String): kotlin/String? // com.compose.sdl/appDataDir|appDataDir(kotlin.String;kotlin.String){}[0]
|
final fun com.compose.sdl/appDataDir(kotlin/String, kotlin/String): kotlin/String? // com.compose.sdl/appDataDir|appDataDir(kotlin.String;kotlin.String){}[0]
|
||||||
@@ -5420,13 +5385,13 @@ final fun com.compose.sdl/com_compose_sdl_AppEvent_WindowResized$stableprop_gett
|
|||||||
final fun com.compose.sdl/com_compose_sdl_ComposeNativeWindow$stableprop_getter(): kotlin/Int // com.compose.sdl/com_compose_sdl_ComposeNativeWindow$stableprop_getter|com_compose_sdl_ComposeNativeWindow$stableprop_getter(){}[0]
|
final fun com.compose.sdl/com_compose_sdl_ComposeNativeWindow$stableprop_getter(): kotlin/Int // com.compose.sdl/com_compose_sdl_ComposeNativeWindow$stableprop_getter|com_compose_sdl_ComposeNativeWindow$stableprop_getter(){}[0]
|
||||||
final fun com.compose.sdl/com_compose_sdl_GpuMode$stableprop_getter(): kotlin/Int // com.compose.sdl/com_compose_sdl_GpuMode$stableprop_getter|com_compose_sdl_GpuMode$stableprop_getter(){}[0]
|
final fun com.compose.sdl/com_compose_sdl_GpuMode$stableprop_getter(): kotlin/Int // com.compose.sdl/com_compose_sdl_GpuMode$stableprop_getter|com_compose_sdl_GpuMode$stableprop_getter(){}[0]
|
||||||
final fun com.compose.sdl/com_compose_sdl_GpuMode_Auto$stableprop_getter(): kotlin/Int // com.compose.sdl/com_compose_sdl_GpuMode_Auto$stableprop_getter|com_compose_sdl_GpuMode_Auto$stableprop_getter(){}[0]
|
final fun com.compose.sdl/com_compose_sdl_GpuMode_Auto$stableprop_getter(): kotlin/Int // com.compose.sdl/com_compose_sdl_GpuMode_Auto$stableprop_getter|com_compose_sdl_GpuMode_Auto$stableprop_getter(){}[0]
|
||||||
final fun com.compose.sdl/com_compose_sdl_GpuMode_Skia$stableprop_getter(): kotlin/Int // com.compose.sdl/com_compose_sdl_GpuMode_Skia$stableprop_getter|com_compose_sdl_GpuMode_Skia$stableprop_getter(){}[0]
|
final fun com.compose.sdl/com_compose_sdl_GpuMode_CpuRaster$stableprop_getter(): kotlin/Int // com.compose.sdl/com_compose_sdl_GpuMode_CpuRaster$stableprop_getter|com_compose_sdl_GpuMode_CpuRaster$stableprop_getter(){}[0]
|
||||||
final fun com.compose.sdl/com_compose_sdl_GpuMode_Skia_Metal$stableprop_getter(): kotlin/Int // com.compose.sdl/com_compose_sdl_GpuMode_Skia_Metal$stableprop_getter|com_compose_sdl_GpuMode_Skia_Metal$stableprop_getter(){}[0]
|
final fun com.compose.sdl/com_compose_sdl_GpuMode_Metal$stableprop_getter(): kotlin/Int // com.compose.sdl/com_compose_sdl_GpuMode_Metal$stableprop_getter|com_compose_sdl_GpuMode_Metal$stableprop_getter(){}[0]
|
||||||
final fun com.compose.sdl/com_compose_sdl_GpuMode_Skia_OpenGL$stableprop_getter(): kotlin/Int // com.compose.sdl/com_compose_sdl_GpuMode_Skia_OpenGL$stableprop_getter|com_compose_sdl_GpuMode_Skia_OpenGL$stableprop_getter(){}[0]
|
final fun com.compose.sdl/com_compose_sdl_GpuMode_OpenGL$stableprop_getter(): kotlin/Int // com.compose.sdl/com_compose_sdl_GpuMode_OpenGL$stableprop_getter|com_compose_sdl_GpuMode_OpenGL$stableprop_getter(){}[0]
|
||||||
final fun com.compose.sdl/com_compose_sdl_GpuMode_Software$stableprop_getter(): kotlin/Int // com.compose.sdl/com_compose_sdl_GpuMode_Software$stableprop_getter|com_compose_sdl_GpuMode_Software$stableprop_getter(){}[0]
|
final fun com.compose.sdl/com_compose_sdl_RawSdlHandles$stableprop_getter(): kotlin/Int // com.compose.sdl/com_compose_sdl_RawSdlHandles$stableprop_getter|com_compose_sdl_RawSdlHandles$stableprop_getter(){}[0]
|
||||||
final fun com.compose.sdl/com_compose_sdl_SDL3Backend$stableprop_getter(): kotlin/Int // com.compose.sdl/com_compose_sdl_SDL3Backend$stableprop_getter|com_compose_sdl_SDL3Backend$stableprop_getter(){}[0]
|
final fun com.compose.sdl/com_compose_sdl_Sdl3Backend$stableprop_getter(): kotlin/Int // com.compose.sdl/com_compose_sdl_Sdl3Backend$stableprop_getter|com_compose_sdl_Sdl3Backend$stableprop_getter(){}[0]
|
||||||
final fun com.compose.sdl/com_compose_sdl_TextLayoutConfig$stableprop_getter(): kotlin/Int // com.compose.sdl/com_compose_sdl_TextLayoutConfig$stableprop_getter|com_compose_sdl_TextLayoutConfig$stableprop_getter(){}[0]
|
final fun com.compose.sdl/com_compose_sdl_TextLayoutConfig$stableprop_getter(): kotlin/Int // com.compose.sdl/com_compose_sdl_TextLayoutConfig$stableprop_getter|com_compose_sdl_TextLayoutConfig$stableprop_getter(){}[0]
|
||||||
final fun com.compose.sdl/createRenderBackend(com.compose.sdl/SDL3Backend, com.compose.sdl/GpuMode): com.compose.sdl/RenderBackend? // com.compose.sdl/createRenderBackend|createRenderBackend(com.compose.sdl.SDL3Backend;com.compose.sdl.GpuMode){}[0]
|
final fun com.compose.sdl/createRenderBackend(com.compose.sdl/Sdl3Backend, com.compose.sdl/GpuMode): com.compose.sdl/RenderBackend? // com.compose.sdl/createRenderBackend|createRenderBackend(com.compose.sdl.Sdl3Backend;com.compose.sdl.GpuMode){}[0]
|
||||||
final fun com.compose.sdl/fileManagerName(): kotlin/String // com.compose.sdl/fileManagerName|fileManagerName(){}[0]
|
final fun com.compose.sdl/fileManagerName(): kotlin/String // com.compose.sdl/fileManagerName|fileManagerName(){}[0]
|
||||||
final fun com.compose.sdl/hasComposeResource(kotlin/String): kotlin/Boolean // com.compose.sdl/hasComposeResource|hasComposeResource(kotlin.String){}[0]
|
final fun com.compose.sdl/hasComposeResource(kotlin/String): kotlin/Boolean // com.compose.sdl/hasComposeResource|hasComposeResource(kotlin.String){}[0]
|
||||||
final fun com.compose.sdl/injectKey(kotlin/Int, kotlin/Boolean) // com.compose.sdl/injectKey|injectKey(kotlin.Int;kotlin.Boolean){}[0]
|
final fun com.compose.sdl/injectKey(kotlin/Int, kotlin/Boolean) // com.compose.sdl/injectKey|injectKey(kotlin.Int;kotlin.Boolean){}[0]
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
* Line-for-line kept in sync; the entry in compose/ui/compose-fork.txt is
|
* Line-for-line kept in sync; the entry in compose/ui/compose-fork.txt is
|
||||||
* commented out so this file survives `scripts/compose-fork/sync.sh`.
|
* commented out so this file survives `scripts/compose-fork/sync.sh`.
|
||||||
*/
|
*/
|
||||||
// VENDOR-BASE: compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/platform/Synchronization.kt @ v1.12.0
|
// VENDOR-BASE: compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/platform/Synchronization.kt @ v1.12.1
|
||||||
|
|
||||||
package androidx.compose.ui.platform
|
package androidx.compose.ui.platform
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import androidx.compose.ui.unit.DpSize
|
|||||||
* StubOwner). Constant values match the upstream `PlatformContext.DefaultViewConfiguration`
|
* StubOwner). Constant values match the upstream `PlatformContext.DefaultViewConfiguration`
|
||||||
* (longPressTimeout=500ms, doubleTapTimeout=300ms, doubleTapMinTime=40ms, touchSlop=8f).
|
* (longPressTimeout=500ms, doubleTapTimeout=300ms, doubleTapMinTime=40ms, touchSlop=8f).
|
||||||
*/
|
*/
|
||||||
object DefaultViewConfiguration : ViewConfiguration {
|
internal object DefaultViewConfiguration : ViewConfiguration {
|
||||||
override val longPressTimeoutMillis: Long = 500
|
override val longPressTimeoutMillis: Long = 500
|
||||||
override val doubleTapTimeoutMillis: Long = 300
|
override val doubleTapTimeoutMillis: Long = 300
|
||||||
override val doubleTapMinTimeMillis: Long = 40
|
override val doubleTapMinTimeMillis: Long = 40
|
||||||
|
|||||||
@@ -98,23 +98,23 @@ class PopupHostState internal constructor() {
|
|||||||
fun contains(inX: Int, inY: Int) = inX >= x && inX < x + w && inY >= y && inY < y + h
|
fun contains(inX: Int, inY: Int) = inX >= x && inX < x + w && inY >= y && inY < y + h
|
||||||
}
|
}
|
||||||
|
|
||||||
private val fDismissers = mutableListOf<Dismisser>()
|
private val mDismissers = mutableListOf<Dismisser>()
|
||||||
|
|
||||||
internal fun setDismisser(inId: Any, inX: Int, inY: Int, inW: Int, inH: Int, inOnDismiss: () -> Unit) {
|
internal fun setDismisser(inId: Any, inX: Int, inY: Int, inW: Int, inH: Int, inOnDismiss: () -> Unit) {
|
||||||
val vD = fDismissers.firstOrNull { it.id === inId } ?: Dismisser(inId).also { fDismissers.add(it) }
|
val vD = mDismissers.firstOrNull { it.id === inId } ?: Dismisser(inId).also { mDismissers.add(it) }
|
||||||
vD.x = inX; vD.y = inY; vD.w = inW; vD.h = inH; vD.onDismiss = inOnDismiss
|
vD.x = inX; vD.y = inY; vD.w = inW; vD.h = inH; vD.onDismiss = inOnDismiss
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun removeDismisser(inId: Any) {
|
internal fun removeDismisser(inId: Any) {
|
||||||
fDismissers.removeAll { it.id === inId }
|
mDismissers.removeAll { it.id === inId }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Dismiss every registered popup whose content rect does NOT contain the
|
/** Dismiss every registered popup whose content rect does NOT contain the
|
||||||
press. Called from the window's press dispatch; never consumes the press. */
|
press. Called from the window's press dispatch; never consumes the press. */
|
||||||
fun notifyOutsidePress(inX: Int, inY: Int) {
|
fun notifyOutsidePress(inX: Int, inY: Int) {
|
||||||
if (fDismissers.isEmpty()) return
|
if (mDismissers.isEmpty()) return
|
||||||
// Copy: an onDismiss typically removes the dismisser (state write).
|
// Copy: an onDismiss typically removes the dismisser (state write).
|
||||||
for (vD in fDismissers.toList()) {
|
for (vD in mDismissers.toList()) {
|
||||||
if (vD.w > 0 && vD.h > 0 && !vD.contains(inX, inY)) vD.onDismiss()
|
if (vD.w > 0 && vD.h > 0 && !vD.contains(inX, inY)) vD.onDismiss()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,26 +139,26 @@ fun createPopupHostState(): PopupHostState = PopupHostState()
|
|||||||
the entry. The hosted content (still composed - it lives in the HOST's
|
the entry. The hosted content (still composed - it lives in the HOST's
|
||||||
composition, not the owner's) observes that, plays its animation, and MUST
|
composition, not the owner's) observes that, plays its animation, and MUST
|
||||||
end with [finish], which actually removes the entry. */
|
end with [finish], which actually removes the entry. */
|
||||||
class PopupExitHandle internal constructor(
|
internal class PopupExitHandle internal constructor(
|
||||||
private val fHost: PopupHostState, // owning host - target of finish()
|
private val mHost: PopupHostState, // owning host - target of finish()
|
||||||
private val fEntry: PopupHostState.Entry, // the entry this handle controls
|
private val mEntry: PopupHostState.Entry, // the entry this handle controls
|
||||||
) {
|
) {
|
||||||
/** True once the owning Popup left the composition and the host is waiting
|
/** True once the owning Popup left the composition and the host is waiting
|
||||||
for this entry's exit animation. Observable - recomposes the content. */
|
for this entry's exit animation. Observable - recomposes the content. */
|
||||||
val isExiting: State<Boolean> get() = fEntry.exiting
|
val isExiting: State<Boolean> get() = mEntry.exiting
|
||||||
|
|
||||||
/** Opt in to exit deferral. Idempotent; call from a SideEffect. */
|
/** Opt in to exit deferral. Idempotent; call from a SideEffect. */
|
||||||
fun enableExitTransition() { fEntry.hasExitTransition = true }
|
fun enableExitTransition() { mEntry.hasExitTransition = true }
|
||||||
|
|
||||||
/** Ends the deferral - the entry is removed from the host for real. */
|
/** Ends the deferral - the entry is removed from the host for real. */
|
||||||
fun finish() { fHost.forceRemove(fEntry.id) }
|
fun finish() { mHost.forceRemove(mEntry.id) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Per-entry handle, provided by PopupLayer around each hosted content. Null
|
/** Per-entry handle, provided by PopupLayer around each hosted content. Null
|
||||||
outside a popup layer. NB: safe to expose through the caller-locals rewrap
|
outside a popup layer. NB: safe to expose through the caller-locals rewrap
|
||||||
in Popup (CompositionLocalProvider(callerContext)) - the caller never
|
in Popup (CompositionLocalProvider(callerContext)) - the caller never
|
||||||
provides this local, so the layer's per-entry value stays visible. */
|
provides this local, so the layer's per-entry value stays visible. */
|
||||||
val LocalPopupExitHandle = staticCompositionLocalOf<PopupExitHandle?> { null }
|
internal val LocalPopupExitHandle = staticCompositionLocalOf<PopupExitHandle?> { null }
|
||||||
|
|
||||||
// ==================
|
// ==================
|
||||||
// MARK: PopupLayer
|
// MARK: PopupLayer
|
||||||
@@ -187,7 +187,7 @@ fun PopupLayer(inHost: PopupHostState) {
|
|||||||
popup host so the dismissing press is NOT consumed (it still reaches whatever
|
popup host so the dismissing press is NOT consumed (it still reaches whatever
|
||||||
is under it - no dead first click). */
|
is under it - no dead first click). */
|
||||||
@Composable
|
@Composable
|
||||||
fun PopupOutsideDismiss(inX: Int, inY: Int, inW: Int, inH: Int, onDismissRequest: () -> Unit) {
|
internal fun PopupOutsideDismiss(inX: Int, inY: Int, inW: Int, inH: Int, onDismissRequest: () -> Unit) {
|
||||||
val vHost = LocalPopupHost.current
|
val vHost = LocalPopupHost.current
|
||||||
val vId = remember { Any() }
|
val vId = remember { Any() }
|
||||||
SideEffect { vHost.setDismisser(vId, inX, inY, inW, inH, onDismissRequest) }
|
SideEffect { vHost.setDismisser(vId, inX, inY, inW, inH, onDismissRequest) }
|
||||||
@@ -203,7 +203,7 @@ fun PopupOutsideDismiss(inX: Int, inY: Int, inW: Int, inH: Int, onDismissRequest
|
|||||||
`x`/`y` are LAYOUT PIXELS (matches `LayoutCoordinates.positionInRoot`), not
|
`x`/`y` are LAYOUT PIXELS (matches `LayoutCoordinates.positionInRoot`), not
|
||||||
`Dp` - layout runs in physical pixels under the Option-B density flow. */
|
`Dp` - layout runs in physical pixels under the Option-B density flow. */
|
||||||
@Composable
|
@Composable
|
||||||
fun PositionedPopup(
|
internal fun PositionedPopup(
|
||||||
x: Int,
|
x: Int,
|
||||||
y: Int,
|
y: Int,
|
||||||
onDismissRequest: () -> Unit,
|
onDismissRequest: () -> Unit,
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ import androidx.compose.ui.geometry.Offset
|
|||||||
|
|
||||||
/* Actuals for the vendored `DragAndDrop.kt` expect classes.
|
/* Actuals for the vendored `DragAndDrop.kt` expect classes.
|
||||||
* Backed by SDL3's SDL_EVENT_DROP_* stream (file / text / begin / position /
|
* Backed by SDL3's SDL_EVENT_DROP_* stream (file / text / begin / position /
|
||||||
* complete) - see Sdl3DragAndDropOwner + SDL3EventMapper for the pump side.
|
* complete) - see Sdl3DragAndDropOwner + AppEvent.kt for the pump side.
|
||||||
*
|
*
|
||||||
* DragAndDropTransferData carries the payload a drop into the window
|
* DragAndDropTransferData carries the payload a drop into the window
|
||||||
* delivered: zero or more file paths (SDL_EVENT_DROP_FILE) plus an optional
|
* delivered: zero or more file paths (SDL_EVENT_DROP_FILE) plus an optional
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ import androidx.compose.ui.node.ModifierNodeElement
|
|||||||
|
|
||||||
/** The per-window DragAndDropManager backing ComposeOwner. Holds a root
|
/** The per-window DragAndDropManager backing ComposeOwner. Holds a root
|
||||||
* DragAndDropNode installed on the root LayoutNode via [modifier]; the SDL
|
* DragAndDropNode installed on the root LayoutNode via [modifier]; the SDL
|
||||||
* event pump (see SDL3EventMapper + ComposeWindow) drives [handleDrop] which
|
* event pump (see AppEvent.kt + ComposeWindow) drives [handleDrop] which
|
||||||
* accumulates BEGIN → FILE / TEXT / POSITION → COMPLETE into a single
|
* accumulates BEGIN → FILE / TEXT / POSITION → COMPLETE into a single
|
||||||
* DragAndDropEvent and dispatches through the node tree.
|
* DragAndDropEvent and dispatches through the node tree.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ package androidx.compose.ui.input.key
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Project [Key] actual - assigns a unique sequential Long to each named
|
* Project [Key] actual - assigns a unique sequential Long to each named
|
||||||
* key. SDL3EventMapper picks the right `Key.X` by switch on SDL scancode
|
* key. The SDL event mapper picks the right `Key.X` by switch on SDL scancode
|
||||||
* (`kKeyForScancode` in `SDL3EventMapper.kt`). Comparison works because
|
* (`kKeyForScancode` in `AppEvent.kt`). Comparison works because
|
||||||
* Key is a value class - `Key(42L) == Key(42L)`.
|
* Key is a value class - `Key(42L) == Key(42L)`.
|
||||||
*/
|
*/
|
||||||
@kotlin.jvm.JvmInline
|
@kotlin.jvm.JvmInline
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
// MANUALLY VENDORED (NON-IDEMPOTENT) from compose-multiplatform-core:
|
// MANUALLY VENDORED (NON-IDEMPOTENT) from compose-multiplatform-core:
|
||||||
// compose/ui/ui/src/skikoMain/.../node/GraphicsLayerOwnerLayer.skiko.kt
|
// compose/ui/ui/src/skikoMain/.../node/GraphicsLayerOwnerLayer.skiko.kt
|
||||||
// VENDOR-BASE: compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/node/GraphicsLayerOwnerLayer.skiko.kt @ v1.12.0
|
// VENDOR-BASE: compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/node/GraphicsLayerOwnerLayer.skiko.kt @ v1.12.1
|
||||||
// Change vs upstream: dropped the trailing `SkiaGraphicsContext.setLightingInfo`
|
// Change vs upstream: dropped the trailing `SkiaGraphicsContext.setLightingInfo`
|
||||||
// extension + LIGHT_* constants (skiko-only shadow lighting; our shadows go via
|
// extension + LIGHT_* constants (skiko-only shadow lighting; our shadows go via
|
||||||
// NativeShadowCanvas). The class body is unchanged - it is the real OwnedLayer
|
// NativeShadowCanvas). The class body is unchanged - it is the real OwnedLayer
|
||||||
|
|||||||
+17
-17
@@ -103,14 +103,14 @@ private const val kImageMime = "image/png"
|
|||||||
// call with an image). Held on nativeHeap because SDL keeps the callback alive
|
// call with an image). Held on nativeHeap because SDL keeps the callback alive
|
||||||
// until the clipboard is cleared or another SDL_SetClipboardData replaces us -
|
// until the clipboard is cleared or another SDL_SetClipboardData replaces us -
|
||||||
// a Kotlin heap reference would break as soon as the caller's coroutine
|
// a Kotlin heap reference would break as soon as the caller's coroutine
|
||||||
// returned. Read by [fClipboardDataCallback], freed by [fClipboardCleanupCallback].
|
// returned. Read by [mClipboardDataCallback], freed by [mClipboardCleanupCallback].
|
||||||
private var fOutgoingImagePtr: CPointer<ByteVar>? = null
|
private var mOutgoingImagePtr: CPointer<ByteVar>? = null
|
||||||
private var fOutgoingImageSize: Int = 0
|
private var mOutgoingImageSize: Int = 0
|
||||||
|
|
||||||
// SDL fires this on the main event thread when another app asks the clipboard
|
// SDL fires this on the main event thread when another app asks the clipboard
|
||||||
// for a MIME we advertised. We serve back the pointer + size we stashed at
|
// for a MIME we advertised. We serve back the pointer + size we stashed at
|
||||||
// SDL_SetClipboardData time. Return NULL if the MIME doesn't match.
|
// SDL_SetClipboardData time. Return NULL if the MIME doesn't match.
|
||||||
private val fClipboardDataCallback = staticCFunction {
|
private val mClipboardDataCallback = staticCFunction {
|
||||||
userdata: COpaquePointer?,
|
userdata: COpaquePointer?,
|
||||||
mimeType: CPointer<ByteVar>?,
|
mimeType: CPointer<ByteVar>?,
|
||||||
sizePtr: CPointer<platform.posix.size_tVar>?,
|
sizePtr: CPointer<platform.posix.size_tVar>?,
|
||||||
@@ -118,20 +118,20 @@ private val fClipboardDataCallback = staticCFunction {
|
|||||||
userdata.hashCode() // unused
|
userdata.hashCode() // unused
|
||||||
val vRequested = mimeType?.toKString() ?: return@staticCFunction null
|
val vRequested = mimeType?.toKString() ?: return@staticCFunction null
|
||||||
if (vRequested != kImageMime) return@staticCFunction null
|
if (vRequested != kImageMime) return@staticCFunction null
|
||||||
val vPtr = fOutgoingImagePtr ?: return@staticCFunction null
|
val vPtr = mOutgoingImagePtr ?: return@staticCFunction null
|
||||||
sizePtr?.pointed?.value = fOutgoingImageSize.toULong()
|
sizePtr?.pointed?.value = mOutgoingImageSize.toULong()
|
||||||
vPtr as COpaquePointer
|
vPtr as COpaquePointer
|
||||||
}
|
}
|
||||||
|
|
||||||
// SDL calls this when the clipboard we set is cleared or overwritten (by us
|
// SDL calls this when the clipboard we set is cleared or overwritten (by us
|
||||||
// or another app). Frees the nativeHeap allocation.
|
// or another app). Frees the nativeHeap allocation.
|
||||||
private val fClipboardCleanupCallback = staticCFunction {
|
private val mClipboardCleanupCallback = staticCFunction {
|
||||||
userdata: COpaquePointer?,
|
userdata: COpaquePointer?,
|
||||||
->
|
->
|
||||||
userdata.hashCode() // unused
|
userdata.hashCode() // unused
|
||||||
fOutgoingImagePtr?.let { nativeHeap.free(it.rawValue) }
|
mOutgoingImagePtr?.let { nativeHeap.free(it.rawValue) }
|
||||||
fOutgoingImagePtr = null
|
mOutgoingImagePtr = null
|
||||||
fOutgoingImageSize = 0
|
mOutgoingImageSize = 0
|
||||||
Unit
|
Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,19 +172,19 @@ private fun sdlReadImage(): ByteArray? = memScoped {
|
|||||||
private fun sdlWriteImage(bytes: ByteArray) {
|
private fun sdlWriteImage(bytes: ByteArray) {
|
||||||
// Free any previously-held buffer proactively (the cleanup callback also
|
// Free any previously-held buffer proactively (the cleanup callback also
|
||||||
// fires from SDL, but doing it eagerly here handles same-thread re-set).
|
// fires from SDL, but doing it eagerly here handles same-thread re-set).
|
||||||
fOutgoingImagePtr?.let { nativeHeap.free(it.rawValue) }
|
mOutgoingImagePtr?.let { nativeHeap.free(it.rawValue) }
|
||||||
|
|
||||||
val vPtr = nativeHeap.allocArray<ByteVar>(bytes.size)
|
val vPtr = nativeHeap.allocArray<ByteVar>(bytes.size)
|
||||||
for (i in bytes.indices) vPtr[i] = bytes[i]
|
for (i in bytes.indices) vPtr[i] = bytes[i]
|
||||||
fOutgoingImagePtr = vPtr
|
mOutgoingImagePtr = vPtr
|
||||||
fOutgoingImageSize = bytes.size
|
mOutgoingImageSize = bytes.size
|
||||||
|
|
||||||
memScoped {
|
memScoped {
|
||||||
val vMimeArray = allocArray<CPointerVar<ByteVar>>(1)
|
val vMimeArray = allocArray<CPointerVar<ByteVar>>(1)
|
||||||
vMimeArray[0] = kImageMime.cstr.ptr
|
vMimeArray[0] = kImageMime.cstr.ptr
|
||||||
SDL_SetClipboardData(
|
SDL_SetClipboardData(
|
||||||
fClipboardDataCallback,
|
mClipboardDataCallback,
|
||||||
fClipboardCleanupCallback,
|
mClipboardCleanupCallback,
|
||||||
null,
|
null,
|
||||||
vMimeArray,
|
vMimeArray,
|
||||||
1.toULong(),
|
1.toULong(),
|
||||||
@@ -213,10 +213,10 @@ private fun sdlWriteEntry(entry: ClipEntry?) {
|
|||||||
// The SDL3-backed Clipboard implementation. Singleton because SDL's clipboard
|
// The SDL3-backed Clipboard implementation. Singleton because SDL's clipboard
|
||||||
// is process-global - allocating a new one per Window() would only waste
|
// is process-global - allocating a new one per Window() would only waste
|
||||||
// memory. Consumed by :desktop-native-window when seeding LocalClipboard.
|
// memory. Consumed by :desktop-native-window when seeding LocalClipboard.
|
||||||
private object SDL3Clipboard : Clipboard {
|
private object Sdl3Clipboard : Clipboard {
|
||||||
override suspend fun getClipEntry(): ClipEntry? = sdlReadEntry()
|
override suspend fun getClipEntry(): ClipEntry? = sdlReadEntry()
|
||||||
override suspend fun setClipEntry(clipEntry: ClipEntry?) { sdlWriteEntry(clipEntry) }
|
override suspend fun setClipEntry(clipEntry: ClipEntry?) { sdlWriteEntry(clipEntry) }
|
||||||
override val nativeClipboard: NativeClipboard get() = nativeClipboardSentinel
|
override val nativeClipboard: NativeClipboard get() = nativeClipboardSentinel
|
||||||
}
|
}
|
||||||
|
|
||||||
fun platformClipboard(): Clipboard = SDL3Clipboard
|
fun platformClipboard(): Clipboard = Sdl3Clipboard
|
||||||
|
|||||||
+4
-4
@@ -18,12 +18,12 @@ import androidx.compose.ui.unit.IntRect
|
|||||||
* no-ops.
|
* no-ops.
|
||||||
*/
|
*/
|
||||||
private class StubSemanticsRegion : SemanticsRegion {
|
private class StubSemanticsRegion : SemanticsRegion {
|
||||||
private var fBounds: IntRect = IntRect.Zero
|
private var mBounds: IntRect = IntRect.Zero
|
||||||
override fun set(rect: IntRect) { fBounds = rect }
|
override fun set(rect: IntRect) { mBounds = rect }
|
||||||
override fun intersect(region: SemanticsRegion): Boolean = false
|
override fun intersect(region: SemanticsRegion): Boolean = false
|
||||||
override fun difference(rect: IntRect): Boolean = false
|
override fun difference(rect: IntRect): Boolean = false
|
||||||
override val bounds: IntRect get() = fBounds
|
override val bounds: IntRect get() = mBounds
|
||||||
override val isEmpty: Boolean get() = fBounds == IntRect.Zero
|
override val isEmpty: Boolean get() = mBounds == IntRect.Zero
|
||||||
}
|
}
|
||||||
|
|
||||||
internal actual fun SemanticsRegion(): SemanticsRegion = StubSemanticsRegion()
|
internal actual fun SemanticsRegion(): SemanticsRegion = StubSemanticsRegion()
|
||||||
|
|||||||
+24
-14
@@ -5,19 +5,27 @@ import androidx.compose.ui.input.key.KeyEvent
|
|||||||
import androidx.compose.ui.input.key.KeyEventType
|
import androidx.compose.ui.input.key.KeyEventType
|
||||||
import androidx.compose.ui.input.pointer.PointerButton
|
import androidx.compose.ui.input.pointer.PointerButton
|
||||||
import androidx.compose.ui.input.pointer.PointerEventType
|
import androidx.compose.ui.input.pointer.PointerEventType
|
||||||
import com.compose.sdl.input.LegacyPointerEvent
|
|
||||||
import kotlinx.cinterop.*
|
import kotlinx.cinterop.*
|
||||||
import sdl3.*
|
import sdl3.*
|
||||||
|
|
||||||
// ==================
|
// ==================
|
||||||
// MARK: SDL3EventMapper
|
// MARK: AppEvent + the SDL3 event mapper
|
||||||
// ==================
|
// ==================
|
||||||
|
|
||||||
/** Events carry the SDL window id they belong to (0 = unknown - injected test
|
/** Events carry the SDL window id they belong to (0 = unknown - injected test
|
||||||
events; the loop routes those to its first window). Quit is app-level. */
|
events; the loop routes those to its first window). Quit is app-level. */
|
||||||
sealed class AppEvent {
|
sealed class AppEvent {
|
||||||
data object Quit : AppEvent()
|
data object Quit : AppEvent()
|
||||||
data class Pointer(val event: LegacyPointerEvent, val windowId: UInt = 0u) : AppEvent()
|
/** A single-pointer SDL mouse event. Flat like its MouseWheel sibling: the
|
||||||
|
fields used to sit behind a `LegacyPointerEvent` wrapper that the mapper
|
||||||
|
built and the window loop immediately took apart again. */
|
||||||
|
data class Pointer(
|
||||||
|
val x: Float,
|
||||||
|
val y: Float,
|
||||||
|
val type: PointerEventType,
|
||||||
|
val button: PointerButton = PointerButton.Primary,
|
||||||
|
val windowId: UInt = 0u,
|
||||||
|
) : AppEvent()
|
||||||
data class Key(val event: KeyEvent, val windowId: UInt = 0u) : AppEvent()
|
data class Key(val event: KeyEvent, val windowId: UInt = 0u) : AppEvent()
|
||||||
data class TextInput(val text: String, val windowId: UInt = 0u) : AppEvent()
|
data class TextInput(val text: String, val windowId: UInt = 0u) : AppEvent()
|
||||||
/** IME preedit / composition (SDL_EVENT_TEXT_EDITING). Empty text = composition
|
/** IME preedit / composition (SDL_EVENT_TEXT_EDITING). Empty text = composition
|
||||||
@@ -75,34 +83,36 @@ fun pollEvents(): List<AppEvent> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun mapEvent(e: SDL_Event): AppEvent? {
|
private fun mapEvent(e: SDL_Event): AppEvent? {
|
||||||
val type = e.type
|
return when (e.type) {
|
||||||
return when (type) {
|
|
||||||
SDL_EVENT_QUIT -> AppEvent.Quit
|
SDL_EVENT_QUIT -> AppEvent.Quit
|
||||||
|
|
||||||
SDL_EVENT_MOUSE_BUTTON_DOWN -> {
|
SDL_EVENT_MOUSE_BUTTON_DOWN -> {
|
||||||
val mb = e.button
|
val mb = e.button
|
||||||
AppEvent.Pointer(LegacyPointerEvent(
|
AppEvent.Pointer(
|
||||||
x = mb.x, y = mb.y,
|
x = mb.x, y = mb.y,
|
||||||
type = PointerEventType.Press,
|
type = PointerEventType.Press,
|
||||||
button = mapButton(mb.button)
|
button = mapButton(mb.button),
|
||||||
), mb.windowID)
|
windowId = mb.windowID,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_EVENT_MOUSE_BUTTON_UP -> {
|
SDL_EVENT_MOUSE_BUTTON_UP -> {
|
||||||
val mb = e.button
|
val mb = e.button
|
||||||
AppEvent.Pointer(LegacyPointerEvent(
|
AppEvent.Pointer(
|
||||||
x = mb.x, y = mb.y,
|
x = mb.x, y = mb.y,
|
||||||
type = PointerEventType.Release,
|
type = PointerEventType.Release,
|
||||||
button = mapButton(mb.button)
|
button = mapButton(mb.button),
|
||||||
), mb.windowID)
|
windowId = mb.windowID,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_EVENT_MOUSE_MOTION -> {
|
SDL_EVENT_MOUSE_MOTION -> {
|
||||||
val mm = e.motion
|
val mm = e.motion
|
||||||
AppEvent.Pointer(LegacyPointerEvent(
|
AppEvent.Pointer(
|
||||||
x = mm.x, y = mm.y,
|
x = mm.x, y = mm.y,
|
||||||
type = PointerEventType.Move
|
type = PointerEventType.Move,
|
||||||
), mm.windowID)
|
windowId = mm.windowID,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_EVENT_KEY_DOWN -> mapKey(e.key, KeyEventType.KeyDown)
|
SDL_EVENT_KEY_DOWN -> mapKey(e.key, KeyEventType.KeyDown)
|
||||||
@@ -5,14 +5,18 @@ import androidx.compose.runtime.mutableStateOf
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.runtime.staticCompositionLocalOf
|
import androidx.compose.runtime.staticCompositionLocalOf
|
||||||
import androidx.compose.ui.input.key.KeyEvent
|
import androidx.compose.ui.input.key.KeyEvent
|
||||||
|
import kotlinx.cinterop.COpaquePointer
|
||||||
import kotlinx.cinterop.reinterpret
|
import kotlinx.cinterop.reinterpret
|
||||||
import kotlinx.cinterop.toKString
|
|
||||||
import sdl3.SDL_GetRendererName
|
|
||||||
import sdl3.SDL_MaximizeWindow
|
import sdl3.SDL_MaximizeWindow
|
||||||
import sdl3.SDL_MinimizeWindow
|
import sdl3.SDL_MinimizeWindow
|
||||||
import sdl3.SDL_RaiseWindow
|
import sdl3.SDL_RaiseWindow
|
||||||
import sdl3.SDL_RestoreWindow
|
import sdl3.SDL_RestoreWindow
|
||||||
|
import sdl3.SDL_SetWindowAlwaysOnTop
|
||||||
|
import sdl3.SDL_SetWindowBordered
|
||||||
|
import sdl3.SDL_SetWindowFocusable
|
||||||
import sdl3.SDL_SetWindowFullscreen
|
import sdl3.SDL_SetWindowFullscreen
|
||||||
|
import sdl3.SDL_SetWindowOpacity
|
||||||
|
import sdl3.SDL_SetWindowResizable
|
||||||
import sdl3.SDL_SetWindowSize
|
import sdl3.SDL_SetWindowSize
|
||||||
import sdl3.SDL_SetWindowTitle
|
import sdl3.SDL_SetWindowTitle
|
||||||
|
|
||||||
@@ -30,46 +34,46 @@ import sdl3.SDL_SetWindowTitle
|
|||||||
them subscribes the caller to recomposition. The setter methods
|
them subscribes the caller to recomposition. The setter methods
|
||||||
call into SDL and also push the new value into the snapshot. */
|
call into SDL and also push the new value into the snapshot. */
|
||||||
class ComposeNativeWindow constructor(
|
class ComposeNativeWindow constructor(
|
||||||
private val backend: SDL3Backend,
|
private val backend: Sdl3Backend,
|
||||||
val gpuMode: GpuMode,
|
val gpuMode: GpuMode,
|
||||||
initialTitle: String,
|
initialTitle: String,
|
||||||
) {
|
) {
|
||||||
private var fWidth by mutableStateOf(backend.windowWidth)
|
private var mWidth by mutableStateOf(backend.windowWidth)
|
||||||
private var fHeight by mutableStateOf(backend.windowHeight)
|
private var mHeight by mutableStateOf(backend.windowHeight)
|
||||||
private var fPixelWidth by mutableStateOf(backend.pixelWidth)
|
private var mPixelWidth by mutableStateOf(backend.pixelWidth)
|
||||||
private var fPixelHeight by mutableStateOf(backend.pixelHeight)
|
private var mPixelHeight by mutableStateOf(backend.pixelHeight)
|
||||||
private var fTitle by mutableStateOf(initialTitle)
|
private var mTitle by mutableStateOf(initialTitle)
|
||||||
private var fMinimized by mutableStateOf(false)
|
private var mMinimized by mutableStateOf(false)
|
||||||
private var fMaximized by mutableStateOf(false)
|
private var mMaximized by mutableStateOf(false)
|
||||||
private var fFullscreen by mutableStateOf(false)
|
private var mFullscreen by mutableStateOf(false)
|
||||||
private var fCloseRequested by mutableStateOf(false)
|
private var mCloseRequested by mutableStateOf(false)
|
||||||
private var fFps by mutableStateOf(0)
|
private var mFps by mutableStateOf(0)
|
||||||
|
|
||||||
// ============
|
// ============
|
||||||
// State
|
// State
|
||||||
|
|
||||||
/** Logical (point) width - the same units layout uses. */
|
/** Logical (point) width - the same units layout uses. */
|
||||||
val width: Int get() = fWidth
|
val width: Int get() = mWidth
|
||||||
val height: Int get() = fHeight
|
val height: Int get() = mHeight
|
||||||
/** Physical (pixel) back-buffer size; on Retina this is `width * pixelDensity`. */
|
/** Physical (pixel) back-buffer size; on Retina this is `width * pixelDensity`. */
|
||||||
val pixelWidth: Int get() = fPixelWidth
|
val pixelWidth: Int get() = mPixelWidth
|
||||||
val pixelHeight: Int get() = fPixelHeight
|
val pixelHeight: Int get() = mPixelHeight
|
||||||
val title: String get() = fTitle
|
val title: String get() = mTitle
|
||||||
val isMinimized: Boolean get() = fMinimized
|
val isMinimized: Boolean get() = mMinimized
|
||||||
val isMaximized: Boolean get() = fMaximized
|
val isMaximized: Boolean get() = mMaximized
|
||||||
val isFullscreen: Boolean get() = fFullscreen
|
val isFullscreen: Boolean get() = mFullscreen
|
||||||
val pixelDensity: Float get() = backend.pixelDensity
|
val pixelDensity: Float get() = backend.pixelDensity
|
||||||
/** Frames per second, refreshed ~once a second by the render loop. Snapshot-
|
/** Frames per second, refreshed ~once a second by the render loop. Snapshot-
|
||||||
backed, so reading it in a composable recomposes when it changes. */
|
backed, so reading it in a composable recomposes when it changes. */
|
||||||
val fps: Int get() = fFps
|
val fps: Int get() = mFps
|
||||||
|
|
||||||
/** Human-readable name of the rendering pipeline:
|
/** Human-readable name of the rendering pipeline:
|
||||||
"Skia / Metal", "Skia / OpenGL", "Skia / CPU raster". */
|
"Skia / Metal", "Skia / OpenGL", "Skia / CPU raster". */
|
||||||
val rendererName: String
|
val rendererName: String
|
||||||
get() = when (gpuMode) {
|
get() = when (gpuMode) {
|
||||||
is GpuMode.Skia.Metal -> "Skia / Metal"
|
is GpuMode.Metal -> "Skia / Metal"
|
||||||
is GpuMode.Skia.OpenGL -> "Skia / OpenGL"
|
is GpuMode.OpenGL -> "Skia / OpenGL"
|
||||||
is GpuMode.Software -> "Skia / CPU raster"
|
is GpuMode.CpuRaster -> "Skia / CPU raster"
|
||||||
is GpuMode.Auto -> "Auto (unresolved)"
|
is GpuMode.Auto -> "Auto (unresolved)"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +83,7 @@ class ComposeNativeWindow constructor(
|
|||||||
fun setTitle(inTitle: String) {
|
fun setTitle(inTitle: String) {
|
||||||
val vWindow = backend.window?.reinterpret<cnames.structs.SDL_Window>() ?: return
|
val vWindow = backend.window?.reinterpret<cnames.structs.SDL_Window>() ?: return
|
||||||
SDL_SetWindowTitle(vWindow, inTitle)
|
SDL_SetWindowTitle(vWindow, inTitle)
|
||||||
fTitle = inTitle
|
mTitle = inTitle
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Logical size in points - SDL fires AppEvent.WindowResized which
|
/** Logical size in points - SDL fires AppEvent.WindowResized which
|
||||||
@@ -91,56 +95,111 @@ class ComposeNativeWindow constructor(
|
|||||||
|
|
||||||
fun minimize() {
|
fun minimize() {
|
||||||
val vWindow = backend.window?.reinterpret<cnames.structs.SDL_Window>() ?: return
|
val vWindow = backend.window?.reinterpret<cnames.structs.SDL_Window>() ?: return
|
||||||
SDL_MinimizeWindow(vWindow); fMinimized = true
|
SDL_MinimizeWindow(vWindow); mMinimized = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun maximize() {
|
fun maximize() {
|
||||||
val vWindow = backend.window?.reinterpret<cnames.structs.SDL_Window>() ?: return
|
val vWindow = backend.window?.reinterpret<cnames.structs.SDL_Window>() ?: return
|
||||||
SDL_MaximizeWindow(vWindow); fMaximized = true; fMinimized = false
|
SDL_MaximizeWindow(vWindow); mMaximized = true; mMinimized = false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun restore() {
|
fun restore() {
|
||||||
val vWindow = backend.window?.reinterpret<cnames.structs.SDL_Window>() ?: return
|
val vWindow = backend.window?.reinterpret<cnames.structs.SDL_Window>() ?: return
|
||||||
SDL_RestoreWindow(vWindow); fMaximized = false; fMinimized = false
|
SDL_RestoreWindow(vWindow); mMaximized = false; mMinimized = false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setFullscreen(inFullscreen: Boolean) {
|
fun setFullscreen(inFullscreen: Boolean) {
|
||||||
val vWindow = backend.window?.reinterpret<cnames.structs.SDL_Window>() ?: return
|
val vWindow = backend.window?.reinterpret<cnames.structs.SDL_Window>() ?: return
|
||||||
SDL_SetWindowFullscreen(vWindow, inFullscreen); fFullscreen = inFullscreen
|
SDL_SetWindowFullscreen(vWindow, inFullscreen); mFullscreen = inFullscreen
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleFullscreen() = setFullscreen(!fFullscreen)
|
fun toggleFullscreen() = setFullscreen(!mFullscreen)
|
||||||
|
|
||||||
fun raise() {
|
fun raise() {
|
||||||
val vWindow = backend.window?.reinterpret<cnames.structs.SDL_Window>() ?: return
|
val vWindow = backend.window?.reinterpret<cnames.structs.SDL_Window>() ?: return
|
||||||
SDL_RaiseWindow(vWindow)
|
SDL_RaiseWindow(vWindow)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============
|
||||||
|
// Mutable window attributes (Compose Desktop's Window() parameters)
|
||||||
|
//
|
||||||
|
// Window() re-applies these from the composition whenever they change, so
|
||||||
|
// app code normally passes them as parameters rather than calling these.
|
||||||
|
// `transparent` is absent on purpose: SDL needs SDL_WINDOW_TRANSPARENT at
|
||||||
|
// creation and offers no setter, so it is a construction-time attribute.
|
||||||
|
|
||||||
|
private var mUndecorated = false
|
||||||
|
private var mResizable = true
|
||||||
|
private var mAlwaysOnTop = false
|
||||||
|
private var mFocusable = true
|
||||||
|
private var mEnabled = true
|
||||||
|
|
||||||
|
val isUndecorated: Boolean get() = mUndecorated
|
||||||
|
val isResizable: Boolean get() = mResizable
|
||||||
|
val isAlwaysOnTop: Boolean get() = mAlwaysOnTop
|
||||||
|
val isFocusable: Boolean get() = mFocusable
|
||||||
|
|
||||||
|
/** False hides the window's title bar and border. */
|
||||||
|
fun setUndecorated(inUndecorated: Boolean) {
|
||||||
|
val vWindow = backend.window?.reinterpret<cnames.structs.SDL_Window>() ?: return
|
||||||
|
SDL_SetWindowBordered(vWindow, !inUndecorated); mUndecorated = inUndecorated
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setResizable(inResizable: Boolean) {
|
||||||
|
val vWindow = backend.window?.reinterpret<cnames.structs.SDL_Window>() ?: return
|
||||||
|
SDL_SetWindowResizable(vWindow, inResizable); mResizable = inResizable
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setAlwaysOnTop(inAlwaysOnTop: Boolean) {
|
||||||
|
val vWindow = backend.window?.reinterpret<cnames.structs.SDL_Window>() ?: return
|
||||||
|
SDL_SetWindowAlwaysOnTop(vWindow, inAlwaysOnTop); mAlwaysOnTop = inAlwaysOnTop
|
||||||
|
}
|
||||||
|
|
||||||
|
/** False stops the window taking keyboard focus when clicked or raised. */
|
||||||
|
fun setFocusable(inFocusable: Boolean) {
|
||||||
|
val vWindow = backend.window?.reinterpret<cnames.structs.SDL_Window>() ?: return
|
||||||
|
SDL_SetWindowFocusable(vWindow, inFocusable); mFocusable = inFocusable
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Window opacity, 0f (fully transparent) to 1f. Needs a compositing window
|
||||||
|
manager; SDL reports failure on platforms without one. */
|
||||||
|
fun setOpacity(inOpacity: Float) {
|
||||||
|
val vWindow = backend.window?.reinterpret<cnames.structs.SDL_Window>() ?: return
|
||||||
|
SDL_SetWindowOpacity(vWindow, inOpacity.coerceIn(0f, 1f))
|
||||||
|
}
|
||||||
|
|
||||||
|
/** True while the window accepts input. A disabled window still renders and
|
||||||
|
repaints; it just drops pointer / keyboard / text / wheel / drop events,
|
||||||
|
which is how Compose Desktop's `enabled = false` behaves. */
|
||||||
|
val isEnabled: Boolean get() = mEnabled
|
||||||
|
|
||||||
|
fun setEnabled(inEnabled: Boolean) { mEnabled = inEnabled }
|
||||||
|
|
||||||
/** Asks composeWindow's main loop to break out at the next frame.
|
/** Asks composeWindow's main loop to break out at the next frame.
|
||||||
Same effect as the user closing the window via the OS. Bypasses any
|
Same effect as the user closing the window via the OS. Bypasses any
|
||||||
onCloseRequest handler - this is the "really quit now" path. */
|
onCloseRequest handler - this is the "really quit now" path. */
|
||||||
fun close() { fCloseRequested = true }
|
fun close() { mCloseRequested = true }
|
||||||
|
|
||||||
// ============
|
// ============
|
||||||
// Close interception
|
// Close interception
|
||||||
|
|
||||||
private var fOnCloseRequest: (() -> Boolean)? = null
|
private var mOnCloseRequest: (() -> Boolean)? = null
|
||||||
|
|
||||||
/** Register a handler invoked when the user tries to close the window (OS
|
/** Register a handler invoked when the user tries to close the window (OS
|
||||||
close button / Quit). Return true to let the close proceed, false to veto
|
close button / Quit). Return true to let the close proceed, false to veto
|
||||||
it (e.g. to show an "unsaved changes" dialog first, then call close()
|
it (e.g. to show an "unsaved changes" dialog first, then call close()
|
||||||
once the user confirms). Pass null to clear. */
|
once the user confirms). Pass null to clear. */
|
||||||
fun setOnCloseRequest(inHandler: (() -> Boolean)?) { fOnCloseRequest = inHandler }
|
fun setOnCloseRequest(inHandler: (() -> Boolean)?) { mOnCloseRequest = inHandler }
|
||||||
|
|
||||||
// ============
|
// ============
|
||||||
// Global key shortcuts
|
// Global key shortcuts
|
||||||
|
|
||||||
private var fOnKeyShortcut: ((KeyEvent) -> Boolean)? = null
|
private var mOnKeyShortcut: ((KeyEvent) -> Boolean)? = null
|
||||||
|
|
||||||
/** Register a handler for key events the focused node didn't consume - for
|
/** Register a handler for key events the focused node didn't consume - for
|
||||||
app-wide shortcuts (Ctrl+S, etc.). Receives every unconsumed key (and all
|
app-wide shortcuts (Ctrl+S, etc.). Receives every unconsumed key (and all
|
||||||
keys when nothing is focused). Return true if handled. Pass null to clear. */
|
keys when nothing is focused). Return true if handled. Pass null to clear. */
|
||||||
fun setOnKeyShortcut(inHandler: ((KeyEvent) -> Boolean)?) { fOnKeyShortcut = inHandler }
|
fun setOnKeyShortcut(inHandler: ((KeyEvent) -> Boolean)?) { mOnKeyShortcut = inHandler }
|
||||||
|
|
||||||
// ============
|
// ============
|
||||||
// Framework hooks - driven by composeWindow's main loop (which lives in
|
// Framework hooks - driven by composeWindow's main loop (which lives in
|
||||||
@@ -148,26 +207,71 @@ class ComposeNativeWindow constructor(
|
|||||||
// intended for app code.
|
// intended for app code.
|
||||||
|
|
||||||
fun onResized() {
|
fun onResized() {
|
||||||
fWidth = backend.windowWidth
|
mWidth = backend.windowWidth
|
||||||
fHeight = backend.windowHeight
|
mHeight = backend.windowHeight
|
||||||
fPixelWidth = backend.pixelWidth
|
mPixelWidth = backend.pixelWidth
|
||||||
fPixelHeight = backend.pixelHeight
|
mPixelHeight = backend.pixelHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Called by the main loop ~once a second with the measured frame rate. */
|
/** Called by the main loop ~once a second with the measured frame rate. */
|
||||||
fun updateFps(inFps: Int) { fFps = inFps }
|
fun updateFps(inFps: Int) { mFps = inFps }
|
||||||
|
|
||||||
val isCloseRequested: Boolean get() = fCloseRequested
|
val isCloseRequested: Boolean get() = mCloseRequested
|
||||||
|
|
||||||
/** Driven by composeWindow's main loop on an OS close / Quit event. Returns
|
/** Driven by composeWindow's main loop on an OS close / Quit event. Returns
|
||||||
true if the close should proceed (no handler, or the handler allowed it). */
|
true if the close should proceed (no handler, or the handler allowed it). */
|
||||||
fun requestCloseFromUser(): Boolean = fOnCloseRequest?.invoke() ?: true
|
fun requestCloseFromUser(): Boolean = mOnCloseRequest?.invoke() ?: true
|
||||||
|
|
||||||
/** Driven by composeWindow's main loop for keys the focused node didn't
|
/** Driven by composeWindow's main loop for keys the focused node didn't
|
||||||
consume. Returns true if the shortcut handler handled it. */
|
consume. Returns true if the shortcut handler handled it. */
|
||||||
fun dispatchKeyShortcut(inEvent: KeyEvent): Boolean = fOnKeyShortcut?.invoke(inEvent) ?: false
|
fun dispatchKeyShortcut(inEvent: KeyEvent): Boolean = mOnKeyShortcut?.invoke(inEvent) ?: false
|
||||||
|
|
||||||
|
// ============
|
||||||
|
// Raw SDL escape hatch
|
||||||
|
|
||||||
|
/**
|
||||||
|
The live SDL handles behind this window, for calling the `sdl3.*` cinterop
|
||||||
|
directly when the Compose-level API doesn't cover something.
|
||||||
|
|
||||||
|
Returns a snapshot: the pointers are only valid while the window is alive,
|
||||||
|
so re-read it rather than caching, and never use it after the window closes.
|
||||||
|
Whatever you do through it is outside the port's control - resizing,
|
||||||
|
destroying or re-creating the window or its renderer behind Compose's back
|
||||||
|
will desync the renderer state.
|
||||||
|
*/
|
||||||
|
fun rawSdlHandles(): RawSdlHandles = RawSdlHandles(
|
||||||
|
window = backend.window,
|
||||||
|
renderer = backend.renderer,
|
||||||
|
glContext = backend.glContext,
|
||||||
|
metalView = backend.metalView,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Opaque SDL pointers for one window, as handed out by
|
||||||
|
[ComposeNativeWindow.rawSdlHandles].
|
||||||
|
|
||||||
|
`reinterpret()` each to the `cnames.structs.*` type the SDL function expects:
|
||||||
|
|
||||||
|
val vHandles = window.rawSdlHandles()
|
||||||
|
vHandles.window?.let { sdl3.SDL_FlashWindow(it.reinterpret(), FLASH_BRIEFLY) }
|
||||||
|
|
||||||
|
Which pointers are non-null depends on the resolved [GpuMode]: `renderer` is
|
||||||
|
set only for the CPU-raster (Software) backend, `glContext` only for Skia
|
||||||
|
OpenGL, and `metalView` only for Skia Metal. `window` is always set on a
|
||||||
|
successfully created window.
|
||||||
|
*/
|
||||||
|
data class RawSdlHandles(
|
||||||
|
/** `SDL_Window*` - always present while the window lives. */
|
||||||
|
val window: COpaquePointer?,
|
||||||
|
/** `SDL_Renderer*` - CPU-raster (Software) backend only. */
|
||||||
|
val renderer: COpaquePointer?,
|
||||||
|
/** `SDL_GLContext` - Skia OpenGL backend only. */
|
||||||
|
val glContext: COpaquePointer?,
|
||||||
|
/** `SDL_MetalView` - Skia Metal backend only. */
|
||||||
|
val metalView: COpaquePointer?,
|
||||||
|
)
|
||||||
|
|
||||||
// ==================
|
// ==================
|
||||||
// MARK: Scope + CompositionLocal
|
// MARK: Scope + CompositionLocal
|
||||||
// ==================
|
// ==================
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import sdl3.SDL_ShowSaveFileDialog
|
|||||||
|
|
||||||
The C callback can't capture Kotlin state, so the result handler is parked in
|
The C callback can't capture Kotlin state, so the result handler is parked in
|
||||||
a StableRef passed as the dialog's `userdata` and disposed inside the callback. */
|
a StableRef passed as the dialog's `userdata` and disposed inside the callback. */
|
||||||
private val fDialogCallback = staticCFunction { inUserData: COpaquePointer?, inFileList: CPointer<CPointerVar<ByteVar>>?, inFilter: Int ->
|
private val mDialogCallback = staticCFunction { inUserData: COpaquePointer?, inFileList: CPointer<CPointerVar<ByteVar>>?, inFilter: Int ->
|
||||||
inFilter.hashCode() // unused (selected filter index)
|
inFilter.hashCode() // unused (selected filter index)
|
||||||
val vRef = inUserData?.asStableRef<(String?) -> Unit>() ?: return@staticCFunction
|
val vRef = inUserData?.asStableRef<(String?) -> Unit>() ?: return@staticCFunction
|
||||||
val vHandler = vRef.get()
|
val vHandler = vRef.get()
|
||||||
@@ -31,7 +31,7 @@ private val fDialogCallback = staticCFunction { inUserData: COpaquePointer?, inF
|
|||||||
fun showSaveFileDialog(inDefaultName: String? = null, inOnResult: (String?) -> Unit) {
|
fun showSaveFileDialog(inDefaultName: String? = null, inOnResult: (String?) -> Unit) {
|
||||||
val vRef = StableRef.create(inOnResult)
|
val vRef = StableRef.create(inOnResult)
|
||||||
SDL_ShowSaveFileDialog(
|
SDL_ShowSaveFileDialog(
|
||||||
fDialogCallback,
|
mDialogCallback,
|
||||||
vRef.asCPointer(),
|
vRef.asCPointer(),
|
||||||
null, // parent window (null = unparented)
|
null, // parent window (null = unparented)
|
||||||
null, // no file-type filters
|
null, // no file-type filters
|
||||||
@@ -45,7 +45,7 @@ fun showSaveFileDialog(inDefaultName: String? = null, inOnResult: (String?) -> U
|
|||||||
fun showOpenFileDialog(inOnResult: (String?) -> Unit) {
|
fun showOpenFileDialog(inOnResult: (String?) -> Unit) {
|
||||||
val vRef = StableRef.create(inOnResult)
|
val vRef = StableRef.create(inOnResult)
|
||||||
SDL_ShowOpenFileDialog(
|
SDL_ShowOpenFileDialog(
|
||||||
fDialogCallback,
|
mDialogCallback,
|
||||||
vRef.asCPointer(),
|
vRef.asCPointer(),
|
||||||
null, // parent window
|
null, // parent window
|
||||||
null, // filters
|
null, // filters
|
||||||
|
|||||||
@@ -4,28 +4,38 @@ package com.compose.sdl
|
|||||||
// MARK: GpuMode
|
// MARK: GpuMode
|
||||||
// ==================
|
// ==================
|
||||||
|
|
||||||
/** Which GPU path the Skia renderer uses.
|
/**
|
||||||
*
|
Which drawing path the renderer uses.
|
||||||
* ┌─ Auto - pick the best for this platform (Metal on macOS, OpenGL on
|
|
||||||
* │ Linux, OpenGL on Windows). If the GPU context/bridge can't be
|
Every mode is Skia - the port renders through Skia on all targets. The axis
|
||||||
* │ created, ComposeWindow falls back to Software.
|
here is only how Skia's output reaches the screen:
|
||||||
* ├─ Software - Skia CPU raster: paints a host pixel buffer that SDL_Renderer
|
|
||||||
* │ uploads as a texture each frame. No GPU context needed.
|
Auto resolve per platform at window creation (Metal on macOS, OpenGL
|
||||||
* └─ Skia.* - Skia GPU bridges
|
on Linux and Windows). If the GPU context can't be created, the
|
||||||
* ├─ OpenGL - Skia GL backend on an SDL OpenGL (WGL/GLX) context
|
window falls back to CpuRaster rather than failing to open.
|
||||||
* └─ Metal - Skia Metal on a CAMetalLayer via SDL_Metal_CreateView (macOS)
|
Metal Skia's Metal backend on a CAMetalLayer (SDL_Metal_CreateView), macOS.
|
||||||
*
|
OpenGL Skia's GL backend on an SDL OpenGL (WGL/GLX) context.
|
||||||
* AUTO resolves via rendererPreferredGpuMode() per target, at composeWindow entry. */
|
CpuRaster Skia paints a host pixel buffer that SDL_Renderer uploads as a
|
||||||
|
texture each frame. No GPU context needed.
|
||||||
|
|
||||||
|
This used to read `Software` vs a nested `Skia.*` group, which dated from when
|
||||||
|
the alternative to Skia was SDL's own renderer. With SDL reduced to windowing
|
||||||
|
that split was actively misleading - "Software" was always Skia too.
|
||||||
|
*/
|
||||||
sealed class GpuMode {
|
sealed class GpuMode {
|
||||||
/** Let the platform pick: Skia.Metal on macOS, Skia.OpenGL on Linux/Windows. */
|
/** Let the platform pick: [Metal] on macOS, [OpenGL] on Linux and Windows. */
|
||||||
object Auto : GpuMode() { override fun toString() = "Auto" }
|
object Auto : GpuMode() { override fun toString() = "Auto" }
|
||||||
|
|
||||||
/** Skia CPU raster - a host pixel buffer uploaded via SDL_Renderer each frame. */
|
/** Skia Metal on a CAMetalLayer via SDL_Metal_CreateView (macOS only). */
|
||||||
object Software : GpuMode() { override fun toString() = "Software" }
|
object Metal : GpuMode() { override fun toString() = "Metal" }
|
||||||
|
|
||||||
/** Skia GPU bridges. */
|
/** Skia GL on an SDL OpenGL context (WGL on Windows, GLX on Linux). */
|
||||||
sealed class Skia : GpuMode() {
|
object OpenGL : GpuMode() { override fun toString() = "OpenGL" }
|
||||||
object OpenGL : Skia() { override fun toString() = "Skia.OpenGL" }
|
|
||||||
object Metal : Skia() { override fun toString() = "Skia.Metal" }
|
/** Skia CPU raster - a host pixel buffer uploaded via SDL_Renderer each frame. */
|
||||||
}
|
object CpuRaster : GpuMode() { override fun toString() = "CpuRaster" }
|
||||||
|
|
||||||
|
/** True for the GPU-backed modes. [Auto] is false because it is unresolved:
|
||||||
|
ask after the window has resolved it, via ComposeNativeWindow.gpuMode. */
|
||||||
|
val isGpuAccelerated: Boolean get() = this is Metal || this is OpenGL
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import sdl3.SDL_OpenURL
|
|||||||
UI until the file manager was up. None of the three platform backends
|
UI until the file manager was up. None of the three platform backends
|
||||||
requires the main thread, so a small background scope launches them and
|
requires the main thread, so a small background scope launches them and
|
||||||
(optionally) posts the result back to Main. */
|
(optionally) posts the result back to Main. */
|
||||||
private val fOpenExternalScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
private val mOpenExternalScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
||||||
|
|
||||||
/** Opens a URL or file:// URI with the OS's default handler (browser, file
|
/** Opens a URL or file:// URI with the OS's default handler (browser, file
|
||||||
manager, …) via SDL_OpenURL - asynchronously, so the UI keeps pumping while
|
manager, …) via SDL_OpenURL - asynchronously, so the UI keeps pumping while
|
||||||
@@ -30,7 +30,7 @@ private val fOpenExternalScope = CoroutineScope(SupervisorJob() + Dispatchers.De
|
|||||||
thread with SDL_OpenURL's success flag. */
|
thread with SDL_OpenURL's success flag. */
|
||||||
@OptIn(ExperimentalForeignApi::class)
|
@OptIn(ExperimentalForeignApi::class)
|
||||||
fun openUrl(inUrl: String, inOnResult: ((Boolean) -> Unit)? = null) {
|
fun openUrl(inUrl: String, inOnResult: ((Boolean) -> Unit)? = null) {
|
||||||
fOpenExternalScope.launch {
|
mOpenExternalScope.launch {
|
||||||
val vOk = SDL_OpenURL(inUrl)
|
val vOk = SDL_OpenURL(inUrl)
|
||||||
if (inOnResult != null) withContext(Dispatchers.Main) { inOnResult(vOk) }
|
if (inOnResult != null) withContext(Dispatchers.Main) { inOnResult(vOk) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,21 @@ import com.compose.sdl.res.ImageLoader
|
|||||||
(official Skiko on macOS/Linux, the fork on mingwX64); text measurement +
|
(official Skiko on macOS/Linux, the fork on mingwX64); text measurement +
|
||||||
drawing go through the skiko paragraph engine (androidx.compose.ui.text
|
drawing go through the skiko paragraph engine (androidx.compose.ui.text
|
||||||
Paragraph actuals), so there is no renderer-owned measurer here. */
|
Paragraph actuals), so there is no renderer-owned measurer here. */
|
||||||
|
/*
|
||||||
|
WHY THIS INTERFACE EXISTS WITH ONE IMPLEMENTATION - do not "simplify" it away.
|
||||||
|
|
||||||
|
SkiaRenderBackend is its only implementor, which reads like leftover
|
||||||
|
dual-backend scaffolding from when SDL's own renderer was the alternative. It
|
||||||
|
is not. SkiaRenderBackend lives in skikoRendererMain, BELOW nativeMain, so
|
||||||
|
nativeMain-level code cannot name it: :desktop-native-window's WindowInstance
|
||||||
|
holds the renderer in nativeMain and would not compile against the concrete
|
||||||
|
type. Verified by trying it - compileNativeMainKotlinMetadata fails with
|
||||||
|
"Unresolved reference 'renderer'".
|
||||||
|
|
||||||
|
So this interface is the nativeMain-visible boundary for an implementation
|
||||||
|
that must live lower down, exactly like the expect fun createRenderBackend
|
||||||
|
that returns it. Same reasoning, same constraint.
|
||||||
|
*/
|
||||||
interface RenderBackend {
|
interface RenderBackend {
|
||||||
/** Loader the shared ImageMeasurePolicy / Res.readBytes plug into. Backed
|
/** Loader the shared ImageMeasurePolicy / Res.readBytes plug into. Backed
|
||||||
by the same decode cache the renderer uses to paint images, so a
|
by the same decode cache the renderer uses to paint images, so a
|
||||||
@@ -30,8 +45,13 @@ interface RenderBackend {
|
|||||||
DrawModifierNode pipeline. Taking a (Canvas)->Unit instead of the host keeps
|
DrawModifierNode pipeline. Taking a (Canvas)->Unit instead of the host keeps
|
||||||
RenderBackend + its implementations independent of the node/host layer - the
|
RenderBackend + its implementations independent of the node/host layer - the
|
||||||
decoupling that lets the renderers live in :ui-graphics (no ui-graphics→ui
|
decoupling that lets the renderers live in :ui-graphics (no ui-graphics→ui
|
||||||
cycle). Default no-op. */
|
cycle).
|
||||||
fun drawRoot(inDraw: (canvas: androidx.compose.ui.graphics.Canvas) -> Unit) {}
|
|
||||||
|
ABSTRACT, not a no-op default: the empty body dates from when a second,
|
||||||
|
non-Skia backend could opt out of it, and with the Skia backend now the
|
||||||
|
only implementation an unimplemented drawRoot would silently render
|
||||||
|
nothing rather than fail to compile. */
|
||||||
|
fun drawRoot(inDraw: (canvas: androidx.compose.ui.graphics.Canvas) -> Unit)
|
||||||
|
|
||||||
/** Flush + present whatever was just drawn. */
|
/** Flush + present whatever was just drawn. */
|
||||||
fun endFrame()
|
fun endFrame()
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ package com.compose.sdl
|
|||||||
|
|
||||||
/** Create the render backend for the selected [GpuMode]; null when the
|
/** Create the render backend for the selected [GpuMode]; null when the
|
||||||
backend can't initialise (caller falls back / reports). */
|
backend can't initialise (caller falls back / reports). */
|
||||||
expect fun createRenderBackend(inSdl: SDL3Backend, inGpu: GpuMode): RenderBackend?
|
expect fun createRenderBackend(inSdl: Sdl3Backend, inGpu: GpuMode): RenderBackend?
|
||||||
|
|
||||||
/** The renderer module's per-OS default GpuMode (used for GpuMode.Auto). */
|
/** The renderer module's per-OS default GpuMode (used for GpuMode.Auto). */
|
||||||
expect fun rendererPreferredGpuMode(): GpuMode
|
expect fun rendererPreferredGpuMode(): GpuMode
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ import sdl3.SDL_GetBasePath
|
|||||||
// no zlib/gzip wrapper). ZIP64 is not supported - the resource set is
|
// no zlib/gzip wrapper). ZIP64 is not supported - the resource set is
|
||||||
// small enough that the standard 4 GB / 65535-entry limits don't apply.
|
// small enough that the standard 4 GB / 65535-entry limits don't apply.
|
||||||
|
|
||||||
private class ComposeResourceArchive(private val fHandle: FileHandle) {
|
private class ComposeResourceArchive(private val mHandle: FileHandle) {
|
||||||
|
|
||||||
// One entry's location + sizing + compression method from the central
|
// One entry's location + sizing + compression method from the central
|
||||||
// directory. method 0 = stored, 8 = deflated.
|
// directory. method 0 = stored, 8 = deflated.
|
||||||
@@ -53,18 +53,18 @@ private class ComposeResourceArchive(private val fHandle: FileHandle) {
|
|||||||
val uncompressedSize: Long,
|
val uncompressedSize: Long,
|
||||||
val method: Int,
|
val method: Int,
|
||||||
)
|
)
|
||||||
private val fEntries: Map<String, Entry>
|
private val mEntries: Map<String, Entry>
|
||||||
|
|
||||||
init {
|
init {
|
||||||
fEntries = readCentralDirectory()
|
mEntries = readCentralDirectory()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun has(inPath: String): Boolean = fEntries.containsKey(inPath)
|
fun has(inPath: String): Boolean = mEntries.containsKey(inPath)
|
||||||
|
|
||||||
/** Reads an entry's bytes (inflated if needed) or null if the entry is
|
/** Reads an entry's bytes (inflated if needed) or null if the entry is
|
||||||
missing / uses an unsupported compression method. */
|
missing / uses an unsupported compression method. */
|
||||||
fun readBytes(inPath: String): ByteArray? {
|
fun readBytes(inPath: String): ByteArray? {
|
||||||
val vEntry = fEntries[inPath] ?: return null
|
val vEntry = mEntries[inPath] ?: return null
|
||||||
if (vEntry.uncompressedSize <= 0L) return ByteArray(0)
|
if (vEntry.uncompressedSize <= 0L) return ByteArray(0)
|
||||||
|
|
||||||
// Local file header layout: 30 fixed bytes, then filename_len + extra_len.
|
// Local file header layout: 30 fixed bytes, then filename_len + extra_len.
|
||||||
@@ -126,7 +126,7 @@ private class ComposeResourceArchive(private val fHandle: FileHandle) {
|
|||||||
// End of Central Directory record: 22 bytes minimum, with up to 65535
|
// End of Central Directory record: 22 bytes minimum, with up to 65535
|
||||||
// bytes of comment trailing. Read the last 64 KiB + 22 and scan backward
|
// bytes of comment trailing. Read the last 64 KiB + 22 and scan backward
|
||||||
// for the EOCD signature.
|
// for the EOCD signature.
|
||||||
val vFileLen: Long = fHandle.size()
|
val vFileLen: Long = mHandle.size()
|
||||||
if (vFileLen < 22L) return emptyMap()
|
if (vFileLen < 22L) return emptyMap()
|
||||||
val vTailLen = minOf(vFileLen, 65557L).toInt()
|
val vTailLen = minOf(vFileLen, 65557L).toInt()
|
||||||
val vTail = ByteArray(vTailLen)
|
val vTail = ByteArray(vTailLen)
|
||||||
@@ -182,14 +182,14 @@ private class ComposeResourceArchive(private val fHandle: FileHandle) {
|
|||||||
if (outBuf.isEmpty()) return true
|
if (outBuf.isEmpty()) return true
|
||||||
var vRead = 0
|
var vRead = 0
|
||||||
while (vRead < outBuf.size) {
|
while (vRead < outBuf.size) {
|
||||||
val vN = fHandle.read(inOffset + vRead, outBuf, vRead, outBuf.size - vRead)
|
val vN = mHandle.read(inOffset + vRead, outBuf, vRead, outBuf.size - vRead)
|
||||||
if (vN <= 0) return false
|
if (vN <= 0) return false
|
||||||
vRead += vN
|
vRead += vN
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun close() = fHandle.close()
|
fun close() = mHandle.close()
|
||||||
|
|
||||||
private fun le16(inBuf: ByteArray, inOff: Int): Int =
|
private fun le16(inBuf: ByteArray, inOff: Int): Int =
|
||||||
(inBuf[inOff].toInt() and 0xFF) or
|
(inBuf[inOff].toInt() and 0xFF) or
|
||||||
|
|||||||
+27
-12
@@ -4,23 +4,32 @@ import kotlinx.cinterop.*
|
|||||||
import sdl3.*
|
import sdl3.*
|
||||||
|
|
||||||
// ==================
|
// ==================
|
||||||
// MARK: SDL3Backend
|
// MARK: Sdl3Backend
|
||||||
// ==================
|
// ==================
|
||||||
|
|
||||||
class SDL3Backend(
|
class Sdl3Backend(
|
||||||
private val title: String = "ComposeNativeSDL3",
|
private val title: String = "ComposeNativeSDL3",
|
||||||
private val width: Int = 800,
|
private val width: Int = 800,
|
||||||
private val height: Int = 600,
|
private val height: Int = 600,
|
||||||
val gpuMode: GpuMode = GpuMode.Software,
|
val gpuMode: GpuMode = GpuMode.CpuRaster,
|
||||||
// Resource paths (inside data.kres) of the pre-decoded .rgba icon blobs.
|
// Resource paths (inside data.kres) of the pre-decoded .rgba icon blobs.
|
||||||
// The first-listed size is irrelevant - the largest becomes the base and
|
// The first-listed size is irrelevant - the largest becomes the base and
|
||||||
// the rest become alternate resolutions. Dark set falls back to light.
|
// the rest become alternate resolutions. Dark set falls back to light.
|
||||||
private val iconLightResourcePaths: List<String> = emptyList(),
|
private val iconLightResourcePaths: List<String> = emptyList(),
|
||||||
private val iconDarkResourcePaths: List<String> = emptyList(),
|
private val iconDarkResourcePaths: List<String> = emptyList(),
|
||||||
|
// Creation-time window attributes, mirroring Compose Desktop's Window().
|
||||||
|
// `undecorated`, `resizable`, `alwaysOnTop` and `focusable` can also be
|
||||||
|
// changed later (see ComposeNativeWindow); `transparent` cannot - SDL needs
|
||||||
|
// SDL_WINDOW_TRANSPARENT at creation, so it is honoured here only.
|
||||||
|
private val undecorated: Boolean = false,
|
||||||
|
private val transparent: Boolean = false,
|
||||||
|
private val resizable: Boolean = true,
|
||||||
|
private val alwaysOnTop: Boolean = false,
|
||||||
|
private val focusable: Boolean = true,
|
||||||
) {
|
) {
|
||||||
init {
|
init {
|
||||||
require(gpuMode !is GpuMode.Auto) {
|
require(gpuMode !is GpuMode.Auto) {
|
||||||
"SDL3Backend received GpuMode.Auto - resolve via preferredGpuMode() first"
|
"Sdl3Backend received GpuMode.Auto - resolve via preferredGpuMode() first"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +75,7 @@ class SDL3Backend(
|
|||||||
com.compose.sdl.res.preferredLocaleProvider = ::sdlPreferredLocale
|
com.compose.sdl.res.preferredLocaleProvider = ::sdlPreferredLocale
|
||||||
com.compose.sdl.res.preferredLocaleTagsProvider = { com.compose.sdl.text.systemPreferredLocaleTags() }
|
com.compose.sdl.res.preferredLocaleTagsProvider = { com.compose.sdl.text.systemPreferredLocaleTags() }
|
||||||
|
|
||||||
if (gpuMode is GpuMode.Skia.OpenGL) {
|
if (gpuMode is GpuMode.OpenGL) {
|
||||||
SDL_GL_SetAttribute(SDL_GLAttr.SDL_GL_CONTEXT_MAJOR_VERSION, 3)
|
SDL_GL_SetAttribute(SDL_GLAttr.SDL_GL_CONTEXT_MAJOR_VERSION, 3)
|
||||||
SDL_GL_SetAttribute(SDL_GLAttr.SDL_GL_CONTEXT_MINOR_VERSION, 2)
|
SDL_GL_SetAttribute(SDL_GLAttr.SDL_GL_CONTEXT_MINOR_VERSION, 2)
|
||||||
SDL_GL_SetAttribute(SDL_GLAttr.SDL_GL_CONTEXT_PROFILE_MASK,
|
SDL_GL_SetAttribute(SDL_GLAttr.SDL_GL_CONTEXT_PROFILE_MASK,
|
||||||
@@ -75,10 +84,16 @@ class SDL3Backend(
|
|||||||
SDL_GL_SetAttribute(SDL_GLAttr.SDL_GL_STENCIL_SIZE, 8)
|
SDL_GL_SetAttribute(SDL_GLAttr.SDL_GL_STENCIL_SIZE, 8)
|
||||||
}
|
}
|
||||||
|
|
||||||
val flags = SDL_WINDOW_RESIZABLE or SDL_WINDOW_HIGH_PIXEL_DENSITY or when (gpuMode) {
|
var attrFlags = SDL_WINDOW_HIGH_PIXEL_DENSITY
|
||||||
is GpuMode.Skia.OpenGL -> SDL_WINDOW_OPENGL
|
if (resizable) attrFlags = attrFlags or SDL_WINDOW_RESIZABLE
|
||||||
is GpuMode.Skia.Metal -> SDL_WINDOW_METAL
|
if (undecorated) attrFlags = attrFlags or SDL_WINDOW_BORDERLESS
|
||||||
is GpuMode.Software -> 0UL
|
if (transparent) attrFlags = attrFlags or SDL_WINDOW_TRANSPARENT
|
||||||
|
if (alwaysOnTop) attrFlags = attrFlags or SDL_WINDOW_ALWAYS_ON_TOP
|
||||||
|
if (!focusable) attrFlags = attrFlags or SDL_WINDOW_NOT_FOCUSABLE
|
||||||
|
val flags = attrFlags or when (gpuMode) {
|
||||||
|
is GpuMode.OpenGL -> SDL_WINDOW_OPENGL
|
||||||
|
is GpuMode.Metal -> SDL_WINDOW_METAL
|
||||||
|
is GpuMode.CpuRaster -> 0UL
|
||||||
is GpuMode.Auto -> error("unreachable")
|
is GpuMode.Auto -> error("unreachable")
|
||||||
}
|
}
|
||||||
window = SDL_CreateWindow(title, width, height, flags)
|
window = SDL_CreateWindow(title, width, height, flags)
|
||||||
@@ -88,7 +103,7 @@ class SDL3Backend(
|
|||||||
}
|
}
|
||||||
|
|
||||||
when (gpuMode) {
|
when (gpuMode) {
|
||||||
is GpuMode.Skia.OpenGL -> {
|
is GpuMode.OpenGL -> {
|
||||||
glContext = SDL_GL_CreateContext(window?.reinterpret())
|
glContext = SDL_GL_CreateContext(window?.reinterpret())
|
||||||
if (glContext == null) {
|
if (glContext == null) {
|
||||||
println("SDL_GL_CreateContext failed: ${SDL_GetError()?.toKString()}")
|
println("SDL_GL_CreateContext failed: ${SDL_GetError()?.toKString()}")
|
||||||
@@ -101,7 +116,7 @@ class SDL3Backend(
|
|||||||
// keeps its fallback frame cap.
|
// keeps its fallback frame cap.
|
||||||
vsyncEnabled = SDL_GL_SetSwapInterval(1)
|
vsyncEnabled = SDL_GL_SetSwapInterval(1)
|
||||||
}
|
}
|
||||||
is GpuMode.Skia.Metal -> {
|
is GpuMode.Metal -> {
|
||||||
metalView = SDL_Metal_CreateView(window?.reinterpret())
|
metalView = SDL_Metal_CreateView(window?.reinterpret())
|
||||||
if (metalView == null) {
|
if (metalView == null) {
|
||||||
println("SDL_Metal_CreateView failed: ${SDL_GetError()?.toKString()}")
|
println("SDL_Metal_CreateView failed: ${SDL_GetError()?.toKString()}")
|
||||||
@@ -111,7 +126,7 @@ class SDL3Backend(
|
|||||||
// blocks - so Metal is vsync-paced and the loop skips its delay.
|
// blocks - so Metal is vsync-paced and the loop skips its delay.
|
||||||
vsyncEnabled = true
|
vsyncEnabled = true
|
||||||
}
|
}
|
||||||
is GpuMode.Software -> {
|
is GpuMode.CpuRaster -> {
|
||||||
// Skia CPU raster: SkiaSurfaceBridge paints a host buffer that
|
// Skia CPU raster: SkiaSurfaceBridge paints a host buffer that
|
||||||
// this SDL_Renderer uploads as a texture each frame.
|
// this SDL_Renderer uploads as a texture each frame.
|
||||||
renderer = SDL_CreateRenderer(window?.reinterpret(), null)
|
renderer = SDL_CreateRenderer(window?.reinterpret(), null)
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
package com.compose.sdl.input
|
|
||||||
|
|
||||||
import androidx.compose.ui.input.pointer.PointerButton
|
|
||||||
import androidx.compose.ui.input.pointer.PointerEventType
|
|
||||||
|
|
||||||
// ==================
|
|
||||||
// MARK: LegacyPointerEvent (project-only)
|
|
||||||
// ==================
|
|
||||||
|
|
||||||
/** Project-only legacy event class used by the SDL3 input pipeline
|
|
||||||
(`SDL3EventMapper` → `AppEvent.Pointer` → `ComposeWindow`'s event loop).
|
|
||||||
The name `PointerEvent` is now reserved for upstream's multi-touch
|
|
||||||
vendored event (in androidx.compose.ui.input.pointer.PointerEvent);
|
|
||||||
this single-pointer (x, y, type, button) shape is the bridge between
|
|
||||||
raw SDL events and upstream-shaped PointerInputChange dispatch.
|
|
||||||
|
|
||||||
ComposeWindow constructs an upstream PointerEvent from this for
|
|
||||||
delivery to Modifier.pointerInput blocks. */
|
|
||||||
class LegacyPointerEvent(
|
|
||||||
// Kept as Float: SDL delivers sub-pixel cursor coordinates, and on HiDPI the
|
|
||||||
// value is multiplied by DPR before dispatch, so truncating to Int here would
|
|
||||||
// quantize the caret to whole-DPR steps (2px on a 2x display) near glyph edges.
|
|
||||||
val x: Float,
|
|
||||||
val y: Float,
|
|
||||||
val type: PointerEventType,
|
|
||||||
val button: PointerButton = PointerButton.Primary,
|
|
||||||
) {
|
|
||||||
override fun equals(other: Any?): Boolean = other is LegacyPointerEvent &&
|
|
||||||
other.x == x && other.y == y && other.type == type && other.button == button
|
|
||||||
override fun hashCode(): Int {
|
|
||||||
var h = x.hashCode(); h = 31 * h + y.hashCode(); h = 31 * h + type.hashCode(); h = 31 * h + button.hashCode(); return h
|
|
||||||
}
|
|
||||||
override fun toString(): String =
|
|
||||||
"LegacyPointerEvent(x=$x, y=$y, type=$type, button=$button)"
|
|
||||||
}
|
|
||||||
@@ -29,12 +29,12 @@ class ComposeRootHost(inDensity: Float = 1f) {
|
|||||||
// the root keeps LayoutNode's ErrorMeasurePolicy ("Undefined measure").
|
// the root keeps LayoutNode's ErrorMeasurePolicy ("Undefined measure").
|
||||||
measurePolicy = androidx.compose.ui.layout.RootMeasurePolicy
|
measurePolicy = androidx.compose.ui.layout.RootMeasurePolicy
|
||||||
}
|
}
|
||||||
private val fOwner = ComposeOwner(rootNode, Density(inDensity), LayoutDirection.Ltr)
|
private val mOwner = ComposeOwner(rootNode, Density(inDensity), LayoutDirection.Ltr)
|
||||||
private val fApplier = NodeApplier(rootNode)
|
private val mApplier = NodeApplier(rootNode)
|
||||||
|
|
||||||
// Upcast to the public supertype so the internal NodeApplier / LayoutNode
|
// Upcast to the public supertype so the internal NodeApplier / LayoutNode
|
||||||
// don't leak across the module boundary; Composition accepts Applier<*>.
|
// don't leak across the module boundary; Composition accepts Applier<*>.
|
||||||
val applier: Applier<*> get() = fApplier
|
val applier: Applier<*> get() = mApplier
|
||||||
|
|
||||||
fun attach() {
|
fun attach() {
|
||||||
// Install the focus root + drag-and-drop root on the root LayoutNode
|
// Install the focus root + drag-and-drop root on the root LayoutNode
|
||||||
@@ -43,8 +43,8 @@ class ComposeRootHost(inDensity: Float = 1f) {
|
|||||||
// focus root the focus tree has no origin and requestFocus never
|
// focus root the focus tree has no origin and requestFocus never
|
||||||
// sticks; without the DnD root the root DragAndDropNode never receives
|
// sticks; without the DnD root the root DragAndDropNode never receives
|
||||||
// events from Sdl3DragAndDropOwner's dispatch calls.
|
// events from Sdl3DragAndDropOwner's dispatch calls.
|
||||||
rootNode.modifier = fOwner.focusOwner.modifier.then(fOwner.dragAndDropManager.modifier)
|
rootNode.modifier = mOwner.focusOwner.modifier.then(mOwner.dragAndDropManager.modifier)
|
||||||
fOwner.attach()
|
mOwner.attach()
|
||||||
// Turn on snapshot observation so writes to `mutableStateOf` (ScrollState.value,
|
// Turn on snapshot observation so writes to `mutableStateOf` (ScrollState.value,
|
||||||
// LazyList firstVisibleItemIndex, etc.) fire the appropriate invalidation
|
// LazyList firstVisibleItemIndex, etc.) fire the appropriate invalidation
|
||||||
// callbacks - requestRelayout / requestRemeasure - routing through the vendored
|
// callbacks - requestRelayout / requestRemeasure - routing through the vendored
|
||||||
@@ -52,53 +52,53 @@ class ComposeRootHost(inDensity: Float = 1f) {
|
|||||||
// state but the placement lambda inside ScrollNode.measure never re-runs, so
|
// state but the placement lambda inside ScrollNode.measure never re-runs, so
|
||||||
// the child layer's move(IntOffset(0, -scroll)) never happens → scroll offset
|
// the child layer's move(IntOffset(0, -scroll)) never happens → scroll offset
|
||||||
// is invisible even though the state is updating.
|
// is invisible even though the state is updating.
|
||||||
fOwner.snapshotObserver.startObserving()
|
mOwner.snapshotObserver.startObserving()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setConstraints(inWidth: Int, inHeight: Int) {
|
fun setConstraints(inWidth: Int, inHeight: Int) {
|
||||||
fOwner.setRootConstraints(Constraints.fixed(inWidth, inHeight))
|
mOwner.setRootConstraints(Constraints.fixed(inWidth, inHeight))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pump the owner's node-animation frame clock (scroll fling / animateScrollToItem / node
|
// Pump the owner's node-animation frame clock (scroll fling / animateScrollToItem / node
|
||||||
// Animatables). Called once per frame by ComposeWindow with a monotonic nanos timestamp.
|
// Animatables). Called once per frame by ComposeWindow with a monotonic nanos timestamp.
|
||||||
fun sendAnimationFrame(inNanos: Long) {
|
fun sendAnimationFrame(inNanos: Long) {
|
||||||
fOwner.animationFrameClock.sendFrame(inNanos)
|
mOwner.animationFrameClock.sendFrame(inNanos)
|
||||||
}
|
}
|
||||||
|
|
||||||
// True while a node-level animation (scroll fling, node Animatable) awaits the next
|
// True while a node-level animation (scroll fling, node Animatable) awaits the next
|
||||||
// animation frame - the node half of the window's quiescence signal (render-to-quiescence
|
// animation frame - the node half of the window's quiescence signal (render-to-quiescence
|
||||||
// screenshot capture asks the window whether ANY work is still pending).
|
// screenshot capture asks the window whether ANY work is still pending).
|
||||||
fun hasAnimationAwaiters(): Boolean = fOwner.animationFrameClock.hasAwaiters
|
fun hasAnimationAwaiters(): Boolean = mOwner.animationFrameClock.hasAwaiters
|
||||||
|
|
||||||
fun measureAndLayout() {
|
fun measureAndLayout() {
|
||||||
// Flush deferred end-of-apply work (focus invalidation etc.) before measuring, so
|
// Flush deferred end-of-apply work (focus invalidation etc.) before measuring, so
|
||||||
// requestFocus() from composition OR from a pointer event this frame takes effect -
|
// requestFocus() from composition OR from a pointer event this frame takes effect -
|
||||||
// e.g. focus-on-click, which schedules a focus invalidation during event dispatch.
|
// e.g. focus-on-click, which schedules a focus invalidation during event dispatch.
|
||||||
fOwner.onEndApplyChanges()
|
mOwner.onEndApplyChanges()
|
||||||
fOwner.measureAndLayout()
|
mOwner.measureAndLayout()
|
||||||
// Drop snapshot observations whose scope is no longer valid (detached nodes,
|
// Drop snapshot observations whose scope is no longer valid (detached nodes,
|
||||||
// destroyed layers, disposed draw scopes). Upstream RootNodeOwner does this after
|
// destroyed layers, disposed draw scopes). Upstream RootNodeOwner does this after
|
||||||
// the measure pass; without it, every disposed subtree's measure/layout/DRAW
|
// the measure pass; without it, every disposed subtree's measure/layout/DRAW
|
||||||
// observation scopes linger in the OwnerSnapshotObserver forever - each pins its
|
// observation scopes linger in the OwnerSnapshotObserver forever - each pins its
|
||||||
// observed object graph (a leak the P2.2 soak caught on ripple/indication draws).
|
// observed object graph (a leak the P2.2 soak caught on ripple/indication draws).
|
||||||
fOwner.snapshotObserver.clearInvalidObservations()
|
mOwner.snapshotObserver.clearInvalidObservations()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the composed tree into [canvas] - re-records dirty layers, then walks
|
// Draw the composed tree into [canvas] - re-records dirty layers, then walks
|
||||||
// the root so clean layers replay their cached content. Backends call this
|
// the root so clean layers replay their cached content. Backends call this
|
||||||
// instead of rootNode.draw so retained-layer bookkeeping runs each frame.
|
// instead of rootNode.draw so retained-layer bookkeeping runs each frame.
|
||||||
fun drawRoot(canvas: androidx.compose.ui.graphics.Canvas) {
|
fun drawRoot(canvas: androidx.compose.ui.graphics.Canvas) {
|
||||||
fOwner.renderRoot(canvas)
|
mOwner.renderRoot(canvas)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The window wires this to set needsFrame - a layer whose content changed
|
// The window wires this to set needsFrame - a layer whose content changed
|
||||||
// (OwnedLayer.invalidate) schedules a frame even with nothing else pending.
|
// (OwnedLayer.invalidate) schedules a frame even with nothing else pending.
|
||||||
fun setInvalidationCallback(callback: () -> Unit) {
|
fun setInvalidationCallback(callback: () -> Unit) {
|
||||||
fOwner.onInvalidate = callback
|
mOwner.onInvalidate = callback
|
||||||
}
|
}
|
||||||
|
|
||||||
// The owner's FocusOwner IS a FocusManager - the window provides it as LocalFocusManager.
|
// The owner's FocusOwner IS a FocusManager - the window provides it as LocalFocusManager.
|
||||||
val focusManager: androidx.compose.ui.focus.FocusManager get() = fOwner.focusOwner
|
val focusManager: androidx.compose.ui.focus.FocusManager get() = mOwner.focusOwner
|
||||||
|
|
||||||
// ==================
|
// ==================
|
||||||
// MARK: Owner-backed values for the composition-locals seed
|
// MARK: Owner-backed values for the composition-locals seed
|
||||||
@@ -107,19 +107,19 @@ class ComposeRootHost(inDensity: Float = 1f) {
|
|||||||
// Provider; ComposeWindow wraps setContent in a CompositionLocalProvider whose
|
// Provider; ComposeWindow wraps setContent in a CompositionLocalProvider whose
|
||||||
// values come from the ComposeOwner attached below. These accessors expose the
|
// values come from the ComposeOwner attached below. These accessors expose the
|
||||||
// right fields without leaking the `internal Owner` interface across modules.
|
// right fields without leaking the `internal Owner` interface across modules.
|
||||||
val density: androidx.compose.ui.unit.Density get() = fOwner.density
|
val density: androidx.compose.ui.unit.Density get() = mOwner.density
|
||||||
val layoutDirection: androidx.compose.ui.unit.LayoutDirection get() = fOwner.layoutDirection
|
val layoutDirection: androidx.compose.ui.unit.LayoutDirection get() = mOwner.layoutDirection
|
||||||
val viewConfiguration: androidx.compose.ui.platform.ViewConfiguration get() = fOwner.viewConfiguration
|
val viewConfiguration: androidx.compose.ui.platform.ViewConfiguration get() = mOwner.viewConfiguration
|
||||||
val graphicsContext: androidx.compose.ui.graphics.GraphicsContext get() = fOwner.graphicsContext
|
val graphicsContext: androidx.compose.ui.graphics.GraphicsContext get() = mOwner.graphicsContext
|
||||||
val inputModeManager: androidx.compose.ui.input.InputModeManager get() = fOwner.inputModeManager
|
val inputModeManager: androidx.compose.ui.input.InputModeManager get() = mOwner.inputModeManager
|
||||||
val hapticFeedback: androidx.compose.ui.hapticfeedback.HapticFeedback get() = fOwner.hapticFeedBack
|
val hapticFeedback: androidx.compose.ui.hapticfeedback.HapticFeedback get() = mOwner.hapticFeedBack
|
||||||
val textToolbar: androidx.compose.ui.platform.TextToolbar get() = fOwner.textToolbar
|
val textToolbar: androidx.compose.ui.platform.TextToolbar get() = mOwner.textToolbar
|
||||||
val windowInfo: androidx.compose.ui.platform.WindowInfo get() = fOwner.windowInfo
|
val windowInfo: androidx.compose.ui.platform.WindowInfo get() = mOwner.windowInfo
|
||||||
|
|
||||||
// Push SDL window focus into windowInfo.isWindowFocused (focus-reactive UI).
|
// Push SDL window focus into windowInfo.isWindowFocused (focus-reactive UI).
|
||||||
fun setWindowFocused(inFocused: Boolean) = fOwner.setWindowFocused(inFocused)
|
fun setWindowFocused(inFocused: Boolean) = mOwner.setWindowFocused(inFocused)
|
||||||
val softwareKeyboardController: androidx.compose.ui.platform.SoftwareKeyboardController
|
val softwareKeyboardController: androidx.compose.ui.platform.SoftwareKeyboardController
|
||||||
get() = fOwner.softwareKeyboardController
|
get() = mOwner.softwareKeyboardController
|
||||||
|
|
||||||
// PointerIconService and its composition local are :ui-internal, so ComposeWindow
|
// PointerIconService and its composition local are :ui-internal, so ComposeWindow
|
||||||
// can't provide the local directly. This wrapper seeds it from the owner so
|
// can't provide the local directly. This wrapper seeds it from the owner so
|
||||||
@@ -127,7 +127,7 @@ class ComposeRootHost(inDensity: Float = 1f) {
|
|||||||
@androidx.compose.runtime.Composable
|
@androidx.compose.runtime.Composable
|
||||||
fun ProvidePointerIconService(content: @androidx.compose.runtime.Composable () -> Unit) {
|
fun ProvidePointerIconService(content: @androidx.compose.runtime.Composable () -> Unit) {
|
||||||
androidx.compose.runtime.CompositionLocalProvider(
|
androidx.compose.runtime.CompositionLocalProvider(
|
||||||
androidx.compose.ui.platform.LocalPointerIconService provides fOwner.pointerIconService,
|
androidx.compose.ui.platform.LocalPointerIconService provides mOwner.pointerIconService,
|
||||||
content = content,
|
content = content,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -140,7 +140,7 @@ class ComposeRootHost(inDensity: Float = 1f) {
|
|||||||
onKeyEvent) - drives text-field editing keys (backspace / arrows / enter) and
|
onKeyEvent) - drives text-field editing keys (backspace / arrows / enter) and
|
||||||
clickable Enter/Space activation. Returns true if some node consumed it. */
|
clickable Enter/Space activation. Returns true if some node consumed it. */
|
||||||
fun dispatchKeyEvent(inEvent: androidx.compose.ui.input.key.KeyEvent): Boolean =
|
fun dispatchKeyEvent(inEvent: androidx.compose.ui.input.key.KeyEvent): Boolean =
|
||||||
runCatching { fOwner.focusOwner.dispatchKeyEvent(inEvent) }.getOrDefault(false)
|
runCatching { mOwner.focusOwner.dispatchKeyEvent(inEvent) }.getOrDefault(false)
|
||||||
|
|
||||||
// ==================
|
// ==================
|
||||||
// MARK: Input - feed the vendored PointerInputEventProcessor
|
// MARK: Input - feed the vendored PointerInputEventProcessor
|
||||||
@@ -152,13 +152,13 @@ class ComposeRootHost(inDensity: Float = 1f) {
|
|||||||
// `expect PointerInputEvent` has no commonMain constructor, so the actual build+dispatch
|
// `expect PointerInputEvent` has no commonMain constructor, so the actual build+dispatch
|
||||||
// lives in nativeMain (feedPointerToProcessor).
|
// lives in nativeMain (feedPointerToProcessor).
|
||||||
fun onPointerRaw(inX: Float, inY: Float, inType: Int, inButton: Int, inUptime: Long) {
|
fun onPointerRaw(inX: Float, inY: Float, inType: Int, inButton: Int, inUptime: Long) {
|
||||||
feedPointerToProcessor(fOwner, inType, inButton, inUptime, inX, inY)
|
feedPointerToProcessor(mOwner, inType, inButton, inUptime, inX, inY)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mouse wheel - feed a scroll PointerInputEvent to the processor so the vendored
|
// Mouse wheel - feed a scroll PointerInputEvent to the processor so the vendored
|
||||||
// Modifier.scrollable (MouseWheelScrollingLogic) handles it, exactly like upstream.
|
// Modifier.scrollable (MouseWheelScrollingLogic) handles it, exactly like upstream.
|
||||||
fun onWheel(inX: Float, inY: Float, inDeltaX: Float, inDeltaY: Float, inUptime: Long) {
|
fun onWheel(inX: Float, inY: Float, inDeltaX: Float, inDeltaY: Float, inUptime: Long) {
|
||||||
feedScrollToProcessor(fOwner, inX, inY, inDeltaX, inDeltaY, inUptime)
|
feedScrollToProcessor(mOwner, inX, inY, inDeltaX, inDeltaY, inUptime)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================
|
// ==================
|
||||||
@@ -169,11 +169,11 @@ class ComposeRootHost(inDensity: Float = 1f) {
|
|||||||
// COMPLETE to these methods; Sdl3DragAndDropOwner accumulates the drop
|
// COMPLETE to these methods; Sdl3DragAndDropOwner accumulates the drop
|
||||||
// session and dispatches through the root DragAndDropNode on COMPLETE.
|
// session and dispatches through the root DragAndDropNode on COMPLETE.
|
||||||
|
|
||||||
fun onDropBegin() = fOwner.dragAndDropManager.dropBegin()
|
fun onDropBegin() = mOwner.dragAndDropManager.dropBegin()
|
||||||
fun onDropPosition(inX: Float, inY: Float) = fOwner.dragAndDropManager.dropPosition(inX, inY)
|
fun onDropPosition(inX: Float, inY: Float) = mOwner.dragAndDropManager.dropPosition(inX, inY)
|
||||||
fun onDropFile(inPath: String) = fOwner.dragAndDropManager.dropFile(inPath)
|
fun onDropFile(inPath: String) = mOwner.dragAndDropManager.dropFile(inPath)
|
||||||
fun onDropText(inText: String) = fOwner.dragAndDropManager.dropText(inText)
|
fun onDropText(inText: String) = mOwner.dragAndDropManager.dropText(inText)
|
||||||
fun onDropComplete() = fOwner.dragAndDropManager.dropComplete()
|
fun onDropComplete() = mOwner.dragAndDropManager.dropComplete()
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: feedPointerToProcessor / feedScrollToProcessor are plain nativeMain
|
// NOTE: feedPointerToProcessor / feedScrollToProcessor are plain nativeMain
|
||||||
|
|||||||
+9
-9
@@ -18,9 +18,9 @@ import com.compose.sdl.node.impl.ComposeOwner
|
|||||||
mouse down unless `buttons.isPrimaryPressed`, and drag/scroll gestures need the held button to
|
mouse down unless `buttons.isPrimaryPressed`, and drag/scroll gestures need the held button to
|
||||||
persist across Move events, so the synthesized PointerInputEvent must carry a live button mask -
|
persist across Move events, so the synthesized PointerInputEvent must carry a live button mask -
|
||||||
not just the changed button. A single mouse => module-level flags are enough. */
|
not just the changed button. A single mouse => module-level flags are enough. */
|
||||||
private var fPrimaryDown = false
|
private var mPrimaryDown = false
|
||||||
private var fSecondaryDown = false
|
private var mSecondaryDown = false
|
||||||
private var fTertiaryDown = false
|
private var mTertiaryDown = false
|
||||||
|
|
||||||
/** Builds the internal PointerInputEvent (its constructor is native-only) from a single mouse
|
/** Builds the internal PointerInputEvent (its constructor is native-only) from a single mouse
|
||||||
pointer and drives the owner's PointerInputEventProcessor. inType: 0=Move 1=Press 2=Release 3=Exit;
|
pointer and drives the owner's PointerInputEventProcessor. inType: 0=Move 1=Press 2=Release 3=Exit;
|
||||||
@@ -34,14 +34,14 @@ internal fun feedPointerToProcessor(
|
|||||||
inY: Float,
|
inY: Float,
|
||||||
) {
|
) {
|
||||||
when (inType) {
|
when (inType) {
|
||||||
1 -> when (inButton) { 0 -> fPrimaryDown = true; 1 -> fSecondaryDown = true; 2 -> fTertiaryDown = true }
|
1 -> when (inButton) { 0 -> mPrimaryDown = true; 1 -> mSecondaryDown = true; 2 -> mTertiaryDown = true }
|
||||||
2 -> when (inButton) { 0 -> fPrimaryDown = false; 1 -> fSecondaryDown = false; 2 -> fTertiaryDown = false }
|
2 -> when (inButton) { 0 -> mPrimaryDown = false; 1 -> mSecondaryDown = false; 2 -> mTertiaryDown = false }
|
||||||
}
|
}
|
||||||
|
|
||||||
val vButtons = PointerButtons(
|
val vButtons = PointerButtons(
|
||||||
isPrimaryPressed = fPrimaryDown,
|
isPrimaryPressed = mPrimaryDown,
|
||||||
isSecondaryPressed = fSecondaryDown,
|
isSecondaryPressed = mSecondaryDown,
|
||||||
isTertiaryPressed = fTertiaryDown,
|
isTertiaryPressed = mTertiaryDown,
|
||||||
)
|
)
|
||||||
val vButton = if (inType == 1 || inType == 2) {
|
val vButton = if (inType == 1 || inType == 2) {
|
||||||
when (inButton) {
|
when (inButton) {
|
||||||
@@ -57,7 +57,7 @@ internal fun feedPointerToProcessor(
|
|||||||
uptime = inUptime,
|
uptime = inUptime,
|
||||||
positionOnScreen = vPos,
|
positionOnScreen = vPos,
|
||||||
position = vPos,
|
position = vPos,
|
||||||
down = fPrimaryDown || fSecondaryDown || fTertiaryDown,
|
down = mPrimaryDown || mSecondaryDown || mTertiaryDown,
|
||||||
pressure = 1f,
|
pressure = 1f,
|
||||||
type = PointerType.Mouse,
|
type = PointerType.Mouse,
|
||||||
activeHover = inType == 0, // Exit (3) also reports no active hover
|
activeHover = inType == 0, // Exit (3) also reports no active hover
|
||||||
|
|||||||
@@ -80,28 +80,28 @@ internal class ComposeOwner(
|
|||||||
) : Owner, OwnedLayerManager {
|
) : Owner, OwnedLayerManager {
|
||||||
|
|
||||||
// The vendored measure/layout state machine, rooted at [root].
|
// The vendored measure/layout state machine, rooted at [root].
|
||||||
private val fDelegate = MeasureAndLayoutDelegate(root)
|
private val mDelegate = MeasureAndLayoutDelegate(root)
|
||||||
|
|
||||||
// The vendored pointer-input dispatcher. Routes a PointerInputEvent through
|
// The vendored pointer-input dispatcher. Routes a PointerInputEvent through
|
||||||
// HitPathTracker to the tree's PointerInputModifierNodes (hover / gesture),
|
// HitPathTracker to the tree's PointerInputModifierNodes (hover / gesture),
|
||||||
// synthesizing Enter/Exit. Fed from ComposeWindow via ComposeRootHost.
|
// synthesizing Enter/Exit. Fed from ComposeWindow via ComposeRootHost.
|
||||||
private val fPointerProcessor = androidx.compose.ui.input.pointer.PointerInputEventProcessor(root)
|
private val mPointerProcessor = androidx.compose.ui.input.pointer.PointerInputEventProcessor(root)
|
||||||
|
|
||||||
// Window focus + container size backing [windowInfo], snapshot-backed so
|
// Window focus + container size backing [windowInfo], snapshot-backed so
|
||||||
// focus-reactive UI and LocalWindowInfo.containerSize readers recompose. Fed by
|
// focus-reactive UI and LocalWindowInfo.containerSize readers recompose. Fed by
|
||||||
// the window: focus via setWindowFocused (SDL activation), size from setRootConstraints.
|
// the window: focus via setWindowFocused (SDL activation), size from setRootConstraints.
|
||||||
private val fWindowFocused = androidx.compose.runtime.mutableStateOf(true)
|
private val mWindowFocused = androidx.compose.runtime.mutableStateOf(true)
|
||||||
private val fContainerSize = androidx.compose.runtime.mutableStateOf(androidx.compose.ui.unit.IntSize.Zero)
|
private val mContainerSize = androidx.compose.runtime.mutableStateOf(androidx.compose.ui.unit.IntSize.Zero)
|
||||||
|
|
||||||
// Called by the window on SDL focus gain/loss.
|
// Called by the window on SDL focus gain/loss.
|
||||||
internal fun setWindowFocused(inFocused: Boolean) { fWindowFocused.value = inFocused }
|
internal fun setWindowFocused(inFocused: Boolean) { mWindowFocused.value = inFocused }
|
||||||
|
|
||||||
// Dispatch one pointer event to the upstream PointerInputModifierNode tree.
|
// Dispatch one pointer event to the upstream PointerInputModifierNode tree.
|
||||||
// [this] is the PositionCalculator (Owner : PositionCalculator).
|
// [this] is the PositionCalculator (Owner : PositionCalculator).
|
||||||
internal fun processPointerInput(inEvent: androidx.compose.ui.input.pointer.PointerInputEvent): Boolean {
|
internal fun processPointerInput(inEvent: androidx.compose.ui.input.pointer.PointerInputEvent): Boolean {
|
||||||
val vResult = fPointerProcessor.process(inEvent, this)
|
val vResult = mPointerProcessor.process(inEvent, this)
|
||||||
// Apply the cursor the hover pipeline just set for this event (deduped in SdlCursors).
|
// Apply the cursor the hover pipeline just set for this event (deduped in SdlCursors).
|
||||||
com.compose.sdl.SdlCursors.apply(fPointerIcon)
|
com.compose.sdl.SdlCursors.apply(mPointerIcon)
|
||||||
return vResult.dispatchedToAPointerInputModifier
|
return vResult.dispatchedToAPointerInputModifier
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,11 +115,11 @@ internal class ComposeOwner(
|
|||||||
// Sets the constraints the root is measured against (window pixel size in
|
// Sets the constraints the root is measured against (window pixel size in
|
||||||
// logical points). Call each frame before [measureAndLayout].
|
// logical points). Call each frame before [measureAndLayout].
|
||||||
fun setRootConstraints(inConstraints: Constraints) {
|
fun setRootConstraints(inConstraints: Constraints) {
|
||||||
fDelegate.updateRootConstraints(inConstraints)
|
mDelegate.updateRootConstraints(inConstraints)
|
||||||
// Report the container size (physical px, the port's layout coord space) to
|
// Report the container size (physical px, the port's layout coord space) to
|
||||||
// windowInfo; updates on every resize since the window re-measures per frame.
|
// windowInfo; updates on every resize since the window re-measures per frame.
|
||||||
if (inConstraints.hasBoundedWidth && inConstraints.hasBoundedHeight) {
|
if (inConstraints.hasBoundedWidth && inConstraints.hasBoundedHeight) {
|
||||||
fContainerSize.value =
|
mContainerSize.value =
|
||||||
androidx.compose.ui.unit.IntSize(inConstraints.maxWidth, inConstraints.maxHeight)
|
androidx.compose.ui.unit.IntSize(inConstraints.maxWidth, inConstraints.maxHeight)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,8 +138,8 @@ internal class ComposeOwner(
|
|||||||
forceRequest: Boolean,
|
forceRequest: Boolean,
|
||||||
scheduleMeasureAndLayout: Boolean,
|
scheduleMeasureAndLayout: Boolean,
|
||||||
) {
|
) {
|
||||||
if (affectsLookahead) fDelegate.requestLookaheadRemeasure(layoutNode, forceRequest)
|
if (affectsLookahead) mDelegate.requestLookaheadRemeasure(layoutNode, forceRequest)
|
||||||
else fDelegate.requestRemeasure(layoutNode, forceRequest)
|
else mDelegate.requestRemeasure(layoutNode, forceRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onRequestRelayout(
|
override fun onRequestRelayout(
|
||||||
@@ -147,25 +147,25 @@ internal class ComposeOwner(
|
|||||||
affectsLookahead: Boolean,
|
affectsLookahead: Boolean,
|
||||||
forceRequest: Boolean,
|
forceRequest: Boolean,
|
||||||
) {
|
) {
|
||||||
if (affectsLookahead) fDelegate.requestLookaheadRelayout(layoutNode, forceRequest)
|
if (affectsLookahead) mDelegate.requestLookaheadRelayout(layoutNode, forceRequest)
|
||||||
else fDelegate.requestRelayout(layoutNode, forceRequest)
|
else mDelegate.requestRelayout(layoutNode, forceRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun measureAndLayout(sendPointerUpdate: Boolean) {
|
override fun measureAndLayout(sendPointerUpdate: Boolean) {
|
||||||
fDelegate.measureAndLayout()
|
mDelegate.measureAndLayout()
|
||||||
fDelegate.dispatchOnPositionedCallbacks()
|
mDelegate.dispatchOnPositionedCallbacks()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun measureAndLayout(layoutNode: LayoutNode, constraints: Constraints) {
|
override fun measureAndLayout(layoutNode: LayoutNode, constraints: Constraints) {
|
||||||
fDelegate.measureAndLayout(layoutNode, constraints)
|
mDelegate.measureAndLayout(layoutNode, constraints)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun forceMeasureTheSubtree(layoutNode: LayoutNode, affectsLookahead: Boolean) {
|
override fun forceMeasureTheSubtree(layoutNode: LayoutNode, affectsLookahead: Boolean) {
|
||||||
fDelegate.forceMeasureTheSubtree(layoutNode, affectsLookahead)
|
mDelegate.forceMeasureTheSubtree(layoutNode, affectsLookahead)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDetach(node: LayoutNode) {
|
override fun onDetach(node: LayoutNode) {
|
||||||
fDelegate.onNodeDetached(node)
|
mDelegate.onNodeDetached(node)
|
||||||
// Drop the detached node's read-observation scopes, exactly as upstream
|
// Drop the detached node's read-observation scopes, exactly as upstream
|
||||||
// RootNodeOwner.onDetach does. Without this, every disposed node's measure/
|
// RootNodeOwner.onDetach does. Without this, every disposed node's measure/
|
||||||
// layout/draw observation scopes accumulate in the snapshot observer forever
|
// layout/draw observation scopes accumulate in the snapshot observer forever
|
||||||
@@ -174,7 +174,7 @@ internal class ComposeOwner(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun registerOnLayoutCompletedListener(listener: Owner.OnLayoutCompletedListener) {
|
override fun registerOnLayoutCompletedListener(listener: Owner.OnLayoutCompletedListener) {
|
||||||
fDelegate.registerOnLayoutCompletedListener(listener)
|
mDelegate.registerOnLayoutCompletedListener(listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun requestOnPositionedCallback(layoutNode: LayoutNode) = Unit
|
override fun requestOnPositionedCallback(layoutNode: LayoutNode) = Unit
|
||||||
@@ -345,12 +345,12 @@ internal class ComposeOwner(
|
|||||||
}
|
}
|
||||||
// Desired hover cursor, set by the vendored HoverIconModifierNode
|
// Desired hover cursor, set by the vendored HoverIconModifierNode
|
||||||
// (Modifier.pointerHoverIcon) and applied via SDL in processPointerInput. null = default.
|
// (Modifier.pointerHoverIcon) and applied via SDL in processPointerInput. null = default.
|
||||||
private var fPointerIcon: androidx.compose.ui.input.pointer.PointerIcon =
|
private var mPointerIcon: androidx.compose.ui.input.pointer.PointerIcon =
|
||||||
androidx.compose.ui.input.pointer.PointerIcon.Default
|
androidx.compose.ui.input.pointer.PointerIcon.Default
|
||||||
override val pointerIconService: PointerIconService = object : PointerIconService {
|
override val pointerIconService: PointerIconService = object : PointerIconService {
|
||||||
override fun getIcon(): androidx.compose.ui.input.pointer.PointerIcon = fPointerIcon
|
override fun getIcon(): androidx.compose.ui.input.pointer.PointerIcon = mPointerIcon
|
||||||
override fun setIcon(value: androidx.compose.ui.input.pointer.PointerIcon?) {
|
override fun setIcon(value: androidx.compose.ui.input.pointer.PointerIcon?) {
|
||||||
fPointerIcon = value ?: androidx.compose.ui.input.pointer.PointerIcon.Default
|
mPointerIcon = value ?: androidx.compose.ui.input.pointer.PointerIcon.Default
|
||||||
}
|
}
|
||||||
override fun getStylusHoverIcon(): androidx.compose.ui.input.pointer.PointerIcon? = null
|
override fun getStylusHoverIcon(): androidx.compose.ui.input.pointer.PointerIcon? = null
|
||||||
override fun setStylusHoverIcon(value: androidx.compose.ui.input.pointer.PointerIcon?) {}
|
override fun setStylusHoverIcon(value: androidx.compose.ui.input.pointer.PointerIcon?) {}
|
||||||
@@ -368,13 +368,13 @@ internal class ComposeOwner(
|
|||||||
owner = this,
|
owner = this,
|
||||||
)
|
)
|
||||||
override val windowInfo: WindowInfo = object : WindowInfo {
|
override val windowInfo: WindowInfo = object : WindowInfo {
|
||||||
override val isWindowFocused: Boolean get() = fWindowFocused.value
|
override val isWindowFocused: Boolean get() = mWindowFocused.value
|
||||||
override val containerSize: androidx.compose.ui.unit.IntSize get() = fContainerSize.value
|
override val containerSize: androidx.compose.ui.unit.IntSize get() = mContainerSize.value
|
||||||
override val containerDpSize: androidx.compose.ui.unit.DpSize
|
override val containerDpSize: androidx.compose.ui.unit.DpSize
|
||||||
get() = with(density) {
|
get() = with(density) {
|
||||||
androidx.compose.ui.unit.DpSize(
|
androidx.compose.ui.unit.DpSize(
|
||||||
fContainerSize.value.width.toDp(),
|
mContainerSize.value.width.toDp(),
|
||||||
fContainerSize.value.height.toDp(),
|
mContainerSize.value.height.toDp(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -412,16 +412,16 @@ internal class ComposeOwner(
|
|||||||
// End-of-apply-changes listeners - the focus system (FocusInvalidationManager) and other
|
// End-of-apply-changes listeners - the focus system (FocusInvalidationManager) and other
|
||||||
// engine parts register here to defer work until changes are applied; without this the
|
// engine parts register here to defer work until changes are applied; without this the
|
||||||
// focus invalidation never flushes and requestFocus() (e.g. focus-on-click) never sticks.
|
// focus invalidation never flushes and requestFocus() (e.g. focus-on-click) never sticks.
|
||||||
private val fEndApplyChangesListeners = mutableListOf<() -> Unit>()
|
private val mEndApplyChangesListeners = mutableListOf<() -> Unit>()
|
||||||
|
|
||||||
override fun registerOnEndApplyChangesListener(listener: () -> Unit) {
|
override fun registerOnEndApplyChangesListener(listener: () -> Unit) {
|
||||||
if (listener !in fEndApplyChangesListeners) fEndApplyChangesListeners.add(listener)
|
if (listener !in mEndApplyChangesListeners) mEndApplyChangesListeners.add(listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onEndApplyChanges() {
|
override fun onEndApplyChanges() {
|
||||||
// Drain in order; listeners may re-register, so loop until empty.
|
// Drain in order; listeners may re-register, so loop until empty.
|
||||||
while (fEndApplyChangesListeners.isNotEmpty()) {
|
while (mEndApplyChangesListeners.isNotEmpty()) {
|
||||||
val vListener = fEndApplyChangesListeners.removeAt(0)
|
val vListener = mEndApplyChangesListeners.removeAt(0)
|
||||||
vListener()
|
vListener()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ import com.compose.sdl.loadComposeResourceBytes
|
|||||||
*
|
*
|
||||||
* Idempotent; called from ComposeWindow.installGlobals (data.kres is loadable by then).
|
* Idempotent; called from ComposeWindow.installGlobals (data.kres is loadable by then).
|
||||||
*/
|
*/
|
||||||
private var fRegistered = false
|
private var mRegistered = false
|
||||||
|
|
||||||
fun registerGenericFonts() {
|
fun registerGenericFonts() {
|
||||||
if (fRegistered) return
|
if (mRegistered) return
|
||||||
fRegistered = true
|
mRegistered = true
|
||||||
loadComposeResourceBytes("font/NotoSansMono.ttf")?.let { IconFont.register("generic:monospace", it) }
|
loadComposeResourceBytes("font/NotoSansMono.ttf")?.let { IconFont.register("generic:monospace", it) }
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -6,4 +6,4 @@ import com.compose.sdl.renderer.skia.SkiaBridge
|
|||||||
// MARK: Linux GPU defaults
|
// MARK: Linux GPU defaults
|
||||||
// ==================
|
// ==================
|
||||||
|
|
||||||
internal actual fun makeMetalBridge(backend: SDL3Backend): SkiaBridge? = null
|
internal actual fun makeMetalBridge(backend: Sdl3Backend): SkiaBridge? = null
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ package com.compose.sdl
|
|||||||
import com.compose.sdl.renderer.skia.SkiaBridge
|
import com.compose.sdl.renderer.skia.SkiaBridge
|
||||||
import com.compose.sdl.renderer.skia.SkiaMetalBridge
|
import com.compose.sdl.renderer.skia.SkiaMetalBridge
|
||||||
|
|
||||||
internal actual fun makeMetalBridge(backend: SDL3Backend): SkiaBridge? {
|
internal actual fun makeMetalBridge(backend: Sdl3Backend): SkiaBridge? {
|
||||||
val bridge = SkiaMetalBridge(backend)
|
val bridge = SkiaMetalBridge(backend)
|
||||||
return if (bridge.init()) bridge else null
|
return if (bridge.init()) bridge else null
|
||||||
}
|
}
|
||||||
+43
-43
@@ -37,16 +37,16 @@ import sdl3.SDL_Metal_GetLayer
|
|||||||
per frame, so we tear the BackendRenderTarget + Surface down every frame
|
per frame, so we tear the BackendRenderTarget + Surface down every frame
|
||||||
(cheap - the DirectContext + device + queue persist). */
|
(cheap - the DirectContext + device + queue persist). */
|
||||||
@OptIn(ExperimentalForeignApi::class, BetaInteropApi::class)
|
@OptIn(ExperimentalForeignApi::class, BetaInteropApi::class)
|
||||||
internal class SkiaMetalBridge(private val backend: SDL3Backend) : SkiaBridge {
|
internal class SkiaMetalBridge(private val backend: Sdl3Backend) : SkiaBridge {
|
||||||
private var fDevice: MTLDeviceProtocol? = null
|
private var mDevice: MTLDeviceProtocol? = null
|
||||||
private var fQueue: MTLCommandQueueProtocol? = null
|
private var mQueue: MTLCommandQueueProtocol? = null
|
||||||
private var fLayer: CAMetalLayer? = null
|
private var mLayer: CAMetalLayer? = null
|
||||||
private var fContext: DirectContext? = null
|
private var mContext: DirectContext? = null
|
||||||
private var fSurface: Surface? = null
|
private var mSurface: Surface? = null
|
||||||
private var fRT: BackendRenderTarget? = null
|
private var mRT: BackendRenderTarget? = null
|
||||||
private var fDrawable: CAMetalDrawableProtocol? = null
|
private var mDrawable: CAMetalDrawableProtocol? = null
|
||||||
private var fWidth = 0
|
private var mWidth = 0
|
||||||
private var fHeight = 0
|
private var mHeight = 0
|
||||||
|
|
||||||
fun init(): Boolean {
|
fun init(): Boolean {
|
||||||
val vView = backend.metalView ?: run {
|
val vView = backend.metalView ?: run {
|
||||||
@@ -84,22 +84,22 @@ internal class SkiaMetalBridge(private val backend: SDL3Backend) : SkiaBridge {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fDevice = vDevice
|
mDevice = vDevice
|
||||||
fQueue = vQueue
|
mQueue = vQueue
|
||||||
fLayer = vLayer
|
mLayer = vLayer
|
||||||
fContext = vContext
|
mContext = vContext
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override val canvas: Canvas
|
override val canvas: Canvas
|
||||||
get() = requireNotNull(fSurface) { "SkiaMetalBridge not initialised" }.canvas
|
get() = requireNotNull(mSurface) { "SkiaMetalBridge not initialised" }.canvas
|
||||||
|
|
||||||
override fun ensureSize(inWidth: Int, inHeight: Int): Boolean {
|
override fun ensureSize(inWidth: Int, inHeight: Int): Boolean {
|
||||||
if (inWidth <= 0 || inHeight <= 0) return false
|
if (inWidth <= 0 || inHeight <= 0) return false
|
||||||
val vLayer = fLayer ?: return false
|
val vLayer = mLayer ?: return false
|
||||||
val vContext = fContext ?: return false
|
val vContext = mContext ?: return false
|
||||||
|
|
||||||
if (inWidth != fWidth || inHeight != fHeight) {
|
if (inWidth != mWidth || inHeight != mHeight) {
|
||||||
vLayer.drawableSize = CGSizeMake(inWidth.toDouble(), inHeight.toDouble())
|
vLayer.drawableSize = CGSizeMake(inWidth.toDouble(), inHeight.toDouble())
|
||||||
// Keep contentsScale in lock-step with the live backing density.
|
// Keep contentsScale in lock-step with the live backing density.
|
||||||
// Setting it only in init() can leave it stale at 1.0 when the
|
// Setting it only in init() can leave it stale at 1.0 when the
|
||||||
@@ -107,18 +107,18 @@ internal class SkiaMetalBridge(private val backend: SDL3Backend) : SkiaBridge {
|
|||||||
// drawable then gets downscaled to the layer's logical backing and
|
// drawable then gets downscaled to the layer's logical backing and
|
||||||
// re-upscaled by the display, softening text and aliasing edges.
|
// re-upscaled by the display, softening text and aliasing edges.
|
||||||
vLayer.contentsScale = backend.pixelDensity.toDouble()
|
vLayer.contentsScale = backend.pixelDensity.toDouble()
|
||||||
fWidth = inWidth
|
mWidth = inWidth
|
||||||
fHeight = inHeight
|
mHeight = inHeight
|
||||||
println("SkiaMetalBridge: drawable ${inWidth}x${inHeight} @ contentsScale ${backend.pixelDensity}")
|
println("SkiaMetalBridge: drawable ${inWidth}x${inHeight} @ contentsScale ${backend.pixelDensity}")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Per-frame: drop the previous frame's drawable wrappers and grab a
|
// Per-frame: drop the previous frame's drawable wrappers and grab a
|
||||||
// fresh one. nextDrawable() may block (~16ms vsync) when 3 drawables
|
// fresh one. nextDrawable() may block (~16ms vsync) when 3 drawables
|
||||||
// are already in flight - that's the natural pacing mechanism.
|
// are already in flight - that's the natural pacing mechanism.
|
||||||
fSurface?.close()
|
mSurface?.close()
|
||||||
fRT?.close()
|
mRT?.close()
|
||||||
fSurface = null
|
mSurface = null
|
||||||
fRT = null
|
mRT = null
|
||||||
|
|
||||||
val vDrawable = vLayer.nextDrawable() ?: run {
|
val vDrawable = vLayer.nextDrawable() ?: run {
|
||||||
println("SkiaMetalBridge: nextDrawable returned null")
|
println("SkiaMetalBridge: nextDrawable returned null")
|
||||||
@@ -142,38 +142,38 @@ internal class SkiaMetalBridge(private val backend: SDL3Backend) : SkiaBridge {
|
|||||||
println("SkiaMetalBridge: Surface.makeFromBackendRenderTarget returned null")
|
println("SkiaMetalBridge: Surface.makeFromBackendRenderTarget returned null")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
fRT = vRT
|
mRT = vRT
|
||||||
fSurface = vSurface
|
mSurface = vSurface
|
||||||
fDrawable = vDrawable
|
mDrawable = vDrawable
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun present() {
|
override fun present() {
|
||||||
val vSurface = fSurface ?: return
|
val vSurface = mSurface ?: return
|
||||||
val vQueue = fQueue ?: return
|
val vQueue = mQueue ?: return
|
||||||
val vDrawable = fDrawable ?: return
|
val vDrawable = mDrawable ?: return
|
||||||
vSurface.flushAndSubmit()
|
vSurface.flushAndSubmit()
|
||||||
val vCommandBuffer = vQueue.commandBuffer() ?: return
|
val vCommandBuffer = vQueue.commandBuffer() ?: return
|
||||||
vCommandBuffer.presentDrawable(vDrawable)
|
vCommandBuffer.presentDrawable(vDrawable)
|
||||||
vCommandBuffer.commit()
|
vCommandBuffer.commit()
|
||||||
fDrawable = null
|
mDrawable = null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun snapshot(): Image? = fSurface?.makeImageSnapshot()
|
override fun snapshot(): Image? = mSurface?.makeImageSnapshot()
|
||||||
|
|
||||||
override fun snapshotBgra(): Triple<Int, Int, ByteArray>? =
|
override fun snapshotBgra(): Triple<Int, Int, ByteArray>? =
|
||||||
readBackBgra(fSurface, fWidth, fHeight)
|
readBackBgra(mSurface, mWidth, mHeight)
|
||||||
|
|
||||||
override fun destroy() {
|
override fun destroy() {
|
||||||
fSurface?.close()
|
mSurface?.close()
|
||||||
fRT?.close()
|
mRT?.close()
|
||||||
fContext?.close()
|
mContext?.close()
|
||||||
fSurface = null
|
mSurface = null
|
||||||
fRT = null
|
mRT = null
|
||||||
fContext = null
|
mContext = null
|
||||||
fLayer = null
|
mLayer = null
|
||||||
fQueue = null
|
mQueue = null
|
||||||
fDevice = null
|
mDevice = null
|
||||||
fDrawable = null
|
mDrawable = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,17 +7,17 @@ import kotlin.experimental.ExperimentalNativeApi
|
|||||||
// MARK: Metal bridge factory (skia-only)
|
// MARK: Metal bridge factory (skia-only)
|
||||||
// ==================
|
// ==================
|
||||||
|
|
||||||
internal expect fun makeMetalBridge(backend: SDL3Backend): SkiaBridge?
|
internal expect fun makeMetalBridge(backend: Sdl3Backend): SkiaBridge?
|
||||||
|
|
||||||
actual fun rendererPreferredGpuMode(): GpuMode {
|
actual fun rendererPreferredGpuMode(): GpuMode {
|
||||||
@OptIn(ExperimentalNativeApi::class)
|
@OptIn(ExperimentalNativeApi::class)
|
||||||
return when (Platform.osFamily) {
|
return when (Platform.osFamily) {
|
||||||
OsFamily.MACOSX -> GpuMode.Skia.Metal
|
OsFamily.MACOSX -> GpuMode.Metal
|
||||||
OsFamily.LINUX -> GpuMode.Skia.OpenGL
|
OsFamily.LINUX -> GpuMode.OpenGL
|
||||||
// Windows (mingwX64, Route 1a): GPU via Skia's GL backend on an SDL WGL
|
// Windows (mingwX64, Route 1a): GPU via Skia's GL backend on an SDL WGL
|
||||||
// context (SkiaGLBridge, shared with Linux). CPU raster stays available
|
// context (SkiaGLBridge, shared with Linux). CPU raster stays available
|
||||||
// as --gpu=software. (A native D3D12 bridge is the milestone-2 upgrade.)
|
// as --gpu=software. (A native D3D12 bridge is the milestone-2 upgrade.)
|
||||||
OsFamily.WINDOWS -> GpuMode.Skia.OpenGL
|
OsFamily.WINDOWS -> GpuMode.OpenGL
|
||||||
else -> GpuMode.Software
|
else -> GpuMode.CpuRaster
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ import com.compose.sdl.renderer.skia.SkiaRenderBackend
|
|||||||
actual delegates here when Skia is the selected renderer). Mirrors the
|
actual delegates here when Skia is the selected renderer). Mirrors the
|
||||||
SDL3 module's createRenderBackend / rendererPreferredGpuMode in the same
|
SDL3 module's createRenderBackend / rendererPreferredGpuMode in the same
|
||||||
package; exactly one renderer module is included per target. */
|
package; exactly one renderer module is included per target. */
|
||||||
actual fun createRenderBackend(inSdl: SDL3Backend, inGpu: GpuMode): RenderBackend? {
|
actual fun createRenderBackend(inSdl: Sdl3Backend, inGpu: GpuMode): RenderBackend? {
|
||||||
val vResolved = if (inGpu is GpuMode.Auto) rendererPreferredGpuMode() else inGpu
|
val vResolved = if (inGpu is GpuMode.Auto) rendererPreferredGpuMode() else inGpu
|
||||||
return try {
|
return try {
|
||||||
SkiaRenderBackend(inSdl, vResolved)
|
SkiaRenderBackend(inSdl, vResolved)
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ import org.jetbrains.skia.Image
|
|||||||
per frame; the concrete implementation owns whatever GPU / CPU
|
per frame; the concrete implementation owns whatever GPU / CPU
|
||||||
resources it needs (raster buffer + SDL_Texture, or a GL/Metal backend
|
resources it needs (raster buffer + SDL_Texture, or a GL/Metal backend
|
||||||
render target). */
|
render target). */
|
||||||
interface SkiaBridge {
|
internal interface SkiaBridge {
|
||||||
val canvas: Canvas
|
val canvas: Canvas
|
||||||
fun ensureSize(inWidth: Int, inHeight: Int): Boolean
|
fun ensureSize(inWidth: Int, inHeight: Int): Boolean
|
||||||
fun present()
|
fun present()
|
||||||
|
|||||||
+57
-32
@@ -4,16 +4,13 @@ import com.compose.sdl.*
|
|||||||
|
|
||||||
import kotlinx.cinterop.*
|
import kotlinx.cinterop.*
|
||||||
import org.jetbrains.skia.BackendRenderTarget
|
import org.jetbrains.skia.BackendRenderTarget
|
||||||
import org.jetbrains.skia.Bitmap
|
|
||||||
import org.jetbrains.skia.Canvas
|
import org.jetbrains.skia.Canvas
|
||||||
import org.jetbrains.skia.ColorAlphaType
|
|
||||||
import org.jetbrains.skia.ColorType
|
|
||||||
import org.jetbrains.skia.DirectContext
|
import org.jetbrains.skia.DirectContext
|
||||||
import org.jetbrains.skia.Image
|
import org.jetbrains.skia.Image
|
||||||
import org.jetbrains.skia.ImageInfo
|
|
||||||
import org.jetbrains.skia.Surface
|
import org.jetbrains.skia.Surface
|
||||||
import org.jetbrains.skia.SurfaceColorFormat
|
import org.jetbrains.skia.SurfaceColorFormat
|
||||||
import org.jetbrains.skia.SurfaceOrigin
|
import org.jetbrains.skia.SurfaceOrigin
|
||||||
|
import sdl3.SDL_GL_MakeCurrent
|
||||||
import sdl3.SDL_GL_SwapWindow
|
import sdl3.SDL_GL_SwapWindow
|
||||||
|
|
||||||
// ==================
|
// ==================
|
||||||
@@ -27,17 +24,38 @@ import sdl3.SDL_GL_SwapWindow
|
|||||||
Resize: tear down and rebuild the BackendRenderTarget + Surface; the
|
Resize: tear down and rebuild the BackendRenderTarget + Surface; the
|
||||||
DirectContext is reused. The default GL framebuffer (id 0) is wrapped
|
DirectContext is reused. The default GL framebuffer (id 0) is wrapped
|
||||||
directly; we don't manage an offscreen FBO. */
|
directly; we don't manage an offscreen FBO. */
|
||||||
internal class SkiaGLBridge(private val backend: SDL3Backend) : SkiaBridge {
|
internal class SkiaGLBridge(private val backend: Sdl3Backend) : SkiaBridge {
|
||||||
private var fContext: DirectContext? = null
|
private var mContext: DirectContext? = null
|
||||||
private var fRT: BackendRenderTarget? = null
|
private var mRT: BackendRenderTarget? = null
|
||||||
private var fSurface: Surface? = null
|
private var mSurface: Surface? = null
|
||||||
private var fWidth = 0
|
private var mWidth = 0
|
||||||
private var fHeight = 0
|
private var mHeight = 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
Binds THIS window's GL context to the calling thread.
|
||||||
|
|
||||||
|
A GL context is per-window but "current" is per-THREAD state, so with more
|
||||||
|
than one window open the last one to touch GL owns the thread. SDL makes a
|
||||||
|
context current once at creation (Sdl3Backend.init) and nothing re-bound it
|
||||||
|
per frame, so window A issued its draw and swap against window B's context:
|
||||||
|
silent corruption while both live, and a hard crash (SIGSEGV in present)
|
||||||
|
the moment B is destroyed and the current context is left dangling.
|
||||||
|
|
||||||
|
Every entry point that touches GL calls this first. Cheap when already
|
||||||
|
current - SDL short-circuits a redundant bind, so the single-window path
|
||||||
|
pays nothing.
|
||||||
|
*/
|
||||||
|
private fun makeCurrent() {
|
||||||
|
val vWindow = backend.window ?: return
|
||||||
|
val vContext = backend.glContext ?: return
|
||||||
|
SDL_GL_MakeCurrent(vWindow.reinterpret(), vContext.reinterpret())
|
||||||
|
}
|
||||||
|
|
||||||
fun init(): Boolean {
|
fun init(): Boolean {
|
||||||
return try {
|
return try {
|
||||||
fContext = DirectContext.makeGL()
|
makeCurrent()
|
||||||
fContext != null
|
mContext = DirectContext.makeGL()
|
||||||
|
mContext != null
|
||||||
} catch (t: Throwable) {
|
} catch (t: Throwable) {
|
||||||
println("SkiaGLBridge: DirectContext.makeGL failed: ${t.message}")
|
println("SkiaGLBridge: DirectContext.makeGL failed: ${t.message}")
|
||||||
false
|
false
|
||||||
@@ -45,17 +63,20 @@ internal class SkiaGLBridge(private val backend: SDL3Backend) : SkiaBridge {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override val canvas: Canvas
|
override val canvas: Canvas
|
||||||
get() = requireNotNull(fSurface) { "SkiaGLBridge not initialised" }.canvas
|
get() = requireNotNull(mSurface) { "SkiaGLBridge not initialised" }.canvas
|
||||||
|
|
||||||
override fun ensureSize(inWidth: Int, inHeight: Int): Boolean {
|
override fun ensureSize(inWidth: Int, inHeight: Int): Boolean {
|
||||||
if (inWidth == fWidth && inHeight == fHeight && fSurface != null) return true
|
// BEFORE the unchanged-size early return: this runs once per frame and is
|
||||||
|
// what re-binds this window's context for the draw phase that follows.
|
||||||
|
makeCurrent()
|
||||||
|
if (inWidth == mWidth && inHeight == mHeight && mSurface != null) return true
|
||||||
if (inWidth <= 0 || inHeight <= 0) return false
|
if (inWidth <= 0 || inHeight <= 0) return false
|
||||||
val vContext = fContext ?: return false
|
val vContext = mContext ?: return false
|
||||||
|
|
||||||
fSurface?.close()
|
mSurface?.close()
|
||||||
fRT?.close()
|
mRT?.close()
|
||||||
fSurface = null
|
mSurface = null
|
||||||
fRT = null
|
mRT = null
|
||||||
|
|
||||||
// GL_RGBA8 = 0x8058. fbId = 0 binds the default framebuffer.
|
// GL_RGBA8 = 0x8058. fbId = 0 binds the default framebuffer.
|
||||||
// sampleCnt = 0 means no MSAA; stencilBits = 8 is what Skia recommends.
|
// sampleCnt = 0 means no MSAA; stencilBits = 8 is what Skia recommends.
|
||||||
@@ -77,31 +98,35 @@ internal class SkiaGLBridge(private val backend: SDL3Backend) : SkiaBridge {
|
|||||||
println("SkiaGLBridge: Surface.makeFromBackendRenderTarget returned null")
|
println("SkiaGLBridge: Surface.makeFromBackendRenderTarget returned null")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
fRT = vRT
|
mRT = vRT
|
||||||
fSurface = vSurface
|
mSurface = vSurface
|
||||||
fWidth = inWidth
|
mWidth = inWidth
|
||||||
fHeight = inHeight
|
mHeight = inHeight
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun present() {
|
override fun present() {
|
||||||
val vSurface = fSurface ?: return
|
val vSurface = mSurface ?: return
|
||||||
val vWindow = backend.window ?: return
|
val vWindow = backend.window ?: return
|
||||||
|
makeCurrent()
|
||||||
vSurface.flushAndSubmit()
|
vSurface.flushAndSubmit()
|
||||||
SDL_GL_SwapWindow(vWindow.reinterpret())
|
SDL_GL_SwapWindow(vWindow.reinterpret())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun snapshot(): Image? = fSurface?.makeImageSnapshot()
|
override fun snapshot(): Image? = mSurface?.makeImageSnapshot()
|
||||||
|
|
||||||
override fun snapshotBgra(): Triple<Int, Int, ByteArray>? =
|
override fun snapshotBgra(): Triple<Int, Int, ByteArray>? =
|
||||||
readBackBgra(fSurface, fWidth, fHeight)
|
readBackBgra(mSurface, mWidth, mHeight)
|
||||||
|
|
||||||
override fun destroy() {
|
override fun destroy() {
|
||||||
fSurface?.close()
|
// Free this window's GPU objects against its OWN context, not whichever
|
||||||
fRT?.close()
|
// window happens to be current.
|
||||||
fContext?.close()
|
makeCurrent()
|
||||||
fSurface = null
|
mSurface?.close()
|
||||||
fRT = null
|
mRT?.close()
|
||||||
fContext = null
|
mContext?.close()
|
||||||
|
mSurface = null
|
||||||
|
mRT = null
|
||||||
|
mContext = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-21
@@ -25,13 +25,13 @@ import org.jetbrains.skia.Color as SkColor
|
|||||||
elevation shadows ride behind it via skiaLeafDrawer + the SkiaBackedCanvas
|
elevation shadows ride behind it via skiaLeafDrawer + the SkiaBackedCanvas
|
||||||
manual-vendor. */
|
manual-vendor. */
|
||||||
internal class SkiaRenderBackend(
|
internal class SkiaRenderBackend(
|
||||||
private val sdl: SDL3Backend,
|
private val sdl: Sdl3Backend,
|
||||||
private val gpuMode: GpuMode,
|
private val gpuMode: GpuMode,
|
||||||
) : RenderBackend {
|
) : RenderBackend {
|
||||||
|
|
||||||
private val fBridge: SkiaBridge = buildBridge()
|
private val mBridge: SkiaBridge = buildBridge()
|
||||||
private val fSkiaImageCache = SkiaImageCache()
|
private val mSkiaImageCache = SkiaImageCache()
|
||||||
private var fCurrentCanvas: Canvas? = null
|
private var mCurrentCanvas: Canvas? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// skiko's paragraph engine always supports variable-font axes (Material
|
// skiko's paragraph engine always supports variable-font axes (Material
|
||||||
@@ -60,40 +60,40 @@ internal class SkiaRenderBackend(
|
|||||||
// Setting it once in the ctor left it dangling at a CLOSED window's (destroyed)
|
// Setting it once in the ctor left it dangling at a CLOSED window's (destroyed)
|
||||||
// image cache after a multi-window teardown → crash on the surviving window's
|
// image cache after a multi-window teardown → crash on the surviving window's
|
||||||
// next frame, so it is re-pointed at THIS backend before every frame.
|
// next frame, so it is re-pointed at THIS backend before every frame.
|
||||||
private val fLeafDrawer = SkiaLeafDrawer(fSkiaImageCache)
|
private val mLeafDrawer = SkiaLeafDrawer(mSkiaImageCache)
|
||||||
|
|
||||||
override val imageLoader: ImageLoader = object : ImageLoader {
|
override val imageLoader: ImageLoader = object : ImageLoader {
|
||||||
override fun intrinsicSize(inPath: String, inKind: ResourceKind): Size =
|
override fun intrinsicSize(inPath: String, inKind: ResourceKind): Size =
|
||||||
fSkiaImageCache.intrinsicSize(inPath, inKind)
|
mSkiaImageCache.intrinsicSize(inPath, inKind)
|
||||||
override fun readBytes(inPath: String): ByteArray? =
|
override fun readBytes(inPath: String): ByteArray? =
|
||||||
loadComposeResourceBytes(inPath)
|
loadComposeResourceBytes(inPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildBridge(): SkiaBridge = when (gpuMode) {
|
private fun buildBridge(): SkiaBridge = when (gpuMode) {
|
||||||
is GpuMode.Skia.Metal -> makeMetalBridge(sdl) ?: error("Skia.Metal isn't supported on this target")
|
is GpuMode.Metal -> makeMetalBridge(sdl) ?: error("Skia.Metal isn't supported on this target")
|
||||||
is GpuMode.Skia.OpenGL -> SkiaGLBridge(sdl).also { require(it.init()) { "Skia.OpenGL init failed" } }
|
is GpuMode.OpenGL -> SkiaGLBridge(sdl).also { require(it.init()) { "Skia.OpenGL init failed" } }
|
||||||
is GpuMode.Software -> SkiaSurfaceBridge(sdl)
|
is GpuMode.CpuRaster -> SkiaSurfaceBridge(sdl)
|
||||||
is GpuMode.Auto -> error("SkiaRenderBackend received non-Skia gpuMode $gpuMode")
|
is GpuMode.Auto -> error("SkiaRenderBackend received non-Skia gpuMode $gpuMode")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ensureSize(inPixelWidth: Int, inPixelHeight: Int): Boolean =
|
override fun ensureSize(inPixelWidth: Int, inPixelHeight: Int): Boolean =
|
||||||
fBridge.ensureSize(inPixelWidth, inPixelHeight)
|
mBridge.ensureSize(inPixelWidth, inPixelHeight)
|
||||||
|
|
||||||
override fun beginFrame(inDpr: Float) {
|
override fun beginFrame(inDpr: Float) {
|
||||||
val canvas = fBridge.canvas
|
val canvas = mBridge.canvas
|
||||||
// Clear the surface to Material dark. Without this the Metal back
|
// Clear the surface to Material dark. Without this the Metal back
|
||||||
// buffer shows uninitialized GPU memory (pink). Clearing before scale
|
// buffer shows uninitialized GPU memory (pink). Clearing before scale
|
||||||
// so it covers the whole physical target.
|
// so it covers the whole physical target.
|
||||||
canvas.clear(SkColor.makeARGB(0xFF, 0x12, 0x12, 0x12))
|
canvas.clear(SkColor.makeARGB(0xFF, 0x12, 0x12, 0x12))
|
||||||
canvas.save()
|
canvas.save()
|
||||||
if (inDpr != 1f) canvas.scale(inDpr, inDpr)
|
if (inDpr != 1f) canvas.scale(inDpr, inDpr)
|
||||||
fCurrentCanvas = canvas
|
mCurrentCanvas = canvas
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun drawRoot(inDraw: (androidx.compose.ui.graphics.Canvas) -> Unit) {
|
override fun drawRoot(inDraw: (androidx.compose.ui.graphics.Canvas) -> Unit) {
|
||||||
val canvas = fCurrentCanvas ?: return
|
val canvas = mCurrentCanvas ?: return
|
||||||
// Point the leaf-draw global at THIS window's renderers before drawing.
|
// Point the leaf-draw global at THIS window's renderers before drawing.
|
||||||
skiaLeafDrawer = fLeafDrawer
|
skiaLeafDrawer = mLeafDrawer
|
||||||
// Wrap the live skia canvas as upstream's SkiaBackedCanvas (real gradients/
|
// Wrap the live skia canvas as upstream's SkiaBackedCanvas (real gradients/
|
||||||
// paint/shader). Its port draw contracts forward to skiaLeafDrawer. The
|
// paint/shader). Its port draw contracts forward to skiaLeafDrawer. The
|
||||||
// ImageBitmap-backed offscreen (VectorPainter / DrawCache) now goes through
|
// ImageBitmap-backed offscreen (VectorPainter / DrawCache) now goes through
|
||||||
@@ -104,18 +104,18 @@ internal class SkiaRenderBackend(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun endFrame() {
|
override fun endFrame() {
|
||||||
fCurrentCanvas?.restore()
|
mCurrentCanvas?.restore()
|
||||||
fCurrentCanvas = null
|
mCurrentCanvas = null
|
||||||
fBridge.present()
|
mBridge.present()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun snapshotBgra(): Triple<Int, Int, ByteArray>? = fBridge.snapshotBgra()
|
override fun snapshotBgra(): Triple<Int, Int, ByteArray>? = mBridge.snapshotBgra()
|
||||||
|
|
||||||
override fun destroy() {
|
override fun destroy() {
|
||||||
// Drop the global if it still points at this (about-to-be-destroyed) backend,
|
// Drop the global if it still points at this (about-to-be-destroyed) backend,
|
||||||
// so a stray draw before the next window's drawRoot can't hit freed renderers.
|
// so a stray draw before the next window's drawRoot can't hit freed renderers.
|
||||||
if (skiaLeafDrawer === fLeafDrawer) skiaLeafDrawer = null
|
if (skiaLeafDrawer === mLeafDrawer) skiaLeafDrawer = null
|
||||||
fSkiaImageCache.destroy()
|
mSkiaImageCache.destroy()
|
||||||
fBridge.destroy()
|
mBridge.destroy()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+32
-32
@@ -18,21 +18,21 @@ import sdl3.*
|
|||||||
/** Owns the CPU pixel buffer Skia draws into, plus the streaming SDL_Texture
|
/** Owns the CPU pixel buffer Skia draws into, plus the streaming SDL_Texture
|
||||||
used to push that buffer onto the window. All three (buffer, Skia surface,
|
used to push that buffer onto the window. All three (buffer, Skia surface,
|
||||||
SDL texture) get reallocated when the window resizes. */
|
SDL texture) get reallocated when the window resizes. */
|
||||||
class SkiaSurfaceBridge(private val backend: SDL3Backend) : SkiaBridge {
|
internal class SkiaSurfaceBridge(private val backend: Sdl3Backend) : SkiaBridge {
|
||||||
private var fWidth = 0
|
private var mWidth = 0
|
||||||
private var fHeight = 0
|
private var mHeight = 0
|
||||||
private var fPixels: CPointer<UByteVar>? = null
|
private var mPixels: CPointer<UByteVar>? = null
|
||||||
private var fSurface: Surface? = null
|
private var mSurface: Surface? = null
|
||||||
private var fTexture: COpaquePointer? = null
|
private var mTexture: COpaquePointer? = null
|
||||||
|
|
||||||
override val canvas: Canvas
|
override val canvas: Canvas
|
||||||
get() = requireNotNull(fSurface) { "SkiaSurfaceBridge not initialised" }.canvas
|
get() = requireNotNull(mSurface) { "SkiaSurfaceBridge not initialised" }.canvas
|
||||||
|
|
||||||
val width: Int get() = fWidth
|
val width: Int get() = mWidth
|
||||||
val height: Int get() = fHeight
|
val height: Int get() = mHeight
|
||||||
|
|
||||||
override fun ensureSize(inWidth: Int, inHeight: Int): Boolean {
|
override fun ensureSize(inWidth: Int, inHeight: Int): Boolean {
|
||||||
if (inWidth == fWidth && inHeight == fHeight && fSurface != null) return true
|
if (inWidth == mWidth && inHeight == mHeight && mSurface != null) return true
|
||||||
if (inWidth <= 0 || inHeight <= 0) return false
|
if (inWidth <= 0 || inHeight <= 0) return false
|
||||||
destroy()
|
destroy()
|
||||||
|
|
||||||
@@ -60,34 +60,34 @@ class SkiaSurfaceBridge(private val backend: SDL3Backend) : SkiaBridge {
|
|||||||
}
|
}
|
||||||
SDL_SetTextureBlendMode(vTexture.reinterpret(), SDL_BLENDMODE_NONE)
|
SDL_SetTextureBlendMode(vTexture.reinterpret(), SDL_BLENDMODE_NONE)
|
||||||
|
|
||||||
fPixels = vPixels
|
mPixels = vPixels
|
||||||
fSurface = vSurface
|
mSurface = vSurface
|
||||||
fTexture = vTexture
|
mTexture = vTexture
|
||||||
fWidth = inWidth
|
mWidth = inWidth
|
||||||
fHeight = inHeight
|
mHeight = inHeight
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Skia → SDL_Texture → screen, once per frame. */
|
/** Skia → SDL_Texture → screen, once per frame. */
|
||||||
override fun present() {
|
override fun present() {
|
||||||
val vRenderer = backend.renderer ?: return
|
val vRenderer = backend.renderer ?: return
|
||||||
val vTexture = fTexture ?: return
|
val vTexture = mTexture ?: return
|
||||||
val vSurface = fSurface ?: return
|
val vSurface = mSurface ?: return
|
||||||
val vPixels = fPixels ?: return
|
val vPixels = mPixels ?: return
|
||||||
|
|
||||||
vSurface.flushAndSubmit()
|
vSurface.flushAndSubmit()
|
||||||
SDL_UpdateTexture(vTexture.reinterpret(), null, vPixels, fWidth * 4)
|
SDL_UpdateTexture(vTexture.reinterpret(), null, vPixels, mWidth * 4)
|
||||||
SDL_RenderTexture(vRenderer.reinterpret(), vTexture.reinterpret(), null, null)
|
SDL_RenderTexture(vRenderer.reinterpret(), vTexture.reinterpret(), null, null)
|
||||||
SDL_RenderPresent(vRenderer.reinterpret())
|
SDL_RenderPresent(vRenderer.reinterpret())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun snapshot(): Image? = fSurface?.makeImageSnapshot()
|
override fun snapshot(): Image? = mSurface?.makeImageSnapshot()
|
||||||
|
|
||||||
/** CPU bridge already has the raw pixels in fPixels (RGBA8888 premul).
|
/** CPU bridge already has the raw pixels in mPixels (RGBA8888 premul).
|
||||||
Repack to BGRA so we share one BMP writer with the GPU bridges. */
|
Repack to BGRA so we share one BMP writer with the GPU bridges. */
|
||||||
override fun snapshotBgra(): Triple<Int, Int, ByteArray>? {
|
override fun snapshotBgra(): Triple<Int, Int, ByteArray>? {
|
||||||
val vPixels = fPixels ?: return null
|
val vPixels = mPixels ?: return null
|
||||||
val vCount = fWidth * fHeight
|
val vCount = mWidth * mHeight
|
||||||
val vBytes = ByteArray(vCount * 4)
|
val vBytes = ByteArray(vCount * 4)
|
||||||
for (i in 0 until vCount) {
|
for (i in 0 until vCount) {
|
||||||
val vR = vPixels[i * 4 + 0]
|
val vR = vPixels[i * 4 + 0]
|
||||||
@@ -99,17 +99,17 @@ class SkiaSurfaceBridge(private val backend: SDL3Backend) : SkiaBridge {
|
|||||||
vBytes[i * 4 + 2] = vR.toByte()
|
vBytes[i * 4 + 2] = vR.toByte()
|
||||||
vBytes[i * 4 + 3] = vA.toByte()
|
vBytes[i * 4 + 3] = vA.toByte()
|
||||||
}
|
}
|
||||||
return Triple(fWidth, fHeight, vBytes)
|
return Triple(mWidth, mHeight, vBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun destroy() {
|
override fun destroy() {
|
||||||
fTexture?.let { SDL_DestroyTexture(it.reinterpret()) }
|
mTexture?.let { SDL_DestroyTexture(it.reinterpret()) }
|
||||||
fSurface?.close()
|
mSurface?.close()
|
||||||
fPixels?.let { nativeHeap.free(it) }
|
mPixels?.let { nativeHeap.free(it) }
|
||||||
fTexture = null
|
mTexture = null
|
||||||
fSurface = null
|
mSurface = null
|
||||||
fPixels = null
|
mPixels = null
|
||||||
fWidth = 0
|
mWidth = 0
|
||||||
fHeight = 0
|
mHeight = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -6,7 +6,7 @@ import com.compose.sdl.renderer.skia.SkiaBridge
|
|||||||
// MARK: Windows (mingwX64) GPU defaults
|
// MARK: Windows (mingwX64) GPU defaults
|
||||||
// ==================
|
// ==================
|
||||||
|
|
||||||
// No Metal on Windows. The default Skia bridge is CPU raster (GpuMode.Software →
|
// No Metal on Windows. The default Skia bridge is CPU raster (GpuMode.CpuRaster →
|
||||||
// SkiaSurfaceBridge), so no GPU-context bridge is provided here yet. A D3D/Vulkan
|
// SkiaSurfaceBridge), so no GPU-context bridge is provided here yet. A D3D/Vulkan
|
||||||
// bridge can be added later (Route 1a milestone 2).
|
// bridge can be added later (Route 1a milestone 2).
|
||||||
internal actual fun makeMetalBridge(backend: SDL3Backend): SkiaBridge? = null
|
internal actual fun makeMetalBridge(backend: Sdl3Backend): SkiaBridge? = null
|
||||||
|
|||||||
+10
-1
@@ -45,6 +45,7 @@ kotlin {
|
|||||||
dependencies {
|
dependencies {
|
||||||
val vComposeJvmVersion = libs.versions.compose.get()
|
val vComposeJvmVersion = libs.versions.compose.get()
|
||||||
val vComposeM3JvmVersion = libs.versions.composeMaterial3.get()
|
val vComposeM3JvmVersion = libs.versions.composeMaterial3.get()
|
||||||
|
val vAdaptiveJvmVersion = libs.versions.composeMaterial3Adaptive.get()
|
||||||
|
|
||||||
// Official Maven coords for everything the shared UI touches; native
|
// Official Maven coords for everything the shared UI touches; native
|
||||||
// configurations substitute them for the port modules automatically
|
// configurations substitute them for the port modules automatically
|
||||||
@@ -64,13 +65,21 @@ kotlin {
|
|||||||
implementation("org.jetbrains.compose.components:components-resources:${vComposeJvmVersion}")
|
implementation("org.jetbrains.compose.components:components-resources:${vComposeJvmVersion}")
|
||||||
|
|
||||||
implementation("org.jetbrains.compose.material3:material3:$vComposeM3JvmVersion")
|
implementation("org.jetbrains.compose.material3:material3:$vComposeM3JvmVersion")
|
||||||
|
implementation("org.jetbrains.compose.material3.adaptive:adaptive:$vAdaptiveJvmVersion")
|
||||||
|
implementation("org.jetbrains.compose.material3.adaptive:adaptive-layout:$vAdaptiveJvmVersion")
|
||||||
|
implementation("org.jetbrains.compose.material3.adaptive:adaptive-navigation:$vAdaptiveJvmVersion")
|
||||||
|
// adaptive api-exposes window-core (WindowSizeClass). Because `adaptive`
|
||||||
|
// is SUBSTITUTED on native configs, KGP's granular-metadata visibility
|
||||||
|
// check drops its transitives from the commonMain classpath - so the
|
||||||
|
// shared screen only sees WindowSizeClass if we declare it DIRECTLY.
|
||||||
|
implementation(libs.androidx.window.core)
|
||||||
|
|
||||||
// Common Material Symbols Utility
|
// Common Material Symbols Utility
|
||||||
implementation(project(":utils:material-symbols"))
|
implementation(project(":utils:material-symbols"))
|
||||||
|
|
||||||
// nav3 + lifecycle: real KMP Maven artifacts on every target
|
// nav3 + lifecycle: real KMP Maven artifacts on every target
|
||||||
implementation(libs.androidx.navigation3.runtime)
|
implementation(libs.androidx.navigation3.runtime)
|
||||||
implementation("org.jetbrains.androidx.navigation3:navigation3-ui:1.2.0-alpha02")
|
implementation("org.jetbrains.androidx.navigation3:navigation3-ui:1.1.2")
|
||||||
implementation(libs.androidx.lifecycle.viewmodel.navigation3)
|
implementation(libs.androidx.lifecycle.viewmodel.navigation3)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ val Material3Screens: List<DemoScreen> = listOf(
|
|||||||
DemoScreen("Pickers") { M3PickersScreen() },
|
DemoScreen("Pickers") { M3PickersScreen() },
|
||||||
DemoScreen("Carousel") { M3CarouselScreen() },
|
DemoScreen("Carousel") { M3CarouselScreen() },
|
||||||
DemoScreen("M3Misc") { M3MiscScreen() },
|
DemoScreen("M3Misc") { M3MiscScreen() },
|
||||||
|
DemoScreen("Adaptive") { AdaptiveScreen() },
|
||||||
)
|
)
|
||||||
|
|
||||||
val Navigation3Screens: List<DemoScreen> = listOf(
|
val Navigation3Screens: List<DemoScreen> = listOf(
|
||||||
|
|||||||
@@ -0,0 +1,241 @@
|
|||||||
|
package screens
|
||||||
|
|
||||||
|
import androidx.compose.foundation.BorderStroke
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.BoxWithConstraints
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.CardDefaults
|
||||||
|
import androidx.compose.material3.ListItem
|
||||||
|
import androidx.compose.material3.ListItemDefaults
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.OutlinedButton
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
|
||||||
|
import androidx.compose.material3.adaptive.Posture
|
||||||
|
import androidx.compose.material3.adaptive.WindowAdaptiveInfo
|
||||||
|
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
|
||||||
|
import androidx.compose.material3.adaptive.currentWindowDpSize
|
||||||
|
import androidx.compose.material3.adaptive.layout.AnimatedPane
|
||||||
|
import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffold
|
||||||
|
import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole
|
||||||
|
import androidx.compose.material3.adaptive.layout.calculatePaneScaffoldDirective
|
||||||
|
import androidx.compose.material3.adaptive.navigation.rememberListDetailPaneScaffoldNavigator
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.SideEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.Dp
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.window.core.layout.WindowSizeClass
|
||||||
|
import androidx.window.core.layout.WindowSizeClass.Companion.HEIGHT_DP_EXPANDED_LOWER_BOUND
|
||||||
|
import androidx.window.core.layout.WindowSizeClass.Companion.HEIGHT_DP_MEDIUM_LOWER_BOUND
|
||||||
|
import androidx.window.core.layout.WindowSizeClass.Companion.WIDTH_DP_EXPANDED_LOWER_BOUND
|
||||||
|
import androidx.window.core.layout.WindowSizeClass.Companion.WIDTH_DP_MEDIUM_LOWER_BOUND
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
/**
|
||||||
|
Probe seam: whether [AdaptiveScreen] last laid out two panes or one. The native
|
||||||
|
`--adaptivetest` probe resizes the window and asserts this flips, which is the
|
||||||
|
only way to prove the fold reacts to a LIVE resize rather than just to the size
|
||||||
|
the window happened to open at. Not part of the demo UI.
|
||||||
|
*/
|
||||||
|
internal var gAdaptiveTwoPane: Boolean = false
|
||||||
|
private set
|
||||||
|
|
||||||
|
/**
|
||||||
|
material3-adaptive running on desktop native - resize the window and watch it fold.
|
||||||
|
|
||||||
|
Upstream `org.jetbrains.compose.material3.adaptive:*` publishes ios + macosArm64
|
||||||
|
only, so this screen doubles as the runtime proof that the vendored
|
||||||
|
`:compose:material3:adaptive:*` modules work on linux and mingw too. It exercises
|
||||||
|
three of the four modules: `adaptive` ([currentWindowAdaptiveInfo]),
|
||||||
|
`adaptive-layout` ([ListDetailPaneScaffold]) and `adaptive-navigation` (the
|
||||||
|
navigator that drives the fold).
|
||||||
|
|
||||||
|
**Why the directive is computed here instead of being left to default.**
|
||||||
|
[rememberListDetailPaneScaffoldNavigator] defaults its directive to the WINDOW
|
||||||
|
size class, but this screen does not get the whole window - the demo shell spends
|
||||||
|
190dp on the sidebar plus 48dp of padding. Defaulting would fold ~240dp too late:
|
||||||
|
the panes would still be side by side in a region already too cramped for them.
|
||||||
|
So the size class is computed from the width this screen actually gets
|
||||||
|
([BoxWithConstraints]), which is what a real pane-hosting app should do too. The
|
||||||
|
header prints both numbers so the difference is visible while resizing.
|
||||||
|
*/
|
||||||
|
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
|
||||||
|
@Composable
|
||||||
|
fun AdaptiveScreen() {
|
||||||
|
val vItems = remember { List(24) { "Item ${it + 1}" } }
|
||||||
|
var vSelected by remember { mutableStateOf(vItems.first()) }
|
||||||
|
val vScope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
val vWindowDpSize = currentWindowDpSize()
|
||||||
|
val vWindowClass = currentWindowAdaptiveInfo().windowSizeClass
|
||||||
|
|
||||||
|
Column(
|
||||||
|
Modifier.fillMaxWidth().padding(16.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||||
|
) {
|
||||||
|
Text("material3-adaptive", style = MaterialTheme.typography.titleLarge)
|
||||||
|
|
||||||
|
BoxWithConstraints(Modifier.fillMaxWidth()) {
|
||||||
|
// The space THIS screen was handed, not the window. maxHeight is
|
||||||
|
// infinite here (the shell hosts every screen in a verticalScroll), so
|
||||||
|
// the pane height is derived from the window instead - see below.
|
||||||
|
val vPaneWidth = maxWidth
|
||||||
|
val vPaneHeight = (vWindowDpSize.height - 200.dp).coerceIn(260.dp, 760.dp)
|
||||||
|
val vPaneClass = sizeClassFor(vPaneWidth, vPaneHeight)
|
||||||
|
|
||||||
|
val vNavigator = rememberListDetailPaneScaffoldNavigator<Nothing>(
|
||||||
|
scaffoldDirective = calculatePaneScaffoldDirective(
|
||||||
|
WindowAdaptiveInfo(vPaneClass, Posture()),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
val vTwoPane = vNavigator.scaffoldDirective.maxHorizontalPartitions > 1
|
||||||
|
SideEffect { gAdaptiveTwoPane = vTwoPane }
|
||||||
|
|
||||||
|
Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
|
||||||
|
ReadoutCard(
|
||||||
|
vWindowLine = "window ${vWindowDpSize.width.value.toInt()}x" +
|
||||||
|
"${vWindowDpSize.height.value.toInt()}dp -> " +
|
||||||
|
"minWidth ${vWindowClass.minWidthDp}dp",
|
||||||
|
vPaneLine = "this screen ${vPaneWidth.value.toInt()}x" +
|
||||||
|
"${vPaneHeight.value.toInt()}dp -> " +
|
||||||
|
"minWidth ${vPaneClass.minWidthDp}dp",
|
||||||
|
vVerdict = if (vTwoPane) {
|
||||||
|
"Wide enough: list and detail sit side by side. " +
|
||||||
|
"Narrow the window to fold them."
|
||||||
|
} else {
|
||||||
|
"Folded: one pane at a time. Pick an item to open the " +
|
||||||
|
"detail, then Back. Widen the window to unfold."
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
ListDetailPaneScaffold(
|
||||||
|
modifier = Modifier.fillMaxWidth().height(vPaneHeight),
|
||||||
|
directive = vNavigator.scaffoldDirective,
|
||||||
|
value = vNavigator.scaffoldValue,
|
||||||
|
listPane = {
|
||||||
|
AnimatedPane {
|
||||||
|
Card(Modifier.fillMaxSize()) {
|
||||||
|
LazyColumn {
|
||||||
|
items(vItems) { vItem ->
|
||||||
|
val vIsSelected = vItem == vSelected
|
||||||
|
ListItem(
|
||||||
|
headlineContent = { Text(vItem) },
|
||||||
|
colors = if (vIsSelected) {
|
||||||
|
ListItemDefaults.colors(
|
||||||
|
containerColor =
|
||||||
|
MaterialTheme.colorScheme.secondaryContainer,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
ListItemDefaults.colors()
|
||||||
|
},
|
||||||
|
modifier = Modifier.fillMaxWidth().clickable {
|
||||||
|
vSelected = vItem
|
||||||
|
vScope.launch {
|
||||||
|
vNavigator.navigateTo(
|
||||||
|
ListDetailPaneScaffoldRole.Detail,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
detailPane = {
|
||||||
|
AnimatedPane {
|
||||||
|
Card(Modifier.fillMaxSize()) {
|
||||||
|
Column(
|
||||||
|
Modifier.padding(16.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
vSelected,
|
||||||
|
style = MaterialTheme.typography.headlineSmall,
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
if (vTwoPane) {
|
||||||
|
"Detail pane, side by side with the list " +
|
||||||
|
"because there is room for both."
|
||||||
|
} else {
|
||||||
|
"Detail pane, filling the scaffold because " +
|
||||||
|
"there is only room for one."
|
||||||
|
},
|
||||||
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
)
|
||||||
|
// Only reachable when folded - with both panes up
|
||||||
|
// there is nothing to go back to.
|
||||||
|
if (vNavigator.canNavigateBack()) {
|
||||||
|
OutlinedButton(
|
||||||
|
onClick = {
|
||||||
|
vScope.launch { vNavigator.navigateBack() }
|
||||||
|
},
|
||||||
|
) { Text("Back to list") }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The live size readout above the scaffold - the whole point of the screen is
|
||||||
|
watching these three lines change as the window is dragged. */
|
||||||
|
@Composable
|
||||||
|
private fun ReadoutCard(vWindowLine: String, vPaneLine: String, vVerdict: String) {
|
||||||
|
Card(
|
||||||
|
Modifier.fillMaxWidth(),
|
||||||
|
colors = CardDefaults.outlinedCardColors(),
|
||||||
|
border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant),
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
Modifier.padding(12.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(2.dp),
|
||||||
|
) {
|
||||||
|
Text(vWindowLine, style = MaterialTheme.typography.bodySmall)
|
||||||
|
Text(vPaneLine, style = MaterialTheme.typography.bodySmall)
|
||||||
|
Text(
|
||||||
|
vVerdict,
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = MaterialTheme.colorScheme.primary,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
The [WindowSizeClass] for an arbitrary region.
|
||||||
|
|
||||||
|
window-core only offers this for the window itself; the breakpoint constants are
|
||||||
|
public, so applying them to a sub-region is just a table lookup.
|
||||||
|
*/
|
||||||
|
private fun sizeClassFor(inWidth: Dp, inHeight: Dp): WindowSizeClass {
|
||||||
|
val vMinWidth = when {
|
||||||
|
inWidth.value >= WIDTH_DP_EXPANDED_LOWER_BOUND -> WIDTH_DP_EXPANDED_LOWER_BOUND
|
||||||
|
inWidth.value >= WIDTH_DP_MEDIUM_LOWER_BOUND -> WIDTH_DP_MEDIUM_LOWER_BOUND
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
val vMinHeight = when {
|
||||||
|
inHeight.value >= HEIGHT_DP_EXPANDED_LOWER_BOUND -> HEIGHT_DP_EXPANDED_LOWER_BOUND
|
||||||
|
inHeight.value >= HEIGHT_DP_MEDIUM_LOWER_BOUND -> HEIGHT_DP_MEDIUM_LOWER_BOUND
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
return WindowSizeClass(vMinWidth, vMinHeight)
|
||||||
|
}
|
||||||
@@ -36,7 +36,7 @@ internal fun AnimationScreen() {
|
|||||||
"animation.core",
|
"animation.core",
|
||||||
"animate*AsState, AnimationSpec (tween / spring / repeatable / infiniteRepeatable), " +
|
"animate*AsState, AnimationSpec (tween / spring / repeatable / infiniteRepeatable), " +
|
||||||
"Easing (Linear, FastOutSlowIn, CubicBezier), rememberInfiniteTransition. " +
|
"Easing (Linear, FastOutSlowIn, CubicBezier), rememberInfiniteTransition. " +
|
||||||
"All driven by the SDL3FrameClock via withFrameNanos.",
|
"All driven by the Sdl3FrameClock via withFrameNanos.",
|
||||||
)
|
)
|
||||||
|
|
||||||
// ============
|
// ============
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ internal fun GestureScreen() {
|
|||||||
ScreenTitle(
|
ScreenTitle(
|
||||||
"pointerInput + gesture DSL",
|
"pointerInput + gesture DSL",
|
||||||
"Suspending Modifier.pointerInput { } with detectTapGestures / detectDragGestures " +
|
"Suspending Modifier.pointerInput { } with detectTapGestures / detectDragGestures " +
|
||||||
"on top. Awaits resume on the SDL3FrameClock; no per-event polling.",
|
"on top. Awaits resume on the Sdl3FrameClock; no per-event polling.",
|
||||||
)
|
)
|
||||||
|
|
||||||
// ============
|
// ============
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,81 @@
|
|||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.SideEffect
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import com.compose.sdl.ComposeNativeWindow
|
||||||
|
import com.compose.sdl.nativeComposeWindow
|
||||||
|
|
||||||
|
/**
|
||||||
|
`--winattrtest`: opens a window with the non-default Compose Desktop attributes
|
||||||
|
set, then checks four things and exits -
|
||||||
|
|
||||||
|
1. the attributes reach SDL and read back off the facade,
|
||||||
|
2. the raw SDL escape hatch hands out the pointers the resolved renderer owns,
|
||||||
|
3. onPreviewKeyEvent sees a key BEFORE the focused content does,
|
||||||
|
4. `enabled = false` drops input entirely.
|
||||||
|
*/
|
||||||
|
fun runWindowAttrTest() {
|
||||||
|
var vPreviewSaw = 0
|
||||||
|
var vKeySaw = 0
|
||||||
|
var vFacade: ComposeNativeWindow? = null
|
||||||
|
var vFrames = 0
|
||||||
|
nativeComposeWindow(
|
||||||
|
title = "attr probe",
|
||||||
|
width = 420,
|
||||||
|
height = 240,
|
||||||
|
undecorated = true,
|
||||||
|
resizable = false,
|
||||||
|
alwaysOnTop = true,
|
||||||
|
focusable = true,
|
||||||
|
enabled = true,
|
||||||
|
// Returning false lets the event continue down the chain, so this also
|
||||||
|
// proves preview runs first without swallowing anything.
|
||||||
|
onPreviewKeyEvent = { vPreviewSaw++; false },
|
||||||
|
onKeyEvent = { vKeySaw++; false },
|
||||||
|
onFrame = { _, _ ->
|
||||||
|
vFrames++
|
||||||
|
// Let the first frames settle so SDL has applied everything.
|
||||||
|
if (vFrames < 3) return@nativeComposeWindow true
|
||||||
|
if (vFrames == 3) {
|
||||||
|
com.compose.sdl.injectKey(41, true) // Escape down
|
||||||
|
com.compose.sdl.injectKey(41, false)
|
||||||
|
return@nativeComposeWindow true
|
||||||
|
}
|
||||||
|
if (vFrames == 4) {
|
||||||
|
// Nothing is focused, so the content declines and BOTH window
|
||||||
|
// handlers must have seen the key.
|
||||||
|
println("KEYCHAIN preview=$vPreviewSaw onKey=$vKeySaw")
|
||||||
|
// Now disable the window and inject again: neither may fire.
|
||||||
|
vFacade?.setEnabled(false)
|
||||||
|
com.compose.sdl.injectKey(41, true)
|
||||||
|
com.compose.sdl.injectKey(41, false)
|
||||||
|
return@nativeComposeWindow true
|
||||||
|
}
|
||||||
|
if (vFrames == 5) {
|
||||||
|
println("DISABLED preview=$vPreviewSaw onKey=$vKeySaw (must be unchanged)")
|
||||||
|
vFacade?.setEnabled(true)
|
||||||
|
}
|
||||||
|
val vW = vFacade
|
||||||
|
if (vW == null) {
|
||||||
|
println("ATTR FAIL: window facade never captured")
|
||||||
|
} else {
|
||||||
|
println(
|
||||||
|
"ATTR undecorated=${vW.isUndecorated} resizable=${vW.isResizable} " +
|
||||||
|
"alwaysOnTop=${vW.isAlwaysOnTop} focusable=${vW.isFocusable} " +
|
||||||
|
"enabled=${vW.isEnabled}"
|
||||||
|
)
|
||||||
|
val vRaw = vW.rawSdlHandles()
|
||||||
|
println(
|
||||||
|
"RAW gpu=${vW.gpuMode} window=${vRaw.window != null} " +
|
||||||
|
"renderer=${vRaw.renderer != null} glContext=${vRaw.glContext != null} " +
|
||||||
|
"metalView=${vRaw.metalView != null}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
false
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
SideEffect { vFacade = window }
|
||||||
|
Box(Modifier.fillMaxSize()) { Text("attr probe") }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.darkColorScheme
|
||||||
|
import androidx.compose.runtime.SideEffect
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.compose.sdl.ComposeNativeWindow
|
||||||
|
import com.compose.sdl.nativeComposeWindow
|
||||||
|
import screens.AdaptiveScreen
|
||||||
|
import screens.gAdaptiveTwoPane
|
||||||
|
|
||||||
|
/**
|
||||||
|
`--adaptivetest`: proves material3-adaptive reacts to a LIVE window resize.
|
||||||
|
|
||||||
|
The `--screen=Adaptive --width=…` screenshots only ever prove the fold is right
|
||||||
|
for the size the window OPENED at - each run is a fresh process. This drives one
|
||||||
|
window through wide → narrow → wide with `setSize`, and asserts the scaffold
|
||||||
|
folds and unfolds along the way. That exercises the whole chain: SDL resize →
|
||||||
|
the owner's snapshot-backed containerSize → recomposition → `BoxWithConstraints`
|
||||||
|
re-measure → a new `PaneScaffoldDirective` on the navigator → a new scaffold value.
|
||||||
|
|
||||||
|
The screen is hosted in the same `verticalScroll` + padding wrapper the demo
|
||||||
|
shell uses for its content pane, so the constraints match the real thing
|
||||||
|
(notably the infinite max height).
|
||||||
|
*/
|
||||||
|
internal fun runAdaptiveTest() {
|
||||||
|
var vFrames = 0
|
||||||
|
var vFacade: ComposeNativeWindow? = null
|
||||||
|
var vWide: Boolean? = null
|
||||||
|
var vFolded: Boolean? = null
|
||||||
|
var vUnfolded: Boolean? = null
|
||||||
|
|
||||||
|
// Frames to settle between each resize - SDL delivers the size change as an
|
||||||
|
// event, so the new constraints only reach layout on a later frame.
|
||||||
|
val kSettle = 6
|
||||||
|
|
||||||
|
nativeComposeWindow(
|
||||||
|
title = "adaptive probe",
|
||||||
|
width = 1400,
|
||||||
|
height = 760,
|
||||||
|
onFrame = { _, _ ->
|
||||||
|
vFrames++
|
||||||
|
when (vFrames) {
|
||||||
|
kSettle -> {
|
||||||
|
vWide = gAdaptiveTwoPane
|
||||||
|
vFacade?.setSize(760, 760)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
kSettle * 2 -> {
|
||||||
|
vFolded = gAdaptiveTwoPane
|
||||||
|
vFacade?.setSize(1400, 760)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
kSettle * 3 -> {
|
||||||
|
vUnfolded = gAdaptiveTwoPane
|
||||||
|
val vPass = vWide == true && vFolded == false && vUnfolded == true
|
||||||
|
println("adaptivetest: wide=$vWide folded=$vFolded unfolded=$vUnfolded")
|
||||||
|
println(
|
||||||
|
if (vPass) {
|
||||||
|
"adaptivetest: PASS (scaffold folded on resize to 760dp " +
|
||||||
|
"and unfolded again at 1400dp)"
|
||||||
|
} else {
|
||||||
|
"adaptivetest: FAIL (expected wide=true folded=false " +
|
||||||
|
"unfolded=true)"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
false
|
||||||
|
}
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
SideEffect { vFacade = window }
|
||||||
|
MaterialTheme(colorScheme = darkColorScheme()) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(MaterialTheme.colorScheme.background)
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
|
.padding(24.dp),
|
||||||
|
) {
|
||||||
|
AdaptiveScreen()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,207 @@
|
|||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.darkColorScheme
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.layout.onGloballyPositioned
|
||||||
|
import androidx.compose.ui.layout.onSizeChanged
|
||||||
|
import androidx.compose.ui.layout.positionInRoot
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.compose.sdl.nativeComposeWindow
|
||||||
|
import utils.encodeBmpBgra32
|
||||||
|
import utils.writeFile
|
||||||
|
|
||||||
|
// ==================
|
||||||
|
// MARK: Animation probes - shared transitions, AnimatedVisibility, dialog entry.
|
||||||
|
// ==================
|
||||||
|
//
|
||||||
|
// Split out of MainNative.kt, which held the entry point plus 20 scenarios in
|
||||||
|
// 1240 lines. Behaviour is unchanged; each probe is `internal` so main()'s
|
||||||
|
// argument dispatch still reaches it.
|
||||||
|
|
||||||
|
/** Drives a SharedTransitionLayout shared-element morph both directions from
|
||||||
|
the frame counter (no clicks) - it requires the LOOKAHEAD pass, which dies
|
||||||
|
with "LookaheadDelegate has not been measured yet" if the owner drops
|
||||||
|
affectsLookahead measure/relayout requests. Reaching the end frame = PASS. */
|
||||||
|
@OptIn(androidx.compose.animation.ExperimentalSharedTransitionApi::class)
|
||||||
|
internal fun runSharedTest() {
|
||||||
|
val vBig = mutableStateOf(false)
|
||||||
|
nativeComposeWindow(
|
||||||
|
title = "sharedtest",
|
||||||
|
width = 300,
|
||||||
|
height = 300,
|
||||||
|
onFrame = { _, vFrame ->
|
||||||
|
when (vFrame) {
|
||||||
|
20 -> { vBig.value = true; true } // small → big morph
|
||||||
|
70 -> { vBig.value = false; true } // big → small morph
|
||||||
|
130 -> {
|
||||||
|
println("sharedtest: PASS (shared-element morph ran both directions)")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
MaterialTheme(colorScheme = darkColorScheme()) {
|
||||||
|
androidx.compose.animation.SharedTransitionLayout {
|
||||||
|
Column {
|
||||||
|
androidx.compose.animation.AnimatedVisibility(visible = !vBig.value) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.sharedElement(
|
||||||
|
sharedContentState = rememberSharedContentState(key = "box"),
|
||||||
|
animatedVisibilityScope = this@AnimatedVisibility,
|
||||||
|
)
|
||||||
|
.size(48.dp)
|
||||||
|
.background(Color(0xFF7C4DFF), RoundedCornerShape(8.dp)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
androidx.compose.animation.AnimatedVisibility(visible = vBig.value) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.sharedElement(
|
||||||
|
sharedContentState = rememberSharedContentState(key = "box"),
|
||||||
|
animatedVisibilityScope = this@AnimatedVisibility,
|
||||||
|
)
|
||||||
|
.size(160.dp)
|
||||||
|
.background(Color(0xFF26A69A), RoundedCornerShape(24.dp)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Frame-by-frame trace of AnimatedVisibility(fadeIn+expandVertically / fadeOut+
|
||||||
|
shrinkVertically): logs the AV container's animated size and the window-Y of a
|
||||||
|
marker Box below it every frame, toggling visibility three times. Diagnoses
|
||||||
|
(a) a size snap between just-before-end and end of the animation and (b)
|
||||||
|
instant (non-animated) transitions on subsequent toggles.
|
||||||
|
|
||||||
|
Expected healthy trace: ~24 smooth frames per toggle ending exactly at 0/60,
|
||||||
|
PLUS one 16px marker jump when the fully-shrunk node unmounts (exit end) or
|
||||||
|
mounts (enter start) - that's the parent's spacedBy(16) collapsing, inherent
|
||||||
|
upstream behaviour (spacing applies to zero-height children too), NOT a bug. */
|
||||||
|
internal fun runAnimVisTest() {
|
||||||
|
val vShown = mutableStateOf(true)
|
||||||
|
var vAvSize = androidx.compose.ui.unit.IntSize(-1, -1)
|
||||||
|
var vMarkerY = -1f
|
||||||
|
var vLastLog = ""
|
||||||
|
nativeComposeWindow(
|
||||||
|
title = "animvistest",
|
||||||
|
width = 600,
|
||||||
|
height = 500,
|
||||||
|
onFrame = { _, vFrame ->
|
||||||
|
// Log only when something moved - keeps the trace readable.
|
||||||
|
val vLine = "size=$vAvSize markerY=$vMarkerY shown=${vShown.value}"
|
||||||
|
if (vLine != vLastLog) {
|
||||||
|
println("animvistest: f=$vFrame $vLine")
|
||||||
|
vLastLog = vLine
|
||||||
|
}
|
||||||
|
when (vFrame) {
|
||||||
|
60 -> { println("animvistest: === HIDE 1 ==="); vShown.value = false; true }
|
||||||
|
140 -> { println("animvistest: === SHOW 2 ==="); vShown.value = true; true }
|
||||||
|
220 -> { println("animvistest: === HIDE 3 ==="); vShown.value = false; true }
|
||||||
|
300 -> false
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
MaterialTheme(colorScheme = darkColorScheme()) {
|
||||||
|
// spacedBy mirrors the demo's Section column - the end-of-exit jump
|
||||||
|
// reported on the FoundationExtra screen involves the spacing around
|
||||||
|
// the AnimatedVisibility node collapsing when the node unmounts.
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
|
) {
|
||||||
|
Box(Modifier.size(30.dp).background(androidx.compose.ui.graphics.Color(0xFFC07040)))
|
||||||
|
androidx.compose.animation.AnimatedVisibility(
|
||||||
|
visible = vShown.value,
|
||||||
|
modifier = Modifier.onSizeChanged { vAvSize = it },
|
||||||
|
enter = androidx.compose.animation.fadeIn() + androidx.compose.animation.expandVertically(),
|
||||||
|
exit = androidx.compose.animation.fadeOut() + androidx.compose.animation.shrinkVertically(),
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(60.dp)
|
||||||
|
.background(androidx.compose.ui.graphics.Color(0xFF7040C0)),
|
||||||
|
) {
|
||||||
|
Text("Animated content", modifier = Modifier.padding(14.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(20.dp)
|
||||||
|
.background(androidx.compose.ui.graphics.Color(0xFF40C070))
|
||||||
|
.onGloballyPositioned { vMarkerY = it.positionInRoot().y },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Boots a window whose full-size surface opens an m3 AlertDialog on click (the real
|
||||||
|
material3 → ui.window.Dialog path, default DialogProperties ⇒ animateTransition on),
|
||||||
|
injects the click, then dumps screenshots during the 0.2s appearance animation and
|
||||||
|
after it settles; then injects Escape and dumps mid-disappearance (0.1s reverse,
|
||||||
|
via the popup host's exit deferral) + after. Visual check: mid shots must show the
|
||||||
|
dialog semi-transparent, slightly scaled-down and shifted down vs the settled shot,
|
||||||
|
and exit_end must show no dialog at all - skiko-parity animation both ways. */
|
||||||
|
internal fun runDialogAnimTest() {
|
||||||
|
fun snap(inBridge: com.compose.sdl.RenderBackend, inName: String) {
|
||||||
|
val vSnap = inBridge.snapshotBgra() ?: return
|
||||||
|
val (vW, vH, vBgra) = vSnap
|
||||||
|
writeFile(inName, encodeBmpBgra32(vW, vH, vBgra))
|
||||||
|
println("dialoganimtest: wrote $inName")
|
||||||
|
}
|
||||||
|
nativeComposeWindow(
|
||||||
|
title = "dialoganimtest",
|
||||||
|
width = 1000,
|
||||||
|
height = 700,
|
||||||
|
onFrame = { vBridge, vFrame ->
|
||||||
|
when (vFrame) {
|
||||||
|
30 -> { com.compose.sdl.injectMouseEvent(1, 500f, 350f); true }
|
||||||
|
32 -> { com.compose.sdl.injectMouseEvent(2, 500f, 350f); true }
|
||||||
|
36 -> { snap(vBridge, "dialog_mid1.bmp"); true }
|
||||||
|
40 -> { snap(vBridge, "dialog_mid2.bmp"); true }
|
||||||
|
90 -> { snap(vBridge, "dialog_end.bmp"); true }
|
||||||
|
92 -> {
|
||||||
|
com.compose.sdl.injectKey(41, true) // Escape → dismiss
|
||||||
|
com.compose.sdl.injectKey(41, false)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
97 -> { snap(vBridge, "dialog_exit_mid.bmp"); true }
|
||||||
|
140 -> { snap(vBridge, "dialog_exit_end.bmp"); false }
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
MaterialTheme(colorScheme = darkColorScheme()) {
|
||||||
|
var vShow by remember { mutableStateOf(false) }
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(MaterialTheme.colorScheme.background)
|
||||||
|
.clickable { vShow = true },
|
||||||
|
)
|
||||||
|
if (vShow) {
|
||||||
|
androidx.compose.material3.AlertDialog(
|
||||||
|
onDismissRequest = { vShow = false },
|
||||||
|
title = { Text("Animated dialog") },
|
||||||
|
text = { Text("Appearance animation parity with the JVM (skiko) Dialog.") },
|
||||||
|
confirmButton = {
|
||||||
|
androidx.compose.material3.TextButton(onClick = { vShow = false }) { Text("OK") }
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,258 @@
|
|||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.darkColorScheme
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.input.pointer.PointerIcon
|
||||||
|
import androidx.compose.ui.input.pointer.pointerHoverIcon
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.compose.sdl.nativeComposeWindow
|
||||||
|
|
||||||
|
// ==================
|
||||||
|
// MARK: Input probes - pointer, keyboard, wheel, cursor and IME.
|
||||||
|
// ==================
|
||||||
|
//
|
||||||
|
// Split out of MainNative.kt, which held the entry point plus 20 scenarios in
|
||||||
|
// 1240 lines. Behaviour is unchanged; each probe is `internal` so main()'s
|
||||||
|
// argument dispatch still reaches it.
|
||||||
|
|
||||||
|
/** Boots a real nativeComposeWindow with a full-size clickable box, then injects
|
||||||
|
move→press→release SDL mouse events a few frames apart (giving the upstream
|
||||||
|
clickable's gesture coroutine time to launch + await between frames), and prints
|
||||||
|
PASS/FAIL based on whether onClick fired. Proves the whole vendored interaction
|
||||||
|
pipeline works under the real Sdl3MainDispatcher + frame loop. */
|
||||||
|
internal fun runClickTest() {
|
||||||
|
var vClicks = 0
|
||||||
|
nativeComposeWindow(
|
||||||
|
title = "clicktest",
|
||||||
|
width = 400,
|
||||||
|
height = 300,
|
||||||
|
onFrame = { _, frameIndex ->
|
||||||
|
when (frameIndex) {
|
||||||
|
20 -> { com.compose.sdl.injectMouseEvent(0, 200f, 150f); true }
|
||||||
|
26 -> { com.compose.sdl.injectMouseEvent(1, 200f, 150f); true }
|
||||||
|
32 -> { com.compose.sdl.injectMouseEvent(2, 200f, 150f); true }
|
||||||
|
70 -> {
|
||||||
|
println(
|
||||||
|
if (vClicks > 0) "clicktest: PASS ($vClicks click(s) via upstream clickable)"
|
||||||
|
else "clicktest: FAIL (0 clicks - upstream clickable did not fire)"
|
||||||
|
)
|
||||||
|
false
|
||||||
|
}
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
MaterialTheme(colorScheme = darkColorScheme()) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(Color(0xFF303040))
|
||||||
|
.clickable { vClicks++; println("clicktest: onClick fired -> $vClicks") },
|
||||||
|
) {
|
||||||
|
Text("Click test", color = Color.White, fontSize = 16.sp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Same injection harness as clicktest, but the target is a Material Switch (Modifier.toggleable
|
||||||
|
from the vendored foundation.selection). Asserts onCheckedChange flipped the state - proving
|
||||||
|
toggleable rides the same verified upstream interaction path as clickable. */
|
||||||
|
internal fun runToggleTest() {
|
||||||
|
var vChecked = false
|
||||||
|
var vChanges = 0
|
||||||
|
nativeComposeWindow(
|
||||||
|
title = "toggletest",
|
||||||
|
width = 400,
|
||||||
|
height = 300,
|
||||||
|
onFrame = { _, frameIndex ->
|
||||||
|
when (frameIndex) {
|
||||||
|
20 -> { com.compose.sdl.injectMouseEvent(0, 200f, 150f); true }
|
||||||
|
26 -> { com.compose.sdl.injectMouseEvent(1, 200f, 150f); true }
|
||||||
|
32 -> { com.compose.sdl.injectMouseEvent(2, 200f, 150f); true }
|
||||||
|
70 -> {
|
||||||
|
println(
|
||||||
|
if (vChanges > 0 && vChecked) "toggletest: PASS (switch toggled to $vChecked via toggleable)"
|
||||||
|
else "toggletest: FAIL (changes=$vChanges checked=$vChecked)"
|
||||||
|
)
|
||||||
|
false
|
||||||
|
}
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
MaterialTheme(colorScheme = darkColorScheme()) {
|
||||||
|
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||||
|
androidx.compose.material3.Switch(
|
||||||
|
checked = vChecked,
|
||||||
|
onCheckedChange = { vChecked = it; vChanges++; println("toggletest: onCheckedChange -> $it") },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Boots a window with a real BasicTextField, clicks it to focus (focus-on-click via the
|
||||||
|
FocusOwner), then injects TEXT_INPUT ("A","B") and a Backspace key through the live SDL path.
|
||||||
|
Asserts the field edits to "A" - proving click-to-focus + typing + editing keys route to the
|
||||||
|
focused field via ComposeRootHost.dispatchKeyEvent + the synthesised typed-key path. */
|
||||||
|
internal fun runKeyTest() {
|
||||||
|
val vText = mutableStateOf("")
|
||||||
|
nativeComposeWindow(
|
||||||
|
title = "keytest",
|
||||||
|
width = 400,
|
||||||
|
height = 200,
|
||||||
|
onFrame = { _, frameIndex ->
|
||||||
|
when (frameIndex) {
|
||||||
|
12 -> { com.compose.sdl.injectMouseEvent(1, 200f, 100f); true } // click field to focus
|
||||||
|
14 -> { com.compose.sdl.injectMouseEvent(2, 200f, 100f); true }
|
||||||
|
24 -> { com.compose.sdl.injectTextInput("A"); true }
|
||||||
|
28 -> { com.compose.sdl.injectTextInput("B"); true }
|
||||||
|
32 -> { com.compose.sdl.injectKey(42, true); com.compose.sdl.injectKey(42, false); true } // Backspace → "A"
|
||||||
|
70 -> {
|
||||||
|
println("keytest: real BasicTextField value='${vText.value}'")
|
||||||
|
println(
|
||||||
|
if (vText.value == "A") "keytest: PASS (click-to-focus + type 'AB' + backspace = 'A')"
|
||||||
|
else "keytest: FAIL (expected 'A')"
|
||||||
|
)
|
||||||
|
false
|
||||||
|
}
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
// The exact regression path: a real BasicTextField, focused by clicking it,
|
||||||
|
// receiving typed text (SDL TEXT_INPUT) + editing keys (Backspace).
|
||||||
|
MaterialTheme(colorScheme = darkColorScheme()) {
|
||||||
|
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||||
|
androidx.compose.foundation.text.BasicTextField(
|
||||||
|
value = vText.value,
|
||||||
|
onValueChange = { vText.value = it },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Boots a tall Column wrapped in the vendored Modifier.verticalScroll, injects several wheel-down
|
||||||
|
events through the live SDL path (→ processor → MouseWheelScrollingLogic), and asserts the
|
||||||
|
ScrollState offset advanced - proving upstream scrolling works end-to-end. */
|
||||||
|
internal fun runScrollTest() {
|
||||||
|
val vScroll = androidx.compose.foundation.ScrollState(0)
|
||||||
|
nativeComposeWindow(
|
||||||
|
title = "scrolltest",
|
||||||
|
width = 400,
|
||||||
|
height = 300,
|
||||||
|
onFrame = { _, frameIndex ->
|
||||||
|
when {
|
||||||
|
frameIndex in 20..40 && frameIndex % 2 == 0 -> {
|
||||||
|
com.compose.sdl.injectWheel(200f, 150f, 0f, -3f) // wheel down
|
||||||
|
true
|
||||||
|
}
|
||||||
|
frameIndex == 90 -> {
|
||||||
|
println("scrolltest: ScrollState.value=${vScroll.value} maxValue=${vScroll.maxValue}")
|
||||||
|
println(
|
||||||
|
if (vScroll.value > 0) "scrolltest: PASS (scrolled to ${vScroll.value}px)"
|
||||||
|
else "scrolltest: FAIL (did not scroll)"
|
||||||
|
)
|
||||||
|
false
|
||||||
|
}
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
MaterialTheme(colorScheme = darkColorScheme()) {
|
||||||
|
Column(modifier = Modifier.fillMaxSize().verticalScroll(vScroll)) {
|
||||||
|
repeat(40) { i ->
|
||||||
|
Text("Scroll row $i - lorem ipsum dolor sit", color = Color.White, fontSize = 16.sp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** --cursortest: injects hover moves over pointerHoverIcon(Text) / (Hand) regions
|
||||||
|
and a bare background, printing the applied SDL system cursor after each. Proves
|
||||||
|
PointerIcon -> SDL_SetCursor end-to-end through the live hover pipeline. */
|
||||||
|
internal fun runCursorTest() {
|
||||||
|
var vBg = "?"; var vText = "?"; var vHand = "?"
|
||||||
|
nativeComposeWindow(
|
||||||
|
title = "cursortest",
|
||||||
|
width = 400,
|
||||||
|
height = 400,
|
||||||
|
onFrame = { _, vFrame ->
|
||||||
|
when (vFrame) {
|
||||||
|
10 -> { com.compose.sdl.injectMouseEvent(0, 200f, 300f); true } // background (below both boxes)
|
||||||
|
14 -> { vBg = com.compose.sdl.appliedCursorName(); true }
|
||||||
|
20 -> { com.compose.sdl.injectMouseEvent(0, 200f, 50f); true } // Text box
|
||||||
|
24 -> { vText = com.compose.sdl.appliedCursorName(); true }
|
||||||
|
30 -> { com.compose.sdl.injectMouseEvent(0, 200f, 150f); true } // Hand box
|
||||||
|
34 -> {
|
||||||
|
vHand = com.compose.sdl.appliedCursorName()
|
||||||
|
println("cursortest: background=$vBg text=$vText hand=$vHand")
|
||||||
|
val vOk = vBg.endsWith("DEFAULT") && vText.endsWith("TEXT") && vHand.endsWith("POINTER")
|
||||||
|
println(if (vOk) "cursortest: PASS" else "cursortest: FAIL")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
MaterialTheme(colorScheme = darkColorScheme()) {
|
||||||
|
Column(Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background)) {
|
||||||
|
Box(Modifier.fillMaxWidth().height(100.dp).pointerHoverIcon(PointerIcon.Text))
|
||||||
|
Box(Modifier.fillMaxWidth().height(100.dp).pointerHoverIcon(PointerIcon.Hand))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** --imetest: focuses a BasicTextField, injects an IME composition (SDL TEXT_EDITING
|
||||||
|
"ni"), then a commit (SDL TEXT_INPUT "に"). Verifies the preedit shows a
|
||||||
|
composing region and the commit REPLACES it (not appends) - the real IME path. */
|
||||||
|
internal fun runImeTest() {
|
||||||
|
val vField = mutableStateOf(androidx.compose.ui.text.input.TextFieldValue(""))
|
||||||
|
nativeComposeWindow(
|
||||||
|
title = "imetest",
|
||||||
|
width = 500,
|
||||||
|
height = 200,
|
||||||
|
onFrame = { _, vFrame ->
|
||||||
|
when (vFrame) {
|
||||||
|
12 -> { com.compose.sdl.injectMouseEvent(1, 250f, 100f); true } // focus centered field
|
||||||
|
14 -> { com.compose.sdl.injectMouseEvent(2, 250f, 100f); true }
|
||||||
|
34 -> { com.compose.sdl.injectTextEditing("ni"); true } // composing (preedit)
|
||||||
|
40 -> { println("imetest: composing text='${vField.value.text}' composition=${vField.value.composition}"); true }
|
||||||
|
50 -> { com.compose.sdl.injectTextInput("に"); true } // commit "に"
|
||||||
|
60 -> {
|
||||||
|
println("imetest: committed text='${vField.value.text}' composition=${vField.value.composition}")
|
||||||
|
val vOk = vField.value.text == "に" && vField.value.composition == null
|
||||||
|
println(if (vOk) "imetest: PASS" else "imetest: FAIL")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
MaterialTheme(colorScheme = darkColorScheme()) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background),
|
||||||
|
contentAlignment = Alignment.Center,
|
||||||
|
) {
|
||||||
|
androidx.compose.foundation.text.BasicTextField(
|
||||||
|
value = vField.value,
|
||||||
|
onValueChange = { vField.value = it },
|
||||||
|
textStyle = androidx.compose.ui.text.TextStyle(color = Color.White, fontSize = 24.sp),
|
||||||
|
cursorBrush = androidx.compose.ui.graphics.SolidColor(Color.White),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.darkColorScheme
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.compose.sdl.nativeComposeWindow
|
||||||
|
import utils.encodeBmpBgra32
|
||||||
|
import utils.writeFile
|
||||||
|
|
||||||
|
// ==================
|
||||||
|
// MARK: Lifecycle probes - back navigation and Navigation3.
|
||||||
|
// ==================
|
||||||
|
//
|
||||||
|
// Split out of MainNative.kt, which held the entry point plus 20 scenarios in
|
||||||
|
// 1240 lines. Behaviour is unchanged; each probe is `internal` so main()'s
|
||||||
|
// argument dispatch still reaches it.
|
||||||
|
|
||||||
|
/** Boots a window with a BackHandler, injects an Escape key through the live SDL
|
||||||
|
path, and asserts the handler fired - proving ComposeWindow's
|
||||||
|
BackNavigationInput drives the NavigationEventDispatcher (the mechanism that
|
||||||
|
collapses an expanded m3 SearchBar on Escape). */
|
||||||
|
@OptIn(androidx.compose.ui.ExperimentalComposeUiApi::class)
|
||||||
|
internal fun runBackTest() {
|
||||||
|
val vBackNoFocus = mutableStateOf(false)
|
||||||
|
val vBackFocused = mutableStateOf(false)
|
||||||
|
val vText = mutableStateOf("")
|
||||||
|
nativeComposeWindow(
|
||||||
|
title = "backtest",
|
||||||
|
width = 400,
|
||||||
|
height = 200,
|
||||||
|
onFrame = { _, frameIndex ->
|
||||||
|
when (frameIndex) {
|
||||||
|
// Phase 1: Escape with NOTHING focused.
|
||||||
|
20 -> {
|
||||||
|
com.compose.sdl.injectKey(41, true) // SDL_SCANCODE_ESCAPE
|
||||||
|
com.compose.sdl.injectKey(41, false)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
// Phase 2: click the text field to focus it, then Escape -
|
||||||
|
// the user-facing SearchBar scenario (field focused while
|
||||||
|
// the back handler should collapse the bar).
|
||||||
|
30 -> { com.compose.sdl.injectMouseEvent(1, 200f, 100f); true }
|
||||||
|
32 -> { com.compose.sdl.injectMouseEvent(2, 200f, 100f); true }
|
||||||
|
44 -> {
|
||||||
|
com.compose.sdl.injectKey(41, true)
|
||||||
|
com.compose.sdl.injectKey(41, false)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
70 -> {
|
||||||
|
println("backtest: noFocus=${vBackNoFocus.value} focused=${vBackFocused.value}")
|
||||||
|
println(
|
||||||
|
if (vBackNoFocus.value && vBackFocused.value)
|
||||||
|
"backtest: PASS (Escape completed back navigation with and without a focused field)"
|
||||||
|
else
|
||||||
|
"backtest: FAIL (noFocus=${vBackNoFocus.value} focusedField=${vBackFocused.value})"
|
||||||
|
)
|
||||||
|
false
|
||||||
|
}
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
androidx.compose.ui.backhandler.BackHandler(enabled = true) {
|
||||||
|
if (!vBackNoFocus.value) vBackNoFocus.value = true else vBackFocused.value = true
|
||||||
|
}
|
||||||
|
MaterialTheme(colorScheme = darkColorScheme()) {
|
||||||
|
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||||
|
// The NEW state-based field - the one m3 SearchBar's InputField
|
||||||
|
// uses - so the probe exercises its key handler, not the legacy
|
||||||
|
// value-based one.
|
||||||
|
androidx.compose.foundation.text.BasicTextField(
|
||||||
|
state = androidx.compose.foundation.text.input.rememberTextFieldState(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun runNav3Test() {
|
||||||
|
val vShow = mutableStateOf(false)
|
||||||
|
nativeComposeWindow(
|
||||||
|
title = "nav3test",
|
||||||
|
width = 1000,
|
||||||
|
height = 700,
|
||||||
|
onFrame = { vBridge, vFrame ->
|
||||||
|
when (vFrame) {
|
||||||
|
30 -> { vShow.value = true; true }
|
||||||
|
// Push Detail #1 (click its card) → per-entry lifecycle goes
|
||||||
|
// CREATED/STARTED during the slide, RESUMED once settled.
|
||||||
|
60 -> { com.compose.sdl.injectMouseEvent(1, 500f, 216f); true }
|
||||||
|
62 -> { com.compose.sdl.injectMouseEvent(2, 500f, 216f); true }
|
||||||
|
// Pop with ESC → ON_PAUSE, then CREATED while animating out,
|
||||||
|
// then the entry disposes.
|
||||||
|
120 -> {
|
||||||
|
com.compose.sdl.injectKey(41, true)
|
||||||
|
com.compose.sdl.injectKey(41, false)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
180 -> {
|
||||||
|
val vSnap = vBridge.snapshotBgra()
|
||||||
|
if (vSnap != null) {
|
||||||
|
val (vW, vH, vBgra) = vSnap
|
||||||
|
writeFile("nav3late.bmp", encodeBmpBgra32(vW, vH, vBgra))
|
||||||
|
println("nav3test: wrote nav3late.bmp (${vW}x${vH})")
|
||||||
|
println("nav3test: PASS (Navigation3 composed at RESUMED; push + pop ran)")
|
||||||
|
} else println("nav3test: FAIL (no snapshot)")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
MaterialTheme(colorScheme = darkColorScheme()) {
|
||||||
|
Box(modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background)) {
|
||||||
|
if (vShow.value) {
|
||||||
|
Box(modifier = Modifier.padding(24.dp)) { screens.Navigation3Screen() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.darkColorScheme
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.decodeToImageBitmap
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.compose.sdl.nativeComposeWindow
|
||||||
|
import demo.registry.allCategories
|
||||||
|
import kotlinx.cinterop.ExperimentalForeignApi
|
||||||
|
import kotlinx.cinterop.toKString
|
||||||
|
|
||||||
|
// ==================
|
||||||
|
// MARK: Renderer probes - the soak run and encoded-image decoding.
|
||||||
|
// ==================
|
||||||
|
//
|
||||||
|
// Split out of MainNative.kt, which held the entry point plus 20 scenarios in
|
||||||
|
// 1240 lines. Behaviour is unchanged; each probe is `internal` so main()'s
|
||||||
|
// argument dispatch still reaches it.
|
||||||
|
|
||||||
|
/** P2.2 soak - cycle through EVERY registered screen kCycles times in ONE process,
|
||||||
|
disposing each via a changing key() so composition + layer (skiko RenderNode)
|
||||||
|
allocate-and-release is exercised repeatedly. After each full cycle, GC then
|
||||||
|
record peak RSS (getrusage ru_maxrss). Peak RSS is monotonic, so after cycle 1 it
|
||||||
|
already reflects visiting every screen once; if there is NO leak it plateaus, if
|
||||||
|
there IS one it keeps climbing each cycle. PASS iff last-cycle peak stays within a
|
||||||
|
ceiling of the first-cycle peak. */
|
||||||
|
@OptIn(kotlin.native.runtime.NativeRuntimeApi::class, ExperimentalForeignApi::class)
|
||||||
|
internal fun runSoakTest() {
|
||||||
|
// Disable never-settling animations so RSS reflects composition/layer lifetime,
|
||||||
|
// not live animation-state churn (same seed the screenshot path uses).
|
||||||
|
com.compose.sdl.disableInfiniteAnimations = true
|
||||||
|
com.compose.sdl.useVirtualFrameTime = true
|
||||||
|
val vAll = allCategories().flatMap { it.screens }
|
||||||
|
// CDN_SOAK_SCREEN=<name> repeats ONE screen 40x/cycle (bisect a specific screen);
|
||||||
|
// default cycles through every screen.
|
||||||
|
val vTarget = platform.posix.getenv("CDN_SOAK_SCREEN")?.toKString()
|
||||||
|
val vScreens = if (vTarget != null) { val vS = vAll.first { it.name.equals(vTarget, ignoreCase = true) }; List(40) { vS } }
|
||||||
|
else vAll
|
||||||
|
val vIndex = mutableStateOf(0)
|
||||||
|
// CDN_SOAK_STATIC=1: mount ONE screen once, never remount - measure RSS every 120 frames.
|
||||||
|
// Isolates a per-FRAME leak (RSS climbs with no remounts) from a per-MOUNT leak.
|
||||||
|
val vStatic = platform.posix.getenv("CDN_SOAK_STATIC")?.toKString() == "1"
|
||||||
|
val kFramesPerScreen = if (vStatic) 120 else 3
|
||||||
|
val kCycles = platform.posix.getenv("CDN_SOAK_CYCLES")?.toKString()?.toIntOrNull() ?: 3
|
||||||
|
val vRssPerCycleMb = mutableListOf<Long>()
|
||||||
|
var vShown = 0
|
||||||
|
|
||||||
|
nativeComposeWindow(
|
||||||
|
title = "soaktest",
|
||||||
|
width = 1000,
|
||||||
|
height = 700,
|
||||||
|
onFrame = { _, vFrame ->
|
||||||
|
if (vFrame > 0 && vFrame % kFramesPerScreen == 0) {
|
||||||
|
if (vStatic) {
|
||||||
|
// No remount - just pump frames on the one mounted screen.
|
||||||
|
kotlin.native.runtime.GC.collect()
|
||||||
|
vRssPerCycleMb.add(currentResidentMb())
|
||||||
|
println("soaktest[static]: measure ${vRssPerCycleMb.size}: currentRSS=${vRssPerCycleMb.last()}MB")
|
||||||
|
} else {
|
||||||
|
vShown++
|
||||||
|
vIndex.value = vShown % vScreens.size
|
||||||
|
if (vShown % vScreens.size == 0) {
|
||||||
|
kotlin.native.runtime.GC.collect()
|
||||||
|
vRssPerCycleMb.add(currentResidentMb())
|
||||||
|
println("soaktest: cycle ${vRssPerCycleMb.size}: currentRSS=${vRssPerCycleMb.last()}MB")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (vRssPerCycleMb.size >= kCycles) {
|
||||||
|
val vFirst = vRssPerCycleMb.first()
|
||||||
|
val vLast = vRssPerCycleMb.last()
|
||||||
|
val vGrowth = vLast - vFirst
|
||||||
|
val vCeiling = maxOf(48L, vFirst / 4) // 25% or 48MB, whichever larger
|
||||||
|
println("soaktest: currentRSS/cycle(MB)=$vRssPerCycleMb (${vScreens.size} screens x $kCycles cycles)")
|
||||||
|
if (vGrowth <= vCeiling) {
|
||||||
|
println("soaktest: PASS (current RSS grew ${vGrowth}MB over cycles 1->$kCycles, within ${vCeiling}MB ceiling)")
|
||||||
|
} else {
|
||||||
|
println("soaktest: FAIL (current RSS grew ${vGrowth}MB > ${vCeiling}MB ceiling - possible leak)")
|
||||||
|
}
|
||||||
|
false
|
||||||
|
} else true
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
MaterialTheme(colorScheme = darkColorScheme()) {
|
||||||
|
val vScroll = rememberScrollState()
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(MaterialTheme.colorScheme.background)
|
||||||
|
.verticalScroll(vScroll)
|
||||||
|
.padding(24.dp),
|
||||||
|
) {
|
||||||
|
// key(vShown) forces a FULL dispose+recompose each advance (even when the
|
||||||
|
// target screen repeats) - the allocate/release churn we soak. Reading
|
||||||
|
// vIndex.value (a State) is what triggers the recomposition each mount.
|
||||||
|
key(vShown) {
|
||||||
|
vScreens[vIndex.value].content()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** CURRENT resident set (MB): current RSS can DROP after GC, so it distinguishes a
|
||||||
|
true leak (ratchets up) from K/N allocator high-water, unlike getrusage's
|
||||||
|
monotonic peak. posix reads it from `ps`; mingw has no `ps`/popen and returns
|
||||||
|
-1 (the soak gate runs on macOS/Linux - see scripts/verify-mac.sh). */
|
||||||
|
internal expect fun currentResidentMb(): Long
|
||||||
|
|
||||||
|
/** --imagebytestest: decodes an in-memory 2x2 BMP via ByteArray.decodeToImageBitmap()
|
||||||
|
(routes to createImageBitmap(bytes)) through Skia's image decoder. Needs a window
|
||||||
|
so the render backend installs the encoded-image decoder. */
|
||||||
|
internal fun runImageBytesTest() {
|
||||||
|
nativeComposeWindow(
|
||||||
|
title = "imagebytestest",
|
||||||
|
width = 200,
|
||||||
|
height = 200,
|
||||||
|
onFrame = { _, vFrame ->
|
||||||
|
if (vFrame >= 2) {
|
||||||
|
try {
|
||||||
|
val vBitmap = tinyRedBmp().decodeToImageBitmap()
|
||||||
|
println("imagebytestest: decoded ${vBitmap.width}x${vBitmap.height}")
|
||||||
|
println(if (vBitmap.width == 2 && vBitmap.height == 2) "imagebytestest: PASS" else "imagebytestest: FAIL (wrong size)")
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
println("imagebytestest: FAIL (${e::class.simpleName}: ${e.message})")
|
||||||
|
}
|
||||||
|
false
|
||||||
|
} else true
|
||||||
|
},
|
||||||
|
) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A minimal 2x2 24bpp red BMP (no compression) - valid decoder input.
|
||||||
|
internal fun tinyRedBmp(): ByteArray {
|
||||||
|
fun le16(v: Int) = byteArrayOf((v and 0xFF).toByte(), ((v shr 8) and 0xFF).toByte())
|
||||||
|
fun le32(v: Int) = byteArrayOf(
|
||||||
|
(v and 0xFF).toByte(), ((v shr 8) and 0xFF).toByte(),
|
||||||
|
((v shr 16) and 0xFF).toByte(), ((v shr 24) and 0xFF).toByte(),
|
||||||
|
)
|
||||||
|
val vPixel = byteArrayOf(0, 0, 0xFF.toByte()) // BGR red
|
||||||
|
val vRow = vPixel + vPixel + byteArrayOf(0, 0) // 2px + 2 pad = 8 bytes (4-byte aligned)
|
||||||
|
val vPixels = vRow + vRow // 2 rows = 16 bytes
|
||||||
|
val vFileHeader = byteArrayOf('B'.code.toByte(), 'M'.code.toByte()) + le32(70) + le32(0) + le32(54)
|
||||||
|
val vDib = le32(40) + le32(2) + le32(2) + le16(1) + le16(24) + le32(0) + le32(16) +
|
||||||
|
le32(2835) + le32(2835) + le32(0) + le32(0)
|
||||||
|
return vFileHeader + vDib + vPixels
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user