Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework transparent effect #8

Merged
merged 1 commit into from
Jun 13, 2022
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
3 changes: 2 additions & 1 deletion window-styler-demo/src/jvmMain/kotlin/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ val backdropOptions = listOf(
WindowBackdrop.Default to "Default",
WindowBackdrop.Solid(Color.Red) to "Solid Red",
WindowBackdrop.Solid(Color.Blue) to "Solid Blue",
WindowBackdrop.Transparent to "Transparent",
WindowBackdrop.Transparent(Color.Transparent) to "Transparent",
WindowBackdrop.Transparent(Color.Yellow.copy(alpha = 0.25F)) to "Yellow Transparent",
WindowBackdrop.Aero to "Aero",
WindowBackdrop.Acrylic(Color.Magenta.copy(alpha = 0.25F)) to "Acrylic Magenta",
WindowBackdrop.Acrylic(Color.Cyan.copy(alpha = 0.25F)) to "Acrylic Cyan",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ internal fun WindowBackdrop.toDwmSystemBackdrop(): DwmSystemBackdrop =
internal fun WindowBackdrop.toAccentState(): AccentState =
when (this) {
is WindowBackdrop.Default, is WindowBackdrop.Solid -> AccentState.ACCENT_ENABLE_GRADIENT
is WindowBackdrop.Transparent -> AccentState.ACCENT_ENABLE_TRANSPARENTGRADIENT
is WindowBackdrop.Aero -> AccentState.ACCENT_ENABLE_BLURBEHIND
is WindowBackdrop.Acrylic -> AccentState.ACCENT_ENABLE_ACRYLICBLURBEHIND
else -> AccentState.ACCENT_DISABLED
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,9 @@ internal fun Color.toAbgr(): Int {
((color[2] * 255.0f + 0.5f).toInt() shl 16) or
((color[1] * 255.0f + 0.5f).toInt() shl 8) or
(color[0] * 255.0f + 0.5f).toInt()
}
}

// For some reason, passing 0 (fully transparent black) to the setAccentPolicy with
// transparent accent policy results in solid red color. As a workaround, we pass
// fully transparent white which has the same visual effect.
internal fun Color.toAbgrForTransparent() = if (alpha == 0F) 0x00FFFFFF else toAbgr()
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import androidx.compose.ui.graphics.Color
sealed interface WindowBackdrop {
object Default : WindowBackdrop
data class Solid(override val color: Color) : ColorableWindowBackdrop
object Transparent : WindowBackdrop
data class Transparent(override val color: Color) : ColorableWindowBackdrop
object Aero : WindowBackdrop
data class Acrylic(override val color: Color) : ColorableWindowBackdrop
object Mica : WindowBackdrop
Expand All @@ -14,4 +14,4 @@ sealed interface WindowBackdrop {

internal interface ColorableWindowBackdrop : WindowBackdrop {
val color: Color
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,19 @@ fun FrameWindowScope.WindowStyle(
if (windowsBuild >= 17763) {
LaunchedEffect(isDarkTheme) {
setImmersiveDarkModeEnabled(hwnd, isDarkTheme)

// For some reason, using setImmersiveDarkModeEnabled after setting accent policy to transparent
// results in solid red backdrop. So, we have to reset the transparent backdrop after using it.
val finalLastEffect = lastEffect
if (finalLastEffect is WindowBackdrop.Transparent) {
setAccentPolicy(hwnd, AccentState.ACCENT_DISABLED)
setAccentPolicy(
hwnd = hwnd,
accentState = backdropType.toAccentState(),
accentFlags = setOf(AccentFlag.DRAW_ALL_BORDERS),
color = finalLastEffect.color.toAbgrForTransparent(),
)
}
}
}

Expand All @@ -43,8 +56,6 @@ fun FrameWindowScope.WindowStyle(
// Set [ACCENT_DISABLED] as [ACCENT_POLICY] to apply styles properly.
setAccentPolicy(hwnd, AccentState.ACCENT_DISABLED)

if (backdropType is WindowBackdrop.Transparent) return@invokeLater

// Only on later Windows 11 versions and if effect is WindowEffect.mica,
// WindowEffect.acrylic or WindowEffect.tabbed, otherwise fallback to old
// approach.
Expand Down Expand Up @@ -73,16 +84,22 @@ fun FrameWindowScope.WindowStyle(
setMicaEffectEnabled(hwnd, false)
}

val color = when (backdropType) {
is WindowBackdrop.Transparent -> backdropType.color.toAbgrForTransparent()
is ColorableWindowBackdrop -> backdropType.color.toAbgr()
else -> 0x7FFFFFFF
}

setAccentPolicy(
hwnd = hwnd,
accentState = backdropType.toAccentState(),
accentFlags = setOf(AccentFlag.DRAW_ALL_BORDERS),
color = (backdropType as? ColorableWindowBackdrop)?.color?.toAbgr() ?: 0x0FFFFFFF,
color = color,
)
}
}

lastEffect = backdropType
}
}
}
}