• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
PlatformLayerProxyQt(QWebFrame * frame,TextureMapperContentLayer * layer,QObject * object)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 
setTextureMapper(PassOwnPtr<TextureMapper> textureMapper)52     void setTextureMapper(PassOwnPtr<TextureMapper> textureMapper)
53     {
54         m_frame->d->textureMapper = textureMapper;
55     }
56 
~PlatformLayerProxyQt()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 
textureMapper()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.
setSizeChanged(const IntSize &)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:
PlatformLayerProxyQWidget(QWebFrame * frame,TextureMapperContentLayer * layer,QWidget * widget)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.
eventFilter(QObject * object,QEvent * event)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 
setNeedsDisplay()102     void setNeedsDisplay()
103     {
104         if (m_widget)
105             m_widget->update();
106     }
107 
setNeedsDisplayInRect(const IntRect & rect)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:
PlatformLayerProxyQGraphicsObject(QWebFrame * frame,TextureMapperContentLayer * layer,QGraphicsObject * object)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 
setNeedsDisplay()139     void setNeedsDisplay()
140     {
141         if (m_graphicsItem)
142             m_graphicsItem->update();
143     }
144 
setNeedsDisplayInRect(const IntRect & rect)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 
setRootGraphicsLayer(TextureMapperPlatformLayer * layer)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 
markForSync(bool scheduleSync)166 void PageClientQWidget::markForSync(bool scheduleSync)
167 {
168     syncTimer.startOneShot(0);
169 }
170 
syncLayers(Timer<PageClientQWidget> *)171 void PageClientQWidget::syncLayers(Timer<PageClientQWidget>*)
172 {
173     QWebFramePrivate::core(page->mainFrame())->view()->syncCompositingStateIncludingSubframes();
174 }
175 #endif
176 
scroll(int dx,int dy,const QRect & rectToScroll)177 void PageClientQWidget::scroll(int dx, int dy, const QRect& rectToScroll)
178 {
179     view->scroll(qreal(dx), qreal(dy), rectToScroll);
180 }
181 
update(const QRect & dirtyRect)182 void PageClientQWidget::update(const QRect & dirtyRect)
183 {
184     view->update(dirtyRect);
185 }
186 
setInputMethodEnabled(bool enable)187 void PageClientQWidget::setInputMethodEnabled(bool enable)
188 {
189     view->setAttribute(Qt::WA_InputMethodEnabled, enable);
190 }
191 
inputMethodEnabled() const192 bool PageClientQWidget::inputMethodEnabled() const
193 {
194     return view->testAttribute(Qt::WA_InputMethodEnabled);
195 }
196 
setInputMethodHints(Qt::InputMethodHints hints)197 void PageClientQWidget::setInputMethodHints(Qt::InputMethodHints hints)
198 {
199     view->setInputMethodHints(hints);
200 }
201 
~PageClientQWidget()202 PageClientQWidget::~PageClientQWidget()
203 {
204 #if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
205     delete platformLayerProxy;
206 #endif
207 }
208 
209 #ifndef QT_NO_CURSOR
cursor() const210 QCursor PageClientQWidget::cursor() const
211 {
212     return view->cursor();
213 }
214 
updateCursor(const QCursor & cursor)215 void PageClientQWidget::updateCursor(const QCursor& cursor)
216 {
217     view->setCursor(cursor);
218 }
219 #endif
220 
palette() const221 QPalette PageClientQWidget::palette() const
222 {
223     return view->palette();
224 }
225 
screenNumber() const226 int PageClientQWidget::screenNumber() const
227 {
228 #if defined(Q_WS_X11)
229     return view->x11Info().screen();
230 #endif
231     return 0;
232 }
233 
ownerWidget() const234 QWidget* PageClientQWidget::ownerWidget() const
235 {
236     return view;
237 }
238 
geometryRelativeToOwnerWidget() const239 QRect PageClientQWidget::geometryRelativeToOwnerWidget() const
240 {
241     return view->geometry();
242 }
243 
pluginParent() const244 QObject* PageClientQWidget::pluginParent() const
245 {
246     return view;
247 }
248 
style() const249 QStyle* PageClientQWidget::style() const
250 {
251     return view->style();
252 }
253 
windowRect() const254 QRectF PageClientQWidget::windowRect() const
255 {
256     return QRectF(view->window()->geometry());
257 }
258 
259 #if !defined(QT_NO_GRAPHICSVIEW)
~PageClientQGraphicsWidget()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 
scroll(int dx,int dy,const QRect & rectToScroll)276 void PageClientQGraphicsWidget::scroll(int dx, int dy, const QRect& rectToScroll)
277 {
278     view->scroll(qreal(dx), qreal(dy), rectToScroll);
279 }
280 
update(const QRect & dirtyRect)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 
createOrDeleteOverlay()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)
syncLayers()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)
setRootGraphicsLayer(TextureMapperPlatformLayer * layer)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
setRootGraphicsLayer(QGraphicsObject * layer)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 
markForSync(bool scheduleSync)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)
updateTiledBackingStoreScale()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 
setInputMethodEnabled(bool enable)378 void PageClientQGraphicsWidget::setInputMethodEnabled(bool enable)
379 {
380     view->setFlag(QGraphicsItem::ItemAcceptsInputMethod, enable);
381 }
382 
inputMethodEnabled() const383 bool PageClientQGraphicsWidget::inputMethodEnabled() const
384 {
385     return view->flags() & QGraphicsItem::ItemAcceptsInputMethod;
386 }
387 
setInputMethodHints(Qt::InputMethodHints hints)388 void PageClientQGraphicsWidget::setInputMethodHints(Qt::InputMethodHints hints)
389 {
390     view->setInputMethodHints(hints);
391 }
392 
393 #ifndef QT_NO_CURSOR
cursor() const394 QCursor PageClientQGraphicsWidget::cursor() const
395 {
396     return view->cursor();
397 }
398 
updateCursor(const QCursor & cursor)399 void PageClientQGraphicsWidget::updateCursor(const QCursor& cursor)
400 {
401     view->setCursor(cursor);
402 }
403 #endif
404 
palette() const405 QPalette PageClientQGraphicsWidget::palette() const
406 {
407     return view->palette();
408 }
409 
screenNumber() const410 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 
ownerWidget() const424 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 
geometryRelativeToOwnerWidget() const433 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)
graphicsItemVisibleRect() const447 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 
pluginParent() const463 QObject* PageClientQGraphicsWidget::pluginParent() const
464 {
465     return view;
466 }
467 
style() const468 QStyle* PageClientQGraphicsWidget::style() const
469 {
470     return view->style();
471 }
472 
windowRect() const473 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