[Qt] Separate QWidget dependant code into separate WebKitWidgets static library
[WebKit-https.git] / Source / WebKit / qt / Api / qwebpage.cpp
1 /*
2     Copyright (C) 2008, 2009, 2012 Nokia Corporation and/or its subsidiary(-ies)
3     Copyright (C) 2007 Staikos Computing Services Inc.
4     Copyright (C) 2007 Apple Inc.
5
6     This library is free software; you can redistribute it and/or
7     modify it under the terms of the GNU Library General Public
8     License as published by the Free Software Foundation; either
9     version 2 of the License, or (at your option) any later version.
10
11     This library is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14     Library General Public License for more details.
15
16     You should have received a copy of the GNU Library General Public License
17     along with this library; see the file COPYING.LIB.  If not, write to
18     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19     Boston, MA 02110-1301, USA.
20 */
21
22 #include "config.h"
23 #include "qwebpage.h"
24
25 #include "CSSComputedStyleDeclaration.h"
26 #include "CSSParser.h"
27 #include "ApplicationCacheStorage.h"
28 #include "BackForwardListImpl.h"
29 #include "MemoryCache.h"
30 #include "Chrome.h"
31 #include "ChromeClientQt.h"
32 #include "ClientRect.h"
33 #include "ContextMenu.h"
34 #include "ContextMenuClientQt.h"
35 #include "ContextMenuController.h"
36 #if USE(QT_MULTIMEDIA)
37 #include "DefaultFullScreenVideoHandler.h"
38 #endif
39 #if ENABLE(DEVICE_ORIENTATION)
40 #include "DeviceMotionClientQt.h"
41 #include "DeviceOrientationClientMock.h"
42 #include "DeviceOrientationClientQt.h"
43 #endif
44 #include "DocumentLoader.h"
45 #include "DragClientQt.h"
46 #include "DragController.h"
47 #include "DragData.h"
48 #include "DragSession.h"
49 #include "Editor.h"
50 #include "EditorClientQt.h"
51 #include "FocusController.h"
52 #include "FormState.h"
53 #include "Frame.h"
54 #include "FrameLoadRequest.h"
55 #include "FrameLoader.h"
56 #include "FrameLoaderClientQt.h"
57 #include "FrameTree.h"
58 #include "FrameView.h"
59 #if ENABLE(GEOLOCATION)
60 #include "GeolocationClientMock.h"
61 #include "GeolocationClientQt.h"
62 #include "GeolocationController.h"
63 #endif
64 #include "GeolocationPermissionClientQt.h"
65 #include "HTMLFormElement.h"
66 #include "HTMLFrameOwnerElement.h"
67 #include "HTMLInputElement.h"
68 #include "HTMLNames.h"
69 #include "HitTestResult.h"
70 #include "Image.h"
71 #include "InitWebKitQt.h"
72 #include "InspectorClientQt.h"
73 #include "InspectorClientWebPage.h"
74 #include "InspectorController.h"
75 #include "InspectorServerQt.h"
76 #include "KURL.h"
77 #include "LocalizedStrings.h"
78 #include "MIMETypeRegistry.h"
79 #include "NavigationAction.h"
80 #include "NetworkingContext.h"
81 #include "NodeList.h"
82 #include "NotImplemented.h"
83 #include "NotificationPresenterClientQt.h"
84 #include "Page.h"
85 #include "PageClientQt.h"
86 #include "PageGroup.h"
87 #include "Pasteboard.h"
88 #include "PlatformKeyboardEvent.h"
89 #include "PlatformTouchEvent.h"
90 #include "PlatformWheelEvent.h"
91 #include "PluginDatabase.h"
92 #include "PluginPackage.h"
93 #include "ProgressTracker.h"
94 #include "QGraphicsWidgetPluginImpl.h"
95 #include "QWebUndoCommand.h"
96 #include "QWidgetPluginImpl.h"
97 #include "QtFallbackWebPopup.h"
98 #include "QtPlatformPlugin.h"
99 #include "RenderTextControl.h"
100 #include "RenderThemeQt.h"
101 #include "SchemeRegistry.h"
102 #include "Scrollbar.h"
103 #include "ScrollbarTheme.h"
104 #include "SecurityOrigin.h"
105 #include "Settings.h"
106 #if defined Q_OS_WIN32
107 #include "SystemInfo.h"
108 #endif // Q_OS_WIN32
109 #include "TextIterator.h"
110 #include "UndoStepQt.h"
111 #include "UserAgentQt.h"
112 #include "WebEventConversion.h"
113 #include "WebKitVersion.h"
114 #include "WindowFeatures.h"
115 #include "WorkerThread.h"
116
117 #include "qwebframe.h"
118 #include "qwebframe_p.h"
119 #include "qwebhistory.h"
120 #include "qwebhistory_p.h"
121 #include "qwebinspector.h"
122 #include "qwebinspector_p.h"
123 #include "qwebkitplatformplugin.h"
124 #include "qwebkitversion.h"
125 #include "qwebpage_p.h"
126 #include "qwebsettings.h"
127 #include "qwebview.h"
128
129 #include <QAction>
130 #include <QApplication>
131 #include <QBasicTimer>
132 #include <QBitArray>
133 #include <QClipboard>
134 #include <QColorDialog>
135 #include <QDebug>
136 #include <QDesktopWidget>
137 #include <QDragEnterEvent>
138 #include <QDragLeaveEvent>
139 #include <QDragMoveEvent>
140 #include <QDropEvent>
141 #include <QFileDialog>
142 #include <QGestureEvent>
143 #include <QInputDialog>
144 #include <QLabel>
145 #include <QMenu>
146 #include <QMessageBox>
147 #include <QNetworkAccessManager>
148 #include <QNetworkProxy>
149 #include <QNetworkRequest>
150 #include <QPainter>
151 #include <QSslSocket>
152 #include <QStyle>
153 #include <QSysInfo>
154 #if USE(QT_MOBILITY_SYSTEMINFO)
155 #include <qsysteminfo.h>
156 #endif
157 #include <QSystemTrayIcon>
158 #include <QTextCharFormat>
159 #include <QToolTip>
160 #include <QTouchEvent>
161 #include <QUndoStack>
162 #include <QUrl>
163 #if defined(Q_WS_X11)
164 #include <QX11Info>
165 #endif
166
167 using namespace WebCore;
168
169 // from text/qfont.cpp
170 QT_BEGIN_NAMESPACE
171 extern Q_GUI_EXPORT int qt_defaultDpi();
172 QT_END_NAMESPACE
173
174 // Lookup table mapping QWebPage::WebActions to the associated Editor commands
175 static const char* editorCommandWebActions[] =
176 {
177     0, // OpenLink,
178
179     0, // OpenLinkInNewWindow,
180     0, // OpenFrameInNewWindow,
181
182     0, // DownloadLinkToDisk,
183     0, // CopyLinkToClipboard,
184
185     0, // OpenImageInNewWindow,
186     0, // DownloadImageToDisk,
187     0, // CopyImageToClipboard,
188
189     0, // Back,
190     0, // Forward,
191     0, // Stop,
192     0, // Reload,
193
194     "Cut", // Cut,
195     "Copy", // Copy,
196     "Paste", // Paste,
197
198     "Undo", // Undo,
199     "Redo", // Redo,
200     "MoveForward", // MoveToNextChar,
201     "MoveBackward", // MoveToPreviousChar,
202     "MoveWordForward", // MoveToNextWord,
203     "MoveWordBackward", // MoveToPreviousWord,
204     "MoveDown", // MoveToNextLine,
205     "MoveUp", // MoveToPreviousLine,
206     "MoveToBeginningOfLine", // MoveToStartOfLine,
207     "MoveToEndOfLine", // MoveToEndOfLine,
208     "MoveToBeginningOfParagraph", // MoveToStartOfBlock,
209     "MoveToEndOfParagraph", // MoveToEndOfBlock,
210     "MoveToBeginningOfDocument", // MoveToStartOfDocument,
211     "MoveToEndOfDocument", // MoveToEndOfDocument,
212     "MoveForwardAndModifySelection", // SelectNextChar,
213     "MoveBackwardAndModifySelection", // SelectPreviousChar,
214     "MoveWordForwardAndModifySelection", // SelectNextWord,
215     "MoveWordBackwardAndModifySelection", // SelectPreviousWord,
216     "MoveDownAndModifySelection", // SelectNextLine,
217     "MoveUpAndModifySelection", // SelectPreviousLine,
218     "MoveToBeginningOfLineAndModifySelection", // SelectStartOfLine,
219     "MoveToEndOfLineAndModifySelection", // SelectEndOfLine,
220     "MoveToBeginningOfParagraphAndModifySelection", // SelectStartOfBlock,
221     "MoveToEndOfParagraphAndModifySelection", // SelectEndOfBlock,
222     "MoveToBeginningOfDocumentAndModifySelection", //SelectStartOfDocument,
223     "MoveToEndOfDocumentAndModifySelection", // SelectEndOfDocument,
224     "DeleteWordBackward", // DeleteStartOfWord,
225     "DeleteWordForward", // DeleteEndOfWord,
226
227     0, // SetTextDirectionDefault,
228     0, // SetTextDirectionLeftToRight,
229     0, // SetTextDirectionRightToLeft,
230
231     "ToggleBold", // ToggleBold,
232     "ToggleItalic", // ToggleItalic,
233     "ToggleUnderline", // ToggleUnderline,
234
235     0, // InspectElement,
236
237     "InsertNewline", // InsertParagraphSeparator
238     "InsertLineBreak", // InsertLineSeparator
239
240     "SelectAll", // SelectAll
241     0, // ReloadAndBypassCache,
242
243     "PasteAndMatchStyle", // PasteAndMatchStyle
244     "RemoveFormat", // RemoveFormat
245     "Strikethrough", // ToggleStrikethrough,
246     "Subscript", // ToggleSubscript
247     "Superscript", // ToggleSuperscript
248     "InsertUnorderedList", // InsertUnorderedList
249     "InsertOrderedList", // InsertOrderedList
250     "Indent", // Indent
251     "Outdent", // Outdent,
252
253     "AlignCenter", // AlignCenter,
254     "AlignJustified", // AlignJustified,
255     "AlignLeft", // AlignLeft,
256     "AlignRight", // AlignRight,
257
258     0, // StopScheduledPageRefresh,
259
260     0, // CopyImageUrlToClipboard,
261
262     0, // OpenLinkInThisWindow,
263
264     0 // WebActionCount
265 };
266
267 // Lookup the appropriate editor command to use for WebAction \a action
268 const char* QWebPagePrivate::editorCommandForWebActions(QWebPage::WebAction action)
269 {
270     if ((action > QWebPage::NoWebAction) && (action < int(sizeof(editorCommandWebActions) / sizeof(const char*))))
271         return editorCommandWebActions[action];
272     return 0;
273 }
274
275 static inline DragOperation dropActionToDragOp(Qt::DropActions actions)
276 {
277     unsigned result = 0;
278     if (actions & Qt::CopyAction)
279         result |= DragOperationCopy;
280     // DragOperationgeneric represents InternetExplorer's equivalent of Move operation,
281     // hence it should be considered as "move"
282     if (actions & Qt::MoveAction)
283         result |= (DragOperationMove | DragOperationGeneric);
284     if (actions & Qt::LinkAction)
285         result |= DragOperationLink;
286     if (result == (DragOperationCopy | DragOperationMove | DragOperationGeneric | DragOperationLink))
287         result = DragOperationEvery;
288     return (DragOperation)result;
289 }
290
291 static inline Qt::DropAction dragOpToDropAction(unsigned actions)
292 {
293     Qt::DropAction result = Qt::IgnoreAction;
294     if (actions & DragOperationCopy)
295         result = Qt::CopyAction;
296     else if (actions & DragOperationMove)
297         result = Qt::MoveAction;
298     // DragOperationgeneric represents InternetExplorer's equivalent of Move operation,
299     // hence it should be considered as "move"
300     else if (actions & DragOperationGeneric)
301         result = Qt::MoveAction;
302     else if (actions & DragOperationLink)
303         result = Qt::LinkAction;
304     return result;
305 }
306
307 QWebPagePrivate::QWebPagePrivate(QWebPage *qq)
308     : q(qq)
309 #ifndef QT_NO_UNDOSTACK
310     , undoStack(0)
311 #endif
312     , m_totalBytes(0)
313     , m_bytesReceived()
314     , clickCausedFocus(false)
315     , linkPolicy(QWebPage::DontDelegateLinks)
316     , m_viewportSize(QSize(0, 0))
317     , useFixedLayout(false)
318     , inspectorFrontend(0)
319     , inspector(0)
320     , inspectorIsInternalOnly(false)
321     , m_lastDropAction(Qt::IgnoreAction)
322 {
323 #if ENABLE(GEOLOCATION) || ENABLE(DEVICE_ORIENTATION)
324     bool useMock = QWebPageAdapter::drtRun;
325 #endif
326
327     WebKit::initializeWebKitWidgets();
328
329     Page::PageClients pageClients;
330     pageClients.chromeClient = new ChromeClientQt(this);
331     pageClients.contextMenuClient = new ContextMenuClientQt();
332     pageClients.editorClient = new EditorClientQt(this);
333     pageClients.dragClient = new DragClientQt(pageClients.chromeClient);
334     pageClients.inspectorClient = new InspectorClientQt(this);
335     page = new Page(pageClients);
336 #if ENABLE(GEOLOCATION)
337     if (useMock) {
338         // In case running in DumpRenderTree mode set the controller to mock provider.
339         GeolocationClientMock* mock = new GeolocationClientMock;
340         WebCore::provideGeolocationTo(page, mock);
341         mock->setController(WebCore::GeolocationController::from(page));
342     } else
343         WebCore::provideGeolocationTo(page, new GeolocationClientQt(this));
344 #endif
345 #if ENABLE(DEVICE_ORIENTATION)
346     if (useMock)
347         WebCore::provideDeviceOrientationTo(page, new DeviceOrientationClientMock);
348     else
349         WebCore::provideDeviceOrientationTo(page, new DeviceOrientationClientQt);
350     WebCore::provideDeviceMotionTo(page, new DeviceMotionClientQt);
351 #endif
352
353     // By default each page is put into their own unique page group, which affects popup windows
354     // and visited links. Page groups (per process only) is a feature making it possible to use
355     // separate settings for each group, so that for instance an integrated browser/email reader
356     // can use different settings for displaying HTML pages and HTML email. To make QtWebKit work
357     // as expected out of the box, we use a default group similar to what other ports are doing.
358     page->setGroupName("Default Group");
359
360     page->addLayoutMilestones(DidFirstVisuallyNonEmptyLayout);
361
362     QWebPageAdapter::init(page);
363
364     history.d = new QWebHistoryPrivate(static_cast<WebCore::BackForwardListImpl*>(page->backForwardList()));
365     memset(actions, 0, sizeof(actions));
366
367     PageGroup::setShouldTrackVisitedLinks(true);
368     
369 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
370     NotificationPresenterClientQt* presenter = NotificationPresenterClientQt::notificationPresenter();
371     presenter->addClient();
372 #ifndef QT_NO_SYSTEMTRAYICON
373     if (!presenter->hasSystemTrayIcon())
374         presenter->setSystemTrayIcon(new QSystemTrayIcon);
375 #endif // QT_NO_SYSTEMTRAYICON
376 #endif // ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
377 }
378
379 QWebPagePrivate::~QWebPagePrivate()
380 {
381 #ifndef QT_NO_CONTEXTMENU
382     delete currentContextMenu.data();
383 #endif
384 #ifndef QT_NO_UNDOSTACK
385     delete undoStack;
386 #endif
387     
388     if (inspector) {
389         // If the inspector is ours, delete it, otherwise just detach from it.
390         if (inspectorIsInternalOnly)
391             delete inspector;
392         else
393             inspector->setPage(0);
394     }
395     // Explicitly destruct the WebCore page at this point when the
396     // QWebPagePrivate / QWebPageAdapater vtables are still intact,
397     // in order for various destruction callbacks out of WebCore to
398     // work.
399     deletePage();
400 }
401
402 WebCore::Page* QWebPagePrivate::core(const QWebPage* page)
403 {
404     return page->d->page;
405 }
406
407 void QWebPagePrivate::show()
408 {
409     if (!view)
410         return;
411     view->window()->show();
412 }
413
414 void QWebPagePrivate::setFocus()
415 {
416     if (!view)
417         return;
418     view->setFocus();
419 }
420
421 void QWebPagePrivate::unfocus()
422 {
423     if (!view)
424         return;
425     view->clearFocus();
426 }
427
428 void QWebPagePrivate::setWindowRect(const QRect &rect)
429 {
430     emit q->geometryChangeRequested(rect);
431 }
432
433 QSize QWebPagePrivate::viewportSize() const
434 {
435     return q->viewportSize();
436 }
437
438 QWebPageAdapter *QWebPagePrivate::createWindow(bool dialog)
439 {
440     QWebPage *newPage = q->createWindow(dialog ? QWebPage::WebModalDialog : QWebPage::WebBrowserWindow);
441     if (!newPage)
442         return 0;
443     // Make sure the main frame exists, as WebCore expects it when returning from this ChromeClient::createWindow()
444     newPage->d->createMainFrame();
445     return newPage->d;
446 }
447
448 void QWebPagePrivate::javaScriptConsoleMessage(const QString &message, int lineNumber, const QString &sourceID)
449 {
450     q->javaScriptConsoleMessage(message, lineNumber, sourceID);
451 }
452
453 void QWebPagePrivate::javaScriptAlert(QWebFrameAdapter* frame, const QString& msg)
454 {
455     q->javaScriptAlert(QWebFramePrivate::kit(frame), msg);
456 }
457
458 bool QWebPagePrivate::javaScriptConfirm(QWebFrameAdapter* frame, const QString& msg)
459 {
460     return q->javaScriptConfirm(QWebFramePrivate::kit(frame), msg);
461 }
462
463 bool QWebPagePrivate::javaScriptPrompt(QWebFrameAdapter *frame, const QString &msg, const QString &defaultValue, QString *result)
464 {
465     return q->javaScriptPrompt(QWebFramePrivate::kit(frame), msg, defaultValue, result);
466 }
467
468 void QWebPagePrivate::printRequested(QWebFrameAdapter *frame)
469 {
470     emit q->printRequested(QWebFramePrivate::kit(frame));
471 }
472
473 void QWebPagePrivate::databaseQuotaExceeded(QWebFrameAdapter* frame, const QString& databaseName)
474 {
475     emit q->databaseQuotaExceeded(QWebFramePrivate::kit(frame), databaseName);
476 }
477
478 void QWebPagePrivate::applicationCacheQuotaExceeded(QWebSecurityOrigin *origin, quint64 defaultOriginQuota, quint64 c)
479 {
480     emit q->applicationCacheQuotaExceeded(origin, defaultOriginQuota, defaultOriginQuota);
481 }
482
483 void QWebPagePrivate::setToolTip(const QString &tip)
484 {
485 #ifndef QT_NO_TOOLTIP
486     if (!view)
487         return;
488
489     if (tip.isEmpty()) {
490         view->setToolTip(QString());
491         QToolTip::hideText();
492     } else {
493         QString dtip = QLatin1String("<p>") + QString(tip).toHtmlEscaped() + QLatin1String("</p>");
494         view->setToolTip(dtip);
495     }
496 #else
497     Q_UNUSED(tip);
498 #endif
499 }
500
501 #if USE(QT_MULTIMEDIA)
502 QWebFullScreenVideoHandler *QWebPagePrivate::createFullScreenVideoHandler()
503 {
504     return new WebKit::DefaultFullScreenVideoHandler;
505 }
506 #endif
507
508 QWebFrameAdapter *QWebPagePrivate::mainFrameAdapter()
509 {
510     return q->mainFrame()->d;
511 }
512
513 QStringList QWebPagePrivate::chooseFiles(QWebFrameAdapter *frame, bool allowMultiple, const QStringList &suggestedFileNames)
514 {
515     if (allowMultiple && q->supportsExtension(QWebPage::ChooseMultipleFilesExtension)) {
516         QWebPage::ChooseMultipleFilesExtensionOption option;
517         option.parentFrame = QWebFramePrivate::kit(frame);
518         option.suggestedFileNames = suggestedFileNames;
519
520         QWebPage::ChooseMultipleFilesExtensionReturn output;
521         q->extension(QWebPage::ChooseMultipleFilesExtension, &option, &output);
522
523         return output.fileNames;
524     }
525     // Single file
526     QStringList result;
527     QString suggestedFile;
528     if (!suggestedFileNames.isEmpty())
529         suggestedFile = suggestedFileNames.first();
530     QString file = q->chooseFile(QWebFramePrivate::kit(frame), suggestedFile);
531     if (!file.isEmpty())
532         result << file;
533     return result;
534 }
535
536 bool QWebPagePrivate::acceptNavigationRequest(QWebFrameAdapter *frameAdapter, const QNetworkRequest &request, int type)
537 {
538     QWebFrame *frame = frameAdapter ? QWebFramePrivate::kit(frameAdapter): 0;
539     if (insideOpenCall
540         && frame == mainFrame.data())
541         return true;
542     return q->acceptNavigationRequest(frame, request, QWebPage::NavigationType(type));
543 }
544
545 void QWebPagePrivate::emitRestoreFrameStateRequested(QWebFrameAdapter *frame)
546 {
547     emit q->restoreFrameStateRequested(QWebFramePrivate::kit(frame));
548 }
549
550 void QWebPagePrivate::emitSaveFrameStateRequested(QWebFrameAdapter *frame, QWebHistoryItem *item)
551 {
552     emit q->saveFrameStateRequested(QWebFramePrivate::kit(frame), item);
553 }
554
555 void QWebPagePrivate::emitDownloadRequested(const QNetworkRequest &request)
556 {
557     emit q->downloadRequested(request);
558 }
559
560 void QWebPagePrivate::emitFrameCreated(QWebFrameAdapter *frame)
561 {
562     emit q->frameCreated(QWebFramePrivate::kit(frame));
563 }
564
565 bool QWebPagePrivate::errorPageExtension(QWebPageAdapter::ErrorPageOption *opt, QWebPageAdapter::ErrorPageReturn *out)
566 {
567     QWebPage::ErrorPageExtensionOption option;
568     if (opt->domain == QLatin1String("QtNetwork"))
569         option.domain = QWebPage::QtNetwork;
570     else if (opt->domain == QLatin1String("HTTP"))
571         option.domain = QWebPage::Http;
572     else if (opt->domain == QLatin1String("WebKit"))
573         option.domain = QWebPage::WebKit;
574     else
575         return false;
576     option.url = opt->url;
577     option.frame = QWebFramePrivate::kit(opt->frame);
578     option.error = opt->error;
579     option.errorString = opt->errorString;
580     QWebPage::ErrorPageExtensionReturn output;
581     if (!q->extension(QWebPage::ErrorPageExtension, &option, &output))
582         return false;
583     out->baseUrl = output.baseUrl;
584     out->content = output.content;
585     out->contentType = output.contentType;
586     out->encoding = output.encoding;
587     return true;
588 }
589
590 QtPluginWidgetAdapter *QWebPagePrivate::createPlugin(const QString &classid, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues)
591 {
592     QObject *widget = q->createPlugin(classid, url, paramNames, paramValues);
593     return adapterForWidget(widget);
594 }
595
596 QtPluginWidgetAdapter *QWebPagePrivate::adapterForWidget(QObject *object) const
597 {
598     if (QWidget *widget = qobject_cast<QWidget*>(object))
599         return new QWidgetPluginImpl(widget);
600     if (QGraphicsWidget *widget = qobject_cast<QGraphicsWidget*>(object))
601         return new QGraphicsWidgetPluginImpl(widget);
602     return 0;
603 }
604
605 void QWebPagePrivate::createMainFrame()
606 {
607     if (!mainFrame) {
608         mainFrame = new QWebFrame(q);
609         emit q->frameCreated(mainFrame.data());
610     }
611 }
612
613 static QWebPage::WebAction webActionForContextMenuAction(WebCore::ContextMenuAction action)
614 {
615     switch (action) {
616         case WebCore::ContextMenuItemTagOpenLink: return QWebPage::OpenLink;
617         case WebCore::ContextMenuItemTagOpenLinkInNewWindow: return QWebPage::OpenLinkInNewWindow;
618         case WebCore::ContextMenuItemTagOpenLinkInThisWindow: return QWebPage::OpenLinkInThisWindow;
619         case WebCore::ContextMenuItemTagDownloadLinkToDisk: return QWebPage::DownloadLinkToDisk;
620         case WebCore::ContextMenuItemTagCopyLinkToClipboard: return QWebPage::CopyLinkToClipboard;
621         case WebCore::ContextMenuItemTagOpenImageInNewWindow: return QWebPage::OpenImageInNewWindow;
622         case WebCore::ContextMenuItemTagDownloadImageToDisk: return QWebPage::DownloadImageToDisk;
623         case WebCore::ContextMenuItemTagCopyImageToClipboard: return QWebPage::CopyImageToClipboard;
624         case WebCore::ContextMenuItemTagCopyImageUrlToClipboard: return QWebPage::CopyImageUrlToClipboard;
625         case WebCore::ContextMenuItemTagOpenFrameInNewWindow: return QWebPage::OpenFrameInNewWindow;
626         case WebCore::ContextMenuItemTagCopy: return QWebPage::Copy;
627         case WebCore::ContextMenuItemTagGoBack: return QWebPage::Back;
628         case WebCore::ContextMenuItemTagGoForward: return QWebPage::Forward;
629         case WebCore::ContextMenuItemTagStop: return QWebPage::Stop;
630         case WebCore::ContextMenuItemTagReload: return QWebPage::Reload;
631         case WebCore::ContextMenuItemTagCut: return QWebPage::Cut;
632         case WebCore::ContextMenuItemTagPaste: return QWebPage::Paste;
633         case WebCore::ContextMenuItemTagDefaultDirection: return QWebPage::SetTextDirectionDefault;
634         case WebCore::ContextMenuItemTagLeftToRight: return QWebPage::SetTextDirectionLeftToRight;
635         case WebCore::ContextMenuItemTagRightToLeft: return QWebPage::SetTextDirectionRightToLeft;
636         case WebCore::ContextMenuItemTagBold: return QWebPage::ToggleBold;
637         case WebCore::ContextMenuItemTagItalic: return QWebPage::ToggleItalic;
638         case WebCore::ContextMenuItemTagUnderline: return QWebPage::ToggleUnderline;
639         case WebCore::ContextMenuItemTagSelectAll: return QWebPage::SelectAll;
640 #if ENABLE(INSPECTOR)
641         case WebCore::ContextMenuItemTagInspectElement: return QWebPage::InspectElement;
642 #endif
643         default: break;
644     }
645     return QWebPage::NoWebAction;
646 }
647
648 #ifndef QT_NO_CONTEXTMENU
649 QMenu *QWebPagePrivate::createContextMenu(const WebCore::ContextMenu *webcoreMenu,
650         const QList<WebCore::ContextMenuItem> *items, QBitArray *visitedWebActions)
651 {
652     if (!client || !webcoreMenu)
653         return 0;
654
655     QMenu* menu = new QMenu(q->view());
656     for (int i = 0; i < items->count(); ++i) {
657         const ContextMenuItem &item = items->at(i);
658         switch (item.type()) {
659         case WebCore::CheckableActionType: /* fall through */
660         case WebCore::ActionType: {
661             QWebPage::WebAction action = webActionForContextMenuAction(item.action());
662             QAction *a = q->action(action);
663             if (a) {
664                 ContextMenuItem it(item);
665                 page->contextMenuController()->checkOrEnableIfNeeded(it);
666                 PlatformMenuItemDescription desc = it.releasePlatformDescription();
667                 a->setEnabled(desc.enabled);
668                 a->setChecked(desc.checked);
669                 a->setCheckable(item.type() == WebCore::CheckableActionType);
670
671                 menu->addAction(a);
672                 visitedWebActions->setBit(action);
673             }
674             break;
675         }
676         case WebCore::SeparatorType:
677             menu->addSeparator();
678             break;
679         case WebCore::SubmenuType: {
680             QMenu *subMenu = createContextMenu(webcoreMenu, item.platformSubMenu(), visitedWebActions);
681
682             bool anyEnabledAction = false;
683
684             QList<QAction *> actions = subMenu->actions();
685             for (int i = 0; i < actions.count(); ++i) {
686                 if (actions.at(i)->isVisible())
687                     anyEnabledAction |= actions.at(i)->isEnabled();
688             }
689
690             // don't show sub-menus with just disabled actions
691             if (anyEnabledAction) {
692                 subMenu->setTitle(item.title());
693                 menu->addAction(subMenu->menuAction());
694             } else
695                 delete subMenu;
696             break;
697         }
698         }
699     }
700     return menu;
701 }
702 #endif // QT_NO_CONTEXTMENU
703
704 #ifndef QT_NO_ACTION
705 void QWebPagePrivate::_q_webActionTriggered(bool checked)
706 {
707     QAction *a = qobject_cast<QAction *>(q->sender());
708     if (!a)
709         return;
710     QWebPage::WebAction action = static_cast<QWebPage::WebAction>(a->data().toInt());
711     q->triggerAction(action, checked);
712 }
713 #endif // QT_NO_ACTION
714
715 void QWebPagePrivate::_q_cleanupLeakMessages()
716 {
717 #ifndef NDEBUG
718     // Need this to make leak messages accurate.
719     memoryCache()->setCapacities(0, 0, 0);
720 #endif
721 }
722
723 void QWebPagePrivate::updateAction(QWebPage::WebAction action)
724 {
725 #ifdef QT_NO_ACTION
726     Q_UNUSED(action)
727 #else
728     QAction *a = actions[action];
729     if (!a || !mainFrame)
730         return;
731
732     WebCore::FrameLoader *loader = mainFrame.data()->d->frame->loader();
733     WebCore::Editor *editor = page->focusController()->focusedOrMainFrame()->editor();
734
735     bool enabled = a->isEnabled();
736     bool checked = a->isChecked();
737
738     switch (action) {
739         case QWebPage::Back:
740             enabled = page->canGoBackOrForward(-1);
741             break;
742         case QWebPage::Forward:
743             enabled = page->canGoBackOrForward(1);
744             break;
745         case QWebPage::Stop:
746             enabled = loader->isLoading();
747             break;
748         case QWebPage::Reload:
749         case QWebPage::ReloadAndBypassCache:
750             enabled = !loader->isLoading();
751             break;
752 #ifndef QT_NO_UNDOSTACK
753         case QWebPage::Undo:
754         case QWebPage::Redo:
755             // those two are handled by QUndoStack
756             break;
757 #endif // QT_NO_UNDOSTACK
758         case QWebPage::SelectAll: // editor command is always enabled
759             break;
760         case QWebPage::SetTextDirectionDefault:
761         case QWebPage::SetTextDirectionLeftToRight:
762         case QWebPage::SetTextDirectionRightToLeft:
763             enabled = editor->canEdit();
764             checked = false;
765             break;
766         default: {
767             // see if it's an editor command
768             const char* commandName = editorCommandForWebActions(action);
769
770             // if it's an editor command, let it's logic determine state
771             if (commandName) {
772                 Editor::Command command = editor->command(commandName);
773                 enabled = command.isEnabled();
774                 if (enabled)
775                     checked = command.state() != FalseTriState;
776                 else
777                     checked = false;
778             }
779             break;
780         }
781     }
782
783     a->setEnabled(enabled);
784
785     if (a->isCheckable())
786         a->setChecked(checked);
787 #endif // QT_NO_ACTION
788 }
789
790 void QWebPagePrivate::updateNavigationActions()
791 {
792     updateAction(QWebPage::Back);
793     updateAction(QWebPage::Forward);
794     updateAction(QWebPage::Stop);
795     updateAction(QWebPage::Reload);
796     updateAction(QWebPage::ReloadAndBypassCache);
797 }
798
799 QObject *QWebPagePrivate::inspectorHandle()
800 {
801     return getOrCreateInspector();
802 }
803
804 void QWebPagePrivate::setInspectorFrontend(QObject* frontend)
805 {
806     inspectorFrontend = qobject_cast<QWidget*>(frontend);
807     if (inspector)
808         inspector->d->setFrontend(frontend);
809 }
810
811 void QWebPagePrivate::setInspectorWindowTitle(const QString& title)
812 {
813     if (inspector)
814         inspector->setWindowTitle(title);
815 }
816
817 void QWebPagePrivate::createWebInspector(QObject** inspectorView, QWebPageAdapter** inspectorPage)
818 {
819     QWebPage* page = new WebKit::InspectorClientWebPage;
820     *inspectorView = page->view();
821     *inspectorPage = page->d;
822 }
823
824 #ifndef QT_NO_MENU
825 static QStringList iterateContextMenu(QMenu* menu)
826 {
827     if (!menu)
828         return QStringList();
829
830     QStringList items;
831     QList<QAction *> actions = menu->actions();
832     for (int i = 0; i < actions.count(); ++i) {
833         if (actions.at(i)->isSeparator())
834             items << QLatin1String("<separator>");
835         else
836             items << actions.at(i)->text();
837         if (actions.at(i)->menu())
838             items << iterateContextMenu(actions.at(i)->menu());
839     }
840     return items;
841 }
842 #endif
843
844 QStringList QWebPagePrivate::menuActionsAsText()
845 {
846 #ifndef QT_NO_MENU
847     return iterateContextMenu(currentContextMenu.data());
848 #else
849     return QStringList();
850 #endif
851 }
852
853 void QWebPagePrivate::emitViewportChangeRequested()
854 {
855     emit q->viewportChangeRequested();
856 }
857
858 void QWebPagePrivate::updateEditorActions()
859 {
860     updateAction(QWebPage::Cut);
861     updateAction(QWebPage::Copy);
862     updateAction(QWebPage::Paste);
863     updateAction(QWebPage::MoveToNextChar);
864     updateAction(QWebPage::MoveToPreviousChar);
865     updateAction(QWebPage::MoveToNextWord);
866     updateAction(QWebPage::MoveToPreviousWord);
867     updateAction(QWebPage::MoveToNextLine);
868     updateAction(QWebPage::MoveToPreviousLine);
869     updateAction(QWebPage::MoveToStartOfLine);
870     updateAction(QWebPage::MoveToEndOfLine);
871     updateAction(QWebPage::MoveToStartOfBlock);
872     updateAction(QWebPage::MoveToEndOfBlock);
873     updateAction(QWebPage::MoveToStartOfDocument);
874     updateAction(QWebPage::MoveToEndOfDocument);
875     updateAction(QWebPage::SelectNextChar);
876     updateAction(QWebPage::SelectPreviousChar);
877     updateAction(QWebPage::SelectNextWord);
878     updateAction(QWebPage::SelectPreviousWord);
879     updateAction(QWebPage::SelectNextLine);
880     updateAction(QWebPage::SelectPreviousLine);
881     updateAction(QWebPage::SelectStartOfLine);
882     updateAction(QWebPage::SelectEndOfLine);
883     updateAction(QWebPage::SelectStartOfBlock);
884     updateAction(QWebPage::SelectEndOfBlock);
885     updateAction(QWebPage::SelectStartOfDocument);
886     updateAction(QWebPage::SelectEndOfDocument);
887     updateAction(QWebPage::DeleteStartOfWord);
888     updateAction(QWebPage::DeleteEndOfWord);
889     updateAction(QWebPage::SetTextDirectionDefault);
890     updateAction(QWebPage::SetTextDirectionLeftToRight);
891     updateAction(QWebPage::SetTextDirectionRightToLeft);
892     updateAction(QWebPage::ToggleBold);
893     updateAction(QWebPage::ToggleItalic);
894     updateAction(QWebPage::ToggleUnderline);
895     updateAction(QWebPage::InsertParagraphSeparator);
896     updateAction(QWebPage::InsertLineSeparator);
897     updateAction(QWebPage::PasteAndMatchStyle);
898     updateAction(QWebPage::RemoveFormat);
899     updateAction(QWebPage::ToggleStrikethrough);
900     updateAction(QWebPage::ToggleSubscript);
901     updateAction(QWebPage::ToggleSuperscript);
902     updateAction(QWebPage::InsertUnorderedList);
903     updateAction(QWebPage::InsertOrderedList);
904     updateAction(QWebPage::Indent);
905     updateAction(QWebPage::Outdent);
906     updateAction(QWebPage::AlignCenter);
907     updateAction(QWebPage::AlignJustified);
908     updateAction(QWebPage::AlignLeft);
909     updateAction(QWebPage::AlignRight);
910 }
911
912 void QWebPagePrivate::timerEvent(QTimerEvent *ev)
913 {
914     int timerId = ev->timerId();
915     if (timerId == tripleClickTimer.timerId())
916         tripleClickTimer.stop();
917     else
918         q->timerEvent(ev);
919 }
920
921 void QWebPagePrivate::mouseMoveEvent(QMouseEvent* ev)
922 {
923     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame.data());
924     if (!frame->view())
925         return;
926
927     bool accepted = frame->eventHandler()->mouseMoved(convertMouseEvent(ev, 0));
928     ev->setAccepted(accepted);
929 }
930
931 void QWebPagePrivate::mousePressEvent(QMouseEvent* ev)
932 {
933     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame.data());
934     if (!frame->view())
935         return;
936
937     RefPtr<WebCore::Node> oldNode;
938     Frame* focusedFrame = page->focusController()->focusedFrame();
939     if (Document* focusedDocument = focusedFrame ? focusedFrame->document() : 0)
940         oldNode = focusedDocument->focusedNode();
941
942     if (tripleClickTimer.isActive()
943             && (ev->pos() - tripleClick).manhattanLength()
944                 < QApplication::startDragDistance()) {
945         mouseTripleClickEvent(ev);
946         return;
947     }
948
949     bool accepted = false;
950     adjustPointForClicking(ev);
951     PlatformMouseEvent mev = convertMouseEvent(ev, 1);
952     // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
953     if (mev.button() != NoButton)
954         accepted = frame->eventHandler()->handleMousePressEvent(mev);
955     ev->setAccepted(accepted);
956
957     RefPtr<WebCore::Node> newNode;
958     focusedFrame = page->focusController()->focusedFrame();
959     if (Document* focusedDocument = focusedFrame ? focusedFrame->document() : 0)
960         newNode = focusedDocument->focusedNode();
961
962     if (newNode && oldNode != newNode)
963         clickCausedFocus = true;
964 }
965
966 void QWebPagePrivate::mouseDoubleClickEvent(QMouseEvent *ev)
967 {
968     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame.data());
969     if (!frame->view())
970         return;
971
972     bool accepted = false;
973     PlatformMouseEvent mev = convertMouseEvent(ev, 2);
974     // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
975     if (mev.button() != NoButton)
976         accepted = frame->eventHandler()->handleMousePressEvent(mev);
977     ev->setAccepted(accepted);
978
979     tripleClickTimer.start(QApplication::doubleClickInterval(), q);
980     tripleClick = QPointF(ev->pos()).toPoint();
981 }
982
983 void QWebPagePrivate::mouseTripleClickEvent(QMouseEvent *ev)
984 {
985     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame.data());
986     if (!frame->view())
987         return;
988
989     bool accepted = false;
990     PlatformMouseEvent mev = convertMouseEvent(ev, 3);
991     // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
992     if (mev.button() != NoButton)
993         accepted = frame->eventHandler()->handleMousePressEvent(mev);
994     ev->setAccepted(accepted);
995 }
996
997 void QWebPagePrivate::mouseReleaseEvent(QMouseEvent *ev)
998 {
999     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame.data());
1000     if (!frame->view())
1001         return;
1002
1003     bool accepted = false;
1004     adjustPointForClicking(ev);
1005     PlatformMouseEvent mev = convertMouseEvent(ev, 0);
1006     // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
1007     if (mev.button() != NoButton)
1008         accepted = frame->eventHandler()->handleMouseReleaseEvent(mev);
1009     ev->setAccepted(accepted);
1010
1011     handleSoftwareInputPanel(ev->button(), QPointF(ev->pos()).toPoint());
1012 }
1013
1014 void QWebPagePrivate::handleSoftwareInputPanel(Qt::MouseButton button, const QPoint& pos)
1015 {
1016     Frame* frame = page->focusController()->focusedFrame();
1017     if (!frame)
1018         return;
1019
1020     if (client && client->inputMethodEnabled()
1021         && frame->document()->focusedNode()
1022         && button == Qt::LeftButton && qApp->autoSipEnabled()) {
1023         QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel(
1024             client->style()->styleHint(QStyle::SH_RequestSoftwareInputPanel));
1025         if (!clickCausedFocus || behavior == QStyle::RSIP_OnMouseClick) {
1026             HitTestResult result = frame->eventHandler()->hitTestResultAtPoint(frame->view()->windowToContents(pos), false);
1027             if (result.isContentEditable()) {
1028                 QEvent event(QEvent::RequestSoftwareInputPanel);
1029                 QApplication::sendEvent(client->ownerWidget(), &event);
1030             }
1031         }
1032     }
1033
1034     clickCausedFocus = false;
1035 }
1036
1037 #ifndef QT_NO_CONTEXTMENU
1038 void QWebPagePrivate::contextMenuEvent(const QPoint& globalPos)
1039 {
1040     QMenu *menu = q->createStandardContextMenu();
1041     if (menu) {
1042         menu->exec(globalPos);
1043         delete menu;
1044     }
1045 }
1046 #endif // QT_NO_CONTEXTMENU
1047
1048 /*!
1049     \since 4.5
1050     This function creates the standard context menu which is shown when
1051     the user clicks on the web page with the right mouse button. It is
1052     called from the default contextMenuEvent() handler. The popup menu's
1053     ownership is transferred to the caller.
1054  */
1055 QMenu *QWebPage::createStandardContextMenu()
1056 {
1057 #ifndef QT_NO_CONTEXTMENU
1058     QMenu* menu = d->currentContextMenu.data();
1059     d->currentContextMenu = 0;
1060     return menu;
1061 #else
1062     return 0;
1063 #endif
1064 }
1065
1066 #ifndef QT_NO_WHEELEVENT
1067 void QWebPagePrivate::wheelEvent(QWheelEvent *ev)
1068 {
1069     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame.data());
1070     if (!frame->view())
1071         return;
1072
1073     PlatformWheelEvent pev = convertWheelEvent(ev, QApplication::wheelScrollLines());
1074     bool accepted = frame->eventHandler()->handleWheelEvent(pev);
1075     ev->setAccepted(accepted);
1076 }
1077 #endif // QT_NO_WHEELEVENT
1078
1079 #ifndef QT_NO_SHORTCUT
1080 QWebPage::WebAction QWebPagePrivate::editorActionForKeyEvent(QKeyEvent* event)
1081 {
1082     static struct {
1083         QKeySequence::StandardKey standardKey;
1084         QWebPage::WebAction action;
1085     } editorActions[] = {
1086         { QKeySequence::Cut, QWebPage::Cut },
1087         { QKeySequence::Copy, QWebPage::Copy },
1088         { QKeySequence::Paste, QWebPage::Paste },
1089         { QKeySequence::Undo, QWebPage::Undo },
1090         { QKeySequence::Redo, QWebPage::Redo },
1091         { QKeySequence::MoveToNextChar, QWebPage::MoveToNextChar },
1092         { QKeySequence::MoveToPreviousChar, QWebPage::MoveToPreviousChar },
1093         { QKeySequence::MoveToNextWord, QWebPage::MoveToNextWord },
1094         { QKeySequence::MoveToPreviousWord, QWebPage::MoveToPreviousWord },
1095         { QKeySequence::MoveToNextLine, QWebPage::MoveToNextLine },
1096         { QKeySequence::MoveToPreviousLine, QWebPage::MoveToPreviousLine },
1097         { QKeySequence::MoveToStartOfLine, QWebPage::MoveToStartOfLine },
1098         { QKeySequence::MoveToEndOfLine, QWebPage::MoveToEndOfLine },
1099         { QKeySequence::MoveToStartOfBlock, QWebPage::MoveToStartOfBlock },
1100         { QKeySequence::MoveToEndOfBlock, QWebPage::MoveToEndOfBlock },
1101         { QKeySequence::MoveToStartOfDocument, QWebPage::MoveToStartOfDocument },
1102         { QKeySequence::MoveToEndOfDocument, QWebPage::MoveToEndOfDocument },
1103         { QKeySequence::SelectNextChar, QWebPage::SelectNextChar },
1104         { QKeySequence::SelectPreviousChar, QWebPage::SelectPreviousChar },
1105         { QKeySequence::SelectNextWord, QWebPage::SelectNextWord },
1106         { QKeySequence::SelectPreviousWord, QWebPage::SelectPreviousWord },
1107         { QKeySequence::SelectNextLine, QWebPage::SelectNextLine },
1108         { QKeySequence::SelectPreviousLine, QWebPage::SelectPreviousLine },
1109         { QKeySequence::SelectStartOfLine, QWebPage::SelectStartOfLine },
1110         { QKeySequence::SelectEndOfLine, QWebPage::SelectEndOfLine },
1111         { QKeySequence::SelectStartOfBlock, QWebPage::SelectStartOfBlock },
1112         { QKeySequence::SelectEndOfBlock,  QWebPage::SelectEndOfBlock },
1113         { QKeySequence::SelectStartOfDocument, QWebPage::SelectStartOfDocument },
1114         { QKeySequence::SelectEndOfDocument, QWebPage::SelectEndOfDocument },
1115         { QKeySequence::DeleteStartOfWord, QWebPage::DeleteStartOfWord },
1116         { QKeySequence::DeleteEndOfWord, QWebPage::DeleteEndOfWord },
1117         { QKeySequence::InsertParagraphSeparator, QWebPage::InsertParagraphSeparator },
1118         { QKeySequence::InsertLineSeparator, QWebPage::InsertLineSeparator },
1119         { QKeySequence::SelectAll, QWebPage::SelectAll },
1120         { QKeySequence::UnknownKey, QWebPage::NoWebAction }
1121     };
1122
1123     for (int i = 0; editorActions[i].standardKey != QKeySequence::UnknownKey; ++i)
1124         if (event == editorActions[i].standardKey)
1125             return editorActions[i].action;
1126
1127     return QWebPage::NoWebAction;
1128 }
1129 #endif // QT_NO_SHORTCUT
1130
1131 void QWebPagePrivate::keyPressEvent(QKeyEvent *ev)
1132 {
1133     bool handled = false;
1134     WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
1135     // we forward the key event to WebCore first to handle potential DOM
1136     // defined event handlers and later on end up in EditorClientQt::handleKeyboardEvent
1137     // to trigger editor commands via triggerAction().
1138     if (!handled)
1139         handled = frame->eventHandler()->keyEvent(ev);
1140     if (!handled) {
1141         handled = true;
1142         if (!handleScrolling(ev, frame)) {
1143             switch (ev->key()) {
1144             case Qt::Key_Back:
1145                 q->triggerAction(QWebPage::Back);
1146                 break;
1147             case Qt::Key_Forward:
1148                 q->triggerAction(QWebPage::Forward);
1149                 break;
1150             case Qt::Key_Stop:
1151                 q->triggerAction(QWebPage::Stop);
1152                 break;
1153             case Qt::Key_Refresh:
1154                 q->triggerAction(QWebPage::Reload);
1155                 break;
1156             case Qt::Key_Backspace:
1157                 if (ev->modifiers() == Qt::ShiftModifier)
1158                     q->triggerAction(QWebPage::Forward);
1159                 else
1160                     q->triggerAction(QWebPage::Back);
1161                 break;
1162             default:
1163                 handled = false;
1164                 break;
1165             }
1166         }
1167     }
1168
1169     ev->setAccepted(handled);
1170 }
1171
1172 void QWebPagePrivate::keyReleaseEvent(QKeyEvent *ev)
1173 {
1174     if (ev->isAutoRepeat()) {
1175         ev->setAccepted(true);
1176         return;
1177     }
1178
1179     WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
1180     bool handled = frame->eventHandler()->keyEvent(ev);
1181     ev->setAccepted(handled);
1182 }
1183
1184 void QWebPagePrivate::focusInEvent(QFocusEvent*)
1185 {
1186     FocusController *focusController = page->focusController();
1187     focusController->setActive(true);
1188     focusController->setFocused(true);
1189     if (!focusController->focusedFrame())
1190         focusController->setFocusedFrame(QWebFramePrivate::core(mainFrame.data()));
1191 }
1192
1193 void QWebPagePrivate::focusOutEvent(QFocusEvent*)
1194 {
1195     // only set the focused frame inactive so that we stop painting the caret
1196     // and the focus frame. But don't tell the focus controller so that upon
1197     // focusInEvent() we can re-activate the frame.
1198     FocusController *focusController = page->focusController();
1199     // Call setFocused first so that window.onblur doesn't get called twice
1200     focusController->setFocused(false);
1201     focusController->setActive(false);
1202 }
1203
1204 template<class T>
1205 void QWebPagePrivate::dragEnterEvent(T* ev)
1206 {
1207 #ifndef QT_NO_DRAGANDDROP
1208     DragData dragData(ev->mimeData(), QPointF(ev->pos()).toPoint(),
1209             QCursor::pos(), dropActionToDragOp(ev->possibleActions()));
1210     Qt::DropAction action = dragOpToDropAction(page->dragController()->dragEntered(&dragData).operation);
1211     ev->setDropAction(action);
1212     ev->acceptProposedAction();
1213 #endif
1214 }
1215
1216 template<class T>
1217 void QWebPagePrivate::dragLeaveEvent(T *ev)
1218 {
1219 #ifndef QT_NO_DRAGANDDROP
1220     DragData dragData(0, IntPoint(), QCursor::pos(), DragOperationNone);
1221     page->dragController()->dragExited(&dragData);
1222     ev->accept();
1223 #endif
1224 }
1225
1226 template<class T>
1227 void QWebPagePrivate::dragMoveEvent(T *ev)
1228 {
1229 #ifndef QT_NO_DRAGANDDROP
1230     DragData dragData(ev->mimeData(), QPointF(ev->pos()).toPoint(),
1231             QCursor::pos(), dropActionToDragOp(ev->possibleActions()));
1232     m_lastDropAction = dragOpToDropAction(page->dragController()->dragUpdated(&dragData).operation);
1233     ev->setDropAction(m_lastDropAction);
1234     if (m_lastDropAction != Qt::IgnoreAction)
1235         ev->accept();
1236 #endif
1237 }
1238
1239 template<class T>
1240 void QWebPagePrivate::dropEvent(T *ev)
1241 {
1242 #ifndef QT_NO_DRAGANDDROP
1243     DragData dragData(ev->mimeData(), QPointF(ev->pos()).toPoint(),
1244             QCursor::pos(), dropActionToDragOp(ev->possibleActions()));
1245     if (page->dragController()->performDrag(&dragData)) {
1246         ev->setDropAction(m_lastDropAction);
1247         ev->accept();
1248     }
1249 #endif
1250 }
1251
1252 void QWebPagePrivate::leaveEvent(QEvent*)
1253 {
1254     // Fake a mouse move event just outside of the widget, since all
1255     // the interesting mouse-out behavior like invalidating scrollbars
1256     // is handled by the WebKit event handler's mouseMoved function.
1257     QMouseEvent fakeEvent(QEvent::MouseMove, QCursor::pos(), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
1258     mouseMoveEvent(&fakeEvent);
1259 }
1260
1261 /*!
1262     \property QWebPage::palette
1263     \brief the page's palette
1264
1265     The base brush of the palette is used to draw the background of the main frame.
1266
1267     By default, this property contains the application's default palette.
1268 */
1269 void QWebPage::setPalette(const QPalette &pal)
1270 {
1271     d->palette = pal;
1272     if (!d->mainFrame || !d->mainFrame.data()->d->frame->view())
1273         return;
1274
1275     QBrush brush = pal.brush(QPalette::Base);
1276     QColor backgroundColor = brush.style() == Qt::SolidPattern ? brush.color() : QColor();
1277     QWebFramePrivate::core(d->mainFrame.data())->view()->updateBackgroundRecursively(backgroundColor, !backgroundColor.alpha());
1278 }
1279
1280 QPalette QWebPage::palette() const
1281 {
1282     return d->palette;
1283 }
1284
1285 void QWebPagePrivate::inputMethodEvent(QInputMethodEvent *ev)
1286 {
1287     WebCore::Frame *frame = page->focusController()->focusedOrMainFrame();
1288     WebCore::Editor *editor = frame->editor();
1289
1290     if (!editor->canEdit()) {
1291         ev->ignore();
1292         return;
1293     }
1294
1295     Node* node = 0;
1296     if (frame->selection()->rootEditableElement())
1297         node = frame->selection()->rootEditableElement()->shadowAncestorNode();
1298
1299     Vector<CompositionUnderline> underlines;
1300     bool hasSelection = false;
1301
1302     for (int i = 0; i < ev->attributes().size(); ++i) {
1303         const QInputMethodEvent::Attribute& a = ev->attributes().at(i);
1304         switch (a.type) {
1305         case QInputMethodEvent::TextFormat: {
1306             QTextCharFormat textCharFormat = a.value.value<QTextFormat>().toCharFormat();
1307             QColor qcolor = textCharFormat.underlineColor();
1308             underlines.append(CompositionUnderline(qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length)), Color(makeRGBA(qcolor.red(), qcolor.green(), qcolor.blue(), qcolor.alpha())), false));
1309             break;
1310         }
1311         case QInputMethodEvent::Cursor: {
1312             frame->selection()->setCaretVisible(a.length); //if length is 0 cursor is invisible
1313             if (a.length > 0) {
1314                 RenderObject* caretRenderer = frame->selection()->caretRenderer();
1315                 if (caretRenderer) {
1316                     QColor qcolor = a.value.value<QColor>();
1317                     caretRenderer->style()->setColor(Color(makeRGBA(qcolor.red(), qcolor.green(), qcolor.blue(), qcolor.alpha())));
1318                 }
1319             }
1320             break;
1321         }
1322         case QInputMethodEvent::Selection: {
1323             hasSelection = true;
1324             // A selection in the inputMethodEvent is always reflected in the visible text
1325             if (node) {
1326                 if (HTMLTextFormControlElement* textControl = toTextFormControl(node))
1327                     textControl->setSelectionRange(qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length)));
1328             }
1329
1330             if (!ev->preeditString().isEmpty())
1331                 editor->setComposition(ev->preeditString(), underlines, qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length)));
1332             else {
1333                 // If we are in the middle of a composition, an empty pre-edit string and a selection of zero
1334                 // cancels the current composition
1335                 if (editor->hasComposition() && (a.start + a.length == 0))
1336                     editor->setComposition(QString(), underlines, 0, 0);
1337             }
1338             break;
1339         }
1340         default:
1341             break;
1342         }
1343     }
1344
1345     if (node && ev->replacementLength() > 0) {
1346         int cursorPos = frame->selection()->extent().offsetInContainerNode();
1347         int start = cursorPos + ev->replacementStart();
1348         if (HTMLTextFormControlElement* textControl = toTextFormControl(node))
1349             textControl->setSelectionRange(start, start + ev->replacementLength());
1350         // Commit regardless of whether commitString is empty, to get rid of selection.
1351         editor->confirmComposition(ev->commitString());
1352     } else if (!ev->commitString().isEmpty()) {
1353         if (editor->hasComposition())
1354             editor->confirmComposition(ev->commitString());
1355         else
1356             editor->insertText(ev->commitString(), 0);
1357     } else if (!hasSelection && !ev->preeditString().isEmpty())
1358         editor->setComposition(ev->preeditString(), underlines, 0, 0);
1359     else if (ev->preeditString().isEmpty() && editor->hasComposition())
1360         editor->confirmComposition(String());
1361
1362     ev->accept();
1363 }
1364
1365 #ifndef QT_NO_PROPERTIES
1366 typedef struct {
1367     const char* name;
1368     double deferredRepaintDelay;
1369     double initialDeferredRepaintDelayDuringLoading;
1370     double maxDeferredRepaintDelayDuringLoading;
1371     double deferredRepaintDelayIncrementDuringLoading;
1372 } QRepaintThrottlingPreset;
1373
1374 void QWebPagePrivate::dynamicPropertyChangeEvent(QDynamicPropertyChangeEvent* event)
1375 {
1376     if (event->propertyName() == "_q_viewMode") {
1377         page->setViewMode(Page::stringToViewMode(q->property("_q_viewMode").toString()));
1378     } else if (event->propertyName() == "_q_HTMLTokenizerChunkSize") {
1379         int chunkSize = q->property("_q_HTMLTokenizerChunkSize").toInt();
1380         q->handle()->page->setCustomHTMLTokenizerChunkSize(chunkSize);
1381     } else if (event->propertyName() == "_q_HTMLTokenizerTimeDelay") {
1382         double timeDelay = q->property("_q_HTMLTokenizerTimeDelay").toDouble();
1383         q->handle()->page->setCustomHTMLTokenizerTimeDelay(timeDelay);
1384     } else if (event->propertyName() == "_q_RepaintThrottlingDeferredRepaintDelay") {
1385         double p = q->property("_q_RepaintThrottlingDeferredRepaintDelay").toDouble();
1386         FrameView::setRepaintThrottlingDeferredRepaintDelay(p);
1387     } else if (event->propertyName() == "_q_RepaintThrottlingnInitialDeferredRepaintDelayDuringLoading") {
1388         double p = q->property("_q_RepaintThrottlingnInitialDeferredRepaintDelayDuringLoading").toDouble();
1389         FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(p);
1390     } else if (event->propertyName() == "_q_RepaintThrottlingMaxDeferredRepaintDelayDuringLoading") {
1391         double p = q->property("_q_RepaintThrottlingMaxDeferredRepaintDelayDuringLoading").toDouble();
1392         FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(p);
1393     } else if (event->propertyName() == "_q_RepaintThrottlingDeferredRepaintDelayIncrementDuringLoading") {
1394         double p = q->property("_q_RepaintThrottlingDeferredRepaintDelayIncrementDuringLoading").toDouble();
1395         FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(p);
1396     } else if (event->propertyName() == "_q_RepaintThrottlingPreset") {
1397         static const QRepaintThrottlingPreset presets[] = {
1398             {   "NoThrottling",     0,      0,      0,      0 },
1399             {   "Legacy",       0.025,      0,    2.5,    0.5 },
1400             {   "Minimal",       0.01,      0,      1,    0.2 },
1401             {   "Medium",       0.025,      1,      5,    0.5 },
1402             {   "Heavy",          0.1,      2,     10,      1 }
1403         };
1404
1405         QString p = q->property("_q_RepaintThrottlingPreset").toString();
1406         for (size_t i = 0; i < sizeof(presets) / sizeof(presets[0]); i++) {
1407             if (p == QLatin1String(presets[i].name)) {
1408                 FrameView::setRepaintThrottlingDeferredRepaintDelay(
1409                         presets[i].deferredRepaintDelay);
1410                 FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(
1411                         presets[i].initialDeferredRepaintDelayDuringLoading);
1412                 FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(
1413                         presets[i].maxDeferredRepaintDelayDuringLoading);
1414                 FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(
1415                         presets[i].deferredRepaintDelayIncrementDuringLoading);
1416                 break;
1417             }
1418         }
1419     }
1420     else if (event->propertyName() == "_q_webInspectorServerPort") {
1421         InspectorServerQt* inspectorServer = InspectorServerQt::server();
1422         inspectorServer->listen(inspectorServerPort());
1423     } else if (event->propertyName() == "_q_deadDecodedDataDeletionInterval") {
1424         double interval = q->property("_q_deadDecodedDataDeletionInterval").toDouble();
1425         memoryCache()->setDeadDecodedDataDeletionInterval(interval);
1426     }
1427 }
1428 #endif
1429
1430 void QWebPagePrivate::shortcutOverrideEvent(QKeyEvent* event)
1431 {
1432     WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
1433     WebCore::Editor* editor = frame->editor();
1434     if (editor->canEdit()) {
1435         if (event->modifiers() == Qt::NoModifier
1436             || event->modifiers() == Qt::ShiftModifier
1437             || event->modifiers() == Qt::KeypadModifier) {
1438                 if (event->key() < Qt::Key_Escape) {
1439                     event->accept();
1440                 } else {
1441                     switch (event->key()) {
1442                     case Qt::Key_Return:
1443                     case Qt::Key_Enter:
1444                     case Qt::Key_Delete:
1445                     case Qt::Key_Home:
1446                     case Qt::Key_End:
1447                     case Qt::Key_Backspace:
1448                     case Qt::Key_Left:
1449                     case Qt::Key_Right:
1450                     case Qt::Key_Up:
1451                     case Qt::Key_Down:
1452                     case Qt::Key_Tab:
1453                         event->accept();
1454                     default:
1455                         break;
1456                     }
1457                 }
1458         }
1459 #ifndef QT_NO_SHORTCUT
1460         else if (editorActionForKeyEvent(event) != QWebPage::NoWebAction)
1461             event->accept();
1462 #endif
1463     }
1464 }
1465
1466 bool QWebPagePrivate::handleScrolling(QKeyEvent *ev, Frame *frame)
1467 {
1468     ScrollDirection direction;
1469     ScrollGranularity granularity;
1470
1471 #ifndef QT_NO_SHORTCUT
1472     if (ev == QKeySequence::MoveToNextPage
1473         || (ev->key() == Qt::Key_Space && !(ev->modifiers() & Qt::ShiftModifier))) {
1474         granularity = ScrollByPage;
1475         direction = ScrollDown;
1476     } else if (ev == QKeySequence::MoveToPreviousPage
1477                || ((ev->key() == Qt::Key_Space) && (ev->modifiers() & Qt::ShiftModifier))) {
1478         granularity = ScrollByPage;
1479         direction = ScrollUp;
1480     } else
1481 #endif // QT_NO_SHORTCUT
1482     if ((ev->key() == Qt::Key_Up && ev->modifiers() & Qt::ControlModifier)
1483                || ev->key() == Qt::Key_Home) {
1484         granularity = ScrollByDocument;
1485         direction = ScrollUp;
1486     } else if ((ev->key() == Qt::Key_Down && ev->modifiers() & Qt::ControlModifier)
1487                || ev->key() == Qt::Key_End) {
1488         granularity = ScrollByDocument;
1489         direction = ScrollDown;
1490     } else {
1491         switch (ev->key()) {
1492             case Qt::Key_Up:
1493                 granularity = ScrollByLine;
1494                 direction = ScrollUp;
1495                 break;
1496             case Qt::Key_Down:
1497                 granularity = ScrollByLine;
1498                 direction = ScrollDown;
1499                 break;
1500             case Qt::Key_Left:
1501                 granularity = ScrollByLine;
1502                 direction = ScrollLeft;
1503                 break;
1504             case Qt::Key_Right:
1505                 granularity = ScrollByLine;
1506                 direction = ScrollRight;
1507                 break;
1508             default:
1509                 return false;
1510         }
1511     }
1512
1513     return frame->eventHandler()->scrollRecursively(direction, granularity);
1514 }
1515
1516 void QWebPagePrivate::adjustPointForClicking(QMouseEvent*)
1517 {
1518     notImplemented();
1519 }
1520
1521 #if !defined(QT_NO_GRAPHICSVIEW)
1522 void QWebPagePrivate::adjustPointForClicking(QGraphicsSceneMouseEvent* ev)
1523 {
1524     QtPlatformPlugin platformPlugin;
1525     OwnPtr<QWebTouchModifier> touchModifier = platformPlugin.createTouchModifier();
1526     if (!touchModifier)
1527         return;
1528
1529     unsigned topPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Up);
1530     unsigned rightPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Right);
1531     unsigned bottomPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Down);
1532     unsigned leftPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Left);
1533
1534     touchModifier = nullptr;
1535
1536     if (!topPadding && !rightPadding && !bottomPadding && !leftPadding)
1537         return;
1538
1539     Document* startingDocument = page->mainFrame()->document();
1540     if (!startingDocument)
1541         return;
1542
1543     IntPoint originalPoint(QPointF(ev->pos()).toPoint());
1544     TouchAdjuster touchAdjuster(topPadding, rightPadding, bottomPadding, leftPadding);
1545     IntPoint adjustedPoint = touchAdjuster.findCandidatePointForTouch(originalPoint, startingDocument);
1546     if (adjustedPoint == IntPoint::zero())
1547         return;
1548
1549     ev->setPos(QPointF(adjustedPoint));
1550 }
1551 #endif
1552
1553 bool QWebPagePrivate::touchEvent(QTouchEvent* event)
1554 {
1555 #if ENABLE(TOUCH_EVENTS)
1556     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame.data());
1557     if (!frame->view())
1558         return false;
1559
1560     // Always accept the QTouchEvent so that we'll receive also TouchUpdate and TouchEnd events
1561     event->setAccepted(true);
1562
1563     // Return whether the default action was cancelled in the JS event handler
1564     return frame->eventHandler()->handleTouchEvent(convertTouchEvent(event));
1565 #else
1566     event->ignore();
1567     return false;
1568 #endif
1569 }
1570
1571 bool QWebPagePrivate::gestureEvent(QGestureEvent* event)
1572 {
1573     QWebFrameAdapter* frame = mainFrame.data()->d;
1574     if (!frame->hasView())
1575         return false;
1576     // QGestureEvents can contain updates for multiple gestures.
1577     bool handled = false;
1578 #if ENABLE(GESTURE_EVENTS)
1579     // QGestureEvent lives in Widgets, we'll need a dummy struct to mule the info it contains to the "other side"
1580     QGestureEventFacade gestureFacade;
1581
1582     QGesture* gesture = event->gesture(Qt::TapGesture);
1583     // Beware that gestures send by DumpRenderTree will have state Qt::NoGesture,
1584     // due to not originating from a GestureRecognizer.
1585     if (gesture && (gesture->state() == Qt::GestureStarted || gesture->state() == Qt::NoGesture)) {
1586         gestureFacade.type = Qt::TapGesture;
1587         QPointF globalPos = static_cast<const QTapGesture*>(gesture)->position();
1588         gestureFacade.globalPos = globalPos.toPoint();
1589         gestureFacade.pos = event->widget()->mapFromGlobal(globalPos.toPoint());
1590         frame->handleGestureEvent(&gestureFacade);
1591         handled = true;
1592     }
1593     gesture = event->gesture(Qt::TapAndHoldGesture);
1594     if (gesture && (gesture->state() == Qt::GestureStarted || gesture->state() == Qt::NoGesture)) {
1595         gestureFacade.type = Qt::TapAndHoldGesture;
1596         QPointF globalPos = static_cast<const QTapAndHoldGesture*>(gesture)->position();
1597         gestureFacade.globalPos = globalPos.toPoint();
1598         gestureFacade.pos = event->widget()->mapFromGlobal(globalPos.toPoint());
1599         frame->handleGestureEvent(&gestureFacade);
1600         handled = true;
1601     }
1602 #endif // ENABLE(GESTURE_EVENTS)
1603
1604     event->setAccepted(handled);
1605     return handled;
1606 }
1607
1608 /*!
1609   This method is used by the input method to query a set of properties of the page
1610   to be able to support complex input method operations as support for surrounding
1611   text and reconversions.
1612
1613   \a property specifies which property is queried.
1614
1615   \sa QWidget::inputMethodEvent(), QInputMethodEvent, QInputContext
1616 */
1617 QVariant QWebPage::inputMethodQuery(Qt::InputMethodQuery property) const
1618 {
1619     Frame* frame = d->page->focusController()->focusedFrame();
1620     if (!frame)
1621         return QVariant();
1622
1623     WebCore::Editor* editor = frame->editor();
1624
1625     RenderObject* renderer = 0;
1626     RenderTextControl* renderTextControl = 0;
1627
1628     if (frame->selection()->rootEditableElement())
1629         renderer = frame->selection()->rootEditableElement()->shadowAncestorNode()->renderer();
1630
1631     if (renderer && renderer->isTextControl())
1632         renderTextControl = toRenderTextControl(renderer);
1633
1634     switch (property) {
1635         case Qt::ImMicroFocus: {
1636             WebCore::FrameView* view = frame->view();
1637             if (view && view->needsLayout()) {
1638                 // We can't access absoluteCaretBounds() while the view needs to layout.
1639                 return QVariant();
1640             }
1641             return QVariant(view->contentsToWindow(frame->selection()->absoluteCaretBounds()));
1642         }
1643         case Qt::ImFont: {
1644             if (renderTextControl) {
1645                 RenderStyle* renderStyle = renderTextControl->style();
1646                 return QVariant(QFont(renderStyle->font().syntheticFont()));
1647             }
1648             return QVariant(QFont());
1649         }
1650         case Qt::ImCursorPosition: {
1651             if (editor->hasComposition())
1652                 return QVariant(frame->selection()->end().offsetInContainerNode());
1653             return QVariant(frame->selection()->extent().offsetInContainerNode());
1654         }
1655         case Qt::ImSurroundingText: {
1656             if (renderTextControl && renderTextControl->textFormControlElement()) {
1657                 QString text = renderTextControl->textFormControlElement()->value();
1658                 RefPtr<Range> range = editor->compositionRange();
1659                 if (range)
1660                     text.remove(range->startPosition().offsetInContainerNode(), TextIterator::rangeLength(range.get()));
1661                 return QVariant(text);
1662             }
1663             return QVariant();
1664         }
1665         case Qt::ImCurrentSelection: {
1666             if (!editor->hasComposition() && renderTextControl && renderTextControl->textFormControlElement()) {
1667                 int start = frame->selection()->start().offsetInContainerNode();
1668                 int end = frame->selection()->end().offsetInContainerNode();
1669                 if (end > start)
1670                     return QVariant(QString(renderTextControl->textFormControlElement()->value()).mid(start, end - start));
1671             }
1672             return QVariant();
1673
1674         }
1675         case Qt::ImAnchorPosition: {
1676             if (editor->hasComposition())
1677                 return QVariant(frame->selection()->start().offsetInContainerNode());
1678             return QVariant(frame->selection()->base().offsetInContainerNode());
1679         }
1680         case Qt::ImMaximumTextLength: {
1681             if (frame->selection()->isContentEditable()) {
1682                 if (frame->document() && frame->document()->focusedNode()) {
1683                     if (frame->document()->focusedNode()->hasTagName(HTMLNames::inputTag)) {
1684                         HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(frame->document()->focusedNode());
1685                         return QVariant(inputElement->maxLength());
1686                     }
1687                 }
1688                 return QVariant(HTMLInputElement::maximumLength);
1689             }
1690             return QVariant(0);
1691         }
1692         default:
1693             return QVariant();
1694     }
1695 }
1696
1697 /*!
1698     \internal
1699 */
1700 void QWebPagePrivate::setInspector(QWebInspector* insp)
1701 {
1702     if (inspector)
1703         inspector->d->setFrontend(0);
1704
1705     inspector = insp;
1706
1707     // Give inspector frontend web view if previously created
1708     if (inspector && inspectorFrontend)
1709         inspector->d->setFrontend(inspectorFrontend);
1710 }
1711
1712 /*!
1713     \internal
1714     Returns the inspector and creates it if it wasn't created yet.
1715     The instance created here will not be available through QWebPage's API.
1716 */
1717 QWebInspector* QWebPagePrivate::getOrCreateInspector()
1718 {
1719 #if ENABLE(INSPECTOR)
1720     if (!inspector) {
1721         QWebInspector* insp = new QWebInspector;
1722         insp->setPage(q);
1723         inspectorIsInternalOnly = true;
1724
1725         Q_ASSERT(inspector); // Associated through QWebInspector::setPage(q)
1726     }
1727 #endif
1728     return inspector;
1729 }
1730
1731 /*! \internal */
1732 InspectorController* QWebPagePrivate::inspectorController()
1733 {
1734 #if ENABLE(INSPECTOR)
1735     return page->inspectorController();
1736 #else
1737     return 0;
1738 #endif
1739 }
1740
1741 quint16 QWebPagePrivate::inspectorServerPort()
1742 {
1743 #if ENABLE(INSPECTOR) && !defined(QT_NO_PROPERTIES)
1744     if (q && q->property("_q_webInspectorServerPort").isValid())
1745         return q->property("_q_webInspectorServerPort").toInt();
1746 #endif
1747     return 0;
1748 }
1749
1750 static bool hasMouseListener(Element* element)
1751 {
1752     ASSERT(element);
1753     return element->hasEventListeners(eventNames().clickEvent)
1754         || element->hasEventListeners(eventNames().mousedownEvent)
1755         || element->hasEventListeners(eventNames().mouseupEvent);
1756 }
1757
1758 static bool isClickableElement(Element* element, RefPtr<NodeList> list)
1759 {
1760     ASSERT(element);
1761     bool isClickable = hasMouseListener(element);
1762     if (!isClickable && list) {
1763         Element* parent = element->parentElement();
1764         unsigned count = list->length();
1765         for (unsigned i = 0; i < count && parent; i++) {
1766             if (list->item(i) != parent)
1767                 continue;
1768
1769             isClickable = hasMouseListener(parent);
1770             if (isClickable)
1771                 break;
1772
1773             parent = parent->parentElement();
1774         }
1775     }
1776
1777     ExceptionCode ec = 0;
1778     return isClickable
1779         || element->webkitMatchesSelector("a,*:link,*:visited,*[role=button],button,input,select,label", ec)
1780         || CSSComputedStyleDeclaration::create(element)->getPropertyValue(cssPropertyID("cursor")) == "pointer";
1781 }
1782
1783 static bool isValidFrameOwner(Element* element)
1784 {
1785     ASSERT(element);
1786     return element->isFrameOwnerElement() && static_cast<HTMLFrameOwnerElement*>(element)->contentFrame();
1787 }
1788
1789 static Element* nodeToElement(Node* node)
1790 {
1791     if (node && node->isElementNode())
1792         return static_cast<Element*>(node);
1793     return 0;
1794 }
1795
1796 QWebPagePrivate::TouchAdjuster::TouchAdjuster(unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
1797     : m_topPadding(topPadding)
1798     , m_rightPadding(rightPadding)
1799     , m_bottomPadding(bottomPadding)
1800     , m_leftPadding(leftPadding)
1801 {
1802 }
1803
1804 IntPoint QWebPagePrivate::TouchAdjuster::findCandidatePointForTouch(const IntPoint& touchPoint, Document* document) const
1805 {
1806     if (!document)
1807         return IntPoint();
1808
1809     int x = touchPoint.x();
1810     int y = touchPoint.y();
1811
1812     RefPtr<NodeList> intersectedNodes = document->nodesFromRect(x, y, m_topPadding, m_rightPadding, m_bottomPadding, m_leftPadding, false /*ignoreClipping*/, false /*allowShadowContent*/);
1813     if (!intersectedNodes)
1814         return IntPoint();
1815
1816     Element* closestClickableElement = 0;
1817     IntRect largestIntersectionRect;
1818     FrameView* view = document->frame()->view();
1819
1820     // Touch rect in contents coordinates.
1821     IntRect touchRect(HitTestLocation::rectForPoint(view->windowToContents(IntPoint(x, y)), m_topPadding, m_rightPadding, m_bottomPadding, m_leftPadding));
1822
1823     // Iterate over the list of nodes hit looking for the one whose bounding area
1824     // has largest intersection with the touch area (point + padding).
1825     for (unsigned i = 0; i < intersectedNodes->length(); i++) {
1826         Node* currentNode = intersectedNodes->item(i);
1827
1828         Element* currentElement = nodeToElement(currentNode);
1829         if (!currentElement || (!isClickableElement(currentElement, 0) && !isValidFrameOwner(currentElement)))
1830             continue;
1831
1832         IntRect currentElementBoundingRect = currentElement->pixelSnappedBoundingBox();
1833         currentElementBoundingRect.intersect(touchRect);
1834
1835         if (currentElementBoundingRect.isEmpty())
1836             continue;
1837
1838         int currentIntersectionRectArea = currentElementBoundingRect.width() * currentElementBoundingRect.height();
1839         int largestIntersectionRectArea = largestIntersectionRect.width() * largestIntersectionRect.height();
1840         if (currentIntersectionRectArea > largestIntersectionRectArea) {
1841             closestClickableElement = currentElement;
1842             largestIntersectionRect = currentElementBoundingRect;
1843         }
1844     }
1845
1846     if (largestIntersectionRect.isEmpty())
1847         return IntPoint();
1848
1849     // Handle the case when user taps a inner frame. It is done in three steps:
1850     // 1) Transform the original touch point to the inner document coordinates;
1851     // 1) Call nodesFromRect for the inner document in case;
1852     // 3) Re-add the inner frame offset (location) before passing the new clicking
1853     //    position to WebCore.
1854     if (closestClickableElement->isFrameOwnerElement()) {
1855         // Adjust client coordinates' origin to be top left of inner frame viewport.
1856         PassRefPtr<ClientRect> rect = closestClickableElement->getBoundingClientRect();
1857         IntPoint newTouchPoint = touchPoint;
1858         IntSize offset =  IntSize(rect->left(), rect->top());
1859         newTouchPoint -= offset;
1860
1861         HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(closestClickableElement);
1862         Document* childDocument = owner->contentFrame()->document();
1863         return findCandidatePointForTouch(newTouchPoint, childDocument);
1864     }
1865     return view->contentsToWindow(largestIntersectionRect).center();
1866 }
1867
1868 /*!
1869    \enum QWebPage::FindFlag
1870
1871    This enum describes the options available to the findText() function. The options
1872    can be OR-ed together from the following list:
1873
1874    \value FindBackward Searches backwards instead of forwards.
1875    \value FindCaseSensitively By default findText() works case insensitive. Specifying this option
1876    changes the behaviour to a case sensitive find operation.
1877    \value FindWrapsAroundDocument Makes findText() restart from the beginning of the document if the end
1878    was reached and the text was not found.
1879    \value HighlightAllOccurrences Highlights all existing occurrences of a specific string.
1880        (This value was introduced in 4.6.)
1881 */
1882
1883 /*!
1884     \enum QWebPage::LinkDelegationPolicy
1885
1886     This enum defines the delegation policies a webpage can have when activating links and emitting
1887     the linkClicked() signal.
1888
1889     \value DontDelegateLinks No links are delegated. Instead, QWebPage tries to handle them all.
1890     \value DelegateExternalLinks When activating links that point to documents not stored on the
1891     local filesystem or an equivalent - such as the Qt resource system - then linkClicked() is emitted.
1892     \value DelegateAllLinks Whenever a link is activated the linkClicked() signal is emitted.
1893
1894     \sa QWebPage::linkDelegationPolicy
1895 */
1896
1897 /*!
1898     \enum QWebPage::NavigationType
1899
1900     This enum describes the types of navigation available when browsing through hyperlinked
1901     documents.
1902
1903     \value NavigationTypeLinkClicked The user clicked on a link or pressed return on a focused link.
1904     \value NavigationTypeFormSubmitted The user activated a submit button for an HTML form.
1905     \value NavigationTypeBackOrForward Navigation to a previously shown document in the back or forward history is requested.
1906     \value NavigationTypeReload The user activated the reload action.
1907     \value NavigationTypeFormResubmitted An HTML form was submitted a second time.
1908     \value NavigationTypeOther A navigation to another document using a method not listed above.
1909
1910     \sa acceptNavigationRequest()
1911 */
1912
1913 /*!
1914     \enum QWebPage::WebAction
1915
1916     This enum describes the types of action which can be performed on the web page.
1917
1918     Actions only have an effect when they are applicable. The availability of
1919     actions can be be determined by checking \l{QAction::}{isEnabled()} on the
1920     action returned by action().
1921
1922     One method of enabling the text editing, cursor movement, and text selection actions
1923     is by setting \l contentEditable to true.
1924
1925     \value NoWebAction No action is triggered.
1926     \value OpenLink Open the current link.
1927     \value OpenLinkInNewWindow Open the current link in a new window.
1928     \value OpenLinkInThisWindow Open the current link without opening a new window. Used on links that would default to opening in another frame or a new window. (Added in Qt 5.0)
1929     \value OpenFrameInNewWindow Replicate the current frame in a new window.
1930     \value DownloadLinkToDisk Download the current link to the disk.
1931     \value CopyLinkToClipboard Copy the current link to the clipboard.
1932     \value OpenImageInNewWindow Open the highlighted image in a new window.
1933     \value DownloadImageToDisk Download the highlighted image to the disk.
1934     \value CopyImageToClipboard Copy the highlighted image to the clipboard.  (Added in Qt 4.8)
1935     \value CopyImageUrlToClipboard Copy the highlighted image's URL to the clipboard.
1936     \value Back Navigate back in the history of navigated links.
1937     \value Forward Navigate forward in the history of navigated links.
1938     \value Stop Stop loading the current page.
1939     \value StopScheduledPageRefresh Stop all pending page refresh/redirect requests.  (Added in Qt 4.7)
1940     \value Reload Reload the current page.
1941     \value ReloadAndBypassCache Reload the current page, but do not use any local cache. (Added in Qt 4.6)
1942     \value Cut Cut the content currently selected into the clipboard.
1943     \value Copy Copy the content currently selected into the clipboard.
1944     \value Paste Paste content from the clipboard.
1945     \value Undo Undo the last editing action.
1946     \value Redo Redo the last editing action.
1947     \value MoveToNextChar Move the cursor to the next character.
1948     \value MoveToPreviousChar Move the cursor to the previous character.
1949     \value MoveToNextWord Move the cursor to the next word.
1950     \value MoveToPreviousWord Move the cursor to the previous word.
1951     \value MoveToNextLine Move the cursor to the next line.
1952     \value MoveToPreviousLine Move the cursor to the previous line.
1953     \value MoveToStartOfLine Move the cursor to the start of the line.
1954     \value MoveToEndOfLine Move the cursor to the end of the line.
1955     \value MoveToStartOfBlock Move the cursor to the start of the block.
1956     \value MoveToEndOfBlock Move the cursor to the end of the block.
1957     \value MoveToStartOfDocument Move the cursor to the start of the document.
1958     \value MoveToEndOfDocument Move the cursor to the end of the document.
1959     \value SelectNextChar Select to the next character.
1960     \value SelectPreviousChar Select to the previous character.
1961     \value SelectNextWord Select to the next word.
1962     \value SelectPreviousWord Select to the previous word.
1963     \value SelectNextLine Select to the next line.
1964     \value SelectPreviousLine Select to the previous line.
1965     \value SelectStartOfLine Select to the start of the line.
1966     \value SelectEndOfLine Select to the end of the line.
1967     \value SelectStartOfBlock Select to the start of the block.
1968     \value SelectEndOfBlock Select to the end of the block.
1969     \value SelectStartOfDocument Select to the start of the document.
1970     \value SelectEndOfDocument Select to the end of the document.
1971     \value DeleteStartOfWord Delete to the start of the word.
1972     \value DeleteEndOfWord Delete to the end of the word.
1973     \value SetTextDirectionDefault Set the text direction to the default direction.
1974     \value SetTextDirectionLeftToRight Set the text direction to left-to-right.
1975     \value SetTextDirectionRightToLeft Set the text direction to right-to-left.
1976     \value ToggleBold Toggle the formatting between bold and normal weight.
1977     \value ToggleItalic Toggle the formatting between italic and normal style.
1978     \value ToggleUnderline Toggle underlining.
1979     \value InspectElement Show the Web Inspector with the currently highlighted HTML element.
1980     \value InsertParagraphSeparator Insert a new paragraph.
1981     \value InsertLineSeparator Insert a new line.
1982     \value SelectAll Selects all content.
1983     \value PasteAndMatchStyle Paste content from the clipboard with current style. (Added in Qt 4.6)
1984     \value RemoveFormat Removes formatting and style. (Added in Qt 4.6)
1985     \value ToggleStrikethrough Toggle the formatting between strikethrough and normal style. (Added in Qt 4.6)
1986     \value ToggleSubscript Toggle the formatting between subscript and baseline. (Added in Qt 4.6)
1987     \value ToggleSuperscript Toggle the formatting between supercript and baseline. (Added in Qt 4.6)
1988     \value InsertUnorderedList Toggles the selection between an ordered list and a normal block. (Added in Qt 4.6)
1989     \value InsertOrderedList Toggles the selection between an ordered list and a normal block. (Added in Qt 4.6)
1990     \value Indent Increases the indentation of the currently selected format block by one increment. (Added in Qt 4.6)
1991     \value Outdent Decreases the indentation of the currently selected format block by one increment. (Added in Qt 4.6)
1992     \value AlignCenter Applies center alignment to content. (Added in Qt 4.6)
1993     \value AlignJustified Applies full justification to content. (Added in Qt 4.6)
1994     \value AlignLeft Applies left justification to content. (Added in Qt 4.6)
1995     \value AlignRight Applies right justification to content. (Added in Qt 4.6)
1996
1997
1998     \omitvalue WebActionCount
1999
2000 */
2001
2002 /*!
2003     \enum QWebPage::WebWindowType
2004
2005     This enum describes the types of window that can be created by the createWindow() function.
2006
2007     \value WebBrowserWindow The window is a regular web browser window.
2008     \value WebModalDialog The window acts as modal dialog.
2009 */
2010
2011
2012 /*!
2013     \class QWebPage::ViewportAttributes
2014     \since 4.7
2015     \brief The QWebPage::ViewportAttributes class describes hints that can be applied to a viewport.
2016
2017     QWebPage::ViewportAttributes provides a description of a viewport, such as viewport geometry,
2018     initial scale factor with limits, plus information about whether a user should be able
2019     to scale the contents in the viewport or not, ie. by zooming.
2020
2021     ViewportAttributes can be set by a web author using the viewport meta tag extension, documented
2022     at \l{http://developer.apple.com/safari/library/documentation/appleapplications/reference/safariwebcontent/usingtheviewport/usingtheviewport.html}{Safari Reference Library: Using the Viewport Meta Tag}.
2023
2024     All values might not be set, as such when dealing with the hints, the developer needs to
2025     check whether the values are valid. Negative values denote an invalid qreal value.
2026
2027     \inmodule QtWebKit
2028 */
2029
2030 /*!
2031     Constructs an empty QWebPage::ViewportAttributes.
2032 */
2033 QWebPage::ViewportAttributes::ViewportAttributes()
2034     : d(0)
2035     , m_initialScaleFactor(-1.0)
2036     , m_minimumScaleFactor(-1.0)
2037     , m_maximumScaleFactor(-1.0)
2038     , m_devicePixelRatio(-1.0)
2039     , m_isUserScalable(true)
2040     , m_isValid(false)
2041 {
2042
2043 }
2044
2045 /*!
2046     Constructs a QWebPage::ViewportAttributes which is a copy from \a other .
2047 */
2048 QWebPage::ViewportAttributes::ViewportAttributes(const QWebPage::ViewportAttributes& other)
2049     : d(other.d)
2050     , m_initialScaleFactor(other.m_initialScaleFactor)
2051     , m_minimumScaleFactor(other.m_minimumScaleFactor)
2052     , m_maximumScaleFactor(other.m_maximumScaleFactor)
2053     , m_devicePixelRatio(other.m_devicePixelRatio)
2054     , m_isUserScalable(other.m_isUserScalable)
2055     , m_isValid(other.m_isValid)
2056     , m_size(other.m_size)
2057 {
2058
2059 }
2060
2061 /*!
2062     Destroys the QWebPage::ViewportAttributes.
2063 */
2064 QWebPage::ViewportAttributes::~ViewportAttributes()
2065 {
2066
2067 }
2068
2069 /*!
2070     Assigns the given QWebPage::ViewportAttributes to this viewport hints and returns a
2071     reference to this.
2072 */
2073 QWebPage::ViewportAttributes& QWebPage::ViewportAttributes::operator=(const QWebPage::ViewportAttributes& other)
2074 {
2075     if (this != &other) {
2076         d = other.d;
2077         m_initialScaleFactor = other.m_initialScaleFactor;
2078         m_minimumScaleFactor = other.m_minimumScaleFactor;
2079         m_maximumScaleFactor = other.m_maximumScaleFactor;
2080         m_isUserScalable = other.m_isUserScalable;
2081         m_isValid = other.m_isValid;
2082         m_size = other.m_size;
2083     }
2084
2085     return *this;
2086 }
2087
2088 /*! \fn inline bool QWebPage::ViewportAttributes::isValid() const
2089     Returns whether this is a valid ViewportAttributes or not.
2090
2091     An invalid ViewportAttributes will have an empty QSize, negative values for scale factors and
2092     true for the boolean isUserScalable.
2093 */
2094
2095 /*! \fn inline QSize QWebPage::ViewportAttributes::size() const
2096     Returns the size of the viewport.
2097 */
2098
2099 /*! \fn inline qreal QWebPage::ViewportAttributes::initialScaleFactor() const
2100     Returns the initial scale of the viewport as a multiplier.
2101 */
2102
2103 /*! \fn inline qreal QWebPage::ViewportAttributes::minimumScaleFactor() const
2104     Returns the minimum scale value of the viewport as a multiplier.
2105 */
2106
2107 /*! \fn inline qreal QWebPage::ViewportAttributes::maximumScaleFactor() const
2108     Returns the maximum scale value of the viewport as a multiplier.
2109 */
2110
2111 /*! \fn inline bool QWebPage::ViewportAttributes::isUserScalable() const
2112     Determines whether or not the scale can be modified by the user.
2113 */
2114
2115
2116 /*!
2117     \class QWebPage
2118     \since 4.4
2119     \brief The QWebPage class provides an object to view and edit web documents.
2120
2121     \inmodule QtWebKit
2122
2123     QWebPage holds a main frame responsible for web content, settings, the history
2124     of navigated links and actions. This class can be used, together with QWebFrame,
2125     to provide functionality like QWebView in a widget-less environment.
2126
2127     QWebPage's API is very similar to QWebView, as you are still provided with
2128     common functions like action() (known as
2129     \l{QWebView::pageAction()}{pageAction}() in QWebView), triggerAction(),
2130     findText() and settings(). More QWebView-like functions can be found in the
2131     main frame of QWebPage, obtained via the mainFrame() function. For example,
2132     the \l{QWebFrame::load()}{load}(), \l{QWebFrame::setUrl()}{setUrl}() and
2133     \l{QWebFrame::setHtml()}{setHtml}() functions for QWebPage can be accessed
2134     using QWebFrame.
2135
2136     The loadStarted() signal is emitted when the page begins to load.The
2137     loadProgress() signal, on the other hand, is emitted whenever an element
2138     of the web page completes loading, such as an embedded image, a script,
2139     etc. Finally, the loadFinished() signal is emitted when the page contents
2140     are loaded completely, independent of script execution or page rendering.
2141     Its argument, either true or false, indicates whether or not the load
2142     operation succeeded.
2143
2144     \section1 Using QWebPage in a Widget-less Environment
2145
2146     Before you begin painting a QWebPage object, you need to set the size of
2147     the viewport by calling setViewportSize(). Then, you invoke the main
2148     frame's render function (QWebFrame::render()). An example of this
2149     is shown in the code snippet below.
2150
2151     Suppose we have a \c Thumbnail class as follows:
2152
2153     \snippet webkitsnippets/webpage/main.cpp 0
2154
2155     The \c Thumbnail's constructor takes in a \a url. We connect our QWebPage
2156     object's \l{QWebPage::}{loadFinished()} signal to our private slot,
2157     \c render().
2158
2159     \snippet webkitsnippets/webpage/main.cpp 1
2160
2161     The \c render() function shows how we can paint a thumbnail using a
2162     QWebPage object.
2163
2164     \snippet webkitsnippets/webpage/main.cpp 2
2165
2166     We begin by setting the \l{QWebPage::viewportSize()}{viewportSize} and
2167     then we instantiate a QImage object, \c image, with the same size as our
2168     \l{QWebPage::viewportSize()}{viewportSize}. This image is then sent
2169     as a parameter to \c painter. Next, we render the contents of the main
2170     frame and its subframes into \c painter. Finally, we save the scaled image.
2171
2172     \sa QWebFrame
2173 */
2174
2175 /*!
2176     Constructs an empty QWebPage with parent \a parent.
2177 */
2178 QWebPage::QWebPage(QObject *parent)
2179     : QObject(parent)
2180     , d(new QWebPagePrivate(this))
2181 {
2182     setView(qobject_cast<QWidget*>(parent));
2183
2184     connect(this, SIGNAL(loadProgress(int)), this, SLOT(_q_onLoadProgressChanged(int)));
2185 #ifndef NDEBUG
2186     connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(_q_cleanupLeakMessages()));
2187 #endif
2188 }
2189
2190 /*!
2191     Destroys the web page.
2192 */
2193 QWebPage::~QWebPage()
2194 {
2195     d->createMainFrame();
2196     FrameLoader* loader = d->mainFrame.data()->d->frame->loader();
2197     if (loader)
2198         loader->detachFromParent();
2199     delete d;
2200 }
2201
2202 /*!
2203     Returns the main frame of the page.
2204
2205     The main frame provides access to the hierarchy of sub-frames and is also needed if you
2206     want to explicitly render a web page into a given painter.
2207
2208     \sa currentFrame()
2209 */
2210 QWebFrame *QWebPage::mainFrame() const
2211 {
2212     d->createMainFrame();
2213     return d->mainFrame.data();
2214 }
2215
2216 /*!
2217     Returns the frame currently active.
2218
2219     \sa mainFrame(), frameCreated()
2220 */
2221 QWebFrame *QWebPage::currentFrame() const
2222 {
2223     d->createMainFrame();
2224     WebCore::Frame *frame = d->page->focusController()->focusedOrMainFrame();
2225     return qobject_cast<QWebFrame*>(frame->loader()->networkingContext()->originatingObject());
2226 }
2227
2228
2229 /*!
2230     \since 4.6
2231
2232     Returns the frame at the given point \a pos, or 0 if there is no frame at
2233     that position.
2234
2235     \sa mainFrame(), currentFrame()
2236 */
2237 QWebFrame* QWebPage::frameAt(const QPoint& pos) const
2238 {
2239     QWebFrame* webFrame = mainFrame();
2240     if (!webFrame->geometry().contains(pos))
2241         return 0;
2242     QWebHitTestResult hitTestResult = webFrame->hitTestContent(pos);
2243     return hitTestResult.frame();
2244 }
2245
2246 /*!
2247     Returns a pointer to the view's history of navigated web pages.
2248 */
2249 QWebHistory *QWebPage::history() const
2250 {
2251     d->createMainFrame();
2252     return &d->history;
2253 }
2254
2255 /*!
2256     Sets the \a view that is associated with the web page.
2257
2258     \sa view()
2259 */
2260 void QWebPage::setView(QWidget* view)
2261 {
2262     if (this->view() == view)
2263         return;
2264
2265     d->view = view;
2266     setViewportSize(view ? view->size() : QSize(0, 0));
2267
2268     // If we have no client, we install a special client delegating
2269     // the responsibility to the QWidget. This is the code path
2270     // handling a.o. the "legacy" QWebView.
2271     //
2272     // If such a special delegate already exist, we substitute the view.
2273
2274     if (d->client) {
2275         if (d->client->isQWidgetClient())
2276             static_cast<PageClientQWidget*>(d->client.data())->view = view;
2277         return;
2278     }
2279
2280     if (view)
2281         d->client.reset(new PageClientQWidget(view, this));
2282 }
2283
2284 /*!
2285     Returns the view widget that is associated with the web page.
2286
2287     \sa setView()
2288 */
2289 QWidget *QWebPage::view() const
2290 {
2291     return d->view.data();
2292 }
2293
2294 /*!
2295     This function is called whenever a JavaScript program tries to print a \a message to the web browser's console.
2296
2297     For example in case of evaluation errors the source URL may be provided in \a sourceID as well as the \a lineNumber.
2298
2299     The default implementation prints nothing.
2300 */
2301 void QWebPage::javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID)
2302 {
2303     Q_UNUSED(sourceID)
2304
2305     // Catch plugin logDestroy message for LayoutTests/plugins/open-and-close-window-with-plugin.html
2306     // At this point DRT's WebPage has already been destroyed
2307     if (QWebPageAdapter::drtRun) {
2308         if (message == QLatin1String("PLUGIN: NPP_Destroy")) {
2309             fprintf(stdout, "CONSOLE MESSAGE: ");
2310             if (lineNumber)
2311                 fprintf(stdout, "line %d: ", lineNumber);
2312             fprintf(stdout, "%s\n", message.toUtf8().constData());
2313         }
2314     }
2315 }
2316
2317 /*!
2318     This function is called whenever a JavaScript program running inside \a frame calls the alert() function with
2319     the message \a msg.
2320
2321     The default implementation shows the message, \a msg, with QMessageBox::information.
2322 */
2323 void QWebPage::javaScriptAlert(QWebFrame *frame, const QString& msg)
2324 {
2325     Q_UNUSED(frame)
2326 #ifndef QT_NO_MESSAGEBOX
2327     QMessageBox box(view());
2328     box.setWindowTitle(tr("JavaScript Alert - %1").arg(mainFrame()->url().host()));
2329     box.setTextFormat(Qt::PlainText);
2330     box.setText(msg);
2331     box.setStandardButtons(QMessageBox::Ok);
2332     box.exec();
2333 #endif
2334 }
2335
2336 /*!
2337     This function is called whenever a JavaScript program running inside \a frame calls the confirm() function
2338     with the message, \a msg. Returns true if the user confirms the message; otherwise returns false.
2339
2340     The default implementation executes the query using QMessageBox::information with QMessageBox::Ok and QMessageBox::Cancel buttons.
2341 */
2342 bool QWebPage::javaScriptConfirm(QWebFrame *frame, const QString& msg)
2343 {
2344     Q_UNUSED(frame)
2345 #ifdef QT_NO_MESSAGEBOX
2346     return true;
2347 #else
2348     QMessageBox box(view());
2349     box.setWindowTitle(tr("JavaScript Confirm - %1").arg(mainFrame()->url().host()));
2350     box.setTextFormat(Qt::PlainText);
2351     box.setText(msg);
2352     box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
2353     return QMessageBox::Ok == box.exec();
2354 #endif
2355 }
2356
2357 /*!
2358     This function is called whenever a JavaScript program running inside \a frame tries to prompt the user for input.
2359     The program may provide an optional message, \a msg, as well as a default value for the input in \a defaultValue.
2360
2361     If the prompt was cancelled by the user the implementation should return false; otherwise the
2362     result should be written to \a result and true should be returned. If the prompt was not cancelled by the
2363     user, the implementation should return true and the result string must not be null.
2364
2365     The default implementation uses QInputDialog::getText().
2366 */
2367 bool QWebPage::javaScriptPrompt(QWebFrame *frame, const QString& msg, const QString& defaultValue, QString* result)
2368 {
2369     Q_UNUSED(frame)
2370     bool ok = false;
2371 #ifndef QT_NO_INPUTDIALOG
2372
2373     QInputDialog dlg(view());
2374     dlg.setWindowTitle(tr("JavaScript Prompt - %1").arg(mainFrame()->url().host()));
2375
2376     // Hack to force the dialog's QLabel into plain text mode
2377     // prevents https://bugs.webkit.org/show_bug.cgi?id=34429
2378     QLabel* label = dlg.findChild<QLabel*>();
2379     if (label)
2380         label->setTextFormat(Qt::PlainText);
2381
2382     // double the &'s because single & will underline the following character
2383     // (Accelerator mnemonics)
2384     QString escMsg(msg);
2385     escMsg.replace(QChar::fromLatin1('&'), QLatin1String("&&"));
2386     dlg.setLabelText(escMsg);
2387
2388     dlg.setTextEchoMode(QLineEdit::Normal);
2389     dlg.setTextValue(defaultValue);
2390
2391     ok = !!dlg.exec();
2392
2393     if (ok && result)
2394         *result = dlg.textValue();
2395 #endif
2396     return ok;
2397 }
2398
2399 /*!
2400     \fn bool QWebPage::shouldInterruptJavaScript()
2401     \since 4.6
2402     This function is called when a JavaScript program is running for a long period of time.
2403
2404     If the user wanted to stop the JavaScript the implementation should return true; otherwise false.
2405
2406     The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons.
2407
2408     \warning Because of binary compatibility constraints, this function is not virtual. If you want to
2409     provide your own implementation in a QWebPage subclass, reimplement the shouldInterruptJavaScript()
2410     slot in your subclass instead. QtWebKit will dynamically detect the slot and call it.
2411 */
2412 bool QWebPage::shouldInterruptJavaScript()
2413 {
2414 #ifdef QT_NO_MESSAGEBOX
2415     return false;
2416 #else
2417     return QMessageBox::Yes == QMessageBox::information(view(), tr("JavaScript Problem - %1").arg(mainFrame()->url().host()), tr("The script on this page appears to have a problem. Do you want to stop the script?"), QMessageBox::Yes, QMessageBox::No);
2418 #endif
2419 }
2420
2421 void QWebPage::setFeaturePermission(QWebFrame* frame, Feature feature, PermissionPolicy policy)
2422 {
2423     switch (feature) {
2424     case Notifications:
2425 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
2426         if (policy == PermissionGrantedByUser)
2427             NotificationPresenterClientQt::notificationPresenter()->allowNotificationForFrame(frame->d->frame);
2428 #endif
2429         break;
2430     case Geolocation:
2431 #if ENABLE(GEOLOCATION)
2432         if (policy != PermissionUnknown)
2433             GeolocationPermissionClientQt::geolocationPermissionClient()->setPermission(frame->d, (policy == PermissionGrantedByUser));
2434 #endif
2435         break;
2436
2437     default:
2438         break;
2439     }
2440 }
2441
2442 /*!
2443     This function is called whenever WebKit wants to create a new window of the given \a type, for
2444     example when a JavaScript program requests to open a document in a new window.
2445
2446     If the new window can be created, the new window's QWebPage is returned; otherwise a null pointer is returned.
2447
2448     If the view associated with the web page is a QWebView object, then the default implementation forwards
2449     the request to QWebView's createWindow() function; otherwise it returns a null pointer.
2450
2451     If \a type is WebModalDialog, the application must call setWindowModality(Qt::ApplicationModal) on the new window.
2452
2453     \note In the cases when the window creation is being triggered by JavaScript, apart from
2454     reimplementing this method application must also set the JavaScriptCanOpenWindows attribute
2455     of QWebSettings to true in order for it to get called.
2456
2457     \sa acceptNavigationRequest(), QWebView::createWindow()
2458 */
2459 QWebPage *QWebPage::createWindow(WebWindowType type)
2460 {
2461     QWebView *webView = qobject_cast<QWebView*>(view());
2462     if (webView) {
2463         QWebView *newView = webView->createWindow(type);
2464         if (newView)
2465             return newView->page();
2466     }
2467     return 0;
2468 }
2469
2470 /*!
2471     This function is called whenever WebKit encounters a HTML object element with type "application/x-qt-plugin". It is
2472     called regardless of the value of QWebSettings::PluginsEnabled. The \a classid, \a url, \a paramNames and \a paramValues
2473     correspond to the HTML object element attributes and child elements to configure the embeddable object.
2474 */
2475 QObject *QWebPage::createPlugin(const QString &classid, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues)
2476 {
2477     Q_UNUSED(classid)
2478     Q_UNUSED(url)
2479     Q_UNUSED(paramNames)
2480     Q_UNUSED(paramValues)
2481     return 0;
2482 }
2483
2484 static void extractContentTypeFromHash(const HashSet<String>& types, QStringList* list)
2485 {
2486     if (!list)
2487         return;
2488
2489     HashSet<String>::const_iterator endIt = types.end();
2490     for (HashSet<String>::const_iterator it = types.begin(); it != endIt; ++it)
2491         *list << *it;
2492 }
2493
2494 static void extractContentTypeFromPluginVector(const Vector<PluginPackage*>& plugins, QStringList* list)
2495 {
2496     if (!list)
2497         return;
2498
2499     for (unsigned int i = 0; i < plugins.size(); ++i) {
2500         MIMEToDescriptionsMap::const_iterator map_it = plugins[i]->mimeToDescriptions().begin();
2501         MIMEToDescriptionsMap::const_iterator map_end = plugins[i]->mimeToDescriptions().end();
2502         for (; map_it != map_end; ++map_it)
2503             *list << map_it->key;
2504     }
2505 }
2506
2507 /*!
2508  *  Returns the list of all content types supported by QWebPage.
2509  */
2510 QStringList QWebPage::supportedContentTypes() const
2511 {
2512     QStringList mimeTypes;
2513
2514     extractContentTypeFromHash(MIMETypeRegistry::getSupportedImageMIMETypes(), &mimeTypes);
2515     extractContentTypeFromHash(MIMETypeRegistry::getSupportedNonImageMIMETypes(), &mimeTypes);
2516     if (d->page->settings() && d->page->settings()->arePluginsEnabled())
2517         extractContentTypeFromPluginVector(PluginDatabase::installedPlugins()->plugins(), &mimeTypes);
2518
2519     return mimeTypes;
2520 }
2521
2522 /*!
2523  *  Returns true if QWebPage can handle the given \a mimeType; otherwise, returns false.
2524  */
2525 bool QWebPage::supportsContentType(const QString& mimeType) const
2526 {
2527     const String type = mimeType.toLower();
2528     if (MIMETypeRegistry::isSupportedImageMIMEType(type))
2529         return true;
2530
2531     if (MIMETypeRegistry::isSupportedNonImageMIMEType(type))
2532         return true;
2533
2534     if (d->page->settings() && d->page->settings()->arePluginsEnabled()
2535         && PluginDatabase::installedPlugins()->isMIMETypeRegistered(type))
2536         return true;
2537
2538     return false;
2539 }
2540
2541 static WebCore::FrameLoadRequest frameLoadRequest(const QUrl &url, WebCore::Frame *frame)
2542 {
2543     return WebCore::FrameLoadRequest(frame->document()->securityOrigin(),
2544         WebCore::ResourceRequest(url, frame->loader()->outgoingReferrer()));
2545 }
2546
2547 static void openNewWindow(const QUrl& url, WebCore::Frame* frame)
2548 {
2549     if (Page* oldPage = frame->page()) {
2550         WindowFeatures features;
2551         NavigationAction action;
2552         FrameLoadRequest request = frameLoadRequest(url, frame);
2553         if (Page* newPage = oldPage->chrome()->createWindow(frame, request, features, action)) {
2554             newPage->mainFrame()->loader()->loadFrameRequest(request, false, false, 0, 0, MaybeSendReferrer);
2555             newPage->chrome()->show();
2556         }
2557     }
2558 }
2559
2560 static void collectChildFrames(QWebFrame* frame, QList<QWebFrame*>& list)
2561 {
2562     list << frame->childFrames();
2563     QListIterator<QWebFrame*> it(frame->childFrames());
2564     while (it.hasNext()) {
2565         collectChildFrames(it.next(), list);
2566     }
2567 }
2568
2569 /*!
2570     This function can be called to trigger the specified \a action.
2571     It is also called by QtWebKit if the user triggers the action, for example
2572     through a context menu item.
2573
2574     If \a action is a checkable action then \a checked specified whether the action
2575     is toggled or not.
2576
2577     \sa action()
2578 */
2579 void QWebPage::triggerAction(WebAction action, bool)
2580 {
2581     WebCore::Frame *frame = d->page->focusController()->focusedOrMainFrame();
2582     if (!frame)
2583         return;
2584     WebCore::Editor *editor = frame->editor();
2585     const char *command = 0;
2586
2587     switch (action) {
2588         case OpenLink:
2589             if (QWebFrame *targetFrame = d->hitTestResult.linkTargetFrame()) {
2590                 WTF::RefPtr<WebCore::Frame> wcFrame = targetFrame->d->frame;
2591                 targetFrame->d->frame->loader()->loadFrameRequest(frameLoadRequest(d->hitTestResult.linkUrl(), wcFrame.get()),
2592                                                                   /*lockHistory*/ false, /*lockBackForwardList*/ false, /*event*/ 0,
2593                                                                   /*FormState*/ 0, MaybeSendReferrer);
2594                 break;
2595             }
2596             // fall through
2597         case OpenLinkInNewWindow:
2598             openNewWindow(d->hitTestResult.linkUrl(), frame);
2599             break;
2600         case OpenLinkInThisWindow:
2601             frame->loader()->loadFrameRequest(frameLoadRequest(d->hitTestResult.linkUrl(), frame),
2602                 /*lockHistory*/ false, /*lockBackForwardList*/ false, /*event*/ 0, /*FormState*/ 0, MaybeSendReferrer);
2603             break;
2604         case OpenFrameInNewWindow: {
2605             KURL url = frame->loader()->documentLoader()->unreachableURL();
2606             if (url.isEmpty())
2607                 url = frame->loader()->documentLoader()->url();
2608             openNewWindow(url, frame);
2609             break;
2610         }
2611         case CopyLinkToClipboard: {
2612 #if defined(Q_WS_X11)
2613             bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode();
2614             Pasteboard::generalPasteboard()->setSelectionMode(true);
2615             editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText());
2616             Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode);
2617 #endif
2618             editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText());
2619             break;
2620         }
2621         case OpenImageInNewWindow:
2622             openNewWindow(d->hitTestResult.imageUrl(), frame);
2623             break;
2624         case DownloadImageToDisk:
2625             frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.imageUrl(), frame->loader()->outgoingReferrer()));
2626             break;
2627         case DownloadLinkToDisk:
2628             frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.linkUrl(), frame->loader()->outgoingReferrer()));
2629             break;
2630 #ifndef QT_NO_CLIPBOARD
2631         case CopyImageToClipboard:
2632             QApplication::clipboard()->setPixmap(d->hitTestResult.pixmap());
2633             break;
2634         case CopyImageUrlToClipboard:
2635             QApplication::clipboard()->setText(d->hitTestResult.imageUrl().toString());
2636             break;
2637 #endif
2638         case Back:
2639             d->page->goBack();
2640             break;
2641         case Forward:
2642             d->page->goForward();
2643             break;
2644         case Stop:
2645             mainFrame()->d->frame->loader()->stopForUserCancel();
2646             d->updateNavigationActions();
2647             break;
2648         case Reload:
2649             mainFrame()->d->frame->loader()->reload(/*endtoendreload*/false);
2650             break;
2651         case ReloadAndBypassCache:
2652             mainFrame()->d->frame->loader()->reload(/*endtoendreload*/true);
2653             break;
2654         case SetTextDirectionDefault:
2655             editor->setBaseWritingDirection(NaturalWritingDirection);
2656             break;
2657         case SetTextDirectionLeftToRight:
2658             editor->setBaseWritingDirection(LeftToRightWritingDirection);
2659             break;
2660         case SetTextDirectionRightToLeft:
2661             editor->setBaseWritingDirection(RightToLeftWritingDirection);
2662             break;
2663         case InspectElement: {
2664 #if ENABLE(INSPECTOR)
2665             if (!d->hitTestResult.isNull()) {
2666                 d->getOrCreateInspector(); // Make sure the inspector is created
2667                 d->inspector->show(); // The inspector is expected to be shown on inspection
2668                 d->page->inspectorController()->inspect(d->hitTestResult.d->innerNonSharedNode.get());
2669             }
2670 #endif
2671             break;
2672         }
2673         case StopScheduledPageRefresh: {
2674             QWebFrame* topFrame = mainFrame();
2675             topFrame->d->frame->navigationScheduler()->cancel();
2676             QList<QWebFrame*> childFrames;
2677             collectChildFrames(topFrame, childFrames);
2678             QListIterator<QWebFrame*> it(childFrames);
2679             while (it.hasNext())
2680                 it.next()->d->frame->navigationScheduler()->cancel();
2681             break;
2682         }
2683         default:
2684             command = QWebPagePrivate::editorCommandForWebActions(action);
2685             break;
2686     }
2687
2688     if (command)
2689         editor->command(command).execute();
2690 }
2691
2692
2693 QColor QWebPagePrivate::colorSelectionRequested(const QColor &selectedColor)
2694 {
2695     QColor ret = selectedColor;
2696 #ifndef QT_NO_COLORDIALOG
2697     ret = QColorDialog::getColor(selectedColor, q->view());
2698     if (!ret.isValid())
2699         ret = selectedColor;
2700 #endif
2701     return ret;
2702 }
2703
2704 QWebSelectMethod *QWebPagePrivate::createSelectPopup()
2705 {
2706     return new QtFallbackWebPopup(this);
2707 }
2708
2709 QRect QWebPagePrivate::viewRectRelativeToWindow()
2710 {
2711
2712     QWidget* ownerWidget= client.isNull() ? 0 : qobject_cast<QWidget*>(client->ownerWidget());
2713     if (!ownerWidget)
2714         return QRect();
2715     QWidget* topLevelWidget = ownerWidget->window();
2716
2717     QPoint topLeftCorner = ownerWidget->mapFrom(topLevelWidget, QPoint(0, 0));
2718     return QRect(topLeftCorner, ownerWidget->size());
2719 }
2720
2721 void QWebPagePrivate::geolocationPermissionRequested(QWebFrameAdapter* frame)
2722 {
2723     emit q->featurePermissionRequested(QWebFramePrivate::kit(frame), QWebPage::Geolocation);
2724 }
2725
2726 void QWebPagePrivate::geolocationPermissionRequestCancelled(QWebFrameAdapter* frame)
2727 {
2728     emit q->featurePermissionRequestCanceled(QWebFramePrivate::kit(frame), QWebPage::Geolocation);
2729 }
2730
2731 void QWebPagePrivate::notificationsPermissionRequested(QWebFrameAdapter* frame)
2732 {
2733     emit q->featurePermissionRequested(QWebFramePrivate::kit(frame), QWebPage::Notifications);
2734 }
2735
2736 void QWebPagePrivate::notificationsPermissionRequestCancelled(QWebFrameAdapter* frame)
2737 {
2738     emit q->featurePermissionRequestCanceled(QWebFramePrivate::kit(frame), QWebPage::Notifications);
2739 }
2740
2741 void QWebPagePrivate::respondToChangedContents()
2742 {
2743     updateEditorActions();
2744
2745     emit q->contentsChanged();
2746 }
2747
2748 void QWebPagePrivate::respondToChangedSelection()
2749 {
2750     updateEditorActions();
2751     emit q->selectionChanged();
2752 }
2753
2754 void QWebPagePrivate::microFocusChanged()
2755 {
2756     emit q->microFocusChanged();
2757 }
2758
2759 void QWebPagePrivate::triggerCopyAction()
2760 {
2761     q->triggerAction(QWebPage::Copy);
2762 }
2763
2764 void QWebPagePrivate::triggerActionForKeyEvent(QKeyEvent* event)
2765 {
2766     QWebPage::WebAction action = editorActionForKeyEvent(event);
2767     q->triggerAction(action);
2768 }
2769
2770 void QWebPagePrivate::clearUndoStack()
2771 {
2772 #ifndef QT_NO_UNDOSTACK
2773     if (undoStack)
2774         undoStack->clear();
2775 #endif
2776 }
2777
2778 bool QWebPagePrivate::canUndo() const
2779 {
2780 #ifndef QT_NO_UNDOSTACK
2781     if (!undoStack)
2782         return false;
2783     return undoStack->canUndo();
2784 #else
2785     return false;
2786 #endif
2787 }
2788
2789 bool QWebPagePrivate::canRedo() const
2790 {
2791 #ifndef QT_NO_UNDOSTACK
2792     if (!undoStack)
2793         return false;
2794     return undoStack->canRedo();
2795 #else
2796     return false;
2797 #endif
2798 }
2799
2800 void QWebPagePrivate::undo()
2801 {
2802 #ifndef QT_NO_UNDOSTACK
2803     if (undoStack)
2804         undoStack->undo();
2805 #endif
2806 }
2807
2808 void QWebPagePrivate::redo()
2809 {
2810 #ifndef QT_NO_UNDOSTACK
2811     if (undoStack)
2812         undoStack->redo();
2813 #endif
2814 }
2815
2816 void QWebPagePrivate::createUndoStep(QSharedPointer<UndoStepQt> step)
2817 {
2818 #ifndef QT_NO_UNDOSTACK
2819     // Call undoStack() getter first to ensure stack is created
2820     // if it doesn't exist yet.
2821     q->undoStack()->push(new QWebUndoCommand(step));
2822 #endif
2823 }
2824
2825 const char *QWebPagePrivate::editorCommandForKeyEvent(QKeyEvent* event)
2826 {
2827     QWebPage::WebAction action = editorActionForKeyEvent(event);
2828     return editorCommandForWebActions(action);
2829 }
2830
2831 QSize QWebPage::viewportSize() const
2832 {
2833     if (d->mainFrame && d->mainFrame.data()->d->frame->view())
2834         return d->mainFrame.data()->d->frame->view()->frameRect().size();
2835
2836     return d->m_viewportSize;
2837 }
2838
2839 /*!
2840     \property QWebPage::viewportSize
2841     \brief the size of the viewport
2842
2843     The size affects for example the visibility of scrollbars
2844     if the document is larger than the viewport.
2845
2846     By default, for a newly-created Web page, this property contains a size with
2847     zero width and height.
2848
2849     \sa QWebFrame::render(), preferredContentsSize
2850 */
2851 void QWebPage::setViewportSize(const QSize &size) const
2852 {
2853     d->m_viewportSize = size;
2854
2855     QWebFrame *frame = mainFrame();
2856     if (frame->d->frame && frame->d->frame->view()) {
2857         WebCore::FrameView* view = frame->d->frame->view();
2858         view->resize(size);
2859         view->adjustViewSize();
2860     }
2861 }
2862
2863 static int getintenv(const char* variable)
2864 {
2865     bool ok;
2866     int value = qgetenv(variable).toInt(&ok);
2867     return (ok) ? value : -1;
2868 }
2869
2870 static QSize queryDeviceSizeForScreenContainingWidget(const QWidget* widget)
2871 {
2872     QDesktopWidget* desktop = QApplication::desktop();
2873     if (!desktop)
2874         return QSize();
2875
2876     QSize size;
2877
2878     if (widget) {
2879         // Returns the available geometry of the screen which contains widget.
2880         // NOTE: this must be the the full screen size including any fixed status areas etc.
2881         size = desktop->availableGeometry(widget).size();
2882     } else
2883         size = desktop->availableGeometry().size();
2884
2885     // This must be in portrait mode, adjust if not.
2886     if (size.width() > size.height()) {
2887         int width = size.width();
2888         size.setWidth(size.height());
2889         size.setHeight(width);
2890     }
2891
2892     return size;
2893 }
2894
2895 /*!
2896     Computes the optimal viewport configuration given the \a availableSize, when
2897     user interface components are disregarded.
2898
2899     The configuration is also dependent on the device screen size which is obtained
2900     automatically. For testing purposes the size can be overridden by setting two
2901     environment variables QTWEBKIT_DEVICE_WIDTH and QTWEBKIT_DEVICE_HEIGHT, which
2902     both needs to be set.
2903
2904     The ViewportAttributes includes a pixel density ratio, which will also be exposed to
2905     the web author though the -webkit-pixel-ratio media feature. This is the ratio
2906     between 1 density-independent pixel (DPI) and physical pixels.
2907
2908     A density-independent pixel is equivalent to one physical pixel on a 160 DPI screen,
2909     so on our platform assumes that as the baseline density.
2910
2911     The conversion of DIP units to screen pixels is quite simple:
2912
2913     pixels = DIPs * (density / 160).
2914
2915     Thus, on a 240 DPI screen, 1 DIPs would equal 1.5 physical pixels.
2916
2917     An invalid instance will be returned in the case an empty size is passed to the
2918     method.
2919
2920     \note The density is automatically obtained from the DPI of the screen where the page
2921     is being shown, but as many X11 servers are reporting wrong DPI, it is possible to
2922     override it using QX11Info::setAppDpiY().
2923 */
2924
2925 QWebPage::ViewportAttributes QWebPage::viewportAttributesForSize(const QSize& availableSize) const
2926 {
2927     static int desktopWidth = 980;
2928
2929     ViewportAttributes result;
2930
2931      if (availableSize.isEmpty())
2932          return result; // Returns an invalid instance.
2933
2934     int deviceWidth = getintenv("QTWEBKIT_DEVICE_WIDTH");
2935     int deviceHeight = getintenv("QTWEBKIT_DEVICE_HEIGHT");
2936
2937     // Both environment variables need to be set - or they will be ignored.
2938     if (deviceWidth < 0 && deviceHeight < 0) {
2939         QSize size = queryDeviceSizeForScreenContainingWidget(view());
2940         deviceWidth = size.width();
2941         deviceHeight = size.height();
2942     }
2943
2944     float devicePixelRatio = qt_defaultDpi() / WebCore::ViewportArguments::deprecatedTargetDPI;
2945
2946     WebCore::ViewportAttributes conf = WebCore::computeViewportAttributes(d->viewportArguments(), desktopWidth, deviceWidth, deviceHeight, devicePixelRatio, availableSize);
2947     WebCore::restrictMinimumScaleFactorToViewportSize(conf, availableSize, devicePixelRatio);
2948     WebCore::restrictScaleFactorToInitialScaleIfNotUserScalable(conf);
2949
2950     result.m_isValid = true;
2951     result.m_size = QSizeF(conf.layoutSize.width(), conf.layoutSize.height());
2952     result.m_initialScaleFactor = conf.initialScale;
2953     result.m_minimumScaleFactor = conf.minimumScale;
2954     result.m_maximumScaleFactor = conf.maximumScale;
2955     result.m_devicePixelRatio = devicePixelRatio;
2956     result.m_isUserScalable = static_cast<bool>(conf.userScalable);
2957
2958     d->page->setDeviceScaleFactor(devicePixelRatio);
2959
2960     return result;
2961 }
2962
2963 QSize QWebPage::preferredContentsSize() const
2964 {
2965     QWebFrame* frame = d->mainFrame.data();
2966     if (frame) {
2967         WebCore::FrameView* view = frame->d->frame->view();
2968         if (view && view->useFixedLayout())
2969             return d->mainFrame.data()->d->frame->view()->fixedLayoutSize();
2970     }
2971
2972     return d->fixedLayoutSize;
2973 }
2974
2975 /*!
2976     \property QWebPage::preferredContentsSize
2977     \since 4.6
2978     \brief a custom size used for laying out the page contents.
2979
2980     By default all pages are laid out using the viewport of the page as the base.
2981
2982     As pages mostly are designed for desktop usage, they often do not layout properly
2983     on small devices as the contents require a certain view width. For this reason
2984     it is common to use a different layout size and then scale the contents to fit
2985     within the actual view.
2986
2987     If this property is set to a valid size, this size is used for all layout needs
2988     instead of the size of the viewport.
2989
2990     Setting an invalid size, makes the page fall back to using the viewport size for layout.
2991
2992     \sa viewportSize
2993 */
2994 void QWebPage::setPreferredContentsSize(const QSize& size) const
2995 {
2996     // FIXME: Rename this method to setCustomLayoutSize
2997
2998     d->fixedLayoutSize = size;
2999
3000     QWebFrame* frame = mainFrame();
3001     if (!frame->d->frame || !frame->d->frame->view())
3002         return;
3003
3004     WebCore::FrameView* view = frame->d->frame->view();
3005
3006     if (size.isValid()) {
3007         view->setUseFixedLayout(true);
3008         view->setFixedLayoutSize(size);
3009     } else if (view->useFixedLayout())
3010         view->setUseFixedLayout(false);
3011
3012     view->layout();
3013 }
3014
3015 /*
3016     This function is to be called after any (animated) scroll/pan has ended, in the case the application handles the
3017     scrolling/panning of the web contents. This is commonly used in combination with tiling where is it common for
3018     the application to pan the actual view, which then resizes itself to the size of the contents.
3019
3020     \note Calling this function makes WebKit stop trying to calculate the visibleContentRect. To turn that on
3021     again, call this method with an empty rect.
3022
3023     \sa QGraphicsWebView::resizesToContents, QWebSettings::TiledBackingStoreEnabled
3024 */
3025 void QWebPage::setActualVisibleContentRect(const QRect& rect) const
3026 {
3027     QWebFrame* frame = mainFrame();
3028     if (!frame->d->frame || !frame->d->frame->view())
3029         return;
3030
3031     WebCore::FrameView* view = frame->d->frame->view();
3032     view->setFixedVisibleContentRect(rect);
3033 }
3034
3035 /*!
3036     \fn bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
3037
3038     This function is called whenever WebKit requests to navigate \a frame to the resource specified by \a request by means of
3039     the specified navigation type \a type.
3040
3041     If \a frame is a null pointer then navigation to a new window is requested. If the request is
3042     accepted createWindow() will be called.
3043
3044     The default implementation interprets the page's linkDelegationPolicy and emits linkClicked accordingly or returns true
3045     to let QWebPage handle the navigation itself.
3046
3047     \sa createWindow()
3048 */
3049 bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
3050 {
3051     Q_UNUSED(frame)
3052     if (type == NavigationTypeLinkClicked) {
3053         switch (d->linkPolicy) {
3054             case DontDelegateLinks:
3055                 return true;
3056
3057             case DelegateExternalLinks:
3058                 if (WebCore::SchemeRegistry::shouldTreatURLSchemeAsLocal(request.url().scheme()))
3059                     return true;
3060                 emit linkClicked(request.url());
3061                 return false;
3062
3063             case DelegateAllLinks:
3064                 emit linkClicked(request.url());
3065                 return false;
3066         }
3067     }
3068     return true;
3069 }
3070
3071 /*!
3072     \property QWebPage::hasSelection
3073     \brief whether this page contains selected content or not.
3074
3075     \sa selectionChanged()
3076 */
3077 bool QWebPage::hasSelection() const
3078 {
3079     d->createMainFrame();
3080     WebCore::Frame* frame = d->page->focusController()->focusedOrMainFrame();
3081     if (frame)
3082         return (frame->selection()->selection().selectionType() != VisibleSelection::NoSelection);
3083     return false;
3084 }
3085
3086 /*!
3087     \property QWebPage::selectedText
3088     \brief the text currently selected
3089
3090     By default, this property contains an empty string.
3091
3092     \sa selectionChanged(), selectedHtml()
3093 */
3094 QString QWebPage::selectedText() const
3095 {
3096     d->createMainFrame();
3097     WebCore::Frame* frame = d->page->focusController()->focusedOrMainFrame();
3098     if (frame->selection()->selection().selectionType() == VisibleSelection::NoSelection)
3099         return QString();
3100     return frame->editor()->selectedText();
3101 }
3102
3103 /*!
3104     \since 4.8
3105     \property QWebPage::selectedHtml
3106     \brief the HTML currently selected
3107
3108     By default, this property contains an empty string.
3109
3110     \sa selectionChanged(), selectedText()
3111 */
3112 QString QWebPage::selectedHtml() const
3113 {
3114     d->createMainFrame();
3115     return d->page->focusController()->focusedOrMainFrame()->editor()->selectedRange()->toHTML();
3116 }
3117
3118 #ifndef QT_NO_ACTION
3119 /*!
3120    Returns a QAction for the specified WebAction \a action.
3121
3122    The action is owned by the QWebPage but you can customize the look by
3123    changing its properties.
3124
3125    QWebPage also takes care of implementing the action, so that upon
3126    triggering the corresponding action is performed on the page.
3127
3128    \sa triggerAction()
3129 */
3130 QAction *QWebPage::action(WebAction action) const
3131 {
3132     if (action == QWebPage::NoWebAction) return 0;
3133     if (d->actions[action])
3134         return d->actions[action];
3135
3136     QString text;
3137     QIcon icon;
3138     QStyle *style = d->client ? d->client->style() : qApp->style();
3139     bool checkable = false;
3140
3141     switch (action) {
3142         case OpenLink:
3143             text = contextMenuItemTagOpenLink();
3144             break;
3145         case OpenLinkInNewWindow:
3146             text = contextMenuItemTagOpenLinkInNewWindow();
3147             break;
3148         case OpenFrameInNewWindow:
3149             text = contextMenuItemTagOpenFrameInNewWindow();
3150             break;
3151         case OpenLinkInThisWindow:
3152             text = contextMenuItemTagOpenLinkInThisWindow();
3153             break;
3154
3155         case DownloadLinkToDisk:
3156             text = contextMenuItemTagDownloadLinkToDisk();
3157             break;
3158         case CopyLinkToClipboard:
3159             text = contextMenuItemTagCopyLinkToClipboard();
3160             break;
3161
3162         case OpenImageInNewWindow:
3163             text = contextMenuItemTagOpenImageInNewWindow();
3164             break;
3165         case DownloadImageToDisk:
3166             text = contextMenuItemTagDownloadImageToDisk();
3167             break;
3168         case CopyImageToClipboard:
3169             text = contextMenuItemTagCopyImageToClipboard();
3170             break;
3171         case CopyImageUrlToClipboard:
3172             text = contextMenuItemTagCopyImageUrlToClipboard();
3173             break;
3174
3175         case Back:
3176             text = contextMenuItemTagGoBack();
3177             icon = style->standardIcon(QStyle::SP_ArrowBack);
3178             break;
3179         case Forward:
3180             text = contextMenuItemTagGoForward();
3181             icon = style->standardIcon(QStyle::SP_ArrowForward);
3182             break;
3183         case Stop:
3184             text = contextMenuItemTagStop();
3185             icon = style->standardIcon(QStyle::SP_BrowserStop);
3186             break;
3187         case Reload:
3188             text = contextMenuItemTagReload();
3189             icon = style->standardIcon(QStyle::SP_BrowserReload);
3190             break;
3191
3192         case Cut:
3193             text = contextMenuItemTagCut();
3194             break;
3195         case Copy:
3196             text = contextMenuItemTagCopy();
3197             break;
3198         case Paste:
3199             text = contextMenuItemTagPaste();
3200             break;
3201         case SelectAll:
3202             text = contextMenuItemTagSelectAll();
3203             break;
3204 #ifndef QT_NO_UNDOSTACK
3205         case Undo: {
3206             QAction *a = undoStack()->createUndoAction(d->q);
3207             d->actions[action] = a;
3208             return a;
3209         }
3210         case Redo: {
3211             QAction *a = undoStack()->createRedoAction(d->q);
3212             d->actions[action] = a;
3213             return a;
3214         }
3215 #endif // QT_NO_UNDOSTACK
3216         case MoveToNextChar:
3217             text = tr("Move the cursor to the next character");
3218             break;
3219         case MoveToPreviousChar:
3220             text = tr("Move the cursor to the previous character");
3221             break;
3222         case MoveToNextWord:
3223             text = tr("Move the cursor to the next word");
3224             break;
3225         case MoveToPreviousWord:
3226             text = tr("Move the cursor to the previous word");
3227             break;
3228         case MoveToNextLine:
3229             text = tr("Move the cursor to the next line");
3230             break;
3231         case MoveToPreviousLine:
3232             text = tr("Move the cursor to the previous line");
3233             break;
3234         case MoveToStartOfLine:
3235             text = tr("Move the cursor to the start of the line");
3236             break;
3237         case MoveToEndOfLine:
3238             text = tr("Move the cursor to the end of the line");
3239             break;
3240         case MoveToStartOfBlock:
3241             text = tr("Move the cursor to the start of the block");
3242             break;
3243         case MoveToEndOfBlock:
3244             text = tr("Move the cursor to the end of the block");
3245             break;
3246         case MoveToStartOfDocument:
3247             text = tr("Move the cursor to the start of the document");
3248             break;
3249         case MoveToEndOfDocument:
3250             text = tr("Move the cursor to the end of the document");
3251             break;
3252         case SelectNextChar:
3253             text = tr("Select to the next character");
3254             break;
3255         case SelectPreviousChar:
3256             text = tr("Select to the previous character");
3257             break;
3258         case SelectNextWord:
3259             text = tr("Select to the next word");
3260             break;
3261         case SelectPreviousWord:
3262             text = tr("Select to the previous word");
3263             break;
3264         case SelectNextLine:
3265             text = tr("Select to the next line");
3266             break;
3267         case SelectPreviousLine:
3268             text = tr("Select to the previous line");
3269             break;
3270         case SelectStartOfLine:
3271             text = tr("Select to the start of the line");
3272             break;
3273         case SelectEndOfLine:
3274             text = tr("Select to the end of the line");
3275             break;
3276         case SelectStartOfBlock:
3277             text = tr("Select to the start of the block");
3278             break;
3279         case SelectEndOfBlock:
3280             text = tr("Select to the end of the block");
3281             break;
3282         case SelectStartOfDocument:
3283             text = tr("Select to the start of the document");
3284             break;
3285         case SelectEndOfDocument:
3286             text = tr("Select to the end of the document");
3287             break;
3288         case DeleteStartOfWord:
3289             text = tr("Delete to the start of the word");
3290             break;
3291         case DeleteEndOfWord:
3292             text = tr("Delete to the end of the word");
3293             break;
3294
3295         case SetTextDirectionDefault:
3296             text = contextMenuItemTagDefaultDirection();
3297             break;
3298         case SetTextDirectionLeftToRight:
3299             text = contextMenuItemTagLeftToRight();
3300             checkable = true;
3301             break;
3302         case SetTextDirectionRightToLeft:
3303             text = contextMenuItemTagRightToLeft();
3304             checkable = true;
3305             break;
3306
3307         case ToggleBold:
3308             text = contextMenuItemTagBold();
3309             checkable = true;
3310             break;
3311         case ToggleItalic:
3312             text = contextMenuItemTagItalic();
3313             checkable = true;
3314             break;
3315         case ToggleUnderline:
3316             text = contextMenuItemTagUnderline();
3317             checkable = true;
3318             break;
3319
3320         case InspectElement:
3321             text = contextMenuItemTagInspectElement();
3322             break;
3323
3324         case InsertParagraphSeparator:
3325             text = tr("Insert a new paragraph");
3326             break;
3327         case InsertLineSeparator:
3328             text = tr("Insert a new line");
3329             break;
3330
3331         case PasteAndMatchStyle:
3332             text = tr("Paste and Match Style");
3333             break;
3334         case RemoveFormat:
3335             text = tr("Remove formatting");
3336             break;
3337
3338         case ToggleStrikethrough:
3339             text = tr("Strikethrough");
3340             checkable = true;
3341             break;
3342         case ToggleSubscript:
3343             text = tr("Subscript");
3344             checkable = true;
3345             break;
3346         case ToggleSuperscript:
3347             text = tr("Superscript");
3348             checkable = true;
3349             break;
3350         case InsertUnorderedList:
3351             text = tr("Insert Bulleted List");
3352             checkable = true;
3353             break;
3354         case InsertOrderedList:
3355             text = tr("Insert Numbered List");
3356             checkable = true;
3357             break;
3358         case Indent:
3359             text = tr("Indent");
3360             break;
3361         case Outdent:
3362             text = tr("Outdent");
3363             break;
3364         case AlignCenter:
3365             text = tr("Center");
3366             break;
3367         case AlignJustified:
3368             text = tr("Justify");
3369             break;
3370         case AlignLeft:
3371             text = tr("Align Left");
3372             break;
3373         case AlignRight:
3374             text = tr("Align Right");
3375             break;
3376         case NoWebAction:
3377             return 0;
3378         default:
3379             break;
3380     }
3381
3382     if (text.isEmpty())
3383         return 0;
3384
3385     QAction *a = new QAction(d->q);
3386     a->setText(text);
3387     a->setData(action);
3388     a->setCheckable(checkable);
3389     a->setIcon(icon);
3390
3391     connect(a, SIGNAL(triggered(bool)),
3392             this, SLOT(_q_webActionTriggered(bool)));
3393
3394     d->actions[action] = a;
3395     d->updateAction(action);
3396     return a;
3397 }
3398 #endif // QT_NO_ACTION
3399
3400 /*!
3401     \property QWebPage::modified
3402     \brief whether the page contains unsubmitted form data, or the contents have been changed.
3403
3404     By default, this property is false.
3405
3406     \sa contentsChanged(), contentEditable, undoStack()
3407 */
3408 bool QWebPage::isModified() const
3409 {
3410 #ifdef QT_NO_UNDOSTACK
3411     return false;
3412 #else
3413     if (!d->undoStack)
3414         return false;
3415     return d->undoStack->canUndo();
3416 #endif // QT_NO_UNDOSTACK
3417 }
3418
3419 #ifndef QT_NO_UNDOSTACK
3420 /*!
3421     Returns a pointer to the undo stack used for editable content.
3422
3423     \sa modified
3424 */
3425 QUndoStack *QWebPage::undoStack() const
3426 {
3427     if (!d->undoStack)
3428         d->undoStack = new QUndoStack(const_cast<QWebPage *>(this));
3429
3430     return d->undoStack;
3431 }
3432 #endif // QT_NO_UNDOSTACK
3433
3434 /*! \reimp
3435 */
3436 bool QWebPage::event(QEvent *ev)
3437 {
3438     switch (ev->type()) {
3439     case QEvent::Timer:
3440         d->timerEvent(static_cast<QTimerEvent*>(ev));
3441         break;
3442     case QEvent::MouseMove:
3443         d->mouseMoveEvent(static_cast<QMouseEvent*>(ev));
3444         break;
3445     case QEvent::MouseButtonPress:
3446         d->mousePressEvent(static_cast<QMouseEvent*>(ev));
3447         break;
3448     case QEvent::MouseButtonDblClick:
3449         d->mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev));
3450         break;
3451     case QEvent::MouseButtonRelease:
3452         d->mouseReleaseEvent(static_cast<QMouseEvent*>(ev));
3453         break;
3454 #if !defined(QT_NO_GRAPHICSVIEW)
3455     case QEvent::GraphicsSceneMouseMove: {
3456         QGraphicsSceneMouseEvent *gsEv = static_cast<QGraphicsSceneMouseEvent*>(ev);
3457         QMouseEvent dummyEvent(QEvent::MouseMove, gsEv->pos(), gsEv->screenPos(), gsEv->button(), gsEv->buttons(), gsEv->modifiers());
3458         d->mouseMoveEvent(&dummyEvent);
3459         ev->setAccepted(dummyEvent.isAccepted());
3460         break;
3461     }
3462     case QEvent::GraphicsSceneMouseRelease: {
3463         QGraphicsSceneMouseEvent *gsEv = static_cast<QGraphicsSceneMouseEvent*>(ev);
3464         QMouseEvent dummyEvent(QEvent::MouseButtonRelease, gsEv->pos(), gsEv->screenPos(), gsEv->button(), gsEv->buttons(), gsEv->modifiers());
3465         d->mouseReleaseEvent(&dummyEvent);
3466         ev->setAccepted(dummyEvent.isAccepted());
3467         break;
3468     }
3469     case QEvent::GraphicsSceneMousePress: {
3470         QGraphicsSceneMouseEvent *gsEv = static_cast<QGraphicsSceneMouseEvent*>(ev);
3471         QMouseEvent dummyEvent(QEvent::MouseButtonPress, gsEv->pos(), gsEv->screenPos(), gsEv->button(), gsEv->buttons(), gsEv->modifiers());
3472         d->mousePressEvent(&dummyEvent);
3473         ev->setAccepted(dummyEvent.isAccepted());
3474         break;
3475     }
3476     case QEvent::GraphicsSceneMouseDoubleClick: {
3477         QGraphicsSceneMouseEvent *gsEv = static_cast<QGraphicsSceneMouseEvent*>(ev);
3478         QMouseEvent dummyEvent(QEvent::MouseButtonDblClick, gsEv->pos(), gsEv->screenPos(), gsEv->button(), gsEv->buttons(), gsEv->modifiers());
3479         d->mouseDoubleClickEvent(&dummyEvent);
3480         ev->setAccepted(dummyEvent.isAccepted());
3481         break;
3482     }
3483 #endif
3484 #ifndef QT_NO_CONTEXTMENU
3485     case QEvent::ContextMenu:
3486         d->contextMenuEvent(static_cast<QContextMenuEvent*>(ev)->globalPos());
3487         break;
3488 #if !defined(QT_NO_GRAPHICSVIEW)
3489     case QEvent::GraphicsSceneContextMenu:
3490         d->contextMenuEvent(static_cast<QGraphicsSceneContextMenuEvent*>(ev)->screenPos());
3491         break;
3492 #endif
3493 #endif
3494 #ifndef QT_NO_WHEELEVENT
3495     case QEvent::Wheel:
3496         d->wheelEvent(static_cast<QWheelEvent*>(ev));
3497         break;
3498 #if !defined(QT_NO_GRAPHICSVIEW)
3499     case QEvent::GraphicsSceneWheel: {
3500         QGraphicsSceneWheelEvent *gsEv = static_cast<QGraphicsSceneWheelEvent*>(ev);
3501         QWheelEvent dummyEvent(gsEv->pos(), gsEv->screenPos(), gsEv->delta(), gsEv->buttons(), gsEv->modifiers(), gsEv->orientation());
3502         d->wheelEvent(&dummyEvent);
3503         ev->setAccepted(dummyEvent.isAccepted());
3504         break;
3505     }
3506 #endif
3507 #endif
3508     case QEvent::KeyPress:
3509         d->keyPressEvent(static_cast<QKeyEvent*>(ev));
3510         break;
3511     case QEvent::KeyRelease:
3512         d->keyReleaseEvent(static_cast<QKeyEvent*>(ev));
3513         break;
3514     case QEvent::FocusIn:
3515         d->focusInEvent(static_cast<QFocusEvent*>(ev));
3516         break;
3517     case QEvent::FocusOut:
3518         d->focusOutEvent(static_cast<QFocusEvent*>(ev));
3519         break;
3520 #ifndef QT_NO_DRAGANDDROP
3521     case QEvent::DragEnter:
3522         d->dragEnterEvent(static_cast<QDragEnterEvent*>(ev));
3523         break;
3524     case QEvent::DragLeave:
3525         d->dragLeaveEvent(static_cast<QDragLeaveEvent*>(ev));
3526         break;
3527     case QEvent::DragMove:
3528         d->dragMoveEvent(static_cast<QDragMoveEvent*>(ev));
3529         break;
3530     case QEvent::Drop:
3531         d->dropEvent(static_cast<QDropEvent*>(ev));
3532         break;
3533 #if !defined(QT_NO_GRAPHICSVIEW)
3534     case QEvent::GraphicsSceneDragEnter:
3535         d->dragEnterEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
3536         break;
3537     case QEvent::GraphicsSceneDragMove:
3538         d->dragMoveEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
3539         break;</