1 /* 2 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) 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 "TiledDrawingArea.h" 28 29 #if ENABLE(TILED_BACKING_STORE) 30 31 #include "DrawingAreaMessageKinds.h" 32 #include "DrawingAreaProxyMessageKinds.h" 33 #include "MessageID.h" 34 #include "UpdateChunk.h" 35 #include "WebCore/Frame.h" 36 #include "WebCore/FrameView.h" 37 #include "WebCoreArgumentCoders.h" 38 #include "WebFrame.h" 39 #include "WebPage.h" 40 #include "WebProcess.h" 41 42 using namespace WebCore; 43 44 namespace WebKit { 45 46 TiledDrawingArea::TiledDrawingArea(WebPage* webPage) 47 : DrawingArea(DrawingAreaTypeTiled, webPage) 48 , m_isWaitingForUpdate(false) 49 , m_shouldPaint(true) 50 , m_displayTimer(WebProcess::shared().runLoop(), this, &TiledDrawingArea::display) 51 , m_tileUpdateTimer(WebProcess::shared().runLoop(), this, &TiledDrawingArea::tileUpdateTimerFired) 52 { 53 } 54 55 TiledDrawingArea::~TiledDrawingArea() 56 { 57 } 58 59 void TiledDrawingArea::scroll(const IntRect& scrollRect, const IntSize& scrollDelta) 60 { 61 // FIXME: Do something much smarter. 62 setNeedsDisplay(scrollRect); 63 } 64 65 void TiledDrawingArea::setNeedsDisplay(const IntRect& rect) 66 { 67 // FIXME: Collect a set of rects/region instead of just the union of all rects. 68 m_dirtyRect.unite(rect); 69 scheduleDisplay(); 70 } 71 72 void TiledDrawingArea::display() 73 { 74 if (!m_shouldPaint) 75 return; 76 77 if (m_dirtyRect.isEmpty()) 78 return; 79 80 m_webPage->layoutIfNeeded(); 81 82 IntRect dirtyRect = m_dirtyRect; 83 m_dirtyRect = IntRect(); 84 85 WebProcess::shared().connection()->deprecatedSend(DrawingAreaProxyLegacyMessage::Invalidate, m_webPage->pageID(), CoreIPC::In(dirtyRect)); 86 87 m_displayTimer.stop(); 88 } 89 90 void TiledDrawingArea::scheduleDisplay() 91 { 92 if (!m_shouldPaint) 93 return; 94 95 if (m_displayTimer.isActive()) 96 return; 97 98 m_displayTimer.startOneShot(0); 99 } 100 101 void TiledDrawingArea::setSize(const IntSize& viewSize) 102 { 103 ASSERT(m_shouldPaint); 104 ASSERT_ARG(viewSize, !viewSize.isEmpty()); 105 106 m_webPage->setSize(viewSize); 107 108 scheduleDisplay(); 109 110 WebProcess::shared().connection()->deprecatedSend(DrawingAreaProxyLegacyMessage::DidSetSize, m_webPage->pageID(), CoreIPC::In(viewSize)); 111 } 112 113 void TiledDrawingArea::suspendPainting() 114 { 115 ASSERT(m_shouldPaint); 116 117 m_shouldPaint = false; 118 m_displayTimer.stop(); 119 } 120 121 void TiledDrawingArea::resumePainting() 122 { 123 ASSERT(!m_shouldPaint); 124 125 m_shouldPaint = true; 126 127 // Display if needed. 128 display(); 129 } 130 131 void TiledDrawingArea::didUpdate() 132 { 133 // Display if needed. 134 display(); 135 } 136 137 void TiledDrawingArea::updateTile(int tileID, const IntRect& dirtyRect, float scale) 138 { 139 m_webPage->layoutIfNeeded(); 140 141 UpdateChunk updateChunk(dirtyRect); 142 paintIntoUpdateChunk(&updateChunk, scale); 143 144 unsigned pendingUpdateCount = m_pendingUpdates.size(); 145 WebProcess::shared().connection()->deprecatedSend(DrawingAreaProxyLegacyMessage::TileUpdated, m_webPage->pageID(), CoreIPC::In(tileID, updateChunk, scale, pendingUpdateCount)); 146 } 147 148 void TiledDrawingArea::tileUpdateTimerFired() 149 { 150 ASSERT(!m_pendingUpdates.isEmpty()); 151 152 UpdateMap::iterator it = m_pendingUpdates.begin(); 153 TileUpdate update = it->second; 154 m_pendingUpdates.remove(it); 155 156 updateTile(update.tileID, update.dirtyRect, update.scale); 157 158 if (m_pendingUpdates.isEmpty()) 159 WebProcess::shared().connection()->deprecatedSend(DrawingAreaProxyLegacyMessage::AllTileUpdatesProcessed, m_webPage->pageID(), CoreIPC::In()); 160 else 161 m_tileUpdateTimer.startOneShot(0.001); 162 } 163 164 void TiledDrawingArea::didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments) 165 { 166 switch (messageID.get<DrawingAreaLegacyMessage::Kind>()) { 167 case DrawingAreaLegacyMessage::SetSize: { 168 IntSize size; 169 if (!arguments->decode(CoreIPC::Out(size))) 170 return; 171 172 setSize(size); 173 break; 174 } 175 case DrawingAreaLegacyMessage::SuspendPainting: 176 suspendPainting(); 177 break; 178 case DrawingAreaLegacyMessage::ResumePainting: 179 resumePainting(); 180 break; 181 case DrawingAreaLegacyMessage::CancelTileUpdate: { 182 int tileID; 183 if (!arguments->decode(CoreIPC::Out(tileID))) 184 return; 185 UpdateMap::iterator it = m_pendingUpdates.find(tileID); 186 if (it != m_pendingUpdates.end()) { 187 m_pendingUpdates.remove(it); 188 if (m_pendingUpdates.isEmpty()) { 189 WebProcess::shared().connection()->deprecatedSend(DrawingAreaProxyLegacyMessage::AllTileUpdatesProcessed, m_webPage->pageID(), CoreIPC::In()); 190 m_tileUpdateTimer.stop(); 191 } 192 } 193 break; 194 } 195 case DrawingAreaLegacyMessage::RequestTileUpdate: { 196 TileUpdate update; 197 if (!arguments->decode(CoreIPC::Out(update.tileID, update.dirtyRect, update.scale))) 198 return; 199 UpdateMap::iterator it = m_pendingUpdates.find(update.tileID); 200 if (it != m_pendingUpdates.end()) 201 it->second.dirtyRect.unite(update.dirtyRect); 202 else { 203 m_pendingUpdates.add(update.tileID, update); 204 if (!m_tileUpdateTimer.isActive()) 205 m_tileUpdateTimer.startOneShot(0); 206 } 207 break; 208 } 209 case DrawingAreaLegacyMessage::TakeSnapshot: { 210 IntSize targetSize; 211 IntRect contentsRect; 212 213 if (!arguments->decode(CoreIPC::Out(targetSize, contentsRect))) 214 return; 215 216 m_webPage->layoutIfNeeded(); 217 218 contentsRect.intersect(IntRect(IntPoint::zero(), m_webPage->mainFrame()->coreFrame()->view()->contentsSize())); 219 220 float targetScale = float(targetSize.width()) / contentsRect.width(); 221 222 UpdateChunk updateChunk(IntRect(IntPoint(contentsRect.x() * targetScale, contentsRect.y() * targetScale), targetSize)); 223 paintIntoUpdateChunk(&updateChunk, targetScale); 224 225 WebProcess::shared().connection()->deprecatedSend(DrawingAreaProxyLegacyMessage::SnapshotTaken, m_webPage->pageID(), CoreIPC::In(updateChunk)); 226 break; 227 } 228 default: 229 ASSERT_NOT_REACHED(); 230 break; 231 } 232 } 233 234 } // namespace WebKit 235 236 #endif // TILED_BACKING_STORE 237