PageOverlayController.cpp [plain text]
#include "config.h"
#include "PageOverlayController.h"
#include "DrawingArea.h"
#include "PageOverlay.h"
#include "WebPage.h"
#include <WebCore/Frame.h>
#include <WebCore/FrameView.h>
#include <WebCore/GraphicsContext.h>
#include <WebCore/GraphicsLayer.h>
#include <WebCore/MainFrame.h>
#include <WebCore/ScrollingCoordinator.h>
#include <WebCore/Settings.h>
#include <WebCore/TiledBacking.h>
using namespace WebCore;
namespace WebKit {
PageOverlayController::PageOverlayController(WebPage& webPage)
: m_webPage(webPage)
{
}
void PageOverlayController::initialize()
{
ASSERT(!m_documentOverlayRootLayer);
ASSERT(!m_viewOverlayRootLayer);
m_documentOverlayRootLayer = GraphicsLayer::create(m_webPage.drawingArea()->graphicsLayerFactory(), *this);
m_viewOverlayRootLayer = GraphicsLayer::create(m_webPage.drawingArea()->graphicsLayerFactory(), *this);
#ifndef NDEBUG
m_documentOverlayRootLayer->setName("Page Overlay container (document-relative)");
m_viewOverlayRootLayer->setName("Page Overlay container (view-relative)");
#endif
}
static void updateOverlayGeometry(PageOverlay& overlay, GraphicsLayer& graphicsLayer)
{
IntRect overlayFrame = overlay.frame();
if (overlayFrame.location() == graphicsLayer.position() && overlayFrame.size() == graphicsLayer.size())
return;
graphicsLayer.setPosition(overlayFrame.location());
graphicsLayer.setSize(overlayFrame.size());
}
void PageOverlayController::installPageOverlay(PassRefPtr<PageOverlay> pageOverlay, PageOverlay::FadeMode fadeMode)
{
ASSERT(m_documentOverlayRootLayer);
ASSERT(m_viewOverlayRootLayer);
RefPtr<PageOverlay> overlay = pageOverlay;
if (m_pageOverlays.contains(overlay))
return;
m_pageOverlays.append(overlay);
overlay->setPage(&m_webPage);
if (fadeMode == PageOverlay::FadeMode::Fade)
overlay->startFadeInAnimation();
std::unique_ptr<GraphicsLayer> layer = GraphicsLayer::create(m_webPage.drawingArea()->graphicsLayerFactory(), *this);
layer->setAnchorPoint(FloatPoint3D());
layer->setBackgroundColor(overlay->backgroundColor());
updateOverlayGeometry(*overlay, *layer);
#ifndef NDEBUG
layer->setName("Page Overlay content");
#endif
updateSettingsForLayer(*layer);
switch (overlay->overlayType()) {
case PageOverlay::OverlayType::View:
m_viewOverlayRootLayer->addChild(layer.get());
break;
case PageOverlay::OverlayType::Document:
m_documentOverlayRootLayer->addChild(layer.get());
break;
}
m_overlayGraphicsLayers.set(overlay.get(), WTF::move(layer));
updateForceSynchronousScrollLayerPositionUpdates();
}
void PageOverlayController::uninstallPageOverlay(PageOverlay* overlay, PageOverlay::FadeMode fadeMode)
{
if (fadeMode == PageOverlay::FadeMode::Fade) {
overlay->startFadeOutAnimation();
return;
}
overlay->setPage(nullptr);
m_overlayGraphicsLayers.take(overlay)->removeFromParent();
size_t overlayIndex = m_pageOverlays.find(overlay);
ASSERT(overlayIndex != notFound);
m_pageOverlays.remove(overlayIndex);
updateForceSynchronousScrollLayerPositionUpdates();
}
void PageOverlayController::updateForceSynchronousScrollLayerPositionUpdates()
{
#if ENABLE(ASYNC_SCROLLING)
bool forceSynchronousScrollLayerPositionUpdates = false;
for (auto& overlay : m_pageOverlays) {
if (overlay->overlayType() == PageOverlay::OverlayType::View)
forceSynchronousScrollLayerPositionUpdates = true;
}
if (Page* page = m_webPage.corePage()) {
if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
scrollingCoordinator->setForceSynchronousScrollLayerPositionUpdates(forceSynchronousScrollLayerPositionUpdates);
}
#endif
}
void PageOverlayController::setPageOverlayNeedsDisplay(PageOverlay& overlay, const WebCore::IntRect& dirtyRect)
{
ASSERT(m_pageOverlays.contains(&overlay));
GraphicsLayer& graphicsLayer = *m_overlayGraphicsLayers.get(&overlay);
if (!graphicsLayer.drawsContent()) {
graphicsLayer.setDrawsContent(true);
updateOverlayGeometry(overlay, graphicsLayer);
}
graphicsLayer.setNeedsDisplayInRect(dirtyRect);
}
void PageOverlayController::setPageOverlayOpacity(PageOverlay& overlay, float opacity)
{
ASSERT(m_pageOverlays.contains(&overlay));
m_overlayGraphicsLayers.get(&overlay)->setOpacity(opacity);
}
void PageOverlayController::clearPageOverlay(PageOverlay& overlay)
{
ASSERT(m_pageOverlays.contains(&overlay));
m_overlayGraphicsLayers.get(&overlay)->setDrawsContent(false);
}
void PageOverlayController::didChangeViewSize()
{
for (auto& overlayAndLayer : m_overlayGraphicsLayers) {
if (overlayAndLayer.key->overlayType() == PageOverlay::OverlayType::View)
updateOverlayGeometry(*overlayAndLayer.key, *overlayAndLayer.value);
}
}
void PageOverlayController::didChangeDocumentSize()
{
for (auto& overlayAndLayer : m_overlayGraphicsLayers) {
if (overlayAndLayer.key->overlayType() == PageOverlay::OverlayType::Document)
updateOverlayGeometry(*overlayAndLayer.key, *overlayAndLayer.value);
}
}
void PageOverlayController::didChangePreferences()
{
for (auto& graphicsLayer : m_overlayGraphicsLayers.values())
updateSettingsForLayer(*graphicsLayer);
}
void PageOverlayController::didChangeDeviceScaleFactor()
{
m_documentOverlayRootLayer->noteDeviceOrPageScaleFactorChangedIncludingDescendants();
m_viewOverlayRootLayer->noteDeviceOrPageScaleFactorChangedIncludingDescendants();
for (auto& graphicsLayer : m_overlayGraphicsLayers.values())
graphicsLayer->setNeedsDisplay();
}
void PageOverlayController::didChangeExposedRect()
{
m_webPage.drawingArea()->scheduleCompositingLayerFlush();
}
void PageOverlayController::didScrollFrame(Frame* frame)
{
for (auto& overlayAndLayer : m_overlayGraphicsLayers) {
if (overlayAndLayer.key->overlayType() == PageOverlay::OverlayType::View || !frame->isMainFrame())
overlayAndLayer.value->setNeedsDisplay();
}
}
void PageOverlayController::flushPageOverlayLayers(FloatRect visibleRect)
{
m_viewOverlayRootLayer->flushCompositingState(visibleRect);
}
void PageOverlayController::updateSettingsForLayer(GraphicsLayer& layer)
{
Settings& settings = m_webPage.corePage()->settings();
layer.setAcceleratesDrawing(settings.acceleratedDrawingEnabled());
layer.setShowDebugBorder(settings.showDebugBorders());
layer.setShowRepaintCounter(settings.showRepaintCounter());
}
bool PageOverlayController::handleMouseEvent(const WebMouseEvent& mouseEvent)
{
if (!m_pageOverlays.size())
return false;
for (auto it = m_pageOverlays.rbegin(), end = m_pageOverlays.rend(); it != end; ++it) {
if ((*it)->mouseEvent(mouseEvent))
return true;
}
return false;
}
WKTypeRef PageOverlayController::copyAccessibilityAttributeValue(WKStringRef attribute, WKTypeRef parameter)
{
if (!m_pageOverlays.size())
return nullptr;
for (auto it = m_pageOverlays.rbegin(), end = m_pageOverlays.rend(); it != end; ++it) {
if (WKTypeRef value = (*it)->copyAccessibilityAttributeValue(attribute, parameter))
return value;
}
return nullptr;
}
WKArrayRef PageOverlayController::copyAccessibilityAttributesNames(bool parameterizedNames)
{
if (!m_pageOverlays.size())
return nullptr;
for (auto it = m_pageOverlays.rbegin(), end = m_pageOverlays.rend(); it != end; ++it) {
if (WKArrayRef value = (*it)->copyAccessibilityAttributeNames(parameterizedNames))
return value;
}
return nullptr;
}
void PageOverlayController::paintContents(const WebCore::GraphicsLayer* graphicsLayer, WebCore::GraphicsContext& graphicsContext, WebCore::GraphicsLayerPaintingPhase, const WebCore::FloatRect& clipRect)
{
for (auto it = m_overlayGraphicsLayers.begin(), end = m_overlayGraphicsLayers.end(); it != end; ++it) {
if (it->value.get() != graphicsLayer)
continue;
GraphicsContextStateSaver stateSaver(graphicsContext);
graphicsContext.clip(clipRect);
it->key->drawRect(graphicsContext, enclosingIntRect(clipRect));
return;
}
}
float PageOverlayController::deviceScaleFactor() const
{
return m_webPage.corePage()->deviceScaleFactor();
}
void PageOverlayController::notifyFlushRequired(const WebCore::GraphicsLayer*)
{
if (m_webPage.drawingArea())
m_webPage.drawingArea()->scheduleCompositingLayerFlush();
}
void PageOverlayController::didChangeOverlayFrame(PageOverlay& overlay)
{
ASSERT(m_pageOverlays.contains(&overlay));
updateOverlayGeometry(overlay, *m_overlayGraphicsLayers.get(&overlay));
}
void PageOverlayController::didChangeOverlayBackgroundColor(PageOverlay& overlay)
{
ASSERT(m_pageOverlays.contains(&overlay));
m_overlayGraphicsLayers.get(&overlay)->setBackgroundColor(overlay.backgroundColor());
}
}