Skip to content

Commit 437cadf

Browse files
committed
Update lwjgl-integration
1 parent aeddeba commit 437cadf

File tree

4 files changed

+79
-30
lines changed

4 files changed

+79
-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: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1-
import androidx.compose.ui.ComposeScene
2-
import androidx.compose.ui.unit.Constraints
1+
/**
2+
* @author Enaium
3+
*/
4+
import androidx.compose.ui.InternalComposeUiApi
5+
import androidx.compose.ui.graphics.asComposeCanvas
6+
import androidx.compose.ui.scene.CanvasLayersComposeScene
7+
import androidx.compose.ui.scene.ComposeScene
38
import androidx.compose.ui.unit.Density
9+
import androidx.compose.ui.unit.IntSize
410
import org.jetbrains.skia.*
511
import org.jetbrains.skia.FramebufferFormat.Companion.GR_GL_RGBA8
612
import org.jetbrains.skiko.FrameDispatcher
@@ -11,6 +17,7 @@ import org.lwjgl.opengl.GL30.GL_FRAMEBUFFER_BINDING
1117
import org.lwjgl.system.MemoryUtil.NULL
1218
import kotlin.system.exitProcess
1319

20+
@OptIn(InternalComposeUiApi::class)
1421
fun main() {
1522
var width = 640
1623
var height = 480
@@ -35,9 +42,10 @@ fun main() {
3542
lateinit var composeScene: ComposeScene
3643

3744
fun render() {
38-
surface.canvas.clear(Color.WHITE)
39-
composeScene.constraints = Constraints(maxWidth = width, maxHeight = height)
40-
composeScene.render(surface.canvas, System.nanoTime())
45+
surface ?: return
46+
surface!!.canvas.clear(Color.WHITE)
47+
composeScene.size = IntSize(width, height)
48+
composeScene.render(surface!!.canvas.asComposeCanvas(), System.nanoTime())
4149

4250
context.flush()
4351
glfwSwapBuffers(windowHandle)
@@ -46,12 +54,17 @@ fun main() {
4654
val frameDispatcher = FrameDispatcher(glfwDispatcher) { render() }
4755

4856
val density = Density(glfwGetWindowContentScale(windowHandle))
49-
composeScene = ComposeScene(glfwDispatcher, density, invalidate = frameDispatcher::scheduleFrame)
57+
composeScene =
58+
CanvasLayersComposeScene(
59+
density = density,
60+
coroutineContext = glfwDispatcher,
61+
invalidate = frameDispatcher::scheduleFrame
62+
)
5063

5164
glfwSetWindowSizeCallback(windowHandle) { _, windowWidth, windowHeight ->
5265
width = windowWidth
5366
height = windowHeight
54-
surface.close()
67+
surface?.close()
5568
surface = createSurface(width, height, context)
5669

5770
glfwSwapInterval(0)
@@ -71,7 +84,7 @@ fun main() {
7184
exitProcess(0)
7285
}
7386

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

0 commit comments

Comments
 (0)