Home | History | Annotate | Download | only in WebCoreSupport
      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 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 
     21 #include "config.h"
     22 
     23 #include "PageClientQt.h"
     24 #include "TextureMapperQt.h"
     25 #include "texmap/TextureMapperPlatformLayer.h"
     26 #include <QGraphicsScene>
     27 #include <QGraphicsView>
     28 #if defined(Q_WS_X11)
     29 #include <QX11Info>
     30 #endif
     31 
     32 #ifdef QT_OPENGL_LIB
     33 #include "opengl/TextureMapperGL.h"
     34 #include <QGLWidget>
     35 #endif
     36 
     37 namespace WebCore {
     38 
     39 #if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
     40 class PlatformLayerProxyQt : public QObject, public virtual TextureMapperLayerClient {
     41 public:
     42     PlatformLayerProxyQt(QWebFrame* frame, TextureMapperContentLayer* layer, QObject* object)
     43         : QObject(object)
     44         , m_frame(frame)
     45         , m_layer(layer)
     46     {
     47         if (m_layer)
     48             m_layer->setPlatformLayerClient(this);
     49         m_frame->d->rootGraphicsLayer = m_layer;
     50     }
     51 
     52     void setTextureMapper(PassOwnPtr<TextureMapper> textureMapper)
     53     {
     54         m_frame->d->textureMapper = textureMapper;
     55     }
     56 
     57     virtual ~PlatformLayerProxyQt()
     58     {
     59         if (m_layer)
     60             m_layer->setPlatformLayerClient(0);
     61         if (m_frame->d)
     62             m_frame->d->rootGraphicsLayer = 0;
     63     }
     64 
     65     virtual TextureMapper* textureMapper()
     66     {
     67         return m_frame->d->textureMapper.get();
     68     }
     69 
     70     // Since we just paint the composited tree and never create a special item for it, we don't have to handle its size changes.
     71     void setSizeChanged(const IntSize&) { }
     72 
     73 private:
     74     QWebFrame* m_frame;
     75     TextureMapperContentLayer* m_layer;
     76 };
     77 
     78 class PlatformLayerProxyQWidget : public PlatformLayerProxyQt {
     79 public:
     80     PlatformLayerProxyQWidget(QWebFrame* frame, TextureMapperContentLayer* layer, QWidget* widget)
     81         : PlatformLayerProxyQt(frame, layer, widget)
     82         , m_widget(widget)
     83     {
     84         if (m_widget)
     85             m_widget->installEventFilter(this);
     86 
     87         if (textureMapper())
     88             return;
     89 
     90         setTextureMapper(TextureMapperQt::create());
     91     }
     92 
     93     // We don't want a huge region-clip on the compositing layers; instead we unite the rectangles together
     94     // and clear them when the paint actually occurs.
     95     bool eventFilter(QObject* object, QEvent* event)
     96     {
     97         if (object == m_widget && event->type() == QEvent::Paint)
     98             m_dirtyRect = QRect();
     99         return QObject::eventFilter(object, event);
    100     }
    101 
    102     void setNeedsDisplay()
    103     {
    104         if (m_widget)
    105             m_widget->update();
    106     }
    107 
    108     void setNeedsDisplayInRect(const IntRect& rect)
    109     {
    110         m_dirtyRect |= rect;
    111         m_widget->update(m_dirtyRect);
    112     }
    113 
    114 private:
    115     QRect m_dirtyRect;
    116     QWidget* m_widget;
    117 };
    118 
    119 #if !defined(QT_NO_GRAPHICSVIEW)
    120 class PlatformLayerProxyQGraphicsObject : public PlatformLayerProxyQt {
    121 public:
    122     PlatformLayerProxyQGraphicsObject(QWebFrame* frame, TextureMapperContentLayer* layer, QGraphicsObject* object)
    123         : PlatformLayerProxyQt(frame, layer, object)
    124         , m_graphicsItem(object)
    125     {
    126         if (textureMapper())
    127             return;
    128 
    129 #ifdef QT_OPENGL_LIB
    130         QGraphicsView* view = object->scene()->views()[0];
    131         if (view && view->viewport() && view->viewport()->inherits("QGLWidget")) {
    132             setTextureMapper(TextureMapperGL::create());
    133             return;
    134         }
    135 #endif
    136         setTextureMapper(TextureMapperQt::create());
    137     }
    138 
    139     void setNeedsDisplay()
    140     {
    141         if (m_graphicsItem)
    142             m_graphicsItem->update();
    143     }
    144 
    145     void setNeedsDisplayInRect(const IntRect& rect)
    146     {
    147         if (m_graphicsItem)
    148             m_graphicsItem->update(QRectF(rect));
    149     }
    150 
    151 private:
    152     QGraphicsItem* m_graphicsItem;
    153 };
    154 #endif // QT_NO_GRAPHICSVIEW
    155 
    156 void PageClientQWidget::setRootGraphicsLayer(TextureMapperPlatformLayer* layer)
    157 {
    158     if (layer) {
    159         platformLayerProxy = new PlatformLayerProxyQWidget(page->mainFrame(), static_cast<TextureMapperContentLayer*>(layer), view);
    160         return;
    161     }
    162     delete platformLayerProxy;
    163     platformLayerProxy = 0;
    164 }
    165 
    166 void PageClientQWidget::markForSync(bool scheduleSync)
    167 {
    168     syncTimer.startOneShot(0);
    169 }
    170 
    171 void PageClientQWidget::syncLayers(Timer<PageClientQWidget>*)
    172 {
    173     QWebFramePrivate::core(page->mainFrame())->view()->syncCompositingStateIncludingSubframes();
    174 }
    175 #endif
    176 
    177 void PageClientQWidget::scroll(int dx, int dy, const QRect& rectToScroll)
    178 {
    179     view->scroll(qreal(dx), qreal(dy), rectToScroll);
    180 }
    181 
    182 void PageClientQWidget::update(const QRect & dirtyRect)
    183 {
    184     view->update(dirtyRect);
    185 }
    186 
    187 void PageClientQWidget::setInputMethodEnabled(bool enable)
    188 {
    189     view->setAttribute(Qt::WA_InputMethodEnabled, enable);
    190 }
    191 
    192 bool PageClientQWidget::inputMethodEnabled() const
    193 {
    194     return view->testAttribute(Qt::WA_InputMethodEnabled);
    195 }
    196 
    197 void PageClientQWidget::setInputMethodHints(Qt::InputMethodHints hints)
    198 {
    199     view->setInputMethodHints(hints);
    200 }
    201 
    202 PageClientQWidget::~PageClientQWidget()
    203 {
    204 #if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
    205     delete platformLayerProxy;
    206 #endif
    207 }
    208 
    209 #ifndef QT_NO_CURSOR
    210 QCursor PageClientQWidget::cursor() const
    211 {
    212     return view->cursor();
    213 }
    214 
    215 void PageClientQWidget::updateCursor(const QCursor& cursor)
    216 {
    217     view->setCursor(cursor);
    218 }
    219 #endif
    220 
    221 QPalette PageClientQWidget::palette() const
    222 {
    223     return view->palette();
    224 }
    225 
    226 int PageClientQWidget::screenNumber() const
    227 {
    228 #if defined(Q_WS_X11)
    229     return view->x11Info().screen();
    230 #endif
    231     return 0;
    232 }
    233 
    234 QWidget* PageClientQWidget::ownerWidget() const
    235 {
    236     return view;
    237 }
    238 
    239 QRect PageClientQWidget::geometryRelativeToOwnerWidget() const
    240 {
    241     return view->geometry();
    242 }
    243 
    244 QObject* PageClientQWidget::pluginParent() const
    245 {
    246     return view;
    247 }
    248 
    249 QStyle* PageClientQWidget::style() const
    250 {
    251     return view->style();
    252 }
    253 
    254 QRectF PageClientQWidget::windowRect() const
    255 {
    256     return QRectF(view->window()->geometry());
    257 }
    258 
    259 #if !defined(QT_NO_GRAPHICSVIEW)
    260 PageClientQGraphicsWidget::~PageClientQGraphicsWidget()
    261 {
    262     delete overlay;
    263 #if USE(ACCELERATED_COMPOSITING)
    264 #if USE(TEXTURE_MAPPER)
    265     delete platformLayerProxy;
    266 #else
    267     if (!rootGraphicsLayer)
    268         return;
    269     // we don't need to delete the root graphics layer. The lifecycle is managed in GraphicsLayerQt.cpp.
    270     rootGraphicsLayer.data()->setParentItem(0);
    271     view->scene()->removeItem(rootGraphicsLayer.data());
    272 #endif
    273 #endif
    274 }
    275 
    276 void PageClientQGraphicsWidget::scroll(int dx, int dy, const QRect& rectToScroll)
    277 {
    278     view->scroll(qreal(dx), qreal(dy), rectToScroll);
    279 }
    280 
    281 void PageClientQGraphicsWidget::update(const QRect& dirtyRect)
    282 {
    283     view->update(dirtyRect);
    284 
    285     createOrDeleteOverlay();
    286     if (overlay)
    287         overlay->update(QRectF(dirtyRect));
    288 #if USE(ACCELERATED_COMPOSITING)
    289     syncLayers();
    290 #endif
    291 }
    292 
    293 void PageClientQGraphicsWidget::createOrDeleteOverlay()
    294 {
    295     // We don't use an overlay with TextureMapper. Instead, the overlay is drawn inside QWebFrame.
    296 #if !USE(TEXTURE_MAPPER)
    297     bool useOverlay = false;
    298     if (!viewResizesToContents) {
    299 #if USE(ACCELERATED_COMPOSITING)
    300         useOverlay = useOverlay || rootGraphicsLayer;
    301 #endif
    302 #if ENABLE(TILED_BACKING_STORE)
    303         useOverlay = useOverlay || QWebFramePrivate::core(page->mainFrame())->tiledBackingStore();
    304 #endif
    305     }
    306     if (useOverlay == !!overlay)
    307         return;
    308 
    309     if (useOverlay) {
    310         overlay = new QGraphicsItemOverlay(view, page);
    311         overlay->setZValue(OverlayZValue);
    312     } else {
    313         // Changing the overlay might be done inside paint events.
    314         overlay->deleteLater();
    315         overlay = 0;
    316     }
    317 #endif // !USE(TEXTURE_MAPPER)
    318 }
    319 
    320 #if USE(ACCELERATED_COMPOSITING)
    321 void PageClientQGraphicsWidget::syncLayers()
    322 {
    323     if (shouldSync) {
    324         QWebFramePrivate::core(page->mainFrame())->view()->syncCompositingStateIncludingSubframes();
    325         shouldSync = false;
    326     }
    327 }
    328 
    329 #if USE(TEXTURE_MAPPER)
    330 void PageClientQGraphicsWidget::setRootGraphicsLayer(TextureMapperPlatformLayer* layer)
    331 {
    332     if (layer) {
    333         platformLayerProxy = new PlatformLayerProxyQGraphicsObject(page->mainFrame(), static_cast<TextureMapperContentLayer*>(layer), view);
    334         return;
    335     }
    336     delete platformLayerProxy;
    337     platformLayerProxy = 0;
    338 }
    339 #else
    340 void PageClientQGraphicsWidget::setRootGraphicsLayer(QGraphicsObject* layer)
    341 {
    342     if (rootGraphicsLayer) {
    343         rootGraphicsLayer.data()->setParentItem(0);
    344         view->scene()->removeItem(rootGraphicsLayer.data());
    345         QWebFramePrivate::core(page->mainFrame())->view()->syncCompositingStateIncludingSubframes();
    346     }
    347 
    348     rootGraphicsLayer = layer;
    349 
    350     if (layer) {
    351         layer->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
    352         layer->setParentItem(view);
    353         layer->setZValue(RootGraphicsLayerZValue);
    354     }
    355     createOrDeleteOverlay();
    356 }
    357 #endif
    358 
    359 void PageClientQGraphicsWidget::markForSync(bool scheduleSync)
    360 {
    361     shouldSync = true;
    362     if (scheduleSync)
    363         syncMetaMethod.invoke(view, Qt::QueuedConnection);
    364 }
    365 
    366 #endif
    367 
    368 #if ENABLE(TILED_BACKING_STORE)
    369 void PageClientQGraphicsWidget::updateTiledBackingStoreScale()
    370 {
    371     WebCore::TiledBackingStore* backingStore = QWebFramePrivate::core(page->mainFrame())->tiledBackingStore();
    372     if (!backingStore)
    373         return;
    374     backingStore->setContentsScale(view->scale());
    375 }
    376 #endif
    377 
    378 void PageClientQGraphicsWidget::setInputMethodEnabled(bool enable)
    379 {
    380     view->setFlag(QGraphicsItem::ItemAcceptsInputMethod, enable);
    381 }
    382 
    383 bool PageClientQGraphicsWidget::inputMethodEnabled() const
    384 {
    385     return view->flags() & QGraphicsItem::ItemAcceptsInputMethod;
    386 }
    387 
    388 void PageClientQGraphicsWidget::setInputMethodHints(Qt::InputMethodHints hints)
    389 {
    390     view->setInputMethodHints(hints);
    391 }
    392 
    393 #ifndef QT_NO_CURSOR
    394 QCursor PageClientQGraphicsWidget::cursor() const
    395 {
    396     return view->cursor();
    397 }
    398 
    399 void PageClientQGraphicsWidget::updateCursor(const QCursor& cursor)
    400 {
    401     view->setCursor(cursor);
    402 }
    403 #endif
    404 
    405 QPalette PageClientQGraphicsWidget::palette() const
    406 {
    407     return view->palette();
    408 }
    409 
    410 int PageClientQGraphicsWidget::screenNumber() const
    411 {
    412 #if defined(Q_WS_X11)
    413     if (QGraphicsScene* scene = view->scene()) {
    414         const QList<QGraphicsView*> views = scene->views();
    415 
    416         if (!views.isEmpty())
    417             return views.at(0)->x11Info().screen();
    418     }
    419 #endif
    420 
    421     return 0;
    422 }
    423 
    424 QWidget* PageClientQGraphicsWidget::ownerWidget() const
    425 {
    426     if (QGraphicsScene* scene = view->scene()) {
    427         const QList<QGraphicsView*> views = scene->views();
    428         return views.value(0);
    429     }
    430     return 0;
    431 }
    432 
    433 QRect PageClientQGraphicsWidget::geometryRelativeToOwnerWidget() const
    434 {
    435     if (!view->scene())
    436         return QRect();
    437 
    438     QList<QGraphicsView*> views = view->scene()->views();
    439     if (views.isEmpty())
    440         return QRect();
    441 
    442     QGraphicsView* graphicsView = views.at(0);
    443     return graphicsView->mapFromScene(view->boundingRect()).boundingRect();
    444 }
    445 
    446 #if ENABLE(TILED_BACKING_STORE)
    447 QRectF PageClientQGraphicsWidget::graphicsItemVisibleRect() const
    448 {
    449     if (!view->scene())
    450         return QRectF();
    451 
    452     QList<QGraphicsView*> views = view->scene()->views();
    453     if (views.isEmpty())
    454         return QRectF();
    455 
    456     QGraphicsView* graphicsView = views.at(0);
    457     int xOffset = graphicsView->horizontalScrollBar()->value();
    458     int yOffset = graphicsView->verticalScrollBar()->value();
    459     return view->mapRectFromScene(QRectF(QPointF(xOffset, yOffset), graphicsView->viewport()->size()));
    460 }
    461 #endif
    462 
    463 QObject* PageClientQGraphicsWidget::pluginParent() const
    464 {
    465     return view;
    466 }
    467 
    468 QStyle* PageClientQGraphicsWidget::style() const
    469 {
    470     return view->style();
    471 }
    472 
    473 QRectF PageClientQGraphicsWidget::windowRect() const
    474 {
    475     if (!view->scene())
    476         return QRectF();
    477 
    478     // The sceneRect is a good approximation of the size of the application, independent of the view.
    479     return view->scene()->sceneRect();
    480 }
    481 #endif // QT_NO_GRAPHICSVIEW
    482 
    483 } // namespace WebCore
    484