Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ apiValidation {
"avfoundation-demo",
"tao-native-test",
"window-scaffold-demo",
"watermark-demo",
// BCV 0.18.1's bundled ASM cannot read JVM 25 class files (major 69).
// Module still uses explicitApi(); re-enable once BCV/KGP ABI supports it.
"decorated-window-jewel",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,23 @@ public fun NucleusApplicationScope.JewelDecoratedWindow(
onPreviewKeyEvent: (KeyEvent) -> Boolean = { false },
onKeyEvent: (KeyEvent) -> Boolean = { false },
titleBarStyle: TitleBarStyle? = null,
// The overlay flags below mirror `dev.nucleusframework.application.DecoratedWindow`.
//
// Full-window per-pixel transparency: pixels the content leaves at alpha 0
// show the desktop behind the window. Creation-time only, normally paired
// with [undecorated]. Tao backend only.
transparent: Boolean = false,
// Click-through window: pointer events fall through to whatever sits below
// and the window never intercepts input. Pair with `focusable = false` for
// passive overlays. Reactive. Tao backend only.
clickThrough: Boolean = false,
// Show the window on every desktop / macOS Space / Windows virtual desktop
// instead of only the one it was created on. Reactive. Tao backend only.
visibleOnAllWorkspaces: Boolean = false,
// Linux only: give this window an X11 surface even when the app runs on a
// native Wayland session, for the window management Wayland has no protocol
// for (stacking, positioning, workspace stickiness). Creation-time only.
forceX11: Boolean = false,
content: @Composable NucleusDecoratedWindowScope.() -> Unit,
) {
val windowStyle = rememberJewelWindowStyle()
Expand All @@ -133,6 +150,10 @@ public fun NucleusApplicationScope.JewelDecoratedWindow(
enabled = enabled,
focusable = focusable,
alwaysOnTop = alwaysOnTop,
transparent = transparent,
clickThrough = clickThrough,
visibleOnAllWorkspaces = visibleOnAllWorkspaces,
forceX11 = forceX11,
undecorated = undecorated,
popupFor = popupFor,
nativeContextMenu = nativeContextMenu,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public final class dev/nucleusframework/window/material2/MaterialDecoratedDialog

public final class dev/nucleusframework/window/material2/MaterialDecoratedWindowKt {
public static final fun MaterialDecoratedWindow-CL87EUo (Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/window/WindowState;ZLjava/lang/String;Landroidx/compose/ui/graphics/painter/Painter;ZZZZLandroidx/compose/ui/unit/DpSize;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ldev/nucleusframework/window/styling/TitleBarStyle;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;III)V
public static final fun MaterialDecoratedWindow-fsutTYA (Ldev/nucleusframework/application/NucleusApplicationScope;Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/window/WindowState;ZLjava/lang/String;Landroidx/compose/ui/graphics/painter/Painter;ZZZZZZZLandroidx/compose/ui/unit/DpSize;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ldev/nucleusframework/window/styling/TitleBarStyle;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;III)V
public static final fun MaterialDecoratedWindow-On4RJk0 (Ldev/nucleusframework/application/NucleusApplicationScope;Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/window/WindowState;ZLjava/lang/String;Landroidx/compose/ui/graphics/painter/Painter;ZZZZZZZLandroidx/compose/ui/unit/DpSize;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ldev/nucleusframework/window/styling/TitleBarStyle;ZZZZZLkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;IIII)V
}

public final class dev/nucleusframework/window/material2/MaterialDialogTitleBarKt {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,26 @@ public fun NucleusApplicationScope.MaterialDecoratedWindow(
onPreviewKeyEvent: (KeyEvent) -> Boolean = { false },
onKeyEvent: (KeyEvent) -> Boolean = { false },
titleBarStyle: TitleBarStyle? = null,
// Fully borderless window (no macOS traffic lights, no CSD outline) — for
// overlay/ghost windows. Tao backend only.
undecorated: Boolean = false,
// The overlay flags below mirror `dev.nucleusframework.application.DecoratedWindow`.
//
// Full-window per-pixel transparency: pixels the content leaves at alpha 0
// show the desktop behind the window. Creation-time only, normally paired
// with [undecorated]. Tao backend only.
transparent: Boolean = false,
// Click-through window: pointer events fall through to whatever sits below
// and the window never intercepts input. Pair with `focusable = false` for
// passive overlays. Reactive. Tao backend only.
clickThrough: Boolean = false,
// Show the window on every desktop / macOS Space / Windows virtual desktop
// instead of only the one it was created on. Reactive. Tao backend only.
visibleOnAllWorkspaces: Boolean = false,
// Linux only: give this window an X11 surface even when the app runs on a
// native Wayland session, for the window management Wayland has no protocol
// for (stacking, positioning, workspace stickiness). Creation-time only.
forceX11: Boolean = false,
content: @Composable NucleusDecoratedWindowScope.() -> Unit,
) {
val outerColors = MaterialTheme.colors
Expand All @@ -117,6 +137,11 @@ public fun NucleusApplicationScope.MaterialDecoratedWindow(
enabled = enabled,
focusable = focusable,
alwaysOnTop = alwaysOnTop,
undecorated = undecorated,
transparent = transparent,
clickThrough = clickThrough,
visibleOnAllWorkspaces = visibleOnAllWorkspaces,
forceX11 = forceX11,
nativePopupLayers = nativePopupLayers,
nativeContextMenu = nativeContextMenu,
hiddenFromDock = hiddenFromDock,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public final class dev/nucleusframework/window/material/MaterialDecoratedDialogK

public final class dev/nucleusframework/window/material/MaterialDecoratedWindowKt {
public static final fun MaterialDecoratedWindow-2nA36Wk (Landroidx/compose/ui/window/ApplicationScope;Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/window/WindowState;ZLjava/lang/String;Landroidx/compose/ui/graphics/painter/Painter;ZZZZLandroidx/compose/ui/unit/DpSize;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ldev/nucleusframework/window/styling/TitleBarStyle;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;III)V
public static final fun MaterialDecoratedWindow-fsutTYA (Ldev/nucleusframework/application/NucleusApplicationScope;Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/window/WindowState;ZLjava/lang/String;Landroidx/compose/ui/graphics/painter/Painter;ZZZZZZZLandroidx/compose/ui/unit/DpSize;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ldev/nucleusframework/window/styling/TitleBarStyle;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;III)V
public static final fun MaterialDecoratedWindow-On4RJk0 (Ldev/nucleusframework/application/NucleusApplicationScope;Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/window/WindowState;ZLjava/lang/String;Landroidx/compose/ui/graphics/painter/Painter;ZZZZZZZLandroidx/compose/ui/unit/DpSize;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ldev/nucleusframework/window/styling/TitleBarStyle;ZZZZZLkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;IIII)V
}

public final class dev/nucleusframework/window/material/MaterialDialogTitleBarKt {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,26 @@ public fun NucleusApplicationScope.MaterialDecoratedWindow(
onPreviewKeyEvent: (KeyEvent) -> Boolean = { false },
onKeyEvent: (KeyEvent) -> Boolean = { false },
titleBarStyle: TitleBarStyle? = null,
// Fully borderless window (no macOS traffic lights, no CSD outline) — for
// overlay/ghost windows. Tao backend only.
undecorated: Boolean = false,
// The overlay flags below mirror `dev.nucleusframework.application.DecoratedWindow`.
//
// Full-window per-pixel transparency: pixels the content leaves at alpha 0
// show the desktop behind the window. Creation-time only, normally paired
// with [undecorated]. Tao backend only.
transparent: Boolean = false,
// Click-through window: pointer events fall through to whatever sits below
// and the window never intercepts input. Pair with `focusable = false` for
// passive overlays. Reactive. Tao backend only.
clickThrough: Boolean = false,
// Show the window on every desktop / macOS Space / Windows virtual desktop
// instead of only the one it was created on. Reactive. Tao backend only.
visibleOnAllWorkspaces: Boolean = false,
// Linux only: give this window an X11 surface even when the app runs on a
// native Wayland session, for the window management Wayland has no protocol
// for (stacking, positioning, workspace stickiness). Creation-time only.
forceX11: Boolean = false,
content: @Composable NucleusDecoratedWindowScope.() -> Unit,
) {
val outerColorScheme = MaterialTheme.colorScheme
Expand All @@ -136,6 +156,11 @@ public fun NucleusApplicationScope.MaterialDecoratedWindow(
enabled = enabled,
focusable = focusable,
alwaysOnTop = alwaysOnTop,
undecorated = undecorated,
transparent = transparent,
clickThrough = clickThrough,
visibleOnAllWorkspaces = visibleOnAllWorkspaces,
forceX11 = forceX11,
nativePopupLayers = nativePopupLayers,
nativeContextMenu = nativeContextMenu,
hiddenFromDock = hiddenFromDock,
Expand Down
9 changes: 6 additions & 3 deletions decorated-window-tao/api/decorated-window-tao.api
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ public final class dev/nucleusframework/window/tao/DecoratedDialogKt {
}

public final class dev/nucleusframework/window/tao/DecoratedWindowComposableKt {
public static final fun DecoratedWindow-KMb5BrY (Ldev/nucleusframework/window/tao/ApplicationScope;Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/window/WindowState;Ljava/lang/String;Landroidx/compose/ui/graphics/painter/Painter;Landroidx/compose/ui/unit/DpSize;ZZZZZZZZLdev/nucleusframework/window/tao/TaoWindow;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ZLdev/nucleusframework/window/tao/MacOSStyle;ZLandroidx/compose/runtime/CompositionLocalContext;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;IIII)V
public static final fun DecoratedWindow-119p4RY (Ldev/nucleusframework/window/tao/ApplicationScope;Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/window/WindowState;Ljava/lang/String;Landroidx/compose/ui/graphics/painter/Painter;Landroidx/compose/ui/unit/DpSize;ZZZZZZZZLdev/nucleusframework/window/tao/TaoWindow;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ZLdev/nucleusframework/window/tao/MacOSStyle;ZLandroidx/compose/runtime/CompositionLocalContext;ZZZLkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;IIII)V
}

public final class dev/nucleusframework/window/tao/DecoratedWindowKt {
Expand Down Expand Up @@ -500,8 +500,8 @@ public final class dev/nucleusframework/window/tao/TaoApplication {
public static final field $stable I
public static final field INSTANCE Ldev/nucleusframework/window/tao/TaoApplication;
public final fun exit ()V
public final fun openWindow (Ljava/lang/String;DDZZZZLdev/nucleusframework/window/tao/TaoWindow;ZZZ)Ldev/nucleusframework/window/tao/TaoWindow;
public static synthetic fun openWindow$default (Ldev/nucleusframework/window/tao/TaoApplication;Ljava/lang/String;DDZZZZLdev/nucleusframework/window/tao/TaoWindow;ZZZILjava/lang/Object;)Ldev/nucleusframework/window/tao/TaoWindow;
public final fun openWindow (Ljava/lang/String;DDZZZZLdev/nucleusframework/window/tao/TaoWindow;ZZZZ)Ldev/nucleusframework/window/tao/TaoWindow;
public static synthetic fun openWindow$default (Ldev/nucleusframework/window/tao/TaoApplication;Ljava/lang/String;DDZZZZLdev/nucleusframework/window/tao/TaoWindow;ZZZZILjava/lang/Object;)Ldev/nucleusframework/window/tao/TaoWindow;
public final fun run (Lkotlin/jvm/functions/Function1;)V
}

Expand Down Expand Up @@ -715,6 +715,7 @@ public final class dev/nucleusframework/window/tao/TaoWindow {
public final fun isFullscreen ()Z
public final fun isMaximized ()Z
public final fun isMinimized ()Z
public final fun isNativeWaylandSurface ()Z
public final fun isPopup ()Z
public final fun isResizable ()Z
public final fun isTiled ()Z
Expand Down Expand Up @@ -747,13 +748,15 @@ public final class dev/nucleusframework/window/tao/TaoWindow {
public final fun setFocusable (Z)V
public final fun setFullscreen (Z)V
public final fun setIcon (II[B)V
public final fun setIgnoreCursorEvents (Z)V
public final fun setInnerSize (DD)V
public final fun setMaximized (Z)V
public final fun setMinimized (Z)V
public final fun setMinimumSize (Ljava/lang/Double;Ljava/lang/Double;)V
public final fun setOuterPosition (DD)V
public final fun setResizable (Z)V
public final fun setTitle (Ljava/lang/String;)V
public final fun setVisibleOnAllWorkspaces (Z)V
public final fun show ()V
public final fun xdgPortalParent (J)Ldev/nucleusframework/window/tao/XdgPortalParent;
public static synthetic fun xdgPortalParent$default (Ldev/nucleusframework/window/tao/TaoWindow;JILjava/lang/Object;)Ldev/nucleusframework/window/tao/XdgPortalParent;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,25 +261,31 @@ internal fun ApplicationScope.openDecoratedWindow(
// parent window's theme/user locals from the first composition without
// hijacking popup positioning. See [LocalTaoCompositionLocalContextBridge].
initialCompositionLocalContext: CompositionLocalContext? = null,
// Linux only: give this window an X11 surface even on a native Wayland
// session — see DecoratedWindow(forceX11 = …).
forceX11: Boolean = false,
content: @Composable TaoDecoratedWindowScope.() -> Unit,
): TaoWindow {
// hiddenFromDock rides on the GTK skip-taskbar/skip-pager hint, which
// native Wayland does not honour: there is no client-side skip-taskbar
// protocol on Wayland (xdg-shell, gtk_shell1 and the staging extensions all
// lack it, and Mutter rejects wlr-layer-shell). It is effective only under
// X11/XWayland. Warn so the no-op isn't silent — force XWayland with
// NUCLEUS_TAO_LINUX_RENDERER=x11 to actually hide the window.
val forcesXWayland =
System.getenv("GDK_BACKEND").orEmpty().equals("x11", ignoreCase = true) ||
// X11/XWayland. Warn so the no-op isn't silent — either take an X11
// surface for this window ([forceX11]) or put the whole app on XWayland
// with NUCLEUS_TAO_LINUX_RENDERER=x11.
val willBeX11 =
forceX11 ||
System.getenv("GDK_BACKEND").orEmpty().equals("x11", ignoreCase = true) ||
System.getenv("NUCLEUS_TAO_LINUX_RENDERER").orEmpty().equals("x11", ignoreCase = true)
if (hiddenFromDock &&
Platform.Current == Platform.Linux &&
Platform.isWayland &&
!forcesXWayland
!willBeX11
) {
hiddenFromDockLogger.warning(
"hiddenFromDock has no effect on native Wayland: Wayland has no client-side " +
"skip-taskbar protocol. Run with NUCLEUS_TAO_LINUX_RENDERER=x11 (XWayland) to hide the window.",
"skip-taskbar protocol. Pass forceX11 = true for this window, or run with " +
"NUCLEUS_TAO_LINUX_RENDERER=x11 (XWayland) for the whole app.",
)
}
val window =
Expand Down Expand Up @@ -311,10 +317,16 @@ internal fun ApplicationScope.openDecoratedWindow(
// TaoComposeSceneHost.attach() instead.
skipTaskbar = hiddenFromDock,
transparent = transparent,
forceX11 = forceX11,
// Tao defaults borderless windows to a drop shadow (DWM on
// Windows, NSWindow.hasShadow on macOS). Overlays must opt out
// or the ghost still shows a soft contour.
undecoratedShadow = !undecorated,
// or the ghost still shows a soft contour. Fully transparent
// windows drop it on Windows too: the style-level shadow traces
// the rectangular HWND, not the content-defined shape (#416) —
// macOS keeps it (AppKit shapes the shadow to the drawn content)
// and Linux keeps its CSD hidden-titlebar path.
undecoratedShadow =
!undecorated && !(transparent && Platform.Current == Platform.Windows),
)

// Compose Hot Reload: the agent only auto-wraps AWT `ComposeWindow`/
Expand Down Expand Up @@ -709,8 +721,10 @@ private fun ApplicationScope.openDecoratedWindowLinux(
) {
// Default: CSD outline (vanilla-style frame for custom chrome).
// `undecorated` = fully borderless overlay — no Compose stroke.
// `transparent` skips it too: the stroke traces the rectangular
// window bounds, not the content-defined shape (#416).
val border =
if (undecorated) {
if (undecorated || transparent) {
Modifier
} else {
rememberUndecoratedWindowBorder(
Expand Down Expand Up @@ -1149,9 +1163,11 @@ private fun ApplicationScope.openDecoratedWindowWindows(
}
// Default: CSD outline for custom chrome windows. `undecorated`
// means fully borderless (vanilla Compose Desktop semantics for
// overlays/ghosts) — do not stroke a frame.
// overlays/ghosts) — do not stroke a frame. `transparent`
// windows skip it too: the DWM 1px frame follows the
// rectangular HWND, not the content-defined shape (#416).
val border =
if (undecorated) {
if (undecorated || transparent) {
Modifier
} else {
rememberUndecoratedWindowBorder(
Expand Down
Loading
Loading