From 164732842ceedb0a8fc1c7a3c44c1c91273e110d Mon Sep 17 00:00:00 2001 From: Ivan Matkov Date: Thu, 4 Apr 2024 19:38:25 +0200 Subject: [PATCH] Remove input handling (#893) 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 --- README.md | 5 +- .../java/org/jetbrains/skiko/sample/Clocks.kt | 153 +---- .../jetbrains/skiko/sample/MainActivity.kt | 10 +- .../jetbrains/skiko/sample/RotatingSquare.kt | 36 -- .../src/main/kotlin/SkiaAwtSample/App.kt | 3 +- .../main/kotlin/SkiaAwtSample/ClocksAwt.kt | 28 +- .../SkiaAwtSample/ResizableSwingSkia.kt | 1 + .../main/kotlin/SkiaAwtSample/SwingSkia.kt | 6 +- samples/SkiaJsSample/build.gradle.kts | 6 +- .../org/jetbrains/skiko/sample/js/App.web.kt} | 8 +- .../skiko/sample/js/BouncingBalls.kt | 4 +- .../org/jetbrains/skiko/sample/js/Examples.kt | 0 .../resources/styles.css | 0 .../SkiaMultiplatformSample/build.gradle.kts | 9 +- .../org/jetbrains/skiko/sample/App.awt.kt | 4 +- .../org/jetbrains/skiko/sample/AwtClocks.kt | 43 +- .../jetbrains/skiko/sample/BouncingBalls.kt | 123 ---- .../org/jetbrains/skiko/sample/Clocks.kt | 158 +----- .../jetbrains/skiko/sample/RotatingSquare.kt | 30 - .../org/jetbrains/skiko/sample/App.ios.kt | 41 +- .../org/jetbrains/skiko/sample/IosClocks.kt | 33 +- .../org/jetbrains/skiko/sample/SwiftHelper.kt | 7 - .../skiko/sample/getSkikoViewContoller.kt | 37 -- .../org/jetbrains/skiko/sample/App.js.kt | 9 +- .../org/jetbrains/skiko/sample/JsClocks.js.kt | 3 - .../jetbrains/skiko/sample/JsClocks.jsWasm.kt | 24 - .../org/jetbrains/skiko/sample/App.macos.kt | 23 +- .../org/jetbrains/skiko/sample/MacosClocks.kt | 44 +- .../org/jetbrains/skiko/sample/App.wasm.kt | 9 +- .../jetbrains/skiko/sample/JsClocks.wasm.kt | 3 - .../jetbrains/skiko/sample/WebClocks.web.kt | 36 ++ .../resources/styles.css | 0 .../org/jetbrains/skiko/Convertors.android.kt | 150 ----- .../org/jetbrains/skiko/Renderer.android.kt | 28 +- .../org/jetbrains/skiko/SkiaLayer.android.kt | 48 +- .../skiko/SkikoGesturesDetector.android.kt | 281 --------- .../org/jetbrains/skiko/SkikoInput.android.kt | 5 - .../org/jetbrains/skiko/SkikoKey.android.kt | 119 ---- .../org/jetbrains/skiko/Convertors.jvm.kt | 170 ------ .../org/jetbrains/skiko/SkiaLayer.awt.kt | 73 +-- .../org/jetbrains/skiko/SkikoInput.awt.kt | 5 - .../org/jetbrains/skiko/SkikoKey.awt.kt | 118 ---- .../skiko/swing/Direct3DSwingRedrawer.kt | 6 +- .../skiko/swing/LinuxOpenGLSwingRedrawer.kt | 4 +- .../skiko/swing/MetalSwingRedrawer.kt | 6 +- .../jetbrains/skiko/swing/SkiaSwingLayer.kt | 10 +- .../skiko/swing/SoftwareSwingRedrawer.kt | 8 +- .../jetbrains/skiko/swing/SwingRedrawer.kt | 14 +- .../skiko/swing/SwingRedrawerBase.kt | 4 +- .../skiko/SkiaLayerPerformanceTest.kt | 2 +- .../org/jetbrains/skiko/SkiaLayerTest.kt | 42 +- .../kotlin/org/jetbrains/skiko/Events.kt | 241 -------- .../kotlin/org/jetbrains/skiko/SkiaLayer.kt | 6 +- .../org/jetbrains/skiko/SkikoInput.common.kt | 5 - .../org/jetbrains/skiko/SkikoKey.common.kt | 111 ---- .../jetbrains/skiko/SkikoRenderDelegate.kt | 20 + .../kotlin/org/jetbrains/skiko/SkikoView.kt | 58 +- .../org/jetbrains/skiko/Convertors.ios.kt | 67 --- .../org/jetbrains/skiko/SkiaLayer.ios.kt | 12 +- .../org/jetbrains/skiko/SkikoInput.ios.kt | 104 ---- .../org/jetbrains/skiko/SkikoKey.ios.kt | 129 ----- .../kotlin/org/jetbrains/skiko/SkikoUIView.kt | 533 +----------------- .../org/jetbrains/skiko/SkiaLayer.js.kt | 11 - .../kotlin/org/jetbrains/skiko/Convertors.kt | 55 -- .../org/jetbrains/skiko/SkiaLayer.js.kt | 12 +- .../org/jetbrains/skiko/SkikoInput.js.kt | 9 - .../kotlin/org/jetbrains/skiko/SkikoKey.js.kt | 115 ---- .../org/jetbrains/skiko/SkiaLayer.linux.kt | 8 +- .../org/jetbrains/skiko/SkikoInput.linux.kt | 5 - .../org/jetbrains/skiko/SkikoKey.linux.kt | 116 ---- .../org/jetbrains/skiko/Convertors.macos.kt | 219 ------- .../org/jetbrains/skiko/SkiaLayer.macos.kt | 209 ++----- .../org/jetbrains/skiko/SkikoInput.macos.kt | 5 - .../org/jetbrains/skiko/SkikoKey.macos.kt | 116 ---- .../{Resources.js.kt => Resources.wasmJs.kt} | 0 .../jetbrains/skiko/SkiaLayer.js.wasmJs.kt | 10 - 76 files changed, 401 insertions(+), 3764 deletions(-) delete mode 100644 samples/SkiaAndroidSample/src/main/java/org/jetbrains/skiko/sample/RotatingSquare.kt rename samples/SkiaJsSample/src/{jsWasmMain/kotlin/org/jetbrains/skiko/sample/js/App.jsWasm.kt => webMain/kotlin/org/jetbrains/skiko/sample/js/App.web.kt} (84%) rename samples/SkiaJsSample/src/{jsWasmMain => webMain}/kotlin/org/jetbrains/skiko/sample/js/BouncingBalls.kt (97%) rename samples/SkiaJsSample/src/{jsWasmMain => webMain}/kotlin/org/jetbrains/skiko/sample/js/Examples.kt (100%) rename samples/SkiaJsSample/src/{jsWasmMain => webMain}/resources/styles.css (100%) delete mode 100644 samples/SkiaMultiplatformSample/src/commonMain/kotlin/org/jetbrains/skiko/sample/BouncingBalls.kt delete mode 100644 samples/SkiaMultiplatformSample/src/commonMain/kotlin/org/jetbrains/skiko/sample/RotatingSquare.kt delete mode 100644 samples/SkiaMultiplatformSample/src/iosMain/kotlin/org/jetbrains/skiko/sample/SwiftHelper.kt delete mode 100644 samples/SkiaMultiplatformSample/src/iosMain/kotlin/org/jetbrains/skiko/sample/getSkikoViewContoller.kt delete mode 100644 samples/SkiaMultiplatformSample/src/jsMain/kotlin/org/jetbrains/skiko/sample/JsClocks.js.kt delete mode 100644 samples/SkiaMultiplatformSample/src/jsWasmMain/kotlin/org/jetbrains/skiko/sample/JsClocks.jsWasm.kt delete mode 100644 samples/SkiaMultiplatformSample/src/wasmJsMain/kotlin/org/jetbrains/skiko/sample/JsClocks.wasm.kt create mode 100644 samples/SkiaMultiplatformSample/src/webMain/kotlin/org/jetbrains/skiko/sample/WebClocks.web.kt rename samples/SkiaMultiplatformSample/src/{jsWasmMain => webMain}/resources/styles.css (100%) delete mode 100644 skiko/src/androidMain/kotlin/org/jetbrains/skiko/Convertors.android.kt delete mode 100644 skiko/src/androidMain/kotlin/org/jetbrains/skiko/SkikoGesturesDetector.android.kt delete mode 100644 skiko/src/androidMain/kotlin/org/jetbrains/skiko/SkikoInput.android.kt delete mode 100644 skiko/src/androidMain/kotlin/org/jetbrains/skiko/SkikoKey.android.kt delete mode 100644 skiko/src/awtMain/kotlin/org/jetbrains/skiko/SkikoInput.awt.kt delete mode 100644 skiko/src/awtMain/kotlin/org/jetbrains/skiko/SkikoKey.awt.kt delete mode 100644 skiko/src/commonMain/kotlin/org/jetbrains/skiko/Events.kt delete mode 100644 skiko/src/commonMain/kotlin/org/jetbrains/skiko/SkikoInput.common.kt delete mode 100644 skiko/src/commonMain/kotlin/org/jetbrains/skiko/SkikoKey.common.kt create mode 100644 skiko/src/commonMain/kotlin/org/jetbrains/skiko/SkikoRenderDelegate.kt delete mode 100644 skiko/src/iosMain/kotlin/org/jetbrains/skiko/Convertors.ios.kt delete mode 100644 skiko/src/iosMain/kotlin/org/jetbrains/skiko/SkikoInput.ios.kt delete mode 100644 skiko/src/iosMain/kotlin/org/jetbrains/skiko/SkikoKey.ios.kt delete mode 100644 skiko/src/jsMain/kotlin/org/jetbrains/skiko/SkiaLayer.js.kt delete mode 100644 skiko/src/jsWasmMain/kotlin/org/jetbrains/skiko/Convertors.kt delete mode 100644 skiko/src/jsWasmMain/kotlin/org/jetbrains/skiko/SkikoInput.js.kt delete mode 100644 skiko/src/jsWasmMain/kotlin/org/jetbrains/skiko/SkikoKey.js.kt delete mode 100644 skiko/src/linuxMain/kotlin/org/jetbrains/skiko/SkikoInput.linux.kt delete mode 100644 skiko/src/linuxMain/kotlin/org/jetbrains/skiko/SkikoKey.linux.kt delete mode 100644 skiko/src/macosMain/kotlin/org/jetbrains/skiko/Convertors.macos.kt delete mode 100644 skiko/src/macosMain/kotlin/org/jetbrains/skiko/SkikoInput.macos.kt delete mode 100644 skiko/src/macosMain/kotlin/org/jetbrains/skiko/SkikoKey.macos.kt rename skiko/src/wasmJsMain/kotlin/org/jetbrains/skiko/{Resources.js.kt => Resources.wasmJs.kt} (100%) delete mode 100644 skiko/src/wasmJsMain/kotlin/org/jetbrains/skiko/SkiaLayer.js.wasmJs.kt diff --git a/README.md b/README.md index bee1d28ce..b28dceab8 100644 --- a/README.md +++ b/README.md @@ -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 } @@ -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) diff --git a/samples/SkiaAndroidSample/src/main/java/org/jetbrains/skiko/sample/Clocks.kt b/samples/SkiaAndroidSample/src/main/java/org/jetbrains/skiko/sample/Clocks.kt index be3b8890b..c0d86259b 100644 --- a/samples/SkiaAndroidSample/src/main/java/org/jetbrains/skiko/sample/Clocks.kt +++ b/samples/SkiaAndroidSample/src/main/java/org/jetbrains/skiko/sample/Clocks.kt @@ -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 @@ -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() @@ -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") @@ -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 -> {} - } - } } \ No newline at end of file diff --git a/samples/SkiaAndroidSample/src/main/java/org/jetbrains/skiko/sample/MainActivity.kt b/samples/SkiaAndroidSample/src/main/java/org/jetbrains/skiko/sample/MainActivity.kt index 0e80219ec..5252eeab6 100644 --- a/samples/SkiaAndroidSample/src/main/java/org/jetbrains/skiko/sample/MainActivity.kt +++ b/samples/SkiaAndroidSample/src/main/java/org/jetbrains/skiko/sample/MainActivity.kt @@ -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?) { @@ -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) diff --git a/samples/SkiaAndroidSample/src/main/java/org/jetbrains/skiko/sample/RotatingSquare.kt b/samples/SkiaAndroidSample/src/main/java/org/jetbrains/skiko/sample/RotatingSquare.kt deleted file mode 100644 index 6746aba88..000000000 --- a/samples/SkiaAndroidSample/src/main/java/org/jetbrains/skiko/sample/RotatingSquare.kt +++ /dev/null @@ -1,36 +0,0 @@ -package org.jetbrains.skiko.sample - -import org.jetbrains.skia.Canvas -import org.jetbrains.skia.Color -import org.jetbrains.skia.Paint -import org.jetbrains.skia.Rect -import org.jetbrains.skiko.SkikoInputEvent -import org.jetbrains.skiko.SkikoKeyboardEvent -import org.jetbrains.skiko.SkikoPointerEvent -import org.jetbrains.skiko.SkikoView - -class RotatingSquare : SkikoView { - override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) { - val angleDeg = (nanoTime / 5_000_000) % 360 - val paint = Paint().apply { color = Color.GREEN } - canvas.clear(Color.RED) - canvas.save(); - canvas.translate(128.0f, 128.0f) - canvas.rotate(angleDeg.toFloat()) - val rect = Rect.makeXYWH(-90.5f, -90.5f, 181.0f, 181.0f) - canvas.drawRect(rect, paint) - canvas.restore() - } - - override fun onInputEvent(event: SkikoInputEvent) { - println("onInput: $event") - } - - override fun onKeyboardEvent(event: SkikoKeyboardEvent) { - println("onKeyboard: $event") - } - - override fun onPointerEvent(event: SkikoPointerEvent) { - println("onMouse: $event") - } -} diff --git a/samples/SkiaAwtSample/src/main/kotlin/SkiaAwtSample/App.kt b/samples/SkiaAwtSample/src/main/kotlin/SkiaAwtSample/App.kt index 9db156143..549cbaa14 100644 --- a/samples/SkiaAwtSample/src/main/kotlin/SkiaAwtSample/App.kt +++ b/samples/SkiaAwtSample/src/main/kotlin/SkiaAwtSample/App.kt @@ -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") { diff --git a/samples/SkiaAwtSample/src/main/kotlin/SkiaAwtSample/ClocksAwt.kt b/samples/SkiaAwtSample/src/main/kotlin/SkiaAwtSample/ClocksAwt.kt index bcf959013..3de988cb2 100644 --- a/samples/SkiaAwtSample/src/main/kotlin/SkiaAwtSample/ClocksAwt.kt +++ b/samples/SkiaAwtSample/src/main/kotlin/SkiaAwtSample/ClocksAwt.kt @@ -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") @@ -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) @@ -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 } } \ No newline at end of file diff --git a/samples/SkiaAwtSample/src/main/kotlin/SkiaAwtSample/ResizableSwingSkia.kt b/samples/SkiaAwtSample/src/main/kotlin/SkiaAwtSample/ResizableSwingSkia.kt index b449f7a9d..32a6d1dfa 100644 --- a/samples/SkiaAwtSample/src/main/kotlin/SkiaAwtSample/ResizableSwingSkia.kt +++ b/samples/SkiaAwtSample/src/main/kotlin/SkiaAwtSample/ResizableSwingSkia.kt @@ -23,6 +23,7 @@ fun swingSkiaResize() = SwingUtilities.invokeLater { } skiaPanel = SkiaSwingPanel(skikoView) + skiaPanel.addMouseMotionListener(skikoView) val leftPanel = JPanel().apply { background = Color.CYAN diff --git a/samples/SkiaAwtSample/src/main/kotlin/SkiaAwtSample/SwingSkia.kt b/samples/SkiaAwtSample/src/main/kotlin/SkiaAwtSample/SwingSkia.kt index cc1e26007..b01616f6e 100644 --- a/samples/SkiaAwtSample/src/main/kotlin/SkiaAwtSample/SwingSkia.kt +++ b/samples/SkiaAwtSample/src/main/kotlin/SkiaAwtSample/SwingSkia.kt @@ -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 @@ -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 diff --git a/samples/SkiaJsSample/build.gradle.kts b/samples/SkiaJsSample/build.gradle.kts index 94f41638a..9ff33528d 100644 --- a/samples/SkiaJsSample/build.gradle.kts +++ b/samples/SkiaJsSample/build.gradle.kts @@ -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) } } } diff --git a/samples/SkiaJsSample/src/jsWasmMain/kotlin/org/jetbrains/skiko/sample/js/App.jsWasm.kt b/samples/SkiaJsSample/src/webMain/kotlin/org/jetbrains/skiko/sample/js/App.web.kt similarity index 84% rename from samples/SkiaJsSample/src/jsWasmMain/kotlin/org/jetbrains/skiko/sample/js/App.jsWasm.kt rename to samples/SkiaJsSample/src/webMain/kotlin/org/jetbrains/skiko/sample/js/App.web.kt index 82a8d34ef..5420252f5 100644 --- a/samples/SkiaJsSample/src/jsWasmMain/kotlin/org/jetbrains/skiko/sample/js/App.jsWasm.kt +++ b/samples/SkiaJsSample/src/webMain/kotlin/org/jetbrains/skiko/sample/js/App.web.kt @@ -3,11 +3,11 @@ package org.jetbrains.skiko.sample.js import org.jetbrains.skia.Canvas import org.jetbrains.skia.Paint import org.jetbrains.skia.Rect -import org.jetbrains.skiko.GenericSkikoView import org.jetbrains.skiko.SkiaLayer -import org.jetbrains.skiko.SkikoView +import org.jetbrains.skiko.SkiaLayerRenderDelegate +import org.jetbrains.skiko.SkikoRenderDelegate -private class DemoApp: SkikoView { +private class DemoApp: SkikoRenderDelegate { private val paint = Paint() override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) { @@ -29,7 +29,7 @@ internal fun runApp() { } else { BouncingBalls() } - skiaLayer.skikoView = GenericSkikoView(skiaLayer, app) + skiaLayer.renderDelegate = SkiaLayerRenderDelegate(skiaLayer, app) skiaLayer.attachTo(canvas) skiaLayer.needRedraw() } diff --git a/samples/SkiaJsSample/src/jsWasmMain/kotlin/org/jetbrains/skiko/sample/js/BouncingBalls.kt b/samples/SkiaJsSample/src/webMain/kotlin/org/jetbrains/skiko/sample/js/BouncingBalls.kt similarity index 97% rename from samples/SkiaJsSample/src/jsWasmMain/kotlin/org/jetbrains/skiko/sample/js/BouncingBalls.kt rename to samples/SkiaJsSample/src/webMain/kotlin/org/jetbrains/skiko/sample/js/BouncingBalls.kt index 51e7a2f1c..b79cd457c 100644 --- a/samples/SkiaJsSample/src/jsWasmMain/kotlin/org/jetbrains/skiko/sample/js/BouncingBalls.kt +++ b/samples/SkiaJsSample/src/webMain/kotlin/org/jetbrains/skiko/sample/js/BouncingBalls.kt @@ -4,12 +4,12 @@ import org.jetbrains.skia.Canvas import org.jetbrains.skia.Color4f import org.jetbrains.skia.Paint import org.jetbrains.skia.PaintMode -import org.jetbrains.skiko.SkikoView +import org.jetbrains.skiko.SkikoRenderDelegate import kotlin.math.PI import kotlin.math.cos import kotlin.math.sin -class BouncingBalls: SkikoView { +class BouncingBalls: SkikoRenderDelegate { private data class Circle(var x: Float, var y: Float, var r: Float) companion object { diff --git a/samples/SkiaJsSample/src/jsWasmMain/kotlin/org/jetbrains/skiko/sample/js/Examples.kt b/samples/SkiaJsSample/src/webMain/kotlin/org/jetbrains/skiko/sample/js/Examples.kt similarity index 100% rename from samples/SkiaJsSample/src/jsWasmMain/kotlin/org/jetbrains/skiko/sample/js/Examples.kt rename to samples/SkiaJsSample/src/webMain/kotlin/org/jetbrains/skiko/sample/js/Examples.kt diff --git a/samples/SkiaJsSample/src/jsWasmMain/resources/styles.css b/samples/SkiaJsSample/src/webMain/resources/styles.css similarity index 100% rename from samples/SkiaJsSample/src/jsWasmMain/resources/styles.css rename to samples/SkiaJsSample/src/webMain/resources/styles.css diff --git a/samples/SkiaMultiplatformSample/build.gradle.kts b/samples/SkiaMultiplatformSample/build.gradle.kts index 8b019e7c2..d62297bd2 100644 --- a/samples/SkiaMultiplatformSample/build.gradle.kts +++ b/samples/SkiaMultiplatformSample/build.gradle.kts @@ -21,9 +21,8 @@ plugins { repositories { google() mavenCentral() + mavenLocal() maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") - - // mavenLocal() } val osName = System.getProperty("os.name") @@ -137,18 +136,18 @@ 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) } val darwinMain by creating { diff --git a/samples/SkiaMultiplatformSample/src/awtMain/kotlin/org/jetbrains/skiko/sample/App.awt.kt b/samples/SkiaMultiplatformSample/src/awtMain/kotlin/org/jetbrains/skiko/sample/App.awt.kt index 3107ace20..e523c6967 100644 --- a/samples/SkiaMultiplatformSample/src/awtMain/kotlin/org/jetbrains/skiko/sample/App.awt.kt +++ b/samples/SkiaMultiplatformSample/src/awtMain/kotlin/org/jetbrains/skiko/sample/App.awt.kt @@ -1,13 +1,13 @@ package org.jetbrains.skiko.sample import org.jetbrains.skiko.* - import java.awt.Dimension import javax.swing.* fun main() { val skiaLayer = SkiaLayer() - skiaLayer.addView(GenericSkikoView(skiaLayer, AwtClocks(skiaLayer))) + val clocks = AwtClocks(skiaLayer) + skiaLayer.renderDelegate = SkiaLayerRenderDelegate(skiaLayer, clocks) SwingUtilities.invokeLater { val window = JFrame("Skiko example").apply { defaultCloseOperation = WindowConstants.EXIT_ON_CLOSE diff --git a/samples/SkiaMultiplatformSample/src/awtMain/kotlin/org/jetbrains/skiko/sample/AwtClocks.kt b/samples/SkiaMultiplatformSample/src/awtMain/kotlin/org/jetbrains/skiko/sample/AwtClocks.kt index 497fc84d7..9ad6237ad 100644 --- a/samples/SkiaMultiplatformSample/src/awtMain/kotlin/org/jetbrains/skiko/sample/AwtClocks.kt +++ b/samples/SkiaMultiplatformSample/src/awtMain/kotlin/org/jetbrains/skiko/sample/AwtClocks.kt @@ -1,21 +1,42 @@ package org.jetbrains.skiko.sample +import org.jetbrains.skiko.CursorManager +import org.jetbrains.skiko.PredefinedCursors import org.jetbrains.skiko.SkiaLayer -import org.jetbrains.skiko.SkikoInputEvent +import java.awt.event.MouseEvent +import java.awt.event.MouseMotionListener +import java.awt.event.MouseWheelEvent +import java.awt.event.MouseWheelListener -class AwtClocks(layer: SkiaLayer) : Clocks(layer) { - override var inputText: String = "Hello, AwtClocks" +class AwtClocks(private val layer: SkiaLayer) : Clocks(layer.renderApi), MouseMotionListener, MouseWheelListener { + private val cursorManager = CursorManager() - override fun handleBackspace() { - if (inputText.isNotEmpty()) { - inputText = inputText.dropLast(1) - } + init { + layer.addMouseMotionListener(this) + } + + override fun mouseDragged(event: MouseEvent) { + xOffset += event.x - xpos + yOffset += event.y - ypos + xpos = event.x.toDouble() + ypos = event.y.toDouble() } - override fun onInputEvent(event: SkikoInputEvent) { - if (event.input != "\b") { - inputText += event.input + override fun mouseMoved(event: MouseEvent) { + if (event.x > 200) { + cursorManager.setCursor(layer.component, PredefinedCursors.HAND) + } else { + cursorManager.setCursor(layer.component, PredefinedCursors.DEFAULT) } + xpos = event.x.toDouble() + ypos = event.y.toDouble() } -} \ No newline at end of file + override fun mouseWheelMoved(event: MouseWheelEvent) { + if (event.isControlDown) { + rotate += if (event.wheelRotation < 0) -5.0 else 5.0 + } else { + scale *= if (event.wheelRotation < 0) 0.9 else 1.1 + } + } +} diff --git a/samples/SkiaMultiplatformSample/src/commonMain/kotlin/org/jetbrains/skiko/sample/BouncingBalls.kt b/samples/SkiaMultiplatformSample/src/commonMain/kotlin/org/jetbrains/skiko/sample/BouncingBalls.kt deleted file mode 100644 index 9b763744d..000000000 --- a/samples/SkiaMultiplatformSample/src/commonMain/kotlin/org/jetbrains/skiko/sample/BouncingBalls.kt +++ /dev/null @@ -1,123 +0,0 @@ -package org.jetbrains.skiko.sample - -import org.jetbrains.skia.* -import org.jetbrains.skiko.* -import kotlin.math.PI -import kotlin.math.cos -import kotlin.math.sin - -class BouncingBalls(private val withFps: Boolean = false): SkikoView { - private data class Circle(var x: Float, var y: Float, var r: Float) - - private val fpsCounter = FPSCounter(2.0, true) - - companion object { - private fun moveCircle(c: Circle, s: Float, angle: Float, width: Int, height: Int, r: Float) { - c.x = (c.x + s * sin(angle)).coerceAtLeast(r).coerceAtMost(width.toFloat() - r) - c.y = (c.y + s * cos(angle)).coerceAtLeast(r).coerceAtMost(height.toFloat() - r) - } - - private fun calculatePosition(circle: Circle, boundingWidth: Int, boundingHeight: Int): Position { - val southmost = circle.y + circle.r - val northmost = circle.y - circle.r - val westmost = circle.x - circle.r - val eastmost = circle.x + circle.r - - return when { - southmost >= boundingHeight -> Position.TOUCHES_SOUTH - northmost <= 0 -> Position.TOUCHES_NORTH - eastmost >= boundingWidth -> Position.TOUCHES_EAST - westmost <= 0 -> Position.TOUCHES_WEST - else -> Position.INSIDE - } - } - } - - private enum class Position { - INSIDE, - TOUCHES_SOUTH, - TOUCHES_NORTH, - TOUCHES_WEST, - TOUCHES_EAST - } - - - private class BouncingBall( - val circle: Circle, - val velocity: Float, - var angle: Double - ) { - fun recalculate(width: Int, height: Int, dt: Float) { - val position = calculatePosition(circle, width, height) - - val dtMillis = dt / 1000000 - - when (position) { - Position.TOUCHES_SOUTH -> angle = PI - angle - Position.TOUCHES_EAST -> angle = -angle - Position.TOUCHES_WEST -> angle = -angle - Position.TOUCHES_NORTH -> angle = PI - angle - Position.INSIDE -> angle - } - - moveCircle(circle, velocity * (dtMillis.coerceAtMost(500f) / 1000), angle.toFloat(), width, height, circle.r) - } - } - - private var prevTimestamp: Long = 0L - - private fun Color4f.asPaint() = Paint().apply { - color4f = this@asPaint - mode = PaintMode.FILL - isAntiAlias = true - } - - private val data = listOf( - BouncingBall(Circle(200f, 50f, 25f), 172f, PI / 4), - BouncingBall(Circle(100f, 100f, 10f), 162f, -PI / 3), - BouncingBall(Circle(150f, 120f, 30f), 168f, 3 * PI / 4), - BouncingBall(Circle(100f, 10f, 25f), 208f, -PI / 6), - BouncingBall(Circle(120f, 100f, 40f), 120f, -1.1 * PI) - ).zip(listOf( - Color4f(0f, 1f, 0f, 0.8f).asPaint(), - Color4f(0f, 0f, 1f, 0.8f).asPaint(), - Color4f(1f, 0f, 0f, 0.8f).asPaint(), - Color4f(1f, 0f, 1f, 0.8f).asPaint(), - Color4f(0f, 1f, 1f, 0.8f).asPaint() - )).toMutableList() - - override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) { - if (withFps) fpsCounter.tick() - - canvas.clear(-1) - val dtime = (nanoTime - prevTimestamp) - prevTimestamp = nanoTime - - data.forEach { (ball, paint) -> - ball.recalculate(width, height, dtime.toFloat()) - canvas.drawCircle(ball.circle.x, ball.circle.y, ball.circle.r, paint) - } - } - - override fun onInputEvent(event: SkikoInputEvent) { - println("onInput: $event") - } - - override fun onKeyboardEvent(event: SkikoKeyboardEvent) { - println("onKeyboard: $event") - } - - override fun onPointerEvent(event: SkikoPointerEvent) { - if (event.isLeftClick) { - val paint = Color4f(1f, 0f, 0f, 0.8f).asPaint() - data += BouncingBall( - Circle(event.x.toFloat(), event.y.toFloat(), 25f), 172f, PI / 4) to paint - } - if (event.isRightClick && data.size > 0) { - data.removeLast() - } - // To avoid log spamming - if (event.kind != SkikoPointerEventKind.MOVE) - println("onMouse: $event") - } -} \ No newline at end of file diff --git a/samples/SkiaMultiplatformSample/src/commonMain/kotlin/org/jetbrains/skiko/sample/Clocks.kt b/samples/SkiaMultiplatformSample/src/commonMain/kotlin/org/jetbrains/skiko/sample/Clocks.kt index 9ebbb00d3..83158a027 100644 --- a/samples/SkiaMultiplatformSample/src/commonMain/kotlin/org/jetbrains/skiko/sample/Clocks.kt +++ b/samples/SkiaMultiplatformSample/src/commonMain/kotlin/org/jetbrains/skiko/sample/Clocks.kt @@ -1,35 +1,42 @@ package org.jetbrains.skiko.sample -import org.jetbrains.skia.* +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.GraphicsApi +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 -abstract class Clocks(private val layer: SkiaLayer): SkikoView { - private val cursorManager = CursorManager() +abstract class Clocks(private val renderApi: GraphicsApi): 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 xOffset = 0.0 - private var yOffset = 0.0 - private var scale = 1.0 - private var k = scale - private var rotate = 0.0 + + var xpos = 0.0 + var ypos = 0.0 + var xOffset = 0.0 + var yOffset = 0.0 + var scale = 1.0 + var rotate = 0.0 + private val fontCollection = FontCollection() .setDefaultFontManager(FontMgr.default) private val style = ParagraphStyle() - abstract val inputText:String - abstract fun handleBackspace() - override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) { if (withFps) fpsCounter.tick() canvas.translate(xOffset.toFloat(), yOffset.toFloat()) @@ -95,20 +102,12 @@ abstract 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: $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") @@ -119,113 +118,4 @@ abstract 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 -> { - if (event.x > 200) { - cursorManager.setCursor(layer.component, PredefinedCursors.HAND) - } else { - cursorManager.setCursor(layer.component, PredefinedCursors.DEFAULT) - } - 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 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 -> { - handleBackspace() - } - 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 -> {} - } - } -} \ No newline at end of file +} diff --git a/samples/SkiaMultiplatformSample/src/commonMain/kotlin/org/jetbrains/skiko/sample/RotatingSquare.kt b/samples/SkiaMultiplatformSample/src/commonMain/kotlin/org/jetbrains/skiko/sample/RotatingSquare.kt deleted file mode 100644 index d6cc9c25a..000000000 --- a/samples/SkiaMultiplatformSample/src/commonMain/kotlin/org/jetbrains/skiko/sample/RotatingSquare.kt +++ /dev/null @@ -1,30 +0,0 @@ -package org.jetbrains.skiko.sample - -import org.jetbrains.skia.* -import org.jetbrains.skiko.* - -class RotatingSquare : SkikoView { - override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) { - val angleDeg = (nanoTime / 5_000_000) % 360 - val paint = Paint().apply { color = Color.GREEN } - canvas.clear(Color.RED) - canvas.save(); - canvas.translate(128.0f, 128.0f) - canvas.rotate(angleDeg.toFloat()) - val rect = Rect.makeXYWH(-90.5f, -90.5f, 181.0f, 181.0f) - canvas.drawRect(rect, paint) - canvas.restore() - } - - override fun onInputEvent(event: SkikoInputEvent) { - println("onInput: $event") - } - - override fun onKeyboardEvent(event: SkikoKeyboardEvent) { - println("onKeyboard: $event") - } - - override fun onPointerEvent(event: SkikoPointerEvent) { - println("onMouse: $event") - } -} \ No newline at end of file diff --git a/samples/SkiaMultiplatformSample/src/iosMain/kotlin/org/jetbrains/skiko/sample/App.ios.kt b/samples/SkiaMultiplatformSample/src/iosMain/kotlin/org/jetbrains/skiko/sample/App.ios.kt index 2239bbf0d..c374d2d61 100644 --- a/samples/SkiaMultiplatformSample/src/iosMain/kotlin/org/jetbrains/skiko/sample/App.ios.kt +++ b/samples/SkiaMultiplatformSample/src/iosMain/kotlin/org/jetbrains/skiko/sample/App.ios.kt @@ -1,9 +1,23 @@ // Use `xcodegen` first, then `open ./SkikoSample.xcodeproj` and then Run button in XCode. package org.jetbrains.skiko.sample -import kotlinx.cinterop.* -import platform.UIKit.* -import platform.Foundation.* +import kotlinx.cinterop.autoreleasepool +import kotlinx.cinterop.cstr +import kotlinx.cinterop.memScoped +import kotlinx.cinterop.toCValues +import org.jetbrains.skiko.SkiaLayer +import org.jetbrains.skiko.SkiaLayerRenderDelegate +import platform.Foundation.NSStringFromClass +import platform.UIKit.UIApplication +import platform.UIKit.UIApplicationDelegateProtocol +import platform.UIKit.UIApplicationDelegateProtocolMeta +import platform.UIKit.UIApplicationMain +import platform.UIKit.UIResponder +import platform.UIKit.UIResponderMeta +import platform.UIKit.UIScreen +import platform.UIKit.UIWindow +import platform.darwin.dispatch_async +import platform.darwin.dispatch_get_main_queue fun main() { val args = emptyArray() @@ -19,7 +33,7 @@ fun main() { class SkikoAppDelegate : UIResponder, UIApplicationDelegateProtocol { companion object : UIResponderMeta(), UIApplicationDelegateProtocolMeta - @ObjCObjectBase.OverrideInit + @OverrideInit constructor() : super() private var _window: UIWindow? = null @@ -27,11 +41,22 @@ class SkikoAppDelegate : UIResponder, UIApplicationDelegateProtocol { override fun setWindow(window: UIWindow?) { _window = window } + + override fun application( + application: UIApplication, + didFinishLaunchingWithOptions: Map? + ): Boolean { + val skiaLayer = SkiaLayer() + val clocks = IosClocks(skiaLayer) + skiaLayer.renderDelegate = SkiaLayerRenderDelegate(skiaLayer, clocks) + dispatch_async(dispatch_get_main_queue()) { + skiaLayer.needRedraw() + } - override fun application(application: UIApplication, didFinishLaunchingWithOptions: Map?): Boolean { - window = UIWindow(frame = UIScreen.mainScreen.bounds) - window!!.rootViewController = getSkikoViewContoller() - window!!.makeKeyAndVisible() + window = UIWindow(frame = UIScreen.mainScreen.bounds).also { + it.rootViewController = clocks.viewController + it.makeKeyAndVisible() + } return true } } diff --git a/samples/SkiaMultiplatformSample/src/iosMain/kotlin/org/jetbrains/skiko/sample/IosClocks.kt b/samples/SkiaMultiplatformSample/src/iosMain/kotlin/org/jetbrains/skiko/sample/IosClocks.kt index 30b45dd83..1b280929c 100644 --- a/samples/SkiaMultiplatformSample/src/iosMain/kotlin/org/jetbrains/skiko/sample/IosClocks.kt +++ b/samples/SkiaMultiplatformSample/src/iosMain/kotlin/org/jetbrains/skiko/sample/IosClocks.kt @@ -2,24 +2,21 @@ package org.jetbrains.skiko.sample import org.jetbrains.skiko.SkiaLayer import org.jetbrains.skiko.SkikoUIView -import org.jetbrains.skiko.SkikoInput +import platform.UIKit.NSLayoutConstraint +import platform.UIKit.UIViewController -class IosClocks(layer: SkiaLayer) : Clocks(layer) { - override var inputText: String = "Hello, IosClocks" - - override fun handleBackspace() { - if (inputText.isNotEmpty()) { - inputText = inputText.dropLast(1) - } - } - - override val input: SkikoInput = object : SkikoInput by SkikoInput.Empty { - override fun insertText(text: String) { - inputText += text - } - - override fun deleteBackward() { - handleBackspace() - } +class IosClocks(skiaLayer: SkiaLayer) : Clocks(skiaLayer.renderApi) { + val viewController: UIViewController + init { + val view = SkikoUIView(skiaLayer) + view.translatesAutoresizingMaskIntoConstraints = false + viewController = UIViewController() + viewController.view.addSubview(view) + NSLayoutConstraint.activateConstraints(listOf( + view.topAnchor.constraintEqualToAnchor(viewController.view.topAnchor), + view.bottomAnchor.constraintEqualToAnchor(viewController.view.bottomAnchor), + view.leadingAnchor.constraintEqualToAnchor(viewController.view.leadingAnchor), + view.trailingAnchor.constraintEqualToAnchor(viewController.view.trailingAnchor) + )) } } diff --git a/samples/SkiaMultiplatformSample/src/iosMain/kotlin/org/jetbrains/skiko/sample/SwiftHelper.kt b/samples/SkiaMultiplatformSample/src/iosMain/kotlin/org/jetbrains/skiko/sample/SwiftHelper.kt deleted file mode 100644 index 91270d465..000000000 --- a/samples/SkiaMultiplatformSample/src/iosMain/kotlin/org/jetbrains/skiko/sample/SwiftHelper.kt +++ /dev/null @@ -1,7 +0,0 @@ -package org.jetbrains.skiko.sample - -import org.jetbrains.skiko.SkiaLayer - -class SwiftHelper { - fun getViewController() = getSkikoViewContoller() -} diff --git a/samples/SkiaMultiplatformSample/src/iosMain/kotlin/org/jetbrains/skiko/sample/getSkikoViewContoller.kt b/samples/SkiaMultiplatformSample/src/iosMain/kotlin/org/jetbrains/skiko/sample/getSkikoViewContoller.kt deleted file mode 100644 index 69e18b1ea..000000000 --- a/samples/SkiaMultiplatformSample/src/iosMain/kotlin/org/jetbrains/skiko/sample/getSkikoViewContoller.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.jetbrains.skiko.sample - -import kotlinx.cinterop.* -import org.jetbrains.skiko.* -import org.jetbrains.skiko.sample.* -import platform.Foundation.* -import platform.UIKit.* -import platform.darwin.dispatch_async -import platform.darwin.dispatch_get_main_queue - -fun makeApp(skiaLayer: SkiaLayer) = IosClocks(skiaLayer) - -fun getSkikoViewContoller(): UIViewController { - val view = SkikoUIView( - SkiaLayer().apply { - skikoView = GenericSkikoView(this, makeApp(this)) - - dispatch_async(dispatch_get_main_queue()) { - needRedraw() - } - } - ) - - view.translatesAutoresizingMaskIntoConstraints = false - - val viewController = UIViewController() - viewController.view.addSubview(view) - - NSLayoutConstraint.activateConstraints(listOf( - view.topAnchor.constraintEqualToAnchor(viewController.view.topAnchor), - view.bottomAnchor.constraintEqualToAnchor(viewController.view.bottomAnchor), - view.leadingAnchor.constraintEqualToAnchor(viewController.view.leadingAnchor), - view.trailingAnchor.constraintEqualToAnchor(viewController.view.trailingAnchor) - )) - - return viewController -} diff --git a/samples/SkiaMultiplatformSample/src/jsMain/kotlin/org/jetbrains/skiko/sample/App.js.kt b/samples/SkiaMultiplatformSample/src/jsMain/kotlin/org/jetbrains/skiko/sample/App.js.kt index 3d17b15db..b038b1f3d 100644 --- a/samples/SkiaMultiplatformSample/src/jsMain/kotlin/org/jetbrains/skiko/sample/App.js.kt +++ b/samples/SkiaMultiplatformSample/src/jsMain/kotlin/org/jetbrains/skiko/sample/App.js.kt @@ -2,8 +2,8 @@ package org.jetbrains.skiko.sample import kotlinx.browser.document import kotlinx.browser.window -import org.jetbrains.skiko.GenericSkikoView import org.jetbrains.skiko.SkiaLayer +import org.jetbrains.skiko.SkiaLayerRenderDelegate import org.jetbrains.skiko.wasm.onWasmReady import org.w3c.dom.HTMLCanvasElement @@ -14,11 +14,10 @@ fun main() { } internal fun runApp() { - val skiaLayer = SkiaLayer() - val game = JsClocks(skiaLayer) - skiaLayer.skikoView = GenericSkikoView(skiaLayer, game) val canvas = document.getElementById("SkikoTarget") as HTMLCanvasElement canvas.setAttribute("tabindex", "0") - skiaLayer.attachTo(canvas) + val skiaLayer = SkiaLayer() + val clocks = WebClocks(skiaLayer, canvas) + skiaLayer.renderDelegate = SkiaLayerRenderDelegate(skiaLayer, clocks) skiaLayer.needRedraw() } diff --git a/samples/SkiaMultiplatformSample/src/jsMain/kotlin/org/jetbrains/skiko/sample/JsClocks.js.kt b/samples/SkiaMultiplatformSample/src/jsMain/kotlin/org/jetbrains/skiko/sample/JsClocks.js.kt deleted file mode 100644 index a15d749e8..000000000 --- a/samples/SkiaMultiplatformSample/src/jsMain/kotlin/org/jetbrains/skiko/sample/JsClocks.js.kt +++ /dev/null @@ -1,3 +0,0 @@ -package org.jetbrains.skiko.sample - -actual val greetings: String = "Hello, JsClocks" \ No newline at end of file diff --git a/samples/SkiaMultiplatformSample/src/jsWasmMain/kotlin/org/jetbrains/skiko/sample/JsClocks.jsWasm.kt b/samples/SkiaMultiplatformSample/src/jsWasmMain/kotlin/org/jetbrains/skiko/sample/JsClocks.jsWasm.kt deleted file mode 100644 index 98182aea2..000000000 --- a/samples/SkiaMultiplatformSample/src/jsWasmMain/kotlin/org/jetbrains/skiko/sample/JsClocks.jsWasm.kt +++ /dev/null @@ -1,24 +0,0 @@ -package org.jetbrains.skiko.sample - -import org.jetbrains.skiko.SkiaLayer -import org.jetbrains.skiko.SkikoInput -import org.jetbrains.skiko.SkikoInputEvent - -expect val greetings: String - -class JsClocks(layer: SkiaLayer) : Clocks(layer) { - override var inputText: String = greetings - - override fun handleBackspace() { - if (inputText.isNotEmpty()) { - inputText = inputText.dropLast(1) - } - } - - override val input: SkikoInput = object : SkikoInput { - override fun onInputEvent(event: SkikoInputEvent) { - inputText += event.input - } - } - -} diff --git a/samples/SkiaMultiplatformSample/src/macosMain/kotlin/org/jetbrains/skiko/sample/App.macos.kt b/samples/SkiaMultiplatformSample/src/macosMain/kotlin/org/jetbrains/skiko/sample/App.macos.kt index 3980979fb..b6d361e7d 100644 --- a/samples/SkiaMultiplatformSample/src/macosMain/kotlin/org/jetbrains/skiko/sample/App.macos.kt +++ b/samples/SkiaMultiplatformSample/src/macosMain/kotlin/org/jetbrains/skiko/sample/App.macos.kt @@ -1,14 +1,21 @@ package org.jetbrains.skiko.sample -import platform.AppKit.* - -import org.jetbrains.skiko.* +import org.jetbrains.skiko.SkiaLayer +import org.jetbrains.skiko.SkiaLayerRenderDelegate +import platform.AppKit.NSApplication +import platform.AppKit.NSApplicationActivationPolicy +import platform.AppKit.NSApplicationDelegateProtocol +import platform.AppKit.NSBackingStoreBuffered +import platform.AppKit.NSMenu +import platform.AppKit.NSWindow +import platform.AppKit.NSWindowStyleMaskClosable +import platform.AppKit.NSWindowStyleMaskMiniaturizable +import platform.AppKit.NSWindowStyleMaskResizable +import platform.AppKit.NSWindowStyleMaskTitled import platform.Foundation.NSMakeRect import platform.Foundation.NSSelectorFromString import platform.darwin.NSObject -fun makeApp(skiaLayer: SkiaLayer) = MacosClocks(skiaLayer) - fun main() { val app = NSApplication.sharedApplication() app.setActivationPolicy(NSApplicationActivationPolicy.NSApplicationActivationPolicyRegular) @@ -30,7 +37,7 @@ fun main() { NSWindowStyleMaskMiniaturizable or NSWindowStyleMaskClosable or NSWindowStyleMaskResizable - val window = object: NSWindow( + val window = object : NSWindow( contentRect = NSMakeRect(0.0, 0.0, 640.0, 480.0), styleMask = windowStyle, backing = NSBackingStoreBuffered, @@ -40,8 +47,8 @@ fun main() { override fun canBecomeMainWindow() = true } val skiaLayer = SkiaLayer() - skiaLayer.skikoView = GenericSkikoView(skiaLayer, makeApp(skiaLayer)) - skiaLayer.attachTo(window) + val clocks = MacosClocks(skiaLayer, window) + skiaLayer.renderDelegate = SkiaLayerRenderDelegate(skiaLayer, clocks) window.makeKeyAndOrderFront(app) app.run() } diff --git a/samples/SkiaMultiplatformSample/src/macosMain/kotlin/org/jetbrains/skiko/sample/MacosClocks.kt b/samples/SkiaMultiplatformSample/src/macosMain/kotlin/org/jetbrains/skiko/sample/MacosClocks.kt index 75d6346ed..746d799d4 100644 --- a/samples/SkiaMultiplatformSample/src/macosMain/kotlin/org/jetbrains/skiko/sample/MacosClocks.kt +++ b/samples/SkiaMultiplatformSample/src/macosMain/kotlin/org/jetbrains/skiko/sample/MacosClocks.kt @@ -1,18 +1,44 @@ package org.jetbrains.skiko.sample +import kotlinx.cinterop.useContents import org.jetbrains.skiko.SkiaLayer -import org.jetbrains.skiko.SkikoInputEvent +import platform.AppKit.NSEvent +import platform.AppKit.NSTrackingActiveInActiveApp +import platform.AppKit.NSTrackingArea +import platform.AppKit.NSTrackingMouseMoved +import platform.AppKit.NSView +import platform.AppKit.NSViewHeightSizable +import platform.AppKit.NSViewWidthSizable +import platform.AppKit.NSWindow -class MacosClocks(layer: SkiaLayer): Clocks(layer) { - override var inputText: String = "" +class MacosClocks(skiaLayer: SkiaLayer, window: NSWindow) : Clocks(skiaLayer.renderApi) { + init { + val nsView = object : NSView(window.frame) { + private var trackingArea : NSTrackingArea? = null - override fun handleBackspace() { - if (inputText.isNotEmpty()) { - inputText = inputText.dropLast(1) + override fun updateTrackingAreas() { + trackingArea?.let { removeTrackingArea(it) } + trackingArea = NSTrackingArea( + rect = bounds, + options = NSTrackingActiveInActiveApp or NSTrackingMouseMoved, + owner = this, + userInfo = null + ) + addTrackingArea(trackingArea!!) + } + + override fun mouseMoved(event: NSEvent) { + val height = frame.useContents { size.height } + event.locationInWindow.useContents { + xpos = x + ypos = height - y + } + } } - } - override fun onInputEvent(event: SkikoInputEvent) { - inputText += event.input + val contentView = window.contentView!! + nsView.autoresizingMask = NSViewHeightSizable or NSViewWidthSizable + contentView.addSubview(nsView) + skiaLayer.attachTo(nsView) } } diff --git a/samples/SkiaMultiplatformSample/src/wasmJsMain/kotlin/org/jetbrains/skiko/sample/App.wasm.kt b/samples/SkiaMultiplatformSample/src/wasmJsMain/kotlin/org/jetbrains/skiko/sample/App.wasm.kt index 542df34d3..5ac2cd2cb 100644 --- a/samples/SkiaMultiplatformSample/src/wasmJsMain/kotlin/org/jetbrains/skiko/sample/App.wasm.kt +++ b/samples/SkiaMultiplatformSample/src/wasmJsMain/kotlin/org/jetbrains/skiko/sample/App.wasm.kt @@ -1,8 +1,8 @@ package org.jetbrains.skiko.sample import kotlinx.browser.document -import org.jetbrains.skiko.GenericSkikoView import org.jetbrains.skiko.SkiaLayer +import org.jetbrains.skiko.SkiaLayerRenderDelegate import org.w3c.dom.HTMLCanvasElement fun main() { @@ -10,11 +10,10 @@ fun main() { } internal fun runApp() { - val skiaLayer = SkiaLayer() - val game = JsClocks(skiaLayer) - skiaLayer.skikoView = GenericSkikoView(skiaLayer, game) val canvas = document.getElementById("SkikoTarget") as HTMLCanvasElement canvas.setAttribute("tabindex", "0") - skiaLayer.attachTo(canvas) + val skiaLayer = SkiaLayer() + val clocks = WebClocks(skiaLayer, canvas) + skiaLayer.renderDelegate = SkiaLayerRenderDelegate(skiaLayer, clocks) skiaLayer.needRedraw() } diff --git a/samples/SkiaMultiplatformSample/src/wasmJsMain/kotlin/org/jetbrains/skiko/sample/JsClocks.wasm.kt b/samples/SkiaMultiplatformSample/src/wasmJsMain/kotlin/org/jetbrains/skiko/sample/JsClocks.wasm.kt deleted file mode 100644 index beea616d9..000000000 --- a/samples/SkiaMultiplatformSample/src/wasmJsMain/kotlin/org/jetbrains/skiko/sample/JsClocks.wasm.kt +++ /dev/null @@ -1,3 +0,0 @@ -package org.jetbrains.skiko.sample - -actual val greetings: String = "Hello, WasmClocks" \ No newline at end of file diff --git a/samples/SkiaMultiplatformSample/src/webMain/kotlin/org/jetbrains/skiko/sample/WebClocks.web.kt b/samples/SkiaMultiplatformSample/src/webMain/kotlin/org/jetbrains/skiko/sample/WebClocks.web.kt new file mode 100644 index 000000000..742ddadaa --- /dev/null +++ b/samples/SkiaMultiplatformSample/src/webMain/kotlin/org/jetbrains/skiko/sample/WebClocks.web.kt @@ -0,0 +1,36 @@ +package org.jetbrains.skiko.sample + +import kotlinx.browser.window +import org.jetbrains.skiko.SkiaLayer +import org.w3c.dom.HTMLCanvasElement +import org.w3c.dom.TouchEvent +import org.w3c.dom.events.Event +import org.w3c.dom.events.MouseEvent +import org.w3c.dom.get + +class WebClocks(skiaLayer: SkiaLayer, canvas: HTMLCanvasElement) : Clocks(skiaLayer.renderApi) { + init { + val scale = window.devicePixelRatio.toFloat() + val bounds = canvas.getBoundingClientRect() + canvas.addTypedEvent("touchmove") { event -> + event.preventDefault() + event.touches[0]?.let { + xpos = (it.clientX - bounds.left) / scale + ypos = (it.clientY - bounds.top) / scale + } + } + canvas.addTypedEvent("mousemove") { event -> + xpos = event.offsetX / scale + ypos = event.offsetY / scale + } + skiaLayer.attachTo(canvas) + } +} + +@Suppress("UNCHECKED_CAST") +private fun HTMLCanvasElement.addTypedEvent( + type: String, + handler: (event: T) -> Unit +) { + this.addEventListener(type, { event -> handler(event as T) }) +} diff --git a/samples/SkiaMultiplatformSample/src/jsWasmMain/resources/styles.css b/samples/SkiaMultiplatformSample/src/webMain/resources/styles.css similarity index 100% rename from samples/SkiaMultiplatformSample/src/jsWasmMain/resources/styles.css rename to samples/SkiaMultiplatformSample/src/webMain/resources/styles.css diff --git a/skiko/src/androidMain/kotlin/org/jetbrains/skiko/Convertors.android.kt b/skiko/src/androidMain/kotlin/org/jetbrains/skiko/Convertors.android.kt deleted file mode 100644 index adff99950..000000000 --- a/skiko/src/androidMain/kotlin/org/jetbrains/skiko/Convertors.android.kt +++ /dev/null @@ -1,150 +0,0 @@ -package org.jetbrains.skiko - -import android.view.MotionEvent -import android.view.KeyEvent -import kotlin.math.abs - -fun toSkikoKeyboardEvent( - event: KeyEvent, - keyCode: Int, - kind: SkikoKeyboardEventKind -): SkikoKeyboardEvent { - return SkikoKeyboardEvent( - key = SkikoKey.valueOf(keyCode), - modifiers = toSkikoModifiers(event), - kind = kind, - timestamp = event.eventTime, - platform = event - ) -} - -fun toSkikoTypeEvent( - event: KeyEvent, - keyCode: Int -): SkikoInputEvent { - return SkikoInputEvent( - input = event.unicodeChar.toChar().toString(), - key = SkikoKey.valueOf(keyCode), - modifiers = toSkikoModifiers(event), - SkikoKeyboardEventKind.TYPE, - platform = event - ) -} - -private fun toSkikoModifiers(event: KeyEvent): SkikoInputModifiers { - var result = 0 - if (event.isAltPressed) { - result = result.or(SkikoInputModifiers.ALT.value) - } - if (event.isShiftPressed) { - result = result.or(SkikoInputModifiers.SHIFT.value) - } - if (event.isCtrlPressed) { - result = result.or(SkikoInputModifiers.CONTROL.value) - } - if (event.isMetaPressed) { - result = result.or(SkikoInputModifiers.META.value) - } - return SkikoInputModifiers(result) -} - -fun toSkikoPointerEvent(event: MotionEvent, density: Float): SkikoPointerEvent { - val upIndex = when (event.action) { - MotionEvent.ACTION_UP -> 0 - MotionEvent.ACTION_POINTER_UP -> event.actionIndex - else -> -1 - } - - val pointers = (0 until event.pointerCount).map { - SkikoPointer( - x = event.getX(it).toDouble() / density, - y = event.getY(it).toDouble() / density, - // Same as in Jetpack Compose for Android - // https://github.com/androidx/androidx/blob/58597f0eba31b89f57b6605b7ed4977cd48ed38d/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/pointer/MotionEventAdapter.android.kt#L126 - // (Mouse isn't supported for Android yet, so hover cannot be checked) - pressed = it != upIndex, - device = SkikoPointerDevice.TOUCH, - id = event.getPointerId(it).toLong(), - pressure = event.getPressure(it).toDouble() - ) - } - - return SkikoPointerEvent( - x = pointers.centroidX, - y = pointers.centroidY, - kind = toSkikoPointerEventKind(event), - timestamp = event.eventTime, - pointers = pointers, - platform = event - ) -} - -fun toSkikoScaleGestureEvent( - event: MotionEvent, - scale: Double, - state: SkikoGestureEventState, - density: Float -): SkikoGestureEvent { - return SkikoGestureEvent( - x = (event.x / density).toDouble(), - y = (event.y / density).toDouble(), - scale = scale, - kind = SkikoGestureEventKind.PINCH, - state = state, - platform = event - ) -} - -private val swipeThreshold = 100 -private val swipeVelocityThreshold = 100 - -internal fun toSkikoGestureDirection( - event1: MotionEvent?, - event2: MotionEvent, - velocityX: Float, - velocityY: Float -): SkikoGestureEventDirection { - if (event1 == null) { - return SkikoGestureEventDirection.UNKNOWN - } - - val dx = event2.x - event1.x - val dy = event2.y - event1.y - if (abs(dx) > abs(dy)) { - if (abs(dx) > swipeThreshold && abs(velocityX) > swipeVelocityThreshold) { - if (dx > 0) { - return SkikoGestureEventDirection.RIGHT - } else { - return SkikoGestureEventDirection.LEFT - } - } - } else { - if (abs(dy) > swipeThreshold && abs(velocityY) > swipeVelocityThreshold) { - if (dy > 0) { - return SkikoGestureEventDirection.DOWN - } else { - return SkikoGestureEventDirection.UP - } - } - } - return SkikoGestureEventDirection.UNKNOWN -} - -internal fun toSkikoPointerEventKind(event: MotionEvent): SkikoPointerEventKind { - return when (event.action) { - MotionEvent.ACTION_POINTER_DOWN, - MotionEvent.ACTION_DOWN -> SkikoPointerEventKind.DOWN - MotionEvent.ACTION_POINTER_UP, - MotionEvent.ACTION_UP -> SkikoPointerEventKind.UP - MotionEvent.ACTION_MOVE -> SkikoPointerEventKind.MOVE - else -> SkikoPointerEventKind.UNKNOWN - } -} - -private fun toSkikoGestureEventKind(event: MotionEvent): SkikoGestureEventKind { - return when (event.action) { - MotionEvent.ACTION_UP -> SkikoGestureEventKind.TAP - MotionEvent.ACTION_MOVE -> SkikoGestureEventKind.PAN - else -> SkikoGestureEventKind.UNKNOWN - } -} \ No newline at end of file diff --git a/skiko/src/androidMain/kotlin/org/jetbrains/skiko/Renderer.android.kt b/skiko/src/androidMain/kotlin/org/jetbrains/skiko/Renderer.android.kt index abd96d3c3..8740f30c0 100644 --- a/skiko/src/androidMain/kotlin/org/jetbrains/skiko/Renderer.android.kt +++ b/skiko/src/androidMain/kotlin/org/jetbrains/skiko/Renderer.android.kt @@ -43,32 +43,6 @@ class SkikoSurfaceView(context: Context, val layer: SkiaLayer) : GLSurfaceView(c fun scheduleFrame() { frameDispatcher.scheduleFrame() } - - internal val gesturesDetector = SkikoGesturesDetector(context, layer) - - override fun onTouchEvent(event: MotionEvent): Boolean { - layer.skikoView?.onPointerEvent(toSkikoPointerEvent(event, layer.contentScale)) - return true - } - - override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { - layer.skikoView?.onKeyboardEvent( - toSkikoKeyboardEvent(event, keyCode, SkikoKeyboardEventKind.DOWN) - ) - if (event.unicodeChar != 0) { - layer.skikoView?.onInputEvent( - toSkikoTypeEvent(event, keyCode) - ) - } - return true - } - - override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean { - layer.skikoView?.onKeyboardEvent( - toSkikoKeyboardEvent(event, keyCode, SkikoKeyboardEventKind.UP) - ) - return true - } } private class SkikoSurfaceRender(private val layer: SkiaLayer, private val manager: FrameManager) : GLSurfaceView.Renderer { @@ -93,7 +67,7 @@ private class SkikoSurfaceRender(private val layer: SkiaLayer, private val manag // This method is called from the main thread. fun update() { - layer.skikoView?.let { + layer.renderDelegate?.let { val bounds = Rect.makeWH(width.toFloat(), width.toFloat()) val canvas = pictureRecorder.beginRecording(bounds) try { diff --git a/skiko/src/androidMain/kotlin/org/jetbrains/skiko/SkiaLayer.android.kt b/skiko/src/androidMain/kotlin/org/jetbrains/skiko/SkiaLayer.android.kt index 5c76bdec8..19bea2be5 100644 --- a/skiko/src/androidMain/kotlin/org/jetbrains/skiko/SkiaLayer.android.kt +++ b/skiko/src/androidMain/kotlin/org/jetbrains/skiko/SkiaLayer.android.kt @@ -2,34 +2,10 @@ package org.jetbrains.skiko import android.content.Context import android.view.* -import android.view.inputmethod.InputMethodManager import org.jetbrains.skia.Canvas import org.jetbrains.skia.PixelGeometry -actual typealias SkikoGesturePlatformEvent = MotionEvent -actual typealias SkikoPlatformPointerEvent = MotionEvent -actual typealias SkikoPlatformInputEvent = KeyEvent -actual typealias SkikoPlatformKeyboardEvent = KeyEvent - actual open class SkiaLayer { - - var gesturesToListen: Array? = null - set(value) { - field = value - initGestures() - } - - private fun initGestures() { - glView?.let { view -> - view.gesturesDetector.setGesturesToListen(gesturesToListen) - if (gesturesToListen != null) { - view.setOnTouchListener { _, event -> - view.gesturesDetector.onTouchEvent(event) - } - } - } - } - private var glView: SkikoSurfaceView? = null private var container: ViewGroup? = null @@ -49,7 +25,7 @@ actual open class SkiaLayer { if (value) throw IllegalArgumentException("transparency unsupported") } - actual var skikoView: SkikoView? = null + actual var renderDelegate: SkikoRenderDelegate? = null actual fun attachTo(container: Any) { when (container) { @@ -60,27 +36,6 @@ actual open class SkiaLayer { } } - private var _isKeyboardVisible = false - - fun showScreenKeyboard() { - if (glView != null) { - val imm = glView!!.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager - imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0) - _isKeyboardVisible = true - } - } - - fun hideScreenKeyboard() { - if (glView != null) { - val imm = glView!!.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager - imm.hideSoftInputFromWindow(glView!!.windowToken, 0) - _isKeyboardVisible = false - } - } - - fun isScreenKeyboardOpen() = _isKeyboardVisible - - fun attachTo(container: ViewGroup) { initDefaultContext(container.context) @@ -89,7 +44,6 @@ actual open class SkiaLayer { this.container = container this.glView = view - initGestures() view.setFocusableInTouchMode(true) diff --git a/skiko/src/androidMain/kotlin/org/jetbrains/skiko/SkikoGesturesDetector.android.kt b/skiko/src/androidMain/kotlin/org/jetbrains/skiko/SkikoGesturesDetector.android.kt deleted file mode 100644 index 263294715..000000000 --- a/skiko/src/androidMain/kotlin/org/jetbrains/skiko/SkikoGesturesDetector.android.kt +++ /dev/null @@ -1,281 +0,0 @@ -package org.jetbrains.skiko - -import android.content.Context -import android.view.MotionEvent -import android.view.GestureDetector -import android.view.GestureDetector.SimpleOnGestureListener -import android.view.ScaleGestureDetector -import android.view.ScaleGestureDetector.SimpleOnScaleGestureListener -import org.jetbrains.skia.toRadians - -internal class SkikoGesturesDetector( - private val context: Context, - private val layer: SkiaLayer -) { - private var gesturesToListen: Array? = null - fun setGesturesToListen(gestures: Array?) { - gesturesToListen = gestures - } - - private fun containsGesture( - gesture: SkikoGestureEventKind - ): Boolean { - gesturesToListen?.let { list -> - return list.contains(gesture) - } - return false - } - - fun onTouchEvent(event: MotionEvent): Boolean { - if (containsGesture(SkikoGestureEventKind.PINCH)) { - scaleGesture.onTouchEvent(event) - } - if (containsGesture(SkikoGestureEventKind.ROTATION)) { - rotationGesture.onTouchEvent(event) - } - return simpleGestures.onTouchEvent(event) - } - - private val simpleGestures = GestureDetector(context, object: WorkaroundSimpleOnGestureListener() { - override fun onSingleTapUp(event: MotionEvent): Boolean { - if (!containsGesture(SkikoGestureEventKind.TAP)) return false - val density = layer.contentScale - layer.skikoView?.onGestureEvent( - SkikoGestureEvent( - x = (event.x / density).toDouble(), - y = (event.y / density).toDouble(), - kind = SkikoGestureEventKind.TAP, - platform = event - ) - ) - return true - } - - override fun onDoubleTap(event: MotionEvent): Boolean { - if (!containsGesture(SkikoGestureEventKind.DOUBLETAP)) return false - val density = layer.contentScale - layer.skikoView?.onGestureEvent( - SkikoGestureEvent( - x = (event.x / density).toDouble(), - y = (event.y / density).toDouble(), - kind = SkikoGestureEventKind.DOUBLETAP, - platform = event - ) - ) - return true - } - - override fun onLongPress(event: MotionEvent) { - if (!containsGesture(SkikoGestureEventKind.LONGPRESS)) return - val density = layer.contentScale - layer.skikoView?.onGestureEvent( - SkikoGestureEvent( - x = (event.x / density).toDouble(), - y = (event.y / density).toDouble(), - kind = SkikoGestureEventKind.LONGPRESS, - platform = event - ) - ) - } - - override fun onScrollWorkaround( - event1: MotionEvent?, - event2: MotionEvent, - distanceX: Float, - distanceY: Float, - ): Boolean { - if (!containsGesture(SkikoGestureEventKind.PAN)) return false - val density = layer.contentScale - layer.skikoView?.onGestureEvent( - SkikoGestureEvent( - x = (event2.x / density).toDouble(), - y = (event2.y / density).toDouble(), - kind = SkikoGestureEventKind.PAN, - platform = event2 - ) - ) - return true - } - - override fun onFlingWorkaround( - event1: MotionEvent?, - event2: MotionEvent, - velocityX: Float, - velocityY: Float - ): Boolean { - if (!containsGesture(SkikoGestureEventKind.SWIPE)) return false - var direction = toSkikoGestureDirection(event1, event2, velocityX, velocityY) - if (direction == SkikoGestureEventDirection.UNKNOWN) { - return false - } - val density = layer.contentScale - layer.skikoView?.onGestureEvent( - SkikoGestureEvent( - x = (event2.x / density).toDouble(), - y = (event2.y / density).toDouble(), - direction = direction, - kind = SkikoGestureEventKind.SWIPE, - platform = event2 - ) - ) - return true - } - }) - - private val scaleGesture = SkikoScaleGestureDetector(context, SkikoScaleGestureListener(layer)) - - private class SkikoScaleGestureDetector( - context: Context, - private val scaleListener: SkikoScaleGestureListener - ) : ScaleGestureDetector(context, scaleListener) { - override fun onTouchEvent(event: MotionEvent): Boolean { - scaleListener.event = event - return super.onTouchEvent(event) - } - } - - private class SkikoScaleGestureListener(val layer: SkiaLayer) : SimpleOnScaleGestureListener() { - var event: MotionEvent? = null - var scale: Double = 1.0 - - override fun onScaleBegin(detector: ScaleGestureDetector): Boolean { - if (event != null) { - scale *= detector.scaleFactor.toDouble() - layer.skikoView?.onGestureEvent( - toSkikoScaleGestureEvent( - event = event!!, - scale = scale, - state = SkikoGestureEventState.STARTED, - layer.contentScale - ) - ) - return true - } - return false - } - - override fun onScale(detector: ScaleGestureDetector): Boolean { - if (event != null) { - scale *= detector.scaleFactor.toDouble() - layer.skikoView?.onGestureEvent( - toSkikoScaleGestureEvent( - event = event!!, - scale = scale, - state = SkikoGestureEventState.CHANGED, - layer.contentScale - ) - ) - return true - } - return false - } - - override fun onScaleEnd(detector: ScaleGestureDetector) { - if (event != null) { - scale *= detector.scaleFactor.toDouble() - layer.skikoView?.onGestureEvent( - toSkikoScaleGestureEvent( - event = event!!, - scale = scale, - state = SkikoGestureEventState.ENDED, - layer.contentScale - ) - ) - } - scale = 1.0 - } - } - - private val rotationGesture = SkikoRotationGestureDetector(SkikoRotationGestureListener(layer)) - - private class SkikoRotationGestureListener(val layer: SkiaLayer) { - var event: MotionEvent? = null - fun onRotation(detector: SkikoRotationGestureDetector) { - if (event != null) { - val density = layer.contentScale - layer.skikoView?.onGestureEvent( - SkikoGestureEvent( - x = (event!!.x / density).toDouble(), - y = (event!!.y / density).toDouble(), - rotation = detector.angle, - kind = SkikoGestureEventKind.ROTATION, - state = SkikoGestureEventState.CHANGED, - platform = event - ) - ) - } - } - } - - private class SkikoRotationGestureDetector( - private val rotationListener: SkikoRotationGestureListener - ) { - private var fX = 0f - private var fY = 0f - private var sX = 0f - private var sY = 0f - private var ptrID1: Int - private var ptrID2: Int - var angle = 0.0 - private set - - companion object { - private const val INVALID_POINTER_ID = -1 - } - - init { - ptrID1 = INVALID_POINTER_ID - ptrID2 = INVALID_POINTER_ID - } - - fun onTouchEvent(event: MotionEvent): Boolean { - rotationListener.event = event - when (event.actionMasked) { - MotionEvent.ACTION_DOWN -> ptrID1 = event.getPointerId(event.actionIndex) - MotionEvent.ACTION_POINTER_DOWN -> { - ptrID2 = event.getPointerId(event.actionIndex) - sX = event.getX(event.findPointerIndex(ptrID1)) - sY = event.getY(event.findPointerIndex(ptrID1)) - fX = event.getX(event.findPointerIndex(ptrID2)) - fY = event.getY(event.findPointerIndex(ptrID2)) - } - MotionEvent.ACTION_MOVE -> if (ptrID1 != INVALID_POINTER_ID && ptrID2 != INVALID_POINTER_ID) { - val nfX: Float - val nfY: Float - val nsX: Float - val nsY: Float - nsX = event.getX(event.findPointerIndex(ptrID1)) - nsY = event.getY(event.findPointerIndex(ptrID1)) - nfX = event.getX(event.findPointerIndex(ptrID2)) - nfY = event.getY(event.findPointerIndex(ptrID2)) - angle = angleBetweenLines(fX, fY, sX, sY, nfX, nfY, nsX, nsY) - rotationListener.onRotation(this) - } - MotionEvent.ACTION_UP -> ptrID1 = INVALID_POINTER_ID - MotionEvent.ACTION_POINTER_UP -> ptrID2 = INVALID_POINTER_ID - MotionEvent.ACTION_CANCEL -> { - ptrID1 = INVALID_POINTER_ID - ptrID2 = INVALID_POINTER_ID - } - } - return true - } - - private fun angleBetweenLines( - fX: Float, - fY: Float, - sX: Float, - sY: Float, - nfX: Float, - nfY: Float, - nsX: Float, - nsY: Float - ): Double { - val angle1 = Math.atan2((fY - sY).toDouble(), (fX - sX).toDouble()) - val angle2 = Math.atan2((nfY - nsY).toDouble(), (nfX - nsX).toDouble()) - return (Math.toDegrees(angle2 - angle1) % 360).toFloat().toRadians() - } - } -} - -typealias MotionEventNullableOrNo = MotionEvent? \ No newline at end of file diff --git a/skiko/src/androidMain/kotlin/org/jetbrains/skiko/SkikoInput.android.kt b/skiko/src/androidMain/kotlin/org/jetbrains/skiko/SkikoInput.android.kt deleted file mode 100644 index c6b5331d3..000000000 --- a/skiko/src/androidMain/kotlin/org/jetbrains/skiko/SkikoInput.android.kt +++ /dev/null @@ -1,5 +0,0 @@ -package org.jetbrains.skiko - -actual interface SkikoInput { - actual object Empty : SkikoInput -} diff --git a/skiko/src/androidMain/kotlin/org/jetbrains/skiko/SkikoKey.android.kt b/skiko/src/androidMain/kotlin/org/jetbrains/skiko/SkikoKey.android.kt deleted file mode 100644 index 92770703a..000000000 --- a/skiko/src/androidMain/kotlin/org/jetbrains/skiko/SkikoKey.android.kt +++ /dev/null @@ -1,119 +0,0 @@ -package org.jetbrains.skiko - -import android.view.KeyEvent.* - -// See https://developer.android.com/reference/android/view/KeyEvent -actual enum class SkikoKey(actual val platformKeyCode: Int) { - KEY_UNKNOWN(KEYCODE_UNKNOWN), - KEY_A(KEYCODE_A), - KEY_S(KEYCODE_S), - KEY_D(KEYCODE_D), - KEY_F(KEYCODE_F), - KEY_H(KEYCODE_H), - KEY_G(KEYCODE_G), - KEY_Z(KEYCODE_Z), - KEY_X(KEYCODE_X), - KEY_C(KEYCODE_C), - KEY_V(KEYCODE_V), - KEY_B(KEYCODE_B), - KEY_Q(KEYCODE_Q), - KEY_W(KEYCODE_W), - KEY_E(KEYCODE_E), - KEY_R(KEYCODE_R), - KEY_Y(KEYCODE_Y), - KEY_T(KEYCODE_T), - KEY_U(KEYCODE_U), - KEY_I(KEYCODE_I), - KEY_P(KEYCODE_P), - KEY_L(KEYCODE_L), - KEY_J(KEYCODE_J), - KEY_K(KEYCODE_K), - KEY_N(KEYCODE_N), - KEY_M(KEYCODE_M), - KEY_O(KEYCODE_O), - KEY_1(KEYCODE_1), - KEY_2(KEYCODE_2), - KEY_3(KEYCODE_3), - KEY_4(KEYCODE_4), - KEY_5(KEYCODE_5), - KEY_6(KEYCODE_6), - KEY_7(KEYCODE_7), - KEY_8(KEYCODE_8), - KEY_9(KEYCODE_9), - KEY_0(KEYCODE_0), - KEY_CLOSE_BRACKET(KEYCODE_RIGHT_BRACKET), - KEY_OPEN_BRACKET(KEYCODE_LEFT_BRACKET), - KEY_QUOTE(KEYCODE_UNKNOWN), - KEY_SEMICOLON(KEYCODE_SEMICOLON), - KEY_SLASH(KEYCODE_SLASH), - KEY_COMMA(KEYCODE_COMMA), - KEY_BACKSLASH(KEYCODE_BACKSLASH), - KEY_PERIOD(KEYCODE_PERIOD), - KEY_BACK_QUOTE(KEYCODE_UNKNOWN), - KEY_EQUALS(KEYCODE_EQUALS), - KEY_MINUS(KEYCODE_MINUS), - KEY_ENTER(KEYCODE_ENTER), - KEY_ESCAPE(KEYCODE_ESCAPE), - KEY_TAB(KEYCODE_TAB), - KEY_BACKSPACE(KEYCODE_DEL), - KEY_SPACE(KEYCODE_SPACE), - KEY_CAPSLOCK(KEYCODE_CAPS_LOCK), - KEY_LEFT_META(KEYCODE_META_LEFT), - KEY_LEFT_SHIFT(KEYCODE_SHIFT_LEFT), - KEY_LEFT_ALT(KEYCODE_ALT_LEFT), - KEY_LEFT_CONTROL(KEYCODE_CTRL_LEFT), - KEY_RIGHT_META(KEYCODE_META_RIGHT), - KEY_RIGHT_SHIFT(KEYCODE_SHIFT_RIGHT), - KEY_RIGHT_ALT(KEYCODE_ALT_RIGHT), - KEY_RIGHT_CONTROL(KEYCODE_CTRL_RIGHT), - KEY_MENU(KEYCODE_UNKNOWN), - KEY_UP(KEYCODE_DPAD_UP), - KEY_DOWN(KEYCODE_DPAD_DOWN), - KEY_LEFT(KEYCODE_DPAD_LEFT), - KEY_RIGHT(KEYCODE_DPAD_RIGHT), - KEY_F1(KEYCODE_F1), - KEY_F2(KEYCODE_F2), - KEY_F3(KEYCODE_F3), - KEY_F4(KEYCODE_F4), - KEY_F5(KEYCODE_F5), - KEY_F6(KEYCODE_F6), - KEY_F7(KEYCODE_F7), - KEY_F8(KEYCODE_F8), - KEY_F9(KEYCODE_F9), - KEY_F10(KEYCODE_F10), - KEY_F11(KEYCODE_F11), - KEY_F12(KEYCODE_F12), - KEY_PRINTSCEEN(KEYCODE_UNKNOWN), - KEY_SCROLL_LOCK(KEYCODE_UNKNOWN), - KEY_PAUSE(KEYCODE_UNKNOWN), - KEY_INSERT(KEYCODE_INSERT), - KEY_HOME(KEYCODE_HOME), - KEY_PGUP(KEYCODE_PAGE_UP), - KEY_DELETE(KEYCODE_FORWARD_DEL), - KEY_END(KEYCODE_MOVE_END), - KEY_PGDOWN(KEYCODE_PAGE_DOWN), - KEY_NUM_LOCK(KEYCODE_UNKNOWN), - KEY_NUMPAD_0(KEYCODE_NUMPAD_0), - KEY_NUMPAD_1(KEYCODE_NUMPAD_1), - KEY_NUMPAD_2(KEYCODE_NUMPAD_2), - KEY_NUMPAD_3(KEYCODE_NUMPAD_3), - KEY_NUMPAD_4(KEYCODE_NUMPAD_4), - KEY_NUMPAD_5(KEYCODE_NUMPAD_5), - KEY_NUMPAD_6(KEYCODE_NUMPAD_6), - KEY_NUMPAD_7(KEYCODE_NUMPAD_7), - KEY_NUMPAD_8(KEYCODE_NUMPAD_8), - KEY_NUMPAD_9(KEYCODE_NUMPAD_9), - KEY_NUMPAD_ENTER(KEYCODE_NUMPAD_ENTER), - KEY_NUMPAD_ADD(KEYCODE_NUMPAD_ADD), - KEY_NUMPAD_SUBTRACT(KEYCODE_NUMPAD_SUBTRACT), - KEY_NUMPAD_MULTIPLY(KEYCODE_NUMPAD_MULTIPLY), - KEY_NUMPAD_DIVIDE(KEYCODE_NUMPAD_DIVIDE), - KEY_NUMPAD_DECIMAL(KEYCODE_UNKNOWN); - - companion object { - fun valueOf(platformKeyCode: Int): SkikoKey { - val key = SkikoKey.values().firstOrNull { it.platformKeyCode == platformKeyCode } - return key ?: SkikoKey.KEY_UNKNOWN - } - } -} \ No newline at end of file diff --git a/skiko/src/awtMain/kotlin/org/jetbrains/skiko/Convertors.jvm.kt b/skiko/src/awtMain/kotlin/org/jetbrains/skiko/Convertors.jvm.kt index 0e76d656b..25bea40b6 100644 --- a/skiko/src/awtMain/kotlin/org/jetbrains/skiko/Convertors.jvm.kt +++ b/skiko/src/awtMain/kotlin/org/jetbrains/skiko/Convertors.jvm.kt @@ -78,173 +78,3 @@ fun BufferedImage.toBitmap(): Bitmap { fun BufferedImage.toImage(): Image { return Image.makeFromBitmap(toBitmap()) } - -private val MouseEventButton4 get() = 4 -private val MouseEventButton5 get() = 5 - -fun toSkikoEvent(event: MouseEvent): SkikoPointerEvent { - return SkikoPointerEvent( - x = event.x.toDouble(), - y = event.y.toDouble(), - pressedButtons = toSkikoPressedMouseButtons(event), - button = toSkikoMouseButton(event), - modifiers = toSkikoModifiers(event.modifiersEx), - kind = when (event.id) { - MouseEvent.MOUSE_PRESSED -> SkikoPointerEventKind.DOWN - MouseEvent.MOUSE_RELEASED -> SkikoPointerEventKind.UP - MouseEvent.MOUSE_DRAGGED -> SkikoPointerEventKind.DRAG - MouseEvent.MOUSE_MOVED -> SkikoPointerEventKind.MOVE - MouseEvent.MOUSE_ENTERED -> SkikoPointerEventKind.ENTER - MouseEvent.MOUSE_EXITED -> SkikoPointerEventKind.EXIT - else -> SkikoPointerEventKind.UNKNOWN - }, - timestamp = event.`when`, - platform = event - ) -} - -fun toSkikoEvent(event: MouseWheelEvent): SkikoPointerEvent { - val scrollAmount = event.preciseWheelRotation - val modifiers = toSkikoModifiers(event.modifiersEx) - val isShiftPressed = modifiers.has(SkikoInputModifiers.SHIFT) - val deltaX = if (isShiftPressed) scrollAmount else 0.0 - val deltaY = if (isShiftPressed) 0.0 else scrollAmount - return SkikoPointerEvent( - x = event.x.toDouble(), - y = event.y.toDouble(), - deltaX = deltaX, - deltaY = deltaY, - pressedButtons = toSkikoPressedMouseButtons(event), - button = toSkikoMouseButton(event), - modifiers = modifiers, - kind = when (event.id) { - MouseEvent.MOUSE_WHEEL -> SkikoPointerEventKind.SCROLL - else -> SkikoPointerEventKind.UNKNOWN - }, - timestamp = event.`when`, - platform = event - ) -} - -fun toSkikoEvent(event: KeyEvent): SkikoKeyboardEvent { - return SkikoKeyboardEvent( - SkikoKey.valueOf(toSkikoKey(event)), - toSkikoModifiers(event.modifiersEx), - when (event.id) { - KEY_PRESSED -> SkikoKeyboardEventKind.DOWN - KEY_RELEASED -> SkikoKeyboardEventKind.UP - else -> SkikoKeyboardEventKind.UNKNOWN - }, - event.`when`, - event - ) -} - -fun toSkikoTypeEvent(typeEvent: KeyEvent, keyEvent: KeyEvent?): SkikoInputEvent { - var key: Int = -1 - var modifiers = SkikoInputModifiers.EMPTY - if (keyEvent != null) { - key = toSkikoKey(keyEvent) - modifiers = toSkikoModifiers(keyEvent.modifiersEx) - } - return SkikoInputEvent( - typeEvent.keyChar.toString(), - SkikoKey.valueOf(key), - modifiers, - SkikoKeyboardEventKind.TYPE, - typeEvent - ) -} - -fun toSkikoTypeEvent(event: InputMethodEvent, keyEvent: KeyEvent?): SkikoInputEvent { - var key: Int = -1 - var modifiers = SkikoInputModifiers.EMPTY - if (keyEvent != null) { - key = toSkikoKey(keyEvent) - modifiers = toSkikoModifiers(keyEvent.modifiersEx) - } - return SkikoInputEvent( - "", - SkikoKey.valueOf(key), - modifiers, - SkikoKeyboardEventKind.TYPE, - event - ) -} - -private fun toSkikoPressedMouseButtons(event: MouseEvent): SkikoMouseButtons { - val mask = event.modifiersEx - var result = 0 - // We should check [event.button] because of case where [event.modifiersEx] does not provide - // info about the pressed mouse button when using touchpad on MacOS 12 (AWT only) - // see: https://youtrack.jetbrains.com/issue/COMPOSE-36 - if (mask and InputEvent.BUTTON1_DOWN_MASK != 0 - || (event.id == MouseEvent.MOUSE_PRESSED && event.button == MouseEvent.BUTTON1)) { - result = result.or(SkikoMouseButtons.LEFT.value) - } - if (mask and InputEvent.BUTTON2_DOWN_MASK != 0 - || (event.id == MouseEvent.MOUSE_PRESSED && event.button == MouseEvent.BUTTON2)) { - result = result.or(SkikoMouseButtons.MIDDLE.value) - } - if (mask and InputEvent.BUTTON3_DOWN_MASK != 0 - || (event.id == MouseEvent.MOUSE_PRESSED && event.button == MouseEvent.BUTTON3)) { - result = result.or(SkikoMouseButtons.RIGHT.value) - } - if (mask and MouseEvent.getMaskForButton(MouseEventButton4) != 0 - || (event.id == MouseEvent.MOUSE_PRESSED && event.button == MouseEventButton4)) { - result = result.or(SkikoMouseButtons.BUTTON_4.value) - } - if (mask and MouseEvent.getMaskForButton(MouseEventButton5) != 0 - || (event.id == MouseEvent.MOUSE_PRESSED && event.button == MouseEventButton5)) { - result = result.or(SkikoMouseButtons.BUTTON_5.value) - } - return SkikoMouseButtons(result) -} - -private fun toSkikoMouseButton(event: MouseEvent): SkikoMouseButtons { - return when (event.button) { - MouseEvent.BUTTON1 -> SkikoMouseButtons.LEFT - MouseEvent.BUTTON2 -> SkikoMouseButtons.MIDDLE - MouseEvent.BUTTON3 -> SkikoMouseButtons.RIGHT - MouseEventButton4 -> SkikoMouseButtons.BUTTON_4 - MouseEventButton5 -> SkikoMouseButtons.BUTTON_5 - else -> SkikoMouseButtons(event.button) - } -} - -private fun toSkikoModifiers(modifiers: Int): SkikoInputModifiers { - var result = 0 - if (modifiers and InputEvent.ALT_DOWN_MASK != 0) { - result = SkikoInputModifiers.ALT.value - } - if (modifiers and InputEvent.SHIFT_DOWN_MASK != 0) { - result = result.or(SkikoInputModifiers.SHIFT.value) - } - if (modifiers and InputEvent.CTRL_DOWN_MASK != 0) { - result = result.or(SkikoInputModifiers.CONTROL.value) - } - if (modifiers and InputEvent.META_DOWN_MASK != 0) { - result = result.or(SkikoInputModifiers.META.value) - } - return SkikoInputModifiers(result) -} - -private fun toSkikoKey(event: KeyEvent): Int { - var key = event.keyCode - val side = event.keyLocation - if (side == KEY_LOCATION_RIGHT) { - if ( - key == SkikoKey.KEY_LEFT_CONTROL.platformKeyCode || - key == SkikoKey.KEY_LEFT_SHIFT.platformKeyCode || - key == SkikoKey.KEY_LEFT_META.platformKeyCode - ) { - key = key.or(0x80000000.toInt()) - } - } - if (side == KEY_LOCATION_NUMPAD) { - if (key == SkikoKey.KEY_ENTER.platformKeyCode) { - key = key.or(0x80000000.toInt()) - } - } - return key -} diff --git a/skiko/src/awtMain/kotlin/org/jetbrains/skiko/SkiaLayer.awt.kt b/skiko/src/awtMain/kotlin/org/jetbrains/skiko/SkiaLayer.awt.kt index 4b9f0b926..8720ee486 100644 --- a/skiko/src/awtMain/kotlin/org/jetbrains/skiko/SkiaLayer.awt.kt +++ b/skiko/src/awtMain/kotlin/org/jetbrains/skiko/SkiaLayer.awt.kt @@ -219,7 +219,7 @@ actual open class SkiaLayer internal constructor( actual val component: Any? get() = backedLayer - actual var skikoView: SkikoView? = null + actual var renderDelegate: SkikoRenderDelegate? = null actual fun attachTo(container: Any) { attachTo(container as JComponent) @@ -231,69 +231,6 @@ actual open class SkiaLayer internal constructor( private var keyEvent: KeyEvent? = null - fun addView(view: SkikoView) { - skikoView = view - addMouseListener(object : MouseAdapter() { - override fun mousePressed(e: MouseEvent) { - skikoView?.onPointerEvent(toSkikoEvent(e)) - } - - override fun mouseReleased(e: MouseEvent) { - skikoView?.onPointerEvent(toSkikoEvent(e)) - } - - override fun mouseEntered(e: MouseEvent) { - skikoView?.onPointerEvent(toSkikoEvent(e)) - } - - override fun mouseExited(e: MouseEvent) { - skikoView?.onPointerEvent(toSkikoEvent(e)) - } - }) - - addMouseMotionListener(object : MouseMotionAdapter() { - override fun mouseDragged(e: MouseEvent) { - skikoView?.onPointerEvent(toSkikoEvent(e)) - } - - override fun mouseMoved(e: MouseEvent) { - skikoView?.onPointerEvent(toSkikoEvent(e)) - } - }) - - addMouseWheelListener(object : MouseWheelListener { - override fun mouseWheelMoved(e: MouseWheelEvent) { - skikoView?.onPointerEvent(toSkikoEvent(e)) - } - }) - - addKeyListener(object : KeyAdapter() { - override fun keyPressed(e: KeyEvent) { - keyEvent = e - skikoView?.onKeyboardEvent(toSkikoEvent(e)) - } - - override fun keyReleased(e: KeyEvent) { - keyEvent = e - skikoView?.onKeyboardEvent(toSkikoEvent(e)) - } - - override fun keyTyped(e: KeyEvent) { - skikoView?.onInputEvent(toSkikoTypeEvent(e, keyEvent)) - } - }) - - addInputMethodListener(object : InputMethodListener { - override fun caretPositionChanged(e: InputMethodEvent) { - skikoView?.onInputEvent(toSkikoTypeEvent(e, keyEvent)) - } - - override fun inputMethodTextChanged(e: InputMethodEvent) { - skikoView?.onInputEvent(toSkikoTypeEvent(e, keyEvent)) - } - }) - } - val clipComponents = mutableListOf() @Volatile @@ -545,7 +482,7 @@ actual open class SkiaLayer internal constructor( try { isRendering = true - skikoView?.onRender(canvas, pictureWidth, pictureHeight, nanoTime) + renderDelegate?.onRender(canvas, pictureWidth, pictureHeight, nanoTime) } finally { isRendering = false } @@ -670,9 +607,3 @@ internal fun Canvas.clipRectBy(rectangle: ClipRectangle, scale: Float) { true ) } - -// InputEvent is abstract, so we wrap to match modality. -actual typealias SkikoGesturePlatformEvent = Any -actual typealias SkikoPlatformInputEvent = Any -actual typealias SkikoPlatformKeyboardEvent = KeyEvent -actual typealias SkikoPlatformPointerEvent = MouseEvent diff --git a/skiko/src/awtMain/kotlin/org/jetbrains/skiko/SkikoInput.awt.kt b/skiko/src/awtMain/kotlin/org/jetbrains/skiko/SkikoInput.awt.kt deleted file mode 100644 index c6b5331d3..000000000 --- a/skiko/src/awtMain/kotlin/org/jetbrains/skiko/SkikoInput.awt.kt +++ /dev/null @@ -1,5 +0,0 @@ -package org.jetbrains.skiko - -actual interface SkikoInput { - actual object Empty : SkikoInput -} diff --git a/skiko/src/awtMain/kotlin/org/jetbrains/skiko/SkikoKey.awt.kt b/skiko/src/awtMain/kotlin/org/jetbrains/skiko/SkikoKey.awt.kt deleted file mode 100644 index 7b75d50b9..000000000 --- a/skiko/src/awtMain/kotlin/org/jetbrains/skiko/SkikoKey.awt.kt +++ /dev/null @@ -1,118 +0,0 @@ -package org.jetbrains.skiko - -import java.awt.event.KeyEvent.* - -actual enum class SkikoKey(actual val platformKeyCode: Int) { - KEY_UNKNOWN(-1), - KEY_A(VK_A), - KEY_S(VK_S), - KEY_D(VK_D), - KEY_F(VK_F), - KEY_H(VK_H), - KEY_G(VK_G), - KEY_Z(VK_Z), - KEY_X(VK_X), - KEY_C(VK_C), - KEY_V(VK_V), - KEY_B(VK_B), - KEY_Q(VK_Q), - KEY_W(VK_W), - KEY_E(VK_E), - KEY_R(VK_R), - KEY_Y(VK_Y), - KEY_T(VK_T), - KEY_U(VK_U), - KEY_I(VK_I), - KEY_P(VK_P), - KEY_L(VK_L), - KEY_J(VK_J), - KEY_K(VK_K), - KEY_N(VK_N), - KEY_M(VK_M), - KEY_O(VK_O), - KEY_1(VK_1), - KEY_2(VK_2), - KEY_3(VK_3), - KEY_4(VK_4), - KEY_5(VK_5), - KEY_6(VK_6), - KEY_7(VK_7), - KEY_8(VK_8), - KEY_9(VK_9), - KEY_0(VK_0), - KEY_CLOSE_BRACKET(VK_CLOSE_BRACKET), - KEY_OPEN_BRACKET(VK_OPEN_BRACKET), - KEY_QUOTE(VK_QUOTE), - KEY_SEMICOLON(VK_SEMICOLON), - KEY_SLASH(VK_SLASH), - KEY_COMMA(VK_COMMA), - KEY_BACKSLASH(VK_BACK_SLASH), - KEY_PERIOD(VK_PERIOD), - KEY_BACK_QUOTE(VK_BACK_QUOTE), - KEY_EQUALS(VK_EQUALS), - KEY_MINUS(VK_MINUS), - KEY_ENTER(VK_ENTER), - KEY_ESCAPE(VK_ESCAPE), - KEY_TAB(VK_TAB), - KEY_BACKSPACE(VK_BACK_SPACE), - KEY_SPACE(VK_SPACE), - KEY_CAPSLOCK(VK_CAPS_LOCK), - KEY_LEFT_META(VK_META), - KEY_LEFT_SHIFT(VK_SHIFT), - KEY_LEFT_ALT(VK_ALT), - KEY_LEFT_CONTROL(VK_CONTROL), - KEY_RIGHT_META(0x80000000.toInt() or VK_META), - KEY_RIGHT_SHIFT(0x80000000.toInt() or VK_SHIFT), - KEY_RIGHT_ALT(VK_ALT_GRAPH), - KEY_RIGHT_CONTROL(0x80000000.toInt() or VK_CONTROL), - KEY_MENU(VK_CONTEXT_MENU), - KEY_UP(VK_UP), - KEY_DOWN(VK_DOWN), - KEY_LEFT(VK_LEFT), - KEY_RIGHT(VK_RIGHT), - KEY_F1(VK_F1), - KEY_F2(VK_F2), - KEY_F3(VK_F3), - KEY_F4(VK_F4), - KEY_F5(VK_F5), - KEY_F6(VK_F6), - KEY_F7(VK_F7), - KEY_F8(VK_F8), - KEY_F9(VK_F9), - KEY_F10(VK_F10), - KEY_F11(VK_F11), - KEY_F12(VK_F12), - KEY_PRINTSCEEN(VK_PRINTSCREEN), - KEY_SCROLL_LOCK(VK_SCROLL_LOCK), - KEY_PAUSE(VK_PAUSE), - KEY_INSERT(VK_INSERT), - KEY_HOME(VK_HOME), - KEY_PGUP(VK_PAGE_UP), - KEY_DELETE(VK_DELETE), - KEY_END(VK_END), - KEY_PGDOWN(VK_PAGE_DOWN), - KEY_NUM_LOCK(VK_NUM_LOCK), - KEY_NUMPAD_0(VK_NUMPAD0), - KEY_NUMPAD_1(VK_NUMPAD1), - KEY_NUMPAD_2(VK_NUMPAD2), - KEY_NUMPAD_3(VK_NUMPAD3), - KEY_NUMPAD_4(VK_NUMPAD4), - KEY_NUMPAD_5(VK_NUMPAD5), - KEY_NUMPAD_6(VK_NUMPAD6), - KEY_NUMPAD_7(VK_NUMPAD7), - KEY_NUMPAD_8(VK_NUMPAD8), - KEY_NUMPAD_9(VK_NUMPAD9), - KEY_NUMPAD_ENTER(0x80000000.toInt() or VK_ENTER), - KEY_NUMPAD_ADD(VK_ADD), - KEY_NUMPAD_SUBTRACT(VK_SUBTRACT), - KEY_NUMPAD_MULTIPLY(VK_MULTIPLY), - KEY_NUMPAD_DIVIDE(VK_DIVIDE), - KEY_NUMPAD_DECIMAL(VK_DECIMAL); - - companion object { - fun valueOf(platformKeyCode: Int): SkikoKey { - val key = SkikoKey.values().firstOrNull { it.platformKeyCode == platformKeyCode } - return if (key == null) SkikoKey.KEY_UNKNOWN else key - } - } -} diff --git a/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/Direct3DSwingRedrawer.kt b/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/Direct3DSwingRedrawer.kt index 1181f92d4..0b9ca8d2c 100644 --- a/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/Direct3DSwingRedrawer.kt +++ b/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/Direct3DSwingRedrawer.kt @@ -6,7 +6,7 @@ import java.awt.Graphics2D internal class Direct3DSwingRedrawer( swingLayerProperties: SwingLayerProperties, - private val skikoView: SkikoView, + private val renderDelegate: SkikoRenderDelegate, analytics: SkiaLayerAnalytics ) : SwingRedrawerBase(swingLayerProperties, analytics, GraphicsApi.DIRECT3D) { companion object { @@ -49,7 +49,7 @@ internal class Direct3DSwingRedrawer( // Calculate aligned width that is needed for performance optimization, // since DirectX uses aligned bytebuffer. // So we will have [Surface] with width == [alignedWidth], - // but imitate (for SkikoView and Swing) like it has width == [width]. + // but imitate (for SkikoRenderDelegate and Swing) like it has width == [width]. val alignedWidth = if (width % widthSizeAlignment != 0) { width + widthSizeAlignment - (width % widthSizeAlignment); } else { @@ -73,7 +73,7 @@ internal class Direct3DSwingRedrawer( val canvas = surface.canvas canvas.clear(Color.TRANSPARENT) - skikoView.onRender(canvas, width, height, nanoTime) + renderDelegate.onRender(canvas, width, height, nanoTime) flush(surface, g) } } diff --git a/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/LinuxOpenGLSwingRedrawer.kt b/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/LinuxOpenGLSwingRedrawer.kt index eddfaea4b..7f8a11e14 100644 --- a/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/LinuxOpenGLSwingRedrawer.kt +++ b/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/LinuxOpenGLSwingRedrawer.kt @@ -6,7 +6,7 @@ import java.awt.Graphics2D internal class LinuxOpenGLSwingRedrawer( swingLayerProperties: SwingLayerProperties, - private val skikoView: SkikoView, + private val renderDelegate: SkikoRenderDelegate, analytics: SkiaLayerAnalytics ) : SwingRedrawerBase(swingLayerProperties, analytics, GraphicsApi.OPENGL) { init { @@ -76,7 +76,7 @@ internal class LinuxOpenGLSwingRedrawer( val canvas = surface.canvas canvas.clear(Color.TRANSPARENT) - skikoView.onRender(canvas, width, height, nanoTime) + renderDelegate.onRender(canvas, width, height, nanoTime) flush(surface, g) unbindAndDisposeTexture(texturePtr) } diff --git a/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/MetalSwingRedrawer.kt b/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/MetalSwingRedrawer.kt index ad720d13c..b9a8a6692 100644 --- a/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/MetalSwingRedrawer.kt +++ b/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/MetalSwingRedrawer.kt @@ -10,7 +10,7 @@ import java.awt.Graphics2D * * For now, it uses drawing to [java.awt.image.BufferedImage] that cause VRAM <-> RAM memory transfer and so increased CPU usage. * - * Content to draw is provided by [SkikoView]. + * Content to draw is provided by [SkikoRenderDelegate]. * * For on-screen rendering see [org.jetbrains.skiko.redrawer.MetalRedrawer]. * @@ -19,7 +19,7 @@ import java.awt.Graphics2D */ internal class MetalSwingRedrawer( swingLayerProperties: SwingLayerProperties, - private val skikoView: SkikoView, + private val renderDelegate: SkikoRenderDelegate, analytics: SkiaLayerAnalytics ) : SwingRedrawerBase(swingLayerProperties, analytics, GraphicsApi.METAL) { companion object { @@ -70,7 +70,7 @@ internal class MetalSwingRedrawer( val canvas = surface.canvas canvas.clear(Color.TRANSPARENT) - skikoView.onRender(canvas, width, height, nanoTime) + renderDelegate.onRender(canvas, width, height, nanoTime) flush(surface, g) } } diff --git a/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/SkiaSwingLayer.kt b/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/SkiaSwingLayer.kt index 8124d1059..46e16c114 100644 --- a/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/SkiaSwingLayer.kt +++ b/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/SkiaSwingLayer.kt @@ -10,7 +10,7 @@ import javax.swing.JComponent import javax.swing.SwingUtilities.isEventDispatchThread /** - * Swing component that draws content provided by [skikoView] with GPU acceleration using Skia engine. + * Swing component that draws content provided by [renderDelegate] with GPU acceleration using Skia engine. * * Drawn content can be clipped by providing [ClipRectangle] to [clipComponents]. * @@ -22,7 +22,7 @@ import javax.swing.SwingUtilities.isEventDispatchThread @Suppress("unused") // used in Compose Multiplatform @ExperimentalSkikoApi open class SkiaSwingLayer( - skikoView: SkikoView, + renderDelegate: SkikoRenderDelegate, analytics: SkiaLayerAnalytics = SkiaLayerAnalytics.Empty, ) : JComponent() { internal companion object { @@ -40,14 +40,14 @@ open class SkiaSwingLayer( val clipComponents: MutableList get() = mutableListOf() - private val skikoViewWithClipping = object : SkikoView by skikoView { + private val renderDelegateWithClipping = object : SkikoRenderDelegate by renderDelegate { override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) { val scale = graphicsConfiguration.defaultTransform.scaleX.toFloat() // clipping for (component in clipComponents) { canvas.clipRectBy(component, scale) } - skikoView.onRender(canvas, width, height, nanoTime) + renderDelegate.onRender(canvas, width, height, nanoTime) } } @@ -64,7 +64,7 @@ open class SkiaSwingLayer( private val redrawerManager = RedrawerManager(properties.renderApi) { renderApi, oldRedrawer -> oldRedrawer?.dispose() - createSwingRedrawer(swingLayerProperties, skikoViewWithClipping, renderApi, analytics) + createSwingRedrawer(swingLayerProperties, renderDelegateWithClipping, renderApi, analytics) } private val redrawer: SwingRedrawer? diff --git a/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/SoftwareSwingRedrawer.kt b/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/SoftwareSwingRedrawer.kt index 1f91c5ab2..dde2472a5 100644 --- a/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/SoftwareSwingRedrawer.kt +++ b/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/SoftwareSwingRedrawer.kt @@ -3,21 +3,21 @@ package org.jetbrains.skiko.swing import org.jetbrains.skia.* import org.jetbrains.skiko.GraphicsApi import org.jetbrains.skiko.SkiaLayerAnalytics -import org.jetbrains.skiko.SkikoView +import org.jetbrains.skiko.SkikoRenderDelegate import org.jetbrains.skiko.autoCloseScope import java.awt.Graphics2D /** * Provides a way to draw on Skia canvas using software rendering without GPU acceleration and then draw it on [java.awt.Graphics2D]. * - * Content to draw is provided by [SkikoView]. + * Content to draw is provided by [SkikoRenderDelegate]. * * @see SwingRedrawerBase * @see SwingOffscreenDrawer */ internal class SoftwareSwingRedrawer( swingLayerProperties: SwingLayerProperties, - private val skikoView: SkikoView, + private val renderDelegate: SkikoRenderDelegate, analytics: SkiaLayerAnalytics ) : SwingRedrawerBase( swingLayerProperties, @@ -48,7 +48,7 @@ internal class SoftwareSwingRedrawer( val canvas = Canvas(storage, SurfaceProps(pixelGeometry = PixelGeometry.UNKNOWN)).autoClose() canvas.clear(Color.TRANSPARENT) - skikoView.onRender(canvas, width, height, nanoTime) + renderDelegate.onRender(canvas, width, height, nanoTime) flush(g) } diff --git a/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/SwingRedrawer.kt b/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/SwingRedrawer.kt index 865c6433b..884dea913 100644 --- a/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/SwingRedrawer.kt +++ b/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/SwingRedrawer.kt @@ -22,25 +22,25 @@ internal interface SwingRedrawer { } /** - * Creates a [SwingRedrawer] that will draw content provided by [skikoView] + * Creates a [SwingRedrawer] that will draw content provided by [renderDelegate] */ internal fun createSwingRedrawer( swingLayerProperties: SwingLayerProperties, - skikoView: SkikoView, + renderDelegate: SkikoRenderDelegate, renderApi: GraphicsApi, analytics: SkiaLayerAnalytics, ): SwingRedrawer { if (renderApi == GraphicsApi.SOFTWARE_COMPAT || renderApi == GraphicsApi.SOFTWARE_FAST) { return SoftwareSwingRedrawer( swingLayerProperties, - skikoView, + renderDelegate, analytics ) } return when (hostOs) { - OS.MacOS -> MetalSwingRedrawer(swingLayerProperties, skikoView, analytics) - OS.Windows -> Direct3DSwingRedrawer(swingLayerProperties, skikoView, analytics) - OS.Linux -> LinuxOpenGLSwingRedrawer(swingLayerProperties, skikoView, analytics) - else -> SoftwareSwingRedrawer(swingLayerProperties, skikoView, analytics) + OS.MacOS -> MetalSwingRedrawer(swingLayerProperties, renderDelegate, analytics) + OS.Windows -> Direct3DSwingRedrawer(swingLayerProperties, renderDelegate, analytics) + OS.Linux -> LinuxOpenGLSwingRedrawer(swingLayerProperties, renderDelegate, analytics) + else -> SoftwareSwingRedrawer(swingLayerProperties, renderDelegate, analytics) } } \ No newline at end of file diff --git a/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/SwingRedrawerBase.kt b/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/SwingRedrawerBase.kt index 045e83803..34f114afa 100644 --- a/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/SwingRedrawerBase.kt +++ b/skiko/src/awtMain/kotlin/org/jetbrains/skiko/swing/SwingRedrawerBase.kt @@ -8,12 +8,12 @@ import java.util.concurrent.CancellationException import javax.swing.SwingUtilities /** - * Provides a base implementation of drawing [SkikoView] content on [java.awt.Graphics2D] + * Provides a base implementation of drawing [SkikoRenderDelegate] content on [java.awt.Graphics2D] * * Each [redraw] request is handled in a following way: * 1. For the first request initialize native GPU context using [createDirectContext] * 2. Create [org.jetbrains.skia.Canvas] where content should be drawn using [initCanvas] - * 3. Acquire drawing "commands" using [SkikoView] + * 3. Acquire drawing "commands" using [SkikoRenderDelegate] * 4. Flush these commands on [java.awt.Graphics2D] using [flush] * * All the steps are performed synchronously on EDT. diff --git a/skiko/src/awtTest/kotlin/org/jetbrains/skiko/SkiaLayerPerformanceTest.kt b/skiko/src/awtTest/kotlin/org/jetbrains/skiko/SkiaLayerPerformanceTest.kt index 3d00f90d5..e977abf3a 100644 --- a/skiko/src/awtTest/kotlin/org/jetbrains/skiko/SkiaLayerPerformanceTest.kt +++ b/skiko/src/awtTest/kotlin/org/jetbrains/skiko/SkiaLayerPerformanceTest.kt @@ -52,7 +52,7 @@ class SkiaLayerPerformanceTest { init { window.setSize(width, height) window.defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE - window.layer.skikoView = object : SkikoView { + window.layer.renderDelegate = object : SkikoRenderDelegate { override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) { scene(canvas, width, height, nanoTime) if (canCollect && frameTimes.size < frameCount) { diff --git a/skiko/src/awtTest/kotlin/org/jetbrains/skiko/SkiaLayerTest.kt b/skiko/src/awtTest/kotlin/org/jetbrains/skiko/SkiaLayerTest.kt index 1ba961e40..49200494f 100644 --- a/skiko/src/awtTest/kotlin/org/jetbrains/skiko/SkiaLayerTest.kt +++ b/skiko/src/awtTest/kotlin/org/jetbrains/skiko/SkiaLayerTest.kt @@ -81,7 +81,7 @@ class SkiaLayerTest { window.setLocation(200, 200) window.setSize(400, 600) window.defaultCloseOperation = WindowConstants.EXIT_ON_CLOSE - window.layer.skikoView = object : SkikoView { + window.layer.renderDelegate = object : SkikoRenderDelegate { override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) { val c1 = counter1 val c2 = counter2 @@ -164,7 +164,7 @@ class SkiaLayerTest { window.setSize(400, 200) window.defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE val app = RectRenderer(window.layer, 200, 100, Color.RED) - window.layer.skikoView = app + window.layer.renderDelegate = app window.isUndecorated = true window.isVisible = true @@ -188,7 +188,7 @@ class SkiaLayerTest { window.preferredSize = Dimension(400, 200) window.defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE val app = RectRenderer(window.layer, 200, 100, Color.RED) - window.layer.skikoView = app + window.layer.renderDelegate = app window.isUndecorated = true window.pack() window.paint(window.graphics) @@ -213,7 +213,7 @@ class SkiaLayerTest { properties = SkiaLayerProperties(renderApi = renderApi) ) var renderedWidth = -1 - layer.skikoView = object : SkikoView { + layer.renderDelegate = object : SkikoRenderDelegate { override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) { renderedWidth = width } @@ -268,7 +268,7 @@ class SkiaLayerTest { window.setLocation(200, 200) window.setSize(40, 20) window.defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE - window.layer.skikoView = RectRenderer(window.layer, 20, 10, Color.RED) + window.layer.renderDelegate = RectRenderer(window.layer, 20, 10, Color.RED) window.isUndecorated = true window.isVisible = true delay(1000) @@ -288,7 +288,7 @@ class SkiaLayerTest { setLocation(200, 200) setSize(400, 200) defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE - layer.skikoView = RectRenderer(layer, 200, 100, color) + layer.renderDelegate = RectRenderer(layer, 200, 100, color) isUndecorated = true isVisible = true } @@ -355,7 +355,7 @@ class SkiaLayerTest { window.setLocation(200, 200) window.setSize(40, 20) window.defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE - window.layer.skikoView = object : SkikoView { + window.layer.renderDelegate = object : SkikoRenderDelegate { override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) { renderCount++ } @@ -386,7 +386,7 @@ class SkiaLayerTest { setLocation(200, 200) setSize(40, 20) defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE - layer.skikoView = if (isAnimated) { + layer.renderDelegate = if (isAnimated) { AnimatedBoxRenderer(layer, pixelsPerSecond = 20.0, size = 20.0) } else { RectRenderer(layer, 20, 10, Color.RED) @@ -430,7 +430,7 @@ class SkiaLayerTest { setLocation(200, 200) setSize(400, 200) defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE - layer.skikoView = AnimatedBoxRenderer(layer, pixelsPerSecond = 20.0, size = 20.0) + layer.renderDelegate = AnimatedBoxRenderer(layer, pixelsPerSecond = 20.0, size = 20.0) isVisible = true } @@ -454,7 +454,7 @@ class SkiaLayerTest { setSize(400, 200) preferredSize = Dimension(400, 200) defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE - layer.skikoView = object : SkikoView { + layer.renderDelegate = object : SkikoRenderDelegate { override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) { } } @@ -539,7 +539,7 @@ class SkiaLayerTest { window.setSize(400, 200) window.defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE val app = RectRenderer(window.layer, 200, 100, Color.RED) - window.layer.skikoView = app + window.layer.renderDelegate = app window.isUndecorated = true window.isVisible = true @@ -591,7 +591,7 @@ class SkiaLayerTest { window.setLocation(200, 200) window.setSize(400, 200) window.defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE - window.layer.skikoView = object : SkikoView { + window.layer.renderDelegate = object : SkikoRenderDelegate { override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) { drawCount++ @@ -623,7 +623,7 @@ class SkiaLayerTest { try { window.setLocation(200, 200) window.setSize(400, 400) - window.layer.skikoView = object : SkikoView { + window.layer.renderDelegate = object : SkikoRenderDelegate { override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) { window.dispose() SwingUtilities.invokeLater { @@ -646,7 +646,7 @@ class SkiaLayerTest { window.setSize(400, 200) window.defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE val app = RectRenderer(window.layer, 200, 100, Color.RED) - window.layer.skikoView = app + window.layer.renderDelegate = app window.isUndecorated = true window.isVisible = true @@ -680,7 +680,7 @@ class SkiaLayerTest { panel.background = Color.GREEN contentPane.add(panel, BorderLayout.WEST) - layer.skikoView = RectRenderer(layer, 100, 100, Color.RED) + layer.renderDelegate = RectRenderer(layer, 100, 100, Color.RED) contentPane.add(layer, BorderLayout.CENTER) }) try { @@ -699,13 +699,13 @@ class SkiaLayerTest { excludeRenderApis = listOf(GraphicsApi.SOFTWARE_COMPAT) ) { val renderTimes = mutableListOf() - val renderer = object: SkikoView { + val renderer = object: SkikoRenderDelegate { override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) { renderTimes.add(System.currentTimeMillis()) } } val window = UiTestWindow { - layer.skikoView = renderer + layer.renderDelegate = renderer contentPane.add(layer, BorderLayout.CENTER) } try { @@ -834,7 +834,7 @@ class SkiaLayerTest { window.setSize(400, 200) window.defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE val app = RectRenderer(window.layer, 200, 100, Color.RED) - window.layer.skikoView = app + window.layer.renderDelegate = app window.isUndecorated = true window.isVisible = true @@ -868,7 +868,7 @@ class SkiaLayerTest { val paragraph by lazy { paragraph(window.layer.contentScale * 40, "=-+Нп") } - window.layer.skikoView = object : SkikoView { + window.layer.renderDelegate = object : SkikoRenderDelegate { override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) { canvas.clear(Color.WHITE.rgb) paragraph.layout(Float.POSITIVE_INFINITY) @@ -901,7 +901,7 @@ class SkiaLayerTest { var rectWidth: Int, var rectHeight: Int, private val rectColor: Color - ) : SkikoView { + ) : SkikoRenderDelegate { override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) { val dpi = layer.contentScale canvas.drawRect(Rect(0f, 0f, width.toFloat(), height.toFloat()), Paint().apply { @@ -917,7 +917,7 @@ class SkiaLayerTest { private val layer: SkiaLayer, private val pixelsPerSecond: Double, private val size: Double - ) : SkikoView { + ) : SkikoRenderDelegate { private var oldNanoTime = Long.MAX_VALUE private var x = 0.0 diff --git a/skiko/src/commonMain/kotlin/org/jetbrains/skiko/Events.kt b/skiko/src/commonMain/kotlin/org/jetbrains/skiko/Events.kt deleted file mode 100644 index 0de1cb9bf..000000000 --- a/skiko/src/commonMain/kotlin/org/jetbrains/skiko/Events.kt +++ /dev/null @@ -1,241 +0,0 @@ -package org.jetbrains.skiko - -import kotlin.jvm.JvmInline - -// Clicked mouse buttons bitmask. -@JvmInline -value class SkikoMouseButtons(val value: Int) { - companion object { - val NONE = SkikoMouseButtons(0) - val LEFT = SkikoMouseButtons(1) - val RIGHT = SkikoMouseButtons(2) - val MIDDLE = SkikoMouseButtons(4) - val BUTTON_1 = SkikoMouseButtons(1) - val BUTTON_2 = SkikoMouseButtons(2) - val BUTTON_3 = SkikoMouseButtons(4) - val BUTTON_4 = SkikoMouseButtons(8) - val BUTTON_5 = SkikoMouseButtons(16) - val BUTTON_6 = SkikoMouseButtons(32) - val BUTTON_7 = SkikoMouseButtons(64) - val BUTTON_8 = SkikoMouseButtons(128) - } - - fun has(value: SkikoMouseButtons): Boolean { - if (value.value and this.value != 0) { - return true - } - return false - } - - override fun toString(): String { - val result = mutableListOf().apply { - if (has(SkikoMouseButtons.LEFT)) { - add("LEFT") - } - if (has(SkikoMouseButtons.RIGHT)) { - add("RIGHT") - } - if (has(SkikoMouseButtons.MIDDLE)) { - add("MIDDLE") - } - if (has(SkikoMouseButtons.BUTTON_4)) { - add("BUTTON_4") - } - if (has(SkikoMouseButtons.BUTTON_5)) { - add("BUTTON_5") - } - if (has(SkikoMouseButtons.BUTTON_6)) { - add("BUTTON_6") - } - if (has(SkikoMouseButtons.BUTTON_7)) { - add("BUTTON_7") - } - if (has(SkikoMouseButtons.BUTTON_8)) { - add("BUTTON_8") - } - } - return if (!result.isEmpty()) result.toString() else "" - } -} - -@JvmInline -value class SkikoInputModifiers(val value: Int) { - companion object { - val EMPTY = SkikoInputModifiers(0) - val META = SkikoInputModifiers(1) - val CONTROL = SkikoInputModifiers(2) - val ALT = SkikoInputModifiers(4) - val SHIFT = SkikoInputModifiers(8) - } - - fun has(value: SkikoInputModifiers): Boolean { - if (value.value and this.value != 0) { - return true - } - return false - } - - override fun toString(): String { - val result = mutableListOf().apply { - if (has(SkikoInputModifiers.META)) { - add("META") - } - if (has(SkikoInputModifiers.CONTROL)) { - add("CONTROL") - } - if (has(SkikoInputModifiers.ALT)) { - add("ALT") - } - if (has(SkikoInputModifiers.SHIFT)) { - add("SHIFT") - } - } - return if (!result.isEmpty()) result.toString() else "" - } -} - -enum class SkikoGestureEventKind { - UNKNOWN, TAP, DOUBLETAP, LONGPRESS, PAN, PINCH, ROTATION, SWIPE -} -enum class SkikoGestureEventDirection { - UNKNOWN, UP, DOWN, LEFT, RIGHT -} -enum class SkikoGestureEventState { - UNKNOWN, PRESSED, STARTED, CHANGED, ENDED -} -expect class SkikoGesturePlatformEvent -data class SkikoGestureEvent( - val x: Double, - val y: Double, - val velocity: Double = 0.0, - val direction: SkikoGestureEventDirection = SkikoGestureEventDirection.UNKNOWN, - val rotation: Double = 0.0, - val scale: Double = 1.0, - val kind: SkikoGestureEventKind, - val state: SkikoGestureEventState = SkikoGestureEventState.UNKNOWN, - val platform: SkikoGesturePlatformEvent? = null -) - -expect class SkikoPlatformInputEvent -data class SkikoInputEvent( - val input: String, - val key: SkikoKey, - val modifiers: SkikoInputModifiers = SkikoInputModifiers.EMPTY, - val kind: SkikoKeyboardEventKind, - val platform: SkikoPlatformInputEvent? -) - -enum class SkikoKeyboardEventKind { - UNKNOWN, UP, DOWN, TYPE -} -expect class SkikoPlatformKeyboardEvent -data class SkikoKeyboardEvent( - val key: SkikoKey, - val modifiers: SkikoInputModifiers = SkikoInputModifiers.EMPTY, - val kind: SkikoKeyboardEventKind, - val timestamp: Long = 0, - val platform: SkikoPlatformKeyboardEvent? -) - -enum class SkikoPointerEventKind { - UNKNOWN, UP, DOWN, MOVE, DRAG, SCROLL, ENTER, EXIT -} - -expect class SkikoPlatformPointerEvent - -// TODO(https://github.com/JetBrains/skiko/issues/680) refactor API -data class SkikoPointerEvent( - /** - * X position in points (scaled pixels that depend on the scale factor of the current display). - * - * If the event contains multiple pointers, it represents the center of all pointers. - */ - val x: Double, - /** - * Y position in points (scaled pixels that depend on the scale factor of the current display) - * - * If the event contains multiple pointers, it represents the center of all pointers. - */ - val y: Double, - val kind: SkikoPointerEventKind, - /** - * Scroll delta along the X axis - */ - val deltaX: Double = 0.0, - /** - * Scroll delta along the Y axis - */ - val deltaY: Double = 0.0, - val pressedButtons: SkikoMouseButtons = SkikoMouseButtons.NONE, - val button: SkikoMouseButtons = SkikoMouseButtons.NONE, - val modifiers: SkikoInputModifiers = SkikoInputModifiers.EMPTY, - /** - * Timestamp in milliseconds - */ - val timestamp: Long = 0, - val pointers: List = listOf( - SkikoPointer(0, x, y, pressedButtons.has(SkikoMouseButtons.LEFT)) - ), - val platform: SkikoPlatformPointerEvent? = null -) - -val SkikoPointerEvent.isLeftClick: Boolean - get() = button.has(SkikoMouseButtons.LEFT) && (kind == SkikoPointerEventKind.UP) - -val SkikoPointerEvent.isRightClick: Boolean - get() = button.has(SkikoMouseButtons.RIGHT) && (kind == SkikoPointerEventKind.UP) - -val SkikoPointerEvent.isMiddleClick: Boolean - get() = button.has(SkikoMouseButtons.MIDDLE) && (kind == SkikoPointerEventKind.UP) - -/** - * The device type that produces pointer events, such as a mouse or stylus. - */ -enum class SkikoPointerDevice { - UNKNOWN, MOUSE, TOUCH -} - -/** - * Represents pointer such as mouse cursor, or touch/stylus press. - * There can be multiple pointers on the screen at the same time. - */ -data class SkikoPointer( - /** - * Unique id associated with the pointer. Used to distinguish between multiple pointers that can exist - * at the same time (i.e. multiple pressed touches). - * - * If there is only on pointer in the system (for example, one mouse), it should always - * have the same id across multiple events. - */ - val id: Long, - - /** - * X position in points (scaled pixels that depend on the scale factor of the current display) - */ - val x: Double, - /** - * Y position in points (scaled pixels that depend on the scale factor of the current display) - */ - val y: Double, - - /** - * `true` if the pointer event is considered "pressed." For example, finger - * touching the screen or a mouse button is pressed [pressed] would be `true`. - * During the up event, pointer is considered not pressed. - */ - val pressed: Boolean, - - /** - * The device type associated with the pointer, such as [mouse][SkikoPointerDevice.MOUSE], - * or [touch][SkikoPointerDevice.TOUCH]. - */ - val device: SkikoPointerDevice = SkikoPointerDevice.MOUSE, - - /** - * Pressure of the pointer. 0.0 - no pressure, 1.0 - average pressure - */ - val pressure: Double = 1.0, -) - -internal val Iterable.centroidX get() = asSequence().map { it.x }.average() -internal val Iterable.centroidY get() = asSequence().map { it.y }.average() \ No newline at end of file diff --git a/skiko/src/commonMain/kotlin/org/jetbrains/skiko/SkiaLayer.kt b/skiko/src/commonMain/kotlin/org/jetbrains/skiko/SkiaLayer.kt index a3ebc2199..b972199c2 100644 --- a/skiko/src/commonMain/kotlin/org/jetbrains/skiko/SkiaLayer.kt +++ b/skiko/src/commonMain/kotlin/org/jetbrains/skiko/SkiaLayer.kt @@ -41,16 +41,16 @@ expect open class SkiaLayer { /** * Current view used for rendering. */ - var skikoView: SkikoView? + var renderDelegate: SkikoRenderDelegate? /** - * Attach this SkikoView to platform container. + * Attach this [SkikoRenderDelegate] to platform container. * Actual type of attach container is platform-specific. */ fun attachTo(container: Any) /** - * Detach this SkikoView from platform container. + * Detach this [SkikoRenderDelegate] from platform container. */ fun detach() diff --git a/skiko/src/commonMain/kotlin/org/jetbrains/skiko/SkikoInput.common.kt b/skiko/src/commonMain/kotlin/org/jetbrains/skiko/SkikoInput.common.kt deleted file mode 100644 index c0f4f792d..000000000 --- a/skiko/src/commonMain/kotlin/org/jetbrains/skiko/SkikoInput.common.kt +++ /dev/null @@ -1,5 +0,0 @@ -package org.jetbrains.skiko - -expect interface SkikoInput { - object Empty : SkikoInput -} diff --git a/skiko/src/commonMain/kotlin/org/jetbrains/skiko/SkikoKey.common.kt b/skiko/src/commonMain/kotlin/org/jetbrains/skiko/SkikoKey.common.kt deleted file mode 100644 index 702380458..000000000 --- a/skiko/src/commonMain/kotlin/org/jetbrains/skiko/SkikoKey.common.kt +++ /dev/null @@ -1,111 +0,0 @@ -package org.jetbrains.skiko - -expect enum class SkikoKey { - KEY_UNKNOWN, - KEY_A, - KEY_S, - KEY_D, - KEY_F, - KEY_H, - KEY_G, - KEY_Z, - KEY_X, - KEY_C, - KEY_V, - KEY_B, - KEY_Q, - KEY_W, - KEY_E, - KEY_R, - KEY_Y, - KEY_T, - KEY_U, - KEY_I, - KEY_P, - KEY_L, - KEY_J, - KEY_K, - KEY_N, - KEY_M, - KEY_O, - KEY_1, - KEY_2, - KEY_3, - KEY_4, - KEY_5, - KEY_6, - KEY_7, - KEY_8, - KEY_9, - KEY_0, - KEY_CLOSE_BRACKET, - KEY_OPEN_BRACKET, - KEY_QUOTE, - KEY_SEMICOLON, - KEY_SLASH, - KEY_COMMA, - KEY_BACKSLASH, - KEY_PERIOD, - KEY_BACK_QUOTE, - KEY_EQUALS, - KEY_MINUS, - KEY_ENTER, - KEY_ESCAPE, - KEY_TAB, - KEY_BACKSPACE, - KEY_SPACE, - KEY_CAPSLOCK, - KEY_LEFT_META, - KEY_LEFT_SHIFT, - KEY_LEFT_ALT, - KEY_LEFT_CONTROL, - KEY_RIGHT_META, - KEY_RIGHT_SHIFT, - KEY_RIGHT_ALT, - KEY_RIGHT_CONTROL, - KEY_MENU, - KEY_UP, - KEY_DOWN, - KEY_LEFT, - KEY_RIGHT, - KEY_F1, - KEY_F2, - KEY_F3, - KEY_F4, - KEY_F5, - KEY_F6, - KEY_F7, - KEY_F8, - KEY_F9, - KEY_F10, - KEY_F11, - KEY_F12, - KEY_PRINTSCEEN, - KEY_SCROLL_LOCK, - KEY_PAUSE, - KEY_INSERT, - KEY_HOME, - KEY_PGUP, - KEY_DELETE, - KEY_END, - KEY_PGDOWN, - KEY_NUM_LOCK, - KEY_NUMPAD_0, - KEY_NUMPAD_1, - KEY_NUMPAD_2, - KEY_NUMPAD_3, - KEY_NUMPAD_4, - KEY_NUMPAD_5, - KEY_NUMPAD_6, - KEY_NUMPAD_7, - KEY_NUMPAD_8, - KEY_NUMPAD_9, - KEY_NUMPAD_ENTER, - KEY_NUMPAD_ADD, - KEY_NUMPAD_SUBTRACT, - KEY_NUMPAD_MULTIPLY, - KEY_NUMPAD_DIVIDE, - KEY_NUMPAD_DECIMAL; - - val platformKeyCode: Int -} diff --git a/skiko/src/commonMain/kotlin/org/jetbrains/skiko/SkikoRenderDelegate.kt b/skiko/src/commonMain/kotlin/org/jetbrains/skiko/SkikoRenderDelegate.kt new file mode 100644 index 000000000..fad0b21cf --- /dev/null +++ b/skiko/src/commonMain/kotlin/org/jetbrains/skiko/SkikoRenderDelegate.kt @@ -0,0 +1,20 @@ +package org.jetbrains.skiko + +import org.jetbrains.skia.Canvas + +interface SkikoRenderDelegate { + fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) +} + +open class SkiaLayerRenderDelegate( + val layer: SkiaLayer, + val renderDelegate: SkikoRenderDelegate +): SkikoRenderDelegate { + override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) { + val contentScale = layer.contentScale + canvas.scale(contentScale, contentScale) + renderDelegate.onRender(canvas, (width / contentScale).toInt(), (height / contentScale).toInt(), nanoTime) + // Request next frame immediately. + layer.needRedraw() + } +} diff --git a/skiko/src/commonMain/kotlin/org/jetbrains/skiko/SkikoView.kt b/skiko/src/commonMain/kotlin/org/jetbrains/skiko/SkikoView.kt index 89347cc89..84b210e71 100644 --- a/skiko/src/commonMain/kotlin/org/jetbrains/skiko/SkikoView.kt +++ b/skiko/src/commonMain/kotlin/org/jetbrains/skiko/SkikoView.kt @@ -1,49 +1,13 @@ package org.jetbrains.skiko -import org.jetbrains.skia.Canvas - -interface SkikoView { - // Input - fun onKeyboardEvent(event: SkikoKeyboardEvent) = Unit - fun onPointerEvent(event: SkikoPointerEvent) = Unit - - @Deprecated("This method will be removed. Use override val input: SkikoInput") - fun onInputEvent(event: SkikoInputEvent) = Unit - val input: SkikoInput get() = SkikoInput.Empty - fun onGestureEvent(event: SkikoGestureEvent) = Unit - - // Rendering - fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) -} - -open class GenericSkikoView( - val layer: SkiaLayer, - val app: SkikoView - ): SkikoView { - - override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) { - val contentScale = layer.contentScale - canvas.scale(contentScale, contentScale) - app.onRender(canvas, (width / contentScale).toInt(), (height / contentScale).toInt(), nanoTime) - // Request next frame immediately. - layer.needRedraw() - } - - override fun onInputEvent(event: SkikoInputEvent) { - app.onInputEvent(event) - } - - override val input: SkikoInput get() = app.input - - override fun onKeyboardEvent(event: SkikoKeyboardEvent) { - app.onKeyboardEvent(event) - } - - override fun onPointerEvent(event: SkikoPointerEvent) { - app.onPointerEvent(event) - } - - override fun onGestureEvent(event: SkikoGestureEvent) { - app.onGestureEvent(event) - } -} +@Deprecated( + message = "Replaced with SkikoRenderDelegate", + replaceWith = ReplaceWith("SkikoRenderDelegate") +) +typealias SkikoView = SkikoRenderDelegate + +@Deprecated( + message = "Replaced with SkiaLayerRenderDelegate", + replaceWith = ReplaceWith("SkiaLayerRenderDelegate") +) +typealias GenericSkikoView = SkiaLayerRenderDelegate diff --git a/skiko/src/iosMain/kotlin/org/jetbrains/skiko/Convertors.ios.kt b/skiko/src/iosMain/kotlin/org/jetbrains/skiko/Convertors.ios.kt deleted file mode 100644 index 5e334e198..000000000 --- a/skiko/src/iosMain/kotlin/org/jetbrains/skiko/Convertors.ios.kt +++ /dev/null @@ -1,67 +0,0 @@ -package org.jetbrains.skiko - -import platform.UIKit.* - -fun toSkikoGestureDirection(direction: UISwipeGestureRecognizerDirection) : SkikoGestureEventDirection { - return when(direction) { - UISwipeGestureRecognizerDirectionUp -> SkikoGestureEventDirection.UP - UISwipeGestureRecognizerDirectionDown -> SkikoGestureEventDirection.DOWN - UISwipeGestureRecognizerDirectionLeft -> SkikoGestureEventDirection.LEFT - UISwipeGestureRecognizerDirectionRight -> SkikoGestureEventDirection.RIGHT - else -> SkikoGestureEventDirection.UNKNOWN - } -} - -fun toSkikoGestureState(state: UIGestureRecognizerState ) : SkikoGestureEventState { - return when(state) { - UIGestureRecognizerStatePossible -> SkikoGestureEventState.PRESSED - UIGestureRecognizerStateBegan -> SkikoGestureEventState.STARTED - UIGestureRecognizerStateChanged -> SkikoGestureEventState.CHANGED - UIGestureRecognizerStateEnded -> SkikoGestureEventState.ENDED - else -> SkikoGestureEventState.UNKNOWN - } -} - -fun toSkikoTypeEvent(character: String, event: UIPress?): SkikoInputEvent { - val key = if (event != null) SkikoKey.valueOf(event.key!!.keyCode) else SkikoKey.KEY_UNKNOWN - val modifiers = if (event != null) toSkikoModifiers(event) else SkikoInputModifiers.EMPTY - return SkikoInputEvent( - character, - key, - modifiers, - SkikoKeyboardEventKind.TYPE, - event - ) -} - -fun toSkikoKeyboardEvent( - event: UIPress, - kind: SkikoKeyboardEventKind -): SkikoKeyboardEvent { - val timestamp = (event.timestamp * 1_000).toLong() - return SkikoKeyboardEvent( - SkikoKey.valueOf(event.key!!.keyCode), - toSkikoModifiers(event), - kind, - timestamp, - event - ) -} - -private fun toSkikoModifiers(event: UIPress): SkikoInputModifiers { - var result = 0 - val modifiers = event.key!!.modifierFlags - if (modifiers and UIKeyModifierAlternate != 0L) { - result = result.or(SkikoInputModifiers.ALT.value) - } - if (modifiers and UIKeyModifierShift != 0L) { - result = result.or(SkikoInputModifiers.SHIFT.value) - } - if (modifiers and UIKeyModifierControl != 0L) { - result = result.or(SkikoInputModifiers.CONTROL.value) - } - if (modifiers and UIKeyModifierCommand != 0L) { - result = result.or(SkikoInputModifiers.META.value) - } - return SkikoInputModifiers(result) -} diff --git a/skiko/src/iosMain/kotlin/org/jetbrains/skiko/SkiaLayer.ios.kt b/skiko/src/iosMain/kotlin/org/jetbrains/skiko/SkiaLayer.ios.kt index 8daba372b..20a5d5cc1 100644 --- a/skiko/src/iosMain/kotlin/org/jetbrains/skiko/SkiaLayer.ios.kt +++ b/skiko/src/iosMain/kotlin/org/jetbrains/skiko/SkiaLayer.ios.kt @@ -53,25 +53,19 @@ actual open class SkiaLayer { // GC bug? fixes leak on iOS view = null - skikoView = null + renderDelegate = null } - actual var skikoView: SkikoView? = null + actual var renderDelegate: SkikoRenderDelegate? = null internal actual fun draw(canvas: Canvas) { throw UnsupportedOperationException("Don't call it, artifact of wrong abstraction") } internal fun draw(surface: Surface) { - skikoView?.onRender(surface.canvas, surface.width, surface.height, getTimeNanos()) + renderDelegate?.onRender(surface.canvas, surface.width, surface.height, getTimeNanos()) } actual val pixelGeometry: PixelGeometry get() = PixelGeometry.UNKNOWN } - -// TODO: do properly -actual typealias SkikoGesturePlatformEvent = UIEvent -actual typealias SkikoPlatformInputEvent = UIPress -actual typealias SkikoPlatformKeyboardEvent = UIPress -actual typealias SkikoPlatformPointerEvent = UIEvent diff --git a/skiko/src/iosMain/kotlin/org/jetbrains/skiko/SkikoInput.ios.kt b/skiko/src/iosMain/kotlin/org/jetbrains/skiko/SkikoInput.ios.kt deleted file mode 100644 index ad533e8b3..000000000 --- a/skiko/src/iosMain/kotlin/org/jetbrains/skiko/SkikoInput.ios.kt +++ /dev/null @@ -1,104 +0,0 @@ -package org.jetbrains.skiko - -actual interface SkikoInput { - - /** - * A Boolean value that indicates whether the text-entry object has any text. - * https://developer.apple.com/documentation/uikit/uikeyinput/1614457-hastext - */ - fun hasText(): Boolean - - /** - * Inserts a character into the displayed text. - * Add the character text to your class’s backing store at the index corresponding to the cursor and redisplay the text. - * https://developer.apple.com/documentation/uikit/uikeyinput/1614543-inserttext - * @param text A string object representing the character typed on the system keyboard. - */ - fun insertText(text: String) - - /** - * Deletes a character from the displayed text. - * Remove the character just before the cursor from your class’s backing store and redisplay the text. - * https://developer.apple.com/documentation/uikit/uikeyinput/1614572-deletebackward - */ - fun deleteBackward() - - /** - * The text position for the end of a document. - * https://developer.apple.com/documentation/uikit/uitextinput/1614555-endofdocument - */ - fun endOfDocument(): Long - - /** - * The range of selected text in a document. - * If the text range has a length, it indicates the currently selected text. - * If it has zero length, it indicates the caret (insertion point). - * If the text-range object is nil, it indicates that there is no current selection. - * https://developer.apple.com/documentation/uikit/uitextinput/1614541-selectedtextrange - */ - fun getSelectedTextRange(): IntRange? - - fun setSelectedTextRange(range: IntRange?) - - fun selectAll() - - /** - * Returns the text in the specified range. - * https://developer.apple.com/documentation/uikit/uitextinput/1614527-text - * @param range A range of text in a document. - * @return A substring of a document that falls within the specified range. - */ - fun textInRange(range: IntRange): String - - /** - * Replaces the text in a document that is in the specified range. - * https://developer.apple.com/documentation/uikit/uitextinput/1614558-replace - * @param range A range of text in a document. - * @param text A string to replace the text in range. - */ - fun replaceRange(range: IntRange, text: String) - - /** - * Inserts the provided text and marks it to indicate that it is part of an active input session. - * Setting marked text either replaces the existing marked text or, - * if none is present, inserts it in place of the current selection. - * https://developer.apple.com/documentation/uikit/uitextinput/1614465-setmarkedtext - * @param markedText The text to be marked. - * @param selectedRange A range within markedText that indicates the current selection. - * This range is always relative to markedText. - */ - fun setMarkedText(markedText: String?, selectedRange: IntRange) - - /** - * The range of currently marked text in a document. - * If there is no marked text, the value of the property is nil. - * Marked text is provisionally inserted text that requires user confirmation; - * it occurs in multistage text input. - * The current selection, which can be a caret or an extended range, always occurs within the marked text. - * https://developer.apple.com/documentation/uikit/uitextinput/1614489-markedtextrange - */ - fun markedTextRange(): IntRange? - - /** - * Unmarks the currently marked text. - * After this method is called, the value of markedTextRange is nil. - * https://developer.apple.com/documentation/uikit/uitextinput/1614512-unmarktext - */ - fun unmarkText() - - actual object Empty : SkikoInput { - override fun hasText(): Boolean = false - override fun insertText(text: String) = Unit - override fun deleteBackward() = Unit - override fun endOfDocument(): Long = 0L - override fun getSelectedTextRange(): IntRange? = null - override fun setSelectedTextRange(range: IntRange?) = Unit - override fun selectAll() = Unit - override fun textInRange(range: IntRange): String = "" - override fun replaceRange(range: IntRange, text: String) = Unit - override fun setMarkedText(markedText: String?, selectedRange: IntRange) = Unit - override fun markedTextRange(): IntRange? = null - override fun unmarkText() = Unit - } - -} diff --git a/skiko/src/iosMain/kotlin/org/jetbrains/skiko/SkikoKey.ios.kt b/skiko/src/iosMain/kotlin/org/jetbrains/skiko/SkikoKey.ios.kt deleted file mode 100644 index f4f3e7a04..000000000 --- a/skiko/src/iosMain/kotlin/org/jetbrains/skiko/SkikoKey.ios.kt +++ /dev/null @@ -1,129 +0,0 @@ -package org.jetbrains.skiko - -import platform.UIKit.* - -actual enum class SkikoKey(val value: UIKeyboardHIDUsage) { - KEY_UNKNOWN(-1), - KEY_A(UIKeyboardHIDUsageKeyboardA), - KEY_S(UIKeyboardHIDUsageKeyboardS), - KEY_D(UIKeyboardHIDUsageKeyboardD), - KEY_F(UIKeyboardHIDUsageKeyboardF), - KEY_H(UIKeyboardHIDUsageKeyboardH), - KEY_G(UIKeyboardHIDUsageKeyboardG), - KEY_Z(UIKeyboardHIDUsageKeyboardZ), - KEY_X(UIKeyboardHIDUsageKeyboardX), - KEY_C(UIKeyboardHIDUsageKeyboardC), - KEY_V(UIKeyboardHIDUsageKeyboardV), - KEY_B(UIKeyboardHIDUsageKeyboardB), - KEY_Q(UIKeyboardHIDUsageKeyboardQ), - KEY_W(UIKeyboardHIDUsageKeyboardW), - KEY_E(UIKeyboardHIDUsageKeyboardE), - KEY_R(UIKeyboardHIDUsageKeyboardR), - KEY_Y(UIKeyboardHIDUsageKeyboardY), - KEY_T(UIKeyboardHIDUsageKeyboardT), - KEY_U(UIKeyboardHIDUsageKeyboardU), - KEY_I(UIKeyboardHIDUsageKeyboardI), - KEY_P(UIKeyboardHIDUsageKeyboardP), - KEY_L(UIKeyboardHIDUsageKeyboardL), - KEY_J(UIKeyboardHIDUsageKeyboardJ), - KEY_K(UIKeyboardHIDUsageKeyboardK), - KEY_N(UIKeyboardHIDUsageKeyboardN), - KEY_M(UIKeyboardHIDUsageKeyboardM), - KEY_O(UIKeyboardHIDUsageKeyboardO), - KEY_1(UIKeyboardHIDUsageKeyboard1), - KEY_2(UIKeyboardHIDUsageKeyboard2), - KEY_3(UIKeyboardHIDUsageKeyboard3), - KEY_4(UIKeyboardHIDUsageKeyboard4), - KEY_5(UIKeyboardHIDUsageKeyboard5), - KEY_6(UIKeyboardHIDUsageKeyboard6), - KEY_7(UIKeyboardHIDUsageKeyboard7), - KEY_8(UIKeyboardHIDUsageKeyboard8), - KEY_9(UIKeyboardHIDUsageKeyboard9), - KEY_0(UIKeyboardHIDUsageKeyboard0), - KEY_CLOSE_BRACKET(UIKeyboardHIDUsageKeyboardCloseBracket), - KEY_OPEN_BRACKET(UIKeyboardHIDUsageKeyboardOpenBracket), - KEY_QUOTE(UIKeyboardHIDUsageKeyboardQuote), - KEY_SEMICOLON(UIKeyboardHIDUsageKeyboardSemicolon), - KEY_SLASH(UIKeyboardHIDUsageKeyboardSlash), - KEY_COMMA(UIKeyboardHIDUsageKeyboardComma), - KEY_BACKSLASH(UIKeyboardHIDUsageKeyboardBackslash), - KEY_PERIOD(UIKeyboardHIDUsageKeyboardPeriod), - KEY_BACK_QUOTE(53), - KEY_EQUALS(UIKeyboardHIDUsageKeyboardEqualSign), - KEY_MINUS(UIKeyboardHIDUsageKeyboardHyphen), - KEY_ENTER(40), - KEY_ESCAPE(UIKeyboardHIDUsageKeyboardEscape), - KEY_TAB(UIKeyboardHIDUsageKeyboardTab), - KEY_BACKSPACE(UIKeyboardHIDUsageKeyboardDeleteOrBackspace), - KEY_SPACE(UIKeyboardHIDUsageKeyboardSpacebar), - KEY_CAPSLOCK(UIKeyboardHIDUsageKeyboardCapsLock), - KEY_LEFT_META(227), - KEY_LEFT_SHIFT(UIKeyboardHIDUsageKeyboardLeftShift), - KEY_LEFT_ALT(UIKeyboardHIDUsageKeyboardLeftAlt), - KEY_LEFT_CONTROL(UIKeyboardHIDUsageKeyboardLeftControl), - KEY_RIGHT_META(231), - KEY_RIGHT_SHIFT(UIKeyboardHIDUsageKeyboardRightShift), - KEY_RIGHT_ALT(UIKeyboardHIDUsageKeyboardRightAlt), - KEY_RIGHT_CONTROL(UIKeyboardHIDUsageKeyboardRightControl), - KEY_MENU(101), - KEY_UP(UIKeyboardHIDUsageKeyboardUpArrow), - KEY_DOWN(UIKeyboardHIDUsageKeyboardDownArrow), - KEY_LEFT(UIKeyboardHIDUsageKeyboardLeftArrow), - KEY_RIGHT(UIKeyboardHIDUsageKeyboardRightArrow), - KEY_F1(UIKeyboardHIDUsageKeyboardF1), - KEY_F2(UIKeyboardHIDUsageKeyboardF2), - KEY_F3(UIKeyboardHIDUsageKeyboardF3), - KEY_F4(UIKeyboardHIDUsageKeyboardF4), - KEY_F5(UIKeyboardHIDUsageKeyboardF5), - KEY_F6(UIKeyboardHIDUsageKeyboardF6), - KEY_F7(UIKeyboardHIDUsageKeyboardF7), - KEY_F8(UIKeyboardHIDUsageKeyboardF8), - KEY_F9(UIKeyboardHIDUsageKeyboardF9), - KEY_F10(UIKeyboardHIDUsageKeyboardF10), - KEY_F11(UIKeyboardHIDUsageKeyboardF11), - KEY_F12(UIKeyboardHIDUsageKeyboardF12), - KEY_PRINTSCEEN(104), - KEY_SCROLL_LOCK(UIKeyboardHIDUsageKeyboardScrollLock), - KEY_PAUSE(UIKeyboardHIDUsageKeyboardPause), - KEY_INSERT(117), - KEY_HOME(UIKeyboardHIDUsageKeyboardHome), - KEY_PGUP(UIKeyboardHIDUsageKeyboardPageUp), - KEY_DELETE(UIKeyboardHIDUsageKeyboardDeleteForward), - KEY_END(UIKeyboardHIDUsageKeyboardEnd), - KEY_PGDOWN(UIKeyboardHIDUsageKeyboardPageDown), - KEY_NUM_LOCK(UIKeyboardHIDUsageKeypadNumLock), - KEY_NUMPAD_0(UIKeyboardHIDUsageKeypad0), - KEY_NUMPAD_1(UIKeyboardHIDUsageKeypad1), - KEY_NUMPAD_2(90), - KEY_NUMPAD_3(UIKeyboardHIDUsageKeypad3), - KEY_NUMPAD_4(92), - KEY_NUMPAD_5(UIKeyboardHIDUsageKeypad5), - KEY_NUMPAD_6(94), - KEY_NUMPAD_7(UIKeyboardHIDUsageKeypad7), - KEY_NUMPAD_8(96), - KEY_NUMPAD_9(UIKeyboardHIDUsageKeypad9), - KEY_NUMPAD_ENTER(UIKeyboardHIDUsageKeypadEnter), - KEY_NUMPAD_ADD(87), - KEY_NUMPAD_SUBTRACT(86), - KEY_NUMPAD_MULTIPLY(UIKeyboardHIDUsageKeypadAsterisk), - KEY_NUMPAD_DIVIDE(UIKeyboardHIDUsageKeypadSlash), - KEY_NUMPAD_DECIMAL(99); - - init { - if (value > Int.MAX_VALUE) { - error("iOS SkikoKey, init value = $value > Int.MAX_VALUE") - } - } - - actual val platformKeyCode get() = value.toInt() - - companion object { - fun valueOf(value: UIKeyboardHIDUsage): SkikoKey { - if (value > Int.MAX_VALUE) { - error("iOS SkikoKey, valueOf value = $value > Int.MAX_VALUE") - } - val key = SkikoKey.values().firstOrNull { it.value == value } - return key ?: SkikoKey.KEY_UNKNOWN - } - } -} diff --git a/skiko/src/iosMain/kotlin/org/jetbrains/skiko/SkikoUIView.kt b/skiko/src/iosMain/kotlin/org/jetbrains/skiko/SkikoUIView.kt index 77290e749..8ff5167b3 100644 --- a/skiko/src/iosMain/kotlin/org/jetbrains/skiko/SkikoUIView.kt +++ b/skiko/src/iosMain/kotlin/org/jetbrains/skiko/SkikoUIView.kt @@ -19,7 +19,7 @@ import kotlin.native.ref.WeakReference @Suppress("CONFLICTING_OVERLOADS") @ExportObjCClass -class SkikoUIView : UIView, UIKeyInputProtocol, UITextInputProtocol { +class SkikoUIView : UIView { companion object : UIViewMeta() { override fun layerClass() = CAMetalLayer } @@ -34,25 +34,8 @@ class SkikoUIView : UIView, UIKeyInputProtocol, UITextInputProtocol { MTLCreateSystemDefaultDevice() ?: throw IllegalStateException("Metal is not supported on this system") private val _metalLayer: CAMetalLayer get() = layer as CAMetalLayer private var _skiaLayer: SkiaLayer? = null - private var _pointInside: (Point, UIEvent?) -> Boolean = { _, _ -> true } - private var _skikoUITextInputTrains: SkikoUITextInputTraits = object : SkikoUITextInputTraits {} - private var _inputDelegate: UITextInputDelegateProtocol? = null - private var _currentTextMenuActions: TextActions? = null private lateinit var _redrawer: MetalRedrawer - /* - * When there at least one tracked touch, we need notify redrawer about it. It should schedule CADisplayLink which - * affects frequency of polling UITouch events on high frequency display and forces it to match display refresh rate. - */ - private var _touchesCount = 0 - set(value) { - field = value - - val needHighFrequencyPolling = value > 0 - - _redrawer.needsProactiveDisplayLink = needHighFrequencyPolling - } - init { multipleTouchEnabled = true opaque = false // For UIKit interop through a "Hole" @@ -71,26 +54,12 @@ class SkikoUIView : UIView, UIKeyInputProtocol, UITextInputProtocol { } } - // merging two constructors might cause a binary incompatibility, which will result in a unclear linking error, - // if a project using newer compose depends on an older compose transitively - // https://youtrack.jetbrains.com/issue/KT-60399 - @Suppress("UNUSED") // public API - constructor( - skiaLayer: SkiaLayer, - frame: CValue = CGRectNull.readValue(), - pointInside: (Point, UIEvent?) -> Boolean = { _, _ -> true } - ) : this(skiaLayer, frame, pointInside, skikoUITextInputTrains = object : SkikoUITextInputTraits {}) - @OptIn(kotlin.experimental.ExperimentalNativeApi::class) constructor( skiaLayer: SkiaLayer, - frame: CValue = CGRectNull.readValue(), - pointInside: (Point, UIEvent?) -> Boolean = { _, _ -> true }, - skikoUITextInputTrains: SkikoUITextInputTraits + frame: CValue = CGRectNull.readValue() ) : super(frame) { _skiaLayer = skiaLayer - _pointInside = pointInside - _skikoUITextInputTrains = skikoUITextInputTrains val weakSkiaLayer = WeakReference(skiaLayer) @@ -105,60 +74,6 @@ class SkikoUIView : UIView, UIKeyInputProtocol, UITextInputProtocol { skiaLayer.view = this } - /** - * Show copy/paste text menu - * @param targetRect - rectangle of selected text area - * @param textActions - available (not null) actions in text menu - */ - fun showTextMenu(targetRect: Rect, textActions: TextActions) { - _currentTextMenuActions = textActions - val menu: UIMenuController = UIMenuController.sharedMenuController() - val cgRect = CGRectMake( - x = targetRect.left.toDouble(), - y = targetRect.top.toDouble(), - width = targetRect.width.toDouble(), - height = targetRect.height.toDouble() - ) - val isTargetVisible = CGRectIntersectsRect(bounds, cgRect) - if (isTargetVisible) { - if (menu.isMenuVisible()) { - menu.setTargetRect(cgRect, this) - } else { - menu.showMenuFromView(this, cgRect) - } - } else { - if (menu.isMenuVisible()) { - menu.hideMenu() - } - } - } - - fun hideTextMenu() { - _currentTextMenuActions = null - val menu: UIMenuController = UIMenuController.sharedMenuController() - menu.hideMenu() - } - - fun isTextMenuShown(): Boolean { - return _currentTextMenuActions != null - } - - override fun copy(sender: Any?) { - _currentTextMenuActions?.copy?.invoke() - } - - override fun paste(sender: Any?) { - _currentTextMenuActions?.paste?.invoke() - } - - override fun cut(sender: Any?) { - _currentTextMenuActions?.cut?.invoke() - } - - override fun selectAll(sender: Any?) { - _currentTextMenuActions?.selectAll?.invoke() - } - internal fun detach() { _redrawer.dispose() } @@ -186,448 +101,4 @@ class SkikoUIView : UIView, UIKeyInputProtocol, UITextInputProtocol { _metalLayer.drawableSize = scaledSize } - - fun showScreenKeyboard() = becomeFirstResponder() - fun hideScreenKeyboard() = resignFirstResponder() - fun isScreenKeyboardOpen() = isFirstResponder - - /** - * A Boolean value that indicates whether the text-entry object has any text. - * https://developer.apple.com/documentation/uikit/uikeyinput/1614457-hastext - */ - override fun hasText(): Boolean { - return _skiaLayer?.skikoView?.input?.hasText() ?: false - } - - /** - * Inserts a character into the displayed text. - * Add the character text to your class’s backing store at the index corresponding to the cursor and redisplay the text. - * https://developer.apple.com/documentation/uikit/uikeyinput/1614543-inserttext - * @param text A string object representing the character typed on the system keyboard. - */ - override fun insertText(text: String) { - _skiaLayer?.skikoView?.input?.insertText(text) - } - - /** - * Deletes a character from the displayed text. - * Remove the character just before the cursor from your class’s backing store and redisplay the text. - * https://developer.apple.com/documentation/uikit/uikeyinput/1614572-deletebackward - */ - override fun deleteBackward() { - _skiaLayer?.skikoView?.input?.deleteBackward() - } - - override fun canBecomeFirstResponder() = true - - override fun pressesBegan(presses: Set<*>, withEvent: UIPressesEvent?) { - if (withEvent != null) { - for (press in withEvent.allPresses) { - val uiPress = press as? UIPress - if (uiPress != null) { - _skiaLayer?.skikoView?.onKeyboardEvent( - toSkikoKeyboardEvent(press, SkikoKeyboardEventKind.DOWN) - ) - } - } - } - super.pressesBegan(presses, withEvent) - } - - override fun pressesEnded(presses: Set<*>, withEvent: UIPressesEvent?) { - if (withEvent != null) { - for (press in withEvent.allPresses) { - val uiPress = press as? UIPress - if (uiPress != null) { - _skiaLayer?.skikoView?.onKeyboardEvent( - toSkikoKeyboardEvent(press, SkikoKeyboardEventKind.UP) - ) - } - } - } - super.pressesEnded(presses, withEvent) - } - - /** - * https://developer.apple.com/documentation/uikit/uiview/1622533-point - */ - override fun pointInside(point: CValue, withEvent: UIEvent?): Boolean { - val skiaPoint: Point = point.useContents { Point(x.toFloat(), y.toFloat()) } - return _pointInside(skiaPoint, withEvent) - } - - override fun touchesBegan(touches: Set<*>, withEvent: UIEvent?) { - super.touchesBegan(touches, withEvent) - - _touchesCount += touches.size - - sendTouchEventToSkikoView(withEvent!!, SkikoPointerEventKind.DOWN) - } - - override fun touchesEnded(touches: Set<*>, withEvent: UIEvent?) { - super.touchesEnded(touches, withEvent) - - _touchesCount -= touches.size - - sendTouchEventToSkikoView(withEvent!!, SkikoPointerEventKind.UP) - } - - override fun touchesMoved(touches: Set<*>, withEvent: UIEvent?) { - super.touchesMoved(touches, withEvent) - sendTouchEventToSkikoView(withEvent!!, SkikoPointerEventKind.MOVE) - } - - override fun touchesCancelled(touches: Set<*>, withEvent: UIEvent?) { - super.touchesCancelled(touches, withEvent) - - _touchesCount -= touches.size - - sendTouchEventToSkikoView(withEvent!!, SkikoPointerEventKind.UP) - } - - private fun sendTouchEventToSkikoView(event: UIEvent, kind: SkikoPointerEventKind) { - val pointers = event.touchesForView(this).orEmpty().map { - val touch = it as UITouch - val (x, y) = touch.locationInView(this).useContents { x to y } - SkikoPointer( - x = x, - y = y, - pressed = touch.isPressed, - device = SkikoPointerDevice.TOUCH, - id = touch.hashCode().toLong(), - pressure = touch.force - ) - } - - _skiaLayer?.skikoView?.onPointerEvent( - SkikoPointerEvent( - x = pointers.centroidX, - y = pointers.centroidY, - kind = kind, - timestamp = (event.timestamp * 1_000).toLong(), - pointers = pointers, - platform = event - ) - ) - } - - override fun inputDelegate(): UITextInputDelegateProtocol? { - return _inputDelegate - } - - override fun setInputDelegate(inputDelegate: UITextInputDelegateProtocol?) { - _inputDelegate = inputDelegate - } - - /** - * Returns the text in the specified range. - * https://developer.apple.com/documentation/uikit/uitextinput/1614527-text - * @param range A range of text in a document. - * @return A substring of a document that falls within the specified range. - */ - override fun textInRange(range: UITextRange): String? { - return _skiaLayer?.skikoView?.input?.textInRange(range.toIntRange()) - } - - /** - * Replaces the text in a document that is in the specified range. - * https://developer.apple.com/documentation/uikit/uitextinput/1614558-replace - * @param range A range of text in a document. - * @param withText A string to replace the text in range. - */ - override fun replaceRange(range: UITextRange, withText: String) { - _skiaLayer?.skikoView?.input?.replaceRange(range.toIntRange(), withText) - } - - override fun setSelectedTextRange(selectedTextRange: UITextRange?) { - _skiaLayer?.skikoView?.input?.setSelectedTextRange(selectedTextRange?.toIntRange()) - } - - /** - * The range of selected text in a document. - * If the text range has a length, it indicates the currently selected text. - * If it has zero length, it indicates the caret (insertion point). - * If the text-range object is nil, it indicates that there is no current selection. - * https://developer.apple.com/documentation/uikit/uitextinput/1614541-selectedtextrange - */ - override fun selectedTextRange(): UITextRange? { - return _skiaLayer?.skikoView?.input?.getSelectedTextRange()?.toUITextRange() - } - - /** - * The range of currently marked text in a document. - * If there is no marked text, the value of the property is nil. - * Marked text is provisionally inserted text that requires user confirmation; - * it occurs in multistage text input. - * The current selection, which can be a caret or an extended range, always occurs within the marked text. - * https://developer.apple.com/documentation/uikit/uitextinput/1614489-markedtextrange - */ - override fun markedTextRange(): UITextRange? { - return _skiaLayer?.skikoView?.input?.markedTextRange()?.toUITextRange() - } - - override fun setMarkedTextStyle(markedTextStyle: Map?) { - // do nothing - } - - override fun markedTextStyle(): Map? { - return null - } - - /** - * Inserts the provided text and marks it to indicate that it is part of an active input session. - * Setting marked text either replaces the existing marked text or, - * if none is present, inserts it in place of the current selection. - * https://developer.apple.com/documentation/uikit/uitextinput/1614465-setmarkedtext - * @param markedText The text to be marked. - * @param selectedRange A range within markedText that indicates the current selection. - * This range is always relative to markedText. - */ - override fun setMarkedText(markedText: String?, selectedRange: CValue) { - val (locationRelative, lengthRelative) = selectedRange.useContents { - location.toInt() to length.toInt() - } - val relativeTextRange = locationRelative until locationRelative + lengthRelative - _skiaLayer?.skikoView?.input?.setMarkedText(markedText, relativeTextRange) - } - - /** - * Unmarks the currently marked text. - * After this method is called, the value of markedTextRange is nil. - * https://developer.apple.com/documentation/uikit/uitextinput/1614512-unmarktext - */ - override fun unmarkText() { - _skiaLayer?.skikoView?.input?.unmarkText() - } - - override fun beginningOfDocument(): UITextPosition { - return IntermediateTextPosition(0) - } - - /** - * The text position for the end of a document. - * https://developer.apple.com/documentation/uikit/uitextinput/1614555-endofdocument - */ - override fun endOfDocument(): UITextPosition { - return IntermediateTextPosition(_skiaLayer?.skikoView?.input?.endOfDocument() ?: 0) - } - - /** - * Attention! fromPosition and toPosition may be null - */ - override fun textRangeFromPosition(fromPosition: UITextPosition, toPosition: UITextPosition): UITextRange? { - val from = (fromPosition as? IntermediateTextPosition)?.position ?: 0 - val to = (toPosition as? IntermediateTextPosition)?.position ?: 0 - return IntermediateTextRange( - IntermediateTextPosition(minOf(from, to)), - IntermediateTextPosition(maxOf(from, to)) - ) - } - - /** - * Attention! position may be null - */ - override fun positionFromPosition(position: UITextPosition, offset: NSInteger): UITextPosition? { - val p = (position as? IntermediateTextPosition)?.position ?: return null - val endOfDocument = _skiaLayer?.skikoView?.input?.endOfDocument() - return if (endOfDocument != null) { - IntermediateTextPosition(max(min(p + offset, endOfDocument), 0)) - } else { - null - } - } - - override fun positionFromPosition( - position: UITextPosition, - inDirection: UITextLayoutDirection, - offset: NSInteger - ): UITextPosition? { - return when (inDirection) { - UITextLayoutDirectionLeft, UITextLayoutDirectionUp -> { - positionFromPosition(position, -offset) - } - - else -> positionFromPosition(position, offset) - } - } - - /** - * Attention! position and toPosition may be null - */ - override fun comparePosition(position: UITextPosition, toPosition: UITextPosition): NSComparisonResult { - val from = (position as? IntermediateTextPosition)?.position ?: 0 - val to = (toPosition as? IntermediateTextPosition)?.position ?: 0 - val result = if (from < to) { - NSOrderedAscending - } else if (from > to) { - NSOrderedDescending - } else { - NSOrderedSame - } - return result - } - - override fun offsetFromPosition(from: UITextPosition, toPosition: UITextPosition): NSInteger { - val fromPosition = from as IntermediateTextPosition - val to = toPosition as IntermediateTextPosition - return to.position - fromPosition.position - } - - override fun tokenizer(): UITextInputTokenizerProtocol { - return UITextInputStringTokenizer() - } - - override fun positionWithinRange(range: UITextRange, atCharacterOffset: NSInteger): UITextPosition? = - TODO("positionWithinRange range: $range, atCharacterOffset: $atCharacterOffset") - - override fun positionWithinRange(range: UITextRange, farthestInDirection: UITextLayoutDirection): UITextPosition? = - TODO("positionWithinRange, farthestInDirection: ${farthestInDirection.directionToStr()}") - - override fun characterRangeByExtendingPosition( - position: UITextPosition, - inDirection: UITextLayoutDirection - ): UITextRange? { - TODO("characterRangeByExtendingPosition, inDirection: ${inDirection.directionToStr()}") - } - - override fun baseWritingDirectionForPosition( - position: UITextPosition, - inDirection: UITextStorageDirection - ): NSWritingDirection { - return NSWritingDirectionLeftToRight // TODO support RTL text direction - } - - override fun setBaseWritingDirection(writingDirection: NSWritingDirection, forRange: UITextRange) { - // TODO support RTL text direction - } - - //Working with Geometry and Hit-Testing. All methods return stubs for now. - override fun firstRectForRange(range: UITextRange): CValue = CGRectNull.readValue() - override fun caretRectForPosition(position: UITextPosition): CValue = CGRectNull.readValue() - override fun selectionRectsForRange(range: UITextRange): List<*> = listOf() - override fun closestPositionToPoint(point: CValue): UITextPosition? = null - override fun closestPositionToPoint(point: CValue, withinRange: UITextRange): UITextPosition? = null - override fun characterRangeAtPoint(point: CValue): UITextRange? = null - - override fun textStylingAtPosition(position: UITextPosition, inDirection: UITextStorageDirection): Map? { - return NSDictionary.dictionary() - } - - override fun characterOffsetOfPosition(position: UITextPosition, withinRange: UITextRange): NSInteger { - TODO("characterOffsetOfPosition") - } - - override fun shouldChangeTextInRange(range: UITextRange, replacementText: String): Boolean { - // Here we should decide to replace text in range or not. - // By default, this method returns true. - return true - } - - override fun textInputView(): UIView { - return this - } - - override fun canPerformAction(action: COpaquePointer?, withSender: Any?): Boolean = - when (action) { - NSSelectorFromString(UIResponderStandardEditActionsProtocol::copy.name + ":") -> - _currentTextMenuActions?.copy != null - - NSSelectorFromString(UIResponderStandardEditActionsProtocol::cut.name + ":") -> - _currentTextMenuActions?.cut != null - - NSSelectorFromString(UIResponderStandardEditActionsProtocol::paste.name + ":") -> - _currentTextMenuActions?.paste != null - - NSSelectorFromString(UIResponderStandardEditActionsProtocol::selectAll.name + ":") -> - _currentTextMenuActions?.selectAll != null - - else -> false - } - - override fun keyboardType(): UIKeyboardType = _skikoUITextInputTrains.keyboardType() - override fun keyboardAppearance(): UIKeyboardAppearance = _skikoUITextInputTrains.keyboardAppearance() - override fun returnKeyType(): UIReturnKeyType = _skikoUITextInputTrains.returnKeyType() - override fun textContentType(): UITextContentType? = _skikoUITextInputTrains.textContentType() - override fun isSecureTextEntry(): Boolean = _skikoUITextInputTrains.isSecureTextEntry() - override fun enablesReturnKeyAutomatically(): Boolean = _skikoUITextInputTrains.enablesReturnKeyAutomatically() - override fun autocapitalizationType(): UITextAutocapitalizationType = - _skikoUITextInputTrains.autocapitalizationType() - - override fun autocorrectionType(): UITextAutocorrectionType = _skikoUITextInputTrains.autocorrectionType() - - override fun dictationRecognitionFailed() { - //todo may be useful - } - - override fun dictationRecordingDidEnd() { - //todo may be useful - } - - /** - * Call when something changes in text data - */ - fun textWillChange() { - _inputDelegate?.textWillChange(this) - } - - /** - * Call when something changes in text data - */ - fun textDidChange() { - _inputDelegate?.textDidChange(this) - } - - /** - * Call when something changes in text data - */ - fun selectionWillChange() { - _inputDelegate?.selectionWillChange(this) - } - - /** - * Call when something changes in text data - */ - fun selectionDidChange() { - _inputDelegate?.selectionDidChange(this) - } } - -private class IntermediateTextPosition(val position: Long = 0) : UITextPosition() - -private fun IntermediateTextRange(start: Int, end: Int) = - IntermediateTextRange( - _start = IntermediateTextPosition(start.toLong()), - _end = IntermediateTextPosition(end.toLong()) - ) - -private class IntermediateTextRange( - private val _start: IntermediateTextPosition, - private val _end: IntermediateTextPosition -) : UITextRange() { - override fun isEmpty() = (_end.position - _start.position) <= 0 - override fun start(): UITextPosition = _start - override fun end(): UITextPosition = _end -} - -private fun UITextRange.toIntRange(): IntRange { - val start = (start() as IntermediateTextPosition).position.toInt() - val end = (end() as IntermediateTextPosition).position.toInt() - return start until end -} - -private fun IntRange.toUITextRange(): UITextRange = - IntermediateTextRange(start = start, end = endInclusive + 1) - -private fun NSWritingDirection.directionToStr() = - when (this) { - UITextLayoutDirectionLeft -> "Left" - UITextLayoutDirectionRight -> "Right" - UITextLayoutDirectionUp -> "Up" - UITextLayoutDirectionDown -> "Down" - else -> "unknown direction" - } - -private val UITouch.isPressed - get() = - phase != UITouchPhase.UITouchPhaseEnded && - phase != UITouchPhase.UITouchPhaseCancelled diff --git a/skiko/src/jsMain/kotlin/org/jetbrains/skiko/SkiaLayer.js.kt b/skiko/src/jsMain/kotlin/org/jetbrains/skiko/SkiaLayer.js.kt deleted file mode 100644 index b0278e870..000000000 --- a/skiko/src/jsMain/kotlin/org/jetbrains/skiko/SkiaLayer.js.kt +++ /dev/null @@ -1,11 +0,0 @@ -package org.jetbrains.skiko - -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 diff --git a/skiko/src/jsWasmMain/kotlin/org/jetbrains/skiko/Convertors.kt b/skiko/src/jsWasmMain/kotlin/org/jetbrains/skiko/Convertors.kt deleted file mode 100644 index 20dab1810..000000000 --- a/skiko/src/jsWasmMain/kotlin/org/jetbrains/skiko/Convertors.kt +++ /dev/null @@ -1,55 +0,0 @@ -package org.jetbrains.skiko - -internal val SPECIAL_KEYS = setOf( - "Unidentified", - "Alt", - "AltGraph", - "Backspace", - "CapsLock", - "Control", - "Fn", - "FnLock", - "Hyper", - "Meta", - "NumLock", - "ScrollLock", - "Shift", - "Super", - "Symbol", - "SymbolLock", - "F1", - "F2", - "F3", - "F4", - "F5", - "F6", - "F7", - "F8", - "F9", - "F10", - "F11", - "F12", - "F13", - "F14", - "F15", - "F16", - "F17", - "F18", - "F19", - "F20", - "F21", - "F22", - "ArrowLeft", - "ArrowUp", - "ArrowRight", - "ArrowDown", - "Help", - "Home", - "Delete", - "End", - "PageUp", - "PageDown", - "Escape", - "Clear", - "Clear" -) \ No newline at end of file diff --git a/skiko/src/jsWasmMain/kotlin/org/jetbrains/skiko/SkiaLayer.js.kt b/skiko/src/jsWasmMain/kotlin/org/jetbrains/skiko/SkiaLayer.js.kt index 401831ff5..515a840bc 100644 --- a/skiko/src/jsWasmMain/kotlin/org/jetbrains/skiko/SkiaLayer.js.kt +++ b/skiko/src/jsWasmMain/kotlin/org/jetbrains/skiko/SkiaLayer.js.kt @@ -8,7 +8,7 @@ import org.jetbrains.skiko.wasm.createWebGLContext /** * Provides a way to render the content and to receive the input events. - * Rendering and events processing should be implemented in [skikoView]. + * Rendering and events processing should be implemented in [renderDelegate]. * * SkikoLayer needs to be initialized with [HTMLCanvasElement] instance * using [attachTo] method. @@ -53,10 +53,10 @@ actual open class SkiaLayer { } /** - * An implementation of SkikoView with content rendering and + * An implementation of [SkikoRenderDelegate] with content rendering and * event processing logic. */ - actual var skikoView: SkikoView? = null + actual var renderDelegate: SkikoRenderDelegate? = null /** * @param container - should be an instance of [HTMLCanvasElement] @@ -76,7 +76,7 @@ actual open class SkiaLayer { /** * Initializes the [CanvasRenderer] and events listeners. - * Delegates rendering and events processing to [skikoView]. + * Delegates rendering and events processing to [renderDelegate]. */ private fun attachTo(htmlCanvas: HTMLCanvasElement) { this.htmlCanvas = htmlCanvas @@ -85,13 +85,13 @@ actual open class SkiaLayer { override fun drawFrame(currentTimestamp: Double) { // currentTimestamp is in milliseconds. val currentNanos = currentTimestamp * 1_000_000 - skikoView?.onRender(canvas!!, width, height, currentNanos.toLong()) + renderDelegate?.onRender(canvas!!, width, height, currentNanos.toLong()) } } } internal actual fun draw(canvas: Canvas) { - skikoView?.onRender(canvas, state!!.width, state!!.height, currentNanoTime()) + renderDelegate?.onRender(canvas, state!!.width, state!!.height, currentNanoTime()) } actual val pixelGeometry: PixelGeometry diff --git a/skiko/src/jsWasmMain/kotlin/org/jetbrains/skiko/SkikoInput.js.kt b/skiko/src/jsWasmMain/kotlin/org/jetbrains/skiko/SkikoInput.js.kt deleted file mode 100644 index b6f6ddac8..000000000 --- a/skiko/src/jsWasmMain/kotlin/org/jetbrains/skiko/SkikoInput.js.kt +++ /dev/null @@ -1,9 +0,0 @@ -package org.jetbrains.skiko - -actual interface SkikoInput { - fun onInputEvent(event: SkikoInputEvent) - - actual object Empty : SkikoInput { - override fun onInputEvent(event: SkikoInputEvent) = Unit - } -} diff --git a/skiko/src/jsWasmMain/kotlin/org/jetbrains/skiko/SkikoKey.js.kt b/skiko/src/jsWasmMain/kotlin/org/jetbrains/skiko/SkikoKey.js.kt deleted file mode 100644 index 7c9fcea28..000000000 --- a/skiko/src/jsWasmMain/kotlin/org/jetbrains/skiko/SkikoKey.js.kt +++ /dev/null @@ -1,115 +0,0 @@ -package org.jetbrains.skiko - -actual enum class SkikoKey(actual val platformKeyCode: Int) { - KEY_UNKNOWN(-1), - KEY_A(65), - KEY_S(83), - KEY_D(68), - KEY_F(70), - KEY_H(72), - KEY_G(71), - KEY_Z(90), - KEY_X(88), - KEY_C(67), - KEY_V(86), - KEY_B(66), - KEY_Q(81), - KEY_W(87), - KEY_E(69), - KEY_R(82), - KEY_Y(89), - KEY_T(54), - KEY_U(85), - KEY_I(73), - KEY_P(80), - KEY_L(76), - KEY_J(74), - KEY_K(75), - KEY_N(78), - KEY_M(77), - KEY_O(79), - KEY_1(49), - KEY_2(50), - KEY_3(51), - KEY_4(52), - KEY_5(53), - KEY_6(54), - KEY_7(55), - KEY_8(56), - KEY_9(57), - KEY_0(48), - KEY_CLOSE_BRACKET(221), - KEY_OPEN_BRACKET(219), - KEY_QUOTE(222), - KEY_SEMICOLON(59), - KEY_SLASH(191), - KEY_COMMA(188), - KEY_BACKSLASH(220), - KEY_PERIOD(190), - KEY_BACK_QUOTE(192), - KEY_EQUALS(61), - KEY_MINUS(173), - KEY_ENTER(13), - KEY_ESCAPE(27), - KEY_TAB(9), - KEY_BACKSPACE(8), - KEY_SPACE(32), - KEY_CAPSLOCK(20), - KEY_LEFT_META(224), - KEY_LEFT_SHIFT(16), - KEY_LEFT_ALT(18), - KEY_LEFT_CONTROL(17), - KEY_RIGHT_META(0x80000000.toInt() or 224), - KEY_RIGHT_SHIFT(0x80000000.toInt() or 16), - KEY_RIGHT_ALT(225), - KEY_RIGHT_CONTROL(0x80000000.toInt() or 17), - KEY_MENU(93), - KEY_UP(38), - KEY_DOWN(40), - KEY_LEFT(37), - KEY_RIGHT(39), - KEY_F1(112), - KEY_F2(113), - KEY_F3(114), - KEY_F4(115), - KEY_F5(116), - KEY_F6(117), - KEY_F7(118), - KEY_F8(119), - KEY_F9(120), - KEY_F10(121), - KEY_F11(122), - KEY_F12(123), - KEY_PRINTSCEEN(44), - KEY_SCROLL_LOCK(145), - KEY_PAUSE(19), - KEY_INSERT(45), - KEY_HOME(36), - KEY_PGUP(33), - KEY_DELETE(46), - KEY_END(35), - KEY_PGDOWN(34), - KEY_NUM_LOCK(144), - KEY_NUMPAD_0(96), - KEY_NUMPAD_1(97), - KEY_NUMPAD_2(98), - KEY_NUMPAD_3(99), - KEY_NUMPAD_4(100), - KEY_NUMPAD_5(101), - KEY_NUMPAD_6(102), - KEY_NUMPAD_7(103), - KEY_NUMPAD_8(104), - KEY_NUMPAD_9(105), - KEY_NUMPAD_ENTER(14), - KEY_NUMPAD_ADD(107), - KEY_NUMPAD_SUBTRACT(109), - KEY_NUMPAD_MULTIPLY(106), - KEY_NUMPAD_DIVIDE(111), - KEY_NUMPAD_DECIMAL(110); - - companion object { - fun valueOf(platformKeyCode: Int): SkikoKey { - return values().firstOrNull { it.platformKeyCode == platformKeyCode } ?: KEY_UNKNOWN - } - } -} diff --git a/skiko/src/linuxMain/kotlin/org/jetbrains/skiko/SkiaLayer.linux.kt b/skiko/src/linuxMain/kotlin/org/jetbrains/skiko/SkiaLayer.linux.kt index b00b61a46..6ff431e18 100644 --- a/skiko/src/linuxMain/kotlin/org/jetbrains/skiko/SkiaLayer.linux.kt +++ b/skiko/src/linuxMain/kotlin/org/jetbrains/skiko/SkiaLayer.linux.kt @@ -31,16 +31,10 @@ actual open class SkiaLayer { TODO("unimplemented") } - actual var skikoView: SkikoView? = null + actual var renderDelegate: SkikoRenderDelegate? = null actual val pixelGeometry: PixelGeometry get() = TODO("Not yet implemented") } -// TODO: do properly -actual typealias SkikoGesturePlatformEvent = Any -actual typealias SkikoPlatformInputEvent = Any -actual typealias SkikoPlatformKeyboardEvent = Any -actual typealias SkikoPlatformPointerEvent = Any - actual val currentSystemTheme: SystemTheme get() = SystemTheme.UNKNOWN \ No newline at end of file diff --git a/skiko/src/linuxMain/kotlin/org/jetbrains/skiko/SkikoInput.linux.kt b/skiko/src/linuxMain/kotlin/org/jetbrains/skiko/SkikoInput.linux.kt deleted file mode 100644 index c6b5331d3..000000000 --- a/skiko/src/linuxMain/kotlin/org/jetbrains/skiko/SkikoInput.linux.kt +++ /dev/null @@ -1,5 +0,0 @@ -package org.jetbrains.skiko - -actual interface SkikoInput { - actual object Empty : SkikoInput -} diff --git a/skiko/src/linuxMain/kotlin/org/jetbrains/skiko/SkikoKey.linux.kt b/skiko/src/linuxMain/kotlin/org/jetbrains/skiko/SkikoKey.linux.kt deleted file mode 100644 index 3a17858d4..000000000 --- a/skiko/src/linuxMain/kotlin/org/jetbrains/skiko/SkikoKey.linux.kt +++ /dev/null @@ -1,116 +0,0 @@ -package org.jetbrains.skiko - -actual enum class SkikoKey(actual val platformKeyCode: Int) { - KEY_UNKNOWN(-1), - KEY_A(0), - KEY_S(1), - KEY_D(2), - KEY_F(3), - KEY_H(4), - KEY_G(5), - KEY_Z(6), - KEY_X(7), - KEY_C(8), - KEY_V(9), - KEY_B(11), - KEY_Q(12), - KEY_W(13), - KEY_E(14), - KEY_R(15), - KEY_Y(16), - KEY_T(17), - KEY_U(32), - KEY_I(34), - KEY_P(35), - KEY_L(37), - KEY_J(38), - KEY_K(40), - KEY_N(45), - KEY_M(46), - KEY_O(31), - KEY_1(18), - KEY_2(19), - KEY_3(20), - KEY_4(21), - KEY_5(23), - KEY_6(22), - KEY_7(26), - KEY_8(28), - KEY_9(25), - KEY_0(29), - KEY_CLOSE_BRACKET(30), - KEY_OPEN_BRACKET(33), - KEY_QUOTE(39), - KEY_SEMICOLON(41), - KEY_SLASH(42), - KEY_COMMA(43), - KEY_BACKSLASH(44), - KEY_PERIOD(47), - KEY_BACK_QUOTE(50), - KEY_EQUALS(24), - KEY_MINUS(27), - KEY_ENTER(36), - KEY_ESCAPE(53), - KEY_TAB(48), - KEY_BACKSPACE(51), - KEY_SPACE(49), - KEY_CAPSLOCK(57), - KEY_LEFT_META(55), - KEY_LEFT_SHIFT(56), - KEY_LEFT_ALT(58), - KEY_LEFT_CONTROL(59), - KEY_RIGHT_META(54), - KEY_RIGHT_SHIFT(60), - KEY_RIGHT_ALT(61), - KEY_RIGHT_CONTROL(62), - KEY_MENU(110), - KEY_UP(126), - KEY_DOWN(125), - KEY_LEFT(123), - KEY_RIGHT(124), - KEY_F1(122), - KEY_F2(120), - KEY_F3(99), - KEY_F4(118), - KEY_F5(96), - KEY_F6(97), - KEY_F7(98), - KEY_F8(100), - KEY_F9(101), - KEY_F10(109), - KEY_F11(103), - KEY_F12(111), - KEY_PRINTSCEEN(105), - KEY_SCROLL_LOCK(107), - KEY_PAUSE(113), - KEY_INSERT(114), - KEY_HOME(115), - KEY_PGUP(116), - KEY_DELETE(117), - KEY_END(119), - KEY_PGDOWN(121), - KEY_NUM_LOCK(71), - KEY_NUMPAD_0(82), - KEY_NUMPAD_1(83), - KEY_NUMPAD_2(84), - KEY_NUMPAD_3(85), - KEY_NUMPAD_4(86), - KEY_NUMPAD_5(87), - KEY_NUMPAD_6(88), - KEY_NUMPAD_7(88), - KEY_NUMPAD_8(91), - KEY_NUMPAD_9(92), - KEY_NUMPAD_ENTER(76), - KEY_NUMPAD_ADD(69), - KEY_NUMPAD_SUBTRACT(78), - KEY_NUMPAD_MULTIPLY(67), - KEY_NUMPAD_DIVIDE(75), - KEY_NUMPAD_DECIMAL(65); - - companion object { - fun valueOf(platformKeyCode: Int): SkikoKey { - val key = SkikoKey.values().firstOrNull { it.platformKeyCode == platformKeyCode } - return if (key == null) SkikoKey.KEY_UNKNOWN else key - } - } -} diff --git a/skiko/src/macosMain/kotlin/org/jetbrains/skiko/Convertors.macos.kt b/skiko/src/macosMain/kotlin/org/jetbrains/skiko/Convertors.macos.kt deleted file mode 100644 index 3766ca335..000000000 --- a/skiko/src/macosMain/kotlin/org/jetbrains/skiko/Convertors.macos.kt +++ /dev/null @@ -1,219 +0,0 @@ -package org.jetbrains.skiko - -import kotlinx.cinterop.useContents -import platform.AppKit.* - -fun toSkikoEvent( - event: NSEvent, - kind: SkikoPointerEventKind, - view: NSView -): SkikoPointerEvent { - var (xpos, ypos) = event.locationInWindow.useContents { - x to y - } - // Translate. - view.frame.useContents { - ypos = size.height - ypos - } - val timestamp = (event.timestamp * 1_000).toLong() - return SkikoPointerEvent( - x = xpos, - y = ypos, - pressedButtons = toSkikoPressedMouseButtons(event, kind), - button = toSkikoMouseButton(event), - modifiers = toSkikoModifiers(event), - kind = kind, - timestamp = timestamp, - platform = event - ) -} - -fun toSkikoEvent( - event: NSEvent, - button: SkikoMouseButtons, - kind: SkikoPointerEventKind, - view: NSView -): SkikoPointerEvent { - var (xpos, ypos) = event.locationInWindow.useContents { - x to y - } - // Translate. - view.frame.useContents { - ypos = size.height - ypos - } - val timestamp = (event.timestamp * 1_000).toLong() - var buttons: SkikoMouseButtons - if (kind == SkikoPointerEventKind.DOWN) { - buttonsFlags = buttonsFlags.or(button.value) - } else { - buttonsFlags = buttonsFlags.xor(button.value) - } - buttons = SkikoMouseButtons(buttonsFlags) - return SkikoPointerEvent( - x = xpos, - y = ypos, - pressedButtons = buttons, - button = button, - modifiers = toSkikoModifiers(event), - kind = kind, - timestamp = timestamp, - platform = event - ) -} - -fun toSkikoScrollEvent( - event: NSEvent, - view: NSView -): SkikoPointerEvent { - var (xpos, ypos) = event.locationInWindow.useContents { - x to y - } - // Translate. - view.frame.useContents { - ypos = size.height - ypos - } - val timestamp = (event.timestamp * 1_000).toLong() - return SkikoPointerEvent( - x = xpos, - y = ypos, - deltaX = event.deltaX, - deltaY = event.deltaY, - pressedButtons = SkikoMouseButtons(buttonsFlags), - button = SkikoMouseButtons.NONE, - modifiers = toSkikoModifiers(event), - kind = SkikoPointerEventKind.SCROLL, - timestamp = timestamp, - platform = event - ) -} - -fun toSkikoEvent( - event: NSEvent, - kind: SkikoKeyboardEventKind -): SkikoKeyboardEvent { - val timestamp = (event.timestamp * 1_000).toLong() - return SkikoKeyboardEvent( - SkikoKey.valueOf(event.keyCode.toInt()), - toSkikoModifiers(event), - kind, - timestamp, - event - ) -} - -fun toSkikoTypeEvent( - character: String, - event: NSEvent?, -): SkikoInputEvent { - val key = if (event != null) SkikoKey.valueOf(event.keyCode.toInt()) else SkikoKey.KEY_UNKNOWN - val modifiers = if (event != null) toSkikoModifiers(event) else SkikoInputModifiers.EMPTY - return SkikoInputEvent( - character, - key, - modifiers, - SkikoKeyboardEventKind.TYPE, - event - ) -} - -private val actionAllKeyUpFlag = 256.toULong() // MacOS specific -private var modifierKeyUpFlag = actionAllKeyUpFlag -fun toSkikoEvent( - event: NSEvent -): SkikoKeyboardEvent { - // NSView.keyDown(NSEvent)/keyUp(NSEvent) does not work with modifier keys, - // so we need to use NSView.flagsChanged(NSEvent) - // and convert modifier key event to regular key event. - // Unfortunately, NSEvent does not give us any information about the type of action, - // so we need to check it manually. - val action = event.modifierFlags and NSEventModifierFlagDeviceIndependentFlagsMask.inv() - var kind = SkikoKeyboardEventKind.DOWN - val key = SkikoKey.valueOf(event.keyCode.toInt()) - if (action >= modifierKeyUpFlag) { - kind = SkikoKeyboardEventKind.DOWN - } else { - kind = SkikoKeyboardEventKind.UP - } - modifierKeyUpFlag = action - if (modifierKeyUpFlag == actionAllKeyUpFlag) { - kind = SkikoKeyboardEventKind.UP - } - val timestamp = (event.timestamp * 1_000).toLong() - return SkikoKeyboardEvent( - SkikoKey.valueOf(event.keyCode.toInt()), - toSkikoModifiers(event), - kind, - timestamp, - event - ) -} - -private var buttonsFlags = 0 -private fun toSkikoPressedMouseButtons( - event: NSEvent, - kind: SkikoPointerEventKind -): SkikoMouseButtons { - val button = event.buttonNumber.toInt() - if (kind == SkikoPointerEventKind.DOWN) { - buttonsFlags = buttonsFlags.or(getSkikoButtonValue(button)) - return SkikoMouseButtons(buttonsFlags) - } - buttonsFlags = buttonsFlags.xor(getSkikoButtonValue(button)) - return SkikoMouseButtons(buttonsFlags) -} - -private fun toSkikoMouseButton(event: NSEvent): SkikoMouseButtons { - return SkikoMouseButtons(getSkikoButtonValue(event.buttonNumber.toInt())) -} - -private fun getSkikoButtonValue(button: Int): Int { - return when (button) { - 2 -> SkikoMouseButtons.MIDDLE.value - 3 -> SkikoMouseButtons.BUTTON_4.value - 4 -> SkikoMouseButtons.BUTTON_5.value - 5 -> SkikoMouseButtons.BUTTON_6.value - 6 -> SkikoMouseButtons.BUTTON_7.value - 7 -> SkikoMouseButtons.BUTTON_8.value - else -> 0 - } -} - -private fun toSkikoModifiers(event: NSEvent): SkikoInputModifiers { - var result = 0 - val modifiers = event.modifierFlags - if (modifiers and NSEventModifierFlagOption != 0.toULong()) { - result = result.or(SkikoInputModifiers.ALT.value) - } - if (modifiers and NSEventModifierFlagShift != 0.toULong()) { - result = result.or(SkikoInputModifiers.SHIFT.value) - } - if (modifiers and NSEventModifierFlagControl != 0.toULong()) { - result = result.or(SkikoInputModifiers.CONTROL.value) - } - if (modifiers and NSEventModifierFlagCommand != 0.toULong()) { - result = result.or(SkikoInputModifiers.META.value) - } - return SkikoInputModifiers(result) -} - -private fun keyToModifier(key: SkikoKey): ULong { - return when (key) { - SkikoKey.KEY_LEFT_ALT, - SkikoKey.KEY_RIGHT_ALT -> { - NSEventModifierFlagOption - } - SkikoKey.KEY_LEFT_SHIFT, - SkikoKey.KEY_RIGHT_SHIFT -> { - NSEventModifierFlagShift - } - SkikoKey.KEY_LEFT_CONTROL, - SkikoKey.KEY_RIGHT_CONTROL -> { - NSEventModifierFlagControl - } - SkikoKey.KEY_LEFT_META, - SkikoKey.KEY_RIGHT_META -> { - NSEventModifierFlagCommand - } - else -> 0.toULong() - } -} \ No newline at end of file diff --git a/skiko/src/macosMain/kotlin/org/jetbrains/skiko/SkiaLayer.macos.kt b/skiko/src/macosMain/kotlin/org/jetbrains/skiko/SkiaLayer.macos.kt index e5e9959db..070a9afd1 100644 --- a/skiko/src/macosMain/kotlin/org/jetbrains/skiko/SkiaLayer.macos.kt +++ b/skiko/src/macosMain/kotlin/org/jetbrains/skiko/SkiaLayer.macos.kt @@ -1,34 +1,21 @@ package org.jetbrains.skiko +import kotlinx.cinterop.BetaInteropApi import kotlinx.cinterop.ObjCAction import kotlinx.cinterop.useContents -import kotlinx.cinterop.CValue -import kotlinx.cinterop.COpaquePointer -import kotlinx.cinterop.convert import org.jetbrains.skia.* -import org.jetbrains.skiko.redrawer.MacOsOpenGLRedrawer import org.jetbrains.skiko.redrawer.Redrawer import platform.AppKit.* -import platform.Foundation.NSAttributedString -import platform.Foundation.NSMutableAttributedString -import platform.Foundation.NSMakeRect -import platform.Foundation.NSMakeRange -import platform.Foundation.NSRange -import platform.Foundation.NSRangePointer -import platform.Foundation.NSPoint -import platform.Foundation.NSRect -import platform.Foundation.NSNotFound import platform.Foundation.NSNotification import platform.Foundation.NSNotificationCenter import platform.Foundation.NSSelectorFromString -import platform.Foundation.addObserver import platform.darwin.NSObject -import platform.CoreGraphics.CGRectMake /** * SkiaLayer implementation for macOS. * Supports only [GraphicsApi.METAL] */ +@OptIn(BetaInteropApi::class) actual open class SkiaLayer { fun isShowing(): Boolean { return true @@ -75,6 +62,7 @@ actual open class SkiaLayer { * Underlying [NSView] */ lateinit var nsView: NSView + private set actual val component: Any? get() = this.nsView @@ -82,7 +70,7 @@ actual open class SkiaLayer { /** * Implements rendering logic and events processing. */ - actual var skikoView: SkikoView? = null + actual var renderDelegate: SkikoRenderDelegate? = null internal var redrawer: Redrawer? = null @@ -93,154 +81,50 @@ actual open class SkiaLayer { private var picture: PictureHolder? = null private val pictureRecorder = PictureRecorder() - /** - * @param container - should be an instance of [NSWindow] - */ - actual fun attachTo(container: Any) { - attachTo(container as NSWindow) - } - - /** - * Initializes the [nsView] then adds it to [window]. Initializes events listeners. - * Delegates events processing to [skikoView]. - */ - fun attachTo(window: NSWindow) { - val (width, height) = window.contentLayoutRect.useContents { - this.size.width to this.size.height + private val nsViewObserver = object : NSObject() { + @ObjCAction + fun frameDidChange(notification: NSNotification) { + redrawer?.syncSize() + redrawer?.redrawImmediately() } - nsView = object : NSView(NSMakeRect(0.0, 0.0, width, height)), NSTextInputClientProtocol { - private var trackingArea : NSTrackingArea? = null - override fun wantsUpdateLayer() = true - override fun acceptsFirstResponder() = true - override fun viewWillMoveToWindow(newWindow: NSWindow?) { - updateTrackingAreas() - } - - override fun updateTrackingAreas() { - trackingArea?.let { removeTrackingArea(it) } - trackingArea = NSTrackingArea( - rect = bounds, - options = NSTrackingActiveAlways or - NSTrackingMouseEnteredAndExited or - NSTrackingMouseMoved or - NSTrackingActiveInKeyWindow or - NSTrackingAssumeInside or - NSTrackingInVisibleRect, - owner = nsView, userInfo = null) - nsView.addTrackingArea(trackingArea!!) - } - - override fun mouseDown(event: NSEvent) { - skikoView?.onPointerEvent(toSkikoEvent(event, SkikoMouseButtons.LEFT, SkikoPointerEventKind.DOWN, nsView)) - } - override fun mouseUp(event: NSEvent) { - skikoView?.onPointerEvent(toSkikoEvent(event, SkikoMouseButtons.LEFT, SkikoPointerEventKind.UP, nsView)) - } - override fun rightMouseDown(event: NSEvent) { - skikoView?.onPointerEvent(toSkikoEvent(event, SkikoMouseButtons.RIGHT, SkikoPointerEventKind.DOWN, nsView)) - } - override fun rightMouseUp(event: NSEvent) { - skikoView?.onPointerEvent(toSkikoEvent(event, SkikoMouseButtons.RIGHT, SkikoPointerEventKind.UP, nsView)) - } - override fun otherMouseDown(event: NSEvent) { - skikoView?.onPointerEvent(toSkikoEvent(event, SkikoPointerEventKind.DOWN, nsView)) - } - override fun otherMouseUp(event: NSEvent) { - skikoView?.onPointerEvent(toSkikoEvent(event, SkikoPointerEventKind.UP, nsView)) - } - override fun mouseMoved(event: NSEvent) { - skikoView?.onPointerEvent(toSkikoEvent(event, SkikoPointerEventKind.MOVE, nsView)) - } - override fun mouseDragged(event: NSEvent) { - skikoView?.onPointerEvent(toSkikoEvent(event, SkikoPointerEventKind.DRAG, nsView)) - } - override fun scrollWheel(event: NSEvent) { - skikoView?.onPointerEvent(toSkikoScrollEvent(event, nsView)) - } - override fun keyDown(event: NSEvent) { - keyEvent = event - skikoView?.onKeyboardEvent(toSkikoEvent(event, SkikoKeyboardEventKind.DOWN)) - interpretKeyEvents(listOf(event)) - } - override fun flagsChanged(event: NSEvent) { - keyEvent = event - skikoView?.onKeyboardEvent(toSkikoEvent(event)) - } - override fun keyUp(event: NSEvent) { - keyEvent = event - skikoView?.onKeyboardEvent(toSkikoEvent(event, SkikoKeyboardEventKind.UP)) - } - private var keyEvent: NSEvent? = null - private var markedText: String = "" - private val kEmptyRange = NSMakeRange(NSNotFound.convert(), 0) - override fun attributedSubstringForProposedRange(range: CValue, actualRange: NSRangePointer?) = null - override fun hasMarkedText(): Boolean { - return markedText.length > 0 - } - override fun markedRange(): CValue { - if (markedText.length > 0) { - return NSMakeRange(0, (markedText.length - 1).convert()) - } - return kEmptyRange - } - override fun selectedRange() = kEmptyRange - override fun characterIndexForPoint(point: CValue) = 0.toULong() - override fun doCommandBySelector(selector: COpaquePointer?) {} - override fun firstRectForCharacterRange(range: CValue, actualRange: NSRangePointer?): CValue { - val (x, y) = window.frame.useContents { - origin.x to origin.y - } - return NSMakeRect(x, y, 0.0, 0.0) - } - override fun insertText(string: Any, replacementRange: CValue) { - val character = when(string) { - is NSAttributedString -> string.string - else -> string as String - } - skikoView?.onInputEvent(toSkikoTypeEvent(character, keyEvent)) - } - override fun setMarkedText(string: Any, selectedRange: CValue, replacementRange: CValue) { - if (string is NSAttributedString) { - markedText = string.string - } else { - markedText = string as String - } - } - override fun unmarkText() { - markedText = "" - } - override fun validAttributesForMarkedText(): List<*> { - return listOf() - } + @ObjCAction + fun windowDidChangeBackingProperties(notification: NSNotification) { + redrawer?.syncSize() + redrawer?.redrawImmediately() + } - @ObjCAction - open fun onWindowClose(arg: NSObject?) { - detach() - val center = NSNotificationCenter.defaultCenter() - center.removeObserver(nsView) - } + fun addObserver() { + val center = NSNotificationCenter.defaultCenter() + center.addObserver( + observer = this, + selector = NSSelectorFromString("frameDidChange:"), + name = NSViewFrameDidChangeNotification, + `object` = nsView, + ) + center.addObserver( + observer = this, + selector = NSSelectorFromString("windowDidChangeBackingProperties:"), + name = NSWindowDidChangeBackingPropertiesNotification, + `object` = nsView.window, + ) } - val center = NSNotificationCenter.defaultCenter() - center.addObserver(nsView, NSSelectorFromString("onWindowClose:"), - NSWindowWillCloseNotification!!, window) - window.delegate = object : NSObject(), NSWindowDelegateProtocol { - override fun windowDidResize(notification: NSNotification) { - val (w, h) = window.contentView!!.frame.useContents { - size.width to size.height - } - nsView.frame = CGRectMake(0.0, 0.0, w, h) - redrawer?.syncSize() - redrawer?.redrawImmediately() - } - override fun windowDidChangeBackingProperties(notification: NSNotification) { - redrawer?.syncSize() - redrawer?.redrawImmediately() - } + fun removeObserver() { + val center = NSNotificationCenter.defaultCenter() + center.removeObserver(this) } - window.contentView!!.addSubview(nsView) - window.makeFirstResponder(nsView) + } + + /** + * @param container - should be an instance of [NSView] + */ + actual fun attachTo(container: Any) { + check(!this::nsView.isInitialized) { "Already attached to another NSView" } + check(container is NSView) { "container should be an instance of NSView" } + nsView = container + nsView.postsFrameChangedNotifications = true + nsViewObserver.addObserver() redrawer = createNativeRedrawer(this, renderApi).apply { syncSize() needRedraw() @@ -248,6 +132,7 @@ actual open class SkiaLayer { } actual fun detach() { + nsViewObserver.removeObserver() redrawer?.dispose() redrawer = null } @@ -271,7 +156,7 @@ actual open class SkiaLayer { val bounds = Rect.makeWH(pictureWidth.toFloat(), pictureHeight.toFloat()) val canvas = pictureRecorder.beginRecording(bounds) - skikoView?.onRender(canvas, pictureWidth.toInt(), pictureHeight.toInt(), nanoTime) + renderDelegate?.onRender(canvas, pictureWidth.toInt(), pictureHeight.toInt(), nanoTime) val picture = pictureRecorder.finishRecordingAsPicture() this.picture = PictureHolder(picture, pictureWidth.toInt(), pictureHeight.toInt()) @@ -286,9 +171,3 @@ actual open class SkiaLayer { actual val pixelGeometry: PixelGeometry get() = PixelGeometry.UNKNOWN } - -// TODO: do properly -actual typealias SkikoGesturePlatformEvent = NSEvent -actual typealias SkikoPlatformInputEvent = NSEvent -actual typealias SkikoPlatformKeyboardEvent = NSEvent -actual typealias SkikoPlatformPointerEvent = NSEvent diff --git a/skiko/src/macosMain/kotlin/org/jetbrains/skiko/SkikoInput.macos.kt b/skiko/src/macosMain/kotlin/org/jetbrains/skiko/SkikoInput.macos.kt deleted file mode 100644 index c6b5331d3..000000000 --- a/skiko/src/macosMain/kotlin/org/jetbrains/skiko/SkikoInput.macos.kt +++ /dev/null @@ -1,5 +0,0 @@ -package org.jetbrains.skiko - -actual interface SkikoInput { - actual object Empty : SkikoInput -} diff --git a/skiko/src/macosMain/kotlin/org/jetbrains/skiko/SkikoKey.macos.kt b/skiko/src/macosMain/kotlin/org/jetbrains/skiko/SkikoKey.macos.kt deleted file mode 100644 index 3a17858d4..000000000 --- a/skiko/src/macosMain/kotlin/org/jetbrains/skiko/SkikoKey.macos.kt +++ /dev/null @@ -1,116 +0,0 @@ -package org.jetbrains.skiko - -actual enum class SkikoKey(actual val platformKeyCode: Int) { - KEY_UNKNOWN(-1), - KEY_A(0), - KEY_S(1), - KEY_D(2), - KEY_F(3), - KEY_H(4), - KEY_G(5), - KEY_Z(6), - KEY_X(7), - KEY_C(8), - KEY_V(9), - KEY_B(11), - KEY_Q(12), - KEY_W(13), - KEY_E(14), - KEY_R(15), - KEY_Y(16), - KEY_T(17), - KEY_U(32), - KEY_I(34), - KEY_P(35), - KEY_L(37), - KEY_J(38), - KEY_K(40), - KEY_N(45), - KEY_M(46), - KEY_O(31), - KEY_1(18), - KEY_2(19), - KEY_3(20), - KEY_4(21), - KEY_5(23), - KEY_6(22), - KEY_7(26), - KEY_8(28), - KEY_9(25), - KEY_0(29), - KEY_CLOSE_BRACKET(30), - KEY_OPEN_BRACKET(33), - KEY_QUOTE(39), - KEY_SEMICOLON(41), - KEY_SLASH(42), - KEY_COMMA(43), - KEY_BACKSLASH(44), - KEY_PERIOD(47), - KEY_BACK_QUOTE(50), - KEY_EQUALS(24), - KEY_MINUS(27), - KEY_ENTER(36), - KEY_ESCAPE(53), - KEY_TAB(48), - KEY_BACKSPACE(51), - KEY_SPACE(49), - KEY_CAPSLOCK(57), - KEY_LEFT_META(55), - KEY_LEFT_SHIFT(56), - KEY_LEFT_ALT(58), - KEY_LEFT_CONTROL(59), - KEY_RIGHT_META(54), - KEY_RIGHT_SHIFT(60), - KEY_RIGHT_ALT(61), - KEY_RIGHT_CONTROL(62), - KEY_MENU(110), - KEY_UP(126), - KEY_DOWN(125), - KEY_LEFT(123), - KEY_RIGHT(124), - KEY_F1(122), - KEY_F2(120), - KEY_F3(99), - KEY_F4(118), - KEY_F5(96), - KEY_F6(97), - KEY_F7(98), - KEY_F8(100), - KEY_F9(101), - KEY_F10(109), - KEY_F11(103), - KEY_F12(111), - KEY_PRINTSCEEN(105), - KEY_SCROLL_LOCK(107), - KEY_PAUSE(113), - KEY_INSERT(114), - KEY_HOME(115), - KEY_PGUP(116), - KEY_DELETE(117), - KEY_END(119), - KEY_PGDOWN(121), - KEY_NUM_LOCK(71), - KEY_NUMPAD_0(82), - KEY_NUMPAD_1(83), - KEY_NUMPAD_2(84), - KEY_NUMPAD_3(85), - KEY_NUMPAD_4(86), - KEY_NUMPAD_5(87), - KEY_NUMPAD_6(88), - KEY_NUMPAD_7(88), - KEY_NUMPAD_8(91), - KEY_NUMPAD_9(92), - KEY_NUMPAD_ENTER(76), - KEY_NUMPAD_ADD(69), - KEY_NUMPAD_SUBTRACT(78), - KEY_NUMPAD_MULTIPLY(67), - KEY_NUMPAD_DIVIDE(75), - KEY_NUMPAD_DECIMAL(65); - - companion object { - fun valueOf(platformKeyCode: Int): SkikoKey { - val key = SkikoKey.values().firstOrNull { it.platformKeyCode == platformKeyCode } - return if (key == null) SkikoKey.KEY_UNKNOWN else key - } - } -} diff --git a/skiko/src/wasmJsMain/kotlin/org/jetbrains/skiko/Resources.js.kt b/skiko/src/wasmJsMain/kotlin/org/jetbrains/skiko/Resources.wasmJs.kt similarity index 100% rename from skiko/src/wasmJsMain/kotlin/org/jetbrains/skiko/Resources.js.kt rename to skiko/src/wasmJsMain/kotlin/org/jetbrains/skiko/Resources.wasmJs.kt diff --git a/skiko/src/wasmJsMain/kotlin/org/jetbrains/skiko/SkiaLayer.js.wasmJs.kt b/skiko/src/wasmJsMain/kotlin/org/jetbrains/skiko/SkiaLayer.js.wasmJs.kt deleted file mode 100644 index bfdf9e338..000000000 --- a/skiko/src/wasmJsMain/kotlin/org/jetbrains/skiko/SkiaLayer.js.wasmJs.kt +++ /dev/null @@ -1,10 +0,0 @@ -package org.jetbrains.skiko - -import org.w3c.dom.events.KeyboardEvent -import org.w3c.dom.events.UIEvent - - -actual typealias SkikoGesturePlatformEvent = Any -actual typealias SkikoPlatformInputEvent = KeyboardEvent -actual typealias SkikoPlatformKeyboardEvent = KeyboardEvent -actual typealias SkikoPlatformPointerEvent = UIEvent