Skip to content

Commit

Permalink
Add an alwaysOnTop flag to DialogWindow. (#1120)
Browse files Browse the repository at this point in the history
  • Loading branch information
m-sasha authored Feb 21, 2024
1 parent 8e4957c commit a59ec05
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 2 deletions.
3 changes: 2 additions & 1 deletion compose/ui/ui/api/desktop/ui.api
Original file line number Diff line number Diff line change
Expand Up @@ -3898,7 +3898,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 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 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;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
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import androidx.compose.ui.awt.ComposeDialog
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.input.key.KeyEvent
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.scene.BaseComposeScene
import androidx.compose.ui.scene.LocalComposeScene
import androidx.compose.ui.scene.platformContext
import androidx.compose.ui.unit.DpSize
Expand Down Expand Up @@ -77,11 +76,50 @@ fun Dialog(
resizable,
enabled,
focusable,
alwaysOnTop = false,
onPreviewKeyEvent,
onKeyEvent,
content
)

@Deprecated(
level = DeprecationLevel.HIDDEN,
message = "Replaced by an overload that also takes alwaysOnTop",
)
@Composable
fun DialogWindow(
onCloseRequest: () -> Unit,
state: DialogState = rememberDialogState(),
visible: Boolean = true,
title: String = "Untitled",
icon: Painter? = null,
undecorated: Boolean = false,
transparent: Boolean = false,
resizable: Boolean = true,
enabled: Boolean = true,
focusable: Boolean = true,
onPreviewKeyEvent: ((KeyEvent) -> Boolean) = { false },
onKeyEvent: ((KeyEvent) -> Boolean) = { false },
content: @Composable DialogWindowScope.() -> Unit
) {
DialogWindow(
onCloseRequest,
state,
visible,
title,
icon,
undecorated,
transparent,
resizable,
enabled,
focusable,
alwaysOnTop = false,
onPreviewKeyEvent,
onKeyEvent,
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
Expand Down Expand Up @@ -129,6 +167,7 @@ fun 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
Expand All @@ -151,6 +190,7 @@ fun DialogWindow(
resizable: Boolean = true,
enabled: Boolean = true,
focusable: Boolean = true,
alwaysOnTop: Boolean = false,
onPreviewKeyEvent: ((KeyEvent) -> Boolean) = { false },
onKeyEvent: ((KeyEvent) -> Boolean) = { false },
content: @Composable DialogWindowScope.() -> Unit
Expand All @@ -165,6 +205,7 @@ fun DialogWindow(
val currentResizable by rememberUpdatedState(resizable)
val currentEnabled by rememberUpdatedState(enabled)
val currentFocusable by rememberUpdatedState(focusable)
val currentAlwaysOnTop by rememberUpdatedState(alwaysOnTop)
val currentOnCloseRequest by rememberUpdatedState(onCloseRequest)

val updater = remember(::ComponentUpdater)
Expand Down Expand Up @@ -243,6 +284,7 @@ fun DialogWindow(
set(currentResizable, dialog::setResizable)
set(currentEnabled, dialog::setEnabled)
set(currentFocusable, dialog::setFocusableWindowState)
set(currentAlwaysOnTop, dialog::setAlwaysOnTop)
}
if (state.size != appliedState.size) {
dialog.setSizeSafely(state.size, WindowPlacement.Floating)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -642,4 +642,28 @@ class DialogWindowTest {
assertThat(renderedText).isEqualTo("2")
}
}

@Test
fun `change alwaysOnTop`() = runApplicationTest {
var dialog: ComposeDialog? = null

var alwaysOnTop by mutableStateOf(false)

launchTestApplication {
DialogWindow(onCloseRequest = ::exitApplication, alwaysOnTop = alwaysOnTop) {
dialog = this.window
Box(Modifier.size(32.dp).background(Color.Red))
}
}

awaitIdle()
assertThat(dialog?.isAlwaysOnTop).isFalse()

alwaysOnTop = true
awaitIdle()
assertThat(dialog?.isAlwaysOnTop).isTrue()

dialog?.dispatchEvent(WindowEvent(dialog, WindowEvent.WINDOW_CLOSING))
}

}

0 comments on commit a59ec05

Please sign in to comment.