2011-02-05 Sheriff Bot <webkit.review.bot@gmail.com>
[WebKit.git] / Tools / QtTestBrowser / launcherwindow.cpp
1 /*
2  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
3  * Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in>
4  * Copyright (C) 2006 George Staikos <staikos@kde.org>
5  * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
6  * Copyright (C) 2006 Zack Rusin <zack@kde.org>
7  * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org>
8  *
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
21  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
28  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include "launcherwindow.h"
34
35 const int gExitClickArea = 80;
36 QVector<int> LauncherWindow::m_zoomLevels;
37
38 LauncherWindow::LauncherWindow(WindowOptions* data, QGraphicsScene* sharedScene)
39     : MainWindow()
40     , m_currentZoom(100)
41     , m_view(0)
42     , m_inspector(0)
43     , m_formatMenuAction(0)
44     , m_zoomAnimation(0)
45 {
46     if (data)
47         m_windowOptions = *data;
48
49     init();
50     if (sharedScene && data->useGraphicsView)
51         static_cast<QGraphicsView*>(m_view)->setScene(sharedScene);
52
53     createChrome();
54 }
55
56 LauncherWindow::~LauncherWindow()
57 {
58     grabZoomKeys(false);
59
60     if (page())
61         page()->setQnamThreaded(false);
62 }
63
64 void LauncherWindow::init()
65 {
66     QSplitter* splitter = new QSplitter(Qt::Vertical, this);
67     setCentralWidget(splitter);
68
69 #if defined(Q_OS_SYMBIAN)
70     setWindowState(Qt::WindowMaximized);
71 #else
72     setWindowState(Qt::WindowNoState);
73     resize(800, 600);
74 #endif
75
76     m_inspector = new WebInspector;
77 #ifndef QT_NO_PROPERTIES
78     if (!m_windowOptions.inspectorUrl.isEmpty())
79         m_inspector->setProperty("_q_inspectorUrl", m_windowOptions.inspectorUrl);
80 #endif
81     connect(this, SIGNAL(destroyed()), m_inspector, SLOT(deleteLater()));
82
83     // the zoom values are chosen to be like in Mozilla Firefox 3
84     if (!m_zoomLevels.count()) {
85         m_zoomLevels << 30 << 50 << 67 << 80 << 90;
86         m_zoomLevels << 100;
87         m_zoomLevels << 110 << 120 << 133 << 150 << 170 << 200 << 240 << 300;
88     }
89
90     grabZoomKeys(true);
91
92     initializeView();
93 }
94
95 void LauncherWindow::initializeView()
96 {
97     delete m_view;
98
99     m_inputUrl = addressUrl();
100     QUrl url = page()->mainFrame()->url();
101     setPage(new WebPage(this));
102     page()->setQnamThreaded(m_windowOptions.useThreadedQnam);
103
104     QSplitter* splitter = static_cast<QSplitter*>(centralWidget());
105
106     if (!m_windowOptions.useGraphicsView) {
107         WebViewTraditional* view = new WebViewTraditional(splitter);
108         view->setPage(page());
109
110         view->installEventFilter(this);
111
112         m_view = view;
113     } else {
114         WebViewGraphicsBased* view = new WebViewGraphicsBased(splitter);
115         view->setPage(page());
116
117         connect(view, SIGNAL(currentFPSUpdated(int)), this, SLOT(updateFPS(int)));
118
119         view->installEventFilter(this);
120         // The implementation of QAbstractScrollArea::eventFilter makes us need
121         // to install the event filter also on the viewport of a QGraphicsView.
122         view->viewport()->installEventFilter(this);
123
124         m_view = view;
125     }
126
127     m_touchMocking = false;
128
129     connect(page(), SIGNAL(loadStarted()), this, SLOT(loadStarted()));
130     connect(page(), SIGNAL(loadFinished(bool)), this, SLOT(loadFinished()));
131     connect(page(), SIGNAL(linkHovered(const QString&, const QString&, const QString&)),
132             this, SLOT(showLinkHover(const QString&, const QString&)));
133     connect(this, SIGNAL(enteredFullScreenMode(bool)), this, SLOT(toggleFullScreenMode(bool)));
134
135     applyPrefs();
136
137     splitter->addWidget(m_inspector);
138     m_inspector->setPage(page());
139     m_inspector->hide();
140
141     if (m_windowOptions.remoteInspectorPort)
142         page()->setProperty("_q_webInspectorServerPort", m_windowOptions.remoteInspectorPort);
143
144     if (url.isValid())
145         page()->mainFrame()->load(url);
146     else  {
147         setAddressUrl(m_inputUrl);
148         m_inputUrl = QString();
149     }
150 }
151
152 void LauncherWindow::applyPrefs()
153 {
154     QWebSettings* settings = page()->settings();
155     settings->setAttribute(QWebSettings::AcceleratedCompositingEnabled, m_windowOptions.useCompositing);
156     settings->setAttribute(QWebSettings::TiledBackingStoreEnabled, m_windowOptions.useTiledBackingStore);
157     settings->setAttribute(QWebSettings::FrameFlatteningEnabled, m_windowOptions.useFrameFlattening);
158     settings->setAttribute(QWebSettings::WebGLEnabled, m_windowOptions.useWebGL);
159
160     if (!isGraphicsBased())
161         return;
162
163     WebViewGraphicsBased* view = static_cast<WebViewGraphicsBased*>(m_view);
164     view->setViewportUpdateMode(m_windowOptions.viewportUpdateMode);
165     view->setFrameRateMeasurementEnabled(m_windowOptions.showFrameRate);
166     view->setItemCacheMode(m_windowOptions.cacheWebView ? QGraphicsItem::DeviceCoordinateCache : QGraphicsItem::NoCache);
167
168     if (m_windowOptions.resizesToContents)
169         toggleResizesToContents(m_windowOptions.resizesToContents);
170 }
171
172 void LauncherWindow::createChrome()
173 {
174 #ifndef QT_NO_SHORTCUT
175     QMenu* fileMenu = menuBar()->addMenu("&File");
176     fileMenu->addAction("New Window", this, SLOT(newWindow()), QKeySequence::New);
177     fileMenu->addAction(tr("Open File..."), this, SLOT(openFile()), QKeySequence::Open);
178     fileMenu->addAction(tr("Open Location..."), this, SLOT(openLocation()), QKeySequence(Qt::CTRL | Qt::Key_L));
179     fileMenu->addAction("Close Window", this, SLOT(close()), QKeySequence::Close);
180     fileMenu->addSeparator();
181     fileMenu->addAction("Take Screen Shot...", this, SLOT(screenshot()));
182 #ifndef QT_NO_PRINTER
183     fileMenu->addAction(tr("Print..."), this, SLOT(print()), QKeySequence::Print);
184 #endif
185     fileMenu->addSeparator();
186     fileMenu->addAction("Quit", QApplication::instance(), SLOT(closeAllWindows()), QKeySequence(Qt::CTRL | Qt::Key_Q));
187
188     QMenu* editMenu = menuBar()->addMenu("&Edit");
189     editMenu->addAction(page()->action(QWebPage::Undo));
190     editMenu->addAction(page()->action(QWebPage::Redo));
191     editMenu->addSeparator();
192     editMenu->addAction(page()->action(QWebPage::Cut));
193     editMenu->addAction(page()->action(QWebPage::Copy));
194     editMenu->addAction(page()->action(QWebPage::Paste));
195     editMenu->addSeparator();
196     QAction* setEditable = editMenu->addAction("Set Editable", this, SLOT(setEditable(bool)));
197     setEditable->setCheckable(true);
198
199     QMenu* viewMenu = menuBar()->addMenu("&View");
200     viewMenu->addAction(page()->action(QWebPage::Stop));
201     viewMenu->addAction(page()->action(QWebPage::Reload));
202     viewMenu->addSeparator();
203     QAction* zoomIn = viewMenu->addAction("Zoom &In", this, SLOT(zoomIn()));
204     QAction* zoomOut = viewMenu->addAction("Zoom &Out", this, SLOT(zoomOut()));
205     QAction* resetZoom = viewMenu->addAction("Reset Zoom", this, SLOT(resetZoom()));
206     QAction* zoomTextOnly = viewMenu->addAction("Zoom Text Only", this, SLOT(toggleZoomTextOnly(bool)));
207     zoomTextOnly->setCheckable(true);
208     zoomTextOnly->setChecked(false);
209     viewMenu->addSeparator();
210     viewMenu->addAction("Dump HTML", this, SLOT(dumpHtml()));
211     // viewMenu->addAction("Dump plugins", this, SLOT(dumpPlugins()));
212
213     zoomIn->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Plus));
214     zoomOut->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Minus));
215     resetZoom->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_0));
216
217     QMenu* formatMenu = new QMenu("F&ormat", this);
218     m_formatMenuAction = menuBar()->addMenu(formatMenu);
219     m_formatMenuAction->setVisible(false);
220     formatMenu->addAction(page()->action(QWebPage::ToggleBold));
221     formatMenu->addAction(page()->action(QWebPage::ToggleItalic));
222     formatMenu->addAction(page()->action(QWebPage::ToggleUnderline));
223     QMenu* writingMenu = formatMenu->addMenu(tr("Writing Direction"));
224     writingMenu->addAction(page()->action(QWebPage::SetTextDirectionDefault));
225     writingMenu->addAction(page()->action(QWebPage::SetTextDirectionLeftToRight));
226     writingMenu->addAction(page()->action(QWebPage::SetTextDirectionRightToLeft));
227
228     QMenu* windowMenu = menuBar()->addMenu("&Window");
229     QAction* toggleFullScreen = windowMenu->addAction("Toggle FullScreen", this, SIGNAL(enteredFullScreenMode(bool)));
230     toggleFullScreen->setShortcut(Qt::Key_F11);
231     toggleFullScreen->setCheckable(true);
232     toggleFullScreen->setChecked(false);
233     // When exit fullscreen mode by clicking on the exit area (bottom right corner) we must
234     // uncheck the Toggle FullScreen action.
235     toggleFullScreen->connect(this, SIGNAL(enteredFullScreenMode(bool)), SLOT(setChecked(bool)));
236
237     QWebSettings* settings = page()->settings();
238
239     QMenu* toolsMenu = menuBar()->addMenu("&Develop");
240     QMenu* graphicsViewMenu = toolsMenu->addMenu("QGraphicsView");
241     QAction* toggleGraphicsView = graphicsViewMenu->addAction("Toggle use of QGraphicsView", this, SLOT(toggleWebView(bool)));
242     toggleGraphicsView->setCheckable(true);
243     toggleGraphicsView->setChecked(isGraphicsBased());
244
245     QAction* toggleWebGL = toolsMenu->addAction("Toggle WebGL", this, SLOT(toggleWebGL(bool)));
246     toggleWebGL->setCheckable(true);
247     toggleWebGL->setChecked(settings->testAttribute(QWebSettings::WebGLEnabled));
248
249     QAction* toggleThreadedQnam = toolsMenu->addAction("Toggle threaded network", this, SLOT(toggleThreadedQnam(bool)));
250     toggleThreadedQnam->setCheckable(true);
251     toggleThreadedQnam->setChecked(m_windowOptions.useThreadedQnam);
252
253     QAction* spatialNavigationAction = toolsMenu->addAction("Toggle Spatial Navigation", this, SLOT(toggleSpatialNavigation(bool)));
254     spatialNavigationAction->setCheckable(true);
255     spatialNavigationAction->setShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_S));
256
257     QAction* toggleFrameFlattening = toolsMenu->addAction("Toggle Frame Flattening", this, SLOT(toggleFrameFlattening(bool)));
258     toggleFrameFlattening->setCheckable(true);
259     toggleFrameFlattening->setChecked(settings->testAttribute(QWebSettings::FrameFlatteningEnabled));
260
261     QAction* touchMockAction = toolsMenu->addAction("Toggle touch mocking", this, SLOT(setTouchMocking(bool)));
262     touchMockAction->setCheckable(true);
263     touchMockAction->setShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_T));
264
265     toolsMenu->addSeparator();
266
267     QAction* userAgentAction = toolsMenu->addAction("Change User Agent", this, SLOT(showUserAgentDialog()));
268     userAgentAction->setShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_U));
269
270     toolsMenu->addAction("Select Elements...", this, SLOT(selectElements()));
271
272     QAction* showInspectorAction = toolsMenu->addAction("Show Web Inspector", m_inspector, SLOT(setVisible(bool)), QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_I));
273     showInspectorAction->setCheckable(true);
274     showInspectorAction->connect(m_inspector, SIGNAL(visibleChanged(bool)), SLOT(setChecked(bool)));
275
276     // GraphicsView sub menu.
277     QAction* toggleAcceleratedCompositing = graphicsViewMenu->addAction("Toggle Accelerated Compositing", this, SLOT(toggleAcceleratedCompositing(bool)));
278     toggleAcceleratedCompositing->setCheckable(true);
279     toggleAcceleratedCompositing->setChecked(settings->testAttribute(QWebSettings::AcceleratedCompositingEnabled));
280     toggleAcceleratedCompositing->setEnabled(isGraphicsBased());
281     toggleAcceleratedCompositing->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
282
283     QAction* toggleResizesToContents = graphicsViewMenu->addAction("Toggle Resizes To Contents Mode", this, SLOT(toggleResizesToContents(bool)));
284     toggleResizesToContents->setCheckable(true);
285     toggleResizesToContents->setChecked(m_windowOptions.resizesToContents);
286     toggleResizesToContents->setEnabled(isGraphicsBased());
287     toggleResizesToContents->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
288
289     QAction* toggleTiledBackingStore = graphicsViewMenu->addAction("Toggle Tiled Backing Store", this, SLOT(toggleTiledBackingStore(bool)));
290     toggleTiledBackingStore->setCheckable(true);
291     toggleTiledBackingStore->setChecked(m_windowOptions.useTiledBackingStore);
292     toggleTiledBackingStore->setEnabled(isGraphicsBased());
293     toggleTiledBackingStore->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
294
295 #if defined(QT_CONFIGURED_WITH_OPENGL)
296     QAction* toggleQGLWidgetViewport = graphicsViewMenu->addAction("Toggle use of QGLWidget Viewport", this, SLOT(toggleQGLWidgetViewport(bool)));
297     toggleQGLWidgetViewport->setCheckable(true);
298     toggleQGLWidgetViewport->setChecked(m_windowOptions.useQGLWidgetViewport);
299     toggleQGLWidgetViewport->setEnabled(isGraphicsBased());
300     toggleQGLWidgetViewport->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
301 #endif
302
303     QMenu* viewportUpdateMenu = graphicsViewMenu->addMenu("Change Viewport Update Mode");
304     viewportUpdateMenu->setEnabled(isGraphicsBased());
305     viewportUpdateMenu->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
306
307     QAction* fullUpdate = viewportUpdateMenu->addAction("FullViewportUpdate");
308     fullUpdate->setCheckable(true);
309     fullUpdate->setChecked((m_windowOptions.viewportUpdateMode == QGraphicsView::FullViewportUpdate) ? true : false);
310
311     QAction* minimalUpdate = viewportUpdateMenu->addAction("MinimalViewportUpdate");
312     minimalUpdate->setCheckable(true);
313     minimalUpdate->setChecked((m_windowOptions.viewportUpdateMode == QGraphicsView::MinimalViewportUpdate) ? true : false);
314
315     QAction* smartUpdate = viewportUpdateMenu->addAction("SmartViewportUpdate");
316     smartUpdate->setCheckable(true);
317     smartUpdate->setChecked((m_windowOptions.viewportUpdateMode == QGraphicsView::SmartViewportUpdate) ? true : false);
318
319     QAction* boundingRectUpdate = viewportUpdateMenu->addAction("BoundingRectViewportUpdate");
320     boundingRectUpdate->setCheckable(true);
321     boundingRectUpdate->setChecked((m_windowOptions.viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) ? true : false);
322
323     QAction* noUpdate = viewportUpdateMenu->addAction("NoViewportUpdate");
324     noUpdate->setCheckable(true);
325     noUpdate->setChecked((m_windowOptions.viewportUpdateMode == QGraphicsView::NoViewportUpdate) ? true : false);
326
327     QSignalMapper* signalMapper = new QSignalMapper(viewportUpdateMenu);
328     signalMapper->setMapping(fullUpdate, QGraphicsView::FullViewportUpdate);
329     signalMapper->setMapping(minimalUpdate, QGraphicsView::MinimalViewportUpdate);
330     signalMapper->setMapping(smartUpdate, QGraphicsView::SmartViewportUpdate);
331     signalMapper->setMapping(boundingRectUpdate, QGraphicsView::BoundingRectViewportUpdate);
332     signalMapper->setMapping(noUpdate, QGraphicsView::NoViewportUpdate);
333
334     connect(fullUpdate, SIGNAL(triggered()), signalMapper, SLOT(map()));
335     connect(minimalUpdate, SIGNAL(triggered()), signalMapper, SLOT(map()));
336     connect(smartUpdate, SIGNAL(triggered()), signalMapper, SLOT(map()));
337     connect(boundingRectUpdate, SIGNAL(triggered()), signalMapper, SLOT(map()));
338     connect(noUpdate, SIGNAL(triggered()), signalMapper, SLOT(map()));
339
340     connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(changeViewportUpdateMode(int)));
341
342     QActionGroup* viewportUpdateModeActions = new QActionGroup(viewportUpdateMenu);
343     viewportUpdateModeActions->addAction(fullUpdate);
344     viewportUpdateModeActions->addAction(minimalUpdate);
345     viewportUpdateModeActions->addAction(smartUpdate);
346     viewportUpdateModeActions->addAction(boundingRectUpdate);
347     viewportUpdateModeActions->addAction(noUpdate);
348
349     graphicsViewMenu->addSeparator();
350
351     QAction* flipAnimated = graphicsViewMenu->addAction("Animated Flip");
352     flipAnimated->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
353     flipAnimated->setEnabled(isGraphicsBased());
354     connect(flipAnimated, SIGNAL(triggered()), SLOT(animatedFlip()));
355
356     QAction* flipYAnimated = graphicsViewMenu->addAction("Animated Y-Flip");
357     flipYAnimated->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
358     flipYAnimated->setEnabled(isGraphicsBased());
359     connect(flipYAnimated, SIGNAL(triggered()), SLOT(animatedYFlip()));
360
361     QAction* cloneWindow = graphicsViewMenu->addAction("Clone Window", this, SLOT(cloneWindow()));
362     cloneWindow->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
363     cloneWindow->setEnabled(isGraphicsBased());
364
365     graphicsViewMenu->addSeparator();
366
367     QAction* showFPS = graphicsViewMenu->addAction("Show FPS", this, SLOT(showFPS(bool)));
368     showFPS->setCheckable(true);
369     showFPS->setEnabled(isGraphicsBased());
370     showFPS->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
371     showFPS->setChecked(m_windowOptions.showFrameRate);
372
373     QMenu* settingsMenu = menuBar()->addMenu("&Settings");
374
375     QAction* toggleAutoLoadImages = settingsMenu->addAction("Disable Auto Load Images", this, SLOT(toggleAutoLoadImages(bool)));
376     toggleAutoLoadImages->setCheckable(true);
377     toggleAutoLoadImages->setChecked(false);
378
379     QAction* togglePlugins = settingsMenu->addAction("Disable Plugins", this, SLOT(togglePlugins(bool)));
380     togglePlugins->setCheckable(true);
381     togglePlugins->setChecked(false);
382
383     QAction* toggleInterruptingJavaScripteEnabled = settingsMenu->addAction("Enable interrupting js scripts", this, SLOT(toggleInterruptingJavaScriptEnabled(bool)));
384     toggleInterruptingJavaScripteEnabled->setCheckable(true);
385     toggleInterruptingJavaScripteEnabled->setChecked(false);
386
387     QAction* toggleJavascriptCanOpenWindows = settingsMenu->addAction("Enable js popup windows", this, SLOT(toggleJavascriptCanOpenWindows(bool)));
388     toggleJavascriptCanOpenWindows->setCheckable(true);
389     toggleJavascriptCanOpenWindows->setChecked(false);
390
391 #endif
392 }
393
394 bool LauncherWindow::isGraphicsBased() const
395 {
396     return bool(qobject_cast<QGraphicsView*>(m_view));
397 }
398
399 void LauncherWindow::keyPressEvent(QKeyEvent* event)
400 {
401 #ifdef Q_WS_MAEMO_5
402     switch (event->key()) {
403     case Qt::Key_F7:
404         zoomIn();
405         event->accept();
406         break;
407     case Qt::Key_F8:
408         zoomOut();
409         event->accept();
410         break;
411     }
412 #endif
413     MainWindow::keyPressEvent(event);
414 }
415
416 void LauncherWindow::grabZoomKeys(bool grab)
417 {
418 #ifdef Q_WS_MAEMO_5
419     if (!winId()) {
420         qWarning("Can't grab keys unless we have a window id");
421         return;
422     }
423
424     Atom atom = XInternAtom(QX11Info::display(), "_HILDON_ZOOM_KEY_ATOM", False);
425     if (!atom) {
426         qWarning("Unable to obtain _HILDON_ZOOM_KEY_ATOM");
427         return;
428     }
429
430     unsigned long val = (grab) ? 1 : 0;
431     XChangeProperty(QX11Info::display(), winId(), atom, XA_INTEGER, 32, PropModeReplace, reinterpret_cast<unsigned char*>(&val), 1);
432 #endif
433 }
434
435 void LauncherWindow::sendTouchEvent()
436 {
437     if (m_touchPoints.isEmpty())
438         return;
439
440     QEvent::Type type = QEvent::TouchUpdate;
441     if (m_touchPoints.size() == 1) {
442         if (m_touchPoints[0].state() == Qt::TouchPointReleased)
443             type = QEvent::TouchEnd;
444         else if (m_touchPoints[0].state() == Qt::TouchPointPressed)
445             type = QEvent::TouchBegin;
446     }
447
448     QTouchEvent touchEv(type);
449     touchEv.setTouchPoints(m_touchPoints);
450     QCoreApplication::sendEvent(page(), &touchEv);
451
452     // After sending the event, remove all touchpoints that were released
453     if (m_touchPoints[0].state() == Qt::TouchPointReleased)
454         m_touchPoints.removeAt(0);
455     if (m_touchPoints.size() > 1 && m_touchPoints[1].state() == Qt::TouchPointReleased)
456         m_touchPoints.removeAt(1);
457 }
458
459 bool LauncherWindow::eventFilter(QObject* obj, QEvent* event)
460 {
461     // If click pos is the bottom right corner (square with size defined by gExitClickArea)
462     // and the window is on FullScreen, the window must return to its original state.
463     if (event->type() == QEvent::MouseButtonRelease) {
464         QMouseEvent* ev = static_cast<QMouseEvent*>(event);
465         if (windowState() == Qt::WindowFullScreen
466             && ev->pos().x() > (width() - gExitClickArea)
467             && ev->pos().y() > (height() - gExitClickArea)) {
468
469             emit enteredFullScreenMode(false);
470         }
471     }
472
473     if (!m_touchMocking)
474         return QObject::eventFilter(obj, event);
475
476     if (event->type() == QEvent::MouseButtonPress
477         || event->type() == QEvent::MouseButtonRelease
478         || event->type() == QEvent::MouseButtonDblClick
479         || event->type() == QEvent::MouseMove) {
480
481         QMouseEvent* ev = static_cast<QMouseEvent*>(event);
482         if (ev->type() == QEvent::MouseMove
483             && !(ev->buttons() & Qt::LeftButton))
484             return false;
485
486         QTouchEvent::TouchPoint touchPoint;
487         touchPoint.setState(Qt::TouchPointMoved);
488         if ((ev->type() == QEvent::MouseButtonPress
489              || ev->type() == QEvent::MouseButtonDblClick))
490             touchPoint.setState(Qt::TouchPointPressed);
491         else if (ev->type() == QEvent::MouseButtonRelease)
492             touchPoint.setState(Qt::TouchPointReleased);
493
494         touchPoint.setId(0);
495         touchPoint.setScreenPos(ev->globalPos());
496         touchPoint.setPos(ev->pos());
497         touchPoint.setPressure(1);
498
499         // If the point already exists, update it. Otherwise create it.
500         if (m_touchPoints.size() > 0 && !m_touchPoints[0].id())
501             m_touchPoints[0] = touchPoint;
502         else if (m_touchPoints.size() > 1 && !m_touchPoints[1].id())
503             m_touchPoints[1] = touchPoint;
504         else
505             m_touchPoints.append(touchPoint);
506
507         sendTouchEvent();
508     } else if (event->type() == QEvent::KeyPress
509         && static_cast<QKeyEvent*>(event)->key() == Qt::Key_F
510         && static_cast<QKeyEvent*>(event)->modifiers() == Qt::ControlModifier) {
511
512         // If the keyboard point is already pressed, release it.
513         // Otherwise create it and append to m_touchPoints.
514         if (m_touchPoints.size() > 0 && m_touchPoints[0].id() == 1) {
515             m_touchPoints[0].setState(Qt::TouchPointReleased);
516             sendTouchEvent();
517         } else if (m_touchPoints.size() > 1 && m_touchPoints[1].id() == 1) {
518             m_touchPoints[1].setState(Qt::TouchPointReleased);
519             sendTouchEvent();
520         } else {
521             QTouchEvent::TouchPoint touchPoint;
522             touchPoint.setState(Qt::TouchPointPressed);
523             touchPoint.setId(1);
524             touchPoint.setScreenPos(QCursor::pos());
525             touchPoint.setPos(m_view->mapFromGlobal(QCursor::pos()));
526             touchPoint.setPressure(1);
527             m_touchPoints.append(touchPoint);
528             sendTouchEvent();
529
530             // After sending the event, change the touchpoint state to stationary
531             m_touchPoints.last().setState(Qt::TouchPointStationary);
532         }
533     }
534
535     return false;
536 }
537
538 void LauncherWindow::loadStarted()
539 {
540     m_view->setFocus(Qt::OtherFocusReason);
541 }
542
543 void LauncherWindow::loadFinished()
544 {
545     QUrl url = page()->mainFrame()->url();
546     addCompleterEntry(url);
547     if (m_inputUrl.isEmpty())
548         setAddressUrl(url.toString(QUrl::RemoveUserInfo));
549     else {
550         setAddressUrl(m_inputUrl);
551         m_inputUrl = QString();
552     }
553 }
554
555 void LauncherWindow::showLinkHover(const QString &link, const QString &toolTip)
556 {
557 #ifndef Q_WS_MAEMO_5
558     statusBar()->showMessage(link);
559 #endif
560 #ifndef QT_NO_TOOLTIP
561     if (!toolTip.isEmpty())
562         QToolTip::showText(QCursor::pos(), toolTip);
563 #endif
564 }
565
566 void LauncherWindow::zoomAnimationFinished()
567 {
568     if (!isGraphicsBased())
569         return;
570     QGraphicsWebView* view = static_cast<WebViewGraphicsBased*>(m_view)->graphicsWebView();
571     view->setTiledBackingStoreFrozen(false);
572 }
573
574 void LauncherWindow::applyZoom()
575 {
576 #ifndef QT_NO_ANIMATION
577     if (isGraphicsBased() && page()->settings()->testAttribute(QWebSettings::TiledBackingStoreEnabled)) {
578         QGraphicsWebView* view = static_cast<WebViewGraphicsBased*>(m_view)->graphicsWebView();
579         view->setTiledBackingStoreFrozen(true);
580         if (!m_zoomAnimation) {
581             m_zoomAnimation = new QPropertyAnimation(view, "scale");
582             m_zoomAnimation->setStartValue(view->scale());
583             connect(m_zoomAnimation, SIGNAL(finished()), this, SLOT(zoomAnimationFinished()));
584         } else {
585             m_zoomAnimation->stop();
586             m_zoomAnimation->setStartValue(m_zoomAnimation->currentValue());
587         }
588
589         m_zoomAnimation->setDuration(300);
590         m_zoomAnimation->setEndValue(qreal(m_currentZoom) / 100.);
591         m_zoomAnimation->start();
592         return;
593     }
594 #endif
595     page()->mainFrame()->setZoomFactor(qreal(m_currentZoom) / 100.0);
596 }
597
598 void LauncherWindow::zoomIn()
599 {
600     int i = m_zoomLevels.indexOf(m_currentZoom);
601     Q_ASSERT(i >= 0);
602     if (i < m_zoomLevels.count() - 1)
603         m_currentZoom = m_zoomLevels[i + 1];
604
605     applyZoom();
606 }
607
608 void LauncherWindow::zoomOut()
609 {
610     int i = m_zoomLevels.indexOf(m_currentZoom);
611     Q_ASSERT(i >= 0);
612     if (i > 0)
613         m_currentZoom = m_zoomLevels[i - 1];
614
615     applyZoom();
616 }
617
618 void LauncherWindow::resetZoom()
619 {
620     m_currentZoom = 100;
621     applyZoom();
622 }
623
624 void LauncherWindow::toggleZoomTextOnly(bool b)
625 {
626     page()->settings()->setAttribute(QWebSettings::ZoomTextOnly, b);
627 }
628
629 void LauncherWindow::print()
630 {
631 #if !defined(QT_NO_PRINTER)
632     QPrintPreviewDialog dlg(this);
633     connect(&dlg, SIGNAL(paintRequested(QPrinter*)),
634             page()->mainFrame(), SLOT(print(QPrinter*)));
635     dlg.exec();
636 #endif
637 }
638
639 void LauncherWindow::screenshot()
640 {
641     QPixmap pixmap = QPixmap::grabWidget(m_view);
642     QLabel* label = 0;
643 #if !defined(Q_OS_SYMBIAN)
644     label = new QLabel;
645     label->setAttribute(Qt::WA_DeleteOnClose);
646     label->setWindowTitle("Screenshot - Preview");
647     label->setPixmap(pixmap);
648     label->show();
649 #endif
650
651 #ifndef QT_NO_FILEDIALOG
652     QString fileName = QFileDialog::getSaveFileName(label, "Screenshot");
653     if (!fileName.isEmpty()) {
654         pixmap.save(fileName, "png");
655         if (label)
656             label->setWindowTitle(QString("Screenshot - Saved at %1").arg(fileName));
657     }
658 #endif
659
660 #if defined(QT_CONFIGURED_WITH_OPENGL)
661     toggleQGLWidgetViewport(m_windowOptions.useQGLWidgetViewport);
662 #endif
663 }
664
665 void LauncherWindow::setEditable(bool on)
666 {
667     page()->setContentEditable(on);
668     m_formatMenuAction->setVisible(on);
669 }
670
671 /*
672 void LauncherWindow::dumpPlugins() {
673     QList<QWebPluginInfo> plugins = QWebSettings::pluginDatabase()->plugins();
674     foreach (const QWebPluginInfo plugin, plugins) {
675         qDebug() << "Plugin:" << plugin.name();
676         foreach (const QWebPluginInfo::MimeType mime, plugin.mimeTypes()) {
677             qDebug() << "   " << mime.name;
678         }
679     }
680 }
681 */
682
683 void LauncherWindow::dumpHtml()
684 {
685     qDebug() << "HTML: " << page()->mainFrame()->toHtml();
686 }
687
688 void LauncherWindow::selectElements()
689 {
690 #ifndef QT_NO_INPUTDIALOG
691     bool ok;
692     QString str = QInputDialog::getText(this, "Select elements", "Choose elements",
693                                         QLineEdit::Normal, "a", &ok);
694
695     if (ok && !str.isEmpty()) {
696         QWebElementCollection result =  page()->mainFrame()->findAllElements(str);
697         foreach (QWebElement e, result)
698             e.setStyleProperty("background-color", "yellow");
699 #ifndef Q_WS_MAEMO_5
700         statusBar()->showMessage(QString("%1 element(s) selected").arg(result.count()), 5000);
701 #endif
702     }
703 #endif
704 }
705
706 void LauncherWindow::setTouchMocking(bool on)
707 {
708     m_touchMocking = on;
709 }
710
711 void LauncherWindow::toggleWebView(bool graphicsBased)
712 {
713     m_windowOptions.useGraphicsView = graphicsBased;
714     initializeView();
715     menuBar()->clear();
716     createChrome();
717 }
718
719 void LauncherWindow::toggleAcceleratedCompositing(bool toggle)
720 {
721     m_windowOptions.useCompositing = toggle;
722     page()->settings()->setAttribute(QWebSettings::AcceleratedCompositingEnabled, toggle);
723 }
724
725 void LauncherWindow::toggleTiledBackingStore(bool toggle)
726 {
727     page()->settings()->setAttribute(QWebSettings::TiledBackingStoreEnabled, toggle);
728 }
729
730 void LauncherWindow::toggleResizesToContents(bool toggle)
731 {
732     m_windowOptions.resizesToContents = toggle;
733     static_cast<WebViewGraphicsBased*>(m_view)->setResizesToContents(toggle);
734 }
735
736 void LauncherWindow::toggleWebGL(bool toggle)
737 {
738     m_windowOptions.useWebGL = toggle;
739     page()->settings()->setAttribute(QWebSettings::WebGLEnabled, toggle);
740 }
741
742 void LauncherWindow::toggleThreadedQnam(bool toggle)
743 {
744     m_windowOptions.useThreadedQnam = toggle;
745     page()->setQnamThreaded(toggle);
746 }
747
748 void LauncherWindow::animatedFlip()
749 {
750     qobject_cast<WebViewGraphicsBased*>(m_view)->animatedFlip();
751 }
752
753 void LauncherWindow::animatedYFlip()
754 {
755     qobject_cast<WebViewGraphicsBased*>(m_view)->animatedYFlip();
756 }
757 void LauncherWindow::toggleSpatialNavigation(bool b)
758 {
759     page()->settings()->setAttribute(QWebSettings::SpatialNavigationEnabled, b);
760 }
761
762 void LauncherWindow::toggleFullScreenMode(bool enable)
763 {
764     if (enable)
765         setWindowState(Qt::WindowFullScreen);
766     else {
767 #if defined(Q_OS_SYMBIAN)
768         setWindowState(Qt::WindowMaximized);
769 #else
770         setWindowState(Qt::WindowNoState);
771 #endif
772     }
773 }
774
775 void LauncherWindow::toggleFrameFlattening(bool toggle)
776 {
777     m_windowOptions.useFrameFlattening = toggle;
778     page()->settings()->setAttribute(QWebSettings::FrameFlatteningEnabled, toggle);
779 }
780
781 void LauncherWindow::toggleInterruptingJavaScriptEnabled(bool enable)
782 {
783     page()->setInterruptingJavaScriptEnabled(enable);
784 }
785
786 void LauncherWindow::toggleJavascriptCanOpenWindows(bool enable)
787 {
788     page()->settings()->setAttribute(QWebSettings::JavascriptCanOpenWindows, enable);
789 }
790
791 void LauncherWindow::toggleAutoLoadImages(bool enable)
792 {
793     page()->settings()->setAttribute(QWebSettings::AutoLoadImages, !enable);
794 }
795
796 void LauncherWindow::togglePlugins(bool enable)
797 {
798     page()->settings()->setAttribute(QWebSettings::PluginsEnabled, !enable);
799 }
800
801 #if defined(QT_CONFIGURED_WITH_OPENGL)
802 void LauncherWindow::toggleQGLWidgetViewport(bool enable)
803 {
804     if (!isGraphicsBased())
805         return;
806
807     m_windowOptions.useQGLWidgetViewport = enable;
808     WebViewGraphicsBased* view = static_cast<WebViewGraphicsBased*>(m_view);
809
810     view->setViewport(enable ? new QGLWidget() : 0);
811 }
812 #endif
813
814 void LauncherWindow::changeViewportUpdateMode(int mode)
815 {
816     m_windowOptions.viewportUpdateMode = QGraphicsView::ViewportUpdateMode(mode);
817
818     if (!isGraphicsBased())
819         return;
820
821     WebViewGraphicsBased* view = static_cast<WebViewGraphicsBased*>(m_view);
822     view->setViewportUpdateMode(m_windowOptions.viewportUpdateMode);
823 }
824
825 void LauncherWindow::showFPS(bool enable)
826 {
827     if (!isGraphicsBased())
828         return;
829
830     m_windowOptions.showFrameRate = enable;
831     WebViewGraphicsBased* view = static_cast<WebViewGraphicsBased*>(m_view);
832     view->setFrameRateMeasurementEnabled(enable);
833
834     if (!enable) {
835 #if defined(Q_WS_MAEMO_5) && defined(Q_OS_SYMBIAN)
836         setWindowTitle("");
837 #else
838         statusBar()->clearMessage();
839 #endif
840     }
841 }
842
843 void LauncherWindow::showUserAgentDialog()
844 {
845     QStringList items;
846     QFile file(":/useragentlist.txt");
847     if (file.open(QIODevice::ReadOnly)) {
848          while (!file.atEnd())
849             items << file.readLine().trimmed();
850         file.close();
851     }
852
853     QSettings settings;
854     QString customUserAgent = settings.value("CustomUserAgent").toString();
855     if (!items.contains(customUserAgent) && !customUserAgent.isEmpty())
856         items << customUserAgent;
857
858     QDialog* dialog = new QDialog(this);
859     dialog->resize(size().width() * 0.7, dialog->size().height());
860     dialog->setMaximumHeight(dialog->size().height());
861     dialog->setWindowTitle("Change User Agent");
862
863     QVBoxLayout* layout = new QVBoxLayout(dialog);
864     dialog->setLayout(layout);
865
866 #ifndef QT_NO_COMBOBOX
867     QComboBox* combo = new QComboBox(dialog);
868     combo->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength);
869     combo->setEditable(true);
870     combo->insertItems(0, items);
871     layout->addWidget(combo);
872
873     int index = combo->findText(page()->userAgentForUrl(QUrl()));
874     combo->setCurrentIndex(index);
875 #endif
876
877     QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok
878             | QDialogButtonBox::Cancel, Qt::Horizontal, dialog);
879     connect(buttonBox, SIGNAL(accepted()), dialog, SLOT(accept()));
880     connect(buttonBox, SIGNAL(rejected()), dialog, SLOT(reject()));
881     layout->addWidget(buttonBox);
882
883 #ifndef QT_NO_COMBOBOX
884     if (dialog->exec() && !combo->currentText().isEmpty()) {
885         page()->setUserAgent(combo->currentText());
886         if (!items.contains(combo->currentText()))
887             settings.setValue("CustomUserAgent", combo->currentText());
888     }
889 #endif
890
891     delete dialog;
892 }
893
894 void LauncherWindow::updateFPS(int fps)
895 {
896     QString fpsStatusText = QString("Current FPS: %1").arg(fps);
897
898 #if defined(Q_WS_MAEMO_5) && defined(Q_OS_SYMBIAN)
899     setWindowTitle(fpsStatusText);
900 #else
901     statusBar()->showMessage(fpsStatusText);
902 #endif
903 }
904
905 LauncherWindow* LauncherWindow::newWindow()
906 {
907     LauncherWindow* mw = new LauncherWindow(&m_windowOptions);
908     mw->show();
909     return mw;
910 }
911
912 LauncherWindow* LauncherWindow::cloneWindow()
913 {
914     LauncherWindow* mw = new LauncherWindow(&m_windowOptions, qobject_cast<QGraphicsView*>(m_view)->scene());
915     mw->show();
916     return mw;
917 }
918