Unverified Commit 7ced4361 authored by Roman Sedaikin's avatar Roman Sedaikin Committed by GitHub

Fixed a case where [event.modifiersEx] does not provide info about the pressed...

Fixed a case where [event.modifiersEx] does not provide info about the pressed mouse button when using touchpad on MacOS 12 (AWT). (#470)

* Fixed a case where [event.modifiersEx] does not provide info about the pressed mouse button when using touchpad on MacOS 12.

* Refactoring 1. Added [pressedButtons] and [button] to [SkikoPointerEvent].

* Refactoring 3. Updated JS pointer events.
parent 9afdad8a
......@@ -75,11 +75,15 @@ 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(),
buttons = toSkikoMouseButtons(event.modifiersEx),
pressedButtons = toSkikoPressedMouseButtons(event),
button = toSkikoMouseButton(event),
modifiers = toSkikoModifiers(event.modifiersEx),
kind = when(event.id) {
MouseEvent.MOUSE_PRESSED -> SkikoPointerEventKind.DOWN
......@@ -106,7 +110,8 @@ fun toSkikoEvent(event: MouseWheelEvent): SkikoPointerEvent {
y = event.y.toDouble(),
deltaX = deltaX,
deltaY = deltaY,
buttons = toSkikoMouseButtons(event.modifiersEx),
pressedButtons = toSkikoPressedMouseButtons(event),
button = toSkikoMouseButton(event),
modifiers = modifiers,
kind = when(event.id) {
MouseEvent.MOUSE_WHEEL-> SkikoPointerEventKind.SCROLL
......@@ -163,20 +168,46 @@ fun toSkikoTypeEvent(event: InputMethodEvent, keyEvent: KeyEvent?): SkikoInputEv
)
}
private fun toSkikoMouseButtons(buttons: Int): SkikoMouseButtons {
private fun toSkikoPressedMouseButtons(event: MouseEvent): SkikoMouseButtons {
val mask = event.modifiersEx
var result = 0
if (buttons and InputEvent.BUTTON1_DOWN_MASK != 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 (buttons and InputEvent.BUTTON2_DOWN_MASK != 0) {
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 (buttons and InputEvent.BUTTON3_DOWN_MASK != 0) {
result = result.or(SkikoMouseButtons.MIDDLE.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) {
......
......@@ -267,7 +267,8 @@ data class SkikoPointerEvent(
val y: Double,
val deltaX: Double = 0.0,
val deltaY: Double = 0.0,
val buttons: SkikoMouseButtons = SkikoMouseButtons.NONE,
val pressedButtons: SkikoMouseButtons = SkikoMouseButtons.NONE,
val button: SkikoMouseButtons = SkikoMouseButtons.NONE,
val modifiers: SkikoInputModifiers = SkikoInputModifiers.EMPTY,
val kind: SkikoPointerEventKind,
val timestamp: Long = 0,
......@@ -275,11 +276,11 @@ data class SkikoPointerEvent(
)
val SkikoPointerEvent.isLeftClick: Boolean
get() = buttons.has(SkikoMouseButtons.LEFT) && (kind == SkikoPointerEventKind.UP)
get() = button.has(SkikoMouseButtons.LEFT) && (kind == SkikoPointerEventKind.UP)
val SkikoPointerEvent.isRightClick: Boolean
get() = buttons.has(SkikoMouseButtons.RIGHT) && (kind == SkikoPointerEventKind.UP)
get() = button.has(SkikoMouseButtons.RIGHT) && (kind == SkikoPointerEventKind.UP)
val SkikoPointerEvent.isMiddleClick: Boolean
get() = buttons.has(SkikoMouseButtons.MIDDLE) && (kind == SkikoPointerEventKind.UP)
get() = button.has(SkikoMouseButtons.MIDDLE) && (kind == SkikoPointerEventKind.UP)
......@@ -61,13 +61,13 @@ private val SPECIAL_KEYS = setOf(
fun toSkikoEvent(
event: MouseEvent,
buttons: Boolean,
kind: SkikoPointerEventKind
): SkikoPointerEvent {
return SkikoPointerEvent(
x = event.offsetX,
y = event.offsetY,
buttons = toSkikoMouseButtons(event, buttons),
pressedButtons = toSkikoPressedMouseButtons(event, kind),
button = toSkikoMouseButton(event),
modifiers = toSkikoModifiers(event),
kind = kind,
timestamp = event.timeStamp.toLong(),
......@@ -81,7 +81,8 @@ fun toSkikoDragEvent(
return SkikoPointerEvent(
x = event.offsetX,
y = event.offsetY,
buttons = toSkikoMouseButtons(event, true),
pressedButtons = SkikoMouseButtons(buttonsFlags),
button = toSkikoMouseButton(event),
modifiers = toSkikoModifiers(event),
kind = SkikoPointerEventKind.DRAG,
timestamp = event.timeStamp.toLong(),
......@@ -129,14 +130,14 @@ fun toSkikoEvent(
fun toSkikoScrollEvent(
event: WheelEvent,
buttons: Boolean
): SkikoPointerEvent {
return SkikoPointerEvent(
x = event.offsetX,
y = event.offsetY,
deltaX = event.deltaX,
deltaY = event.deltaY,
buttons = toSkikoMouseButtons(event, buttons),
pressedButtons = SkikoMouseButtons(buttonsFlags),
button = SkikoMouseButtons.NONE,
modifiers = toSkikoModifiers(event),
kind = SkikoPointerEventKind.SCROLL,
timestamp = event.timeStamp.toLong(),
......@@ -144,22 +145,34 @@ fun toSkikoScrollEvent(
)
}
private fun toSkikoMouseButtons(
private var buttonsFlags = 0
private fun toSkikoPressedMouseButtons(
event: MouseEvent,
pressed: Boolean
kind: SkikoPointerEventKind
): SkikoMouseButtons {
// https://www.w3schools.com/jsref/event_button.asp
var result = 0
if (pressed && event.button.toInt() == 0) {
result = result.or(SkikoMouseButtons.LEFT.value)
val button = event.button.toInt()
if (kind == SkikoPointerEventKind.DOWN) {
buttonsFlags = buttonsFlags.or(getSkikoButtonValue(button))
return SkikoMouseButtons(buttonsFlags)
}
if (pressed && event.button.toInt() == 2) {
result = result.or(SkikoMouseButtons.RIGHT.value)
}
if (pressed && event.button.toInt() == 1) {
result = result.or(SkikoMouseButtons.MIDDLE.value)
buttonsFlags = buttonsFlags.xor(getSkikoButtonValue(button))
return SkikoMouseButtons(buttonsFlags)
}
private fun toSkikoMouseButton(event: MouseEvent): SkikoMouseButtons {
return SkikoMouseButtons(getSkikoButtonValue(event.button.toInt()))
}
private fun getSkikoButtonValue(button: Int): Int {
return when (button) {
0 -> SkikoMouseButtons.LEFT.value
1 -> SkikoMouseButtons.MIDDLE.value
2 -> SkikoMouseButtons.RIGHT.value
3 -> SkikoMouseButtons.BUTTON_4.value
4 -> SkikoMouseButtons.BUTTON_5.value
else -> 0
}
return SkikoMouseButtons(result)
}
private fun toSkikoModifiers(event: MouseEvent): SkikoInputModifiers {
......
......@@ -62,27 +62,27 @@ actual open class SkiaLayer {
}.apply { initCanvas(desiredWidth, desiredHeight, contentScale) }
// See https://www.w3schools.com/jsref/dom_obj_event.asp
// https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events
htmlCanvas.addEventListener("pointerdown", { event ->
htmlCanvas.addEventListener("mousedown", { event ->
event as MouseEvent
isPointerPressed = true
skikoView?.onPointerEvent(toSkikoEvent(event, true, SkikoPointerEventKind.DOWN))
skikoView?.onPointerEvent(toSkikoEvent(event, SkikoPointerEventKind.DOWN))
})
htmlCanvas.addEventListener("pointerup", { event ->
htmlCanvas.addEventListener("mouseup", { event ->
event as MouseEvent
isPointerPressed = false
skikoView?.onPointerEvent(toSkikoEvent(event, true, SkikoPointerEventKind.UP))
skikoView?.onPointerEvent(toSkikoEvent(event, SkikoPointerEventKind.UP))
})
htmlCanvas.addEventListener("pointermove", { event ->
htmlCanvas.addEventListener("mousemove", { event ->
event as MouseEvent
if (isPointerPressed) {
skikoView?.onPointerEvent(toSkikoDragEvent(event))
} else {
skikoView?.onPointerEvent(toSkikoEvent(event, false, SkikoPointerEventKind.MOVE))
skikoView?.onPointerEvent(toSkikoEvent(event, SkikoPointerEventKind.MOVE))
}
})
htmlCanvas.addEventListener("wheel", { event ->
event as WheelEvent
skikoView?.onPointerEvent(toSkikoScrollEvent(event, isPointerPressed))
skikoView?.onPointerEvent(toSkikoScrollEvent(event))
})
htmlCanvas.addEventListener("contextmenu", { event ->
event.preventDefault()
......
......@@ -19,7 +19,8 @@ fun toSkikoEvent(
return SkikoPointerEvent(
x = xpos,
y = ypos,
buttons = toSkikoMouseButtons(event, kind),
pressedButtons = toSkikoPressedMouseButtons(event, kind),
button = toSkikoMouseButton(event),
modifiers = toSkikoModifiers(event),
kind = kind,
timestamp = timestamp,
......@@ -44,15 +45,15 @@ fun toSkikoEvent(
var buttons: SkikoMouseButtons
if (kind == SkikoPointerEventKind.DOWN) {
buttonsFlags = buttonsFlags.or(button.value)
buttons = SkikoMouseButtons(buttonsFlags)
} else {
buttons = SkikoMouseButtons(buttonsFlags)
buttonsFlags = buttonsFlags.xor(button.value)
}
buttons = SkikoMouseButtons(buttonsFlags)
return SkikoPointerEvent(
x = xpos,
y = ypos,
buttons = buttons,
pressedButtons = buttons,
button = button,
modifiers = toSkikoModifiers(event),
kind = kind,
timestamp = timestamp,
......@@ -77,7 +78,8 @@ fun toSkikoScrollEvent(
y = ypos,
deltaX = event.deltaX,
deltaY = event.deltaY,
buttons = SkikoMouseButtons.NONE,
pressedButtons = SkikoMouseButtons(buttonsFlags),
button = SkikoMouseButtons.NONE,
modifiers = toSkikoModifiers(event),
kind = SkikoPointerEventKind.SCROLL,
timestamp = timestamp,
......@@ -147,7 +149,7 @@ fun toSkikoEvent(
}
private var buttonsFlags = 0
private fun toSkikoMouseButtons(
private fun toSkikoPressedMouseButtons(
event: NSEvent,
kind: SkikoPointerEventKind
): SkikoMouseButtons {
......@@ -156,9 +158,12 @@ private fun toSkikoMouseButtons(
buttonsFlags = buttonsFlags.or(getSkikoButtonValue(button))
return SkikoMouseButtons(buttonsFlags)
}
return SkikoMouseButtons(buttonsFlags).also {
buttonsFlags = buttonsFlags.xor(getSkikoButtonValue(button))
}
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 {
......
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