Skip to content

Commit

Permalink
Merge pull request #124 from JetBrains/feature/fix_drag_undecorated2
Browse files Browse the repository at this point in the history
Fix consuming events of undecorated resizable window
  • Loading branch information
igordmn authored Nov 26, 2021
2 parents ca6db90 + 02261c9 commit 9bbf022
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 140 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import androidx.compose.foundation.text.InlineTextContent
import androidx.compose.foundation.text.appendInlineContent
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.foundation.verticalScroll
import androidx.compose.foundation.window.WindowDraggableArea
import androidx.compose.material.BottomAppBar
import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
Expand Down Expand Up @@ -113,6 +114,7 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextDecoration.Companion.Underline
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.em
Expand Down Expand Up @@ -153,17 +155,19 @@ private fun FrameWindowScope.App() {
MaterialTheme {
Scaffold(
topBar = {
TopAppBar(
title = {
Row(verticalAlignment = Alignment.CenterVertically) {
Image(
painterResource("androidx/compose/desktop/example/star.svg"),
contentDescription = "Star"
)
Text(title)
WindowDraggableArea {
TopAppBar(
title = {
Row(verticalAlignment = Alignment.CenterVertically) {
Image(
painterResource("androidx/compose/desktop/example/star.svg"),
contentDescription = "Star"
)
Text(title)
}
}
}
)
)
}
},
floatingActionButton = {
ExtendedFloatingActionButton(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class ComposeDialog(
owner: Window? = null,
modalityType: ModalityType = ModalityType.MODELESS
) : JDialog(owner, modalityType) {
private val delegate = ComposeWindowDelegate(this)
private val delegate = ComposeWindowDelegate(this, ::isUndecorated)
internal val layer get() = delegate.layer

init {
Expand Down Expand Up @@ -115,41 +115,22 @@ class ComposeDialog(
super.dispose()
}

private val undecoratedWindowResizer = UndecoratedWindowResizer(this, layer)

override fun setUndecorated(value: Boolean) {
super.setUndecorated(value)
undecoratedWindowResizer.enabled = isUndecorated && isResizable
delegate.undecoratedWindowResizer.enabled = isUndecorated && isResizable
}

override fun setResizable(value: Boolean) {
super.setResizable(value)
undecoratedWindowResizer.enabled = isUndecorated && isResizable
delegate.undecoratedWindowResizer.enabled = isUndecorated && isResizable
}

/**
* `true` if background of the window is transparent, `false` otherwise
* Transparency should be set only if window is not showing and `isUndecorated` is set to
* `true`, otherwise AWT will throw an exception.
*/
var isTransparent: Boolean
get() = layer.component.transparency
set(value) {
if (value != layer.component.transparency) {
check(isUndecorated) { "Transparent window should be undecorated!" }
check(!isDisplayable) {
"Cannot change transparency if window is already displayable."
}
layer.component.transparency = value
if (value) {
if (hostOs != OS.Windows) {
background = Color(0, 0, 0, 0)
}
} else {
background = null
}
}
}
var isTransparent: Boolean by delegate::isTransparent

/**
* Registers a task to run when the rendering API changes.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ import javax.swing.JFrame
class ComposeWindow(
graphicsConfiguration: GraphicsConfiguration? = null
) : JFrame(graphicsConfiguration) {
private val delegate = ComposeWindowDelegate(this)
private val delegate = ComposeWindowDelegate(this, ::isUndecorated)
internal val layer get() = delegate.layer

init {
Expand Down Expand Up @@ -118,41 +118,22 @@ class ComposeWindow(
super.dispose()
}

private val undecoratedWindowResizer = UndecoratedWindowResizer(this, layer)

override fun setUndecorated(value: Boolean) {
super.setUndecorated(value)
undecoratedWindowResizer.enabled = isUndecorated && isResizable
delegate.undecoratedWindowResizer.enabled = isUndecorated && isResizable
}

override fun setResizable(value: Boolean) {
super.setResizable(value)
undecoratedWindowResizer.enabled = isUndecorated && isResizable
delegate.undecoratedWindowResizer.enabled = isUndecorated && isResizable
}

/**
* `true` if background of the window is transparent, `false` otherwise
* Transparency should be set only if window is not showing and `isUndecorated` is set to
* `true`, otherwise AWT will throw an exception.
*/
var isTransparent: Boolean
get() = layer.component.transparency
set(value) {
if (value != layer.component.transparency) {
check(isUndecorated) { "Transparent window should be undecorated!" }
check(!isDisplayable) {
"Cannot change transparency if window is already displayable."
}
layer.component.transparency = value
if (value) {
if (hostOs != OS.Windows) {
background = Color(0, 0, 0, 0)
}
} else {
background = null
}
}
}
var isTransparent: Boolean by delegate::isTransparent

var placement: WindowPlacement
get() = when {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,29 @@ import androidx.compose.runtime.CompositionLocalContext
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.input.key.KeyEvent
import androidx.compose.ui.window.LocalWindow
import androidx.compose.ui.window.UndecoratedWindowResizer
import org.jetbrains.skiko.ClipComponent
import org.jetbrains.skiko.GraphicsApi
import org.jetbrains.skiko.OS
import org.jetbrains.skiko.SkiaLayer
import org.jetbrains.skiko.hostOs
import java.awt.Color
import java.awt.Component
import java.awt.Window
import java.awt.event.MouseListener
import java.awt.event.MouseMotionListener
import java.awt.event.MouseWheelListener
import javax.swing.JLayeredPane

internal class ComposeWindowDelegate(private val window: Window) {
internal class ComposeWindowDelegate(
private val window: Window,
private val isUndecorated: () -> Boolean
) {
private var isDisposed = false

val layer = ComposeLayer()
val undecoratedWindowResizer = UndecoratedWindowResizer(window)

val pane = object : JLayeredPane() {
override fun setBounds(x: Int, y: Int, width: Int, height: Int) {
layer.component.setSize(width, height)
Expand Down Expand Up @@ -67,6 +76,7 @@ internal class ComposeWindowDelegate(private val window: Window) {
init {
pane.layout = null
pane.add(layer.component, Integer.valueOf(1))
setContent {}
}

fun add(component: Component): Component {
Expand All @@ -93,6 +103,7 @@ internal class ComposeWindowDelegate(private val window: Window) {
LocalLayerContainer provides pane
) {
content()
undecoratedWindowResizer.Content()
}
}
}
Expand All @@ -116,6 +127,25 @@ internal class ComposeWindowDelegate(private val window: Window) {
val renderApi: GraphicsApi
get() = layer.component.renderApi

var isTransparent: Boolean
get() = layer.component.transparency
set(value) {
if (value != layer.component.transparency) {
check(isUndecorated()) { "Transparent window should be undecorated!" }
check(!window.isDisplayable) {
"Cannot change transparency if window is already displayable."
}
layer.component.transparency = value
if (value) {
if (hostOs != OS.Windows) {
window.background = Color(0, 0, 0, 0)
}
} else {
window.background = null
}
}
}

fun addMouseListener(listener: MouseListener) {
layer.component.addMouseListener(listener)
}
Expand Down
Loading

0 comments on commit 9bbf022

Please sign in to comment.