Inconsistent behaviour of isMouseOver() between physical mouse and touch screen

gui
windows

#1

Touch device (Windows 64 bit) 2 in 1 PC (convertible).

When in a Widget’s mouseUp() callback handler you call isMouseOver(true) you receive:

  1. true when using a physical mouse (and the pointer is on the widget)
  2. false when you use the touch display (and your finger is on the widget when you lift it up)

If you move the mouse pointer over the widget and then touch and lift your finger then isMouseOver(true) gives back true.

How am I supposed to test if the user has lifted up the finger over the widget it has clicked (= touched) a moment before?

Although I was extremely careful of NOT moving the finger in between the press (touch) and the release (lift), I have also tested isMouseOverOrDragging(true), just in case. The result is always the same: false is returned.

It seems to me a juce bug. Or not?


#2

Well… the current behaviour isn’t wrong… It’s a bit of a grey area, depending on how you think about it.

For example in a button that has down/over/normal states, you wouldn’t want it to go into its “over” state on a touch-up like you would for a mouse-up, since the “over” state doesn’t really exist for touches. So for that, it makes sense that the mouse is never “over” it.

I agree it’s a bit unexpected in the context you’re talking about here, but have a look at how Button handles this internally:


#3

Thanks for the reply. The workaround used in the code you pasted is, well, a workaround. That does not solve the conceptual problem.

The mouseUp() callback belongs to the Component class abstraction, which is far more general than a particular derived class, among many, like Button.
Component should not provide a (limiting and inconsistent) implementation because it is possibly more useful for a partcular implementation of one of its descendants, but wrong for all the others.
And, by the way, it is so obvious and ortogonal: touch = click, lift = release. And when I release I could be over the clicked component or not (if I moved the mouse/finger enough far away); isMouseOver() should tell me if I am “over” the component or not. I then could ask MouseEvent the MouseInputSource, and call on it isMouse(), isTouch(), isPen().
Hovering is a complete different concept, that applies even when you are not clicking/releasing. A touch device cannot detected an hovering finger detached from screen contact, but can definitely tell if it is over something (without the leading H) when you touch/drag/lift the finger (and generate the corresponding mouse events). A detached finger will leave the mouse pointer at its last known position (when you released/lifted the finger). It will be updated as soon as you touch again the screen.
Every derived class can do its business out of these general, simple, and logical base blocks.

I hope to have used the correct terms, since English is not my language.

What do you think?


#4

No, it’s not a workaround. You’re making assumptions about isMouseOver which aren’t correct.

The job of isMouseOver() is to tell you whether the mouse is currently over a component. In the case of a touch, that’s always false unless the finger is still down. When mouseUp is called, the finger already up, therefore it’s consistent for isMouseOver to return false.

The question you should be asking is where the finger was when the mouseUp event happened, not where it currently is at the time of the callback. That position information lives in the MouseEvent structure, and that’s why Button uses it to decide whether the click was inside it or not.

The important point here is that isMouseOver is not tied to events. Just because you call it during a mouseUp callback doesn’t mean that it’ll tell you about that event. It has no idea that you’re in the middle of an event callback!


#5

OK. I think you should make explicit this design decision by incorporating this explanation into the isMouseOver() documentation.

In fact the word “mouse” in many functions names has been stretched over the years to support also different pointing devices (i.e.: touch screens). But this extension does not always hold true, as it is the case of isMouseOver() which is really meaningful only for mice (while the user might reasonably, but incorrectly, assume it is valid for every pointing device).

Regards.


#6

Yes, that’s a good point about the meaning of “mouse” in these functions. Back when I created all the classes for this, touches weren’t really a thing that anyone was thinking about!