QWebPageAdapter.cpp 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408
  1. /*
  2. * Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Library General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Library General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Library General Public License
  15. * along with this library; see the file COPYING.LIB. If not, write to
  16. * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  17. * Boston, MA 02110-1301, USA.
  18. *
  19. */
  20. #include "config.h"
  21. #include "QWebPageAdapter.h"
  22. #include "CSSComputedStyleDeclaration.h"
  23. #include "CSSParser.h"
  24. #include "Chrome.h"
  25. #include "ChromeClientQt.h"
  26. #include "ClientRect.h"
  27. #include "ContextMenu.h"
  28. #include "ContextMenuClientQt.h"
  29. #include "ContextMenuController.h"
  30. #if ENABLE(DEVICE_ORIENTATION)
  31. #include "DeviceMotionClientMock.h"
  32. #include "DeviceMotionController.h"
  33. #include "DeviceOrientationClientMock.h"
  34. #include "DeviceOrientationController.h"
  35. #if HAVE(QTSENSORS)
  36. #include "DeviceMotionClientQt.h"
  37. #include "DeviceOrientationClientQt.h"
  38. #endif
  39. #endif
  40. #include "DocumentLoader.h"
  41. #include "DragClientQt.h"
  42. #include "DragController.h"
  43. #include "DragData.h"
  44. #include "DragSession.h"
  45. #include "Editor.h"
  46. #include "EditorClientQt.h"
  47. #include "EventHandler.h"
  48. #include "FocusController.h"
  49. #include "FrameLoadRequest.h"
  50. #include "FrameSelection.h"
  51. #include "FrameView.h"
  52. #if ENABLE(GEOLOCATION)
  53. #include "GeolocationClientMock.h"
  54. #include "GeolocationController.h"
  55. #if HAVE(QTLOCATION)
  56. #include "GeolocationClientQt.h"
  57. #endif
  58. #endif
  59. #include "GeolocationPermissionClientQt.h"
  60. #include "HTMLFrameOwnerElement.h"
  61. #include "HTMLInputElement.h"
  62. #include "HitTestResult.h"
  63. #include "InitWebCoreQt.h"
  64. #include "InspectorClientQt.h"
  65. #include "InspectorController.h"
  66. #include "InspectorServerQt.h"
  67. #include "LocalizedStrings.h"
  68. #include "MIMETypeRegistry.h"
  69. #include "MemoryCache.h"
  70. #include "NetworkingContext.h"
  71. #include "NodeList.h"
  72. #include "NotificationPresenterClientQt.h"
  73. #include "PageGroup.h"
  74. #include "Pasteboard.h"
  75. #include "PlatformKeyboardEvent.h"
  76. #include "PlatformMouseEvent.h"
  77. #include "PlatformTouchEvent.h"
  78. #include "PlatformWheelEvent.h"
  79. #include "PluginDatabase.h"
  80. #include "PluginPackage.h"
  81. #include "ProgressTracker.h"
  82. #include "QWebFrameAdapter.h"
  83. #include "RenderTextControl.h"
  84. #include "SchemeRegistry.h"
  85. #include "Scrollbar.h"
  86. #include "ScrollbarTheme.h"
  87. #include "Settings.h"
  88. #include "UndoStepQt.h"
  89. #include "UserAgentQt.h"
  90. #include "WebEventConversion.h"
  91. #include "WebKitVersion.h"
  92. #include "WindowFeatures.h"
  93. #include "qwebhistory_p.h"
  94. #include "qwebpluginfactory.h"
  95. #include "qwebsettings.h"
  96. #include <Page.h>
  97. #include <QBitArray>
  98. #include <QGuiApplication>
  99. #include <QMimeData>
  100. #include <QMouseEvent>
  101. #include <QNetworkAccessManager>
  102. #include <QStyleHints>
  103. #include <QTextCharFormat>
  104. #include <QTouchEvent>
  105. #include <QWheelEvent>
  106. // from text/qfont.cpp
  107. QT_BEGIN_NAMESPACE
  108. extern Q_GUI_EXPORT int qt_defaultDpi();
  109. QT_END_NAMESPACE
  110. using namespace WebCore;
  111. bool QWebPageAdapter::drtRun = false;
  112. typedef QWebPageAdapter::MenuItemDescription MenuItem;
  113. static inline DragOperation dropActionToDragOp(Qt::DropActions actions)
  114. {
  115. unsigned result = 0;
  116. if (actions & Qt::CopyAction)
  117. result |= DragOperationCopy;
  118. // DragOperationgeneric represents InternetExplorer's equivalent of Move operation,
  119. // hence it should be considered as "move"
  120. if (actions & Qt::MoveAction)
  121. result |= (DragOperationMove | DragOperationGeneric);
  122. if (actions & Qt::LinkAction)
  123. result |= DragOperationLink;
  124. if (result == (DragOperationCopy | DragOperationMove | DragOperationGeneric | DragOperationLink))
  125. result = DragOperationEvery;
  126. return (DragOperation)result;
  127. }
  128. static inline Qt::DropAction dragOpToDropAction(unsigned actions)
  129. {
  130. Qt::DropAction result = Qt::IgnoreAction;
  131. if (actions & DragOperationCopy)
  132. result = Qt::CopyAction;
  133. else if (actions & DragOperationMove)
  134. result = Qt::MoveAction;
  135. // DragOperationgeneric represents InternetExplorer's equivalent of Move operation,
  136. // hence it should be considered as "move"
  137. else if (actions & DragOperationGeneric)
  138. result = Qt::MoveAction;
  139. else if (actions & DragOperationLink)
  140. result = Qt::LinkAction;
  141. return result;
  142. }
  143. static WebCore::FrameLoadRequest frameLoadRequest(const QUrl &url, WebCore::Frame *frame)
  144. {
  145. return WebCore::FrameLoadRequest(frame->document()->securityOrigin(),
  146. WebCore::ResourceRequest(url, frame->loader()->outgoingReferrer()));
  147. }
  148. static void openNewWindow(const QUrl& url, Frame* frame)
  149. {
  150. if (Page* oldPage = frame->page()) {
  151. WindowFeatures features;
  152. NavigationAction action;
  153. FrameLoadRequest request = frameLoadRequest(url, frame);
  154. if (Page* newPage = oldPage->chrome().createWindow(frame, request, features, action)) {
  155. newPage->mainFrame()->loader()->loadFrameRequest(request, false, false, 0, 0, MaybeSendReferrer);
  156. newPage->chrome().show();
  157. }
  158. }
  159. }
  160. QWebPageAdapter::QWebPageAdapter()
  161. : settings(0)
  162. , page(0)
  163. , pluginFactory(0)
  164. , forwardUnsupportedContent(false)
  165. , insideOpenCall(false)
  166. , clickCausedFocus(false)
  167. , m_totalBytes(0)
  168. , m_bytesReceived()
  169. , networkManager(0)
  170. {
  171. WebCore::initializeWebCoreQt();
  172. }
  173. void QWebPageAdapter::initializeWebCorePage()
  174. {
  175. #if ENABLE(GEOLOCATION) || ENABLE(DEVICE_ORIENTATION)
  176. const bool useMock = QWebPageAdapter::drtRun;
  177. #endif
  178. Page::PageClients pageClients;
  179. pageClients.chromeClient = new ChromeClientQt(this);
  180. pageClients.contextMenuClient = new ContextMenuClientQt();
  181. pageClients.editorClient = new EditorClientQt(this);
  182. pageClients.dragClient = new DragClientQt(pageClients.chromeClient);
  183. pageClients.inspectorClient = new InspectorClientQt(this);
  184. page = new Page(pageClients);
  185. #if ENABLE(GEOLOCATION)
  186. if (useMock) {
  187. // In case running in DumpRenderTree mode set the controller to mock provider.
  188. GeolocationClientMock* mock = new GeolocationClientMock;
  189. WebCore::provideGeolocationTo(page, mock);
  190. mock->setController(WebCore::GeolocationController::from(page));
  191. }
  192. #if HAVE(QTLOCATION)
  193. else
  194. WebCore::provideGeolocationTo(page, new GeolocationClientQt(this));
  195. #endif
  196. #endif
  197. #if ENABLE(DEVICE_ORIENTATION)
  198. if (useMock) {
  199. DeviceOrientationClientMock* mockOrientationClient = new DeviceOrientationClientMock;
  200. WebCore::provideDeviceOrientationTo(page, mockOrientationClient);
  201. DeviceMotionClientMock* mockMotionClient= new DeviceMotionClientMock;
  202. WebCore::provideDeviceMotionTo(page, mockMotionClient);
  203. }
  204. #if HAVE(QTSENSORS)
  205. else {
  206. WebCore::provideDeviceOrientationTo(page, new DeviceOrientationClientQt);
  207. WebCore::provideDeviceMotionTo(page, new DeviceMotionClientQt);
  208. }
  209. #endif
  210. #endif
  211. // By default each page is put into their own unique page group, which affects popup windows
  212. // and visited links. Page groups (per process only) is a feature making it possible to use
  213. // separate settings for each group, so that for instance an integrated browser/email reader
  214. // can use different settings for displaying HTML pages and HTML email. To make QtWebKit work
  215. // as expected out of the box, we use a default group similar to what other ports are doing.
  216. page->setGroupName("Default Group");
  217. page->addLayoutMilestones(DidFirstVisuallyNonEmptyLayout);
  218. settings = new QWebSettings(page->settings());
  219. #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
  220. WebCore::provideNotification(page, NotificationPresenterClientQt::notificationPresenter());
  221. #endif
  222. history.d = new QWebHistoryPrivate(static_cast<WebCore::BackForwardListImpl*>(page->backForwardList()));
  223. PageGroup::setShouldTrackVisitedLinks(true);
  224. }
  225. QWebPageAdapter::~QWebPageAdapter()
  226. {
  227. delete page;
  228. delete settings;
  229. #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
  230. NotificationPresenterClientQt::notificationPresenter()->removeClient();
  231. #endif
  232. }
  233. void QWebPageAdapter::deletePage()
  234. {
  235. // Before we delete the page, detach the mainframe's loader
  236. FrameLoader* loader = mainFrameAdapter()->frame->loader();
  237. if (loader)
  238. loader->detachFromParent();
  239. delete page;
  240. page = 0;
  241. }
  242. QWebPageAdapter* QWebPageAdapter::kit(Page* page)
  243. {
  244. return static_cast<ChromeClientQt*>(page->chrome().client())->m_webPage;
  245. }
  246. ViewportArguments QWebPageAdapter::viewportArguments() const
  247. {
  248. return page ? page->viewportArguments() : WebCore::ViewportArguments();
  249. }
  250. void QWebPageAdapter::registerUndoStep(WTF::PassRefPtr<WebCore::UndoStep> step)
  251. {
  252. createUndoStep(QSharedPointer<UndoStepQt>(new UndoStepQt(step)));
  253. }
  254. void QWebPageAdapter::setNetworkAccessManager(QNetworkAccessManager *manager)
  255. {
  256. if (manager == networkManager)
  257. return;
  258. if (networkManager && networkManager->parent() == handle())
  259. delete networkManager;
  260. networkManager = manager;
  261. }
  262. QNetworkAccessManager* QWebPageAdapter::networkAccessManager()
  263. {
  264. if (!networkManager)
  265. networkManager = new QNetworkAccessManager(handle());
  266. return networkManager;
  267. }
  268. bool QWebPageAdapter::hasSelection() const
  269. {
  270. Frame* frame = page->focusController()->focusedOrMainFrame();
  271. if (frame)
  272. return (frame->selection()->selection().selectionType() != VisibleSelection::NoSelection);
  273. return false;
  274. }
  275. QString QWebPageAdapter::selectedText() const
  276. {
  277. Frame* frame = page->focusController()->focusedOrMainFrame();
  278. if (frame->selection()->selection().selectionType() == VisibleSelection::NoSelection)
  279. return QString();
  280. return frame->editor().selectedText();
  281. }
  282. QString QWebPageAdapter::selectedHtml() const
  283. {
  284. return page->focusController()->focusedOrMainFrame()->editor().selectedRange()->toHTML();
  285. }
  286. bool QWebPageAdapter::isContentEditable() const
  287. {
  288. return page->isEditable();
  289. }
  290. void QWebPageAdapter::setContentEditable(bool editable)
  291. {
  292. page->setEditable(editable);
  293. page->setTabKeyCyclesThroughElements(!editable);
  294. Frame* frame = mainFrameAdapter()->frame;
  295. if (editable) {
  296. frame->editor().applyEditingStyleToBodyElement();
  297. // FIXME: mac port calls this if there is no selectedDOMRange
  298. // frame->setSelectionFromNone();
  299. }
  300. }
  301. bool QWebPageAdapter::findText(const QString& subString, FindFlag options)
  302. {
  303. ::WebCore::FindOptions webCoreFindOptions = 0;
  304. if (!(options & FindCaseSensitively))
  305. webCoreFindOptions |= WebCore::CaseInsensitive;
  306. if (options & FindBackward)
  307. webCoreFindOptions |= WebCore::Backwards;
  308. if (options & FindWrapsAroundDocument)
  309. webCoreFindOptions |= WebCore::WrapAround;
  310. if (options & FindAtWordBeginningsOnly)
  311. webCoreFindOptions |= WebCore::AtWordStarts;
  312. if (options & TreatMedialCapitalAsWordBeginning)
  313. webCoreFindOptions |= WebCore::TreatMedialCapitalAsWordStart;
  314. if (options & FindBeginsInSelection)
  315. webCoreFindOptions |= WebCore::StartInSelection;
  316. if (options & HighlightAllOccurrences) {
  317. if (subString.isEmpty()) {
  318. page->unmarkAllTextMatches();
  319. return true;
  320. }
  321. return page->markAllMatchesForText(subString, webCoreFindOptions, /*shouldHighlight*/ true, /*limit*/ 0);
  322. }
  323. if (subString.isEmpty()) {
  324. page->mainFrame()->selection()->clear();
  325. Frame* frame = page->mainFrame()->tree()->firstChild();
  326. while (frame) {
  327. frame->selection()->clear();
  328. frame = frame->tree()->traverseNextWithWrap(false);
  329. }
  330. }
  331. return page->findString(subString, webCoreFindOptions);
  332. }
  333. void QWebPageAdapter::adjustPointForClicking(QMouseEvent* ev)
  334. {
  335. #if ENABLE(TOUCH_ADJUSTMENT)
  336. QtPlatformPlugin platformPlugin;
  337. OwnPtr<QWebTouchModifier> touchModifier = platformPlugin.createTouchModifier();
  338. if (!touchModifier)
  339. return;
  340. unsigned topPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Up);
  341. unsigned rightPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Right);
  342. unsigned bottomPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Down);
  343. unsigned leftPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Left);
  344. touchModifier = nullptr;
  345. if (!topPadding && !rightPadding && !bottomPadding && !leftPadding)
  346. return;
  347. EventHandler* eventHandler = page->mainFrame()->eventHandler();
  348. ASSERT(eventHandler);
  349. IntRect touchRect(ev->pos().x() - leftPadding, ev->pos().y() - topPadding, leftPadding + rightPadding, topPadding + bottomPadding);
  350. IntPoint adjustedPoint;
  351. Node* adjustedNode;
  352. bool foundClickableNode = eventHandler->bestClickableNodeForTouchPoint(touchRect.center(), touchRect.size(), adjustedPoint, adjustedNode);
  353. if (!foundClickableNode)
  354. return;
  355. QMouseEvent* ret = new QMouseEvent(ev->type(), QPoint(adjustedPoint), ev->globalPos(), ev->button(), ev->buttons(), ev->modifiers());
  356. delete ev;
  357. ev = ret;
  358. #else
  359. Q_UNUSED(ev);
  360. #endif
  361. }
  362. void QWebPageAdapter::mouseMoveEvent(QMouseEvent* ev)
  363. {
  364. WebCore::Frame* frame = mainFrameAdapter()->frame;
  365. if (!frame->view())
  366. return;
  367. bool accepted = frame->eventHandler()->mouseMoved(convertMouseEvent(ev, 0));
  368. ev->setAccepted(accepted);
  369. }
  370. void QWebPageAdapter::mousePressEvent(QMouseEvent* ev)
  371. {
  372. WebCore::Frame* frame = mainFrameAdapter()->frame;
  373. if (!frame->view())
  374. return;
  375. RefPtr<WebCore::Node> oldNode;
  376. Frame* focusedFrame = page->focusController()->focusedFrame();
  377. if (Document* focusedDocument = focusedFrame ? focusedFrame->document() : 0)
  378. oldNode = focusedDocument->focusedElement();
  379. if (tripleClickTimer.isActive()
  380. && (ev->pos() - tripleClick).manhattanLength() < qGuiApp->styleHints()->startDragDistance()) {
  381. mouseTripleClickEvent(ev);
  382. return;
  383. }
  384. bool accepted = false;
  385. PlatformMouseEvent mev = convertMouseEvent(ev, 1);
  386. // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
  387. if (mev.button() != NoButton)
  388. accepted = frame->eventHandler()->handleMousePressEvent(mev);
  389. ev->setAccepted(accepted);
  390. RefPtr<WebCore::Node> newNode;
  391. focusedFrame = page->focusController()->focusedFrame();
  392. if (Document* focusedDocument = focusedFrame ? focusedFrame->document() : 0)
  393. newNode = focusedDocument->focusedElement();
  394. if (newNode && oldNode != newNode)
  395. clickCausedFocus = true;
  396. }
  397. void QWebPageAdapter::mouseDoubleClickEvent(QMouseEvent *ev)
  398. {
  399. WebCore::Frame* frame = mainFrameAdapter()->frame;
  400. if (!frame->view())
  401. return;
  402. bool accepted = false;
  403. PlatformMouseEvent mev = convertMouseEvent(ev, 2);
  404. // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
  405. if (mev.button() != NoButton)
  406. accepted = frame->eventHandler()->handleMousePressEvent(mev);
  407. ev->setAccepted(accepted);
  408. tripleClickTimer.start(qGuiApp->styleHints()->mouseDoubleClickInterval(), handle());
  409. tripleClick = QPointF(ev->pos()).toPoint();
  410. }
  411. void QWebPageAdapter::mouseTripleClickEvent(QMouseEvent *ev)
  412. {
  413. WebCore::Frame* frame = mainFrameAdapter()->frame;
  414. if (!frame->view())
  415. return;
  416. bool accepted = false;
  417. PlatformMouseEvent mev = convertMouseEvent(ev, 3);
  418. // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
  419. if (mev.button() != NoButton)
  420. accepted = frame->eventHandler()->handleMousePressEvent(mev);
  421. ev->setAccepted(accepted);
  422. }
  423. void QWebPageAdapter::mouseReleaseEvent(QMouseEvent *ev)
  424. {
  425. WebCore::Frame* frame = mainFrameAdapter()->frame;
  426. if (!frame->view())
  427. return;
  428. bool accepted = false;
  429. PlatformMouseEvent mev = convertMouseEvent(ev, 0);
  430. // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
  431. if (mev.button() != NoButton)
  432. accepted = frame->eventHandler()->handleMouseReleaseEvent(mev);
  433. ev->setAccepted(accepted);
  434. handleSoftwareInputPanel(ev->button(), QPointF(ev->pos()).toPoint());
  435. }
  436. void QWebPageAdapter::handleSoftwareInputPanel(Qt::MouseButton button, const QPoint& pos)
  437. {
  438. Frame* frame = page->focusController()->focusedFrame();
  439. if (!frame)
  440. return;
  441. if (client && client->inputMethodEnabled()
  442. && frame->document()->focusedElement()
  443. && button == Qt::LeftButton && qGuiApp->property("autoSipEnabled").toBool()) {
  444. if (!clickCausedFocus || requestSoftwareInputPanel()) {
  445. HitTestResult result = frame->eventHandler()->hitTestResultAtPoint(frame->view()->windowToContents(pos));
  446. if (result.isContentEditable()) {
  447. QEvent event(QEvent::RequestSoftwareInputPanel);
  448. QGuiApplication::sendEvent(client->ownerWidget(), &event);
  449. }
  450. }
  451. }
  452. clickCausedFocus = false;
  453. }
  454. #ifndef QT_NO_WHEELEVENT
  455. void QWebPageAdapter::wheelEvent(QWheelEvent *ev, int wheelScrollLines)
  456. {
  457. WebCore::Frame* frame = mainFrameAdapter()->frame;
  458. if (!frame->view())
  459. return;
  460. PlatformWheelEvent pev = convertWheelEvent(ev, wheelScrollLines);
  461. bool accepted = frame->eventHandler()->handleWheelEvent(pev);
  462. ev->setAccepted(accepted);
  463. }
  464. #endif // QT_NO_WHEELEVENT
  465. #ifndef QT_NO_DRAGANDDROP
  466. Qt::DropAction QWebPageAdapter::dragEntered(const QMimeData *data, const QPoint &pos, Qt::DropActions possibleActions)
  467. {
  468. DragData dragData(data, pos, QCursor::pos(), dropActionToDragOp(possibleActions));
  469. return dragOpToDropAction(page->dragController()->dragEntered(&dragData).operation);
  470. }
  471. void QWebPageAdapter::dragLeaveEvent()
  472. {
  473. DragData dragData(0, IntPoint(), QCursor::pos(), DragOperationNone);
  474. page->dragController()->dragExited(&dragData);
  475. }
  476. Qt::DropAction QWebPageAdapter::dragUpdated(const QMimeData *data, const QPoint &pos, Qt::DropActions possibleActions)
  477. {
  478. DragData dragData(data, pos, QCursor::pos(), dropActionToDragOp(possibleActions));
  479. return dragOpToDropAction(page->dragController()->dragUpdated(&dragData).operation);
  480. }
  481. bool QWebPageAdapter::performDrag(const QMimeData *data, const QPoint &pos, Qt::DropActions possibleActions)
  482. {
  483. DragData dragData(data, pos, QCursor::pos(), dropActionToDragOp(possibleActions));
  484. return page->dragController()->performDrag(&dragData);
  485. }
  486. void QWebPageAdapter::inputMethodEvent(QInputMethodEvent *ev)
  487. {
  488. WebCore::Frame *frame = page->focusController()->focusedOrMainFrame();
  489. WebCore::Editor &editor = frame->editor();
  490. if (!editor.canEdit()) {
  491. ev->ignore();
  492. return;
  493. }
  494. Node* node = 0;
  495. if (frame->selection()->rootEditableElement())
  496. node = frame->selection()->rootEditableElement()->deprecatedShadowAncestorNode();
  497. Vector<CompositionUnderline> underlines;
  498. bool hasSelection = false;
  499. for (int i = 0; i < ev->attributes().size(); ++i) {
  500. const QInputMethodEvent::Attribute& a = ev->attributes().at(i);
  501. switch (a.type) {
  502. case QInputMethodEvent::TextFormat: {
  503. QTextCharFormat textCharFormat = a.value.value<QTextFormat>().toCharFormat();
  504. QColor qcolor = textCharFormat.underlineColor();
  505. 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));
  506. break;
  507. }
  508. case QInputMethodEvent::Cursor: {
  509. frame->selection()->setCaretVisible(a.length); // if length is 0 cursor is invisible
  510. if (a.length > 0) {
  511. RenderObject* caretRenderer = frame->selection()->caretRenderer();
  512. if (caretRenderer) {
  513. QColor qcolor = a.value.value<QColor>();
  514. caretRenderer->style()->setColor(Color(makeRGBA(qcolor.red(), qcolor.green(), qcolor.blue(), qcolor.alpha())));
  515. }
  516. }
  517. break;
  518. }
  519. case QInputMethodEvent::Selection: {
  520. hasSelection = true;
  521. // A selection in the inputMethodEvent is always reflected in the visible text
  522. if (node) {
  523. if (isHTMLTextFormControlElement(node))
  524. toHTMLTextFormControlElement(node)->setSelectionRange(qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length)));
  525. }
  526. if (!ev->preeditString().isEmpty())
  527. editor.setComposition(ev->preeditString(), underlines, qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length)));
  528. else {
  529. // If we are in the middle of a composition, an empty pre-edit string and a selection of zero
  530. // cancels the current composition
  531. if (editor.hasComposition() && !(a.start + a.length))
  532. editor.setComposition(QString(), underlines, 0, 0);
  533. }
  534. break;
  535. }
  536. default:
  537. break;
  538. }
  539. }
  540. if (node && ev->replacementLength() > 0) {
  541. int cursorPos = frame->selection()->extent().offsetInContainerNode();
  542. int start = cursorPos + ev->replacementStart();
  543. if (isHTMLTextFormControlElement(node))
  544. toHTMLTextFormControlElement(node)->setSelectionRange(start, start + ev->replacementLength());
  545. // Commit regardless of whether commitString is empty, to get rid of selection.
  546. editor.confirmComposition(ev->commitString());
  547. } else if (!ev->commitString().isEmpty()) {
  548. if (editor.hasComposition())
  549. editor.confirmComposition(ev->commitString());
  550. else
  551. editor.insertText(ev->commitString(), 0);
  552. } else if (!hasSelection && !ev->preeditString().isEmpty())
  553. editor.setComposition(ev->preeditString(), underlines, 0, 0);
  554. else if (ev->preeditString().isEmpty() && editor.hasComposition())
  555. editor.confirmComposition(String());
  556. ev->accept();
  557. }
  558. QVariant QWebPageAdapter::inputMethodQuery(Qt::InputMethodQuery property) const
  559. {
  560. Frame* frame = page->focusController()->focusedFrame();
  561. if (!frame)
  562. return QVariant();
  563. WebCore::Editor& editor = frame->editor();
  564. RenderObject* renderer = 0;
  565. RenderTextControl* renderTextControl = 0;
  566. if (frame->selection()->rootEditableElement())
  567. renderer = frame->selection()->rootEditableElement()->deprecatedShadowAncestorNode()->renderer();
  568. if (renderer && renderer->isTextControl())
  569. renderTextControl = toRenderTextControl(renderer);
  570. switch (property) {
  571. case Qt::ImMicroFocus: {
  572. WebCore::FrameView* view = frame->view();
  573. if (view && view->needsLayout()) {
  574. // We can't access absoluteCaretBounds() while the view needs to layout.
  575. return QVariant();
  576. }
  577. return QVariant(view->contentsToWindow(frame->selection()->absoluteCaretBounds()));
  578. }
  579. case Qt::ImFont: {
  580. if (renderTextControl) {
  581. RenderStyle* renderStyle = renderTextControl->style();
  582. return QVariant(QFont(renderStyle->font().syntheticFont()));
  583. }
  584. return QVariant(QFont());
  585. }
  586. case Qt::ImCursorPosition: {
  587. if (editor.hasComposition())
  588. return QVariant(frame->selection()->end().offsetInContainerNode());
  589. return QVariant(frame->selection()->extent().offsetInContainerNode());
  590. }
  591. case Qt::ImSurroundingText: {
  592. if (renderTextControl && renderTextControl->textFormControlElement()) {
  593. QString text = renderTextControl->textFormControlElement()->value();
  594. RefPtr<Range> range = editor.compositionRange();
  595. if (range)
  596. text.remove(range->startPosition().offsetInContainerNode(), TextIterator::rangeLength(range.get()));
  597. return QVariant(text);
  598. }
  599. return QVariant();
  600. }
  601. case Qt::ImCurrentSelection: {
  602. if (!editor.hasComposition() && renderTextControl && renderTextControl->textFormControlElement()) {
  603. int start = frame->selection()->start().offsetInContainerNode();
  604. int end = frame->selection()->end().offsetInContainerNode();
  605. if (end > start)
  606. return QVariant(QString(renderTextControl->textFormControlElement()->value()).mid(start, end - start));
  607. }
  608. return QVariant();
  609. }
  610. case Qt::ImAnchorPosition: {
  611. if (editor.hasComposition())
  612. return QVariant(frame->selection()->start().offsetInContainerNode());
  613. return QVariant(frame->selection()->base().offsetInContainerNode());
  614. }
  615. case Qt::ImMaximumTextLength: {
  616. if (frame->selection()->isContentEditable()) {
  617. if (frame->document() && frame->document()->focusedElement()) {
  618. if (frame->document()->focusedElement()->hasTagName(HTMLNames::inputTag)) {
  619. HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(frame->document()->focusedElement());
  620. return QVariant(inputElement->maxLength());
  621. }
  622. }
  623. return QVariant(HTMLInputElement::maximumLength);
  624. }
  625. return QVariant(0);
  626. }
  627. default:
  628. return QVariant();
  629. }
  630. }
  631. typedef struct {
  632. const char* name;
  633. double deferredRepaintDelay;
  634. double initialDeferredRepaintDelayDuringLoading;
  635. double maxDeferredRepaintDelayDuringLoading;
  636. double deferredRepaintDelayIncrementDuringLoading;
  637. } QRepaintThrottlingPreset;
  638. void QWebPageAdapter::dynamicPropertyChangeEvent(QObject* obj, QDynamicPropertyChangeEvent* event)
  639. {
  640. if (event->propertyName() == "_q_viewMode") {
  641. page->setViewMode(Page::stringToViewMode(obj->property("_q_viewMode").toString()));
  642. } else if (event->propertyName() == "_q_HTMLTokenizerChunkSize") {
  643. int chunkSize = obj->property("_q_HTMLTokenizerChunkSize").toInt();
  644. page->setCustomHTMLTokenizerChunkSize(chunkSize);
  645. } else if (event->propertyName() == "_q_HTMLTokenizerTimeDelay") {
  646. double timeDelay = obj->property("_q_HTMLTokenizerTimeDelay").toDouble();
  647. page->setCustomHTMLTokenizerTimeDelay(timeDelay);
  648. } else if (event->propertyName() == "_q_RepaintThrottlingDeferredRepaintDelay") {
  649. double p = obj->property("_q_RepaintThrottlingDeferredRepaintDelay").toDouble();
  650. FrameView::setRepaintThrottlingDeferredRepaintDelay(p);
  651. } else if (event->propertyName() == "_q_RepaintThrottlingnInitialDeferredRepaintDelayDuringLoading") {
  652. double p = obj->property("_q_RepaintThrottlingnInitialDeferredRepaintDelayDuringLoading").toDouble();
  653. FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(p);
  654. } else if (event->propertyName() == "_q_RepaintThrottlingMaxDeferredRepaintDelayDuringLoading") {
  655. double p = obj->property("_q_RepaintThrottlingMaxDeferredRepaintDelayDuringLoading").toDouble();
  656. FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(p);
  657. } else if (event->propertyName() == "_q_RepaintThrottlingDeferredRepaintDelayIncrementDuringLoading") {
  658. double p = obj->property("_q_RepaintThrottlingDeferredRepaintDelayIncrementDuringLoading").toDouble();
  659. FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(p);
  660. } else if (event->propertyName() == "_q_RepaintThrottlingPreset") {
  661. static const QRepaintThrottlingPreset presets[] = {
  662. { "NoThrottling", 0, 0, 0, 0 },
  663. { "Legacy", 0.025, 0, 2.5, 0.5 },
  664. { "Minimal", 0.01, 0, 1, 0.2 },
  665. { "Medium", 0.025, 1, 5, 0.5 },
  666. { "Heavy", 0.1, 2, 10, 1 }
  667. };
  668. QString p = obj->property("_q_RepaintThrottlingPreset").toString();
  669. for (size_t i = 0; i < sizeof(presets) / sizeof(presets[0]); i++) {
  670. if (p == QLatin1String(presets[i].name)) {
  671. FrameView::setRepaintThrottlingDeferredRepaintDelay(presets[i].deferredRepaintDelay);
  672. FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(presets[i].initialDeferredRepaintDelayDuringLoading);
  673. FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(presets[i].maxDeferredRepaintDelayDuringLoading);
  674. FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(presets[i].deferredRepaintDelayIncrementDuringLoading);
  675. break;
  676. }
  677. }
  678. } else if (event->propertyName() == "_q_webInspectorServerPort") {
  679. #if ENABLE(INSPECTOR)
  680. QVariant port = obj->property("_q_webInspectorServerPort");
  681. if (port.isValid()) {
  682. InspectorServerQt* inspectorServer = InspectorServerQt::server();
  683. inspectorServer->listen(port.toInt());
  684. }
  685. #endif
  686. } else if (event->propertyName() == "_q_deadDecodedDataDeletionInterval") {
  687. double interval = obj->property("_q_deadDecodedDataDeletionInterval").toDouble();
  688. memoryCache()->setDeadDecodedDataDeletionInterval(interval);
  689. }
  690. }
  691. #endif // QT_NO_DRAGANDDROP
  692. #define MAP_ACTION_FROM_VALUE(Name, Value) \
  693. case Value: return QWebPageAdapter::Name
  694. static QWebPageAdapter::MenuAction adapterActionForContextMenuAction(WebCore::ContextMenuAction action)
  695. {
  696. switch (action) {
  697. FOR_EACH_MAPPED_MENU_ACTION(MAP_ACTION_FROM_VALUE, SEMICOLON_SEPARATOR);
  698. #if ENABLE(INSPECTOR)
  699. case WebCore::ContextMenuItemTagInspectElement:
  700. return QWebPageAdapter::InspectElement;
  701. #endif
  702. default:
  703. break;
  704. }
  705. return QWebPageAdapter::NoAction;
  706. }
  707. QList<MenuItem> descriptionForPlatformMenu(const Vector<ContextMenuItem>& items, Page* page)
  708. {
  709. QList<MenuItem> itemDescriptions;
  710. if (!items.size())
  711. return itemDescriptions;
  712. for (int i = 0; i < items.size(); ++i) {
  713. const ContextMenuItem &item = items.at(i);
  714. MenuItem description;
  715. switch (item.type()) {
  716. case WebCore::CheckableActionType: /* fall through */
  717. case WebCore::ActionType: {
  718. QWebPageAdapter::MenuAction action = adapterActionForContextMenuAction(item.action());
  719. if (action > QWebPageAdapter::NoAction) {
  720. description.type = MenuItem::Action;
  721. description.action = action;
  722. ContextMenuItem it(item);
  723. page->contextMenuController()->checkOrEnableIfNeeded(it);
  724. if (it.enabled())
  725. description.traits |= MenuItem::Enabled;
  726. if (item.type() == WebCore::CheckableActionType) {
  727. description.traits |= MenuItem::Checkable;
  728. if (it.checked())
  729. description.traits |= MenuItem::Checked;
  730. }
  731. }
  732. break;
  733. }
  734. case WebCore::SeparatorType:
  735. description.type = MenuItem::Separator;
  736. break;
  737. case WebCore::SubmenuType: {
  738. description.type = MenuItem::SubMenu;
  739. description.subMenu = descriptionForPlatformMenu(item.subMenuItems(), page);
  740. description.subMenuTitle = item.title();
  741. // Don't append empty submenu descriptions.
  742. if (description.subMenu.isEmpty())
  743. continue;
  744. }
  745. }
  746. if (description.type > MenuItem::NoType)
  747. itemDescriptions.append(description);
  748. }
  749. return itemDescriptions;
  750. }
  751. QWebHitTestResultPrivate* QWebPageAdapter::updatePositionDependentMenuActions(const QPoint& pos, QBitArray* visitedWebActions)
  752. {
  753. ASSERT(visitedWebActions);
  754. WebCore::Frame* focusedFrame = page->focusController()->focusedOrMainFrame();
  755. HitTestResult result = focusedFrame->eventHandler()->hitTestResultAtPoint(focusedFrame->view()->windowToContents(pos));
  756. page->contextMenuController()->setHitTestResult(result);
  757. #if ENABLE(INSPECTOR)
  758. if (page->inspectorController()->enabled())
  759. page->contextMenuController()->addInspectElementItem();
  760. #endif
  761. WebCore::ContextMenu* webcoreMenu = page->contextMenuController()->contextMenu();
  762. QList<MenuItem> itemDescriptions;
  763. if (client && webcoreMenu)
  764. itemDescriptions = descriptionForPlatformMenu(webcoreMenu->items(), page);
  765. createAndSetCurrentContextMenu(itemDescriptions, visitedWebActions);
  766. if (result.scrollbar())
  767. return 0;
  768. return new QWebHitTestResultPrivate(result);
  769. }
  770. static void extractContentTypeFromHash(const HashSet<String>& types, QStringList* list)
  771. {
  772. if (!list)
  773. return;
  774. HashSet<String>::const_iterator endIt = types.end();
  775. for (HashSet<String>::const_iterator it = types.begin(); it != endIt; ++it)
  776. *list << *it;
  777. }
  778. static void extractContentTypeFromPluginVector(const Vector<PluginPackage*>& plugins, QStringList* list)
  779. {
  780. if (!list)
  781. return;
  782. for (unsigned i = 0; i < plugins.size(); ++i) {
  783. MIMEToDescriptionsMap::const_iterator it = plugins[i]->mimeToDescriptions().begin();
  784. MIMEToDescriptionsMap::const_iterator end = plugins[i]->mimeToDescriptions().end();
  785. for (; it != end; ++it)
  786. *list << it->key;
  787. }
  788. }
  789. QStringList QWebPageAdapter::supportedContentTypes() const
  790. {
  791. QStringList mimeTypes;
  792. extractContentTypeFromHash(MIMETypeRegistry::getSupportedImageMIMETypes(), &mimeTypes);
  793. extractContentTypeFromHash(MIMETypeRegistry::getSupportedNonImageMIMETypes(), &mimeTypes);
  794. if (page->settings() && page->settings()->arePluginsEnabled())
  795. extractContentTypeFromPluginVector(PluginDatabase::installedPlugins()->plugins(), &mimeTypes);
  796. return mimeTypes;
  797. }
  798. void QWebPageAdapter::_q_cleanupLeakMessages()
  799. {
  800. #ifndef NDEBUG
  801. // Need this to make leak messages accurate.
  802. memoryCache()->setCapacities(0, 0, 0);
  803. #endif
  804. }
  805. void QWebPageAdapter::_q_onLoadProgressChanged(int)
  806. {
  807. m_totalBytes = page->progress()->totalPageAndResourceBytesToLoad();
  808. m_bytesReceived = page->progress()->totalBytesReceived();
  809. }
  810. bool QWebPageAdapter::supportsContentType(const QString& mimeType) const
  811. {
  812. const String type = mimeType.toLower();
  813. if (MIMETypeRegistry::isSupportedImageMIMEType(type))
  814. return true;
  815. if (MIMETypeRegistry::isSupportedNonImageMIMEType(type))
  816. return true;
  817. if (page->settings() && page->settings()->arePluginsEnabled()
  818. && PluginDatabase::installedPlugins()->isMIMETypeRegistered(type))
  819. return true;
  820. return false;
  821. }
  822. void QWebPageAdapter::didShowInspector()
  823. {
  824. #if ENABLE(INSPECTOR)
  825. page->inspectorController()->show();
  826. #endif
  827. }
  828. void QWebPageAdapter::didCloseInspector()
  829. {
  830. #if ENABLE(INSPECTOR)
  831. page->inspectorController()->close();
  832. #endif
  833. }
  834. void QWebPageAdapter::updateActionInternal(QWebPageAdapter::MenuAction action, const char* commandName, bool* enabled, bool* checked)
  835. {
  836. WebCore::FrameLoader* loader = mainFrameAdapter()->frame->loader();
  837. WebCore::Editor& editor = page->focusController()->focusedOrMainFrame()->editor();
  838. switch (action) {
  839. case QWebPageAdapter::Back:
  840. *enabled = page->canGoBackOrForward(-1);
  841. break;
  842. case QWebPageAdapter::Forward:
  843. *enabled = page->canGoBackOrForward(1);
  844. break;
  845. case QWebPageAdapter::Stop:
  846. *enabled = loader->isLoading();
  847. break;
  848. case QWebPageAdapter::Reload:
  849. *enabled = !loader->isLoading();
  850. break;
  851. case QWebPageAdapter::SetTextDirectionDefault:
  852. case QWebPageAdapter::SetTextDirectionLeftToRight:
  853. case QWebPageAdapter::SetTextDirectionRightToLeft:
  854. *enabled = editor.canEdit();
  855. *checked = false;
  856. break;
  857. default: {
  858. // if it's an editor command, let its logic determine state
  859. if (commandName) {
  860. Editor::Command command = editor.command(commandName);
  861. *enabled = command.isEnabled();
  862. if (*enabled)
  863. *checked = command.state() != FalseTriState;
  864. else
  865. *checked = false;
  866. }
  867. break;
  868. }
  869. }
  870. }
  871. void QWebPageAdapter::triggerAction(QWebPageAdapter::MenuAction action, QWebHitTestResultPrivate* hitTestResult, const char* commandName, bool endToEndReload)
  872. {
  873. Frame* frame = page->focusController()->focusedOrMainFrame();
  874. if (!frame)
  875. return;
  876. Editor& editor = frame->editor();
  877. // Convenience
  878. QWebHitTestResultPrivate hitTest;
  879. if (!hitTestResult)
  880. hitTestResult = &hitTest;
  881. switch (action) {
  882. case OpenLink:
  883. if (Frame* targetFrame = hitTestResult->webCoreFrame) {
  884. targetFrame->loader()->loadFrameRequest(frameLoadRequest(hitTestResult->linkUrl, targetFrame), /*lockHistory*/ false, /*lockBackForwardList*/ false, /*event*/ 0, /*FormState*/ 0, MaybeSendReferrer);
  885. break;
  886. }
  887. // fall through
  888. case OpenLinkInNewWindow:
  889. openNewWindow(hitTestResult->linkUrl, frame);
  890. break;
  891. case OpenLinkInThisWindow:
  892. frame->loader()->loadFrameRequest(frameLoadRequest(hitTestResult->linkUrl, frame), /*lockHistory*/ false, /*lockBackForwardList*/ false, /*event*/ 0, /*FormState*/ 0, MaybeSendReferrer);
  893. break;
  894. case OpenFrameInNewWindow: {
  895. KURL url = frame->loader()->documentLoader()->unreachableURL();
  896. if (url.isEmpty())
  897. url = frame->loader()->documentLoader()->url();
  898. openNewWindow(url, frame);
  899. break;
  900. }
  901. case CopyLinkToClipboard: {
  902. #if defined(Q_WS_X11)
  903. bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode();
  904. Pasteboard::generalPasteboard()->setSelectionMode(true);
  905. editor.copyURL(hitTestResult->linkUrl, hitTestResult->linkText);
  906. Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode);
  907. #endif
  908. editor.copyURL(hitTestResult->linkUrl, hitTestResult->linkText);
  909. break;
  910. }
  911. case OpenImageInNewWindow:
  912. openNewWindow(hitTestResult->imageUrl, frame);
  913. break;
  914. case DownloadImageToDisk:
  915. frame->loader()->client()->startDownload(WebCore::ResourceRequest(hitTestResult->imageUrl, frame->loader()->outgoingReferrer()));
  916. break;
  917. case DownloadLinkToDisk:
  918. frame->loader()->client()->startDownload(WebCore::ResourceRequest(hitTestResult->linkUrl, frame->loader()->outgoingReferrer()));
  919. break;
  920. case Back:
  921. page->goBack();
  922. break;
  923. case Forward:
  924. page->goForward();
  925. break;
  926. case Stop:
  927. mainFrameAdapter()->frame->loader()->stopForUserCancel();
  928. updateNavigationActions();
  929. break;
  930. case Reload:
  931. mainFrameAdapter()->frame->loader()->reload(endToEndReload);
  932. break;
  933. case SetTextDirectionDefault:
  934. editor.setBaseWritingDirection(NaturalWritingDirection);
  935. break;
  936. case SetTextDirectionLeftToRight:
  937. editor.setBaseWritingDirection(LeftToRightWritingDirection);
  938. break;
  939. case SetTextDirectionRightToLeft:
  940. editor.setBaseWritingDirection(RightToLeftWritingDirection);
  941. break;
  942. #if ENABLE(INSPECTOR)
  943. case InspectElement: {
  944. ASSERT(hitTestResult != &hitTest);
  945. page->inspectorController()->inspect(hitTestResult->innerNonSharedNode);
  946. break;
  947. }
  948. #endif
  949. default:
  950. if (commandName)
  951. editor.command(commandName).execute();
  952. break;
  953. }
  954. }
  955. QString QWebPageAdapter::contextMenuItemTagForAction(QWebPageAdapter::MenuAction action, bool* checkable) const
  956. {
  957. ASSERT(checkable);
  958. switch (action) {
  959. case OpenLink:
  960. return contextMenuItemTagOpenLink();
  961. case OpenLinkInNewWindow:
  962. return contextMenuItemTagOpenLinkInNewWindow();
  963. case OpenFrameInNewWindow:
  964. return contextMenuItemTagOpenFrameInNewWindow();
  965. case OpenLinkInThisWindow:
  966. return contextMenuItemTagOpenLinkInThisWindow();
  967. case DownloadLinkToDisk:
  968. return contextMenuItemTagDownloadLinkToDisk();
  969. case CopyLinkToClipboard:
  970. return contextMenuItemTagCopyLinkToClipboard();
  971. case OpenImageInNewWindow:
  972. return contextMenuItemTagOpenImageInNewWindow();
  973. case DownloadImageToDisk:
  974. return contextMenuItemTagDownloadImageToDisk();
  975. case CopyImageToClipboard:
  976. return contextMenuItemTagCopyImageToClipboard();
  977. case CopyImageUrlToClipboard:
  978. return contextMenuItemTagCopyImageUrlToClipboard();
  979. case Cut:
  980. return contextMenuItemTagCut();
  981. case Copy:
  982. return contextMenuItemTagCopy();
  983. case Paste:
  984. return contextMenuItemTagPaste();
  985. case SelectAll:
  986. return contextMenuItemTagSelectAll();
  987. case Back:
  988. return contextMenuItemTagGoBack();
  989. case Forward:
  990. return contextMenuItemTagGoForward();
  991. case Reload:
  992. return contextMenuItemTagReload();
  993. case Stop:
  994. return contextMenuItemTagStop();
  995. case SetTextDirectionDefault:
  996. return contextMenuItemTagDefaultDirection();
  997. case SetTextDirectionLeftToRight:
  998. *checkable = true;
  999. return contextMenuItemTagLeftToRight();
  1000. case SetTextDirectionRightToLeft:
  1001. *checkable = true;
  1002. return contextMenuItemTagRightToLeft();
  1003. case ToggleBold:
  1004. *checkable = true;
  1005. return contextMenuItemTagBold();
  1006. case ToggleItalic:
  1007. *checkable = true;
  1008. return contextMenuItemTagItalic();
  1009. case ToggleUnderline:
  1010. *checkable = true;
  1011. return contextMenuItemTagUnderline();
  1012. #if ENABLE(INSPECTOR)
  1013. case InspectElement:
  1014. return contextMenuItemTagInspectElement();
  1015. #endif
  1016. default:
  1017. ASSERT_NOT_REACHED();
  1018. return QString();
  1019. }
  1020. }
  1021. #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
  1022. void QWebPageAdapter::setNotificationsAllowedForFrame(QWebFrameAdapter* frame, bool allowed)
  1023. {
  1024. NotificationPresenterClientQt::notificationPresenter()->setNotificationsAllowedForFrame(frame->frame, allowed);
  1025. }
  1026. void QWebPageAdapter::addNotificationPresenterClient()
  1027. {
  1028. NotificationPresenterClientQt::notificationPresenter()->addClient();
  1029. }
  1030. #ifndef QT_NO_SYSTEMTRAYICON
  1031. bool QWebPageAdapter::hasSystemTrayIcon() const
  1032. {
  1033. return NotificationPresenterClientQt::notificationPresenter()->hasSystemTrayIcon();
  1034. }
  1035. void QWebPageAdapter::setSystemTrayIcon(QObject *icon)
  1036. {
  1037. NotificationPresenterClientQt::notificationPresenter()->setSystemTrayIcon(icon);
  1038. }
  1039. #endif // QT_NO_SYSTEMTRAYICON
  1040. #endif // ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
  1041. #if ENABLE(GEOLOCATION) && HAVE(QTLOCATION)
  1042. void QWebPageAdapter::setGeolocationEnabledForFrame(QWebFrameAdapter* frame, bool on)
  1043. {
  1044. GeolocationPermissionClientQt::geolocationPermissionClient()->setPermission(frame, on);
  1045. }
  1046. #endif
  1047. QString QWebPageAdapter::defaultUserAgentString()
  1048. {
  1049. return UserAgentQt::standardUserAgent("", WEBKIT_MAJOR_VERSION, WEBKIT_MINOR_VERSION);
  1050. }
  1051. bool QWebPageAdapter::treatSchemeAsLocal(const QString& scheme)
  1052. {
  1053. return WebCore::SchemeRegistry::shouldTreatURLSchemeAsLocal(scheme);
  1054. }
  1055. QObject* QWebPageAdapter::currentFrame() const
  1056. {
  1057. Frame* frame = page->focusController()->focusedOrMainFrame();
  1058. return frame->loader()->networkingContext()->originatingObject();
  1059. }
  1060. bool QWebPageAdapter::hasFocusedNode() const
  1061. {
  1062. bool hasFocus = false;
  1063. Frame* frame = page->focusController()->focusedFrame();
  1064. if (frame) {
  1065. Document* document = frame->document();
  1066. hasFocus = document && document->focusedElement();
  1067. }
  1068. return hasFocus;
  1069. }
  1070. QWebPageAdapter::ViewportAttributes QWebPageAdapter::viewportAttributesForSize(const QSize &availableSize, const QSize &deviceSize) const
  1071. {
  1072. static const int desktopWidth = 980;
  1073. float devicePixelRatio = qt_defaultDpi() / WebCore::ViewportArguments::deprecatedTargetDPI;
  1074. WebCore::ViewportAttributes conf = WebCore::computeViewportAttributes(viewportArguments(), desktopWidth, deviceSize.width(), deviceSize.height(), devicePixelRatio, availableSize);
  1075. WebCore::restrictMinimumScaleFactorToViewportSize(conf, availableSize, devicePixelRatio);
  1076. WebCore::restrictScaleFactorToInitialScaleIfNotUserScalable(conf);
  1077. page->setDeviceScaleFactor(devicePixelRatio);
  1078. QWebPageAdapter::ViewportAttributes result;
  1079. result.size = QSizeF(conf.layoutSize.width(), conf.layoutSize.height());
  1080. result.initialScaleFactor = conf.initialScale;
  1081. result.minimumScaleFactor = conf.minimumScale;
  1082. result.maximumScaleFactor = conf.maximumScale;
  1083. result.devicePixelRatio = devicePixelRatio;
  1084. result.isUserScalable = static_cast<bool>(conf.userScalable);
  1085. return result;
  1086. }
  1087. bool QWebPageAdapter::handleKeyEvent(QKeyEvent *ev)
  1088. {
  1089. Frame* frame = page->focusController()->focusedOrMainFrame();
  1090. return frame->eventHandler()->keyEvent(ev);
  1091. }
  1092. bool QWebPageAdapter::handleScrolling(QKeyEvent *ev)
  1093. {
  1094. Frame* frame = page->focusController()->focusedOrMainFrame();
  1095. WebCore::ScrollDirection direction;
  1096. WebCore::ScrollGranularity granularity;
  1097. #ifndef QT_NO_SHORTCUT
  1098. if (ev == QKeySequence::MoveToNextPage) {
  1099. granularity = WebCore::ScrollByPage;
  1100. direction = WebCore::ScrollDown;
  1101. } else if (ev == QKeySequence::MoveToPreviousPage) {
  1102. granularity = WebCore::ScrollByPage;
  1103. direction = WebCore::ScrollUp;
  1104. } else
  1105. #endif // QT_NO_SHORTCUT
  1106. if ((ev->key() == Qt::Key_Up && ev->modifiers() & Qt::ControlModifier) || ev->key() == Qt::Key_Home) {
  1107. granularity = WebCore::ScrollByDocument;
  1108. direction = WebCore::ScrollUp;
  1109. } else if ((ev->key() == Qt::Key_Down && ev->modifiers() & Qt::ControlModifier) || ev->key() == Qt::Key_End) {
  1110. granularity = WebCore::ScrollByDocument;
  1111. direction = WebCore::ScrollDown;
  1112. } else {
  1113. switch (ev->key()) {
  1114. case Qt::Key_Up:
  1115. granularity = WebCore::ScrollByLine;
  1116. direction = WebCore::ScrollUp;
  1117. break;
  1118. case Qt::Key_Down:
  1119. granularity = WebCore::ScrollByLine;
  1120. direction = WebCore::ScrollDown;
  1121. break;
  1122. case Qt::Key_Left:
  1123. granularity = WebCore::ScrollByLine;
  1124. direction = WebCore::ScrollLeft;
  1125. break;
  1126. case Qt::Key_Right:
  1127. granularity = WebCore::ScrollByLine;
  1128. direction = WebCore::ScrollRight;
  1129. break;
  1130. default:
  1131. return false;
  1132. }
  1133. }
  1134. return frame->eventHandler()->scrollRecursively(direction, granularity);
  1135. }
  1136. void QWebPageAdapter::focusInEvent(QFocusEvent *)
  1137. {
  1138. FocusController* focusController = page->focusController();
  1139. focusController->setActive(true);
  1140. focusController->setFocused(true);
  1141. if (!focusController->focusedFrame())
  1142. focusController->setFocusedFrame(mainFrameAdapter()->frame);
  1143. }
  1144. void QWebPageAdapter::focusOutEvent(QFocusEvent *)
  1145. {
  1146. // only set the focused frame inactive so that we stop painting the caret
  1147. // and the focus frame. But don't tell the focus controller so that upon
  1148. // focusInEvent() we can re-activate the frame.
  1149. FocusController* focusController = page->focusController();
  1150. // Call setFocused first so that window.onblur doesn't get called twice
  1151. focusController->setFocused(false);
  1152. focusController->setActive(false);
  1153. }
  1154. bool QWebPageAdapter::handleShortcutOverrideEvent(QKeyEvent* event)
  1155. {
  1156. WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
  1157. WebCore::Editor& editor = frame->editor();
  1158. if (!editor.canEdit())
  1159. return false;
  1160. if (event->modifiers() == Qt::NoModifier
  1161. || event->modifiers() == Qt::ShiftModifier
  1162. || event->modifiers() == Qt::KeypadModifier) {
  1163. if (event->key() < Qt::Key_Escape)
  1164. event->accept();
  1165. else {
  1166. switch (event->key()) {
  1167. case Qt::Key_Return:
  1168. case Qt::Key_Enter:
  1169. case Qt::Key_Delete:
  1170. case Qt::Key_Home:
  1171. case Qt::Key_End:
  1172. case Qt::Key_Backspace:
  1173. case Qt::Key_Left:
  1174. case Qt::Key_Right:
  1175. case Qt::Key_Up:
  1176. case Qt::Key_Down:
  1177. case Qt::Key_Tab:
  1178. event->accept();
  1179. default:
  1180. break;
  1181. }
  1182. }
  1183. }
  1184. return true;
  1185. }
  1186. bool QWebPageAdapter::touchEvent(QTouchEvent* event)
  1187. {
  1188. #if ENABLE(TOUCH_EVENTS)
  1189. Frame* frame = mainFrameAdapter()->frame;
  1190. if (!frame->view())
  1191. return false;
  1192. // Always accept the QTouchEvent so that we'll receive also TouchUpdate and TouchEnd events
  1193. event->setAccepted(true);
  1194. // Return whether the default action was cancelled in the JS event handler
  1195. return frame->eventHandler()->handleTouchEvent(convertTouchEvent(event));
  1196. #else
  1197. event->ignore();
  1198. return false;
  1199. #endif
  1200. }
  1201. bool QWebPageAdapter::swallowContextMenuEvent(QContextMenuEvent *event, QWebFrameAdapter *webFrame)
  1202. {
  1203. // Check the first and last enum values match at least, since we cast.
  1204. ASSERT(int(QWebPageAdapter::ScrollUp) == int(WebCore::ScrollUp));
  1205. ASSERT(int(QWebPageAdapter::ScrollRight) == int(WebCore::ScrollRight));
  1206. ASSERT(int(QWebPageAdapter::ScrollByLine) == int(WebCore::ScrollByLine));
  1207. ASSERT(int(QWebPageAdapter::ScrollByDocument) == int(WebCore::ScrollByDocument));
  1208. page->contextMenuController()->clearContextMenu();
  1209. if (webFrame) {
  1210. Frame* frame = webFrame->frame;
  1211. if (Scrollbar* scrollBar = frame->view()->scrollbarAtPoint(convertMouseEvent(event, 1).position())) {
  1212. bool horizontal = (scrollBar->orientation() == HorizontalScrollbar);
  1213. QWebPageAdapter::ScrollDirection direction = QWebPageAdapter::InvalidScrollDirection;
  1214. QWebPageAdapter::ScrollGranularity granularity = QWebPageAdapter::InvalidScrollGranularity;
  1215. bool scroll = handleScrollbarContextMenuEvent(event, horizontal, &direction, &granularity);
  1216. if (!scroll)
  1217. return true;
  1218. if (direction == QWebPageAdapter::InvalidScrollDirection || granularity == QWebPageAdapter::InvalidScrollGranularity) {
  1219. ScrollbarTheme* theme = scrollBar->theme();
  1220. // Set the pressed position to the middle of the thumb so that when we
  1221. // do move, the delta will be from the current pixel position of the
  1222. // thumb to the new position
  1223. int position = theme->trackPosition(scrollBar) + theme->thumbPosition(scrollBar) + theme->thumbLength(scrollBar) / 2;
  1224. scrollBar->setPressedPos(position);
  1225. const QPoint pos = scrollBar->convertFromContainingWindow(event->pos());
  1226. scrollBar->moveThumb(horizontal ? pos.x() : pos.y());
  1227. } else
  1228. scrollBar->scrollableArea()->scroll(WebCore::ScrollDirection(direction), WebCore::ScrollGranularity(granularity));
  1229. return true;
  1230. }
  1231. }
  1232. WebCore::Frame* focusedFrame = page->focusController()->focusedOrMainFrame();
  1233. focusedFrame->eventHandler()->sendContextMenuEvent(convertMouseEvent(event, 1));
  1234. ContextMenu* menu = page->contextMenuController()->contextMenu();
  1235. // If the website defines its own handler then sendContextMenuEvent takes care of
  1236. // calling/showing it and the context menu pointer will be zero. This is the case
  1237. // on maps.google.com for example.
  1238. return !menu;
  1239. }