Home | History | Annotate | Download | only in WebPage
      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