Open kirill-grouchnikov opened 3 years ago
You could try this template:
import androidx.compose.desktop.AppManager
import androidx.compose.desktop.Window
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Text
import androidx.compose.material.Surface
import androidx.compose.ui.Alignment
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.pointerMoveFilter
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.window.WindowDraggableArea
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import javax.swing.JFrame
fun main() {
Window(
undecorated = true
) {
Row(
modifier = Modifier.background(color = Color(75, 75, 75))
.fillMaxWidth()
.height(30.dp)
.padding(start = 20.dp, end = 10.dp),
verticalAlignment = Alignment.CenterVertically
) {
WindowDraggableArea(
modifier = Modifier.weight(1f)
) {
Text(text = "Undecorated window", color = Color.White)
}
Row {
Button(
onClick = {
val current = AppManager.focusedWindow
if (current != null) {
current.window.setExtendedState(JFrame.ICONIFIED)
}
}
)
Spacer(modifier = Modifier.width(5.dp))
Button(
onClick = {
val current = AppManager.focusedWindow
if (current != null) {
if (current.window.extendedState == JFrame.MAXIMIZED_BOTH) {
current.window.setExtendedState(JFrame.NORMAL)
} else {
current.window.setExtendedState(JFrame.MAXIMIZED_BOTH)
}
}
}
)
Spacer(modifier = Modifier.width(5.dp))
Button(
onClick = {
AppManager.focusedWindow?.close()
}
)
}
}
}
}
@Composable
fun Button(
text: String = "",
onClick: () -> Unit = {},
color: Color = Color(210, 210, 210),
size: Int = 16
) {
val buttonHover = remember { mutableStateOf(false) }
Surface(
color = if (buttonHover.value)
Color(color.red / 1.3f, color.green / 1.3f, color.blue / 1.3f)
else
color,
shape = RoundedCornerShape((size / 2).dp)
) {
Box(
modifier = Modifier
.clickable(onClick = onClick)
.size(size.dp, size.dp)
.pointerMoveFilter(
onEnter = {
buttonHover.value = true
false
},
onExit = {
buttonHover.value = false
false
},
onMove = { false }
)
) {
Text(text = text)
}
}
}
A more convenient API for managing window state (minimize, maximize, restore, fullscreen) will be ready soon. But for now, if you want to resize the undecorated window using the mouse, you must add listeners directly to the AppWindow.window ( JFrame). Also transparency is not ready for Compose for Desktop so you cannot create rounded undecorated windows.
Thanks Roman. We'd also need something for resizing undecorated windows by grabbing the window edge / corner and dragging those.
@Rsedaikin Is there any reference for the features this new API will support? I would be interested if it will support native window features like maximising without going into fullscreen or snap to side (aero snap) under windows
There are some resolution, but it require the JetBrains/JetBrainsRuntime
Some code for it: https://github.com/ButterCam/compose-jetbrains-theme/blob/main/expui/src/main/kotlin/io/kanro/compose/jetbrains/expui/util/CustomWindowDecorationAccessing.kt
See the readme for more information: https://github.com/ButterCam/compose-jetbrains-theme
Thanks Roman. We'd also need something for resizing undecorated windows by grabbing the window edge / corner and dragging those.
There are some resolution, but it require the JetBrains/JetBrainsRuntime
So far I use the latest compose-multiplatform (version: 1.4.0) with any jdk11 or jdk17 distributions. Using "undecorated=true" attribute, it works well for "resizing undecorated windows by grabbing the window edge / corner and dragging those".
So it seem it isn't necessary to get awt method using reflect @devkanro
plugins {
kotlin("jvm") version "1.8.20"
id("org.jetbrains.compose") version "1.4.0"
}
I think this is already fixed now with WindowDraggableArea
?
Not the resizing functionality
@amir1376 there are some updates for JBR, you can check the latest impl for it:
https://github.com/JetBrains/jewel/tree/main/decorated-window
Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.
What is the proposed approach to creating undecorated windows in Compose for Desktop that still need to display some sort of a draggable title pane area with close/minimize/maximize buttons?
The dragging / resizing in Swing is done as part of the
JRootPane
UI delegate. For example https://github.com/openjdk/jdk/blob/master/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalRootPaneUI.java#L698 for dragging and resizing under the Metal look-and-feel. The listener is then set on the whole window in https://github.com/openjdk/jdk/blob/master/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalRootPaneUI.java#L246 and processes all relevant mouse events.Is this the same approach that we should adopt for
Window
s created withundecorated=true
?