Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Designing a unified multi-click API #859

Closed
xStrom opened this issue Apr 19, 2020 · 18 comments
Closed

Designing a unified multi-click API #859

xStrom opened this issue Apr 19, 2020 · 18 comments
Labels
discussion needs feedback and ideas shell concerns the shell abstraction

Comments

@xStrom
Copy link
Member

xStrom commented Apr 19, 2020

While working on #843 I also started thinking about double-clicks and how to best do them. I think that the behavior should match across platforms so that druid users can just read the druid docs and not worry about platform specifics.

Double-clicks are good, triple-clicks possibly worth it, but what about quadruple-clicks or even more? I'm not sure there's really much value in going beyond three. It's definitely more work.

  • Windows natively supports only up to double, so will need a custom implementation anyway.
  • GTK seems to support triple clicks, so we can probably piggyback on that for up to triple.
  • macOS supports up to triple on most buttons, but seems to be practically unbounded for left and right buttons. We can piggyback on the platform for up to triple, including unbounded_count % 3.
  • Web has some support via UIEvent.detail but I haven't tested how well it works.

Custom implementations (which Windows will need anyway) will need to be careful to follow the user configured OS setting for double click timeout.

Thus I propose the following unified API:

  • Support for up to triple-clicks.
  • Both MouseDown and MouseUp contain the click count.
  • No extra double or triple click events, it's merely an extra event property for those who care.
@xStrom xStrom added discussion needs feedback and ideas shell concerns the shell abstraction labels Apr 19, 2020
@cmyr
Copy link
Member

cmyr commented Apr 27, 2020

I think this design makes sense.

If we're using a simple timer to determine whether a click is part of a 'click sequence' I'm not sure if it makes much difference whether or not we stop at three, but I also don't think quadruple clicks are a problem we need to worry about in this century? Famous last words?

@ratmice
Copy link
Collaborator

ratmice commented Apr 27, 2020

Question about click count, If i recall, mac OS would send sequentially higher click counts, so you would get an event with MouseDown and click count 1, then one with 2, etc.
Is this what you had in mind, or would their be a single event with click count 2.

Double clicks and event propagation can sometimes be tricky, presume it's possible that the first click gets put on some system platform event queue, same for the second click +incr click count,
the first event causes the window to close, the target for the 2nd event now no longer exists.

Anyhow its just an awkward case to keep in mind

Edit: Another thing to keep in mind with macOS, I don't recall if its clickCount is actually zerod by a timer at all. It may in fact be zerod only when the mouse location changes. There is a timestamp there associated with each event so they don't necessarily lose the ability to derive whether a click is a part of a click sequence.

@cmyr
Copy link
Member

cmyr commented Apr 27, 2020

It's a timer. playing around, here are three events with different positions that count as a click sequence, and then two events in the same location that don't:

(155.7109375, 201.76953125): 1
(155.41796875, 201.26171875): 2
(154.8828125, 200.51171875): 3

(147.55859375, 248.6640625): 1
(147.55859375, 248.6640625): 1

@xStrom
Copy link
Member Author

xStrom commented Apr 27, 2020

Yes my earlier macOS findings match this, indeed it's a timer.

As for what I meant for events, I mean that every physical click of a button will generate exactly one click event, no more. Each click event has a count associated with it, so those apps that care about differentiating double clicks can look at that while most apps can just ignore it.

@xStrom
Copy link
Member Author

xStrom commented Apr 27, 2020

If we're using a simple timer to determine whether a click is part of a 'click sequence' I'm not sure if it makes much difference whether or not we stop at three

That's true, but that's also why I want to stop at three. Because then we don't have to use a timer ourselves on some platforms like macOS. There we can just use the OS provided count which is guaranteed to respect OS settings.

@cmyr
Copy link
Member

cmyr commented Apr 27, 2020

I'm happy to stop at three, but on macOS couldn't we just use the clickCount property, which can be any integer?

@xStrom
Copy link
Member Author

xStrom commented Apr 28, 2020

macOS clickCount also stops at three with middle/X1/X2 in my testing. It's only left/right which can be any integer.

If you see more than 3 with all buttons then that would be interesting.

@cmyr
Copy link
Member

cmyr commented Apr 28, 2020

interesting yea there's weird stuff going on. I can get the middle mouse button up to ten repeats, but not higher.

Also interesting: it doesn't seem like the click count is button dependent; if I alternate between right and left it keeps incrementing.

I think most of this is just weird buggy edge case stuff that we can ignore. Three is a reasonable limit. I guess one thing to think about, though, is what happens on the 4th click; do we send click count of 1? The middle button seems to get weirdly throttled on my current mouse, but I don't trust my hardware particularly, and I don't seem to have another mouse around.

@xStrom
Copy link
Member Author

xStrom commented Apr 28, 2020

I think doing (count - 1) % 3 + 1 to just wraparound to a 1/2/3 sequence is a good way to harvest the larger OS count with some value.

@xStrom
Copy link
Member Author

xStrom commented Apr 28, 2020

I did some more testing. I can actually get the middle button up to 4, but no more. X1/X2 are 3 max.

The interesting situation however is having the count increase while switching between left & right buttons. This doesn't work when switching between other buttons.

I don't think this is something we would want. Doing a single right click and then a single left click shouldn't execute a double left click action. Testing macOS itself in Finder for example, doing a right click and then a left click doesn't open a folder. I'm not sure what it's doing underneath, but it's not just checking the click count.

I think the druid API should guarantee that the click count is per button. This allows for simple double click detection logic in the app.

@ratmice
Copy link
Collaborator

ratmice commented Apr 28, 2020

Interesting about non-differentiation between buttons, at least during some point in history, it was possible to treat all buttons the same so left/right could be treated as a single button... probably a bug that isn't taking single-button vs multi-button into account.

@cmyr
Copy link
Member

cmyr commented Apr 28, 2020

I agree, and I the the implementation might actually get simpler if we don't rely on on system detection, assuming we have some way of getting the correct 'click interval'; this is trivial on macos, exposed on the NSEvent class as doubleClickInterval

@xStrom
Copy link
Member Author

xStrom commented Apr 28, 2020

Indeed, after learning of these subtleties, the manual implementation is looking more attractive.

@ForLoveOfCats
Copy link
Collaborator

I was reading through this and assumed that this proposed system had yet to be implemented but (on the GTK shell) I was surprised to see that the MouseDown event has a count field which reports the click count. Was there some PR adding this to the GTK shell that I cannot find? I'm pleased to be able to have something like this working in some sense already but it has some odd behaviour which makes me want to read through the PR which added this.

@xStrom
Copy link
Member Author

xStrom commented May 19, 2020

The current GTK click count was added in #151 so it has always been there. The count currently exists in some form on GTK, macOS, and Windows. This issue here is about improving it further and also crucially making it behave the same across platforms.

@wrl
Copy link

wrl commented Aug 24, 2020

The way I handle this in Rutabaga is to have a platform function for retrieving the current double-click interval and then incrementing a click-counter when synthesising a click event. This is easy to get on Windows and macOS, but I punted on the Linux approach.

raphlinus added a commit that referenced this issue Aug 24, 2020
This is a partial fix for #859, addressing only the Windows platform.
But in general it should represent how we want to handle this.
@raphlinus
Copy link
Contributor

There is some more work to be done here. One thing I noticed in testing Runebender on Linux is that on double-click, Gtk sends both a GDK_BUTTON_PRESS and a GDK_2BUTTON_PRESS event. In our translation layer, this sends two mouse-down events, with count of 1 and 2. That in turn trips an internal invariant in RB's mouse handling, and thus a panic.

I did a little digging, and don't see an easy way to fix this on Gtk. I think it's likely we'll end up having to do our own click counting, just as we do on Windows. There, a challenge is to pick up the preferences. But I suspect it's not impossible to read those from the same source as Gtk, so we're consistent.

raphlinus added a commit that referenced this issue Oct 15, 2020
Do our own click counting rather than relying on the count given by Gtk.
Among other things, this avoids the problems of multiple click events.

Progress towards #859
@PoignardAzur
Copy link
Collaborator

Is this issue still relevant? MouseEvent has a count field now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion needs feedback and ideas shell concerns the shell abstraction
Projects
None yet
Development

No branches or pull requests

7 participants