|
1 /* |
|
2 * Copyright (C) 2010 Nokia Corporation 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 program 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 program; 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 |
|
21 #include "qwkpage.h" |
|
22 #include "qwkpage_p.h" |
|
23 |
|
24 #include "ClientImpl.h" |
|
25 #include "LocalizedStrings.h" |
|
26 #include "WebEventFactoryQt.h" |
|
27 #include "WKStringQt.h" |
|
28 #include "WKURLQt.h" |
|
29 #include <QAction> |
|
30 #include <QApplication> |
|
31 #include <QGraphicsSceneMouseEvent> |
|
32 #include <QStyle> |
|
33 #include <QtDebug> |
|
34 #include <WebKit2/WKFrame.h> |
|
35 #include <WebKit2/WKRetainPtr.h> |
|
36 |
|
37 using namespace WebKit; |
|
38 using namespace WebCore; |
|
39 |
|
40 QWKPagePrivate::QWKPagePrivate(QWKPage* qq, WKPageNamespaceRef namespaceRef) |
|
41 : q(qq) |
|
42 , createNewPageFn(0) |
|
43 { |
|
44 memset(actions, 0, sizeof(actions)); |
|
45 page = toWK(namespaceRef)->createWebPage(); |
|
46 page->setPageClient(this); |
|
47 } |
|
48 |
|
49 QWKPagePrivate::~QWKPagePrivate() |
|
50 { |
|
51 page->close(); |
|
52 } |
|
53 |
|
54 void QWKPagePrivate::init(const QSize& viewportSize, DrawingAreaProxy* proxy) |
|
55 { |
|
56 page->initializeWebPage(IntSize(viewportSize), proxy); |
|
57 } |
|
58 |
|
59 void QWKPagePrivate::toolTipChanged(const String&, const String& newTooltip) |
|
60 { |
|
61 emit q->statusBarMessage(QString(newTooltip)); |
|
62 } |
|
63 |
|
64 void QWKPagePrivate::paint(QPainter* painter, QRect area) |
|
65 { |
|
66 painter->save(); |
|
67 |
|
68 painter->setBrush(Qt::white); |
|
69 painter->drawRect(area); |
|
70 |
|
71 if (page->isValid() && page->drawingArea()) |
|
72 page->drawingArea()->paint(IntRect(area), painter); |
|
73 |
|
74 painter->restore(); |
|
75 } |
|
76 |
|
77 void QWKPagePrivate::keyPressEvent(QKeyEvent* ev) |
|
78 { |
|
79 WebKeyboardEvent keyboardEvent = WebEventFactory::createWebKeyboardEvent(ev); |
|
80 page->keyEvent(keyboardEvent); |
|
81 } |
|
82 |
|
83 void QWKPagePrivate::keyReleaseEvent(QKeyEvent* ev) |
|
84 { |
|
85 WebKeyboardEvent keyboardEvent = WebEventFactory::createWebKeyboardEvent(ev); |
|
86 page->keyEvent(keyboardEvent); |
|
87 } |
|
88 |
|
89 void QWKPagePrivate::mouseMoveEvent(QGraphicsSceneMouseEvent* ev) |
|
90 { |
|
91 // For some reason mouse press results in mouse hover (which is |
|
92 // converted to mouse move for WebKit). We ignore these hover |
|
93 // events by comparing lastPos with newPos. |
|
94 // NOTE: lastPos from the event always comes empty, so we work |
|
95 // around that here. |
|
96 static QPointF lastPos = QPointF(); |
|
97 if (lastPos == ev->pos()) |
|
98 return; |
|
99 lastPos = ev->pos(); |
|
100 |
|
101 WebMouseEvent mouseEvent = WebEventFactory::createWebMouseEvent(ev, 0); |
|
102 page->mouseEvent(mouseEvent); |
|
103 } |
|
104 |
|
105 void QWKPagePrivate::mousePressEvent(QGraphicsSceneMouseEvent* ev) |
|
106 { |
|
107 if (tripleClickTimer.isActive() && (ev->pos() - tripleClick).manhattanLength() < QApplication::startDragDistance()) { |
|
108 WebMouseEvent mouseEvent = WebEventFactory::createWebMouseEvent(ev, 3); |
|
109 page->mouseEvent(mouseEvent); |
|
110 return; |
|
111 } |
|
112 |
|
113 WebMouseEvent mouseEvent = WebEventFactory::createWebMouseEvent(ev, 1); |
|
114 page->mouseEvent(mouseEvent); |
|
115 } |
|
116 |
|
117 void QWKPagePrivate::mouseReleaseEvent(QGraphicsSceneMouseEvent* ev) |
|
118 { |
|
119 WebMouseEvent mouseEvent = WebEventFactory::createWebMouseEvent(ev, 0); |
|
120 page->mouseEvent(mouseEvent); |
|
121 } |
|
122 |
|
123 void QWKPagePrivate::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* ev) |
|
124 { |
|
125 WebMouseEvent mouseEvent = WebEventFactory::createWebMouseEvent(ev, 2); |
|
126 page->mouseEvent(mouseEvent); |
|
127 |
|
128 tripleClickTimer.start(QApplication::doubleClickInterval(), q); |
|
129 tripleClick = ev->pos().toPoint(); |
|
130 } |
|
131 |
|
132 void QWKPagePrivate::wheelEvent(QGraphicsSceneWheelEvent* ev) |
|
133 { |
|
134 WebWheelEvent wheelEvent = WebEventFactory::createWebWheelEvent(ev); |
|
135 page->wheelEvent(wheelEvent); |
|
136 } |
|
137 |
|
138 void QWKPagePrivate::updateAction(QWKPage::WebAction action) |
|
139 { |
|
140 #ifdef QT_NO_ACTION |
|
141 Q_UNUSED(action) |
|
142 #else |
|
143 QAction* a = actions[action]; |
|
144 if (!a) |
|
145 return; |
|
146 |
|
147 RefPtr<WebKit::WebFrameProxy> mainFrame = page->mainFrame(); |
|
148 if (!mainFrame) |
|
149 return; |
|
150 |
|
151 bool enabled = a->isEnabled(); |
|
152 bool checked = a->isChecked(); |
|
153 |
|
154 switch (action) { |
|
155 case QWKPage::Back: |
|
156 enabled = page->canGoBack(); |
|
157 break; |
|
158 case QWKPage::Forward: |
|
159 enabled = page->canGoForward(); |
|
160 break; |
|
161 case QWKPage::Stop: |
|
162 enabled = !(WebFrameProxy::LoadStateFinished == mainFrame->loadState()); |
|
163 break; |
|
164 case QWKPage::Reload: |
|
165 enabled = (WebFrameProxy::LoadStateFinished == mainFrame->loadState()); |
|
166 break; |
|
167 default: |
|
168 break; |
|
169 } |
|
170 |
|
171 a->setEnabled(enabled); |
|
172 |
|
173 if (a->isCheckable()) |
|
174 a->setChecked(checked); |
|
175 #endif // QT_NO_ACTION |
|
176 } |
|
177 |
|
178 void QWKPagePrivate::updateNavigationActions() |
|
179 { |
|
180 updateAction(QWKPage::Back); |
|
181 updateAction(QWKPage::Forward); |
|
182 updateAction(QWKPage::Stop); |
|
183 updateAction(QWKPage::Reload); |
|
184 } |
|
185 |
|
186 #ifndef QT_NO_ACTION |
|
187 void QWKPagePrivate::_q_webActionTriggered(bool checked) |
|
188 { |
|
189 QAction* a = qobject_cast<QAction*>(q->sender()); |
|
190 if (!a) |
|
191 return; |
|
192 QWKPage::WebAction action = static_cast<QWKPage::WebAction>(a->data().toInt()); |
|
193 q->triggerAction(action, checked); |
|
194 } |
|
195 #endif // QT_NO_ACTION |
|
196 |
|
197 QWKPage::QWKPage(WKPageNamespaceRef namespaceRef) |
|
198 : d(new QWKPagePrivate(this, namespaceRef)) |
|
199 { |
|
200 WKPageLoaderClient loadClient = { |
|
201 0, /* version */ |
|
202 this, /* clientInfo */ |
|
203 qt_wk_didStartProvisionalLoadForFrame, |
|
204 qt_wk_didReceiveServerRedirectForProvisionalLoadForFrame, |
|
205 qt_wk_didFailProvisionalLoadWithErrorForFrame, |
|
206 qt_wk_didCommitLoadForFrame, |
|
207 qt_wk_didFinishLoadForFrame, |
|
208 qt_wk_didFailLoadWithErrorForFrame, |
|
209 qt_wk_didReceiveTitleForFrame, |
|
210 qt_wk_didFirstLayoutForFrame, |
|
211 qt_wk_didFirstVisuallyNonEmptyLayoutForFrame, |
|
212 qt_wk_didStartProgress, |
|
213 qt_wk_didChangeProgress, |
|
214 qt_wk_didFinishProgress, |
|
215 qt_wk_didBecomeUnresponsive, |
|
216 qt_wk_didBecomeResponsive |
|
217 }; |
|
218 WKPageSetPageLoaderClient(pageRef(), &loadClient); |
|
219 |
|
220 WKPageUIClient uiClient = { |
|
221 0, /* version */ |
|
222 this, /* clientInfo */ |
|
223 qt_wk_createNewPage, |
|
224 qt_wk_showPage, |
|
225 qt_wk_close, |
|
226 qt_wk_runJavaScriptAlert, |
|
227 }; |
|
228 WKPageSetPageUIClient(pageRef(), &uiClient); |
|
229 } |
|
230 |
|
231 QWKPage::~QWKPage() |
|
232 { |
|
233 delete d; |
|
234 WKPageTerminate(pageRef()); |
|
235 } |
|
236 |
|
237 void QWKPage::timerEvent(QTimerEvent* ev) |
|
238 { |
|
239 int timerId = ev->timerId(); |
|
240 if (timerId == d->tripleClickTimer.timerId()) |
|
241 d->tripleClickTimer.stop(); |
|
242 else |
|
243 QObject::timerEvent(ev); |
|
244 } |
|
245 |
|
246 WKPageRef QWKPage::pageRef() const |
|
247 { |
|
248 return toRef(d->page.get()); |
|
249 } |
|
250 |
|
251 void QWKPage::setCreateNewPageFunction(CreateNewPageFn function) |
|
252 { |
|
253 d->createNewPageFn = function; |
|
254 } |
|
255 |
|
256 void QWKPage::load(const QUrl& url) |
|
257 { |
|
258 WKRetainPtr<WKURLRef> wkurl(WKURLCreateWithQUrl(url)); |
|
259 WKPageLoadURL(pageRef(), wkurl.get()); |
|
260 } |
|
261 |
|
262 void QWKPage::setUrl(const QUrl& url) |
|
263 { |
|
264 load(url); |
|
265 } |
|
266 |
|
267 QUrl QWKPage::url() const |
|
268 { |
|
269 WKRetainPtr<WKFrameRef> frame = WKPageGetMainFrame(pageRef()); |
|
270 if (!frame) |
|
271 return QUrl(); |
|
272 return WKURLCopyQUrl(WKFrameGetURL(frame.get())); |
|
273 } |
|
274 |
|
275 QString QWKPage::title() const |
|
276 { |
|
277 return WKStringCopyQString(WKPageGetTitle(pageRef())); |
|
278 } |
|
279 |
|
280 void QWKPage::setViewportSize(const QSize& size) |
|
281 { |
|
282 if (d->page->drawingArea()) |
|
283 d->page->drawingArea()->setSize(IntSize(size)); |
|
284 } |
|
285 |
|
286 #ifndef QT_NO_ACTION |
|
287 void QWKPage::triggerAction(WebAction action, bool) |
|
288 { |
|
289 switch (action) { |
|
290 case Back: |
|
291 d->page->goBack(); |
|
292 break; |
|
293 case Forward: |
|
294 d->page->goForward(); |
|
295 break; |
|
296 case Stop: |
|
297 d->page->stopLoading(); |
|
298 break; |
|
299 case Reload: |
|
300 d->page->reload(/* reloadFromOrigin */ true); |
|
301 break; |
|
302 default: |
|
303 break; |
|
304 } |
|
305 } |
|
306 #endif // QT_NO_ACTION |
|
307 |
|
308 #ifndef QT_NO_ACTION |
|
309 QAction* QWKPage::action(WebAction action) const |
|
310 { |
|
311 if (action == QWKPage::NoWebAction || action >= WebActionCount) |
|
312 return 0; |
|
313 |
|
314 if (d->actions[action]) |
|
315 return d->actions[action]; |
|
316 |
|
317 QString text; |
|
318 QIcon icon; |
|
319 QStyle* style = qobject_cast<QApplication*>(QCoreApplication::instance())->style(); |
|
320 bool checkable = false; |
|
321 |
|
322 switch (action) { |
|
323 case Back: |
|
324 text = contextMenuItemTagGoBack(); |
|
325 icon = style->standardIcon(QStyle::SP_ArrowBack); |
|
326 break; |
|
327 case Forward: |
|
328 text = contextMenuItemTagGoForward(); |
|
329 icon = style->standardIcon(QStyle::SP_ArrowForward); |
|
330 break; |
|
331 case Stop: |
|
332 text = contextMenuItemTagStop(); |
|
333 icon = style->standardIcon(QStyle::SP_BrowserStop); |
|
334 break; |
|
335 case Reload: |
|
336 text = contextMenuItemTagReload(); |
|
337 icon = style->standardIcon(QStyle::SP_BrowserReload); |
|
338 break; |
|
339 default: |
|
340 return 0; |
|
341 break; |
|
342 } |
|
343 |
|
344 if (text.isEmpty()) |
|
345 return 0; |
|
346 |
|
347 QAction* a = new QAction(d->q); |
|
348 a->setText(text); |
|
349 a->setData(action); |
|
350 a->setCheckable(checkable); |
|
351 a->setIcon(icon); |
|
352 |
|
353 connect(a, SIGNAL(triggered(bool)), this, SLOT(_q_webActionTriggered(bool))); |
|
354 |
|
355 d->actions[action] = a; |
|
356 d->updateAction(action); |
|
357 return a; |
|
358 } |
|
359 #endif // QT_NO_ACTION |
|
360 |
|
361 #include "moc_qwkpage.cpp" |