From 572e171eac7b6bf8a408ff1e24803c36e361b303 Mon Sep 17 00:00:00 2001 From: Shagen Ogandzhanian Date: Wed, 6 Mar 2024 12:05:22 +0100 Subject: [PATCH 1/2] [wasm] send correct window sized on resize --- .../compose/mpp/demo/bug/BugReproducers.kt | 3 +- .../mpp/demo/bug/ResizePopupCrashOnJS.kt | 67 +++++++++++++++++++ .../compose/ui/window/ComposeWindow.js.kt | 41 ++++++------ 3 files changed, 90 insertions(+), 21 deletions(-) create mode 100644 compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/bug/ResizePopupCrashOnJS.kt diff --git a/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/bug/BugReproducers.kt b/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/bug/BugReproducers.kt index c738f1695a595..0c299a329e519 100644 --- a/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/bug/BugReproducers.kt +++ b/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/bug/BugReproducers.kt @@ -26,5 +26,6 @@ val BugReproducers = Screen.Selection( IOSSelectionContainerCrash, IOSDynamicKeyboardType, NoPressInteractionInOutlinedTextField, - WebBaselineAlways0 + WebBaselineAlways0, + ResizePopupCrashOnJS ) diff --git a/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/bug/ResizePopupCrashOnJS.kt b/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/bug/ResizePopupCrashOnJS.kt new file mode 100644 index 0000000000000..5d301343d4b8d --- /dev/null +++ b/compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/bug/ResizePopupCrashOnJS.kt @@ -0,0 +1,67 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.mpp.demo.bug + +import androidx.compose.mpp.demo.Screen +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.foundation.layout.* +import androidx.compose.material.* +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp + +@OptIn(ExperimentalMaterialApi::class) +internal val ResizePopupCrashOnJS = Screen.Example("Resize Popup") { + MaterialTheme { + var expanded by remember { mutableStateOf(false) } + val items = listOf("Resize", "The", "Window") + var selectedOptionText by remember { mutableStateOf(items[0]) } + ExposedDropdownMenuBox( + expanded = expanded, + onExpandedChange = { + expanded = it + }, + ) { + OutlinedTextField( + modifier = Modifier + .fillMaxWidth() + .padding(top = 16.dp), + value = selectedOptionText, + onValueChange = {}, + readOnly = true + ) + ExposedDropdownMenu( + expanded = expanded, + onDismissRequest = { + expanded = false + }, + ) { + items.forEach { selectionOption -> + DropdownMenuItem( + onClick = { + selectedOptionText = selectionOption + expanded = false + }, + ) { + Text(selectionOption) + + } + } + } + } + } +} diff --git a/compose/ui/ui/src/jsWasmMain/kotlin/androidx/compose/ui/window/ComposeWindow.js.kt b/compose/ui/ui/src/jsWasmMain/kotlin/androidx/compose/ui/window/ComposeWindow.js.kt index 60f0067f80b93..b76bc013d474d 100644 --- a/compose/ui/ui/src/jsWasmMain/kotlin/androidx/compose/ui/window/ComposeWindow.js.kt +++ b/compose/ui/ui/src/jsWasmMain/kotlin/androidx/compose/ui/window/ComposeWindow.js.kt @@ -171,14 +171,9 @@ private class ComposeWindow( } init { - layer.layer.attachTo(canvas) initEvents(canvas) canvas.setAttribute("tabindex", "0") - layer.layer.needRedraw() - - _windowInfo.containerSize = IntSize(canvas.width, canvas.height) - layer.setSize(canvas.width, canvas.height) layer.setDensity(density) layer.setContent { @@ -189,12 +184,20 @@ private class ComposeWindow( } } - fun resize(newSize: IntSize) { - canvas.width = newSize.width - canvas.height = newSize.height - _windowInfo.containerSize = IntSize(canvas.width, canvas.height) + fun resize(boxSize: IntSize) { + val density = density.density.toInt() + + val width = boxSize.width * density + val height = boxSize.height * density + + //TODO: We can remove this as soon as it'll been fixed on skiko side + canvas.width = width + canvas.height = height + + _windowInfo.containerSize = IntSize(width, height) + layer.layer.attachTo(canvas) - layer.setSize(canvas.width, canvas.height) + layer.setSize(width, height) layer.layer.needRedraw() } @@ -247,6 +250,11 @@ fun CanvasBasedWindow( ) } + fun getParentContainerBox(): IntSize { + val documentElement = document.documentElement ?: return IntSize(0, 0) + return IntSize(documentElement.clientWidth, documentElement.clientHeight) + } + val actualRequestResize: suspend () -> IntSize = if (requestResize != null) { requestResize } else { @@ -258,23 +266,16 @@ fun CanvasBasedWindow( // because the default behaviour expects that the Canvas takes the entire window space, // so the app has the same lifecycle as the browser tab. window.addEventListener("resize", { _ -> - val w = document.documentElement?.clientWidth ?: 0 - val h = document.documentElement?.clientHeight ?: 0 - channel.trySend(IntSize(w, h)) + channel.trySend(getParentContainerBox()) }) + channel.trySend(getParentContainerBox()) + suspend { channel.receive() } } - if (requestResize == null) { - (document.getElementById(canvasElementId) as? HTMLCanvasElement)?.let { - it.width = document.documentElement?.clientWidth ?: 0 - it.height = document.documentElement?.clientHeight ?: 0 - } - } - var composeWindow: ComposeWindow? = null composeWindow = ComposeWindow( canvasId = canvasElementId, From 8af0963017213d39882ab6e4cfe90d0956ed9b63 Mon Sep 17 00:00:00 2001 From: Shagen Ogandzhanian Date: Wed, 6 Mar 2024 14:38:47 +0100 Subject: [PATCH 2/2] Set only logical units to resize - it will be actually re-evaluated with density in attachTo --- .../kotlin/androidx/compose/ui/window/ComposeWindow.js.kt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/compose/ui/ui/src/jsWasmMain/kotlin/androidx/compose/ui/window/ComposeWindow.js.kt b/compose/ui/ui/src/jsWasmMain/kotlin/androidx/compose/ui/window/ComposeWindow.js.kt index b76bc013d474d..52ff34993650d 100644 --- a/compose/ui/ui/src/jsWasmMain/kotlin/androidx/compose/ui/window/ComposeWindow.js.kt +++ b/compose/ui/ui/src/jsWasmMain/kotlin/androidx/compose/ui/window/ComposeWindow.js.kt @@ -190,9 +190,11 @@ private class ComposeWindow( val width = boxSize.width * density val height = boxSize.height * density - //TODO: We can remove this as soon as it'll been fixed on skiko side - canvas.width = width - canvas.height = height + // TODO: What we actually should do is to pass this new dimensions to attachTo without setting them directly on canvas. + // We should be HTMLCanvas-agnostic in that sense + canvas.width = boxSize.width + canvas.height = boxSize.height + _windowInfo.containerSize = IntSize(width, height)