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