summaryrefslogtreecommitdiffstats
path: root/Source/WebKit2/UIProcess/API/qt/qgraphicswkview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebKit2/UIProcess/API/qt/qgraphicswkview.cpp')
-rw-r--r--Source/WebKit2/UIProcess/API/qt/qgraphicswkview.cpp442
1 files changed, 442 insertions, 0 deletions
diff --git a/Source/WebKit2/UIProcess/API/qt/qgraphicswkview.cpp b/Source/WebKit2/UIProcess/API/qt/qgraphicswkview.cpp
new file mode 100644
index 0000000..f01c5b2
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/qt/qgraphicswkview.cpp
@@ -0,0 +1,442 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "qgraphicswkview.h"
+
+#include "ChunkedUpdateDrawingAreaProxy.h"
+#include "IntSize.h"
+#include "RunLoop.h"
+#include "TiledDrawingAreaProxy.h"
+#include "UpdateChunk.h"
+#include "WKAPICast.h"
+#include "qwkpage.h"
+#include "qwkpage_p.h"
+#include <QApplication>
+#include <QCursor>
+#include <QGraphicsSceneMouseEvent>
+#include <QGraphicsView>
+#include <QMenu>
+#include <QPainter>
+#include <QScrollBar>
+#include <QStyleOptionGraphicsItem>
+#include <QUrl>
+#include <QtDebug>
+#include <WebKit2/WKRetainPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/WTFString.h>
+
+using namespace WebKit;
+using namespace WebCore;
+
+struct QGraphicsWKViewPrivate {
+ QGraphicsWKViewPrivate(QGraphicsWKView* view);
+ WKPageRef pageRef() const { return page->pageRef(); }
+
+ void onScaleChanged();
+ void commitScale();
+
+ QGraphicsWKView* q;
+ QWKPage* page;
+ QMenu* activeMenu;
+ RunLoop::Timer<QGraphicsWKViewPrivate> m_scaleCommitTimer;
+ bool m_isChangingScale;
+};
+
+QGraphicsWKView::QGraphicsWKView(QWKContext* context, BackingStoreType backingStoreType, QGraphicsItem* parent)
+ : QGraphicsWidget(parent)
+ , d(new QGraphicsWKViewPrivate(this))
+{
+ setFocusPolicy(Qt::StrongFocus);
+ setAcceptHoverEvents(true);
+
+ PassOwnPtr<DrawingAreaProxy> drawingAreaProxy;
+
+ d->page = new QWKPage(context);
+
+ switch (backingStoreType) {
+#if ENABLE(TILED_BACKING_STORE)
+ case Tiled:
+ drawingAreaProxy = TiledDrawingAreaProxy::create(this, toImpl(page()->pageRef()));
+ connect(this, SIGNAL(scaleChanged()), this, SLOT(onScaleChanged()));
+ break;
+#endif
+ case Simple:
+ default:
+ drawingAreaProxy = ChunkedUpdateDrawingAreaProxy::create(this, toImpl(page()->pageRef()));
+ break;
+ }
+
+ d->page->d->init(this, drawingAreaProxy);
+ connect(d->page, SIGNAL(titleChanged(QString)), this, SIGNAL(titleChanged(QString)));
+ connect(d->page, SIGNAL(loadStarted()), this, SIGNAL(loadStarted()));
+ connect(d->page, SIGNAL(loadFinished(bool)), this, SIGNAL(loadFinished(bool)));
+ connect(d->page, SIGNAL(loadProgress(int)), this, SIGNAL(loadProgress(int)));
+ connect(d->page, SIGNAL(initialLayoutCompleted()), this, SIGNAL(initialLayoutCompleted()));
+ connect(d->page, SIGNAL(urlChanged(const QUrl&)), this, SIGNAL(urlChanged(const QUrl&)));
+ connect(d->page, SIGNAL(cursorChanged(const QCursor&)), this, SLOT(updateCursor(const QCursor&)));
+ connect(d->page, SIGNAL(focusNextPrevChild(bool)), this, SLOT(focusNextPrevChildCallback(bool)));
+ connect(d->page, SIGNAL(showContextMenu(QMenu*)), this, SLOT(showContextMenu(QMenu*)));
+}
+
+QGraphicsWKView::~QGraphicsWKView()
+{
+ delete d->page;
+ delete d;
+}
+
+QWKPage* QGraphicsWKView::page() const
+{
+ return d->page;
+}
+
+void QGraphicsWKView::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget*)
+{
+ page()->d->paint(painter, option->exposedRect.toAlignedRect());
+}
+
+void QGraphicsWKView::setGeometry(const QRectF& rect)
+{
+ QSizeF oldSize = geometry().size();
+ QGraphicsWidget::setGeometry(rect);
+ if (geometry().size() == oldSize)
+ return;
+
+ // NOTE: call geometry() as setGeometry ensures that
+ // the geometry is within legal bounds (minimumSize, maximumSize)
+ page()->setViewportSize(geometry().size().toSize());
+}
+
+void QGraphicsWKView::load(const QUrl& url)
+{
+ page()->load(url);
+}
+
+void QGraphicsWKView::setUrl(const QUrl& url)
+{
+ page()->setUrl(url);
+}
+
+QUrl QGraphicsWKView::url() const
+{
+ return page()->url();
+}
+
+QString QGraphicsWKView::title() const
+{
+ return page()->title();
+}
+
+void QGraphicsWKView::triggerPageAction(QWKPage::WebAction action, bool checked)
+{
+ page()->triggerAction(action, checked);
+}
+
+void QGraphicsWKView::back()
+{
+ page()->triggerAction(QWKPage::Back);
+}
+
+void QGraphicsWKView::forward()
+{
+ page()->triggerAction(QWKPage::Forward);
+}
+
+void QGraphicsWKView::reload()
+{
+ page()->triggerAction(QWKPage::Reload);
+}
+
+void QGraphicsWKView::stop()
+{
+ page()->triggerAction(QWKPage::Stop);
+}
+
+void QGraphicsWKView::updateCursor(const QCursor& cursor)
+{
+ setCursor(cursor);
+}
+
+class FriendlyWidget : public QWidget
+{
+public:
+ bool focusNextPrevChild(bool next);
+};
+
+void QGraphicsWKView::focusNextPrevChildCallback(bool next)
+{
+ if (hasFocus()) {
+ // find the view which has the focus:
+ QList<QGraphicsView*> views = scene()->views();
+ const int viewCount = views.count();
+ QGraphicsView* focusedView = 0;
+ for (int i = 0; i < viewCount; ++i) {
+ if (views[i]->hasFocus()) {
+ focusedView = views[i];
+ break;
+ }
+ }
+
+ if (focusedView) {
+ QWidget* window = focusedView->window();
+ FriendlyWidget* friendlyWindow = static_cast<FriendlyWidget*>(window);
+ friendlyWindow->focusNextPrevChild(next);
+ }
+ }
+}
+
+/*! \reimp
+*/
+bool QGraphicsWKView::focusNextPrevChild(bool next)
+{
+ QKeyEvent ev(QEvent::KeyPress, Qt::Key_Tab, Qt::KeyboardModifiers(next ? Qt::NoModifier : Qt::ShiftModifier));
+ page()->d->keyPressEvent(&ev);
+ return true;
+}
+
+/*! \reimp
+*/
+QVariant QGraphicsWKView::itemChange(GraphicsItemChange change, const QVariant& value)
+{
+ // Here so that it can be reimplemented without breaking ABI.
+ return QGraphicsWidget::itemChange(change, value);
+}
+
+/*! \reimp
+*/
+bool QGraphicsWKView::event(QEvent* event)
+{
+ QEvent::Type eventType = event->type();
+ switch (eventType) {
+ case QEvent::TouchBegin:
+ case QEvent::TouchEnd:
+ case QEvent::TouchUpdate:
+ touchEvent(static_cast<QTouchEvent*>(event));
+ return true;
+ case QEvent::Show:
+ page()->d->page->drawingArea()->setPageIsVisible(true);
+ break;
+ case QEvent::Hide:
+ page()->d->page->drawingArea()->setPageIsVisible(false);
+ break;
+ default:
+ break;
+ }
+
+ // Here so that it can be reimplemented without breaking ABI.
+ return QGraphicsWidget::event(event);
+}
+
+/*! \reimp
+*/
+QSizeF QGraphicsWKView::sizeHint(Qt::SizeHint which, const QSizeF& constraint) const
+{
+ if (which == Qt::PreferredSize)
+ return QSizeF(800, 600);
+ return QGraphicsWidget::sizeHint(which, constraint);
+}
+
+/*! \reimp
+*/
+QVariant QGraphicsWKView::inputMethodQuery(Qt::InputMethodQuery query) const
+{
+ // implement
+ return QVariant();
+}
+
+/*! \reimp
+*/
+void QGraphicsWKView::keyPressEvent(QKeyEvent* ev)
+{
+ page()->d->keyPressEvent(ev);
+}
+
+/*! \reimp
+*/
+void QGraphicsWKView::keyReleaseEvent(QKeyEvent* ev)
+{
+ page()->d->keyReleaseEvent(ev);
+}
+
+void QGraphicsWKView::hoverMoveEvent(QGraphicsSceneHoverEvent* ev)
+{
+ QGraphicsSceneMouseEvent me(QEvent::GraphicsSceneMouseMove);
+ me.setPos(ev->pos());
+ me.setScreenPos(ev->screenPos());
+
+ page()->d->mouseMoveEvent(&me);
+
+ if (!ev->isAccepted())
+ QGraphicsItem::hoverMoveEvent(ev);
+}
+
+void QGraphicsWKView::mouseMoveEvent(QGraphicsSceneMouseEvent* ev)
+{
+ page()->d->mouseMoveEvent(ev);
+ if (!ev->isAccepted())
+ QGraphicsItem::mouseMoveEvent(ev);
+}
+
+void QGraphicsWKView::mousePressEvent(QGraphicsSceneMouseEvent* ev)
+{
+ page()->d->mousePressEvent(ev);
+ if (!ev->isAccepted())
+ QGraphicsItem::mousePressEvent(ev);
+}
+
+void QGraphicsWKView::mouseReleaseEvent(QGraphicsSceneMouseEvent* ev)
+{
+ page()->d->mouseReleaseEvent(ev);
+ if (!ev->isAccepted())
+ QGraphicsItem::mouseReleaseEvent(ev);
+}
+
+void QGraphicsWKView::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* ev)
+{
+ page()->d->mouseDoubleClickEvent(ev);
+ if (!ev->isAccepted())
+ QGraphicsItem::mouseReleaseEvent(ev);
+}
+
+void QGraphicsWKView::wheelEvent(QGraphicsSceneWheelEvent* ev)
+{
+ page()->d->wheelEvent(ev);
+ if (!ev->isAccepted())
+ QGraphicsItem::wheelEvent(ev);
+}
+
+void QGraphicsWKView::touchEvent(QTouchEvent* ev)
+{
+ page()->d->touchEvent(ev);
+}
+
+void QGraphicsWKView::focusInEvent(QFocusEvent*)
+{
+ page()->d->page->viewStateDidChange(WebPageProxy::ViewIsFocused | WebPageProxy::ViewWindowIsActive);
+}
+
+void QGraphicsWKView::focusOutEvent(QFocusEvent*)
+{
+ page()->d->page->viewStateDidChange(WebPageProxy::ViewIsFocused | WebPageProxy::ViewWindowIsActive);
+}
+
+void QGraphicsWKView::showContextMenu(QMenu* menu)
+{
+ // Remove the active menu in case this function is called twice.
+ if (d->activeMenu)
+ d->activeMenu->hide();
+
+ d->activeMenu = menu;
+
+ QWidget* view = 0;
+ if (QGraphicsScene* myScene = scene()) {
+ const QList<QGraphicsView*> views = myScene->views();
+ for (unsigned i = 0; i < views.size(); ++i) {
+ if (views.at(i) == QApplication::focusWidget()) {
+ view = views.at(i);
+ break;
+ }
+ }
+ if (!view)
+ view = views.value(0, 0);
+ }
+ if (view)
+ menu->setParent(view, menu->windowFlags());
+ menu->exec(view->mapToGlobal(menu->pos()));
+ if (d->activeMenu == menu)
+ d->activeMenu = 0;
+}
+
+void QGraphicsWKView::takeSnapshot(const QSize& size, const QRect& contentsRect)
+{
+#if ENABLE(TILED_BACKING_STORE)
+ DrawingAreaProxy* drawingArea = page()->d->page->drawingArea();
+ if (drawingArea->info().type != DrawingAreaInfo::Tiled)
+ return;
+ TiledDrawingAreaProxy* tiledDrawingArea = static_cast<TiledDrawingAreaProxy*>(drawingArea);
+ tiledDrawingArea->takeSnapshot(size, contentsRect);
+#endif
+}
+
+QGraphicsWKViewPrivate::QGraphicsWKViewPrivate(QGraphicsWKView* view)
+ : q(view)
+ , activeMenu(0)
+ , m_scaleCommitTimer(RunLoop::current(), this, &QGraphicsWKViewPrivate::commitScale)
+ , m_isChangingScale(false)
+{
+}
+
+QRectF QGraphicsWKView::visibleRect() const
+{
+ if (!scene())
+ return QRectF();
+
+ QList<QGraphicsView*> views = scene()->views();
+ if (views.isEmpty())
+ return QRectF();
+
+ QGraphicsView* graphicsView = views.at(0);
+ int xOffset = graphicsView->horizontalScrollBar()->value();
+ int yOffset = graphicsView->verticalScrollBar()->value();
+ return mapRectFromScene(QRectF(QPointF(xOffset, yOffset), graphicsView->viewport()->size()));
+}
+
+void QGraphicsWKView::prepareScaleChange()
+{
+#if ENABLE(TILED_BACKING_STORE)
+ ASSERT(!d->m_isChangingScale);
+ d->m_isChangingScale = true;
+ d->m_scaleCommitTimer.stop();
+#endif
+}
+
+void QGraphicsWKView::commitScaleChange()
+{
+#if ENABLE(TILED_BACKING_STORE)
+ ASSERT(d->m_isChangingScale);
+ d->m_isChangingScale = false;
+ d->commitScale();
+#endif
+}
+
+void QGraphicsWKViewPrivate::onScaleChanged()
+{
+#if ENABLE(TILED_BACKING_STORE)
+ if (!m_isChangingScale)
+ m_scaleCommitTimer.startOneShot(0.1);
+#endif
+}
+
+void QGraphicsWKViewPrivate::commitScale()
+{
+#if ENABLE(TILED_BACKING_STORE)
+ DrawingAreaProxy* drawingArea = page->d->page->drawingArea();
+ float newScale = q->scale();
+ if (drawingArea->info().type == DrawingAreaInfo::Tiled) {
+ TiledDrawingAreaProxy* tiledDrawingArea = static_cast<TiledDrawingAreaProxy*>(drawingArea);
+ if (tiledDrawingArea->contentsScale() == newScale)
+ return;
+ tiledDrawingArea->setContentsScale(newScale);
+ // For now we block until complete.
+ tiledDrawingArea->waitUntilUpdatesComplete();
+ }
+#endif
+}
+
+#include "moc_qgraphicswkview.cpp"