diff options
Diffstat (limited to 'Source')
18 files changed, 235 insertions, 147 deletions
diff --git a/Source/WebCore/bindings/v8/custom/V8DocumentCustom.cpp b/Source/WebCore/bindings/v8/custom/V8DocumentCustom.cpp index 7cad58e..d142a9f 100644 --- a/Source/WebCore/bindings/v8/custom/V8DocumentCustom.cpp +++ b/Source/WebCore/bindings/v8/custom/V8DocumentCustom.cpp @@ -43,6 +43,7 @@ #include "V8CanvasRenderingContext2D.h" #include "V8CustomXPathNSResolver.h" #include "V8DOMImplementation.h" +#include "V8DOMWrapper.h" #include "V8HTMLDocument.h" #include "V8IsolatedContext.h" #include "V8Node.h" @@ -144,9 +145,8 @@ v8::Handle<v8::Value> V8Document::createTouchListCallback(const v8::Arguments& a RefPtr<TouchList> touchList = TouchList::create(); for (int i = 0; i < args.Length(); i++) { - if (!args[i]->IsObject()) - return v8::Undefined(); - touchList->append(V8Touch::toNative(args[i]->ToObject())); + Touch* touch = V8DOMWrapper::isWrapperOfType(args[i], &V8Touch::info) ? V8Touch::toNative(args[i]->ToObject()) : 0; + touchList->append(touch); } return toV8(touchList.release()); diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp index ff50390..b6a1393 100644 --- a/Source/WebCore/dom/Document.cpp +++ b/Source/WebCore/dom/Document.cpp @@ -5064,15 +5064,9 @@ PassRefPtr<Touch> Document::createTouch(DOMWindow* window, EventTarget* target, // http://developer.apple.com/library/safari/#documentation/UserExperience/Reference/DocumentAdditionsReference/DocumentAdditions/DocumentAdditions.html // when this method should throw and nor is it by inspection of iOS behavior. It would be nice to verify any cases where it throws under iOS // and implement them here. See https://bugs.webkit.org/show_bug.cgi?id=47819 - // Ditto for the createTouchList method below. Frame* frame = window ? window->frame() : this->frame(); return Touch::create(frame, target, identifier, screenX, screenY, pageX, pageY); } - -PassRefPtr<TouchList> Document::createTouchList(ExceptionCode&) const -{ - return TouchList::create(); -} #endif DocumentLoader* Document::loader() const diff --git a/Source/WebCore/dom/Document.h b/Source/WebCore/dom/Document.h index a4fc266..ce82b2e 100644 --- a/Source/WebCore/dom/Document.h +++ b/Source/WebCore/dom/Document.h @@ -1085,7 +1085,6 @@ public: #if ENABLE(TOUCH_EVENTS) PassRefPtr<Touch> createTouch(DOMWindow*, EventTarget*, int identifier, int pageX, int pageY, int screenX, int screenY, ExceptionCode&) const; - PassRefPtr<TouchList> createTouchList(ExceptionCode&) const; #endif const DocumentTiming* timing() const { return &m_documentTiming; } diff --git a/Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp b/Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp index e26fa9e..7bed5bb 100644 --- a/Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp @@ -63,6 +63,7 @@ using namespace android; namespace WebCore { typedef std::pair<int, float> FallbackFontKey; + typedef HashMap<FallbackFontKey, FontPlatformData*> FallbackHash; static void updateForFont(SkPaint* paint, const SimpleFontData* font) { @@ -696,7 +697,17 @@ const FontPlatformData* TextRunWalker::setupComplexFont( { static FallbackHash fallbackPlatformData; - FallbackFontKey key(script, platformData.size()); + // generate scriptStyleIndex - we need unique hash IDs for each style + // of each script - normal, bold, italic, bolditalic. the first set of + // NUM_SCRIPTS are the normal style version, followed by bold, then + // italic, then bold italic. additional fake style bits can be added. + int scriptStyleIndex = script; + if (platformData.isFakeBold()) + scriptStyleIndex += NUM_SCRIPTS; + if (platformData.isFakeItalic()) + scriptStyleIndex += NUM_SCRIPTS << 1; + + FallbackFontKey key(scriptStyleIndex, platformData.size()); FontPlatformData* newPlatformData = 0; if (!fallbackPlatformData.contains(key)) { diff --git a/Source/WebCore/platform/graphics/android/fonts/FontCacheAndroid.cpp b/Source/WebCore/platform/graphics/android/fonts/FontCacheAndroid.cpp index 5696a46..4bb388c 100644 --- a/Source/WebCore/platform/graphics/android/fonts/FontCacheAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/fonts/FontCacheAndroid.cpp @@ -175,7 +175,7 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD } result = new FontPlatformData(tf, fontDescription.computedSize(), - (style & SkTypeface::kBold) && !tf->isBold(), + (style & SkTypeface::kBold), (style & SkTypeface::kItalic) && !tf->isItalic(), fontDescription.orientation(), fontDescription.textOrientation()); diff --git a/Source/WebCore/platform/graphics/android/fonts/FontPlatformData.h b/Source/WebCore/platform/graphics/android/fonts/FontPlatformData.h index 1e46971..02a0cea 100644 --- a/Source/WebCore/platform/graphics/android/fonts/FontPlatformData.h +++ b/Source/WebCore/platform/graphics/android/fonts/FontPlatformData.h @@ -92,6 +92,9 @@ public: HB_FaceRec_* harfbuzzFace() const; SkTypeface* typeface() const { return mTypeface; } + bool isFakeBold() const { return mFakeBold; } + bool isFakeItalic() const { return mFakeItalic; } + private: class RefCountedHarfbuzzFace : public RefCounted<RefCountedHarfbuzzFace> { public: diff --git a/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.cpp index 82af3bf..9ee97ac 100644 --- a/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.cpp @@ -84,7 +84,13 @@ void BaseLayerAndroid::updatePositionsRecursive(const SkRect& visibleContentRect updateLayerPositions(visibleContentRect); TransformationMatrix ident; - FloatRect clip(0, 0, getWidth(), getHeight()); + + // Start with an unnecessarily large clip, since the base layer can + // dynamically increase in size to cover the viewport, and we cache its draw + // clip. This way the base layer will never have it's visible area clipped + // by its m_clippingRect, only the viewport. + // Note: values larger than this suffer from floating point rounding issues + FloatRect clip(0, 0, 1e7, 1e7); bool forcePositionCalculation = !m_positionsCalculated; float scale = 1.0f; diff --git a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp index 293bbbc..d709a9c 100644 --- a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp @@ -122,6 +122,7 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer), m_transform = layer.m_transform; m_drawTransform = layer.m_drawTransform; + m_drawTransformUnfudged = layer.m_drawTransformUnfudged; m_childrenTransform = layer.m_childrenTransform; m_dirtyRegion = layer.m_dirtyRegion; @@ -272,6 +273,9 @@ void LayerAndroid::addDirtyArea() return; } + // TODO: rewrite this to handle partial invalidate, and to handle base + // layer's large clip correctly + IntSize layerSize(getSize().width(), getSize().height()); FloatRect area = @@ -283,6 +287,7 @@ void LayerAndroid::addDirtyArea() area.intersect(clip); IntRect dirtyArea(area.x(), area.y(), area.width(), area.height()); + state()->addDirtyArea(dirtyArea); } @@ -407,6 +412,7 @@ void LayerAndroid::updateLocalTransformAndClip(const TransformationMatrix& paren -originY, -anchorPointZ()); + m_drawTransformUnfudged = m_drawTransform; if (m_drawTransform.isIdentityOrTranslation() && surface() && surface()->allowTransformFudging()) { // adjust the translation coordinates of the draw transform matrix so @@ -455,9 +461,8 @@ void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentM setDrawOpacity(opacity); // constantly recalculate the draw transform of layers that may require it (and their children) - forceCalculation |= isPositionFixed() - || contentIsScrollable() - || (m_animations.size() != 0); + forceCalculation |= hasDynamicTransform(); + forceCalculation &= !(disableFixedElemUpdate && isPositionFixed()); if (forceCalculation) updateLocalTransformAndClip(parentMatrix, clipping); @@ -465,7 +470,7 @@ void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentM if (!countChildren() || !m_visible) return; - TransformationMatrix localMatrix = m_drawTransform; + TransformationMatrix localMatrix = m_drawTransformUnfudged; // Flatten to 2D if the layer doesn't preserve 3D. if (!preserves3D()) { @@ -682,7 +687,7 @@ void LayerAndroid::assignSurfaces(LayerMergeState* mergeState) mergeState->currentSurface->addLayer(this, m_drawTransform); m_surface = mergeState->currentSurface; - if (contentIsScrollable() || isPositionFixed()) { + if (hasDynamicTransform()) { // disable layer merging within the children of these layer types mergeState->nonMergeNestedLevel++; } @@ -704,7 +709,7 @@ void LayerAndroid::assignSurfaces(LayerMergeState* mergeState) mergeState->depth--; } - if (contentIsScrollable() || isPositionFixed()) { + if (hasDynamicTransform()) { // re-enable joining mergeState->nonMergeNestedLevel--; diff --git a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h index c56d50a..f821d89 100644 --- a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h @@ -166,7 +166,7 @@ public: void setPreserves3D(bool value) { m_preserves3D = value; } void setAnchorPointZ(float z) { m_anchorPointZ = z; } float anchorPointZ() { return m_anchorPointZ; } - void setDrawTransform(const TransformationMatrix& transform) { m_drawTransform = transform; } + void setDrawTransform(const TransformationMatrix& transform) { m_drawTransform = m_drawTransformUnfudged = transform; } virtual const TransformationMatrix* drawTransform() const { return &m_drawTransform; } void setChildrenTransform(const TransformationMatrix& t) { m_childrenTransform = t; } void setDrawClip(const FloatRect& rect) { m_clippingRect = rect; } @@ -300,11 +300,15 @@ protected: virtual void onDraw(SkCanvas*, SkScalar opacity, android::DrawExtra* extra, PaintStyle style); virtual InvalidateFlags onSetHwAccelerated(bool hwAccelerated) { return InvalidateNone; } TransformationMatrix m_drawTransform; + TransformationMatrix m_drawTransformUnfudged; int m_uniqueId; private: void updateLocalTransformAndClip(const TransformationMatrix& parentMatrix, const FloatRect& clip); + bool hasDynamicTransform() { + return contentIsScrollable() || isPositionFixed() || (m_animations.size() != 0); + } #if DUMP_NAV_CACHE friend class CachedLayer::Debug; // debugging access only diff --git a/Source/WebCore/platform/graphics/android/rendering/Surface.cpp b/Source/WebCore/platform/graphics/android/rendering/Surface.cpp index 9df1a7a..73466d3 100644 --- a/Source/WebCore/platform/graphics/android/rendering/Surface.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/Surface.cpp @@ -90,13 +90,24 @@ bool Surface::tryUpdateSurface(Surface* oldSurface) return true; } + SkRegion invalRegion; + bool fullInval = false; if (singleLayer() && oldSurface->singleLayer()) { // both are single matching layers, simply apply inval SkRegion* layerInval = getFirstLayer()->getInvalRegion(); - m_surfaceBacking->markAsDirty(*layerInval); + invalRegion = *layerInval; + + if (isBase()) { + // the base layer paints outside it's content area to ensure the + // viewport is convered, so fully invalidate all tiles if its size + // changes to ensure no stale content remains + LayerContent* newContent = getFirstLayer()->content(); + LayerContent* oldContent = oldSurface->getFirstLayer()->content(); + fullInval = newContent->width() != oldContent->width() + || newContent->height() != oldContent->height(); + } } else { - SkRegion invalRegion; - bool fullInval = m_layers.size() != oldSurface->m_layers.size(); + fullInval = m_layers.size() != oldSurface->m_layers.size(); if (!fullInval) { for (unsigned int i = 0; i < m_layers.size(); i++) { if ((m_layers[i]->uniqueId() != oldSurface->m_layers[i]->uniqueId()) @@ -111,16 +122,15 @@ bool Surface::tryUpdateSurface(Surface* oldSurface) FloatRect layerPos = m_layers[i]->fullContentAreaMapped(); m_layers[i]->getInvalRegion()->translate(layerPos.x(), layerPos.y()); invalRegion.op(*(m_layers[i]->getInvalRegion()), SkRegion::kUnion_Op); - break; } } } + } - if (fullInval) - invalRegion.setRect(-1e8, -1e8, 2e8, 2e8); + if (fullInval) + invalRegion.setRect(-1e8, -1e8, 2e8, 2e8); - m_surfaceBacking->markAsDirty(invalRegion); - } + m_surfaceBacking->markAsDirty(invalRegion); return true; } @@ -230,17 +240,15 @@ bool Surface::drawGL(bool layerTilesDisabled) if (singleLayer() && !getFirstLayer()->visible()) return false; - bool isBaseLayer = isBase() - || getFirstLayer()->subclassType() == LayerAndroid::FixedBackgroundImageLayer - || getFirstLayer()->subclassType() == LayerAndroid::ForegroundBaseLayer; - - FloatRect drawClip = getFirstLayer()->drawClip(); - if (!singleLayer()) { - for (unsigned int i = 1; i < m_layers.size(); i++) - drawClip.unite(m_layers[i]->drawClip()); + if (!isBase()) { + FloatRect drawClip = getFirstLayer()->drawClip(); + if (!singleLayer()) { + for (unsigned int i = 1; i < m_layers.size(); i++) + drawClip.unite(m_layers[i]->drawClip()); + } + FloatRect clippingRect = TilesManager::instance()->shader()->rectInInvViewCoord(drawClip); + TilesManager::instance()->shader()->clip(clippingRect); } - FloatRect clippingRect = TilesManager::instance()->shader()->rectInInvViewCoord(drawClip); - TilesManager::instance()->shader()->clip(clippingRect); bool askRedraw = false; if (m_surfaceBacking && !tilesDisabled) { diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp index 3cfabe1..1c769bf 100644 --- a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp @@ -151,10 +151,8 @@ void SurfaceCollection::addFrameworkInvals() bool SurfaceCollection::isReady() { // Override layer readiness check for single surface mode - if (m_compositedRoot->state()->isSingleSurfaceRenderingMode()) { - // TODO: single surface mode should be properly double buffered - return true; - } + if (m_compositedRoot->state()->isSingleSurfaceRenderingMode()) + return m_surfaces[0]->isReady(); for (unsigned int i = 0; i < m_surfaces.size(); i++) { if (!m_surfaces[i]->isReady()) { @@ -165,12 +163,6 @@ bool SurfaceCollection::isReady() return true; } -bool SurfaceCollection::isBaseSurfaceReady() -{ - // m_surfaces[0] should be the base surface when in single surface mode. - return m_surfaces[0]->isReady(); -} - bool SurfaceCollection::isMissingBackgroundContent() { // return true when the first surface is missing content (indicating the @@ -222,9 +214,9 @@ void SurfaceCollection::mergeInvalsInto(SurfaceCollection* replacementSurface) m_compositedRoot->mergeInvalsInto(replacementSurface->m_compositedRoot); } -void SurfaceCollection::evaluateAnimations(double currentTime) +bool SurfaceCollection::evaluateAnimations(double currentTime) { - m_compositedRoot->evaluateAnimations(currentTime); + return m_compositedRoot->evaluateAnimations(currentTime); } bool SurfaceCollection::hasCompositedLayers() diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.h b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.h index ff4195f..a903015 100644 --- a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.h +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.h @@ -54,7 +54,6 @@ public: void swapTiles(); void addFrameworkInvals(); bool isReady(); - bool isBaseSurfaceReady(); bool isMissingBackgroundContent(); void removePainterOperations(); void computeTexturesAmount(TexturesResult* result); @@ -63,7 +62,7 @@ public: void setIsPainting(SurfaceCollection* drawingSurfaceCollection); void setIsDrawing(); void mergeInvalsInto(SurfaceCollection* replacementSurfaceCollection); - void evaluateAnimations(double currentTime); + bool evaluateAnimations(double currentTime); bool hasCompositedLayers(); bool hasCompositedAnimations(); diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp index 724bf89..174720f 100644 --- a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp @@ -171,7 +171,8 @@ void SurfaceCollectionManager::updateScrollableLayer(int layerId, int x, int y) } -int SurfaceCollectionManager::singleSurfaceModeInvalidation(bool scrolling, +int SurfaceCollectionManager::singleSurfaceModeInvalidation(bool hasRunningAnimation, + bool scrolling, bool shouldDraw) { int returnFlags = 0; @@ -179,21 +180,28 @@ int SurfaceCollectionManager::singleSurfaceModeInvalidation(bool scrolling, // scrolling or have an incoming painting tree. bool requireDirtyAll = (m_previouslyScrolling && !scrolling) || m_newPaintingCollection; - if (requireDirtyAll) - TilesManager::instance()->dirtyAllTiles(); // We also need to tell the framework to continue to invoke until // the base layer is ready. bool drawingBaseSurfaceReady = m_drawingCollection - && m_drawingCollection->isBaseSurfaceReady(); + && m_drawingCollection->isReady(); + + // When the base layer is ready, we can ask the framework to draw. And if + // animation is running, dirty all the tiles, otherwise the animation will + // be paused. + if (drawingBaseSurfaceReady) { + if (!shouldDraw) + returnFlags |= DrawGlInfo::kStatusDraw; + else + requireDirtyAll |= hasRunningAnimation; + } + if (requireDirtyAll) + TilesManager::instance()->dirtyAllTiles(); + bool requireInvoke = requireDirtyAll || !drawingBaseSurfaceReady; if (requireInvoke) returnFlags |= DrawGlInfo::kStatusInvoke; - // When the base layer is ready, we can ask the framework to draw. - if (!shouldDraw && drawingBaseSurfaceReady) - returnFlags |= DrawGlInfo::kStatusDraw; - m_newPaintingCollection = false; m_previouslyScrolling = scrolling; @@ -246,9 +254,6 @@ int SurfaceCollectionManager::drawGL(double currentTime, IntRect& viewRect, if (m_paintingCollection) returnFlags |= DrawGlInfo::kStatusInvoke; - if (singleSurfaceMode) - returnFlags |= singleSurfaceModeInvalidation(scrolling, shouldDraw); - if (!shouldDraw) { if (didCollectionSwap || (!m_paintingCollection @@ -270,6 +275,7 @@ int SurfaceCollectionManager::drawGL(double currentTime, IntRect& viewRect, // Don't have a drawing collection, draw white background Color background = Color::white; bool drawBackground = true; + bool hasRunningAnimation = false; if (m_drawingCollection) { bool drawingReady = didCollectionSwap || m_drawingCollection->isReady(); @@ -288,7 +294,7 @@ int SurfaceCollectionManager::drawGL(double currentTime, IntRect& viewRect, returnFlags |= DrawGlInfo::kStatusInvoke; } - m_drawingCollection->evaluateAnimations(currentTime); + hasRunningAnimation = m_drawingCollection->evaluateAnimations(currentTime); ALOGV("drawing collection %p", m_drawingCollection); background = m_drawingCollection->getBackgroundColor(); @@ -298,6 +304,9 @@ int SurfaceCollectionManager::drawGL(double currentTime, IntRect& viewRect, background = m_paintingCollection->getBackgroundColor(); } + if (singleSurfaceMode) + returnFlags |= singleSurfaceModeInvalidation(hasRunningAnimation, + scrolling, shouldDraw); // Start doing the actual GL drawing. if (drawBackground) { ALOGV("background is %x", background.rgb()); diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.h b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.h index 6aed060..53b5bb6 100644 --- a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.h +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.h @@ -59,7 +59,7 @@ private: void swap(); void clearCollections(); void updatePaintingCollection(SurfaceCollection* newCollection); - int singleSurfaceModeInvalidation(bool scrolling, bool shouldDraw); + int singleSurfaceModeInvalidation(bool hasRunningAnimation, bool scrolling, bool shouldDraw); SurfaceCollection* m_drawingCollection; SurfaceCollection* m_paintingCollection; SurfaceCollection* m_queuedCollection; diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp index 161c0b2..c0766e4 100644 --- a/Source/WebKit/android/jni/WebViewCore.cpp +++ b/Source/WebKit/android/jni/WebViewCore.cpp @@ -401,7 +401,7 @@ struct WebViewCore::TextFieldInitDataGlue { jfieldID m_maxLength; jfieldID m_contentBounds; jfieldID m_nodeLayerId; - jfieldID m_contentRect; + jfieldID m_clientRect; }; /* @@ -526,7 +526,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m m_textFieldInitDataGlue->m_maxLength = env->GetFieldID(tfidClazz, "mMaxLength", "I"); m_textFieldInitDataGlue->m_contentBounds = env->GetFieldID(tfidClazz, "mContentBounds", "Landroid/graphics/Rect;"); m_textFieldInitDataGlue->m_nodeLayerId = env->GetFieldID(tfidClazz, "mNodeLayerId", "I"); - m_textFieldInitDataGlue->m_contentRect = env->GetFieldID(tfidClazz, "mContentRect", "Landroid/graphics/Rect;"); + m_textFieldInitDataGlue->m_clientRect = env->GetFieldID(tfidClazz, "mClientRect", "Landroid/graphics/Rect;"); m_textFieldInitDataGlue->m_constructor = GetJMethod(env, tfidClazz, "<init>", "()V"); env->DeleteLocalRef(tfidClazz); @@ -1507,6 +1507,7 @@ bool WebViewCore::selectWordAroundPosition(Frame* frame, VisiblePosition pos) VisibleSelection selection(pos); selection.expandUsingGranularity(WordGranularity); SelectionController* selectionController = frame->selection(); + selection = VisibleSelection(selection.start(), selection.end()); bool wordSelected = false; if (selectionController->shouldChangeSelection(selection)) { @@ -1566,7 +1567,8 @@ void WebViewCore::layerToAbsoluteOffset(const LayerAndroid* layer, IntPoint& off void WebViewCore::setSelectionCaretInfo(SelectText* selectTextContainer, const WebCore::Position& pos, const IntPoint& frameOffset, - SelectText::HandleId handleId, int caretRectOffset, EAffinity affinity) + SelectText::HandleId handleId, SelectText::HandleType handleType, + int caretRectOffset, EAffinity affinity) { Node* node = pos.anchorNode(); LayerAndroid* layer = 0; @@ -1584,6 +1586,7 @@ void WebViewCore::setSelectionCaretInfo(SelectText* selectTextContainer, caretRect.setX(absoluteOffset.x() - offset.x() + caretRectOffset); caretRect.setY(absoluteOffset.y() - offset.y()); selectTextContainer->setCaretRect(handleId, caretRect); + selectTextContainer->setHandleType(handleId, handleType); selectTextContainer->setTextRect(handleId, positionToTextRect(pos, affinity, offset)); } @@ -1604,11 +1607,11 @@ bool WebViewCore::isLtr(const Position& position) SelectText* WebViewCore::createSelectText(const VisibleSelection& selection) { bool isCaret = selection.isCaret(); + Position base = selection.base(); + Position extent = selection.extent(); if (selection.isNone() || (!selection.isContentEditable() && isCaret) - || !selection.start().anchorNode() - || !selection.start().anchorNode()->renderer() - || !selection.end().anchorNode() - || !selection.end().anchorNode()->renderer()) + || !base.anchorNode() || !base.anchorNode()->renderer() + || !extent.anchorNode() || !extent.anchorNode()->renderer()) return 0; RefPtr<Range> range = selection.firstRange(); @@ -1624,20 +1627,27 @@ SelectText* WebViewCore::createSelectText(const VisibleSelection& selection) IntPoint frameOffset = convertGlobalContentToFrameContent(IntPoint()); SelectText* selectTextContainer = new SelectText(); if (isCaret) { - setSelectionCaretInfo(selectTextContainer, selection.start(), frameOffset, - SelectText::LeftHandle, 0, selection.affinity()); - setSelectionCaretInfo(selectTextContainer, selection.start(), frameOffset, - SelectText::RightHandle, 0, selection.affinity()); + setSelectionCaretInfo(selectTextContainer, base, frameOffset, + SelectText::BaseHandle, SelectText::CenterHandle, 0, + selection.affinity()); + setSelectionCaretInfo(selectTextContainer, base, frameOffset, + SelectText::ExtentHandle, SelectText::CenterHandle, 0, + selection.affinity()); } else { - bool ltr = isLtr(selection.start()); - Position left = ltr ? selection.start() : selection.end(); - Position right = ltr ? selection.end() : selection.start(); - int leftOffset = isLtr(left) ? 0 : -1; - int rightOffset = isLtr(right) ? 0 : -1; - setSelectionCaretInfo(selectTextContainer, left, frameOffset, - SelectText::LeftHandle, leftOffset, selection.affinity()); - setSelectionCaretInfo(selectTextContainer, right, frameOffset, - SelectText::RightHandle, rightOffset, selection.affinity()); + bool isBaseLtr = isLtr(base); + bool isBaseStart = selection.base() == selection.start(); + int baseOffset = isBaseLtr ? 0 : -1; + SelectText::HandleType baseHandleType = (isBaseLtr == isBaseStart) + ? SelectText::LeftHandle : SelectText::RightHandle; + EAffinity affinity = selection.affinity(); + setSelectionCaretInfo(selectTextContainer, base, frameOffset, + SelectText::BaseHandle, baseHandleType, baseOffset, affinity); + bool isExtentLtr = isLtr(extent); + int extentOffset = isExtentLtr ? 0 : -1; + SelectText::HandleType extentHandleType = (isExtentLtr == isBaseStart) + ? SelectText::RightHandle : SelectText::LeftHandle; + setSelectionCaretInfo(selectTextContainer, extent, frameOffset, + SelectText::ExtentHandle, extentHandleType, extentOffset, affinity); Node* stopNode = range->pastLastNode(); for (Node* node = range->firstNode(); node != stopNode; node = node->traverseNextNode()) { @@ -1726,47 +1736,65 @@ Position WebViewCore::trimSelectionPosition(const Position &start, const Positio return pos; } -void WebViewCore::selectText(int startX, int startY, int endX, int endY) +void WebViewCore::selectText(SelectText::HandleId handleId, int x, int y) { SelectionController* sc = focusedFrame()->selection(); - IntPoint startPoint = convertGlobalContentToFrameContent(IntPoint(startX, startY)); - VisiblePosition startPosition(visiblePositionForContentPoint(startPoint)); - IntPoint endPoint = convertGlobalContentToFrameContent(IntPoint(endX, endY)); - VisiblePosition endPosition(visiblePositionForContentPoint(endPoint)); + VisibleSelection selection = sc->selection(); + Position base = selection.base(); + Position extent = selection.extent(); + IntPoint dragPoint = convertGlobalContentToFrameContent(IntPoint(x, y)); + VisiblePosition dragPosition(visiblePositionForContentPoint(dragPoint)); - if (startPosition.isNull() || endPosition.isNull()) + if (base.isNull() || extent.isNull() || dragPosition.isNull()) return; - - // Ensure startPosition is before endPosition - if (comparePositions(startPosition, endPosition) > 0) - swap(startPosition, endPosition); - - if (sc->isContentEditable()) { - startPosition = sc->selection().visibleStart().honorEditableBoundaryAtOrAfter(startPosition); - endPosition = sc->selection().visibleEnd().honorEditableBoundaryAtOrBefore(endPosition); - if (startPosition.isNull() || endPosition.isNull()) { + bool draggingBase = (handleId == SelectText::BaseHandle); + if (draggingBase) + base = dragPosition.deepEquivalent(); + else + extent = dragPosition.deepEquivalent(); + + bool baseIsStart = (comparePositions(base, extent) <= 0); + Position& start = baseIsStart ? base : extent; + Position& end = baseIsStart ? extent : base; + VisiblePosition startPosition(start, selection.affinity()); + VisiblePosition endPosition(end, selection.affinity()); + bool draggingStart = (baseIsStart == draggingBase); + + if (draggingStart) { + startPosition = endPosition.honorEditableBoundaryAtOrAfter(startPosition); + if (startPosition.isNull()) return; + if (selection.isCaret()) + start = end = startPosition.deepEquivalent(); + else { + if ((startPosition != endPosition) && isEndOfBlock(startPosition)) { + // Ensure startPosition is not at end of block + VisiblePosition nextStartPosition(startPosition.next()); + if (nextStartPosition.isNotNull()) + startPosition = nextStartPosition; + } + start = startPosition.deepEquivalent(); + start = trimSelectionPosition(start, end); + } + } else { + endPosition = startPosition.honorEditableBoundaryAtOrAfter(endPosition); + if (endPosition.isNull()) + return; + if (selection.isCaret()) + start = end = endPosition.deepEquivalent(); + else { + if ((startPosition != endPosition) && isStartOfBlock(endPosition)) { + // Ensure endPosition is not at start of block + VisiblePosition prevEndPosition(endPosition.previous()); + if (!prevEndPosition.isNull()) + endPosition = prevEndPosition; + } + end = endPosition.deepEquivalent(); + end = trimSelectionPosition(end, start); } } - // Ensure startPosition is not at end of block - if (startPosition != endPosition && isEndOfBlock(startPosition)) { - VisiblePosition nextStartPosition(startPosition.next()); - if (!nextStartPosition.isNull()) - startPosition = nextStartPosition; - } - // Ensure endPosition is not at start of block - if (startPosition != endPosition && isStartOfBlock(endPosition)) { - VisiblePosition prevEndPosition(endPosition.previous()); - if (!prevEndPosition.isNull()) - endPosition = prevEndPosition; - } - - Position start = startPosition.deepEquivalent(); - Position end = endPosition.deepEquivalent(); - start = trimSelectionPosition(start, end); - end = trimSelectionPosition(end, start); - VisibleSelection selection(start, end); + selection = VisibleSelection(base, extent); // Only allow changes between caret positions or to text selection. bool selectChangeAllowed = (!selection.isCaret() || sc->isCaret()); if (selectChangeAllowed && sc->shouldChangeSelection(selection)) @@ -2950,27 +2978,25 @@ void WebViewCore::passToJs(int generation, const WTF::String& current, updateTextSelection(); } -WebCore::IntRect WebViewCore::scrollFocusedTextInput(float xPercent, int y) +void WebViewCore::scrollFocusedTextInput(float xPercent, int y) { WebCore::Node* focus = currentFocus(); if (!focus) { clearTextEntry(); - return WebCore::IntRect(); + return; } WebCore::RenderTextControl* renderText = toRenderTextControl(focus); if (!renderText) { clearTextEntry(); - return WebCore::IntRect(); + return; } - int x = (int) (xPercent * (renderText->scrollWidth() - + int x = (int)round(xPercent * (renderText->scrollWidth() - renderText->clientWidth())); renderText->setScrollLeft(x); renderText->setScrollTop(y); focus->document()->frame()->selection()->recomputeCaretRect(); - LayerAndroid* layer = 0; - platformLayerIdFromNode(focus, &layer); - return absoluteContentRect(focus, layer); + updateTextSelection(); } void WebViewCore::setFocusControllerActive(bool active) @@ -3364,10 +3390,10 @@ bool WebViewCore::isAutoCompleteEnabled(Node* node) return isEnabled; } -WebCore::IntRect WebViewCore::absoluteContentRect(WebCore::Node* node, +WebCore::IntRect WebViewCore::absoluteClientRect(WebCore::Node* node, LayerAndroid* layer) { - IntRect contentRect; + IntRect clientRect; if (node) { RenderObject* render = node->renderer(); if (render && render->isBox() && !render->isBody()) { @@ -3376,11 +3402,12 @@ WebCore::IntRect WebViewCore::absoluteContentRect(WebCore::Node* node, WebViewCore::layerToAbsoluteOffset(layer, offset); RenderBox* renderBox = toRenderBox(render); - contentRect = renderBox->absoluteContentBox(); - contentRect.move(-offset.x(), -offset.y()); + clientRect = renderBox->clientBoxRect(); + FloatPoint absPos = renderBox->localToAbsolute(FloatPoint()); + clientRect.move(absPos.x() - offset.x(), absPos.y() - offset.y()); } } - return contentRect; + return clientRect; } jobject WebViewCore::createTextFieldInitData(Node* node) @@ -3413,11 +3440,11 @@ jobject WebViewCore::createTextFieldInitData(Node* node) env->SetObjectField(initData, classDef->m_name, fieldName.get()); ScopedLocalRef<jstring> label(env, wtfStringToJstring(env, requestLabel(document->frame(), node), false)); - env->SetObjectField(initData, classDef->m_name, label.get()); + env->SetObjectField(initData, classDef->m_label, label.get()); env->SetIntField(initData, classDef->m_maxLength, getMaxLength(node)); LayerAndroid* layer = 0; int layerId = platformLayerIdFromNode(node, &layer); - IntRect bounds = absoluteContentRect(node, layer); + IntRect bounds = absoluteClientRect(node, layer); ScopedLocalRef<jobject> jbounds(env, intRectToRect(env, bounds)); env->SetObjectField(initData, classDef->m_contentBounds, jbounds.get()); env->SetIntField(initData, classDef->m_nodeLayerId, layerId); @@ -3429,7 +3456,7 @@ jobject WebViewCore::createTextFieldInitData(Node* node) contentRect.move(-rtc->scrollLeft(), -rtc->scrollTop()); } ScopedLocalRef<jobject> jcontentRect(env, intRectToRect(env, contentRect)); - env->SetObjectField(initData, classDef->m_contentRect, jcontentRect.get()); + env->SetObjectField(initData, classDef->m_clientRect, jcontentRect.get()); return initData; } @@ -3888,11 +3915,18 @@ void WebViewCore::setBackgroundColor(SkColor c) // need (int) cast to find the right constructor WebCore::Color bcolor((int)SkColorGetR(c), (int)SkColorGetG(c), (int)SkColorGetB(c), (int)SkColorGetA(c)); + + if (view->baseBackgroundColor() == bcolor) + return; + view->setBaseBackgroundColor(bcolor); // Background color of 0 indicates we want a transparent background if (c == 0) view->setTransparent(true); + + //invalidate so the new color is shown + contentInvalidateAll(); } jclass WebViewCore::getPluginClass(const WTF::String& libName, const char* className) @@ -4498,12 +4532,10 @@ static void PassToJs(JNIEnv* env, jobject obj, jint nativeClass, } static void ScrollFocusedTextInput(JNIEnv* env, jobject obj, jint nativeClass, - jfloat xPercent, jint y, jobject contentBounds) + jfloat xPercent, jint y) { WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass); - IntRect bounds = viewImpl->scrollFocusedTextInput(xPercent, y); - if (contentBounds) - GraphicsJNI::irect_to_jrect(bounds, env, contentBounds); + viewImpl->scrollFocusedTextInput(xPercent, y); } static void SetFocusControllerActive(JNIEnv* env, jobject obj, jint nativeClass, @@ -4928,10 +4960,10 @@ static jobject GetText(JNIEnv* env, jobject obj, jint nativeClass, } static void SelectText(JNIEnv* env, jobject obj, jint nativeClass, - jint startX, jint startY, jint endX, jint endY) + jint handleId, jint x, jint y) { WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass); - viewImpl->selectText(startX, startY, endX, endY); + viewImpl->selectText(static_cast<SelectText::HandleId>(handleId), x, y); } static void ClearSelection(JNIEnv* env, jobject obj, jint nativeClass) @@ -5003,7 +5035,7 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { (void*) MoveMouse }, { "passToJs", "(IILjava/lang/String;IIZZZZ)V", (void*) PassToJs }, - { "nativeScrollFocusedTextInput", "(IFILandroid/graphics/Rect;)V", + { "nativeScrollFocusedTextInput", "(IFI)V", (void*) ScrollFocusedTextInput }, { "nativeSetFocusControllerActive", "(IZ)V", (void*) SetFocusControllerActive }, @@ -5068,7 +5100,7 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { (void*) InsertText }, { "nativeGetText", "(IIIII)Ljava/lang/String;", (void*) GetText }, - { "nativeSelectText", "(IIIII)V", + { "nativeSelectText", "(IIII)V", (void*) SelectText }, { "nativeClearTextSelection", "(I)V", (void*) ClearSelection }, diff --git a/Source/WebKit/android/jni/WebViewCore.h b/Source/WebKit/android/jni/WebViewCore.h index 7cc3fd6..cf1295c 100644 --- a/Source/WebKit/android/jni/WebViewCore.h +++ b/Source/WebKit/android/jni/WebViewCore.h @@ -397,7 +397,7 @@ namespace android { /** * Scroll the focused textfield to (x, y) in document space */ - WebCore::IntRect scrollFocusedTextInput(float x, int y); + void scrollFocusedTextInput(float x, int y); /** * Set the FocusController's active and focused states, so that * the caret will draw (true) or not. @@ -580,7 +580,7 @@ namespace android { int startX, int startY, int endX, int endY); static int platformLayerIdFromNode(WebCore::Node* node, WebCore::LayerAndroid** outLayer = 0); - void selectText(int startX, int startY, int endX, int endY); + void selectText(SelectText::HandleId handleId, int x, int y); bool selectWordAt(int x, int y); // Converts from the global content coordinates that WebView sends @@ -728,12 +728,12 @@ namespace android { void setSelectionCaretInfo(SelectText* selectTextContainer, const WebCore::Position& position, const WebCore::IntPoint& frameOffset, - SelectText::HandleId handleId, int offset, - EAffinity affinity); + SelectText::HandleId handleId, SelectText::HandleType handleType, + int offset, EAffinity affinity); static int getMaxLength(WebCore::Node* node); static WTF::String getFieldName(WebCore::Node* node); static bool isAutoCompleteEnabled(WebCore::Node* node); - WebCore::IntRect absoluteContentRect(WebCore::Node* node, + WebCore::IntRect absoluteClientRect(WebCore::Node* node, WebCore::LayerAndroid* layer); static WebCore::IntRect positionToTextRect(const WebCore::Position& position, WebCore::EAffinity affinity, const WebCore::IntPoint& offset); diff --git a/Source/WebKit/android/nav/SelectText.h b/Source/WebKit/android/nav/SelectText.h index aaaf3bb..8f7592d 100644 --- a/Source/WebKit/android/nav/SelectText.h +++ b/Source/WebKit/android/nav/SelectText.h @@ -35,8 +35,13 @@ namespace android { class SelectText : public RegionLayerDrawExtra { public: enum HandleId { + BaseHandle = 0, + ExtentHandle = 1, + }; + enum HandleType { LeftHandle = 0, - RightHandle = 1, + CenterHandle = 1, + RightHandle = 2, }; IntRect& caretRect(HandleId id) { return m_caretRects[id]; } @@ -48,11 +53,14 @@ public: void setText(const String& text) { m_text = text.threadsafeCopy(); } String& getText() { return m_text; } + HandleType getHandleType(HandleId id) { return m_handleType[id]; } + void setHandleType(HandleId id, HandleType type) { m_handleType[id] = type; } private: IntRect m_caretRects[2]; IntRect m_textRects[2]; int m_caretLayerId[2]; + HandleType m_handleType[2]; String m_text; }; diff --git a/Source/WebKit/android/nav/WebView.cpp b/Source/WebKit/android/nav/WebView.cpp index a277fc3..fae566c 100644 --- a/Source/WebKit/android/nav/WebView.cpp +++ b/Source/WebKit/android/nav/WebView.cpp @@ -731,6 +731,15 @@ void findMaxVisibleRect(int movingLayerId, SkIRect& visibleContentRect) } } +bool isHandleLeft(SelectText::HandleId handleId) +{ + SelectText* selectText = static_cast<SelectText*>(getDrawExtra(DrawExtrasSelection)); + if (!selectText) + return (handleId == SelectText::BaseHandle); + + return (selectText->getHandleType(handleId) == SelectText::LeftHandle); +} + private: // local state for WebView bool m_isDrawingPaused; // private to getFrameCache(); other functions operate in a different thread @@ -1287,6 +1296,13 @@ static void nativeFindMaxVisibleRect(JNIEnv *env, jobject obj, jint nativeView, GraphicsJNI::irect_to_jrect(nativeRect, env, visibleContentRect); } +static bool nativeIsHandleLeft(JNIEnv *env, jobject obj, jint nativeView, + jint handleId) +{ + WebView* webview = reinterpret_cast<WebView*>(nativeView); + return webview->isHandleLeft(static_cast<SelectText::HandleId>(handleId)); +} + /* * JNI registration */ @@ -1365,6 +1381,8 @@ static JNINativeMethod gJavaWebViewMethods[] = { (void*) nativeSetHwAccelerated }, { "nativeFindMaxVisibleRect", "(IILandroid/graphics/Rect;)V", (void*) nativeFindMaxVisibleRect }, + { "nativeIsHandleLeft", "(II)Z", + (void*) nativeIsHandleLeft }, }; int registerWebView(JNIEnv* env) |