Skip to content

Commit

Permalink
Add decoration parameter to Window and DialogWindow to control …
Browse files Browse the repository at this point in the history
…the thickness of the undecorated window resizers. (#1505)
  • Loading branch information
m-sasha authored Sep 4, 2024
1 parent f932476 commit 5ce381c
Show file tree
Hide file tree
Showing 8 changed files with 595 additions and 99 deletions.
33 changes: 32 additions & 1 deletion compose/ui/ui/api/desktop/ui.api
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ public final class androidx/compose/ui/awt/ComposeDialog : javax/swing/JDialog {
public final fun getCompositionLocalContext ()Landroidx/compose/runtime/CompositionLocalContext;
public final fun getExceptionHandler ()Landroidx/compose/ui/window/WindowExceptionHandler;
public final fun getRenderApi ()Lorg/jetbrains/skiko/GraphicsApi;
public final fun getUndecoratedResizerThickness-D9Ej5fM ()F
public final fun getWindowHandle ()J
public final fun isTransparent ()Z
public final fun onRenderApiChanged (Lkotlin/jvm/functions/Function0;)V
Expand All @@ -459,6 +460,7 @@ public final class androidx/compose/ui/awt/ComposeDialog : javax/swing/JDialog {
public fun setResizable (Z)V
public final fun setTransparent (Z)V
public fun setUndecorated (Z)V
public final fun setUndecoratedResizerThickness-0680j_4 (F)V
}

public final class androidx/compose/ui/awt/ComposePanel : javax/swing/JLayeredPane {
Expand Down Expand Up @@ -514,6 +516,7 @@ public final class androidx/compose/ui/awt/ComposeWindow : javax/swing/JFrame {
public final fun getExceptionHandler ()Landroidx/compose/ui/window/WindowExceptionHandler;
public final fun getPlacement ()Landroidx/compose/ui/window/WindowPlacement;
public final fun getRenderApi ()Lorg/jetbrains/skiko/GraphicsApi;
public final fun getUndecoratedResizerThickness-D9Ej5fM ()F
public final fun getWindowHandle ()J
public final fun isMinimized ()Z
public final fun isTransparent ()Z
Expand All @@ -534,6 +537,7 @@ public final class androidx/compose/ui/awt/ComposeWindow : javax/swing/JFrame {
public fun setResizable (Z)V
public final fun setTransparent (Z)V
public fun setUndecorated (Z)V
public final fun setUndecoratedResizerThickness-0680j_4 (F)V
}

public final class androidx/compose/ui/awt/RenderSettings {
Expand Down Expand Up @@ -4137,7 +4141,8 @@ public abstract interface class androidx/compose/ui/window/DialogWindowScope : a
public final class androidx/compose/ui/window/Dialog_desktopKt {
public static final fun Dialog (Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/window/DialogState;ZLjava/lang/String;Landroidx/compose/ui/graphics/painter/Painter;ZZZZZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;III)V
public static final fun Dialog (ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;II)V
public static final synthetic fun DialogWindow (Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/window/DialogState;ZLjava/lang/String;Landroidx/compose/ui/graphics/painter/Painter;ZZZZZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;III)V
public static final fun DialogWindow (Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/window/DialogState;ZLjava/lang/String;Landroidx/compose/ui/graphics/painter/Painter;Landroidx/compose/ui/window/WindowDecoration;ZZZZZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;III)V
public static final fun DialogWindow (Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/window/DialogState;ZLjava/lang/String;Landroidx/compose/ui/graphics/painter/Painter;ZZZZZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;III)V
public static final fun DialogWindow (Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/window/DialogState;ZLjava/lang/String;Landroidx/compose/ui/graphics/painter/Painter;ZZZZZZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;III)V
public static final fun DialogWindow (ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;II)V
}
Expand Down Expand Up @@ -4254,6 +4259,29 @@ public final class androidx/compose/ui/window/Tray_desktopKt {
public static final fun rememberTrayState (Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/window/TrayState;
}

public abstract interface class androidx/compose/ui/window/WindowDecoration {
public static final field Companion Landroidx/compose/ui/window/WindowDecoration$Companion;
}

public final class androidx/compose/ui/window/WindowDecoration$Companion {
public final fun Undecorated-0680j_4 (F)Landroidx/compose/ui/window/WindowDecoration;
public static synthetic fun Undecorated-0680j_4$default (Landroidx/compose/ui/window/WindowDecoration$Companion;FILjava/lang/Object;)Landroidx/compose/ui/window/WindowDecoration;
}

public final class androidx/compose/ui/window/WindowDecoration$SystemDefault : androidx/compose/ui/window/WindowDecoration {
public static final field $stable I
public static final field INSTANCE Landroidx/compose/ui/window/WindowDecoration$SystemDefault;
public fun equals (Ljava/lang/Object;)Z
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class androidx/compose/ui/window/WindowDecorationDefaults {
public static final field $stable I
public static final field INSTANCE Landroidx/compose/ui/window/WindowDecorationDefaults;
public final fun getResizerThickness-D9Ej5fM ()F
}

public abstract interface class androidx/compose/ui/window/WindowExceptionHandler {
public abstract fun onException (Ljava/lang/Throwable;)V
}
Expand Down Expand Up @@ -4377,9 +4405,12 @@ public final class androidx/compose/ui/window/WindowState_desktopKt {

public final class androidx/compose/ui/window/Window_desktopKt {
public static final fun MenuBar (Landroidx/compose/ui/window/FrameWindowScope;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;I)V
public static final fun Window (Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/window/WindowState;ZLjava/lang/String;Landroidx/compose/ui/graphics/painter/Painter;Landroidx/compose/ui/window/WindowDecoration;ZZZZZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;III)V
public static final fun Window (Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/window/WindowState;ZLjava/lang/String;Landroidx/compose/ui/graphics/painter/Painter;ZZZZZZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;III)V
public static final fun Window (ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;II)V
public static final fun singleWindowApplication (Landroidx/compose/ui/window/WindowState;ZLjava/lang/String;Landroidx/compose/ui/graphics/painter/Painter;Landroidx/compose/ui/window/WindowDecoration;ZZZZZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ZLkotlin/jvm/functions/Function3;)V
public static final fun singleWindowApplication (Landroidx/compose/ui/window/WindowState;ZLjava/lang/String;Landroidx/compose/ui/graphics/painter/Painter;ZZZZZZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ZLkotlin/jvm/functions/Function3;)V
public static synthetic fun singleWindowApplication$default (Landroidx/compose/ui/window/WindowState;ZLjava/lang/String;Landroidx/compose/ui/graphics/painter/Painter;Landroidx/compose/ui/window/WindowDecoration;ZZZZZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ZLkotlin/jvm/functions/Function3;ILjava/lang/Object;)V
public static synthetic fun singleWindowApplication$default (Landroidx/compose/ui/window/WindowState;ZLjava/lang/String;Landroidx/compose/ui/graphics/painter/Painter;ZZZZZZLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ZLkotlin/jvm/functions/Function3;ILjava/lang/Object;)V
}

Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package androidx.compose.ui.input.pointer

import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.Stable
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.PointerEventPass.Main
Expand Down Expand Up @@ -78,7 +77,7 @@ internal interface PointerIconService {
* @param icon The icon to set
* @param overrideDescendants when false (by default) descendants are able to set their own pointer
* icon. If true, no descendants under this parent are eligible to change the icon (it will be set
* to the this [the parent's] icon).
* to this [the parent's] icon).
*/
@Stable
fun Modifier.pointerHoverIcon(icon: PointerIcon, overrideDescendants: Boolean = false) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import androidx.compose.ui.input.key.KeyEvent
import androidx.compose.ui.layout.layoutId
import androidx.compose.ui.semantics.dialog
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.window.DialogWindowScope
import androidx.compose.ui.window.UndecoratedWindowResizer
import androidx.compose.ui.window.WindowExceptionHandler
Expand Down Expand Up @@ -220,6 +221,11 @@ class ComposeDialog : JDialog {
}
}

/**
* The thickness of the resizers used when the dialog is undecorated and resizable.
*/
var undecoratedResizerThickness: Dp by undecoratedWindowResizer::resizerThickness

override fun dispose() {
composePanel.dispose()
super.dispose()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.key.KeyEvent
import androidx.compose.ui.layout.layoutId
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.window.FrameWindowScope
import androidx.compose.ui.window.UndecoratedWindowResizer
import androidx.compose.ui.window.WindowExceptionHandler
Expand Down Expand Up @@ -160,6 +161,11 @@ class ComposeWindow @ExperimentalComposeUiApi constructor(
}
}

/**
* The thickness of the resizers used when the window is undecorated and resizable.
*/
var undecoratedResizerThickness: Dp by undecoratedWindowResizer::resizerThickness

override fun dispose() {
composePanel.dispose()
super.dispose()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,25 +66,43 @@ fun Dialog(
onKeyEvent: ((KeyEvent) -> Boolean) = { false },
content: @Composable DialogWindowScope.() -> Unit
) = DialogWindow(
onCloseRequest,
state,
visible,
title,
icon,
undecorated,
transparent,
resizable,
enabled,
focusable,
onCloseRequest = onCloseRequest,
state = state,
visible = visible,
title = title,
icon = icon,
decoration = windowDecorationFromFlag(undecorated),
transparent = transparent,
resizable = resizable,
enabled = enabled,
focusable = focusable,
alwaysOnTop = false,
onPreviewKeyEvent,
onKeyEvent,
content
onPreviewKeyEvent = onPreviewKeyEvent,
onKeyEvent = onKeyEvent,
content = content
)

@Deprecated(
level = DeprecationLevel.HIDDEN,
message = "Replaced by an overload that also takes alwaysOnTop",
level = DeprecationLevel.WARNING,
message = "Replaced by an overload that takes a decoration argument",
replaceWith = ReplaceWith("DialogWindow(" +
"onCloseRequest," +
"state," +
"visible," +
"title," +
"icon," +
"if (undecorated) WindowDecoration.Undecorated() else WindowDecoration.SystemDefault," +
"transparent," +
"resizable," +
"enabled," +
"focusable," +
"alwaysOnTop," +
"onPreviewKeyEvent," +
"onKeyEvent," +
"content" +
")",
"androidx.compose.ui.window.WindowDecoration"
)
)
@Composable
fun DialogWindow(
Expand All @@ -93,7 +111,7 @@ fun DialogWindow(
visible: Boolean = true,
title: String = "Untitled",
icon: Painter? = null,
undecorated: Boolean = false,
undecorated: Boolean,
transparent: Boolean = false,
resizable: Boolean = true,
enabled: Boolean = true,
Expand All @@ -103,20 +121,20 @@ fun DialogWindow(
content: @Composable DialogWindowScope.() -> Unit
) {
DialogWindow(
onCloseRequest,
state,
visible,
title,
icon,
undecorated,
transparent,
resizable,
enabled,
focusable,
onCloseRequest = onCloseRequest,
state = state,
visible = visible,
title = title,
icon = icon,
decoration = windowDecorationFromFlag(undecorated),
transparent = transparent,
resizable = resizable,
enabled = enabled,
focusable = focusable,
alwaysOnTop = false,
onPreviewKeyEvent,
onKeyEvent,
content
onPreviewKeyEvent = onPreviewKeyEvent,
onKeyEvent = onKeyEvent,
content = content
)
}

Expand Down Expand Up @@ -178,14 +196,129 @@ fun DialogWindow(
* If you return false, the key event will be sent to this [onKeyEvent]'s parent.
* @param content content of the dialog
*/
@Deprecated(
level = DeprecationLevel.WARNING,
message = "Replaced by an overload that takes a decoration argument",
replaceWith = ReplaceWith("DialogWindow(" +
"onCloseRequest," +
"state," +
"visible," +
"title," +
"icon," +
"if (undecorated) WindowDecoration.Undecorated() else WindowDecoration.SystemDefault," +
"transparent," +
"resizable," +
"enabled," +
"focusable," +
"alwaysOnTop," +
"onPreviewKeyEvent," +
"onKeyEvent," +
"content" +
")",
"androidx.compose.ui.window.WindowDecoration"
)
)
@Composable
fun DialogWindow(
onCloseRequest: () -> Unit,
state: DialogState = rememberDialogState(),
visible: Boolean = true,
title: String = "Untitled",
icon: Painter? = null,
undecorated: Boolean = false,
undecorated: Boolean,
transparent: Boolean = false,
resizable: Boolean = true,
enabled: Boolean = true,
focusable: Boolean = true,
alwaysOnTop: Boolean = false,
onPreviewKeyEvent: ((KeyEvent) -> Boolean) = { false },
onKeyEvent: ((KeyEvent) -> Boolean) = { false },
content: @Composable DialogWindowScope.() -> Unit
) {
DialogWindow(
onCloseRequest = onCloseRequest,
state = state,
visible = visible,
title = title,
icon = icon,
decoration = windowDecorationFromFlag(undecorated),
transparent = transparent,
resizable = resizable,
enabled = enabled,
focusable = focusable,
alwaysOnTop = alwaysOnTop,
onPreviewKeyEvent = onPreviewKeyEvent,
onKeyEvent = onKeyEvent,
content = content,
)
}

/**
* Composes platform dialog in the current composition. When Dialog enters the composition,
* a new platform dialog will be created and receives the focus. When Dialog leaves the
* composition, dialog will be disposed and closed.
*
* Dialog is a modal window. It means it blocks the parent [Window] / [DialogWindow] in which composition
* context it was created.
*
* Usage:
* ```
* @Composable
* fun main() = application {
* var isDialogOpen by remember { mutableStateOf(true) }
* if (isDialogOpen) {
* Dialog(onCloseRequest = { isDialogOpen = false }) {}
* }
* }
* ```
* @param onCloseRequest Callback that will be called when the user closes the dialog.
* Usually in this callback we need to manually tell Compose what to do:
* - change `isOpen` state of the dialog (which is manually defined)
* - close the whole application (`onCloseRequest = ::exitApplication` in [ApplicationScope])
* - don't close the dialog on close request (`onCloseRequest = {}`)
* @param state The state object to be used to control or observe the dialog's state
* When size/position is changed by the user, state will be updated.
* When size/position of the dialog is changed by the application (changing state),
* the native dialog will update its corresponding properties.
* If [DialogState.position] is not [WindowPosition.isSpecified], then after the first show on the
* screen [DialogState.position] will be set to the absolute values.
* @param visible Is [DialogWindow] visible to user.
* If `false`:
* - internal state of [DialogWindow] is preserved and will be restored next time the dialog
* will be visible;
* - native resources will not be released. They will be released only when [DialogWindow]
* will leave the composition.
* @param title Title in the titlebar of the dialog
* @param icon Icon in the titlebar of the window (for platforms which support this).
* On macOs individual windows can't have a separate icon. To change the icon in the Dock,
* set it via `iconFile` in build.gradle
* (https://github.com/JetBrains/compose-jb/tree/master/tutorials/Native_distributions_and_local_execution#platform-specific-options)
* @param decoration Specifies the decoration for this dialog.
* @param transparent Disables or enables window transparency. Transparency should be set
* only if window is undecorated, otherwise an exception will be thrown.
* @param resizable Can dialog be resized by the user (application still can resize the dialog
* changing [state])
* @param enabled Can dialog react to input events
* @param focusable Can dialog receive focus
* @param alwaysOnTop Should the dialog always be on top of another windows and dialogs
* @param onPreviewKeyEvent This callback is invoked when the user interacts with the hardware
* keyboard. It gives ancestors of a focused component the chance to intercept a [KeyEvent].
* Return true to stop propagation of this event. If you return false, the key event will be
* sent to this [onPreviewKeyEvent]'s child. If none of the children consume the event,
* it will be sent back up to the root using the onKeyEvent callback.
* @param onKeyEvent This callback is invoked when the user interacts with the hardware
* keyboard. While implementing this callback, return true to stop propagation of this event.
* If you return false, the key event will be sent to this [onKeyEvent]'s parent.
* @param content content of the dialog
*/
@Composable
fun DialogWindow(
onCloseRequest: () -> Unit,
state: DialogState = rememberDialogState(),
visible: Boolean = true,
title: String = "Untitled",
icon: Painter? = null,
decoration: WindowDecoration = WindowDecoration.SystemDefault,
transparent: Boolean = false,
resizable: Boolean = true,
enabled: Boolean = true,
Expand All @@ -200,7 +333,7 @@ fun DialogWindow(
val currentState by rememberUpdatedState(state)
val currentTitle by rememberUpdatedState(title)
val currentIcon by rememberUpdatedState(icon)
val currentUndecorated by rememberUpdatedState(undecorated)
val currentDecoration by rememberUpdatedState(decoration)
val currentTransparent by rememberUpdatedState(transparent)
val currentResizable by rememberUpdatedState(resizable)
val currentEnabled by rememberUpdatedState(enabled)
Expand Down Expand Up @@ -279,12 +412,13 @@ fun DialogWindow(
updater.update {
set(currentTitle, dialog::setTitle)
set(currentIcon, dialog::setIcon)
set(currentUndecorated, dialog::setUndecoratedSafely)
set(currentDecoration is UndecoratedWindowDecoration, dialog::setUndecoratedSafely)
set(currentTransparent, dialog::isTransparent::set)
set(currentResizable, dialog::setResizable)
set(currentEnabled, dialog::setEnabled)
set(currentFocusable, dialog::setFocusableWindowState)
set(currentAlwaysOnTop, dialog::setAlwaysOnTop)
set(currentDecoration.resizerThickness, dialog::undecoratedResizerThickness::set)
}
if (state.size != appliedState.size) {
dialog.setSizeSafely(state.size, WindowPlacement.Floating)
Expand Down
Loading

0 comments on commit 5ce381c

Please sign in to comment.