Unverified Commit 47215871 authored by Shagen Ogandzhanian's avatar Shagen Ogandzhanian Committed by GitHub

Remove media events from Skiko completely (#892)

This is the skiko part of
https://youtrack.jetbrains.com/issue/COMPOSE-1149/wasm-js-Remove-media-events-from-Skiko

This commit introduces following changes:

 * CanvasRenderer is html-agnostic and deals with NativePointer
* SkiaLayer does not set any DOM dimensions of the canvas - it's up to
the user of the Skia to resolve this dimensions
 * Media event listeners are removed completely
parent 574e3eee
...@@ -10,10 +10,10 @@ ...@@ -10,10 +10,10 @@
<body> <body>
<h1>Skiko running with K/JS</h1> <h1>Skiko running with K/JS</h1>
<canvas id="c1" width="300" height="300"></canvas> <canvas id="c1" width="600" height="600" style="width: 300px; height: 300px"></canvas>
<canvas id="c2" width="300" height="300"></canvas> <canvas id="c2" width="600" height="600" style="width: 300px; height: 300px"></canvas>
<div> <div>
<canvas id="c3" width="606" height="400"></canvas> <canvas id="c3" width="1212" height="800" style="width: 606px; height: 400px"></canvas>
</div> </div>
</body> </body>
</html> </html>
\ No newline at end of file
...@@ -9,10 +9,10 @@ ...@@ -9,10 +9,10 @@
<body> <body>
<h1>Skiko running with K/Wasm</h1> <h1>Skiko running with K/Wasm</h1>
<canvas id="c1" width="300" height="300"></canvas> <canvas id="c1" width="600" height="600" style="width: 300px; height: 300px"></canvas>
<canvas id="c2" width="300" height="300"></canvas> <canvas id="c2" width="600" height="600" style="width: 300px; height: 300px"></canvas>
<div> <div>
<canvas id="c3" width="606" height="400"></canvas> <canvas id="c3" width="1212" height="800" style="width: 606px; height: 400px"></canvas>
</div> </div>
</body> </body>
</html> </html>
...@@ -15,11 +15,10 @@ fun main() { ...@@ -15,11 +15,10 @@ fun main() {
internal fun runApp() { internal fun runApp() {
val skiaLayer = SkiaLayer() val skiaLayer = SkiaLayer()
skiaLayer.onContentScaleChanged = { scale -> println(scale) }
val game = JsClocks(skiaLayer) val game = JsClocks(skiaLayer)
skiaLayer.skikoView = GenericSkikoView(skiaLayer, game) skiaLayer.skikoView = GenericSkikoView(skiaLayer, game)
val canvas = document.getElementById("SkikoTarget") as HTMLCanvasElement val canvas = document.getElementById("SkikoTarget") as HTMLCanvasElement
canvas.setAttribute("tabindex", "0") canvas.setAttribute("tabindex", "0")
skiaLayer.attachTo(canvas) skiaLayer.attachTo(canvas)
skiaLayer.needRedraw() skiaLayer.needRedraw()
} }
\ No newline at end of file
...@@ -11,11 +11,10 @@ fun main() { ...@@ -11,11 +11,10 @@ fun main() {
internal fun runApp() { internal fun runApp() {
val skiaLayer = SkiaLayer() val skiaLayer = SkiaLayer()
skiaLayer.onContentScaleChanged = { scale -> println(scale) }
val game = JsClocks(skiaLayer) val game = JsClocks(skiaLayer)
skiaLayer.skikoView = GenericSkikoView(skiaLayer, game) skiaLayer.skikoView = GenericSkikoView(skiaLayer, game)
val canvas = document.getElementById("SkikoTarget") as HTMLCanvasElement val canvas = document.getElementById("SkikoTarget") as HTMLCanvasElement
canvas.setAttribute("tabindex", "0") canvas.setAttribute("tabindex", "0")
skiaLayer.attachTo(canvas) skiaLayer.attachTo(canvas)
skiaLayer.needRedraw() skiaLayer.needRedraw()
} }
\ No newline at end of file
package org.jetbrains.skiko package org.jetbrains.skiko
import kotlinx.browser.window
import org.w3c.dom.AddEventListenerOptions
import org.w3c.dom.MediaQueryListEvent
import org.w3c.dom.events.KeyboardEvent import org.w3c.dom.events.KeyboardEvent
import org.w3c.dom.events.UIEvent import org.w3c.dom.events.UIEvent
actual typealias SkikoGesturePlatformEvent = Any actual typealias SkikoGesturePlatformEvent = Any
actual typealias SkikoPlatformInputEvent = KeyboardEvent actual typealias SkikoPlatformInputEvent = KeyboardEvent
actual typealias SkikoPlatformKeyboardEvent = KeyboardEvent actual typealias SkikoPlatformKeyboardEvent = KeyboardEvent
// MouseEvent is base class of PointerEvent // MouseEvent is base class of PointerEvent
actual typealias SkikoPlatformPointerEvent = UIEvent actual typealias SkikoPlatformPointerEvent = UIEvent
internal actual fun SkiaLayer.setOnChangeScaleNotifier() {
state?.initCanvas(desiredWidth, desiredHeight, contentScale, this.pixelGeometry)
window.matchMedia("(resolution: ${contentScale}dppx)")
.addEventListener("change", { evt ->
evt as MediaQueryListEvent
if (!evt.matches) {
setOnChangeScaleNotifier()
}
}, AddEventListenerOptions(capture = true, once = true))
onContentScaleChanged?.invoke(contentScale)
}
\ No newline at end of file
...@@ -14,9 +14,10 @@ import org.jetbrains.skiko.wasm.createWebGLContext ...@@ -14,9 +14,10 @@ import org.jetbrains.skiko.wasm.createWebGLContext
* [drawFrame] has to be implemented to perform the actual drawing on [canvas]. * [drawFrame] has to be implemented to perform the actual drawing on [canvas].
*/ */
internal abstract class CanvasRenderer( internal abstract class CanvasRenderer(
private val htmlCanvas: HTMLCanvasElement private val contextPointer: NativePointer,
val width: Int,
val height: Int,
) { ) {
private val contextPointer = createWebGLContext(htmlCanvas)
private val context: DirectContext private val context: DirectContext
private var surface: Surface? = null private var surface: Surface? = null
private var renderTarget: BackendRenderTarget? = null private var renderTarget: BackendRenderTarget? = null
...@@ -28,35 +29,15 @@ internal abstract class CanvasRenderer( ...@@ -28,35 +29,15 @@ internal abstract class CanvasRenderer(
protected var canvas: Canvas? = null protected var canvas: Canvas? = null
private set private set
/**
* The current width of [htmlCanvas]
*/
val width: Int
get() = htmlCanvas.width
/**
* The current height of [htmlCanvas]
*/
val height: Int
get() = htmlCanvas.height
init { init {
makeGLContextCurrent(contextPointer) makeGLContextCurrent(contextPointer)
context = DirectContext.makeGL() context = DirectContext.makeGL()
initCanvas()
} }
/** fun initCanvas() {
* Initializes the canvas.
*
* @param desiredWidth - width in pixels
* @param desiredHeight - height in pixels
* @param scale - a value to adjust the canvas' size
* (https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio)
*/
fun initCanvas(desiredWidth: Int, desiredHeight: Int, scale: Float, pixelGeometry: PixelGeometry) {
disposeCanvas() disposeCanvas()
htmlCanvas.width = (desiredWidth * scale).toInt()
htmlCanvas.height = (desiredHeight * scale).toInt()
renderTarget = BackendRenderTarget.makeGL(width, height, 1, 8, 0, 0x8058) renderTarget = BackendRenderTarget.makeGL(width, height, 1, 8, 0, 0x8058)
surface = Surface.makeFromBackendRenderTarget( surface = Surface.makeFromBackendRenderTarget(
context, context,
...@@ -64,7 +45,7 @@ internal abstract class CanvasRenderer( ...@@ -64,7 +45,7 @@ internal abstract class CanvasRenderer(
SurfaceOrigin.BOTTOM_LEFT, SurfaceOrigin.BOTTOM_LEFT,
SurfaceColorFormat.RGBA_8888, SurfaceColorFormat.RGBA_8888,
ColorSpace.sRGB, ColorSpace.sRGB,
SurfaceProps(pixelGeometry = pixelGeometry) SurfaceProps()
) ?: throw RenderException("Cannot create surface") ) ?: throw RenderException("Cannot create surface")
canvas = surface!!.canvas canvas = surface!!.canvas
} }
......
...@@ -4,6 +4,7 @@ import org.jetbrains.skia.Canvas ...@@ -4,6 +4,7 @@ import org.jetbrains.skia.Canvas
import org.jetbrains.skia.PixelGeometry import org.jetbrains.skia.PixelGeometry
import org.jetbrains.skiko.w3c.HTMLCanvasElement import org.jetbrains.skiko.w3c.HTMLCanvasElement
import org.jetbrains.skiko.w3c.window import org.jetbrains.skiko.w3c.window
import org.jetbrains.skiko.wasm.createWebGLContext
/** /**
* Provides a way to render the content and to receive the input events. * Provides a way to render the content and to receive the input events.
...@@ -61,18 +62,13 @@ actual open class SkiaLayer { ...@@ -61,18 +62,13 @@ actual open class SkiaLayer {
* @param container - should be an instance of [HTMLCanvasElement] * @param container - should be an instance of [HTMLCanvasElement]
*/ */
actual fun attachTo(container: Any) { actual fun attachTo(container: Any) {
attachTo(container as HTMLCanvasElement, false) attachTo(container as HTMLCanvasElement)
} }
actual fun detach() { actual fun detach() {
// TODO: when switch to the frame dispatcher - stop it here. // TODO: when switch to the frame dispatcher - stop it here.
} }
internal var isPointerPressed = false
internal var desiredWidth = 0
internal var desiredHeight = 0
actual val component: Any? actual val component: Any?
get() = this.htmlCanvas get() = this.htmlCanvas
...@@ -82,25 +78,16 @@ actual open class SkiaLayer { ...@@ -82,25 +78,16 @@ actual open class SkiaLayer {
* Initializes the [CanvasRenderer] and events listeners. * Initializes the [CanvasRenderer] and events listeners.
* Delegates rendering and events processing to [skikoView]. * Delegates rendering and events processing to [skikoView].
*/ */
private fun attachTo(htmlCanvas: HTMLCanvasElement, autoDetach: Boolean = true) { private fun attachTo(htmlCanvas: HTMLCanvasElement) {
this.htmlCanvas = htmlCanvas this.htmlCanvas = htmlCanvas
// Scale canvas to allow high DPI rendering as suggested in state = object: CanvasRenderer(createWebGLContext(htmlCanvas), htmlCanvas.width, htmlCanvas.height) {
// https://www.khronos.org/webgl/wiki/HandlingHighDPI.
desiredWidth = htmlCanvas.width
desiredHeight = htmlCanvas.height
htmlCanvas.style.width = "${desiredWidth}px"
htmlCanvas.style.height = "${desiredHeight}px"
setOnChangeScaleNotifier()
state = object: CanvasRenderer(htmlCanvas) {
override fun drawFrame(currentTimestamp: Double) { override fun drawFrame(currentTimestamp: Double) {
// currentTimestamp is in milliseconds. // currentTimestamp is in milliseconds.
val currentNanos = currentTimestamp * 1_000_000 val currentNanos = currentTimestamp * 1_000_000
skikoView?.onRender(canvas!!, width, height, currentNanos.toLong()) skikoView?.onRender(canvas!!, width, height, currentNanos.toLong())
} }
}.apply { initCanvas(desiredWidth, desiredHeight, contentScale, pixelGeometry) } }
// See https://www.w3schools.com/jsref/dom_obj_event.asp
// https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events
} }
internal actual fun draw(canvas: Canvas) { internal actual fun draw(canvas: Canvas) {
...@@ -109,9 +96,4 @@ actual open class SkiaLayer { ...@@ -109,9 +96,4 @@ actual open class SkiaLayer {
actual val pixelGeometry: PixelGeometry actual val pixelGeometry: PixelGeometry
get() = PixelGeometry.UNKNOWN get() = PixelGeometry.UNKNOWN
}
var onContentScaleChanged: ((Float) -> Unit)? = null \ No newline at end of file
}
internal expect fun SkiaLayer.setOnChangeScaleNotifier()
package org.jetbrains.skiko package org.jetbrains.skiko
import kotlinx.browser.window
import org.w3c.dom.AddEventListenerOptions
import org.w3c.dom.MediaQueryListEvent
import org.w3c.dom.events.KeyboardEvent import org.w3c.dom.events.KeyboardEvent
import org.w3c.dom.events.UIEvent import org.w3c.dom.events.UIEvent
...@@ -12,15 +8,3 @@ actual typealias SkikoGesturePlatformEvent = Any ...@@ -12,15 +8,3 @@ actual typealias SkikoGesturePlatformEvent = Any
actual typealias SkikoPlatformInputEvent = KeyboardEvent actual typealias SkikoPlatformInputEvent = KeyboardEvent
actual typealias SkikoPlatformKeyboardEvent = KeyboardEvent actual typealias SkikoPlatformKeyboardEvent = KeyboardEvent
actual typealias SkikoPlatformPointerEvent = UIEvent actual typealias SkikoPlatformPointerEvent = UIEvent
internal actual fun SkiaLayer.setOnChangeScaleNotifier() {
state?.initCanvas(desiredWidth, desiredHeight, contentScale, this.pixelGeometry)
window.matchMedia("(resolution: ${contentScale}dppx)")
.addEventListener("change", { evt ->
evt as MediaQueryListEvent
if (!evt.matches) {
setOnChangeScaleNotifier()
}
}, AddEventListenerOptions(capture = true, once = true))
onContentScaleChanged?.invoke(contentScale)
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment