1/* 2 * Copyright (C) 2010 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "ChunkedUpdateDrawingArea.h" 28 29#include "DrawingAreaMessageKinds.h" 30#include "DrawingAreaProxyMessageKinds.h" 31#include "MessageID.h" 32#include "UpdateChunk.h" 33#include "WebCoreArgumentCoders.h" 34#include "WebPage.h" 35#include "WebProcess.h" 36 37using namespace WebCore; 38 39namespace WebKit { 40 41ChunkedUpdateDrawingArea::ChunkedUpdateDrawingArea(WebPage* webPage) 42 : DrawingArea(DrawingAreaTypeChunkedUpdate, webPage) 43 , m_isWaitingForUpdate(false) 44 , m_paintingIsSuspended(false) 45 , m_displayTimer(WebProcess::shared().runLoop(), this, &ChunkedUpdateDrawingArea::display) 46{ 47} 48 49ChunkedUpdateDrawingArea::~ChunkedUpdateDrawingArea() 50{ 51} 52 53void ChunkedUpdateDrawingArea::scroll(const IntRect& scrollRect, const IntSize& scrollOffset) 54{ 55 // FIXME: Do something much smarter. 56 setNeedsDisplay(scrollRect); 57} 58 59void ChunkedUpdateDrawingArea::setNeedsDisplay(const IntRect& rect) 60{ 61 // FIXME: Collect a set of rects/region instead of just the union 62 // of all rects. 63 m_dirtyRect.unite(rect); 64 scheduleDisplay(); 65} 66 67void ChunkedUpdateDrawingArea::display() 68{ 69 ASSERT(!m_isWaitingForUpdate); 70 71 if (m_paintingIsSuspended) 72 return; 73 74 if (m_dirtyRect.isEmpty()) 75 return; 76 77 // Layout if necessary. 78 m_webPage->layoutIfNeeded(); 79 80 IntRect dirtyRect = m_dirtyRect; 81 m_dirtyRect = IntRect(); 82 83 // Create a new UpdateChunk and paint into it. 84 UpdateChunk updateChunk(dirtyRect); 85 paintIntoUpdateChunk(&updateChunk); 86 87 WebProcess::shared().connection()->deprecatedSend(DrawingAreaProxyLegacyMessage::Update, m_webPage->pageID(), CoreIPC::In(updateChunk)); 88 89 m_isWaitingForUpdate = true; 90 m_displayTimer.stop(); 91} 92 93void ChunkedUpdateDrawingArea::forceRepaint() 94{ 95 m_isWaitingForUpdate = false; 96 display(); 97} 98 99void ChunkedUpdateDrawingArea::scheduleDisplay() 100{ 101 if (m_paintingIsSuspended) 102 return; 103 104 if (m_isWaitingForUpdate) 105 return; 106 107 if (m_dirtyRect.isEmpty()) 108 return; 109 110 if (m_displayTimer.isActive()) 111 return; 112 113 m_displayTimer.startOneShot(0); 114} 115 116void ChunkedUpdateDrawingArea::setSize(const IntSize& viewSize) 117{ 118 ASSERT_ARG(viewSize, !viewSize.isEmpty()); 119 120 // We don't want to wait for an update until we display. 121 m_isWaitingForUpdate = false; 122 123 m_webPage->setSize(viewSize); 124 m_webPage->layoutIfNeeded(); 125 126 if (m_paintingIsSuspended) { 127 ASSERT(!m_displayTimer.isActive()); 128 129 // Painting is suspended, just send back an empty update chunk. 130 WebProcess::shared().connection()->deprecatedSend(DrawingAreaProxyLegacyMessage::DidSetSize, m_webPage->pageID(), CoreIPC::In(UpdateChunk())); 131 return; 132 } 133 134 // Create a new UpdateChunk and paint into it. 135 UpdateChunk updateChunk(IntRect(0, 0, viewSize.width(), viewSize.height())); 136 paintIntoUpdateChunk(&updateChunk); 137 138 m_displayTimer.stop(); 139 140 WebProcess::shared().connection()->deprecatedSend(DrawingAreaProxyLegacyMessage::DidSetSize, m_webPage->pageID(), CoreIPC::In(updateChunk)); 141} 142 143void ChunkedUpdateDrawingArea::suspendPainting() 144{ 145 ASSERT(!m_paintingIsSuspended); 146 147 m_paintingIsSuspended = true; 148 m_displayTimer.stop(); 149} 150 151void ChunkedUpdateDrawingArea::deprecatedResumePainting(bool forceRepaint) 152{ 153 ASSERT(m_paintingIsSuspended); 154 155 m_paintingIsSuspended = false; 156 157 if (forceRepaint) { 158 // Just set the dirty rect to the entire page size. 159 m_dirtyRect = m_webPage->bounds(); 160 } 161 162 // Schedule a display. 163 scheduleDisplay(); 164} 165 166void ChunkedUpdateDrawingArea::didUpdate() 167{ 168 m_isWaitingForUpdate = false; 169 170 // Display if needed. 171 display(); 172} 173 174void ChunkedUpdateDrawingArea::didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments) 175{ 176 switch (messageID.get<DrawingAreaLegacyMessage::Kind>()) { 177 case DrawingAreaLegacyMessage::SetSize: { 178 IntSize size; 179 if (!arguments->decode(CoreIPC::Out(size))) 180 return; 181 182 setSize(size); 183 break; 184 } 185 186 case DrawingAreaLegacyMessage::SuspendPainting: 187 suspendPainting(); 188 break; 189 190 case DrawingAreaLegacyMessage::ResumePainting: { 191 bool forceRepaint; 192 if (!arguments->decode(CoreIPC::Out(forceRepaint))) 193 return; 194 195 deprecatedResumePainting(forceRepaint); 196 break; 197 } 198 case DrawingAreaLegacyMessage::DidUpdate: 199 didUpdate(); 200 break; 201 202 default: 203 ASSERT_NOT_REACHED(); 204 break; 205 } 206} 207 208} // namespace WebKit 209