Skip to content

Commit

Permalink
Remove input handling (#893)
Browse files Browse the repository at this point in the history
skiko is supposed to be a wrapper around skia, however it has unrelated
features like input. This PR removes it from this library - it's
supposed to be handled externally.

- Removed `SkikoInput`, `SkikoKey`, `SkikoPlatform*Event`
- Replaced `SkikoView` to `SkikoRenderDelegate` and related field in
`SkiaLayer`
- `SkiaLayer` on macOS native now receives `NSView` instead of creating
it internally and attaching it to the `NSWindow`. In theory, it allows
initializing non-full-window skia view there (not tested)
- Updated samples and readme
  • Loading branch information
MatkovIvan authored Apr 4, 2024
1 parent 4f22664 commit 1647328
Show file tree
Hide file tree
Showing 76 changed files with 401 additions and 3,764 deletions.
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ Simple example for Kotlin/JVM
```kotlin
fun main() {
val skiaLayer = SkiaLayer()
skiaLayer.skikoView = GenericSkikoView(skiaLayer, object : SkikoView {
skiaLayer.renderDelegate = SkiaLayerRenderDelegate(skiaLayer, object : SkikoRenderDelegate {
val paint = Paint().apply {
color = Color.RED
}
Expand Down Expand Up @@ -108,8 +108,7 @@ class SkikoAppDelegate : UIResponder, UIApplicationDelegateProtocol {
window!!.rootViewController = SkikoViewController(
SkikoUIView(
SkiaLayer().apply {
gesturesToListen = SkikoGestureEventKind.values()
skikoView = GenericSkikoView(skiaLayer, object : SkikoView {
renderDelegate = SkiaLayerRenderDelegate(skiaLayer, object : SkikoRenderDelegate {
val paint = Paint().apply { color = Color.RED }
override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) {
canvas.clear(Color.CYAN)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,32 @@
package org.jetbrains.skiko.sample

import org.jetbrains.skia.*
import android.view.View
import org.jetbrains.skia.Canvas
import org.jetbrains.skia.FontMgr
import org.jetbrains.skia.Paint
import org.jetbrains.skia.PaintMode
import org.jetbrains.skia.Rect
import org.jetbrains.skia.paragraph.FontCollection
import org.jetbrains.skia.paragraph.ParagraphBuilder
import org.jetbrains.skia.paragraph.ParagraphStyle
import org.jetbrains.skia.paragraph.TextStyle
import org.jetbrains.skiko.*
import org.jetbrains.skiko.FPSCounter
import org.jetbrains.skiko.OS
import org.jetbrains.skiko.SkiaLayer
import org.jetbrains.skiko.SkikoRenderDelegate
import org.jetbrains.skiko.currentSystemTheme
import org.jetbrains.skiko.hostOs
import kotlin.math.PI
import kotlin.math.cos
import kotlin.math.sin
import kotlin.math.PI

class Clocks(private val layer: SkiaLayer): SkikoView {
class Clocks(private val skiaLayer: SkiaLayer, view: View): SkikoRenderDelegate {
private val withFps = true
private val fpsCounter = FPSCounter()
private val platformYOffset = if (hostOs == OS.Ios) 50f else 5f
private var frame = 0
private var xpos = 0.0
private var ypos = 0.0
private var xpos = 0.0f
private var ypos = 0.0f
private var xOffset = 0.0
private var yOffset = 0.0
private var scale = 1.0
Expand All @@ -25,7 +35,14 @@ class Clocks(private val layer: SkiaLayer): SkikoView {
private val fontCollection = FontCollection()
.setDefaultFontManager(FontMgr.default)
private val style = ParagraphStyle()
private var inputText = ""

init {
view.setOnTouchListener { _, event ->
xpos = event.x / skiaLayer.contentScale
ypos = event.y / skiaLayer.contentScale
true
}
}

override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) {
if (withFps) fpsCounter.tick()
Expand Down Expand Up @@ -92,20 +109,12 @@ class Clocks(private val layer: SkiaLayer): SkikoView {

val renderInfo = ParagraphBuilder(style, fontCollection)
.pushStyle(TextStyle().setColor(0xFF000000.toInt()))
.addText("Graphics API: ${layer.renderApi} ✿゚ ${currentSystemTheme}${maybeFps}")
.addText("Graphics API: ${skiaLayer.renderApi} ✿゚ ${currentSystemTheme}${maybeFps}")
.popStyle()
.build()
renderInfo.layout(Float.POSITIVE_INFINITY)
renderInfo.paint(canvas, 5f, platformYOffset)

val input = ParagraphBuilder(style, fontCollection)
.pushStyle(TextStyle().setColor(0xFF000000.toInt()))
.addText("TextInput: $inputText")
.popStyle()
.build()
input.layout(Float.POSITIVE_INFINITY)
input.paint(canvas, 5f, platformYOffset + 20f)

val frames = ParagraphBuilder(style, fontCollection)
.pushStyle(TextStyle().setColor(0xff9BC730L.toInt()).setFontSize(20f))
.addText("Frames: ${frame++}\nAngle: $rotate")
Expand All @@ -116,116 +125,4 @@ class Clocks(private val layer: SkiaLayer): SkikoView {

canvas.resetMatrix()
}

private fun reset() {
xOffset = 0.0
yOffset = 0.0
rotate = 0.0
scale = 1.0
}

override fun onPointerEvent(event: SkikoPointerEvent) {
when (event.kind) {
SkikoPointerEventKind.DOWN,
SkikoPointerEventKind.MOVE -> {
xpos = event.x
ypos = event.y
}
SkikoPointerEventKind.DRAG -> {
xOffset += event.x - xpos
yOffset += event.y - ypos
xpos = event.x
ypos = event.y
}
SkikoPointerEventKind.SCROLL -> {
when (event.modifiers) {
SkikoInputModifiers.CONTROL -> {
rotate += if (event.deltaY < 0) -5.0 else 5.0
}
else -> {
if (event.y != 0.0) {
scale *= if (event.deltaY < 0) 0.9 else 1.1
}
}
}
}
else -> {}
}
}

override fun onInputEvent(event: SkikoInputEvent) {
if (event.input != "\b") {
inputText += event.input
}
}

override fun onKeyboardEvent(event: SkikoKeyboardEvent) {
if (event.kind == SkikoKeyboardEventKind.DOWN) {
when (event.key) {
SkikoKey.KEY_NUMPAD_ADD -> scale *= 1.1
SkikoKey.KEY_I -> {
if (event.modifiers == SkikoInputModifiers.SHIFT) {
scale *= 1.1
}
}
SkikoKey.KEY_NUMPAD_SUBTRACT -> scale *= 0.9
SkikoKey.KEY_O -> {
if (event.modifiers == SkikoInputModifiers.SHIFT) {
scale *= 0.9
}
}
SkikoKey.KEY_R -> {
if (event.modifiers == SkikoInputModifiers.SHIFT) {
rotate -= 5.0
}
}
SkikoKey.KEY_L -> {
if (event.modifiers == SkikoInputModifiers.SHIFT) {
rotate += 5.0
}
}
SkikoKey.KEY_NUMPAD_4,
SkikoKey.KEY_LEFT -> xOffset -= 5.0
SkikoKey.KEY_NUMPAD_8,
SkikoKey.KEY_UP -> yOffset -= 5.0
SkikoKey.KEY_NUMPAD_6,
SkikoKey.KEY_RIGHT -> xOffset += 5.0
SkikoKey.KEY_NUMPAD_2,
SkikoKey.KEY_DOWN -> yOffset += 5.0
SkikoKey.KEY_SPACE -> { reset() }
SkikoKey.KEY_BACKSPACE -> {
if (inputText.isNotEmpty()) {
inputText = inputText.dropLast(1)
}
}
else -> {}
}
}
}

override fun onGestureEvent(event: SkikoGestureEvent) {
when (event.kind) {
SkikoGestureEventKind.TAP -> {
xpos = event.x
ypos = event.y
}
SkikoGestureEventKind.DOUBLETAP -> { reset() }
SkikoGestureEventKind.PINCH -> {
if (event.state == SkikoGestureEventState.STARTED) {
k = scale
}
scale = k * event.scale
}
SkikoGestureEventKind.PAN -> {
xOffset += event.x - xpos
yOffset += event.y - ypos
xpos = event.x
ypos = event.y
}
SkikoGestureEventKind.ROTATION -> {
rotate = event.rotation * 180.0 / PI
}
else -> {}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ package org.jetbrains.skiko.sample

import android.app.Activity
import android.os.Bundle
import android.view.WindowManager
import android.widget.LinearLayout
import org.jetbrains.skiko.GenericSkikoView
import org.jetbrains.skiko.SkiaLayer
import org.jetbrains.skiko.SkikoGestureEventKind
import org.jetbrains.skiko.SkiaLayerRenderDelegate

class MainActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
Expand All @@ -21,10 +19,8 @@ class MainActivity : Activity() {
//layoutParams = ViewGroup.LayoutParams(1000, 1200)
}

val skiaLayer = SkiaLayer().apply {
gesturesToListen = SkikoGestureEventKind.values()
}
skiaLayer.skikoView = GenericSkikoView(skiaLayer, Clocks(skiaLayer))
val skiaLayer = SkiaLayer()
skiaLayer.renderDelegate = SkiaLayerRenderDelegate(skiaLayer, Clocks(skiaLayer, holder))
skiaLayer.attachTo(holder)
layout.addView(holder)

Expand Down

This file was deleted.

3 changes: 2 additions & 1 deletion samples/SkiaAwtSample/src/main/kotlin/SkiaAwtSample/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ fun createWindow(title: String, exitOnClose: Boolean) = SwingUtilities.invokeLat
println("Changed renderer for $layer: new value is ${layer.renderApi}")
}

skiaLayer.addView(GenericSkikoView(skiaLayer, clocks))
skiaLayer.renderDelegate = SkiaLayerRenderDelegate(skiaLayer, clocks)
skiaLayer.addMouseMotionListener(clocks)

// Window transparency
if (System.getProperty("skiko.transparency") == "true") {
Expand Down
28 changes: 9 additions & 19 deletions samples/SkiaAwtSample/src/main/kotlin/SkiaAwtSample/ClocksAwt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package SkiaAwtSample
import org.jetbrains.skia.*
import org.jetbrains.skia.paragraph.*
import org.jetbrains.skiko.*
import java.awt.event.MouseEvent
import java.awt.event.MouseMotionListener
import kotlin.math.PI
import kotlin.math.cos
import kotlin.math.sin

open class ClocksAwt(private val scaleProvider: () -> Float) : SkikoView {
open class ClocksAwt(private val scaleProvider: () -> Float) : SkikoRenderDelegate, MouseMotionListener {
constructor(layer: SkiaLayer) : this({ layer.contentScale })

private val typeface = Typeface.makeFromFile("fonts/JetBrainsMono-Regular.ttf")
Expand All @@ -22,8 +24,8 @@ open class ClocksAwt(private val scaleProvider: () -> Float) : SkikoView {
}

private var frame = 0
private var xpos = 0.0
private var ypos = 0.0
private var xpos = 0
private var ypos = 0
private val fontCollection = FontCollection()
.setDefaultFontManager(FontMgr.default)

Expand Down Expand Up @@ -108,23 +110,11 @@ open class ClocksAwt(private val scaleProvider: () -> Float) : SkikoView {
canvas.drawLine(left, top + rectH, left + rectW, top, Paint())
}

override fun onPointerEvent(event: SkikoPointerEvent) {
when (event.kind) {
SkikoPointerEventKind.DOWN,
SkikoPointerEventKind.MOVE -> {
xpos = event.x
ypos = event.y
}
else -> {}
}
// TODO: provide example that covers all features of pointer event
}

override fun onInputEvent(event: SkikoInputEvent) {
// TODO: provide example that covers all features of text input event
override fun mouseDragged(e: MouseEvent) {
}

override fun onKeyboardEvent(event: SkikoKeyboardEvent) {
// TODO: provide example that covers all features of keyboard event
override fun mouseMoved(e: MouseEvent) {
xpos = e.x
ypos = e.y
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ fun swingSkiaResize() = SwingUtilities.invokeLater {
}

skiaPanel = SkiaSwingPanel(skikoView)
skiaPanel.addMouseMotionListener(skikoView)

val leftPanel = JPanel().apply {
background = Color.CYAN
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package SkiaAwtSample

import org.jetbrains.skiko.GenericSkikoView
import org.jetbrains.skiko.SkiaLayerRenderDelegate
import java.awt.BorderLayout
import java.awt.Color
import java.awt.Dimension
Expand Down Expand Up @@ -85,7 +85,9 @@ fun swingSkia() = SwingUtilities.invokeLater {

private fun getSkiaPanel(): SkiaPanel {
return SkiaPanel().apply {
layer.addView(GenericSkikoView(layer, ClocksAwt(layer)))
val clocks = ClocksAwt(layer)
layer.renderDelegate = SkiaLayerRenderDelegate(layer, clocks)
layer.addMouseMotionListener(clocks)
val btnPanelOK = JPanel()
btnPanelOK.layout = BorderLayout(0, 0)
btnPanelOK.background = Color.white
Expand Down
6 changes: 3 additions & 3 deletions samples/SkiaJsSample/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -72,19 +72,19 @@ kotlin {
}
}

val jsWasmMain by creating {
val webMain by creating {
dependsOn(commonMain)
resources.setSrcDirs(resources.srcDirs)
resources.srcDirs(unzipTask.map { it.destinationDir })
}

val jsMain by getting {
dependsOn(jsWasmMain)
dependsOn(webMain)
}


val wasmJsMain by getting {
dependsOn(jsWasmMain)
dependsOn(webMain)
}
}
}
Expand Down
Loading

0 comments on commit 1647328

Please sign in to comment.