Bug #1283
closedProblems with WPaintedWidget on iPad
0%
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
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
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
Updated by Koen Deforche over 12 years ago
- File iPadProblem.cpp iPadProblem.cpp added
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
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
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.
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
Updated by Koen Deforche over 12 years ago
- Status changed from Feedback to Closed