VisualViewport.cpp [plain text]
#include "config.h"
#include "VisualViewport.h"
#include "ContextDestructionObserver.h"
#include "DOMWindow.h"
#include "Document.h"
#include "DocumentEventQueue.h"
#include "Event.h"
#include "EventNames.h"
#include "Frame.h"
#include "FrameView.h"
#include "Page.h"
namespace WebCore {
VisualViewport::VisualViewport(DOMWindow& window)
: DOMWindowProperty(&window)
{
}
EventTargetInterface VisualViewport::eventTargetInterface() const
{
return VisualViewportEventTargetInterfaceType;
}
ScriptExecutionContext* VisualViewport::scriptExecutionContext() const
{
if (!m_window)
return nullptr;
return static_cast<ContextDestructionObserver*>(m_window)->scriptExecutionContext();
}
bool VisualViewport::addEventListener(const AtomicString& eventType, Ref<EventListener>&& listener, const AddEventListenerOptions& options)
{
if (!EventTarget::addEventListener(eventType, WTFMove(listener), options))
return false;
if (auto* frame = this->frame())
frame->document()->addListenerTypeIfNeeded(eventType);
return true;
}
void VisualViewport::updateFrameLayout() const
{
ASSERT(frame());
frame()->document()->updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasks::Synchronously);
}
double VisualViewport::offsetLeft() const
{
if (!frame())
return 0;
updateFrameLayout();
return m_offsetLeft;
}
double VisualViewport::offsetTop() const
{
if (!frame())
return 0;
updateFrameLayout();
return m_offsetTop;
}
double VisualViewport::pageLeft() const
{
if (!frame())
return 0;
updateFrameLayout();
return m_pageLeft;
}
double VisualViewport::pageTop() const
{
if (!frame())
return 0;
updateFrameLayout();
return m_pageTop;
}
double VisualViewport::width() const
{
if (!frame())
return 0;
updateFrameLayout();
return m_width;
}
double VisualViewport::height() const
{
if (!frame())
return 0;
updateFrameLayout();
return m_height;
}
double VisualViewport::scale() const
{
auto* frame = this->frame();
if (!frame || !frame->isMainFrame())
return 1;
updateFrameLayout();
return m_scale;
}
void VisualViewport::update()
{
double offsetLeft = 0;
double offsetTop = 0;
m_pageLeft = 0;
m_pageTop = 0;
double width = 0;
double height = 0;
double scale = 1;
if (auto* frame = this->frame()) {
if (auto* view = frame->view()) {
auto visualViewportRect = view->visualViewportRect();
auto layoutViewportRect = view->layoutViewportRect();
auto pageZoomFactor = frame->pageZoomFactor();
ASSERT(pageZoomFactor);
offsetLeft = (visualViewportRect.x() - layoutViewportRect.x()) / pageZoomFactor;
offsetTop = (visualViewportRect.y() - layoutViewportRect.y()) / pageZoomFactor;
m_pageLeft = visualViewportRect.x() / pageZoomFactor;
m_pageTop = visualViewportRect.y() / pageZoomFactor;
width = visualViewportRect.width() / pageZoomFactor;
height = visualViewportRect.height() / pageZoomFactor;
}
if (auto* page = frame->page())
scale = page->pageScaleFactor();
}
if (m_offsetLeft != offsetLeft || m_offsetTop != offsetTop) {
enqueueScrollEvent();
m_offsetLeft = offsetLeft;
m_offsetTop = offsetTop;
}
if (m_width != width || m_height != height || m_scale != scale) {
enqueueResizeEvent();
m_width = width;
m_height = height;
m_scale = scale;
}
}
void VisualViewport::enqueueResizeEvent()
{
auto* frame = this->frame();
if (!frame)
return;
frame->document()->eventQueue().enqueueResizeEvent(*this, Event::CanBubble::No, Event::IsCancelable::No);
}
void VisualViewport::enqueueScrollEvent()
{
auto* frame = this->frame();
if (!frame)
return;
frame->document()->eventQueue().enqueueScrollEvent(*this, Event::CanBubble::No, Event::IsCancelable::No);
}
}