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 @@
<body>
<h1>Skiko running with K/JS</h1>
<canvas id="c1" width="300" height="300"></canvas>
<canvas id="c2" width="300" height="300"></canvas>
<canvas id="c1" width="600" height="600" style="width: 300px; height: 300px"></canvas>
<canvas id="c2" width="600" height="600" style="width: 300px; height: 300px"></canvas>
<div>
<canvas id="c3" width="606" height="400"></canvas>
<canvas id="c3" width="1212" height="800" style="width: 606px; height: 400px"></canvas>
</div>
</body>
</html>
\ No newline at end of file
......@@ -9,10 +9,10 @@
<body>
<h1>Skiko running with K/Wasm</h1>
<canvas id="c1" width="300" height="300"></canvas>
<canvas id="c2" width="300" height="300"></canvas>
<canvas id="c1" width="600" height="600" style="width: 300px; height: 300px"></canvas>
<canvas id="c2" width="600" height="600" style="width: 300px; height: 300px"></canvas>
<div>
<canvas id="c3" width="606" height="400"></canvas>
<canvas id="c3" width="1212" height="800" style="width: 606px; height: 400px"></canvas>
</div>
</body>
</html>
......@@ -15,11 +15,10 @@ fun main() {
internal fun runApp() {
val skiaLayer = SkiaLayer()
skiaLayer.onContentScaleChanged = { scale -> println(scale) }
val game = JsClocks(skiaLayer)
skiaLayer.skikoView = GenericSkikoView(skiaLayer, game)
val canvas = document.getElementById("SkikoTarget") as HTMLCanvasElement
canvas.setAttribute("tabindex", "0")
skiaLayer.attachTo(canvas)
skiaLayer.needRedraw()
}
\ No newline at end of file
}
......@@ -11,11 +11,10 @@ fun main() {
internal fun runApp() {
val skiaLayer = SkiaLayer()
skiaLayer.onContentScaleChanged = { scale -> println(scale) }
val game = JsClocks(skiaLayer)
skiaLayer.skikoView = GenericSkikoView(skiaLayer, game)
val canvas = document.getElementById("SkikoTarget") as HTMLCanvasElement
canvas.setAttribute("tabindex", "0")
skiaLayer.attachTo(canvas)
skiaLayer.needRedraw()
}
\ No newline at end of file
}
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.UIEvent
actual typealias SkikoGesturePlatformEvent = Any
actual typealias SkikoPlatformInputEvent = KeyboardEvent
actual typealias SkikoPlatformKeyboardEvent = KeyboardEvent
// MouseEvent is base class of PointerEvent
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
* [drawFrame] has to be implemented to perform the actual drawing on [canvas].
*/
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 var surface: Surface? = null
private var renderTarget: BackendRenderTarget? = null
......@@ -28,35 +29,15 @@ internal abstract class CanvasRenderer(
protected var canvas: Canvas? = null
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 {
makeGLContextCurrent(contextPointer)
context = DirectContext.makeGL()
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) {
fun initCanvas() {
disposeCanvas()
htmlCanvas.width = (desiredWidth * scale).toInt()
htmlCanvas.height = (desiredHeight * scale).toInt()
renderTarget = BackendRenderTarget.makeGL(width, height, 1, 8, 0, 0x8058)
surface = Surface.makeFromBackendRenderTarget(
context,
......@@ -64,7 +45,7 @@ internal abstract class CanvasRenderer(
SurfaceOrigin.BOTTOM_LEFT,
SurfaceColorFormat.RGBA_8888,
ColorSpace.sRGB,
SurfaceProps(pixelGeometry = pixelGeometry)
SurfaceProps()
) ?: throw RenderException("Cannot create surface")
canvas = surface!!.canvas
}
......
......@@ -4,6 +4,7 @@ import org.jetbrains.skia.Canvas
import org.jetbrains.skia.PixelGeometry
import org.jetbrains.skiko.w3c.HTMLCanvasElement
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.
......@@ -61,18 +62,13 @@ actual open class SkiaLayer {
* @param container - should be an instance of [HTMLCanvasElement]
*/
actual fun attachTo(container: Any) {
attachTo(container as HTMLCanvasElement, false)
attachTo(container as HTMLCanvasElement)
}
actual fun detach() {
// 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?
get() = this.htmlCanvas
......@@ -82,25 +78,16 @@ actual open class SkiaLayer {
* Initializes the [CanvasRenderer] and events listeners.
* Delegates rendering and events processing to [skikoView].
*/
private fun attachTo(htmlCanvas: HTMLCanvasElement, autoDetach: Boolean = true) {
private fun attachTo(htmlCanvas: HTMLCanvasElement) {
this.htmlCanvas = htmlCanvas
// Scale canvas to allow high DPI rendering as suggested in
// 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) {
state = object: CanvasRenderer(createWebGLContext(htmlCanvas), htmlCanvas.width, htmlCanvas.height) {
override fun drawFrame(currentTimestamp: Double) {
// currentTimestamp is in milliseconds.
val currentNanos = currentTimestamp * 1_000_000
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) {
......@@ -109,9 +96,4 @@ actual open class SkiaLayer {
actual val pixelGeometry: PixelGeometry
get() = PixelGeometry.UNKNOWN
var onContentScaleChanged: ((Float) -> Unit)? = null
}
internal expect fun SkiaLayer.setOnChangeScaleNotifier()
}
\ No newline at end of file
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.UIEvent
......@@ -12,15 +8,3 @@ actual typealias SkikoGesturePlatformEvent = Any
actual typealias SkikoPlatformInputEvent = KeyboardEvent
actual typealias SkikoPlatformKeyboardEvent = KeyboardEvent
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