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

Add missing type checks to interop container listener #1747

Merged
merged 1 commit into from
Dec 18, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ internal fun FocusEvent.isFocusGainedHandledBySwingPanel(container: Container) =
* @param key The unique identifier for the panel container.
* @param focusComponent The component that should receive focus.
*/
private class SwingInteropViewGroup(
internal class SwingInteropViewGroup(
key: Int,
private val focusComponent: Component
) : JPanel() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import androidx.compose.ui.SessionMutex
import androidx.compose.ui.awt.AwtEventListener
import androidx.compose.ui.awt.AwtEventListeners
import androidx.compose.ui.awt.OnlyValidPrimaryMouseButtonFilter
import androidx.compose.ui.awt.SwingInteropViewGroup
import androidx.compose.ui.awt.isFocusGainedHandledBySwingPanel
import androidx.compose.ui.awt.runOnEDTThread
import androidx.compose.ui.focus.FocusDirection
Expand Down Expand Up @@ -171,11 +172,13 @@ internal class ComposeSceneMediator(
requestRedraw = ::onComposeInvalidation
)

private val containerListener = object : ContainerListener {
private val clipMap = mutableMapOf<Component, ClipRectangle>()
private val interopContainerListener = object : ContainerListener {
private val clipMap = mutableMapOf<SwingInteropViewGroup, ClipRectangle>()

override fun componentAdded(e: ContainerEvent) {
val component = e.child
if (component !is SwingInteropViewGroup) return

if (useInteropBlending) {
// In case of interop blending, compose might draw content above this [component].
// But due to implementation of [JLayeredPane]'s lightweight/heavyweight mixing
Expand All @@ -192,17 +195,19 @@ internal class ComposeSceneMediator(

override fun componentRemoved(e: ContainerEvent) {
val component = e.child
if (component !is SwingInteropViewGroup) return

removeClipComponent(component)
component.unsubscribeFromMouseEvents(mouseListener)
}

private fun addClipComponent(component: Component) {
private fun addClipComponent(component: SwingInteropViewGroup) {
val clipRectangle = interopContainer.getClipRectForComponent(component)
clipMap[component] = clipRectangle
skiaLayerComponent.clipComponents.add(clipRectangle)
}

private fun removeClipComponent(component: Component) {
private fun removeClipComponent(component: SwingInteropViewGroup) {
clipMap.remove(component)?.let {
skiaLayerComponent.clipComponents.remove(it)
}
Expand Down Expand Up @@ -350,9 +355,9 @@ internal class ComposeSceneMediator(
container.add(invisibleComponent)
container.add(contentComponent)

// Adding a listener after adding [invisibleComponent] and [contentComponent]
// to react only on changes with [interopLayer].
container.addContainerListener(containerListener)
// Because interopContainer.root == container, add a listener only after adding
// [invisibleComponent] and [contentComponent] to react only on changes with [interopLayer].
interopContainer.root.addContainerListener(interopContainerListener)

// AwtDragAndDropManager support
container.transferHandler = dragAndDropManager.transferHandler
Expand Down Expand Up @@ -475,9 +480,10 @@ internal class ComposeSceneMediator(

unsubscribe(contentComponent)

// Since rendering will not happen after, we needs to execute all scheduled updates
interopContainer.root.removeContainerListener(interopContainerListener)
// Since rendering will not happen after, we need to execute all scheduled updates
interopContainer.dispose()
container.removeContainerListener(containerListener)

container.remove(contentComponent)
container.remove(invisibleComponent)
container.transferHandler = null
Expand Down