Skip to content

Commit 587a35e

Browse files
committed
Update lwjgl-integration
1 parent aeddeba commit 587a35e

File tree

4 files changed

+82
-30
lines changed

4 files changed

+82
-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: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
import androidx.compose.ui.ComposeScene
2-
import androidx.compose.ui.ExperimentalComposeUiApi
1+
/**
2+
* @author Enaium
3+
*/
4+
import androidx.compose.ui.InternalComposeUiApi
35
import androidx.compose.ui.geometry.Offset
6+
import androidx.compose.ui.input.key.Key
47
import androidx.compose.ui.input.key.KeyEvent
8+
import androidx.compose.ui.input.key.KeyEventType
59
import androidx.compose.ui.input.pointer.PointerEventType
10+
import androidx.compose.ui.scene.ComposeScene
611
import androidx.compose.ui.unit.Density
712
import org.lwjgl.glfw.GLFW.*
813
import java.awt.Component
@@ -11,7 +16,7 @@ import java.awt.event.MouseEvent
1116
import java.awt.event.MouseWheelEvent
1217
import java.awt.event.KeyEvent as AwtKeyEvent
1318

14-
@OptIn(ExperimentalComposeUiApi::class)
19+
@OptIn(InternalComposeUiApi::class)
1520
fun ComposeScene.subscribeToGLFWEvents(windowHandle: Long) {
1621
glfwSetMouseButtonCallback(windowHandle) { _, button, action, mods ->
1722
sendPointerEvent(
@@ -21,23 +26,23 @@ fun ComposeScene.subscribeToGLFWEvents(windowHandle: Long) {
2126
GLFW_RELEASE -> PointerEventType.Release
2227
else -> PointerEventType.Unknown
2328
},
24-
nativeEvent = MouseEvent(getAwtMods(windowHandle))
29+
nativeEvent = MouseEvent(getAwtMods(windowHandle))
2530
)
2631
}
2732

2833
glfwSetCursorPosCallback(windowHandle) { _, xpos, ypos ->
2934
sendPointerEvent(
3035
position = Offset(xpos.toFloat(), ypos.toFloat()),
3136
eventType = PointerEventType.Move,
32-
nativeEvent = MouseEvent(getAwtMods(windowHandle))
37+
nativeEvent = MouseEvent(getAwtMods(windowHandle))
3338
)
3439
}
3540

3641
glfwSetCursorEnterCallback(windowHandle) { _, entered ->
3742
sendPointerEvent(
3843
position = glfwGetCursorPos(windowHandle),
3944
eventType = if (entered) PointerEventType.Enter else PointerEventType.Exit,
40-
nativeEvent = MouseEvent(getAwtMods(windowHandle))
45+
nativeEvent = MouseEvent(getAwtMods(windowHandle))
4146
)
4247
}
4348

@@ -46,7 +51,7 @@ fun ComposeScene.subscribeToGLFWEvents(windowHandle: Long) {
4651
eventType = PointerEventType.Scroll,
4752
position = glfwGetCursorPos(windowHandle),
4853
scrollDelta = Offset(xoffset.toFloat(), -yoffset.toFloat()),
49-
nativeEvent = MouseWheelEvent(getAwtMods(windowHandle))
54+
nativeEvent = MouseWheelEvent(getAwtMods(windowHandle))
5055
)
5156
}
5257

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

6368
// Note that we don't distinguish between Left/Right Shift, Del from numpad or not, etc.
6469
// To distinguish we should change `location` parameter
65-
sendKeyEvent(KeyEvent(awtId, time, getAwtMods(windowHandle), awtKey, 0.toChar(), AwtKeyEvent.KEY_LOCATION_STANDARD))
70+
sendKeyEvent(
71+
KeyEvent(
72+
awtId,
73+
time,
74+
getAwtMods(windowHandle),
75+
awtKey,
76+
0.toChar(),
77+
AwtKeyEvent.KEY_LOCATION_STANDARD
78+
)
79+
)
6680
}
6781

6882
glfwSetCharCallback(windowHandle) { _, codepoint ->
6983
for (char in Character.toChars(codepoint)) {
7084
val time = System.nanoTime() / 1_000_000
71-
sendKeyEvent(KeyEvent(AwtKeyEvent.KEY_TYPED, time, getAwtMods(windowHandle), 0, char, AwtKeyEvent.KEY_LOCATION_UNKNOWN))
85+
sendKeyEvent(
86+
KeyEvent(
87+
AwtKeyEvent.KEY_TYPED,
88+
time,
89+
getAwtMods(windowHandle),
90+
0,
91+
char,
92+
AwtKeyEvent.KEY_LOCATION_UNKNOWN
93+
)
94+
)
7295
}
7396
}
7497

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

113+
@OptIn(InternalComposeUiApi::class)
90114
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)
115+
key = Key(key),
116+
codePoint = char.code,
117+
type = if (awtId == AwtKeyEvent.KEY_PRESSED) KeyEventType.KeyDown else if (awtId == AwtKeyEvent.KEY_RELEASED) KeyEventType.KeyUp else KeyEventType.Unknown,
118+
nativeEvent = AwtKeyEvent(awtComponent, awtId, time, awtMods, key, char, location)
92119
)
93120

94121
private fun MouseEvent(awtMods: Int) = MouseEvent(
@@ -111,11 +138,23 @@ private fun getAwtMods(windowHandle: Long): Int {
111138
awtMods = awtMods or (1 shl 14)
112139
if (glfwGetMouseButton(windowHandle, GLFW_MOUSE_BUTTON_5) == GLFW_PRESS)
113140
awtMods = awtMods or (1 shl 15)
114-
if (glfwGetKey(windowHandle, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || glfwGetKey(windowHandle, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS)
141+
if (glfwGetKey(windowHandle, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || glfwGetKey(
142+
windowHandle,
143+
GLFW_KEY_RIGHT_CONTROL
144+
) == GLFW_PRESS
145+
)
115146
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)
147+
if (glfwGetKey(windowHandle, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS || glfwGetKey(
148+
windowHandle,
149+
GLFW_KEY_RIGHT_SHIFT
150+
) == GLFW_PRESS
151+
)
117152
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)
153+
if (glfwGetKey(windowHandle, GLFW_KEY_LEFT_ALT) == GLFW_PRESS || glfwGetKey(
154+
windowHandle,
155+
GLFW_KEY_RIGHT_ALT
156+
) == GLFW_PRESS
157+
)
119158
awtMods = awtMods or InputEvent.ALT_DOWN_MASK
120159
return awtMods
121-
}
160+
}

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)