[go: nahoru, domu]

Window resizing API update.

- added [resizable] argument to AppWindow, Window, DesktopDialog
- added [makeFullscreen], [maximize], [minimize], [restore] methods to AppFrame, AppWindow
- added [isFullscreen], [isMaximized], [isMinimized] properties to AppFrame, AppWindow
- fixed possible memory leak: when ComposeLayer is disposed, [composition.dispose()] is invoked
- added kdoc to new API

Test: manual.
Change-Id: I3ea11677288baeab2762665f859e8227a51e1bc7
diff --git a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
index 1e2c5ac..d3040c6 100644
--- a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
@@ -99,7 +99,7 @@
 const val REACTIVE_STREAMS = "org.reactivestreams:reactive-streams:1.0.0"
 const val RX_JAVA = "io.reactivex.rxjava2:rxjava:2.2.9"
 const val RX_JAVA3 = "io.reactivex.rxjava3:rxjava:3.0.0"
-val SKIKO_VERSION = System.getenv("SKIKO_VERSION") ?: "0.1.18"
+val SKIKO_VERSION = System.getenv("SKIKO_VERSION") ?: "0.1.21"
 val SKIKO = "org.jetbrains.skiko:skiko-jvm:$SKIKO_VERSION"
 val SKIKO_LINUX_X64 = "org.jetbrains.skiko:skiko-jvm-runtime-linux-x64:$SKIKO_VERSION"
 val SKIKO_MACOS_X64 = "org.jetbrains.skiko:skiko-jvm-runtime-macos-x64:$SKIKO_VERSION"
diff --git a/compose/desktop/desktop/samples/src/jvmMain/kotlin/androidx/compose/desktop/examples/popupexample/AppContent.kt b/compose/desktop/desktop/samples/src/jvmMain/kotlin/androidx/compose/desktop/examples/popupexample/AppContent.kt
index db9c668..734012b 100644
--- a/compose/desktop/desktop/samples/src/jvmMain/kotlin/androidx/compose/desktop/examples/popupexample/AppContent.kt
+++ b/compose/desktop/desktop/samples/src/jvmMain/kotlin/androidx/compose/desktop/examples/popupexample/AppContent.kt
@@ -96,9 +96,29 @@
                     TextBox(text = AppState.wndTitle.value)
                 }
                 Row {
-                    Button(color = Color(232, 182, 109), size = IntSize(16, 16))
+                    Button(
+                        color = Color(210, 210, 210),
+                        size = IntSize(16, 16),
+                        >
+                            AppManager.focusedWindow?.makeFullscreen()
+                        }
+                    )
+                    Spacer(modifier = Modifier.width(30.dp))
+                    Button(
+                        color = Color(232, 182, 109),
+                        size = IntSize(16, 16),
+                        >
+                            AppManager.focusedWindow?.minimize()
+                        }
+                    )
                     Spacer(modifier = Modifier.width(3.dp))
-                    Button(color = Color(150, 232, 150), size = IntSize(16, 16))
+                    Button(
+                        color = Color(150, 232, 150),
+                        size = IntSize(16, 16),
+                        >
+                            AppManager.focusedWindow?.maximize()
+                        }
+                    )
                     Spacer(modifier = Modifier.width(3.dp))
                     Button(
                          AppManager.exit() },
@@ -130,6 +150,9 @@
                                         AppManager.focusedWindow?.close()
                                     }
                                 )
+                                onDispose {
+                                    println("Dispose composition")
+                                }
                             }
                         },
                         color = Color(26, 198, 188)
@@ -160,15 +183,14 @@
                         .fillMaxWidth()
                 ) {
                     ContextMenu()
-                    Spacer(modifier = Modifier.height(30.dp))
-                    Spacer(modifier = Modifier.height(60.dp))
+                    Spacer(modifier = Modifier.height(100.dp))
                     Row {
                         Checkbox(
                             checked = AppState.undecorated.value,
                             >
                                 AppState.undecorated.value = !AppState.undecorated.value
                             },
-                            modifier = Modifier.height(30.dp).padding(start = 20.dp)
+                            modifier = Modifier.height(35.dp).padding(start = 20.dp)
                         )
                         Spacer(modifier = Modifier.width(5.dp))
                         TextBox(text = "- undecorated")
@@ -320,7 +342,7 @@
     text: String = "",
     onClick: () -> Unit = {},
     color: Color = Color(10, 162, 232),
-    size: IntSize = IntSize(150, 30)
+    size: IntSize = IntSize(200, 35)
 ) {
     val buttonHover = remember { mutableStateOf(false) }
     Button(
@@ -371,7 +393,8 @@
 
     Surface(
         modifier = Modifier
-            .padding(start = 4.dp, top = 2.dp),
+            .padding(start = 4.dp, top = 2.dp)
+            .clickable( showMenu.value = true }),
         color = Color(255, 255, 255, 40),
         shape = RoundedCornerShape(4.dp)
     ) {
@@ -380,9 +403,8 @@
                 TextBox(
                     text = "Selected: ${items[selectedIndex.value]}",
                     modifier = Modifier
-                        .height(26.dp)
+                        .height(35.dp)
                         .padding(start = 4.dp, end = 4.dp)
-                        .clickable( showMenu.value = true })
                 )
             },
             expanded = showMenu.value,
@@ -405,7 +427,7 @@
 @Composable
 fun RadioButton(text: String, state: MutableState<Boolean>) {
     Box(
-        modifier = Modifier.height(30.dp),
+        modifier = Modifier.height(35.dp),
         contentAlignment = Alignment.Center
     ) {
         RadioButton(
diff --git a/compose/desktop/desktop/samples/src/jvmMain/kotlin/androidx/compose/desktop/examples/popupexample/Main.kt b/compose/desktop/desktop/samples/src/jvmMain/kotlin/androidx/compose/desktop/examples/popupexample/Main.kt
index 4269d43..3fc4f935 100644
--- a/compose/desktop/desktop/samples/src/jvmMain/kotlin/androidx/compose/desktop/examples/popupexample/Main.kt
+++ b/compose/desktop/desktop/samples/src/jvmMain/kotlin/androidx/compose/desktop/examples/popupexample/Main.kt
@@ -71,6 +71,7 @@
             ),
             Menu(
                 "About",
+                MenuItems.IsFullscreen,
                 MenuItems.About,
                 MenuItems.Update
             )
diff --git a/compose/desktop/desktop/samples/src/jvmMain/kotlin/androidx/compose/desktop/examples/popupexample/MenuItems.kt b/compose/desktop/desktop/samples/src/jvmMain/kotlin/androidx/compose/desktop/examples/popupexample/MenuItems.kt
index 0d41ab0..e43c1d2 100644
--- a/compose/desktop/desktop/samples/src/jvmMain/kotlin/androidx/compose/desktop/examples/popupexample/MenuItems.kt
+++ b/compose/desktop/desktop/samples/src/jvmMain/kotlin/androidx/compose/desktop/examples/popupexample/MenuItems.kt
@@ -60,4 +60,12 @@
         },
         shortcut = KeyStroke(Key.U)
     )
+
+    val IsFullscreen = MenuItem(
+        name = "Is fullscreen mode",
+        >
+            println("Fullscreen mode: ${AppManager.focusedWindow?.isFullscreen}")
+        },
+        shortcut = KeyStroke(Key.F)
+    )
 }
\ No newline at end of file
diff --git a/compose/desktop/desktop/samples/src/jvmMain/kotlin/androidx/compose/desktop/examples/swingexample/Main.kt b/compose/desktop/desktop/samples/src/jvmMain/kotlin/androidx/compose/desktop/examples/swingexample/Main.kt
index bfb6073..d3826cd 100644
--- a/compose/desktop/desktop/samples/src/jvmMain/kotlin/androidx/compose/desktop/examples/swingexample/Main.kt
+++ b/compose/desktop/desktop/samples/src/jvmMain/kotlin/androidx/compose/desktop/examples/swingexample/Main.kt
@@ -36,6 +36,7 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.MutableState
 import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.onDispose
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
@@ -70,6 +71,9 @@
     // setting the content
     composePanel.setContent {
         ComposeContent()
+        onDispose {
+            println("Dispose composition")
+        }
     }
 
     val window = JFrame()
diff --git a/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/ScrollbarTest.kt b/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/ScrollbarTest.kt
index c2f7983..3a7a05b 100644
--- a/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/ScrollbarTest.kt
+++ b/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/ScrollbarTest.kt
@@ -67,7 +67,7 @@
     val rule = createComposeRule()
 
     // don't inline, surface controls canvas life time
-    private val surface = Surface.makeRasterN32Premul(100, 100)
+    private val surface = Surface.makeRasterN32Premul(100, 100)!!
     private val canvas = surface.canvas
 
     @Test
diff --git a/compose/ui/ui-test-junit4/src/desktopMain/kotlin/androidx/compose/ui/test/junit4/DesktopComposeTestRule.kt b/compose/ui/ui-test-junit4/src/desktopMain/kotlin/androidx/compose/ui/test/junit4/DesktopComposeTestRule.kt
index f66b098..c112bfd 100644
--- a/compose/ui/ui-test-junit4/src/desktopMain/kotlin/androidx/compose/ui/test/junit4/DesktopComposeTestRule.kt
+++ b/compose/ui/ui-test-junit4/src/desktopMain/kotlin/androidx/compose/ui/test/junit4/DesktopComposeTestRule.kt
@@ -159,7 +159,7 @@
     }
 
     private fun performSetContent(composable: @Composable() () -> Unit) {
-        val surface = Surface.makeRasterN32Premul(displaySize.width, displaySize.height)
+        val surface = Surface.makeRasterN32Premul(displaySize.width, displaySize.height)!!
         val canvas = surface.canvas
         val owners = DesktopOwners(invalidate = {}).also {
             owners = it
diff --git a/compose/ui/ui-test/src/desktopMain/kotlin/androidx/compose/ui/test/TestComposeWindow.kt b/compose/ui/ui-test/src/desktopMain/kotlin/androidx/compose/ui/test/TestComposeWindow.kt
index 3c47455..1f05602 100644
--- a/compose/ui/ui-test/src/desktopMain/kotlin/androidx/compose/ui/test/TestComposeWindow.kt
+++ b/compose/ui/ui-test/src/desktopMain/kotlin/androidx/compose/ui/test/TestComposeWindow.kt
@@ -32,7 +32,7 @@
     val density: Density = Density(1f, 1f),
     var desktopPlatform: DesktopPlatform = DesktopPlatform.Linux
 ) {
-    val surface = Surface.makeRasterN32Premul(width, height)
+    val surface = Surface.makeRasterN32Premul(width, height)!!
     val canvas = surface.canvas
     val owners = DesktopOwners(invalidate = {})
 
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/AppFrame.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/AppFrame.kt
index cd34bb7..2f06ec2 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/AppFrame.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/AppFrame.kt
@@ -19,6 +19,7 @@
 import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.window.MenuBar
 import java.awt.image.BufferedImage
+import javax.swing.JFrame
 
 /**
  * AppFrame is an abstract class that represents a window.
@@ -121,6 +122,54 @@
     abstract fun removeMenuBar()
 
     /**
+     * Switches the window to fullscreen mode if the window is resizable. If the window is in
+     * fullscreen mode [minimize] and [maximize] methods are ignored.
+     */
+    abstract fun makeFullscreen()
+
+    /**
+     * Returns true if the window is in fullscreen state, false otherwise.
+     */
+    abstract val isFullscreen: Boolean
+        get
+
+    /**
+     * Minimizes the window to the taskbar.
+     */
+    abstract fun minimize()
+
+    /**
+     * Returns true if the window is minimized, false otherwise.
+     */
+    val isMinimized: Boolean
+        get() = window.extendedState == JFrame.ICONIFIED
+
+    /**
+     * Maximizes the window to fill all available screen space.
+     */
+    abstract fun maximize()
+
+    /**
+     * Returns true if the window is maximized, false otherwise.
+     */
+    val isMaximized: Boolean
+        get() = window.extendedState == JFrame.MAXIMIZED_BOTH
+
+    /**
+     * Restores the previous state and size of the window after
+     * maximizing/minimizing/fullscreen mode.
+     */
+    abstract fun restore()
+
+    /**
+     * Sets the ability to resize the window. True - the window can be resized,
+     * false - the window cannot be resized. If the window is in fullscreen mode
+     * setter of this property is ignored. If this property is true the [makeFullscreen()]
+     * method is ignored.
+     */
+    abstract var resizable: Boolean
+
+    /**
      * Sets the new position of the window on the screen.
      *
      * @param x the new x-coordinate of the window.
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/AppWindow.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/AppWindow.kt
index a4a323b..36b80cd 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/AppWindow.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/AppWindow.kt
@@ -32,6 +32,7 @@
 import java.awt.event.WindowAdapter
 import java.awt.event.WindowEvent
 import java.awt.image.BufferedImage
+import javax.swing.JFrame
 import javax.swing.JMenuBar
 import javax.swing.SwingUtilities
 import javax.swing.WindowConstants
@@ -52,6 +53,8 @@
  * @param menuBar Window menu bar. The menu bar can be displayed inside a window (Windows,
  * Linux) or at the top of the screen (Mac OS).
  * @param undecorated Removes the native window border if set to true. The default value is false.
+ * @param resizable Makes the window resizable if is set to true and unresizable if is set to
+ * false. The default value is true.
  * @param events Allows to describe events of the window.
  * Supported events: onOpen, onClose, onMinimize, onMaximize, onRestore, onFocusGet, onFocusLost,
  * onResize, onRelocate.
@@ -65,6 +68,7 @@
     icon: BufferedImage? = null,
     menuBar: MenuBar? = null,
     undecorated: Boolean = false,
+    resizable: Boolean = true,
     events: WindowEvents = WindowEvents(),
     onDismissRequest: (() -> Unit)? = null,
     content: @Composable () -> Unit = emptyContent()
@@ -77,6 +81,7 @@
         icon = icon,
         menuBar = menuBar,
         undecorated = undecorated,
+        resizable = resizable,
         events = events,
         >
     ).show {
@@ -121,7 +126,10 @@
             })
             addWindowFocusListener(object : WindowAdapter() {
                 override fun windowGainedFocus(event: WindowEvent) {
-                    window.setJMenuBar(parent.menuBar?.menuBar)
+                    // Dialogs should not receive a common application menu bar
+                    if (invoker == null) {
+                        window.setJMenuBar(parent.menuBar?.menuBar)
+                    }
                     events.invokeOnFocusGet()
                 }
                 override fun windowLostFocus(event: WindowEvent) {
@@ -158,6 +166,7 @@
         icon: BufferedImage? = null,
         menuBar: MenuBar? = null,
         undecorated: Boolean = false,
+        resizable: Boolean = true,
         events: WindowEvents = WindowEvents(),
         onDismissRequest: (() -> Unit)? = null
     ) : this(
@@ -168,6 +177,7 @@
         icon = icon,
         menuBar = menuBar,
         undecorated = undecorated,
+        resizable = resizable,
         events = events,
         >
     ) {
@@ -188,6 +198,8 @@
      * @param menuBar Window menu bar. The menu bar can be displayed inside a window (Windows,
      * Linux) or at the top of the screen (Mac OS).
      * @param undecorated Removes the native window border if set to true. The default value is false.
+     * @param resizable Makes the window resizable if is set to true and unresizable if is set to
+     * false. The default value is true.
      * @param events Allows to describe events of the window.
      * Supported events: onOpen, onClose, onMinimize, onMaximize, onRestore, onFocusGet, onFocusLost,
      * onResize, onRelocate.
@@ -201,6 +213,7 @@
         icon: BufferedImage? = null,
         menuBar: MenuBar? = null,
         undecorated: Boolean = false,
+        resizable: Boolean = true,
         events: WindowEvents = WindowEvents(),
         onDismissRequest: (() -> Unit)? = null
     ) {
@@ -209,6 +222,7 @@
         setTitle(title)
         setIcon(icon)
         setSize(size.width, size.height)
+        this.resizable = resizable
         if (centered) {
             setWindowCentered()
         } else {
@@ -282,6 +296,72 @@
     }
 
     /**
+     * Returns true if the window is in fullscreen mode, false otherwise.
+     */
+    override val isFullscreen: Boolean
+        get() = window.layer.wrapped.fullscreen
+
+    /**
+     * Switches the window to fullscreen mode if the window is resizable. If the window is in
+     * fullscreen mode [minimize] and [maximize] methods are ignored.
+     */
+    override fun makeFullscreen() {
+        if (!isFullscreen && resizable) {
+            window.layer.wrapped.fullscreen = true
+        }
+    }
+
+    /**
+     * Minimizes the window to the taskbar. If the window is in fullscreen mode this method
+     * is ignored.
+     */
+    override fun minimize() {
+        if (!isFullscreen) {
+            window.setExtendedState(JFrame.ICONIFIED)
+        }
+    }
+
+    /**
+     * Maximizes the window to fill all available screen space. If the window is in fullscreen mode
+     * this method is ignored.
+     */
+    override fun maximize() {
+        if (!isFullscreen) {
+            window.setExtendedState(JFrame.MAXIMIZED_BOTH)
+        }
+    }
+
+    /**
+     * Restores the previous state and size of the window after
+     * maximizing/minimizing/fullscreen mode.
+     */
+    override fun restore() {
+        if (isFullscreen) {
+            window.layer.wrapped.fullscreen = false
+        }
+        window.setExtendedState(JFrame.NORMAL)
+    }
+
+    private var _resizable: Boolean = true
+
+    /**
+     * Sets the ability to resize the window. True - the window can be resized,
+     * false - the window cannot be resized. If the window is in fullscreen mode
+     * setter of this property is ignored. If this property is true the [makeFullscreen()]
+     * method is ignored.
+     */
+    override var resizable: Boolean
+        get() {
+            return window.isResizable()
+        }
+        set(value) {
+            if (!isFullscreen) {
+                _resizable = value
+                window.setResizable(value)
+            }
+        }
+
+    /**
      * Sets the new size of the window.
      *
      * @param width the new width of the window.
@@ -384,11 +464,11 @@
         window.apply {
             defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE
             setFocusableWindowState(true)
-            setResizable(true)
             setEnabled(true)
             toFront()
             requestFocus()
         }
+        resizable = _resizable
         disconnectPair()
     }
 
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/ComposeLayer.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/ComposeLayer.kt
index 66110a8..062c2a9 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/ComposeLayer.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/ComposeLayer.kt
@@ -50,6 +50,7 @@
 
 internal class ComposeLayer {
 
+    private var composition: Composition? = null
     private val events = AWTDebounceEventQueue()
 
     var owners: DesktopOwners? = null
@@ -275,6 +276,7 @@
     }
 
     fun dispose() {
+        composition?.dispose()
         events.cancel()
         check(!isDisposed)
         frameDispatcher.cancel()
@@ -298,7 +300,7 @@
         invalidate: () -> Unit = this::needRedrawLayer,
         parentComposition: CompositionReference? = null,
         content: @Composable () -> Unit
-    ): Composition {
+    ) {
         check(owners == null) {
             "Cannot setContent twice."
         }
@@ -306,7 +308,7 @@
         val desktopOwner = DesktopOwner(desktopOwners, density)
 
         owners = desktopOwners
-        val composition = desktopOwner.setContent(parent = parentComposition, content = content)
+        composition = desktopOwner.setContent(parent = parentComposition, content = content)
 
         onDensityChanged(desktopOwner::density::set)
 
@@ -314,7 +316,5 @@
             is AppFrame -> parent.>
             is ComposePanel -> parent.>
         }
-
-        return composition
     }
 }
\ No newline at end of file
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/ComposePanel.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/ComposePanel.kt
index 6915ec41..57d1f10 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/ComposePanel.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/ComposePanel.kt
@@ -114,6 +114,8 @@
     }
 
     override fun paint(g: Graphics?) {
+        super.paint(g)
+        layer?.reinit()
         needRedrawLayer()
     }
 }
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/ComposeWindow.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/ComposeWindow.kt
index 4b5c6b7..677caf8 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/ComposeWindow.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/ComposeWindow.kt
@@ -16,7 +16,6 @@
 package androidx.compose.desktop
 
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.Composition
 import androidx.compose.runtime.CompositionReference
 import java.awt.event.ComponentAdapter
 import java.awt.event.ComponentEvent
@@ -47,14 +46,12 @@
      *        scheduling of composition updates.
      *        If null then default root composition will be used.
      * @param content Composable content of the ComposeWindow.
-     *
-     * @return Composition of the content.
      */
     fun setContent(
         parentComposition: CompositionReference? = null,
         content: @Composable () -> Unit
-    ): Composition {
-        return layer.setContent(
+    ) {
+        layer.setContent(
             parent = parent,
             invalidate = this::needRedrawLayer,
             parentComposition = parentComposition,
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/window/DesktopDialog.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/window/DesktopDialog.kt
index 9b5cc81..f9a249d 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/window/DesktopDialog.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/window/DesktopDialog.kt
@@ -43,6 +43,8 @@
  * @param menuBar Window menu bar. The menu bar can be displayed inside a window (Windows,
  * Linux) or at the top of the screen (Mac OS).
  * @param undecorated Removes the native window border if set to true. The default value is false.
+ * @param resizable Makes the window resizable if is set to true and unresizable if is set to
+ * false. The default value is true.
  * @param events Allows to describe events of the window.
  * Supported events: onOpen, onClose, onMinimize, onMaximize, onRestore, onFocusGet, onFocusLost,
  * onResize, onRelocate.
@@ -56,6 +58,7 @@
     val icon: BufferedImage? = null,
     val menuBar: MenuBar? = null,
     val undecorated: Boolean = false,
+    val resizable: Boolean = true,
     val events: WindowEvents = WindowEvents()
 ) : DialogProperties
 
@@ -86,6 +89,7 @@
             icon = desktopProperties.icon,
             menuBar = desktopProperties.menuBar,
             undecorated = desktopProperties.undecorated,
+            resizable = desktopProperties.resizable,
             events = desktopProperties.events,
             >
         )
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/RenderingTestScope.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/RenderingTestScope.kt
index 6c3c4b2..9f966fa 100644
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/RenderingTestScope.kt
+++ b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/RenderingTestScope.kt
@@ -55,7 +55,7 @@
         nanoTime = { currentTimeMillis * 1_000_000 }
     )
 
-    val surface: Surface = Surface.makeRasterN32Premul(width, height)
+    val surface: Surface = Surface.makeRasterN32Premul(width, height)!!
     val canvas: Canvas = surface.canvas
     val owners = DesktopOwners(
         invalidate = frameDispatcher::scheduleFrame