-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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 more info about lwjgl integration #1738
base: master
Are you sure you want to change the base?
Conversation
|
||
CompositionLocalProvider( | ||
LocalLayerContainer provides awtContainer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LocalLayerContainer
is internal. Please describe in this doc how you use it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rememberCursorPosition
is using AWT to get mouse position, in an app with ComposeSence, currently, the only way to make cursor related feature (ContextMenu, CursorPopup, Tooltip) work is to provide a fake AWT Container and update window bound and position for the fake container, and you need to implement your own window region detection, render scaling, etc.
This can be removed or changed if we could have something LocalMouseLocationProvider
mentioned in #1736
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean, how do you able to use/access LocalLayerContainer
? It is marked as internal, so you can't access it in default Gradle/Kotlin configuration. Do you add some arguments to Kotlin compiler?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I just create a fake class and override in the classpath(Gradle default duplicate strategy should work). My current workaround is to create a package androidx.compose.ui.awt
and create a file LocalLayerContainer.desktop.kt
import androidx.compose.runtime.staticCompositionLocalOf
import your.package.awtContainer
val LocalLayerContainer: androidx.compose.runtime.ProvidableCompositionLocal<java.awt.Container> =
staticCompositionLocalOf { awtContainer }
I am also trying to make a kotlin compiler plugin to remove all access modifiers and make everything public open.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just create a fake class and override in the classpath
Smart :). Could you add this into the doc?
Also, could you describe in ## Problems
that this section contains only temporary workarounds, that won't needed when Compose resolves these problems.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- The file should contain the package:
package androidx.compose.ui.awt
- Better to write this:
package androidx.compose.ui.awt
import androidx.compose.runtime.compositionLocalOf
import java.awt.Container
internal val LocalLayerContainer = compositionLocalOf<Container> {
error("CompositionLocal LayerContainer not provided")
}
because we use CompositionLocalProvider
to pass awtContainer
- I have an exception (on Windows):
Exception in thread "main" java.lang.NullPointerException: graphicsConfiguration must not be null
at androidx.compose.ui.window.LayoutConfiguration_desktopKt.getDensity(LayoutConfiguration.desktop.kt:39)
at androidx.compose.ui.window.DesktopPopup_desktopKt.rememberCursorPositionProvider-B5uucgQ(DesktopPopup.desktop.kt:236)
at androidx.compose.foundation.TooltipPlacement$CursorPoint.positionProvider(TooltipArea.desktop.kt:227)
at androidx.compose.foundation.TooltipArea_desktopKt.TooltipArea(TooltipArea.desktop.kt:151)
when I try to run:
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.TooltipArea
import androidx.compose.foundation.TooltipPlacement
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Button
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.awt.LocalLayerContainer
import androidx.compose.ui.awt.awtContainer
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.dp
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun App() {
CompositionLocalProvider(LocalLayerContainer provides awtContainer) {
val buttons =
listOf("Button A", "Button B", "Button C", "Button D", "Button E", "Button F")
Column(Modifier.fillMaxSize(), Arrangement.spacedBy(5.dp)) {
buttons.forEachIndexed { index, name ->
// wrap button in BoxWithTooltip
TooltipArea(
tooltip = {
// composable tooltip content
Surface(
modifier = Modifier.shadow(4.dp),
color = Color(255, 255, 210),
shape = RoundedCornerShape(4.dp)
) {
Text(
text = "Tooltip for ${name}",
modifier = Modifier.padding(10.dp)
)
}
},
modifier = Modifier.padding(start = 40.dp),
delayMillis = 600, // in milliseconds
tooltipPlacement = TooltipPlacement.CursorPoint(
alignment = Alignment.BottomEnd,
offset = if (index % 2 == 0) DpOffset(
-16.dp,
0.dp
) else DpOffset.Zero // tooltip offset
)
) {
Button(onClick = {}) { Text(text = name) }
}
}
}
}
}
How have you solved it?
- Add a note to
## Problems
:
This section describes the current issues with LWJGL integration, and suggests temporary workarounds. These workarounds won't be needed when these issues are fixed in Compose.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, weird. I didn't run into a null pointer error (with ComposeSence).
It might be caused by AWT headless property, try System.setProperty("java.awt.headless", "false")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This works for me:
val awtContainer = object : Container() {
// Note that this can cause some issues with multiple displays with different densities
// (if some widget relies on the density of this container)
override fun getGraphicsConfiguration() =
GraphicsEnvironment.getLocalGraphicsEnvironment()
.defaultScreenDevice
.defaultConfiguration
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can avoid classpath hacks with just using @Suppress("INVISIBLE_MEMBER")
on use-site.
|
||
### Popup | ||
Since Compose still use some AWT events (https://github.com/JetBrains/compose-jb/issues/1736), you can provide a fake contaniner. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since Compose still use some AWT events (https://github.com/JetBrains/compose-jb/issues/1736), you can provide a fake contaniner. | |
Since Compose still use some AWT events (https://github.com/JetBrains/compose-jb/issues/1736), you can provide a fake container. |
I am working with Compose and LWJGL on Linux. |
No description provided.