runModalLoop and Windows 8 touch screen


#1

Hi,

I just discover an issue on a Windows 8 tablet, using the touch screen. A child component running a modal loop is not able to receive “mouse” events coming from the touch screen… but no problem if the "real mouse " is used instead.

Here is a short piece of code showing the issue. I can “touch” the Open button then the modal component is displayed. But at this time I can’t “touch” the Close button. I can “click” it, but not “touch”… you see what I mean? :wink:

Any idea? I know it would be better to migrate my code to use enterModalState instead of runModaLoop, but no time for that right now.

Many thanks in advance,

/Phil

/*
  ==============================================================================

    This file was auto-generated!

    It contains the basic outline for a simple desktop window.

  ==============================================================================
*/

#include "MainWindow.h"

class MyComponent : public Component,
                    public Button::Listener
{
public:
    TextButton btnOpen;
    
    MyComponent()
    {
        addAndMakeVisible(&btnOpen);
        btnOpen.setBounds(20,20,80,20);
        btnOpen.setButtonText("Open");
        btnOpen.addListener(this);
    }

    class MyDialog : public Component,
                     public Button::Listener
    {
    public:
        TextButton btnClose;

        MyDialog()
        {
            addAndMakeVisible(&btnClose);
            btnClose.setBounds(20,20,80,20);
            btnClose.setButtonText("Close");
            btnClose.addListener(this);
        }

        void buttonClicked (Button* button)
        {
            exitModalState(0);
        }

        void paint(Graphics& g)
        {
            g.fillAll(Colours::red);
        }
    };

    void buttonClicked (Button* button)
    {
        MyDialog dlg;
        addAndMakeVisible(&dlg);
        dlg.setBounds(40,40,getWidth()-80,getHeight()-80);
        dlg.runModalLoop();

    }
};


//==============================================================================
MainAppWindow::MainAppWindow()
    : DocumentWindow (JUCEApplication::getInstance()->getApplicationName(),
                      Colours::lightgrey,
                      DocumentWindow::allButtons)
{
    centreWithSize (500, 400);
    setVisible (true);

    setContentOwned(new MyComponent(), false);
}

MainAppWindow::~MainAppWindow()
{
}

void MainAppWindow::closeButtonPressed()
{
    JUCEApplication::getInstance()->systemRequestedQuit();
}

#2

I’m afraid I don’t have a touch-screen yet! Anyone got experience of this?


#3

Welcome to another round of Microsoft hell. I just debugged something similar on a non Juce Win32 app. The short answer is, touch / mouse translation for legacy is weird. Also, the WM_TOUCH / WM_GESTURE stuff introduced in Windows 7 appears to be going obsolete for a new set of WM_POINTERxxxx messages:

http://msdn.microsoft.com/en-us/library/hh454904(v=vs.85).aspx

I turned the tablet back in, but what I ended up doing in my case was registering window handles with RegisterPointerInputTarget:

http://msdn.microsoft.com/en-us/library/hh454911(v=vs.85).aspx

So that I got unified mouse, pen, and touch input. But that has some weird quirks too. The USB touch monitor I have here doesn’t have a suitable Win8 driver, but the next time I have access to a Win8 touch system I’ll take a look at this specific case.


#4

Thanks for the hint :idea:

I tried to use this RegisterPointerInputTarget method… without success. I’ve installed the latest platform SDK and setup WINVER to 0x602, but wasn’t able to get it compiling :?

Anyway, it’s not the best solution for me to use such specific API implying to distribute a special build for Windows 8… I’m already building for XP32, Vista/Seven32, Vista/Seven64, MacOSX, iOS… that’s engough, I don’t want to maintain an additional version just because of the Win8 touch screen that worked very well under Windows 7 :evil:

A better solution could be using an alternate way to handle modal components, probably using enterModalState. But before making change I have to ensure that it is useful under Windows 8 w/ touch screen.


#5

[quote]I tried to use this RegisterPointerInputTarget method… without success. I’ve installed the latest platform SDK and setup WINVER to 0x602, but wasn’t able to get it compiling

Anyway, it’s not the best solution for me to use such specific API implying to distribute a special build for Windows 8… I’m already building for XP32, Vista/Seven32, Vista/Seven64, MacOSX, iOS… that’s engough, I don’t want to maintain an additional version just because of the Win8 touch screen that worked very well under Windows 7 [/quote]

The trick is to dynamically load any functions that aren’t available in all versions of Windows - search the codebase for JUCE_LOAD_WINAPI_FUNCTION to see some examples.


#6

Thanks Jules, it’s an interesting feature.

I tried it and RegisterPointerInputTarget is now called on my tablet, but returns an ERROR_ACCESS_DENIED even UIAccess=true in the manifest .

Searching in Juce source code, I just found that RegisterPointerInputTarget is already used in juce_win32_Windowing.cpp, around line 1295, called with argument 0. That’s probably why my call is failing. So I’ve modified the code, duplicating the call to register mouse, pen, and touch input as suggested by jfitzpat, but I got no change… I lose the touch screen as soon I’m running a modal loop.

Well, I guess the new WM_POINTERxxx stuff should be handled by Juce to fix this issue… hopefully most of the Windows 8 users are still using a mouse at the moment :wink: but for how long…


#7

I can confirm the issue happening on Windows 8 with touchscreen.

I am calling .runModalLoop() on a CallOutBox. I would like to try converting my code to use enterModalState() for testing purpose (to see if events are processed in the modal, however, just replacing .runModalLoop() by .enterModalState() not opening the modal. Is it supposed to ? What should I do to display it?