#include "config.h"
#include "PageOverlay.h"
#include "WebPage.h"
#include "WebProcess.h"
#include <WebCore/FrameView.h>
#include <WebCore/GraphicsContext.h>
#include <WebCore/MainFrame.h>
#include <WebCore/Page.h>
#include <WebCore/ScrollbarTheme.h>
#include <wtf/CurrentTime.h>
using namespace WebCore;
namespace WebKit {
static const double fadeAnimationDuration = 0.2;
static const double fadeAnimationFrameRate = 30;
PassRefPtr<PageOverlay> PageOverlay::create(Client* client, OverlayType overlayType)
{
return adoptRef(new PageOverlay(client, overlayType));
}
PageOverlay::PageOverlay(Client* client, OverlayType overlayType)
: m_client(client)
, m_webPage(nullptr)
, m_fadeAnimationTimer(RunLoop::main(), this, &PageOverlay::fadeAnimationTimerFired)
, m_fadeAnimationStartTime(0)
, m_fadeAnimationDuration(fadeAnimationDuration)
, m_fadeAnimationType(NoAnimation)
, m_fractionFadedIn(1)
, m_overlayType(overlayType)
, m_backgroundColor(Color::transparent)
{
}
PageOverlay::~PageOverlay()
{
}
IntRect PageOverlay::bounds() const
{
if (!m_overrideFrame.isEmpty())
return IntRect(IntPoint(), m_overrideFrame.size());
FrameView* frameView = m_webPage->mainFrameView();
switch (m_overlayType) {
case OverlayType::View: {
int width = frameView->width();
int height = frameView->height();
if (!ScrollbarTheme::theme()->usesOverlayScrollbars()) {
if (frameView->verticalScrollbar())
width -= frameView->verticalScrollbar()->width();
if (frameView->horizontalScrollbar())
height -= frameView->horizontalScrollbar()->height();
}
return IntRect(0, 0, width, height);
}
case OverlayType::Document:
return IntRect(IntPoint(), frameView->contentsSize());
};
ASSERT_NOT_REACHED();
return IntRect(IntPoint(), frameView->contentsSize());
}
IntRect PageOverlay::frame() const
{
if (!m_overrideFrame.isEmpty())
return m_overrideFrame;
return bounds();
}
void PageOverlay::setFrame(IntRect frame)
{
if (m_overrideFrame == frame)
return;
m_overrideFrame = frame;
if (m_webPage)
m_webPage->pageOverlayController().didChangeOverlayFrame(*this);
}
void PageOverlay::setBackgroundColor(RGBA32 backgroundColor)
{
if (m_backgroundColor == backgroundColor)
return;
m_backgroundColor = backgroundColor;
if (m_webPage)
m_webPage->pageOverlayController().didChangeOverlayBackgroundColor(*this);
}
void PageOverlay::setPage(WebPage* webPage)
{
m_client->willMoveToWebPage(this, webPage);
m_webPage = webPage;
m_client->didMoveToWebPage(this, webPage);
m_fadeAnimationTimer.stop();
}
void PageOverlay::setNeedsDisplay(const IntRect& dirtyRect)
{
if (!m_webPage)
return;
m_webPage->pageOverlayController().setPageOverlayOpacity(*this, m_fractionFadedIn);
m_webPage->pageOverlayController().setPageOverlayNeedsDisplay(*this, dirtyRect);
}
void PageOverlay::setNeedsDisplay()
{
setNeedsDisplay(bounds());
}
void PageOverlay::drawRect(GraphicsContext& graphicsContext, const IntRect& dirtyRect)
{
IntRect paintRect = intersection(dirtyRect, bounds());
if (paintRect.isEmpty())
return;
GraphicsContextStateSaver stateSaver(graphicsContext);
m_client->drawRect(this, graphicsContext, paintRect);
}
bool PageOverlay::mouseEvent(const WebMouseEvent& mouseEvent)
{
if (!bounds().contains(mouseEvent.position()))
return false;
return m_client->mouseEvent(this, mouseEvent);
}
WKTypeRef PageOverlay::copyAccessibilityAttributeValue(WKStringRef attribute, WKTypeRef parameter)
{
return m_client->copyAccessibilityAttributeValue(this, attribute, parameter);
}
WKArrayRef PageOverlay::copyAccessibilityAttributeNames(bool parameterizedNames)
{
return m_client->copyAccessibilityAttributeNames(this, parameterizedNames);
}
void PageOverlay::startFadeInAnimation()
{
m_fractionFadedIn = 0;
m_fadeAnimationType = FadeInAnimation;
startFadeAnimation();
}
void PageOverlay::startFadeOutAnimation()
{
m_fractionFadedIn = 1;
m_fadeAnimationType = FadeOutAnimation;
startFadeAnimation();
}
void PageOverlay::stopFadeOutAnimation()
{
m_fractionFadedIn = 1.0;
m_fadeAnimationTimer.stop();
}
void PageOverlay::startFadeAnimation()
{
m_fadeAnimationStartTime = currentTime();
m_fadeAnimationTimer.startRepeating(1 / fadeAnimationFrameRate);
}
void PageOverlay::fadeAnimationTimerFired()
{
float animationProgress = (currentTime() - m_fadeAnimationStartTime) / m_fadeAnimationDuration;
if (animationProgress >= 1.0)
animationProgress = 1.0;
double sine = sin(piOverTwoFloat * animationProgress);
float fadeAnimationValue = sine * sine;
m_fractionFadedIn = (m_fadeAnimationType == FadeInAnimation) ? fadeAnimationValue : 1 - fadeAnimationValue;
m_webPage->pageOverlayController().setPageOverlayOpacity(*this, m_fractionFadedIn);
if (animationProgress == 1.0) {
m_fadeAnimationTimer.stop();
bool wasFadingOut = m_fadeAnimationType == FadeOutAnimation;
m_fadeAnimationType = NoAnimation;
if (wasFadingOut)
m_webPage->uninstallPageOverlay(this, PageOverlay::FadeMode::DoNotFade);
}
}
void PageOverlay::clear()
{
m_webPage->pageOverlayController().clearPageOverlay(*this);
}
}