Skip to content

Commit 9fa2a69

Browse files
committed
Update lwjgl-integration
1 parent aeddeba commit 9fa2a69

File tree

4 files changed

+76
-30
lines changed

4 files changed

+76
-30
lines changed

experimental/lwjgl-integration/build.gradle.kts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import org.jetbrains.compose.compose
22
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
33

44
plugins {
5-
kotlin("jvm") version "1.5.31"
6-
id("org.jetbrains.compose") version "1.0.0"
5+
kotlin("jvm") version "2.1.10"
6+
id("org.jetbrains.kotlin.plugin.compose") version "2.1.10"
7+
id("org.jetbrains.compose") version "1.8.0-alpha02"
78
}
89

910
repositories {

experimental/lwjgl-integration/src/main/kotlin/App.kt

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
import androidx.compose.foundation.VerticalScrollbar
2-
import androidx.compose.foundation.layout.*
2+
import androidx.compose.foundation.layout.Box
3+
import androidx.compose.foundation.layout.Column
4+
import androidx.compose.foundation.layout.fillMaxHeight
5+
import androidx.compose.foundation.layout.width
36
import androidx.compose.foundation.lazy.LazyColumn
47
import androidx.compose.foundation.lazy.rememberLazyListState
58
import androidx.compose.foundation.rememberScrollbarAdapter
69
import androidx.compose.material.Button
710
import androidx.compose.material.Text
811
import androidx.compose.material.TextField
9-
import androidx.compose.runtime.Composable
10-
import androidx.compose.runtime.mutableStateOf
11-
import androidx.compose.runtime.remember
12-
import androidx.compose.runtime.getValue
13-
import androidx.compose.runtime.setValue
12+
import androidx.compose.runtime.*
1413
import androidx.compose.ui.Alignment
1514
import androidx.compose.ui.Modifier
1615
import androidx.compose.ui.unit.dp

experimental/lwjgl-integration/src/main/kotlin/GlfwEvents.kt

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
import androidx.compose.ui.ComposeScene
2-
import androidx.compose.ui.ExperimentalComposeUiApi
1+
import androidx.compose.ui.InternalComposeUiApi
32
import androidx.compose.ui.geometry.Offset
3+
import androidx.compose.ui.input.key.Key
44
import androidx.compose.ui.input.key.KeyEvent
5+
import androidx.compose.ui.input.key.KeyEventType
56
import androidx.compose.ui.input.pointer.PointerEventType
7+
import androidx.compose.ui.scene.ComposeScene
68
import androidx.compose.ui.unit.Density
79
import org.lwjgl.glfw.GLFW.*
810
import java.awt.Component
@@ -11,7 +13,7 @@ import java.awt.event.MouseEvent
1113
import java.awt.event.MouseWheelEvent
1214
import java.awt.event.KeyEvent as AwtKeyEvent
1315

14-
@OptIn(ExperimentalComposeUiApi::class)
16+
@OptIn(InternalComposeUiApi::class)
1517
fun ComposeScene.subscribeToGLFWEvents(windowHandle: Long) {
1618
glfwSetMouseButtonCallback(windowHandle) { _, button, action, mods ->
1719
sendPointerEvent(
@@ -21,23 +23,23 @@ fun ComposeScene.subscribeToGLFWEvents(windowHandle: Long) {
2123
GLFW_RELEASE -> PointerEventType.Release
2224
else -> PointerEventType.Unknown
2325
},
24-
nativeEvent = MouseEvent(getAwtMods(windowHandle))
26+
nativeEvent = MouseEvent(getAwtMods(windowHandle))
2527
)
2628
}
2729

2830
glfwSetCursorPosCallback(windowHandle) { _, xpos, ypos ->
2931
sendPointerEvent(
3032
position = Offset(xpos.toFloat(), ypos.toFloat()),
3133
eventType = PointerEventType.Move,
32-
nativeEvent = MouseEvent(getAwtMods(windowHandle))
34+
nativeEvent = MouseEvent(getAwtMods(windowHandle))
3335
)
3436
}
3537

3638
glfwSetCursorEnterCallback(windowHandle) { _, entered ->
3739
sendPointerEvent(
3840
position = glfwGetCursorPos(windowHandle),
3941
eventType = if (entered) PointerEventType.Enter else PointerEventType.Exit,
40-
nativeEvent = MouseEvent(getAwtMods(windowHandle))
42+
nativeEvent = MouseEvent(getAwtMods(windowHandle))
4143
)
4244
}
4345

@@ -46,7 +48,7 @@ fun ComposeScene.subscribeToGLFWEvents(windowHandle: Long) {
4648
eventType = PointerEventType.Scroll,
4749
position = glfwGetCursorPos(windowHandle),
4850
scrollDelta = Offset(xoffset.toFloat(), -yoffset.toFloat()),
49-
nativeEvent = MouseWheelEvent(getAwtMods(windowHandle))
51+
nativeEvent = MouseWheelEvent(getAwtMods(windowHandle))
5052
)
5153
}
5254

@@ -62,13 +64,31 @@ fun ComposeScene.subscribeToGLFWEvents(windowHandle: Long) {
6264

6365
// Note that we don't distinguish between Left/Right Shift, Del from numpad or not, etc.
6466
// To distinguish we should change `location` parameter
65-
sendKeyEvent(KeyEvent(awtId, time, getAwtMods(windowHandle), awtKey, 0.toChar(), AwtKeyEvent.KEY_LOCATION_STANDARD))
67+
sendKeyEvent(
68+
KeyEvent(
69+
awtId,
70+
time,
71+
getAwtMods(windowHandle),
72+
awtKey,
73+
0.toChar(),
74+
AwtKeyEvent.KEY_LOCATION_STANDARD
75+
)
76+
)
6677
}
6778

6879
glfwSetCharCallback(windowHandle) { _, codepoint ->
6980
for (char in Character.toChars(codepoint)) {
7081
val time = System.nanoTime() / 1_000_000
71-
sendKeyEvent(KeyEvent(AwtKeyEvent.KEY_TYPED, time, getAwtMods(windowHandle), 0, char, AwtKeyEvent.KEY_LOCATION_UNKNOWN))
82+
sendKeyEvent(
83+
KeyEvent(
84+
AwtKeyEvent.KEY_TYPED,
85+
time,
86+
getAwtMods(windowHandle),
87+
0,
88+
char,
89+
AwtKeyEvent.KEY_LOCATION_UNKNOWN
90+
)
91+
)
7292
}
7393
}
7494

@@ -87,8 +107,12 @@ private fun glfwGetCursorPos(window: Long): Offset {
87107
// in the future versions of Compose we plan to get rid of the need of AWT events/components
88108
val awtComponent = object : Component() {}
89109

110+
@OptIn(InternalComposeUiApi::class)
90111
private fun KeyEvent(awtId: Int, time: Long, awtMods: Int, key: Int, char: Char, location: Int) = KeyEvent(
91-
AwtKeyEvent(awtComponent, awtId, time, awtMods, key, char, location)
112+
key = Key(key),
113+
codePoint = char.code,
114+
type = if (awtId == AwtKeyEvent.KEY_PRESSED) KeyEventType.KeyDown else if (awtId == AwtKeyEvent.KEY_RELEASED) KeyEventType.KeyUp else KeyEventType.Unknown,
115+
nativeEvent = AwtKeyEvent(awtComponent, awtId, time, awtMods, key, char, location)
92116
)
93117

94118
private fun MouseEvent(awtMods: Int) = MouseEvent(
@@ -111,11 +135,23 @@ private fun getAwtMods(windowHandle: Long): Int {
111135
awtMods = awtMods or (1 shl 14)
112136
if (glfwGetMouseButton(windowHandle, GLFW_MOUSE_BUTTON_5) == GLFW_PRESS)
113137
awtMods = awtMods or (1 shl 15)
114-
if (glfwGetKey(windowHandle, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || glfwGetKey(windowHandle, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS)
138+
if (glfwGetKey(windowHandle, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || glfwGetKey(
139+
windowHandle,
140+
GLFW_KEY_RIGHT_CONTROL
141+
) == GLFW_PRESS
142+
)
115143
awtMods = awtMods or InputEvent.CTRL_DOWN_MASK
116-
if (glfwGetKey(windowHandle, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS || glfwGetKey(windowHandle, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS)
144+
if (glfwGetKey(windowHandle, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS || glfwGetKey(
145+
windowHandle,
146+
GLFW_KEY_RIGHT_SHIFT
147+
) == GLFW_PRESS
148+
)
117149
awtMods = awtMods or InputEvent.SHIFT_DOWN_MASK
118-
if (glfwGetKey(windowHandle, GLFW_KEY_LEFT_ALT) == GLFW_PRESS || glfwGetKey(windowHandle, GLFW_KEY_RIGHT_ALT) == GLFW_PRESS)
150+
if (glfwGetKey(windowHandle, GLFW_KEY_LEFT_ALT) == GLFW_PRESS || glfwGetKey(
151+
windowHandle,
152+
GLFW_KEY_RIGHT_ALT
153+
) == GLFW_PRESS
154+
)
119155
awtMods = awtMods or InputEvent.ALT_DOWN_MASK
120156
return awtMods
121-
}
157+
}

experimental/lwjgl-integration/src/main/kotlin/main.kt

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
import androidx.compose.ui.ComposeScene
2-
import androidx.compose.ui.unit.Constraints
1+
import androidx.compose.ui.InternalComposeUiApi
2+
import androidx.compose.ui.graphics.asComposeCanvas
3+
import androidx.compose.ui.scene.CanvasLayersComposeScene
4+
import androidx.compose.ui.scene.ComposeScene
35
import androidx.compose.ui.unit.Density
6+
import androidx.compose.ui.unit.IntSize
47
import org.jetbrains.skia.*
58
import org.jetbrains.skia.FramebufferFormat.Companion.GR_GL_RGBA8
69
import org.jetbrains.skiko.FrameDispatcher
@@ -11,6 +14,7 @@ import org.lwjgl.opengl.GL30.GL_FRAMEBUFFER_BINDING
1114
import org.lwjgl.system.MemoryUtil.NULL
1215
import kotlin.system.exitProcess
1316

17+
@OptIn(InternalComposeUiApi::class)
1418
fun main() {
1519
var width = 640
1620
var height = 480
@@ -35,9 +39,10 @@ fun main() {
3539
lateinit var composeScene: ComposeScene
3640

3741
fun render() {
38-
surface.canvas.clear(Color.WHITE)
39-
composeScene.constraints = Constraints(maxWidth = width, maxHeight = height)
40-
composeScene.render(surface.canvas, System.nanoTime())
42+
surface ?: return
43+
surface!!.canvas.clear(Color.WHITE)
44+
composeScene.size = IntSize(width, height)
45+
composeScene.render(surface!!.canvas.asComposeCanvas(), System.nanoTime())
4146

4247
context.flush()
4348
glfwSwapBuffers(windowHandle)
@@ -46,12 +51,17 @@ fun main() {
4651
val frameDispatcher = FrameDispatcher(glfwDispatcher) { render() }
4752

4853
val density = Density(glfwGetWindowContentScale(windowHandle))
49-
composeScene = ComposeScene(glfwDispatcher, density, invalidate = frameDispatcher::scheduleFrame)
54+
composeScene =
55+
CanvasLayersComposeScene(
56+
density = density,
57+
coroutineContext = glfwDispatcher,
58+
invalidate = frameDispatcher::scheduleFrame
59+
)
5060

5161
glfwSetWindowSizeCallback(windowHandle) { _, windowWidth, windowHeight ->
5262
width = windowWidth
5363
height = windowHeight
54-
surface.close()
64+
surface?.close()
5565
surface = createSurface(width, height, context)
5666

5767
glfwSwapInterval(0)
@@ -71,7 +81,7 @@ fun main() {
7181
exitProcess(0)
7282
}
7383

74-
private fun createSurface(width: Int, height: Int, context: DirectContext): Surface {
84+
private fun createSurface(width: Int, height: Int, context: DirectContext): Surface? {
7585
val fbId = GL11.glGetInteger(GL_FRAMEBUFFER_BINDING)
7686
val renderTarget = BackendRenderTarget.makeGL(width, height, 0, 8, fbId, GR_GL_RGBA8)
7787
return Surface.makeFromBackendRenderTarget(

0 commit comments

Comments
 (0)