1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "config.h"
6#include "core/page/PageAnimator.h"
7
8#include "core/animation/DocumentAnimations.h"
9#include "core/frame/FrameView.h"
10#include "core/frame/LocalFrame.h"
11#include "core/page/Chrome.h"
12#include "core/page/ChromeClient.h"
13#include "core/page/Page.h"
14#include "core/svg/SVGDocumentExtensions.h"
15#include "platform/Logging.h"
16
17namespace blink {
18
19PageAnimator::PageAnimator(Page& page)
20    : m_page(page)
21    , m_animationFramePending(false)
22    , m_servicingAnimations(false)
23    , m_updatingLayoutAndStyleForPainting(false)
24{
25}
26
27PassRefPtrWillBeRawPtr<PageAnimator> PageAnimator::create(Page& page)
28{
29    return adoptRefWillBeNoop(new PageAnimator(page));
30}
31
32void PageAnimator::trace(Visitor* visitor)
33{
34    visitor->trace(m_page);
35}
36
37void PageAnimator::serviceScriptedAnimations(double monotonicAnimationStartTime)
38{
39    RefPtrWillBeRawPtr<PageAnimator> protector(this);
40    m_animationFramePending = false;
41    TemporaryChange<bool> servicing(m_servicingAnimations, true);
42
43    WillBeHeapVector<RefPtrWillBeMember<Document> > documents;
44    for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
45        if (frame->isLocalFrame())
46            documents.append(toLocalFrame(frame)->document());
47    }
48
49    for (size_t i = 0; i < documents.size(); ++i) {
50        if (documents[i]->frame()) {
51            documents[i]->view()->serviceScrollAnimations(monotonicAnimationStartTime);
52
53            if (const FrameView::ScrollableAreaSet* scrollableAreas = documents[i]->view()->scrollableAreas()) {
54                for (FrameView::ScrollableAreaSet::iterator it = scrollableAreas->begin(); it != scrollableAreas->end(); ++it)
55                    (*it)->serviceScrollAnimations(monotonicAnimationStartTime);
56            }
57        }
58    }
59
60    for (size_t i = 0; i < documents.size(); ++i) {
61        DocumentAnimations::updateAnimationTimingForAnimationFrame(*documents[i], monotonicAnimationStartTime);
62        SVGDocumentExtensions::serviceOnAnimationFrame(*documents[i], monotonicAnimationStartTime);
63    }
64
65    for (size_t i = 0; i < documents.size(); ++i)
66        documents[i]->serviceScriptedAnimations(monotonicAnimationStartTime);
67}
68
69void PageAnimator::scheduleVisualUpdate()
70{
71    // FIXME: also include m_animationFramePending here. It is currently not there due to crbug.com/353756.
72    if (m_servicingAnimations || m_updatingLayoutAndStyleForPainting)
73        return;
74    m_page->chrome().scheduleAnimation();
75}
76
77void PageAnimator::updateLayoutAndStyleForPainting(LocalFrame* rootFrame)
78{
79    RefPtr<FrameView> view = rootFrame->view();
80
81    TemporaryChange<bool> servicing(m_updatingLayoutAndStyleForPainting, true);
82
83    // In order for our child HWNDs (NativeWindowWidgets) to update properly,
84    // they need to be told that we are updating the screen. The problem is that
85    // the native widgets need to recalculate their clip region and not overlap
86    // any of our non-native widgets. To force the resizing, call
87    // setFrameRect(). This will be a quick operation for most frames, but the
88    // NativeWindowWidgets will update a proper clipping region.
89    view->setFrameRect(view->frameRect());
90
91    // setFrameRect may have the side-effect of causing existing page layout to
92    // be invalidated, so layout needs to be called last.
93    view->updateLayoutAndStyleForPainting();
94}
95
96}
97