Unverified Commit 5b5ee682 authored by jershell's avatar jershell Committed by GitHub

Support touch events on mobile`s browsers (#850)

* add support for touchscreen events in js for mobile devices

* add touchevents for wasm

---------
Co-authored-by: 's avatardmitriy tukhvatullin <tukhvatullin01@gmail.com>
parent fd9a62d5
package org.jetbrains.skiko package org.jetbrains.skiko
import org.w3c.dom.TouchEvent
import org.w3c.dom.asList
import org.w3c.dom.events.KeyboardEvent import org.w3c.dom.events.KeyboardEvent
import org.w3c.dom.events.MouseEvent import org.w3c.dom.events.MouseEvent
import org.w3c.dom.events.WheelEvent import org.w3c.dom.events.WheelEvent
...@@ -35,6 +37,38 @@ internal fun toSkikoDragEvent( ...@@ -35,6 +37,38 @@ internal fun toSkikoDragEvent(
) )
} }
internal fun toSkikoEvent(
event: TouchEvent,
kind: SkikoPointerEventKind,
offsetX: Double,
offsetY: Double
): SkikoPointerEvent {
val touches = event.changedTouches.asList()
val pointers = touches.map { touch ->
val x = touch.clientX.toDouble() - offsetX
val y = touch.clientY.toDouble() - offsetY
val force = touch.asDynamic().force as Double
SkikoPointer(
x = x,
y = y,
pressed = kind in listOf(SkikoPointerEventKind.DOWN, SkikoPointerEventKind.MOVE),
device = SkikoPointerDevice.TOUCH,
id = touch.identifier.toLong(),
pressure = force
)
}
return SkikoPointerEvent(
x = pointers.centroidX,
y = pointers.centroidY,
kind = kind,
timestamp = (currentNanoTime() / 1E6).toLong(),
pointers = pointers,
platform = event
)
}
internal fun toSkikoTypeEvent( internal fun toSkikoTypeEvent(
character: String, character: String,
event: KeyboardEvent?, event: KeyboardEvent?,
......
...@@ -2,15 +2,42 @@ package org.jetbrains.skiko ...@@ -2,15 +2,42 @@ package org.jetbrains.skiko
import kotlinx.browser.window import kotlinx.browser.window
import org.jetbrains.skiko.w3c.HTMLCanvasElement import org.jetbrains.skiko.w3c.HTMLCanvasElement
import org.w3c.dom.TouchEvent
import org.w3c.dom.events.KeyboardEvent import org.w3c.dom.events.KeyboardEvent
import org.w3c.dom.events.MouseEvent import org.w3c.dom.events.MouseEvent
import org.w3c.dom.events.WheelEvent import org.w3c.dom.events.WheelEvent
import org.w3c.dom.events.UIEvent
internal actual fun SkiaLayer.bindCanvasEventsToSkikoView( internal actual fun SkiaLayer.bindCanvasEventsToSkikoView(
canvas: HTMLCanvasElement canvas: HTMLCanvasElement
) { ) {
val htmlCanvas = canvas.unsafeCast<org.w3c.dom.HTMLCanvasElement>() val htmlCanvas = canvas.unsafeCast<org.w3c.dom.HTMLCanvasElement>()
var offsetX = 0.0
var offsetY = 0.0
htmlCanvas.addEventListener("touchstart", { event ->
event.preventDefault()
event as TouchEvent
htmlCanvas.getBoundingClientRect().apply {
offsetX = left
offsetY = top
}
skikoView?.onPointerEvent(toSkikoEvent(event, SkikoPointerEventKind.DOWN, offsetX, offsetY))
})
htmlCanvas.addEventListener("touchmove", { event ->
event.preventDefault()
event as TouchEvent
skikoView?.onPointerEvent(toSkikoEvent(event, SkikoPointerEventKind.MOVE, offsetX, offsetY))
})
htmlCanvas.addEventListener("touchend", { event ->
event.preventDefault()
event as TouchEvent
skikoView?.onPointerEvent(toSkikoEvent(event, SkikoPointerEventKind.UP, offsetX, offsetY))
})
htmlCanvas.addEventListener("touchcancel", { event ->
event.preventDefault()
event as TouchEvent
skikoView?.onPointerEvent(toSkikoEvent(event, SkikoPointerEventKind.UP, offsetX, offsetY))
})
htmlCanvas.addEventListener("mousedown", { event -> htmlCanvas.addEventListener("mousedown", { event ->
event as MouseEvent event as MouseEvent
isPointerPressed = true isPointerPressed = true
...@@ -54,7 +81,7 @@ actual typealias SkikoGesturePlatformEvent = Any ...@@ -54,7 +81,7 @@ 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 = MouseEvent actual typealias SkikoPlatformPointerEvent = UIEvent
internal actual fun SkiaLayer.setOnChangeScaleNotifier() { internal actual fun SkiaLayer.setOnChangeScaleNotifier() {
state?.initCanvas(desiredWidth, desiredHeight, contentScale, this.pixelGeometry) state?.initCanvas(desiredWidth, desiredHeight, contentScale, this.pixelGeometry)
......
package org.jetbrains.skiko package org.jetbrains.skiko
import org.w3c.dom.TouchEvent
import org.w3c.dom.asList
import org.w3c.dom.events.KeyboardEvent import org.w3c.dom.events.KeyboardEvent
import org.w3c.dom.events.MouseEvent import org.w3c.dom.events.MouseEvent
import org.w3c.dom.events.WheelEvent import org.w3c.dom.events.WheelEvent
internal external abstract class ExtendedTouchEvent: TouchEvent {
val force: Double
}
internal fun toSkikoEvent(
event: TouchEvent,
kind: SkikoPointerEventKind,
offsetX: Double,
offsetY: Double
): SkikoPointerEvent {
val touches = event.changedTouches.asList()
val pointers = touches.map { touch ->
val x = touch.clientX.toDouble() - offsetX
val y = touch.clientY.toDouble() - offsetY
val force = touch.unsafeCast<ExtendedTouchEvent>().force
SkikoPointer(
x = x,
y = y,
pressed = kind in listOf(SkikoPointerEventKind.DOWN, SkikoPointerEventKind.MOVE),
device = SkikoPointerDevice.TOUCH,
id = touch.identifier.toLong(),
pressure = force
)
}
return SkikoPointerEvent(
x = pointers.centroidX,
y = pointers.centroidY,
kind = kind,
timestamp = (currentNanoTime() / 1E6).toLong(),
pointers = pointers,
platform = event
)
}
internal fun toSkikoEvent( internal fun toSkikoEvent(
event: MouseEvent, event: MouseEvent,
kind: SkikoPointerEventKind kind: SkikoPointerEventKind
......
...@@ -2,16 +2,43 @@ package org.jetbrains.skiko ...@@ -2,16 +2,43 @@ package org.jetbrains.skiko
import kotlinx.browser.window import kotlinx.browser.window
import org.jetbrains.skiko.w3c.HTMLCanvasElement import org.jetbrains.skiko.w3c.HTMLCanvasElement
import org.w3c.dom.TouchEvent
import org.w3c.dom.events.KeyboardEvent import org.w3c.dom.events.KeyboardEvent
import org.w3c.dom.events.MouseEvent import org.w3c.dom.events.MouseEvent
import org.w3c.dom.events.UIEvent
import org.w3c.dom.events.WheelEvent import org.w3c.dom.events.WheelEvent
internal actual fun SkiaLayer.bindCanvasEventsToSkikoView( internal actual fun SkiaLayer.bindCanvasEventsToSkikoView(
canvas: HTMLCanvasElement canvas: HTMLCanvasElement
) { ) {
val htmlCanvas = canvas as org.w3c.dom.HTMLCanvasElement val htmlCanvas = canvas as org.w3c.dom.HTMLCanvasElement
var offsetX = 0.0
var offsetY = 0.0
htmlCanvas.addEventListener("touchstart", { event ->
event.preventDefault()
event as TouchEvent
htmlCanvas.getBoundingClientRect().apply {
offsetX = left
offsetY = top
}
skikoView?.onPointerEvent(toSkikoEvent(event, SkikoPointerEventKind.DOWN, offsetX, offsetY))
})
htmlCanvas.addEventListener("touchmove", { event ->
event.preventDefault()
event as TouchEvent
skikoView?.onPointerEvent(toSkikoEvent(event, SkikoPointerEventKind.MOVE, offsetX, offsetY))
})
htmlCanvas.addEventListener("touchend", { event ->
event.preventDefault()
event as TouchEvent
skikoView?.onPointerEvent(toSkikoEvent(event, SkikoPointerEventKind.UP, offsetX, offsetY))
})
htmlCanvas.addEventListener("touchcancel", { event ->
event.preventDefault()
event as TouchEvent
skikoView?.onPointerEvent(toSkikoEvent(event, SkikoPointerEventKind.UP, offsetX, offsetY))
})
htmlCanvas.addEventListener("mousedown", { event -> htmlCanvas.addEventListener("mousedown", { event ->
event as MouseEvent event as MouseEvent
isPointerPressed = true isPointerPressed = true
...@@ -55,7 +82,7 @@ actual typealias SkikoGesturePlatformEvent = Any ...@@ -55,7 +82,7 @@ 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 = MouseEvent actual typealias SkikoPlatformPointerEvent = UIEvent
internal actual fun SkiaLayer.setOnChangeScaleNotifier() { internal actual fun SkiaLayer.setOnChangeScaleNotifier() {
state?.initCanvas(desiredWidth, desiredHeight, contentScale, this.pixelGeometry) state?.initCanvas(desiredWidth, desiredHeight, contentScale, this.pixelGeometry)
......
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