Closed haikalpribadi closed 2 years ago
If there's no out-of-the-box solution to detect left, right, and double click at once right now, the only workaround I can think of is to:
Use mouseClickable()
that takes advantage of MouseClickScope
and detect left and right click, using buttons.isPrimaryPressed
and buttons.isSecondaryPressed
. Then, in the logic that handles left click, check whether the last left click was very recent (e.g. less than 500ms ago) and if so execute your onDoubleClick
function. However, how can we know what the OS's default double-click duration limit? I believe this is configurable differently on everyone's OS, right? So we don't want to just hard code our own arbitrary number such as 500ms (albeit common) ?
Any updates, @akurasov ? Thanks!
I just realised, that if you provide an API to get the clickCount()
in MouseClickScope
(through mouseClickable()
) then this whole problem is solved. MouseClickScope
already provides isPrimary
and isSecondary
. With clickCount()
it would be perfect!
Okay, I've figured out how to achieve the above issue now:
modifier = Modifier.onPointerEvent(PointerEventType.Press) {
when {
it.buttons.isPrimaryPressed -> when (it.awtEvent.clickCount) {
1 -> onSingleLeftClick()
2 -> onDoubleLeftClick()
}
it.buttons.isSecondaryPressed -> onRightClick()
}
}
I'll close this issue now.
PS: Note that when a double click is performed on a mouse, the first click is registered as its own event too. Apparently, this seems to be standard UX in the operating system. So if you're implementing this, make sure that your first event (onSingleLeftClick()
) does not conflict with your second event (onDoubleLeftClick()
). The second event should be able to naturally follow after the first event. An example of this UX would be the act of single & double clicking on a file icon. The first click can trigger the "selection" of the file icon, and the second event can trigger the "opening" of the file represented by the icon. This way the both events can happen subsequently and not cause conflicting UX.
If we use AWT interop, it is better to check it.awtEvent.button:
when (it.awtEvent.button) {
MouseEvent.BUTTON1 -> when (it.awtEvent.clickCount) {
1 -> onSingleLeftClick()
2 -> onDoubleLeftClick()
}
MouseEvent.BUTTON3 -> onRightClick()
}
Because it.buttons.isPrimaryPressed
represents the state of the button, not the property of the event (i.e. if press the second button, and the first button is pressed, isPrimaryPressed
will return true).
To properly implement simultaneous handling of left/right clicks using only Compose API, we should store the state of the buttons (wasPrimaryPressed
) and compare it with the current state. But that is too verbose, and that is why Compose needs high-level API for handling simultaneous left/right clicks (we plan to look at that).
Thanks, @igordmn . If we follow your suggestion above, what would be the it.awtEvent.button
be when the user clicks both left and right simultaneously?
what would be the it.awtEvent.button be when the user clicks both left and right simultaneously?
When we press the right button (and the left is already pressed) - it will be MouseEvent.BUTTON3
When we press the left button (and the right is already pressed) - it will be MouseEvent.BUTTON1
So it's the last button that user pressed?
So it's the last button that user pressed?
Yes (more precisely it is the button, associated with the event)
I see. I'll go with your suggestion, then, @igordmn. Thanks!
Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.
Hi 👋🏽 I need a component to listen 3 types of mouse clicks: a) single left click (aka primary) b) single right click (aka secondary), and c) double (left) click
I've experimented with
Modifier.mouseClickable()
and.combinedClickable()
, and I've tested out the documentation outlined here: https://github.com/JetBrains/compose-jb/blob/master/tutorials/Mouse_Events/README.mdI can confirm that
mouseClickable()
takes inMouseClickScope.() -> Unit
that allows us to identify (a) single left click and (b) single right click, usingbuttons.isPrimaryPressed
andbuttons.isSecondaryPressed
properties in theMouseClickScope
. I can also confirm that.combinedClickable()
allows us to detect (a) single left click and (c) double (left) click, usingonClick
andonDoubleClick
callback arguments.However, I can't figure out a solution that would allow me to detect all 3 of (a) (b) and (c) at once. Appending
Modifier.mouseClickable(...).combinedClickable(...)
orModifier.combinedClickable(...).mouseClickable(...)
would only register the last of the two clickable setting.Can anyone tell me if it is possible to identify all 3 clicks on one component, right now? If so, how to go about it? If not, what's missing and what can we do to help implement it?
Thanks!