Project

General

Profile

Actions

Bug #1283

closed

Problems with WPaintedWidget on iPad

Added by Anonymous over 12 years ago. Updated over 12 years ago.

Status:
Closed
Priority:
Normal
Assignee:
Target version:
Start date:
05/07/2012
Due date:
% Done:

0%

Estimated time:

Description

Hello,

I am developing an Windows application with WT, using the WPaintedWidget and server-initiated updates. It works fine with Windows + Linux Browsers. But with an iPad i have the problem, that the application responds on a mouse click not directly. If I click on the iPad (touch it with my finger), i get no response. If I click again, I get the response of the first click. The third click, sends the response of the second click ... and so on.

The WT-application is part of a 3-tier application (server-application - WT-application - browser) and works in the following way:

1) Create the WPaintedWidget and bind an handler for mouse click.

2) Create an socket connection to the server-applikation.

3) If the mouse handler gets an click, send it via the socket to the server-application

4) Create an thread, which reads input from the server-application via the socket.

5) If the server-application sends data, read it in the thread and paint it in the WPaintedWidget with server-initiated updates.

The application is a bit complex. So I have reduced it to a small example, that reproduces the problem. The sending of data to the other application is simulated with a Windows-Event object. The thread waits for the events and the mouse handler signals the event. The data is the position of the click and the response is the drawing of a rectangle on this position. On Firefox/Chrome under Windows/Linux the rectangle will be painted on the position where I clicked (this is OK). With Safari on the iPad the rectangle will be painted on the position where I clicked before this click (this is the problem).

Here is the code of the example:

#include "stdafx.h"

#include <Wt/WApplication>
#include <Wt/WEnvironment>
#include <Wt/WText>
#include <Wt/WPainter>
#include <Wt/WPaintedWidget>
#include <Wt/WContainerWidget>
using namespace Wt;

#include <process.h>

class HtmlCanvas : public WPaintedWidget
{
private:
    int cnt;
    int x, y;

public:
    HtmlCanvas(WContainerWidget *parent = 0);
    void changeContent(int nx, int ny);

protected:
    virtual void paintEvent(WPaintDevice *paintDevice);
};

HtmlCanvas::HtmlCanvas(WContainerWidget *parent)
  : WPaintedWidget(parent)
{
    cnt = 0; x = 10; y = 10;
    resize(300, 400);
}

void HtmlCanvas::changeContent(int px, int py) {
    x = px;
    y = py;
}

void HtmlCanvas::paintEvent(WPaintDevice *paintDevice) {
    wchar_t buff[20];

    _swprintf(buff, _T("%d"), cnt);
    cnt++;
    WPainter painter(paintDevice);
    painter.drawRect(0.0, 0.0, 300, 400);
    painter.setBrush(WBrush(WColor(200, 200, 200)));
    painter.drawRect(x, y, 100, 30);
    painter.drawText(x+5, y+5, 100-10, 30-10, AlignCenter, WString(buff));  
}

class SimpleApplication : public WApplication {

public:
    HANDLE m_signalData;
    HtmlCanvas* m_htmlCanvas;

    SimpleApplication (const WEnvironment& env);
    void HtmlCanvasMouseUp(const Wt::WMouseEvent& e);
};

SimpleApplication::SimpleApplication (const WEnvironment& env)
  : WApplication(env) {

    enableUpdates(true);

    setTitle("SimpleWt");

    root()->addWidget(new WText("<h1>SimpleWt</h1>"));

    m_htmlCanvas = new HtmlCanvas(root());
    m_htmlCanvas->setPreferredMethod(WPaintedWidget::HtmlCanvas);
    m_htmlCanvas->setOffsets(WLength(0), WFlags<Side>(Top));
    m_htmlCanvas->setOffsets(WLength(0), WFlags<Side>(Left));

    m_htmlCanvas->mouseWentUp().connect(this, &SimpleApplication::HtmlCanvasMouseUp);
    m_signalData = CreateEvent(NULL, FALSE, FALSE, NULL);
}

void SimpleApplication::HtmlCanvasMouseUp(const Wt::WMouseEvent& e) {
    m_htmlCanvas->changeContent(e.widget().x, e.widget().y);
    SetEvent(m_signalData);
} 

static void StartThread(void* p) {
    SimpleApplication* simpleApplication = (SimpleApplication*)p;
    for(;;) {
        WaitForSingleObject(simpleApplication->m_signalData , INFINITE);

        WApplication* wAp = simpleApplication;
        Wt::WApplication::UpdateLock lock(wAp);
        if (lock) {
            WFlags<PaintFlag> fl(PaintUpdate);

            simpleApplication->m_htmlCanvas->update(fl);
            wAp->triggerUpdate();
        }
    }
}

WApplication* createWTApp(const WEnvironment& env) {
    SimpleApplication* simpleApplication = new SimpleApplication (env);
    _beginthread(StartThread, 0, (LPVOID)simpleApplication);
    return simpleApplication;
}


int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) {
    char *argv[] = { "SimpleWt.exe", "--http-address=0.0.0.0", "--http-port=8080", "--deploy-path=/simpleWt", "--docroot=."};

    WRun(5, argv, &createWTApp);
}

I used the following environment:

  • Visual Studio 2008
  • WT 3.2.1
  • boost-1.46.1
  • Windows XP Service Pack 3
  • iPad2 Version 5.1(9B176)

The problem only occurs with the http-connector. With the ISAPI-connector the response will be send directly on the iPad too. I have not tried the fastCGI connector, because it is not available on windows.

I have added the Visual Studio Project of the example as attachment.

Thank you for solving the problem.

Herbert Zenz

Nonne & Schneider Informationssysteme GmbH

hrz@nsi.de


Files

SimpleWt.zip (12.6 KB) SimpleWt.zip Anonymous, 05/07/2012 06:19 PM
iPadProblem.cpp (2.85 KB) iPadProblem.cpp Koen Deforche, 05/18/2012 06:12 PM
Actions #1

Updated by Koen Deforche over 12 years ago

  • Status changed from New to Feedback
  • Assignee set to Koen Deforche
  • Target version set to 3.2.2

Hey,

Intriguing that it makes a difference wthttpd versus ISAPI... If not, I would have guessed that perhaps mouseWentUp() is not properly mapped to a touch event. Would it work properly if you change it for a touch event (touchEnded()) ?

Regards,

koen

Actions #2

Updated by Herbert Zenz over 12 years ago

Hello,

The problem is not the mouse handler, it is the response in the Html-Canvas in form of HtmlCanvas::paintEvent().

If I click on the iPad, the mouse handler will be triggered immediately, but HtmlCanvas::paintEvent()

will not be called.

To illustrate the problem, I have set some breakpoints, clicked on the canvas and looked for reaching

the breakpoints.

                                                            iPad           firefox  iPad with ISAPI
SimpleApplication::HtmlCanvasMouseUp()                      reached    reached  reached     
void WebSession::setTriggerUpdate()                         reached        reached  reached
void HtmlCanvas::paintEvent()                               *not* reached  reached  reached

The problem is between WebSession::setTriggerUpdate() and HtmlCanvas::paintEvent().

Nevertheless, I have tried using touch events - with some more problems:

1. It is not possible to get the position, the vector tv (see code below) has the size 0, if i

click.

2. If I use gestures (zoom, move zoomed screen), the handler will be called too, which must be

ignored. This is not so, if the mouseUp() handler is used.

3. Sometimes the handler will be called twice, if I use gestures and in some of these cases the argument contains a position.

Here is the code I used:

...
m_htmlCanvas->touchEnded().connect(this, &SimpleApplication::HtmlCanvasTouchEnd);
...
void SimpleApplication::HtmlCanvasTouchEnd(const Wt::WTouchEvent& e) {
    std::vector<Touch> tv = e.touches();
    int num = tv.size();

    if (num > 0) {
        m_htmlCanvas->changeContent(tv[0].widget().x, tv[0].widget().y);
        SetEvent(m_signalData);
    }
}

Regards,

Herbert

Actions #3

Updated by Koen Deforche over 12 years ago

Hey,

I can't reproduce this problem with iPad + wthttpd on linux (and wt git).

I modified the example (but only to use boost::thread instead of windows specific condition variables).

Should this example still exhibit the problem ?

Regards,

koen

Actions #4

Updated by Herbert Zenz over 12 years ago

Sorry for the long waiting time, but we have only one iPad in the company for testing such things.

I have tested your example with Windows and I got the same problem.

The problem is not in the synchronization of the threads. I thinks it lies in the communication between the server (http-connector) and the browser, which uses sockets. The implementation of sockets has many differences between windows and linux/unix.

Our application works only with Windows, because it uses many WIN32 API calls, .NET and the com-API. So I must use the Windows version of WT.

Regards,

Herbert

Actions #5

Updated by Wim Dumon over 12 years ago

Herbert,

I tested wt git head on Windows 7, boost 1.47, wthttp connector, and all seems to work fine. Are you also testing the http connector?

Wim.

Actions #6

Updated by Herbert Zenz over 12 years ago

Hello Wim,

Yes - I tested the http connector and the problem only occur with it and not with the IIS connector.

But I used Windows XP and the actual version of WT: 3.2.1.

Now I have tested my example with the wt git head (and Windows XP) ... and the problem does not occur. So I hope it will be solved in the next release of wt.

Thank you for your support!

Regards

Herbert

Actions #7

Updated by Koen Deforche over 12 years ago

  • Status changed from Feedback to Closed
Actions

Also available in: Atom PDF