Skip to content

Instantly share code, notes, and snippets.

@adrientetar
Created March 19, 2025 02:12
Show Gist options
  • Select an option

  • Save adrientetar/b039998a0752261d2ee7db9ade3e7c15 to your computer and use it in GitHub Desktop.

Select an option

Save adrientetar/b039998a0752261d2ee7db9ade3e7c15 to your computer and use it in GitHub Desktop.
Custom title bar in Compose Multiplatform with JBR runtime. Updated for the new WindowDecorations API. known JBR 17 old version: b1207.30 new version: b1367.22
import sun.misc.Unsafe
import java.awt.Frame
import java.lang.reflect.AccessibleObject
import java.lang.reflect.Method
/**
* Access custom window decoration functions in the JetBrains Runtime.
*
* Original code: <https://github.com/ButterCam/compose-jetbrains-theme/blob/main/expui/src/main/kotlin/io/kanro/compose/jetbrains/expui/util/CustomWindowDecorationAccessing.kt>
* Updated for new WindowDecorations JBR API: <https://android.googlesource.com/platform/external/jetbrains/JetBrainsRuntime/+/a8a5398a738fab3daa559874e779faad9c85e746%5E%21/#F24>
*/
object WindowDecorations {
init {
UnsafeAccess.assignAccessibility(
UnsafeAccess.desktopModule,
listOf("java.awt")
)
}
private val windowDecorationsInstance: Any? = try {
val windowDecorations = Class.forName(windowDecorationsClassName)
val constructor = windowDecorations.declaredConstructors.first()
constructor.isAccessible = true
constructor.newInstance()
} catch (e: Exception) {
null
}
private val createCustomTitleBarMethod: Method? =
getMethod("createCustomTitleBar")
private val setHeightMethod: Method? =
getCustomTitleBarMethod("setHeight", Float::class.java)
private fun getMethod(name: String, vararg params: Class<*>): Method? {
return try {
val clazz = Class.forName(windowDecorationsClassName)
val method = clazz.getDeclaredMethod(name, *params)
method.isAccessible = true
method
} catch (e: Exception) {
null
}
}
private fun getCustomTitleBarMethod(name: String, vararg params: Class<*>): Method? {
return try {
val clazz = Class.forName(customTitleBarClassName)
val method = clazz.getDeclaredMethod(name, *params)
method.isAccessible = true
method
} catch (e: Exception) {
null
}
}
/**
* Disable the system title bar for the provided [frame] - only retain the window controls,
* centered around the provided [height].
*
* @return `true` if the custom title bar was set successfully, `false` otherwise.
*/
fun setCustomTitleBar(frame: Frame, height: Float): Boolean {
val windowDecorations = windowDecorationsInstance ?: return false
// Create custom title bar
val customTitleBar = run {
val method = createCustomTitleBarMethod ?: return false
method.invoke(windowDecorations) ?: return false
}
// Set the height
val setHeightMethod = setHeightMethod ?: return false
setHeightMethod.invoke(customTitleBar, height)
// Set custom title bar
val setCustomTitleBarMethod = getMethod(
"setCustomTitleBar", Frame::class.java, customTitleBar::class.java
) ?: return false
setCustomTitleBarMethod.invoke(windowDecorations, frame, customTitleBar)
return true
}
}
private const val windowDecorationsClassName = "java.awt.Window\$WindowDecorations"
private const val customTitleBarClassName = "java.awt.Window\$CustomTitleBar"
private object UnsafeAccess {
private val unsafe: Any? by lazy {
try {
val theUnsafe = Unsafe::class.java.getDeclaredField("theUnsafe")
theUnsafe.isAccessible = true
theUnsafe.get(null) as Unsafe
} catch (e: Throwable) {
null
}
}
val desktopModule by lazy {
ModuleLayer.boot().findModule("java.desktop").get()
}
val ownerModule by lazy {
this.javaClass.module
}
private val isAccessibleFieldOffset: Long? by lazy {
try {
(unsafe as? Unsafe)?.objectFieldOffset(Parent::class.java.getDeclaredField("first"))
} catch (e: Throwable) {
null
}
}
private val implAddOpens by lazy {
try {
Module::class.java.getDeclaredMethod(
"implAddOpens", String::class.java, Module::class.java
).accessible()
} catch (e: Throwable) {
null
}
}
fun assignAccessibility(obj: AccessibleObject) {
try {
val theUnsafe = unsafe as? Unsafe ?: return
val offset = isAccessibleFieldOffset ?: return
theUnsafe.putBooleanVolatile(obj, offset, true)
} catch (e: Throwable) {
// ignore
}
}
fun assignAccessibility(module: Module, packages: List<String>) {
try {
packages.forEach {
implAddOpens?.invoke(module, it, ownerModule)
}
} catch (e: Throwable) {
// ignore
}
}
private class Parent {
var first = false
@Volatile
var second: Any? = null
}
}
private fun <T : AccessibleObject> T.accessible(): T {
return apply {
UnsafeAccess.assignAccessibility(this)
}
}
@Frosty-J
Copy link

Frosty-J commented Sep 9, 2025

Do you know if we can allow the OS to handle mouse events in that title bar area? For dragging and such.

I can do WindowDraggableArea() { Box(Modifier.fillMaxWidth().height(titleBarHeight)) } but that doesn't support Aero snap or double-clicking to maximise, nor does it restore the window if dragging when maximised or have the native position constraints.

I also tried looking at https://github.com/compose-fluent/compose-fluent-ui/tree/master/gallery/src/desktopMain/kotlin/io/github/composefluent/gallery but cannot see an easy way to extract its custom title bar solution since it's so integrated into the gallery project and associated library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment