diff options
26 files changed, 213 insertions, 209 deletions
diff --git a/WebCore/platform/graphics/android/GLWebViewState.cpp b/WebCore/platform/graphics/android/GLWebViewState.cpp index 5ba094b..53d5c5e 100644 --- a/WebCore/platform/graphics/android/GLWebViewState.cpp +++ b/WebCore/platform/graphics/android/GLWebViewState.cpp @@ -127,7 +127,7 @@ void GLWebViewState::unlockBaseLayerUpdate() { } void GLWebViewState::setExtra(BaseLayerAndroid* layer, SkPicture& picture, - const IntRect& rect) + const IntRect& rect, bool allowSame) { android::Mutex::Autolock lock(m_baseLayerLock); if (!m_baseLayerUpdate) @@ -135,7 +135,7 @@ void GLWebViewState::setExtra(BaseLayerAndroid* layer, SkPicture& picture, layer->setExtra(picture); - if (m_lastInval == rect) + if (!allowSame && m_lastInval == rect) return; if (!rect.isEmpty()) diff --git a/WebCore/platform/graphics/android/GLWebViewState.h b/WebCore/platform/graphics/android/GLWebViewState.h index 2082f2c..d28c16a 100644 --- a/WebCore/platform/graphics/android/GLWebViewState.h +++ b/WebCore/platform/graphics/android/GLWebViewState.h @@ -169,7 +169,7 @@ public: unsigned int paintBaseLayerContent(SkCanvas* canvas); void setBaseLayer(BaseLayerAndroid* layer, const IntRect& rect); - void setExtra(BaseLayerAndroid*, SkPicture&, const IntRect&); + void setExtra(BaseLayerAndroid*, SkPicture&, const IntRect&, bool allowSame); void scheduleUpdate(const double& currentTime, const SkIRect& viewport, float scale); TiledPage* sibling(TiledPage* page); diff --git a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp index e887964..49f20ab 100644 --- a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp +++ b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp @@ -271,7 +271,17 @@ void GraphicsLayerAndroid::setPosition(const FloatPoint& point) if (point == m_position) return; - GraphicsLayer::setPosition(point); + FloatPoint pos(point); +#if ENABLE(ANDROID_OVERFLOW_SCROLL) + // Add the scroll position back in. When scrolling a layer, all the children + // are positioned based on the content scroll. Adding the scroll position + // back in allows the children to draw based on 0,0. + RenderLayer* layer = renderLayerFromClient(m_client); + if (layer && layer->parent() && layer->parent()->hasOverflowScroll()) + pos += layer->parent()->scrolledContentOffset(); +#endif + + GraphicsLayer::setPosition(pos); #ifdef LAYER_DEBUG_2 LOG("(%x) setPosition(%.2f,%.2f) pos(%.2f, %.2f) anchor(%.2f,%.2f) size(%.2f, %.2f)", @@ -279,7 +289,7 @@ void GraphicsLayerAndroid::setPosition(const FloatPoint& point) m_anchorPoint.x(), m_anchorPoint.y(), m_size.width(), m_size.height()); #endif updateFixedPosition(); - m_contentLayer->setPosition(point.x(), point.y()); + m_contentLayer->setPosition(pos.x(), pos.y()); askForSync(); } @@ -368,31 +378,6 @@ void GraphicsLayerAndroid::setDrawsContent(bool drawsContent) if (m_contentLayer->isRootLayer()) return; if (m_drawsContent) { -#if ENABLE(ANDROID_OVERFLOW_SCROLL) - RenderLayer* layer = renderLayerFromClient(m_client); - if (layer) { - if (layer->hasOverflowScroll() && !m_foregroundLayer) { - m_foregroundLayer = new ScrollableLayerAndroid(); - m_foregroundClipLayer = new LayerAndroid(false); - m_foregroundClipLayer->setMasksToBounds(true); - - m_foregroundClipLayer->addChild(m_foregroundLayer); - m_contentLayer->addChild(m_foregroundClipLayer); - } else if (layer->isRootLayer() - && layer->renderer()->frame()->ownerRenderer()) { - // We have to do another check for scrollable content since an - // iframe might be compositing for other reasons. - FrameView* view = layer->renderer()->frame()->view(); - if (view->hasOverflowScroll()) { - // Replace the content layer with a scrollable layer. - LayerAndroid* layer = new ScrollableLayerAndroid(*m_contentLayer); - m_contentLayer->unref(); - m_contentLayer = layer; - } - } - } -#endif - m_haveContents = true; setNeedsDisplay(); } @@ -478,6 +463,79 @@ private: GraphicsLayerPaintingPhase m_originalPhase; }; +void GraphicsLayerAndroid::updateScrollingLayers() +{ +#if ENABLE(ANDROID_OVERFLOW_SCROLL) + RenderLayer* layer = renderLayerFromClient(m_client); + if (!layer) + return; + bool hasOverflowScroll = m_foregroundLayer || m_contentLayer->contentIsScrollable(); + bool layerNeedsOverflow = layer->hasOverflowScroll(); + bool iframeNeedsOverflow = layer->isRootLayer() && + layer->renderer()->frame()->ownerRenderer() && + layer->renderer()->frame()->view()->hasOverflowScroll(); + + if (hasOverflowScroll && (layerNeedsOverflow || iframeNeedsOverflow)) { + // Already has overflow layers. + return; + } + if (!hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow) { + // Does not need overflow layers. + return; + } + if (layerNeedsOverflow || iframeNeedsOverflow) { + ASSERT(!hasOverflowScroll); + if (layerNeedsOverflow) { + ASSERT(!m_foregroundLayer && !m_foregroundClipLayer); + m_foregroundLayer = new ScrollableLayerAndroid(); + m_foregroundClipLayer = new LayerAndroid(false); + m_foregroundClipLayer->setMasksToBounds(true); + m_foregroundClipLayer->addChild(m_foregroundLayer); + m_contentLayer->addChild(m_foregroundClipLayer); + } else { + ASSERT(iframeNeedsOverflow && !m_contentLayer->contentIsScrollable()); + // No need to copy the children as they will be removed and synced. + m_contentLayer->removeChildren(); + // Replace the content layer with a scrollable layer. + LayerAndroid* layer = new ScrollableLayerAndroid(*m_contentLayer); + m_contentLayer->unref(); + m_contentLayer = layer; + if (m_parent) { + // The content layer has changed so the parent needs to sync + // children. + static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true; + } + } + // Need to rebuild our children based on the new structure. + m_needsSyncChildren = true; + askForSync(); + } else { + ASSERT(hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow); + ASSERT(m_contentLayer); + // Remove the foreground layers. + if (m_foregroundLayer) { + m_foregroundLayer->unref(); + m_foregroundLayer = 0; + m_foregroundClipLayer->unref(); + m_foregroundClipLayer = 0; + } + // No need to copy over children. + m_contentLayer->removeChildren(); + LayerAndroid* layer = new LayerAndroid(*m_contentLayer); + m_contentLayer->unref(); + m_contentLayer = layer; + if (m_parent) { + // The content layer has changed so the parent needs to sync + // children. + static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true; + } + // Children are all re-parented. + m_needsSyncChildren = true; + askForSync(); + } +#endif +} + bool GraphicsLayerAndroid::repaint() { LOG("(%x) repaint(), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ", @@ -506,8 +564,13 @@ bool GraphicsLayerAndroid::repaint() m_foregroundLayer->setSize(contentsRect.width(), contentsRect.height()); // Paint everything else into the main recording canvas. phase.clear(GraphicsLayerPaintBackground); - if (!paintContext(m_foregroundLayer->recordContext(), contentsRect)) - return false; + + // Paint at 0,0. + IntSize scroll = layer->scrolledContentOffset(); + layer->scrollToOffset(0, 0, true, false); + // At this point, it doesn't matter if painting failed. + (void) paintContext(m_foregroundLayer->recordContext(), contentsRect); + layer->scrollToOffset(scroll.width(), scroll.height(), true, false); // Construct the clip layer for masking the contents. IntRect clip = layer->renderer()->absoluteBoundingBoxRect(); @@ -830,10 +893,16 @@ void GraphicsLayerAndroid::syncChildren() { if (m_needsSyncChildren) { m_contentLayer->removeChildren(); - if (m_foregroundClipLayer) + LayerAndroid* layer = m_contentLayer; + if (m_foregroundClipLayer) { m_contentLayer->addChild(m_foregroundClipLayer); + // Use the scrollable content layer as the parent of the children so + // that they move with the content. + layer = m_foregroundLayer; + layer->removeChildren(); + } for (unsigned int i = 0; i < m_children.size(); i++) - m_contentLayer->addChild(m_children[i]->platformLayer()); + layer->addChild(m_children[i]->platformLayer()); m_needsSyncChildren = false; } } @@ -857,6 +926,7 @@ void GraphicsLayerAndroid::syncCompositingState() for (unsigned int i = 0; i < m_children.size(); i++) m_children[i]->syncCompositingState(); + updateScrollingLayers(); syncChildren(); syncMask(); diff --git a/WebCore/platform/graphics/android/GraphicsLayerAndroid.h b/WebCore/platform/graphics/android/GraphicsLayerAndroid.h index ce6bac1..da247ca 100644 --- a/WebCore/platform/graphics/android/GraphicsLayerAndroid.h +++ b/WebCore/platform/graphics/android/GraphicsLayerAndroid.h @@ -127,6 +127,7 @@ private: void syncMask(); void updateFixedPosition(); + void updateScrollingLayers(); // with SkPicture, we always repaint the entire layer's content. bool repaint(); diff --git a/WebCore/platform/graphics/android/TiledPage.cpp b/WebCore/platform/graphics/android/TiledPage.cpp index 620aa6f..36988dd 100644 --- a/WebCore/platform/graphics/android/TiledPage.cpp +++ b/WebCore/platform/graphics/android/TiledPage.cpp @@ -49,8 +49,6 @@ #endif // DEBUG -#define MAX_TILES 256 - namespace WebCore { using namespace android; @@ -65,7 +63,7 @@ TiledPage::TiledPage(int id, GLWebViewState* state) , m_latestPictureInval(0) , m_prepare(false) { - m_baseTiles = new BaseTile[MAX_TILES]; + m_baseTiles = new BaseTile[TilesManager::getMaxTextureAllocation() + 1]; #ifdef DEBUG_COUNT ClassTracker::instance()->increment("TiledPage"); #endif diff --git a/WebCore/platform/graphics/android/TilesManager.cpp b/WebCore/platform/graphics/android/TilesManager.cpp index 571d9cc..0fb3b1b 100644 --- a/WebCore/platform/graphics/android/TilesManager.cpp +++ b/WebCore/platform/graphics/android/TilesManager.cpp @@ -58,7 +58,7 @@ // at least 5 * 3 = 15 textures. We can also enable offscreen textures #define EXPANDED_TILE_BOUNDS_X 1 #define EXPANDED_TILE_BOUNDS_Y 4 -#define MAX_TEXTURE_ALLOCATION (5+EXPANDED_TILE_BOUNDS_X*2)*(3+EXPANDED_TILE_BOUNDS_Y*2)*2 +#define MAX_TEXTURE_ALLOCATION (5+1+EXPANDED_TILE_BOUNDS_X*2)*(3+1+EXPANDED_TILE_BOUNDS_Y*2)*2 #define TILE_WIDTH 300 #define TILE_HEIGHT 300 @@ -78,6 +78,11 @@ GLint TilesManager::getMaxTextureSize() return maxTextureSize; } +int TilesManager::getMaxTextureAllocation() +{ + return MAX_TEXTURE_ALLOCATION; +} + TilesManager::TilesManager() : m_layersMemoryUsage(0) , m_maxTextureCount(0) @@ -369,7 +374,8 @@ int TilesManager::maxTextureCount() void TilesManager::setMaxTextureCount(int max) { XLOG("setMaxTextureCount: %d", max); - if (m_maxTextureCount >= max && m_maxTextureCount) + if (max > MAX_TEXTURE_ALLOCATION || + (m_maxTextureCount >= max && m_maxTextureCount)) return; android::Mutex::Autolock lock(m_texturesLock); diff --git a/WebCore/platform/graphics/android/TilesManager.h b/WebCore/platform/graphics/android/TilesManager.h index eeb38fe..29b7fc1 100644 --- a/WebCore/platform/graphics/android/TilesManager.h +++ b/WebCore/platform/graphics/android/TilesManager.h @@ -45,6 +45,7 @@ class TilesManager { public: static TilesManager* instance(); static GLint getMaxTextureSize(); + static int getMaxTextureAllocation(); static bool hardwareAccelerationEnabled() { diff --git a/WebCore/platform/graphics/android/android_graphics.cpp b/WebCore/platform/graphics/android/android_graphics.cpp index c046858..e50cfec 100644 --- a/WebCore/platform/graphics/android/android_graphics.cpp +++ b/WebCore/platform/graphics/android/android_graphics.cpp @@ -109,14 +109,8 @@ void CursorRing::draw(SkCanvas* canvas, LayerAndroid* layer, IntRect* inval) inval->unite(m_lastBounds); } -bool CursorRing::setup() +void CursorRing::setIsButton(const CachedNode* node) { - m_node->localCursorRings(m_frame, &m_rings); - if (!m_rings.size()) { - DBG_NAV_LOG("!rings.size()"); - m_viewImpl->m_hasCursorBounds = false; - return false; - } m_isButton = false; m_viewImpl->gButtonMutex.lock(); // If this is a button drawn by us (rather than webkit) do not draw the @@ -124,7 +118,7 @@ bool CursorRing::setup() // Should be in sync with recordButtons, since that will be called // before this. if (m_viewImpl->m_buttons.size() > 0) { - WebCore::Node* cursorPointer = (WebCore::Node*) m_node->nodePointer(); + WebCore::Node* cursorPointer = (WebCore::Node*) node->nodePointer(); Container* end = m_viewImpl->m_buttons.end(); for (Container* ptr = m_viewImpl->m_buttons.begin(); ptr != end; ptr++) { if (ptr->matches(cursorPointer)) { @@ -134,6 +128,17 @@ bool CursorRing::setup() } } m_viewImpl->gButtonMutex.unlock(); +} + +bool CursorRing::setup() +{ + m_node->localCursorRings(m_frame, &m_rings); + if (!m_rings.size()) { + DBG_NAV_LOG("!rings.size()"); + m_viewImpl->m_hasCursorBounds = false; + return false; + } + setIsButton(m_node); m_bounds = m_node->localBounds(m_frame); m_viewImpl->updateCursorBounds(m_root, m_frame, m_node); diff --git a/WebCore/platform/graphics/android/android_graphics.h b/WebCore/platform/graphics/android/android_graphics.h index 9f52a27..be309a6 100644 --- a/WebCore/platform/graphics/android/android_graphics.h +++ b/WebCore/platform/graphics/android/android_graphics.h @@ -54,6 +54,7 @@ public: CursorRing(WebViewCore* core) : m_viewImpl(core) {} virtual ~CursorRing() {} virtual void draw(SkCanvas* , LayerAndroid* , IntRect* ); + void setIsButton(const CachedNode* ); bool setup(); private: friend class WebView; diff --git a/WebCore/rendering/RenderLayerBacking.cpp b/WebCore/rendering/RenderLayerBacking.cpp index 48aa3ec..0d39f7a 100644 --- a/WebCore/rendering/RenderLayerBacking.cpp +++ b/WebCore/rendering/RenderLayerBacking.cpp @@ -1021,14 +1021,6 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* bool selectionOnly = paintBehavior & PaintBehaviorSelectionOnly; if (shouldPaint && (paintingPhase & GraphicsLayerPaintForeground)) { -#if ENABLE(ANDROID_OVERFLOW_SCROLL) - // Scroll to 0,0 and paint the entire contents, then scroll back the - // the original offset. - int x = m_owningLayer->scrollXOffset(); - int y = m_owningLayer->scrollYOffset(); - if (m_owningLayer->hasOverflowScroll()) - m_owningLayer->scrollToOffset(0, 0, false, false); -#endif // Set up the clip used when painting our children. setClip(context, paintDirtyRect, clipRectToApply); PaintInfo paintInfo(context, clipRectToApply, @@ -1067,10 +1059,6 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* // Now walk the sorted list of children with positive z-indices. m_owningLayer->paintList(m_owningLayer->posZOrderList(), rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, 0, 0); -#if ENABLE(ANDROID_OVERFLOW_SCROLL) - if (m_owningLayer->hasOverflowScroll()) - m_owningLayer->scrollToOffset(x, y, false, false); -#endif } if (shouldPaint && (paintingPhase & GraphicsLayerPaintMask)) { diff --git a/WebCore/rendering/RenderLayerCompositor.cpp b/WebCore/rendering/RenderLayerCompositor.cpp index f31ab9d..9775134 100644 --- a/WebCore/rendering/RenderLayerCompositor.cpp +++ b/WebCore/rendering/RenderLayerCompositor.cpp @@ -1288,6 +1288,10 @@ bool RenderLayerCompositor::clippedByAncestor(RenderLayer* layer) const // into the hierarchy between this layer and its children in the z-order hierarchy. bool RenderLayerCompositor::clipsCompositingDescendants(const RenderLayer* layer) const { +#if ENABLE(ANDROID_OVERFLOW_SCROLL) + if (layer->hasOverflowScroll()) + return false; +#endif return layer->hasCompositingDescendant() && (layer->renderer()->hasOverflowClip() || layer->renderer()->hasClip()); } diff --git a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp index fb5701a..980c03e 100644 --- a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp +++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp @@ -87,8 +87,6 @@ void ChromeClientAndroid::attachRootGraphicsLayer(WebCore::Frame*, WebCore::Grap { // frame is not used in Android as we should only get root graphics layer for the main frame m_rootGraphicsLayer = layer; - if (!layer) - return; scheduleCompositingLayerSync(); } diff --git a/WebKit/android/WebCoreSupport/WebRequest.cpp b/WebKit/android/WebCoreSupport/WebRequest.cpp index fd6bbe2..a14036f 100644 --- a/WebKit/android/WebCoreSupport/WebRequest.cpp +++ b/WebKit/android/WebCoreSupport/WebRequest.cpp @@ -116,10 +116,28 @@ const std::string& WebRequest::getUserAgent() const return m_userAgent; } +#ifdef LOG_REQUESTS +namespace { +int remaining = 0; +} +#endif + void WebRequest::finish(bool success) { m_runnableFactory.RevokeAll(); - ASSERT(m_loadState < Finished, "called finish on an already finished WebRequest (%d)", m_loadState); + ASSERT(m_loadState < Finished, "(%p) called finish on an already finished WebRequest (%d) (%s)", this, m_loadState, m_url.c_str()); + if (m_loadState >= Finished) + return; +#ifdef LOG_REQUESTS + time_t finish; + time(&finish); + finish = finish - m_startTime; + struct tm * timeinfo; + char buffer[80]; + timeinfo = localtime(&finish); + strftime(buffer, 80, "Time: %M:%S",timeinfo); + android_printLog(ANDROID_LOG_DEBUG, "KM", "(%p) finish (%d) (%s) (%d) (%s)", this, --remaining, buffer, success, m_url.c_str()); +#endif // Make sure WebUrlLoaderClient doesn't delete us in the middle of this method. scoped_refptr<WebRequest> guard(this); @@ -183,6 +201,10 @@ void WebRequest::updateLoadFlags(int& loadFlags) void WebRequest::start() { ASSERT(m_loadState == Created, "Start called on a WebRequest not in CREATED state: (%s)", m_url.c_str()); +#ifdef LOG_REQUESTS + android_printLog(ANDROID_LOG_DEBUG, "KM", "(%p) start (%d) (%s)", this, ++remaining, m_url.c_str()); + time(&m_startTime); +#endif m_loadState = Started; diff --git a/WebKit/android/WebCoreSupport/WebRequest.h b/WebKit/android/WebCoreSupport/WebRequest.h index ae386fd..dba7559 100644 --- a/WebKit/android/WebCoreSupport/WebRequest.h +++ b/WebKit/android/WebCoreSupport/WebRequest.h @@ -113,6 +113,9 @@ private: ScopedRunnableMethodFactory<WebRequest> m_runnableFactory; bool m_wantToPause; bool m_isPaused; +#ifdef LOG_REQUESTS + time_t m_startTime; +#endif }; } // namespace android diff --git a/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp b/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp index 636f7be..642a81a 100644 --- a/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp +++ b/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp @@ -87,6 +87,8 @@ bool WebUrlLoaderClient::isActive() const { if (m_cancelling) return false; + if (!m_resourceHandle) + return false; if (!m_resourceHandle->client()) return false; if (m_finished) diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp index 8c0fade..6e6196a 100644 --- a/WebKit/android/jni/WebViewCore.cpp +++ b/WebKit/android/jni/WebViewCore.cpp @@ -2234,7 +2234,7 @@ String WebViewCore::modifySelectionTextNavigationAxis(DOMSelection* selection, i // the text content, rather its container, is highlighted. Node* focusNode = selection->focusNode(); if (focusNode->isElementNode()) { - focusNode = getImplicitAnchorOrFocusNode(selection->focusNode(), + focusNode = getImplicitBoundaryNode(selection->focusNode(), selection->focusOffset(), direction); if (!focusNode) return String(); @@ -2270,9 +2270,9 @@ String WebViewCore::modifySelectionTextNavigationAxis(DOMSelection* selection, i // Enforce that the selection does not cross anchor boundaries. This is // a workaround for the asymmetric behavior of WebKit while crossing // anchors. - anchorNode = getImplicitAnchorOrFocusNode(selection->anchorNode(), + anchorNode = getImplicitBoundaryNode(selection->anchorNode(), selection->anchorOffset(), direction); - focusNode = getImplicitAnchorOrFocusNode(selection->focusNode(), + focusNode = getImplicitBoundaryNode(selection->focusNode(), selection->focusOffset(), direction); if (anchorNode && focusNode && anchorNode != focusNode) { Node* inputControl = getIntermediaryInputElement(anchorNode, focusNode, @@ -2357,7 +2357,7 @@ String WebViewCore::modifySelectionTextNavigationAxis(DOMSelection* selection, i return markup; } -Node* WebViewCore::getImplicitAnchorOrFocusNode(Node* node, unsigned offset, int direction) +Node* WebViewCore::getImplicitBoundaryNode(Node* node, unsigned offset, int direction) { if (node->offsetInCharacters()) return node; @@ -2404,7 +2404,7 @@ Node* WebViewCore::getNextAnchorNode(Node* anchorNode, bool ignoreFirstNode, int void WebViewCore::advanceAnchorNode(DOMSelection* selection, int direction, String& markup, bool ignoreFirstNode, ExceptionCode& ec) { - Node* anchorNode = getImplicitAnchorOrFocusNode(selection->anchorNode(), + Node* anchorNode = getImplicitBoundaryNode(selection->anchorNode(), selection->anchorOffset(), direction); if (!anchorNode) { ec = NOT_FOUND_ERR; @@ -2689,8 +2689,7 @@ String WebViewCore::formatMarkup(DOMSelection* selection) Node* nextNode = currentNode->traverseNextNode(); if (!isVisible(currentNode)) { if (currentRange) { - markup = markup + stripAppleSpanFromMarkup( - currentRange->toHTML()).utf8().data(); + markup = markup + currentRange->toHTML().utf8().data(); currentRange = 0; } } else { @@ -2715,8 +2714,7 @@ String WebViewCore::formatMarkup(DOMSelection* selection) wholeRange->endOffset(), ec); if (ec) break; - markup = markup + stripAppleSpanFromMarkup( - currentRange->toHTML()).utf8().data(); + markup = markup + currentRange->toHTML().utf8().data(); } else { if (currentNode->offsetInCharacters()) currentRange->setEnd(currentNode, @@ -2733,18 +2731,6 @@ String WebViewCore::formatMarkup(DOMSelection* selection) return markup.stripWhiteSpace(); } -String WebViewCore::stripAppleSpanFromMarkup(String markup) -{ - int fromIdx = markup.find("<span class=\"Apple-style-span\""); - while (fromIdx > -1) { - int toIdx = markup.find(">"); - markup = markup.replace(fromIdx, toIdx - fromIdx + 1, ""); - markup = markup.replace("</span>", ""); - fromIdx = markup.find("<span class=\"Apple-style-span\""); - } - return markup; -} - void WebViewCore::selectAt(int x, int y) { JNIEnv* env = JSC::Bindings::getJNIEnv(); diff --git a/WebKit/android/jni/WebViewCore.h b/WebKit/android/jni/WebViewCore.h index d38be79..411be1c 100644 --- a/WebKit/android/jni/WebViewCore.h +++ b/WebKit/android/jni/WebViewCore.h @@ -671,13 +671,12 @@ namespace android { Node* m_currentNodeDomNavigationAxis; void scrollNodeIntoView(Frame* frame, Node* node); bool isContentTextNode(Node* node); - String stripAppleSpanFromMarkup(String markup); Node* getIntermediaryInputElement(Node* fromNode, Node* toNode, int direction); bool isContentInputElement(Node* node); bool isDescendantOf(Node* parent, Node* node); void advanceAnchorNode(DOMSelection* selection, int direction, String& markup, bool ignoreFirstNode, ExceptionCode& ec); Node* getNextAnchorNode(Node* anchorNode, bool skipFirstHack, int direction); - Node* getImplicitAnchorOrFocusNode(Node* node, unsigned offset, int direction); + Node* getImplicitBoundaryNode(Node* node, unsigned offset, int direction); #if ENABLE(TOUCH_EVENTS) bool m_forwardingTouchEvents; diff --git a/WebKit/android/nav/CacheBuilder.cpp b/WebKit/android/nav/CacheBuilder.cpp index 56bce1e..d2ae0a4 100644 --- a/WebKit/android/nav/CacheBuilder.cpp +++ b/WebKit/android/nav/CacheBuilder.cpp @@ -547,6 +547,7 @@ void CacheBuilder::Debug::groups() { IntRect clipBounds = IntRect(0, 0, INT_MAX, INT_MAX); IntRect focusBounds = IntRect(0, 0, INT_MAX, INT_MAX); IntRect* rectPtr = &focusBounds; + int imageCount = 0; if (node->isTextNode()) { Text* textNode = (Text*) node; if (CacheBuilder::ConstructTextRects(textNode, 0, textNode, @@ -556,7 +557,7 @@ void CacheBuilder::Debug::groups() { } else { IntRect nodeBounds = node->getRect(); if (CacheBuilder::ConstructPartRects(node, nodeBounds, rectPtr, - globalOffsetX, globalOffsetY, &rects) == false) + globalOffsetX, globalOffsetY, &rects, &imageCount) == false) continue; } unsigned arraySize = rects.size(); @@ -592,8 +593,8 @@ void CacheBuilder::Debug::groups() { mIndex += snprintf(&mBuffer[mIndex], mBufferSize - mIndex, ", %d, %d, %d, %d", textBox->x(), textBox->y(), textBox->logicalWidth(), textBox->logicalHeight()); int baseline = textBox->renderer()->style(textBox->isFirstLineStyle())->font().ascent(); - mIndex += snprintf(&mBuffer[mIndex], mBufferSize - mIndex, ", %d }, // %d ", - baseline, ++rectIndex); + mIndex += snprintf(&mBuffer[mIndex], mBufferSize - mIndex, ", %d, %d }, // %d ", + baseline, imageCount, ++rectIndex); wideString(node->textContent().characters() + textBox->start(), textBox->len(), true); DUMP_NAV_LOGD("%.*s\n", mIndex, mBuffer); textBox = textBox->nextTextBox(); @@ -1129,6 +1130,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, bool isFocus = node == focused; bool takesFocus = false; int columnGap = 0; + int imageCount = 0; TextDirection direction = LTR; String exported; CachedNodeType type = NORMAL_CACHEDNODETYPE; @@ -1328,7 +1330,8 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, cachedNode.setBounds(bounds); cachedNode.mCursorRing.append(bounds); } else if (ConstructPartRects(node, bounds, &cachedNode.mBounds, - globalOffsetX, globalOffsetY, &cachedNode.mCursorRing) == false) + globalOffsetX, globalOffsetY, &cachedNode.mCursorRing, + &imageCount) == false) continue; keepTextNode: if (nodeRenderer) { // area tags' node->renderer() == 0 @@ -1412,6 +1415,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, cachedNode.setOriginalAbsoluteBounds(originalAbsBounds); cachedNode.setParentIndex(last->mCachedNodeIndex); cachedNode.setParentGroup(ParentWithChildren(node)); + cachedNode.setSingleImage(imageCount == 1); cachedNode.setTabIndex(tabIndex); cachedNode.setType(type); if (type == TEXT_INPUT_CACHEDNODETYPE) { @@ -3024,7 +3028,8 @@ bool CacheBuilder::AddPartRect(IntRect& bounds, int x, int y, } bool CacheBuilder::ConstructPartRects(Node* node, const IntRect& bounds, - IntRect* focusBounds, int x, int y, WTF::Vector<IntRect>* result) + IntRect* focusBounds, int x, int y, WTF::Vector<IntRect>* result, + int* imageCountPtr) { WTF::Vector<ClipColumnTracker> clipTracker(1); ClipColumnTracker* baseTracker = clipTracker.data(); // sentinel @@ -3075,6 +3080,7 @@ bool CacheBuilder::ConstructPartRects(Node* node, const IntRect& bounds, bounds.intersect(clipBounds); if (AddPartRect(bounds, x, y, result, focusBounds) == false) return false; + *imageCountPtr += 1; continue; } if (hasClip == false) { diff --git a/WebKit/android/nav/CacheBuilder.h b/WebKit/android/nav/CacheBuilder.h index d229df0..d48a045 100644 --- a/WebKit/android/nav/CacheBuilder.h +++ b/WebKit/android/nav/CacheBuilder.h @@ -83,7 +83,8 @@ public: void allowAllTextDetection() { mAllowableTypes = ALL_CACHEDNODE_BITS; } void buildCache(CachedRoot* root); static bool ConstructPartRects(Node* node, const IntRect& bounds, - IntRect* focusBounds, int x, int y, WTF::Vector<IntRect>* result); + IntRect* focusBounds, int x, int y, WTF::Vector<IntRect>* result, + int* imageCountPtr); Node* currentFocus() const; void disallowAddressDetection() { mAllowableTypes = (CachedNodeBits) ( mAllowableTypes & ~ADDRESS_CACHEDNODE_BIT); } diff --git a/WebKit/android/nav/CachedFrame.cpp b/WebKit/android/nav/CachedFrame.cpp index b25ad7d..419be14 100644 --- a/WebKit/android/nav/CachedFrame.cpp +++ b/WebKit/android/nav/CachedFrame.cpp @@ -153,11 +153,9 @@ bool CachedFrame::checkBetween(BestData* best, Direction direction) } bool CachedFrame::checkRings(const CachedNode* node, - const WTF::Vector<WebCore::IntRect>& rings, - const WebCore::IntRect& nodeBounds, const WebCore::IntRect& testBounds) const { - return mRoot->checkRings(picture(node), rings, nodeBounds, testBounds); + return mRoot->checkRings(picture(node), node, testBounds); } bool CachedFrame::checkVisited(const CachedNode* node, Direction direction) const diff --git a/WebKit/android/nav/CachedFrame.h b/WebKit/android/nav/CachedFrame.h index 8ca73cf..470f522 100644 --- a/WebKit/android/nav/CachedFrame.h +++ b/WebKit/android/nav/CachedFrame.h @@ -83,8 +83,6 @@ public: WebCore::IntRect unadjustBounds(const CachedNode*, const WebCore::IntRect& ) const; bool checkRings(const CachedNode* node, - const WTF::Vector<WebCore::IntRect>& rings, - const WebCore::IntRect& nodeBounds, const WebCore::IntRect& testBounds) const; bool checkVisited(const CachedNode* , CachedFrame::Direction ) const; size_t childCount() { return mCachedFrames.size(); } diff --git a/WebKit/android/nav/CachedNode.cpp b/WebKit/android/nav/CachedNode.cpp index 4ba7b48..e3ba34d 100644 --- a/WebKit/android/nav/CachedNode.cpp +++ b/WebKit/android/nav/CachedNode.cpp @@ -110,7 +110,7 @@ void CachedNode::fixUpCursorRects(const CachedFrame* frame) mFixedUpCursorRects = true; // if the hit-test rect doesn't intersect any other rect, use it if (mHitBounds != mBounds && mHitBounds.contains(mBounds) && - frame->checkRings(this, mCursorRing, mBounds, mHitBounds)) { + frame->checkRings(this, mHitBounds)) { DBG_NAV_LOGD("use mHitBounds (%d,%d,%d,%d)", mHitBounds.x(), mHitBounds.y(), mHitBounds.width(), mHitBounds.height()); mUseHitBounds = true; @@ -122,7 +122,7 @@ void CachedNode::fixUpCursorRects(const CachedFrame* frame) // any other cursor ring bounds, use it IntRect sloppyBounds = mBounds; sloppyBounds.inflate(2); // give it a couple of extra pixels - if (frame->checkRings(this, mCursorRing, mBounds, sloppyBounds)) { + if (frame->checkRings(this, sloppyBounds)) { DBG_NAV_LOGD("use mBounds (%d,%d,%d,%d)", mBounds.x(), mBounds.y(), mBounds.width(), mBounds.height()); mUseBounds = true; @@ -424,6 +424,7 @@ void CachedNode::Debug::print() const DEBUG_PRINT_BOOL(mLast); DEBUG_PRINT_BOOL(mUseBounds); DEBUG_PRINT_BOOL(mUseHitBounds); + DEBUG_PRINT_BOOL(mSingleImage); } #endif diff --git a/WebKit/android/nav/CachedNode.h b/WebKit/android/nav/CachedNode.h index 961018b..f9bcbed 100644 --- a/WebKit/android/nav/CachedNode.h +++ b/WebKit/android/nav/CachedNode.h @@ -145,8 +145,10 @@ public: void* parentGroup() const { return mParentGroup; } int parentIndex() const { return mParentIndex; } bool partRectsContains(const CachedNode* other) const; + const WebCore::IntRect& rawBounds() const { return mBounds; } void reset(); WebCore::IntRect ring(const CachedFrame* , size_t part) const; + const WTF::Vector<WebCore::IntRect>& rings() const { return mCursorRing; } void setBounds(const WebCore::IntRect& bounds) { mBounds = bounds; } void setClippedOut(bool clipped) { mClippedOut = clipped; } void setColorIndex(int index) { mColorIndex = index; } @@ -170,9 +172,11 @@ public: void setNavableRects() { mNavableRects = mCursorRing.size(); } void setParentGroup(void* group) { mParentGroup = group; } void setParentIndex(int parent) { mParentIndex = parent; } + void setSingleImage(bool single) { mSingleImage = single; } void setTabIndex(int index) { mTabIndex = index; } void setType(CachedNodeType type) { mType = type; } void show() { mIsHidden = false; } + bool singleImage() const { return mSingleImage; } int tabIndex() const { return mTabIndex; } int textInputIndex() const { return isTextInput() ? mDataIndex : -1; } const CachedNode* traverseNextNode() const { return mLast ? NULL : &this[1]; } @@ -210,6 +214,7 @@ private: bool mIsTransparent : 1; bool mIsUnclipped : 1; bool mLast : 1; // true if this is the last node in a group + bool mSingleImage : 1; bool mUseBounds : 1; bool mUseHitBounds : 1; #ifdef BROWSER_DEBUG diff --git a/WebKit/android/nav/CachedRoot.cpp b/WebKit/android/nav/CachedRoot.cpp index 2f0e74d..2662071 100644 --- a/WebKit/android/nav/CachedRoot.cpp +++ b/WebKit/android/nav/CachedRoot.cpp @@ -131,104 +131,6 @@ public: #define kMargin 16 #define kSlop 2 -class BoundsCheck : public CommonCheck { -public: - BoundsCheck() { - mAllDrawnIn.setEmpty(); - mLastAll.setEmpty(); - mLastOver.setEmpty(); - } - - static int Area(SkIRect test) { - return test.width() * test.height(); - } - - void checkLast() { - if (mAllDrawnIn.isEmpty()) - return; - if (mLastAll.isEmpty() || Area(mLastAll) < Area(mAllDrawnIn)) { - mLastAll = mAllDrawnIn; - mDrawnOver.setEmpty(); - } - mAllDrawnIn.setEmpty(); - } - - bool hidden() { - return (mLastAll.isEmpty() && mLastOver.isEmpty()) || - mDrawnOver.contains(mBounds); - } - - virtual bool onIRect(const SkIRect& rect) { - if (joinGlyphs(rect)) - return false; - bool interestingType = mType == kDrawBitmap_Type - || mType == kDrawSprite_Type - || mType == kDrawRect_Type || isTextType(mType); - if (SkIRect::Intersects(mBounds, rect) == false) { - DBG_NAV_LOGD("BoundsCheck (no intersect) rect={%d,%d,%d,%d}" - " mType=%s", rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, - TypeNames[mType]); - if (interestingType) - checkLast(); - return false; - } - if (interestingType == false) - return false; - if (!mDrawnOver.contains(rect) && (mBoundsSlop.contains(rect) || - (mBounds.fLeft == rect.fLeft && mBounds.fRight == rect.fRight && - mBounds.fTop >= rect.fTop && mBounds.fBottom <= rect.fBottom) || - (mBounds.fTop == rect.fTop && mBounds.fBottom == rect.fBottom && - mBounds.fLeft >= rect.fLeft && mBounds.fRight <= rect.fRight))) { - mDrawnOver.setEmpty(); - mAllDrawnIn.join(rect); - DBG_NAV_LOGD("BoundsCheck (contains) rect={%d,%d,%d,%d}" - " mAllDrawnIn={%d,%d,%d,%d} mType=%s", - rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, - mAllDrawnIn.fLeft, mAllDrawnIn.fTop, mAllDrawnIn.fRight, - mAllDrawnIn.fBottom, TypeNames[mType]); - } else { - checkLast(); - if (!isTextType(mType)) { - if ( -#if 0 -// should the opaqueness of the bitmap disallow its ability to draw over? -// not sure that this test is needed - (mType != kDrawBitmap_Type || - (mIsOpaque && mAllOpaque)) && -#endif - mLastAll.isEmpty() == false) - mDrawnOver.op(rect, SkRegion::kUnion_Op); - } else { -// FIXME -// sometimes the text is not drawn entirely inside the cursor area, even though -// it is the correct text. Until I figure out why, I allow text drawn at the -// end that is not covered up by something else to represent the link -// example that triggers this that should be figured out: -// http://cdn.labpixies.com/campaigns/blackjack/blackjack.html?lang=en&country=US&libs=assets/feature/core -// ( http://tinyurl.com/ywsyzb ) - mLastOver = rect; - } -#if DEBUG_NAV_UI - const SkIRect& drawnOver = mDrawnOver.getBounds(); - DBG_NAV_LOGD("(overlaps) rect={%d,%d,%d,%d}" - " mDrawnOver={%d,%d,%d,%d} mType=%s mIsOpaque=%s mAllOpaque=%s", - rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, - drawnOver.fLeft, drawnOver.fTop, drawnOver.fRight, drawnOver.fBottom, - TypeNames[mType], mIsOpaque ? "true" : "false", - mAllOpaque ? "true" : "false"); -#endif - } - return false; - } - - SkIRect mBounds; - SkIRect mBoundsSlop; - SkRegion mDrawnOver; - SkIRect mLastOver; - SkIRect mAllDrawnIn; - SkIRect mLastAll; -}; - class BoundsCanvas : public ParseCanvas { public: @@ -675,10 +577,12 @@ public: class RingCheck : public CommonCheck { public: RingCheck(const WTF::Vector<WebCore::IntRect>& rings, - const WebCore::IntRect& bitBounds, const WebCore::IntRect& testBounds) + const WebCore::IntRect& bitBounds, const WebCore::IntRect& testBounds, + bool singleImage) : mTestBounds(testBounds) , mBitBounds(bitBounds) , mPushPop(false) + , mSingleImage(singleImage) { const WebCore::IntRect* r; for (r = rings.begin(); r != rings.end(); r++) { @@ -910,7 +814,7 @@ protected: && mType != kDrawSprite_Type && mType != kDrawBitmap_Type) return false; if (mLayerTypes.isEmpty() || mLayerTypes.last() != mType - || !mAppendLikeTypes || mPushPop + || !mAppendLikeTypes || mPushPop || mSingleImage // if the last and current were not glyphs, // and the two bounds have a gap between, don't join them -- push // an empty between them @@ -1054,6 +958,7 @@ private: char mCh; bool mAppendLikeTypes; bool mPushPop; + bool mSingleImage; }; class RingCanvas : public BoundsCanvas { @@ -1205,16 +1110,16 @@ void CachedRoot::checkForJiggle(int* xDeltaPtr) const *xDeltaPtr = jiggleCheck.jiggle(); } -bool CachedRoot::checkRings(SkPicture* picture, - const WTF::Vector<WebCore::IntRect>& rings, - const WebCore::IntRect& nodeBounds, +bool CachedRoot::checkRings(SkPicture* picture, const CachedNode* node, const WebCore::IntRect& testBounds) const { if (!picture) return false; + const WTF::Vector<WebCore::IntRect>& rings = node->rings(); + const WebCore::IntRect& nodeBounds = node->rawBounds(); IntRect bitBounds; calcBitBounds(nodeBounds, &bitBounds); - RingCheck ringCheck(rings, bitBounds, testBounds); + RingCheck ringCheck(rings, bitBounds, testBounds, node->singleImage()); RingCanvas checker(&ringCheck); SkBitmap bitmap; bitmap.setConfig(SkBitmap::kARGB_8888_Config, bitBounds.width(), @@ -1576,7 +1481,7 @@ bool CachedRoot::maskIfHidden(BestData* best) const const WebCore::IntRect& bounds = bestNode->bounds(frame); IntRect bitBounds; calcBitBounds(bounds, &bitBounds); - RingCheck ringCheck(rings, bitBounds, bounds); + RingCheck ringCheck(rings, bitBounds, bounds, bestNode->singleImage()); RingCanvas checker(&ringCheck); SkBitmap bitmap; bitmap.setConfig(SkBitmap::kARGB_8888_Config, bitBounds.width(), diff --git a/WebKit/android/nav/CachedRoot.h b/WebKit/android/nav/CachedRoot.h index a09e4fb..1f8b851 100644 --- a/WebKit/android/nav/CachedRoot.h +++ b/WebKit/android/nav/CachedRoot.h @@ -52,8 +52,7 @@ public: void calcBitBounds(const IntRect& , IntRect* ) const; int checkForCenter(int x, int y) const; void checkForJiggle(int* ) const; - bool checkRings(SkPicture* , const WTF::Vector<WebCore::IntRect>& rings, - const WebCore::IntRect& nodeBounds, + bool checkRings(SkPicture* , const CachedNode* , const WebCore::IntRect& testBounds) const; WebCore::IntPoint cursorLocation() const; int documentHeight() { return mContents.height(); } diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp index 948ea6b..deb2b28 100644 --- a/WebKit/android/nav/WebView.cpp +++ b/WebKit/android/nav/WebView.cpp @@ -303,10 +303,8 @@ void nativeRecordButtons(bool hasFocus, bool pressed, bool invalidate) if (hasFocus) { if (pressed || m_ring.m_isPressed) state = RenderSkinAndroid::kPressed; - else if (SkTime::GetMSecs() < m_ringAnimationEnd - && m_ringAnimationEnd != UINT_MAX) { + else if (SkTime::GetMSecs() < m_ringAnimationEnd) state = RenderSkinAndroid::kFocused; - } } } ptr->updateFocusState(state); @@ -390,6 +388,7 @@ bool drawCursorPreamble(CachedRoot* root) resetCursorRing(); return false; } + m_ring.setIsButton(node); if (node->isHidden()) { DBG_NAV_LOG("node->isHidden()"); m_viewImpl->m_hasCursorBounds = false; @@ -473,6 +472,7 @@ bool drawGL(WebCore::IntRect& viewRect, float scale, int extras) SkPicture picture; IntRect rect(0, 0, 0, 0); + bool allowSame = false; if (extra) { LayerAndroid mainPicture(m_navPictureUI); PictureSet* content = m_baseLayer->content(); @@ -480,8 +480,15 @@ bool drawGL(WebCore::IntRect& viewRect, float scale, int extras) content->height()); extra->draw(canvas, &mainPicture, &rect); picture.endRecording(); + } else if (extras == DrawExtrasCursorRing && m_ring.m_isButton) { + const CachedFrame* cachedFrame; + const CachedNode* cachedCursor = root->currentCursor(&cachedFrame); + if (cachedCursor) { + rect = cachedCursor->bounds(cachedFrame); + allowSame = true; + } } - m_glWebViewState->setExtra(m_baseLayer, picture, rect); + m_glWebViewState->setExtra(m_baseLayer, picture, rect, allowSame); LayerAndroid* compositeLayer = compositeRoot(); if (compositeLayer) |