On Win7 touch input, Button::Listener::buttonClicked is called twice when tapped with finger, only once when clicked with mouse


#1

Hi!

This is what I found after a remote debugging session with a Win7 multitouch laptop, where I was trying to see why my toggle buttons only worked some of the time when using the touch-screen:

While when clicked with the mouse, the button only calls its buttonClicked event once, when it is tapped with the finger, the event may be called once, but very often it is instead called twice!

In the below code, in the case where the buttonClicked even is triggered twice from a single tap, the button behaves as if it was never touched, since it toggles to the new state and then back to the old one very quickly:

void AITreeViewAIItemComponent::buttonClicked(Button* buttonThatWasClicked) {
   if(buttonThatWasClicked == &m_OpenCloseButton) {
        if (!m_OpenCloseButton.isMouseButtonDown()) {
            if (buttonThatWasClicked->getToggleState()) {
                if (r_Item->mightContainSubItems())
                    r_Item->setOpen(true);
            }
            else {
                r_Item->setOpen(false);
            }
        }
    }
}

I can't see any way in which I can discriminate beetween the first and second call to the event, I tried adding the check to isMouseButtonDown but it is true both times.

Here's two stack traces, from the first and second call to the event aboe respectively:

First time buttonClicked is called:

     TWO.exe!AITreeViewAIItemComponent::buttonClicked(juce::Button * buttonThatWasClicked) Line 209    C++
     TWO.exe!juce::ListenerList<juce::Button::Listener,juce::Array<juce::Button::Listener *,juce::DummyCriticalSection,0> >::callChecked<juce::Component::BailOutChecker,juce::Button *>(const juce::Component::BailOutChecker & bailOutChecker, void (juce::Button *) * callbackFunction, juce::Button * param1) Line 178    C++
     TWO.exe!juce::Button::sendClickMessage(const juce::ModifierKeys & modifiers) Line 411    C++
     TWO.exe!juce::Button::setToggleState(bool shouldBeOn, juce::NotificationType notification) Line 190    C++
     TWO.exe!juce::Button::internalClickCallback(const juce::ModifierKeys & modifiers) Line 350    C++
     TWO.exe!juce::Button::mouseUp(const juce::MouseEvent & e) Line 461    C++
     TWO.exe!juce::Component::internalMouseUp(juce::MouseInputSource source, juce::Point<float> relativePos, juce::Time time, const juce::ModifierKeys oldModifiers) Line 2497    C++
     TWO.exe!juce::MouseInputSourceInternal::sendMouseUp(juce::Component & comp, juce::Point<float> screenPos, juce::Time time, const juce::ModifierKeys oldMods) Line 148    C++
>    TWO.exe!juce::MouseInputSourceInternal::setButtons(juce::Point<float> screenPos, juce::Time time, const juce::ModifierKeys newButtonState) Line 191    C++
     TWO.exe!juce::MouseInputSourceInternal::handleEvent(juce::ComponentPeer & newPeer, juce::Point<float> positionWithinPeer, juce::Time time, const juce::ModifierKeys newMods) Line 306    C++
     TWO.exe!juce::MouseInputSource::handleEvent(juce::ComponentPeer & peer, juce::Point<float> pos, __int64 time, juce::ModifierKeys mods) Line 568    C++
     TWO.exe!juce::ComponentPeer::handleMouseEvent(int touchIndex, juce::Point<float> pos, juce::ModifierKeys newMods, __int64 time) Line 91    C++
     TWO.exe!juce::HWNDComponentPeer::doMouseEvent(juce::Point<float> position) Line 1659    C++
     TWO.exe!juce::HWNDComponentPeer::doMouseMove(juce::Point<float> position) Line 1741    C++
     TWO.exe!juce::HWNDComponentPeer::peerWindowProc(HWND__ * h, unsigned int message, unsigned int wParam, long lParam) Line 2420    C++
     TWO.exe!juce::HWNDComponentPeer::windowProc(HWND__ * h, unsigned int message, unsigned int wParam, long lParam) Line 2353    C++
     [External Code]    
     [Frames below may be incorrect and/or missing, no symbols loaded for user32.dll]    
     TWO.exe!juce::MessageManager::dispatchNextMessageOnSystemQueue(bool returnIfNoPendingMessages) Line 135    C++
     TWO.exe!juce::MessageManager::runDispatchLoopUntil(int millisecondsToRunFor) Line 99    C++
     TWO.exe!juce::MessageManager::runDispatchLoop() Line 87    C++
     TWO.exe!juce::JUCEApplicationBase::main() Line 244    C++
     TWO.exe!WinMain(HINSTANCE__ * __formal, HINSTANCE__ * __formal, char * __formal, int __formal) Line 142    C++
     [External Code]    

Second time buttonClicked is called:

>    TWO.exe!AITreeViewAIItemComponent::buttonClicked(juce::Button * buttonThatWasClicked) Line 209    C++
     TWO.exe!juce::ListenerList<juce::Button::Listener,juce::Array<juce::Button::Listener *,juce::DummyCriticalSection,0> >::callChecked<juce::Component::BailOutChecker,juce::Button *>(const juce::Component::BailOutChecker & bailOutChecker, void (juce::Button *) * callbackFunction, juce::Button * param1) Line 178    C++
     TWO.exe!juce::Button::sendClickMessage(const juce::ModifierKeys & modifiers) Line 411    C++
     TWO.exe!juce::Button::setToggleState(bool shouldBeOn, juce::NotificationType notification) Line 190    C++
     TWO.exe!juce::Button::internalClickCallback(const juce::ModifierKeys & modifiers) Line 350    C++
     TWO.exe!juce::Button::mouseUp(const juce::MouseEvent & e) Line 461    C++
     TWO.exe!juce::Component::internalMouseUp(juce::MouseInputSource source, juce::Point<float> relativePos, juce::Time time, const juce::ModifierKeys oldModifiers) Line 2497    C++
     TWO.exe!juce::MouseInputSourceInternal::sendMouseUp(juce::Component & comp, juce::Point<float> screenPos, juce::Time time, const juce::ModifierKeys oldMods) Line 148    C++
     TWO.exe!juce::MouseInputSourceInternal::setButtons(juce::Point<float> screenPos, juce::Time time, const juce::ModifierKeys newButtonState) Line 191    C++
     TWO.exe!juce::MouseInputSourceInternal::handleEvent(juce::ComponentPeer & newPeer, juce::Point<float> positionWithinPeer, juce::Time time, const juce::ModifierKeys newMods) Line 306    C++
     TWO.exe!juce::MouseInputSource::handleEvent(juce::ComponentPeer & peer, juce::Point<float> pos, __int64 time, juce::ModifierKeys mods) Line 568    C++
     TWO.exe!juce::ComponentPeer::handleMouseEvent(int touchIndex, juce::Point<float> pos, juce::ModifierKeys newMods, __int64 time) Line 91    C++
     TWO.exe!juce::HWNDComponentPeer::doMouseEvent(juce::Point<float> position) Line 1659    C++
     TWO.exe!juce::HWNDComponentPeer::doMouseUp(juce::Point<float> position, const unsigned int wParam) Line 1770    C++
     TWO.exe!juce::HWNDComponentPeer::peerWindowProc(HWND__ * h, unsigned int message, unsigned int wParam, long lParam) Line 2429    C++
     TWO.exe!juce::HWNDComponentPeer::windowProc(HWND__ * h, unsigned int message, unsigned int wParam, long lParam) Line 2353    C++
     [External Code]    
     [Frames below may be incorrect and/or missing, no symbols loaded for user32.dll]    
     TWO.exe!juce::MessageManager::dispatchNextMessageOnSystemQueue(bool returnIfNoPendingMessages) Line 135    C++
     TWO.exe!juce::MessageManager::runDispatchLoopUntil(int millisecondsToRunFor) Line 99    C++
     TWO.exe!juce::MessageManager::runDispatchLoop() Line 87    C++
     TWO.exe!juce::JUCEApplicationBase::main() Line 244    C++
     TWO.exe!WinMain(HINSTANCE__ * __formal, HINSTANCE__ * __formal, char * __formal, int __formal) Line 142    C++
     [External Code]    

 

Formatting could be better, but it is what it is...

I'd say this seems like a bug to me, somewhere in the first stack trace, what shouldn't really be a mouseUp event seems to become one, but of course I could be wrong...

 

Is this a bug? If not, how do you recommend I get toggle buttons that respond consistently to touch input?

 

Thanks!

Ilias B.

 


#2

It looks like the OS is generating a mouse-click from the fake touch event. The mystery mouse-up is because this ends up looking like two mouse-downs in succession, and the other mouseUp is inserted automatically, to enforce the order of an up always following a down event.

I vaguely remember fixing this some ago.. You're on the latest version, right?


#3

Hi,

Yes, I updated juce from git 5 days ago!

The strange thing is, if it is of any help, I don't remember this happen on a friend's Win 8.1 touch-screen laptop, only on my win 7 one. But both were multi-touch. I have not remote-debugged with my friend's laptop, nor have I installed 8.1 on mine, so the above is anecdotal for the moment...

What confused me is that it is not always two events from one tap, sometimes it is one event. It seems to be sensitive to how I do the tap. If it is a bit sloppy (not too much, just the gesture I'm used to doing on my mobile), it triggers two events, if it is executed with surgical precision, I seem to consistently get one event (with a stack-trace like the second one).

So maybe the few milliseconds of the finger moving by 1-2 pixels during the tap is at fault.


#4

So maybe the few milliseconds of the finger moving by 1-2 pixels during the tap is at fault.

Could be.. Would need to fire up my win8 tablet and try it out, but haven't time to do that right now.