Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ fun TitleBarScope.DialogCloseButton(
) {
CompositionLocalProvider(LocalLayoutDirection provides LocalControlButtonsDirection.current) {
val icons = linuxTitleBarIcons()
val layout = rememberLinuxButtonLayout()
val buttonAlignment = if (layout.controlsOnRight) Alignment.End else Alignment.Start
val windowState = state.toDecoratedWindowState()
val closeHover = if (windowState.isActive) icons.closeHoverFocused else icons.closeHover
val closePressed = if (windowState.isActive) icons.closePressedFocused else icons.closePressed
Expand All @@ -153,6 +155,7 @@ fun TitleBarScope.DialogCloseButton(
iconPressed = closePressed,
contentDescription = "Close",
style = style,
alignment = buttonAlignment,
isCloseButton = true,
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.github.kdroidfilter.nucleus.window

import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.ExperimentalComposeUiApi
Expand All @@ -10,11 +9,9 @@ import androidx.compose.ui.input.pointer.PointerButton
import androidx.compose.ui.input.pointer.PointerEventPass
import androidx.compose.ui.input.pointer.PointerEventType
import androidx.compose.ui.input.pointer.onPointerEvent
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import com.jetbrains.JBR
import io.github.kdroidfilter.nucleus.core.runtime.LinuxDesktopEnvironment
import io.github.kdroidfilter.nucleus.window.styling.TitleBarStyle
import io.github.kdroidfilter.nucleus.window.utils.linux.rememberLinuxButtonLayout
import java.awt.event.MouseEvent

@OptIn(ExperimentalComposeUiApi::class)
Expand All @@ -31,7 +28,8 @@ internal fun DecoratedDialogScope.LinuxDialogTitleBar(
val linuxStyle = createLinuxTitleBarStyle(style)
val dialogState = state
val controlDir = controlButtonsDirection.resolve()
val controlsSide = if (controlDir == LayoutDirection.Rtl) WindowControlsSide.Start else WindowControlsSide.End
val controlsOnRight = rememberLinuxButtonLayout().controlsOnRight
val controlsSide = if (controlsOnRight) WindowControlsSide.End else WindowControlsSide.Start

CompositionLocalProvider(LocalWindowControlsSide provides controlsSide) {
DialogTitleBarImpl(
Expand All @@ -48,15 +46,7 @@ internal fun DecoratedDialogScope.LinuxDialogTitleBar(
style = linuxStyle,
controlButtonsDirection = controlDir,
layoutPolicy = layoutPolicy,
applyTitleBar = { _, _ ->
val padding =
if (LinuxDesktopEnvironment.Current == LinuxDesktopEnvironment.KDE) {
PaddingValues(end = 4.dp)
} else {
PaddingValues(0.dp)
}
padding
},
applyTitleBar = { _, _ -> kdePaddingForButtonLayout() },
) { _ ->
DialogCloseButton(window, dialogState, linuxStyle)
content(dialogState)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ internal fun DecoratedDialogScope.MacOSDialogTitleBar(

val controlDir = controlButtonsDirection.resolve()
val isRtl = controlDir == LayoutDirection.Rtl
val controlsSide = if (isRtl) WindowControlsSide.Start else WindowControlsSide.End
val controlsSide = if (isRtl) WindowControlsSide.End else WindowControlsSide.Start

CompositionLocalProvider(LocalWindowControlsSide provides controlsSide) {
DialogTitleBarImpl(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ internal fun DecoratedWindowScope.MacOSTitleBar(

val controlDir = controlButtonsDirection.resolve()
val controlIsRtl = controlDir == LayoutDirection.Rtl
val controlsSide = if (controlIsRtl) WindowControlsSide.Start else WindowControlsSide.End
val controlsSide = if (controlIsRtl) WindowControlsSide.End else WindowControlsSide.Start

CompositionLocalProvider(LocalWindowControlsSide provides controlsSide) {
TitleBarImpl(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.github.kdroidfilter.nucleus.window

import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
Expand All @@ -13,10 +12,9 @@ import androidx.compose.ui.input.pointer.PointerEventPass
import androidx.compose.ui.input.pointer.PointerEventType
import androidx.compose.ui.input.pointer.onPointerEvent
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import io.github.kdroidfilter.nucleus.core.runtime.LinuxDesktopEnvironment
import io.github.kdroidfilter.nucleus.window.styling.TitleBarStyle
import io.github.kdroidfilter.nucleus.window.utils.linux.JniLinuxWindowBridge
import io.github.kdroidfilter.nucleus.window.utils.linux.rememberLinuxButtonLayout
import java.awt.MouseInfo

@OptIn(ExperimentalComposeUiApi::class)
Expand All @@ -31,7 +29,8 @@ internal fun DecoratedDialogScope.LinuxDialogTitleBar(
content: @Composable TitleBarScope.(DecoratedDialogState) -> Unit = {},
) {
val controlDir = controlButtonsDirection.resolve()
val controlsSide = if (controlDir == LayoutDirection.Rtl) WindowControlsSide.Start else WindowControlsSide.End
val controlsOnRight = rememberLinuxButtonLayout().controlsOnRight
val controlsSide = if (controlsOnRight) WindowControlsSide.End else WindowControlsSide.Start

if (JniLinuxWindowBridge.isLoaded) {
NativeLinuxDialogTitleBar(
Expand Down Expand Up @@ -80,15 +79,7 @@ private fun DecoratedDialogScope.NativeLinuxDialogTitleBar(
style = linuxStyle,
controlButtonsDirection = controlButtonsDirection,
layoutPolicy = layoutPolicy,
applyTitleBar = { _, _ ->
val padding =
if (LinuxDesktopEnvironment.Current == LinuxDesktopEnvironment.KDE) {
PaddingValues(end = 4.dp)
} else {
PaddingValues(0.dp)
}
padding
},
applyTitleBar = { _, _ -> kdePaddingForButtonLayout() },
backgroundContent = {
Spacer(
modifier =
Expand Down Expand Up @@ -152,15 +143,7 @@ private fun DecoratedDialogScope.FallbackLinuxDialogTitleBar(
style = linuxStyle,
controlButtonsDirection = controlButtonsDirection,
layoutPolicy = layoutPolicy,
applyTitleBar = { _, _ ->
val padding =
if (LinuxDesktopEnvironment.Current == LinuxDesktopEnvironment.KDE) {
PaddingValues(end = 4.dp)
} else {
PaddingValues(0.dp)
}
padding
},
applyTitleBar = { _, _ -> kdePaddingForButtonLayout() },
backgroundContent = {
Spacer(modifier = Modifier.fillMaxSize().windowDragHandler(window))
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ internal fun DecoratedDialogScope.MacOSDialogTitleBar(
) {
val controlDir = controlButtonsDirection.resolve()
val controlIsRtl = controlDir == LayoutDirection.Rtl
val controlsSide = if (controlIsRtl) WindowControlsSide.Start else WindowControlsSide.End
val controlsSide = if (controlIsRtl) WindowControlsSide.End else WindowControlsSide.Start

DisposableEffect(window) {
onDispose {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ internal fun DecoratedWindowScope.MacOSTitleBar(
// correct side. Uses the control buttons direction (decoupled from content).
val controlDir = controlButtonsDirection.resolve()
val controlIsRtl = controlDir == LayoutDirection.Rtl
val controlsSide = if (controlIsRtl) WindowControlsSide.Start else WindowControlsSide.End
val controlsSide = if (controlIsRtl) WindowControlsSide.End else WindowControlsSide.Start
LaunchedEffect(window, controlIsRtl) {
val ptr = JniMacWindowUtil.getWindowPtr(window)
if (ptr != 0L && JniMacTitleBarBridge.isLoaded) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,8 @@ private fun JvmApplicationContext.configurePackageTask(
packageTask.packageDescription.set(executables.description)
packageTask.packageCopyright.set(executables.copyright)
packageTask.packageVendor.set(executables.vendor)
packageTask.packageVersion.set(packageVersionFor(packageTask.targetFormat))
// jpackage app-image: use the jpackage-safe version.
packageTask.packageVersion.set(jpackageVersionFor(packageTask.targetFormat))
}

val dirSuffix = if (sandboxed) "-sandboxed" else ""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@ internal fun JvmApplicationContext.packageVersionFor(targetFormat: TargetFormat)
?: "1.0.0"
}

/**
* Version used when jpackage builds the app-image (`--app-version`).
*
* jpackage is the only [io.github.kdroidfilter.nucleus.desktop.application.dsl.PackagingBackend.JPACKAGE]
* step ([TargetFormat.RawAppImage]) and enforces strict platform version rules — notably Windows
* rejects SemVer pre-release/build metadata such as `2.3.5-beta.7`. All real installer formats run
* through electron-builder and keep the full SemVer via [packageVersionFor].
*/
internal fun JvmApplicationContext.jpackageVersionFor(targetFormat: TargetFormat): Provider<String> =
packageVersionFor(targetFormat).map { it.toJpackageVersion() }

// jpackage rejects SemVer pre-release/build metadata; keep only the MAJOR.MINOR.PATCH core.
private fun String.toJpackageVersion(): String =
substringBefore('-').substringBefore('+')

@Suppress("CyclomaticComplexMethod") // Exhaustive when on TargetFormat enum
private fun JvmApplicationDistributions.packageVersionFor(targetFormat: TargetFormat): String? {
val formatSpecificVersion: String? =
Expand Down
Loading