Unverified Commit cc4e47fc authored by Nikolay Igotti's avatar Nikolay Igotti Committed by GitHub

Cursor control API (#500)

Let's keep as is for know, and just mention minSdk in README.
parent a73e8750
......@@ -11,6 +11,7 @@ import kotlin.math.sin
import kotlin.math.PI
class Clocks(private val layer: SkiaLayer): SkikoView {
private val cursorManager = CursorManager()
private val withFps = true
private val fpsCounter = FPSCounter()
private val platformYOffset = if (hostOs == OS.Ios) 50f else 5f
......@@ -128,6 +129,11 @@ class Clocks(private val layer: SkiaLayer): SkikoView {
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
}
......
......@@ -4,9 +4,10 @@ import android.content.*
import android.content.ClipboardManager
import android.content.res.Configuration
import android.net.Uri
import android.view.PointerIcon.*
import android.view.View
import org.jetbrains.skiko.redrawer.Redrawer
actual fun setSystemLookAndFeel(): Unit = TODO()
internal class AndroidOpenGLRedrawer(
......@@ -64,4 +65,28 @@ internal actual fun ClipboardManager_getText(): String? {
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clip = clipboard.primaryClip ?: return null
return clip.getItemAt(0)?.text?.toString()
}
\ No newline at end of file
}
actual typealias Cursor = android.view.PointerIcon
// TODO: not sure if correct.
internal actual fun CursorManager_setCursor(component: Any, cursor: Cursor) {
if (component is View) {
component.pointerIcon = cursor
}
}
internal actual fun CursorManager_getCursor(component: Any): Cursor? =
if (component is View) {
component.pointerIcon
} else {
null
}
internal actual fun getCursorById(id: PredefinedCursorsId): Cursor =
when (id) {
PredefinedCursorsId.DEFAULT -> getSystemIcon(defaultContext!!, TYPE_DEFAULT)
PredefinedCursorsId.CROSSHAIR -> getSystemIcon(defaultContext!!, TYPE_CROSSHAIR)
PredefinedCursorsId.HAND -> getSystemIcon(defaultContext!!, TYPE_HAND)
PredefinedCursorsId.TEXT -> getSystemIcon(defaultContext!!, TYPE_TEXT)
}
\ No newline at end of file
......@@ -109,5 +109,8 @@ actual open class SkiaLayer {
}
}
actual val component: Any?
get() = this.container
internal actual fun draw(canvas: Canvas): Unit = TODO()
}
\ No newline at end of file
package org.jetbrains.skiko
import org.jetbrains.skiko.redrawer.*
import java.awt.Component
import java.awt.Desktop
import java.awt.Toolkit
import java.awt.datatransfer.DataFlavor
......@@ -63,3 +64,27 @@ internal actual fun ClipboardManager_getText(): String? {
null
}
}
actual typealias Cursor = java.awt.Cursor
internal actual fun CursorManager_setCursor(component: Any, cursor: Cursor) {
if (component is Component) {
component.cursor = cursor
}
}
internal actual fun CursorManager_getCursor(component: Any): Cursor? {
return if (component is Component) {
component.cursor
} else {
null
}
}
internal actual fun getCursorById(id: PredefinedCursorsId): Cursor =
when (id) {
PredefinedCursorsId.DEFAULT -> Cursor(Cursor.DEFAULT_CURSOR)
PredefinedCursorsId.CROSSHAIR -> Cursor(Cursor.CROSSHAIR_CURSOR)
PredefinedCursorsId.HAND -> Cursor(Cursor.HAND_CURSOR)
PredefinedCursorsId.TEXT -> Cursor(Cursor.TEXT_CURSOR)
}
\ No newline at end of file
......@@ -147,6 +147,9 @@ actual open class SkiaLayer internal constructor(
fullscreenAdapter.fullscreen = value
}
actual val component: Any?
get() = backedLayer
actual var skikoView: SkikoView? = null
actual fun attachTo(container: Any) {
......
package org.jetbrains.skiko
/**
* Identifiers of predefined cursors.
*/
enum class PredefinedCursorsId {
DEFAULT,
CROSSHAIR,
TEXT,
HAND
}
/**
* Predefined platform cursors.
*/
object PredefinedCursors {
val DEFAULT: Cursor = getCursorById(PredefinedCursorsId.DEFAULT)
val CROSSHAIR: Cursor = getCursorById(PredefinedCursorsId.CROSSHAIR)
val TEXT: Cursor = getCursorById(PredefinedCursorsId.TEXT)
val HAND: Cursor = getCursorById(PredefinedCursorsId.HAND)
}
/**
* Pointer device cursor abstraction.
*/
expect class Cursor
internal expect fun getCursorById(id: PredefinedCursorsId): Cursor
......@@ -18,10 +18,43 @@ internal expect fun URIHandler_openUri(uri: String)
* Manager for controlling system clipboard. Is open so that platform could provide an override if default doesn't fit.
*/
open class ClipboardManager {
/**
* Set current system clipboard content as text.
*/
open fun setText(text: String) = ClipboardManager_setText(text)
/**
* Get current system clipboard content as text.
*/
open fun getText(): String? = ClipboardManager_getText()
}
internal expect fun ClipboardManager_setText(text: String)
internal expect fun ClipboardManager_getText(): String?
/**
* Manager to control cursor per native component.
*/
open class CursorManager {
/**
* Set cursor for the given component.
*/
open fun setCursor(component: Any?, cursor: Cursor) {
if (component != null) CursorManager_setCursor(component, cursor)
}
/**
* Get cursor for the given component.
*/
open fun getCursor(component: Any?): Cursor? = if (component != null) {
CursorManager_getCursor(component)
} else { null }
}
/**
* Sets cursor for the platform component.
*/
internal expect fun CursorManager_setCursor(component: Any, cursor: Cursor)
/**
* Gets current cursor for the platform component, or null if not defined or known.
*/
internal expect fun CursorManager_getCursor(component: Any): Cursor?
......@@ -3,20 +3,58 @@ package org.jetbrains.skiko
import org.jetbrains.skia.Canvas
import org.jetbrains.skia.Picture
/**
* Generic layer for Skiko rendering.
*/
expect open class SkiaLayer {
/**
* Current graphics API used for rendering.
*/
var renderApi: GraphicsApi
/**
* Current content scale.
*/
val contentScale: Float
/**
* If rendering is full screen.
*/
var fullscreen: Boolean
/**
* If transparency is enabled.
*/
var transparency: Boolean
/**
* Underlying platform component.
*/
val component: Any?
/**
* Current view used for rendering.
*/
var skikoView: SkikoView?
// Actual type of attach container is platform-specific.
/**
* Attach this SkikoView to platform container.
* Actual type of attach container is platform-specific.
*/
fun attachTo(container: Any)
/**
* Detach this SkikoView from platform container.
*/
fun detach()
/**
* Force redraw.
*/
fun needRedraw()
/**
* Drawing function.
*/
internal fun draw(canvas: Canvas)
}
......
......@@ -13,4 +13,19 @@ internal actual fun ClipboardManager_setText(text: String) {
}
internal actual fun ClipboardManager_getText(): String? {
return UIPasteboard.generalPasteboard.string
}
\ No newline at end of file
}
// TODO: not sure if correct.
actual typealias Cursor = Any
internal actual fun CursorManager_setCursor(component: Any, cursor: Cursor) {}
internal actual fun CursorManager_getCursor(component: Any): Cursor? = null
internal actual fun getCursorById(id: PredefinedCursorsId): Cursor =
when (id) {
PredefinedCursorsId.DEFAULT -> Any()
PredefinedCursorsId.CROSSHAIR -> Any()
PredefinedCursorsId.HAND -> Any()
PredefinedCursorsId.TEXT -> Any()
}
\ No newline at end of file
......@@ -42,6 +42,9 @@ actual open class SkiaLayer {
redrawer?.needRedraw()
}
actual val component: Any?
get() = this.view
val width: Float
get() = view!!.frame.useContents {
return@useContents size.width.toFloat()
......
package org.jetbrains.skiko
import kotlinx.coroutines.await
import org.w3c.dom.HTMLElement
internal actual inline fun <R> maybeSynchronized(lock: Any, block: () -> R): R =
block()
......@@ -16,6 +16,31 @@ internal actual fun ClipboardManager_setText(text: String) {
}
internal actual fun ClipboardManager_getText(): String? {
TODO("implement ClipboardManager_getText")
// TODO("implement ClipboardManager_getText")
// kotlinx.browser.window.navigator.clipboard.readText()
}
\ No newline at end of file
return null
}
actual typealias Cursor = String
internal actual fun CursorManager_setCursor(component: Any, cursor: Cursor) {
if (component is HTMLElement) {
component.style.cursor = cursor
}
}
internal actual fun CursorManager_getCursor(component: Any): Cursor? {
return if (component is HTMLElement) {
component.style.cursor
} else {
null
}
}
internal actual fun getCursorById(id: PredefinedCursorsId): Cursor =
when (id) {
PredefinedCursorsId.DEFAULT -> "default"
PredefinedCursorsId.CROSSHAIR -> "crosshair"
PredefinedCursorsId.HAND -> "pointer"
PredefinedCursorsId.TEXT -> "text"
}
\ No newline at end of file
......@@ -76,11 +76,18 @@ actual open class SkiaLayer {
private var desiredWidth = 0
private var desiredHeight = 0
actual val component: Any?
get() = this.htmlCanvas
private var htmlCanvas: HTMLCanvasElement? = null
/**
* Initializes the [CanvasRenderer] and events listeners.
* Delegates rendering and events processing to [skikoView].
*/
fun attachTo(htmlCanvas: HTMLCanvasElement, autoDetach: Boolean = true) {
this.htmlCanvas = htmlCanvas
// Scale canvas to allow high DPI rendering as suggested in
// https://www.khronos.org/webgl/wiki/HandlingHighDPI.
desiredWidth = htmlCanvas.width
......
......@@ -10,4 +10,22 @@ internal actual fun ClipboardManager_setText(text: String) {
internal actual fun ClipboardManager_getText(): String? {
TODO("Implement ClipboardManager_getText() on Linux")
}
\ No newline at end of file
}
actual typealias Cursor = Any
internal actual fun CursorManager_setCursor(component: Any, cursor: Cursor) {
TODO("Implement CursorManager_setCursor on Linux")
}
internal actual fun CursorManager_getCursor(component: Any): Cursor? {
TODO("Implement CursorManager_getCursor on Linux")
}
internal actual fun getCursorById(id: PredefinedCursorsId): Cursor =
when (id) {
PredefinedCursorsId.DEFAULT -> Any()
PredefinedCursorsId.CROSSHAIR -> Any()
PredefinedCursorsId.HAND -> Any()
PredefinedCursorsId.TEXT -> Any()
}
\ No newline at end of file
......@@ -14,6 +14,8 @@ actual open class SkiaLayer {
actual var transparency: Boolean
get() = TODO("Not yet implemented")
set(value) {}
actual val component: Any?
get() = TODO("Not yet implemented")
actual fun needRedraw() {
TODO("unimplemented")
}
......
package org.jetbrains.skiko
import platform.AppKit.NSPasteboard
import platform.AppKit.NSPasteboardTypeString
import platform.AppKit.NSWorkspace
import platform.AppKit.*
import platform.Foundation.NSURL
internal actual fun URIHandler_openUri(uri: String) {
......@@ -15,4 +13,31 @@ internal actual fun ClipboardManager_setText(text: String) {
internal actual fun ClipboardManager_getText(): String? {
return NSPasteboard.generalPasteboard.stringForType(dataType = NSPasteboardTypeString)
}
\ No newline at end of file
}
actual typealias Cursor = NSCursor
// TODO: not sure if it is correct.
internal actual fun CursorManager_setCursor(component: Any, cursor: Cursor) {
if (component is NSView) {
component.resetCursorRects()
component.addCursorRect(component.bounds(), cursor)
}
}
internal actual fun CursorManager_getCursor(component: Any): Cursor? {
return if (component is NSView) {
// TODO: likely incorrect.
NSCursor.currentCursor
} else {
null
}
}
internal actual fun getCursorById(id: PredefinedCursorsId): Cursor =
when (id) {
PredefinedCursorsId.DEFAULT -> NSCursor.arrowCursor
PredefinedCursorsId.CROSSHAIR -> NSCursor.crosshairCursor
PredefinedCursorsId.HAND -> NSCursor.pointingHandCursor
PredefinedCursorsId.TEXT -> NSCursor.IBeamCursor
}
\ No newline at end of file
......@@ -76,6 +76,9 @@ actual open class SkiaLayer {
*/
lateinit var nsView: NSView
actual val component: Any?
get() = this.nsView
/**
* Implements rendering logic and events processing.
*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment