@@ -19,6 +19,7 @@ import androidx.compose.ui.Alignment
1919import androidx.compose.ui.ExperimentalComposeUiApi
2020import androidx.compose.ui.Modifier
2121import androidx.compose.ui.graphics.Color
22+ import androidx.compose.ui.graphics.ColorFilter
2223import androidx.compose.ui.graphics.painter.Painter
2324import androidx.compose.ui.graphics.vector.rememberVectorPainter
2425import androidx.compose.ui.input.pointer.PointerEventType
@@ -50,6 +51,7 @@ import dev.nucleusframework.window.icons.windows.RestoreDark
5051import dev.nucleusframework.window.icons.windows.RestoreInactive
5152import dev.nucleusframework.window.icons.windows.RestoreInactiveDark
5253import dev.nucleusframework.window.icons.windows.WindowsControlButtonIcons
54+ import dev.nucleusframework.window.styling.TitleBarStyle
5355import dev.nucleusframework.window.tao.TaoWindow
5456
5557// Mirrors `decorated-window-core/WindowsWindowControlArea.kt` so the visual
@@ -93,6 +95,7 @@ private val WindowsCloseButtonPressed = Color(0xFFF1707A)
9395internal fun WindowControlsWindows (
9496 win : TaoWindow ,
9597 state : DecoratedWindowState ,
98+ style : TitleBarStyle ,
9699 modifier : Modifier = Modifier ,
97100 isFullscreen : Boolean = false,
98101 onExitFullscreen : (() -> Unit )? = null,
@@ -106,6 +109,7 @@ internal fun WindowControlsWindows(
106109 WindowsCaptionButton (
107110 onClick = { win.minimize() },
108111 isDark = isDark,
112+ style = style,
109113 icon =
110114 if (state.isActive) {
111115 if (isDark) WindowsControlButtonIcons .MinimizeDark else WindowsControlButtonIcons .Minimize
@@ -125,6 +129,7 @@ internal fun WindowControlsWindows(
125129 WindowsCaptionButton (
126130 onClick = onExitFullscreen,
127131 isDark = isDark,
132+ style = style,
128133 icon =
129134 if (state.isActive) {
130135 if (isDark) {
@@ -149,6 +154,7 @@ internal fun WindowControlsWindows(
149154 WindowsCaptionButton (
150155 onClick = { win.setMaximized(false ) },
151156 isDark = isDark,
157+ style = style,
152158 icon =
153159 if (state.isActive) {
154160 if (isDark) WindowsControlButtonIcons .RestoreDark else WindowsControlButtonIcons .Restore
@@ -165,6 +171,7 @@ internal fun WindowControlsWindows(
165171 WindowsCaptionButton (
166172 onClick = { win.setMaximized(true ) },
167173 isDark = isDark,
174+ style = style,
168175 icon =
169176 if (state.isActive) {
170177 if (isDark) WindowsControlButtonIcons .MaximizeDark else WindowsControlButtonIcons .Maximize
@@ -185,6 +192,7 @@ internal fun WindowControlsWindows(
185192 WindowsCaptionButton (
186193 onClick = { win.requestUserClose() },
187194 isDark = isDark,
195+ style = style,
188196 icon =
189197 if (state.isActive) {
190198 if (isDark) WindowsControlButtonIcons .CloseDark else WindowsControlButtonIcons .Close
@@ -209,6 +217,7 @@ internal fun WindowControlsWindows(
209217private fun WindowsCaptionButton (
210218 onClick : () -> Unit ,
211219 isDark : Boolean ,
220+ style : TitleBarStyle ,
212221 icon : androidx.compose.ui.graphics.vector.ImageVector ,
213222 contentDescription : String ,
214223 iconHover : androidx.compose.ui.graphics.vector.ImageVector ? = null,
@@ -218,20 +227,28 @@ private fun WindowsCaptionButton(
218227 var pressed by remember { mutableStateOf(false ) }
219228
220229 val backgroundColor =
221- when {
222- pressed && isCloseButton -> WindowsCloseButtonPressed
223- pressed -> if (isDark) WindowsButtonPressedDark else WindowsButtonPressedLight
224- hovered && isCloseButton -> WindowsCloseButtonHovered
225- hovered -> if ( isDark) WindowsButtonHoveredDark else WindowsButtonHoveredLight
226- else -> Color . Transparent
227- }
230+ captionButtonBackground(
231+ hovered = hovered,
232+ pressed = pressed,
233+ isCloseButton = isCloseButton,
234+ isDark = isDark,
235+ style = style,
236+ )
228237
229238 val isCloseHovered = (hovered || pressed) && isCloseButton
230239 val currentIcon: Painter =
231240 rememberVectorPainter(
232241 if (isCloseHovered && iconHover != null ) iconHover else icon,
233242 )
234243
244+ val colorFilter =
245+ captionButtonColorFilter(
246+ hovered = hovered,
247+ pressed = pressed,
248+ isCloseHovered = isCloseHovered,
249+ style = style,
250+ )
251+
235252 Box (
236253 modifier =
237254 Modifier
@@ -252,6 +269,51 @@ private fun WindowsCaptionButton(
252269 ),
253270 contentAlignment = Alignment .Center ,
254271 ) {
255- Image (painter = currentIcon, contentDescription = contentDescription)
272+ Image (painter = currentIcon, contentDescription = contentDescription, colorFilter = colorFilter)
273+ }
274+ }
275+
276+ // Mirrors `decorated-window-core/WindowsWindowControlArea.kt` so custom
277+ // [TitleBarStyle] colors apply identically on the Tao backend. Close-button
278+ // hover/pressed always use the fixed Windows red — matching AWT.
279+ private fun captionButtonBackground (
280+ hovered : Boolean ,
281+ pressed : Boolean ,
282+ isCloseButton : Boolean ,
283+ isDark : Boolean ,
284+ style : TitleBarStyle ,
285+ ): Color {
286+ val customHover = style.colors.iconButtonHoveredBackground
287+ val customPressed = style.colors.iconButtonPressedBackground
288+ val pressedColor =
289+ customPressed.takeUnless { it == Color .Transparent }
290+ ? : if (isDark) WindowsButtonPressedDark else WindowsButtonPressedLight
291+ val hoveredColor =
292+ customHover.takeUnless { it == Color .Transparent }
293+ ? : if (isDark) WindowsButtonHoveredDark else WindowsButtonHoveredLight
294+ return when {
295+ pressed && isCloseButton -> WindowsCloseButtonPressed
296+ pressed -> pressedColor
297+ hovered && isCloseButton -> WindowsCloseButtonHovered
298+ hovered -> hoveredColor
299+ else -> Color .Transparent
300+ }
301+ }
302+
303+ private fun captionButtonColorFilter (
304+ hovered : Boolean ,
305+ pressed : Boolean ,
306+ isCloseHovered : Boolean ,
307+ style : TitleBarStyle ,
308+ ): ColorFilter ? {
309+ val iconTint = style.colors.controlButtonIconColor
310+ val iconHoverTint = style.colors.controlButtonIconHoverColor
311+ return when {
312+ // Close hover swaps to the baked-red close artwork; don't tint it.
313+ isCloseHovered -> null
314+ (hovered || pressed) && iconHoverTint != Color .Unspecified ->
315+ ColorFilter .tint(iconHoverTint)
316+ iconTint != Color .Unspecified -> ColorFilter .tint(iconTint)
317+ else -> null
256318 }
257319}
0 commit comments