[Qt] [WK2] Improve position of context menu for QDesktopWebView
[WebKit-https.git] / Source / WebKit2 / UIProcess / API / qt / qdesktopwebview.cpp
1 /*
2  * Copyright (C) 2011 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 "config.h"
22 #include "qdesktopwebview.h"
23 #include "qdesktopwebview_p.h"
24 #include "qwkcontext.h"
25
26 #include <QGraphicsSceneResizeEvent>
27 #include <QStyleOptionGraphicsItem>
28 #include <QtDeclarative/qsgcanvas.h>
29 #include <QtDeclarative/qsgevent.h>
30 #include <QtDeclarative/qsgitem.h>
31 #include <QtGui/QCursor>
32 #include <QtGui/QFocusEvent>
33 #include <QtGui/QGraphicsSceneEvent>
34 #include <QtGui/QHoverEvent>
35 #include <QtGui/QInputMethodEvent>
36 #include <QtGui/QKeyEvent>
37 #include <QtGui/QTouchEvent>
38 #include <QtGui/QWheelEvent>
39
40 QDesktopWebViewPrivate::QDesktopWebViewPrivate(QDesktopWebView* q, WKContextRef contextRef, WKPageGroupRef pageGroupRef)
41     : q(q)
42     , page(this, contextRef ? new QWKContext(contextRef) : defaultWKContext(), pageGroupRef)
43     , isCrashed(false)
44 {
45 }
46
47 void QDesktopWebViewPrivate::setViewNeedsDisplay(const QRect& invalidatedArea)
48 {
49     q->update(invalidatedArea);
50 }
51
52 QSize QDesktopWebViewPrivate::drawingAreaSize()
53 {
54     return QSize(q->width(), q->height());
55 }
56
57 void QDesktopWebViewPrivate::contentSizeChanged(const QSize&)
58 {
59 }
60
61 bool QDesktopWebViewPrivate::isActive()
62 {
63     // FIXME: The scene graph did not have the concept of being active or not when this was written.
64     return true;
65 }
66
67 bool QDesktopWebViewPrivate::hasFocus()
68 {
69     return q->hasFocus();
70 }
71
72 bool QDesktopWebViewPrivate::isVisible()
73 {
74     return q->isVisible();
75 }
76
77 void QDesktopWebViewPrivate::startDrag(Qt::DropActions supportedDropActions, const QImage& dragImage, QMimeData* data, QPoint* clientPosition, QPoint* globalPosition, Qt::DropAction* dropAction)
78 {
79     QWidget* widget = q->canvas();
80     if (!widget)
81         return;
82
83     QDrag* drag = new QDrag(widget);
84     drag->setPixmap(QPixmap::fromImage(dragImage));
85     drag->setMimeData(data);
86     *dropAction = drag->exec(supportedDropActions);
87     *globalPosition = QCursor::pos();
88     *clientPosition = widget->mapFromGlobal(*globalPosition);
89 }
90
91 void QDesktopWebViewPrivate::didChangeUrl(const QUrl& url)
92 {
93     emit q->urlChanged(url);
94 }
95
96 void QDesktopWebViewPrivate::didChangeTitle(const QString& newTitle)
97 {
98     emit q->titleChanged(newTitle);
99 }
100
101 void QDesktopWebViewPrivate::didChangeToolTip(const QString& newToolTip)
102 {
103     // FIXME: Add a proper implementation when Qt 5 supports tooltip.
104     q->canvas()->setToolTip(newToolTip);
105 }
106
107 void QDesktopWebViewPrivate::didChangeStatusText(const QString& newMessage)
108 {
109     emit q->statusBarMessageChanged(newMessage);
110 }
111
112 void QDesktopWebViewPrivate::didChangeCursor(const QCursor& newCursor)
113 {
114     // FIXME: add proper cursor handling when Qt 5 supports it.
115     q->canvas()->setCursor(newCursor);
116 }
117
118 void QDesktopWebViewPrivate::loadDidBegin()
119 {
120     emit q->loadStarted();
121 }
122
123 void QDesktopWebViewPrivate::loadDidSucceed()
124 {
125     emit q->loadSucceeded();
126 }
127
128 void QDesktopWebViewPrivate::loadDidFail(const QWebError& error)
129 {
130     emit q->loadFailed(error);
131 }
132
133 void QDesktopWebViewPrivate::didChangeLoadProgress(int percentageLoaded)
134 {
135     emit q->loadProgressChanged(percentageLoaded);
136 }
137
138 void QDesktopWebViewPrivate::showContextMenu(QSharedPointer<QMenu> menu)
139 {
140     // Remove the active menu in case this function is called twice.
141     if (activeMenu)
142         activeMenu->hide();
143
144     if (menu->isEmpty())
145         return;
146
147     QWidget* widget = q->canvas();
148     if (!widget)
149         return;
150
151     activeMenu = menu;
152
153     menu->setParent(widget, menu->windowFlags());
154     QPoint menuPositionInScene = q->mapToScene(menu->pos()).toPoint();
155     menu->exec(widget->mapToGlobal(menuPositionInScene));
156     // The last function to get out of exec() clear the local copy.
157     if (activeMenu == menu)
158         activeMenu.clear();
159 }
160
161 void QDesktopWebViewPrivate::hideContextMenu()
162 {
163     if (activeMenu)
164         activeMenu->hide();
165 }
166
167 QDesktopWebView::QDesktopWebView(QSGItem* parent)
168     : QSGPaintedItem(parent)
169     , d(new QDesktopWebViewPrivate(this))
170 {
171     init();
172 }
173
174 QDesktopWebView::QDesktopWebView(WKContextRef contextRef, WKPageGroupRef pageGroupRef, QSGItem* parent)
175     : QSGPaintedItem(parent)
176     , d(new QDesktopWebViewPrivate(this, contextRef, pageGroupRef))
177 {
178     init();
179 }
180
181 void QDesktopWebView::init()
182 {
183     setAcceptedMouseButtons(Qt::MouseButtonMask);
184     setAcceptHoverEvents(true);
185 }
186
187 QDesktopWebView::~QDesktopWebView()
188 {
189     delete d;
190 }
191
192 void QDesktopWebView::load(const QUrl& url)
193 {
194     d->page.load(url);
195 }
196
197 QUrl QDesktopWebView::url() const
198 {
199     return d->page.url();
200 }
201
202 int QDesktopWebView::loadProgress() const
203 {
204     return d->page.loadProgress();
205 }
206
207 QString QDesktopWebView::title() const
208 {
209     return d->page.title();
210 }
211
212 QAction* QDesktopWebView::navigationAction(QtWebKit::NavigationAction which) const
213 {
214     return d->page.navigationAction(which);
215 }
216
217 static void paintCrashedPage(QPainter* painter, const QRectF& rect)
218 {
219     painter->fillRect(rect, Qt::gray);
220     painter->drawText(rect, Qt::AlignCenter, QLatin1String(":("));
221 }
222
223 void QDesktopWebView::keyPressEvent(QKeyEvent* event)
224 {
225     this->event(event);
226 }
227
228 void QDesktopWebView::keyReleaseEvent(QKeyEvent* event)
229 {
230     this->event(event);
231 }
232
233 void QDesktopWebView::inputMethodEvent(QInputMethodEvent* event)
234 {
235     this->event(event);
236 }
237
238 void QDesktopWebView::focusInEvent(QFocusEvent* event)
239 {
240     this->event(event);
241 }
242
243 void QDesktopWebView::focusOutEvent(QFocusEvent* event)
244 {
245     this->event(event);
246 }
247
248 void QDesktopWebView::mousePressEvent(QGraphicsSceneMouseEvent* event)
249 {
250     this->event(event);
251 }
252
253 void QDesktopWebView::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
254 {
255     this->event(event);
256 }
257
258 void QDesktopWebView::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
259 {
260     this->event(event);
261 }
262
263 void QDesktopWebView::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
264 {
265     this->event(event);
266 }
267
268 void QDesktopWebView::wheelEvent(QWheelEvent* event)
269 {
270     // FIXME: for some reason, the scene graph delivers QWheelEvent instead of QGraphicsSceneWheelEvent.
271     // We transform them in QGraphicsSceneWheelEvent for consistency. Otherwise the position would be complete magic.
272     // We shoud modify the scenegraph to get the correct type of events.
273     QGraphicsSceneWheelEvent graphicsEvent(QEvent::GraphicsSceneWheel);
274     graphicsEvent.setPos(event->pos());
275     graphicsEvent.setButtons(event->buttons());
276     graphicsEvent.setDelta(event->delta());
277     graphicsEvent.setModifiers(event->modifiers());
278     graphicsEvent.setOrientation(event->orientation());
279     graphicsEvent.setScenePos(mapToScene(event->pos()));
280     graphicsEvent.setScreenPos(event->globalPos());
281     this->event(&graphicsEvent);
282 }
283
284 void QDesktopWebView::touchEvent(QTouchEvent* event)
285 {
286     this->event(event);
287 }
288
289 void QDesktopWebView::hoverEnterEvent(QHoverEvent* event)
290 {
291     this->event(event);
292 }
293
294 void QDesktopWebView::hoverMoveEvent(QHoverEvent* event)
295 {
296     this->event(event);
297 }
298
299 void QDesktopWebView::hoverLeaveEvent(QHoverEvent* event)
300 {
301     this->event(event);
302 }
303
304 void QDesktopWebView::dragMoveEvent(QSGDragEvent* event)
305 {
306     this->event(event);
307 }
308
309 void QDesktopWebView::dragEnterEvent(QSGDragEvent* event)
310 {
311     this->event(event);
312 }
313
314 void QDesktopWebView::dragExitEvent(QSGDragEvent* event)
315 {
316     this->event(event);
317 }
318
319 void QDesktopWebView::dragDropEvent(QSGDragEvent* event)
320 {
321     this->event(event);
322 }
323
324 void QDesktopWebView::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry)
325 {
326     QSGPaintedItem::geometryChanged(newGeometry, oldGeometry);
327     if (newGeometry.size() != oldGeometry.size())
328         d->page.setDrawingAreaSize(newGeometry.size().toSize());
329 }
330
331 void QDesktopWebView::paint(QPainter* painter)
332 {
333     const QRectF rect = boundingRect();
334     if (d->isCrashed) {
335         paintCrashedPage(painter, rect);
336         return;
337     }
338
339     d->page.paint(painter, rect.toAlignedRect());
340 }
341
342 bool QDesktopWebView::event(QEvent* ev)
343 {
344     if (d->page.handleEvent(ev))
345         return true;
346     return QSGItem::event(ev);
347 }
348
349 WKPageRef QDesktopWebView::pageRef() const
350 {
351     return d->page.pageRef();
352 }
353
354 void QDesktopWebViewPrivate::processDidCrash()
355 {
356     isCrashed = true;
357     q->update();
358 }
359
360 void QDesktopWebViewPrivate::didRelaunchProcess()
361 {
362     isCrashed = false;
363     q->update();
364 }
365
366 #include "moc_qdesktopwebview.cpp"