diff options
25 files changed, 710 insertions, 482 deletions
@@ -228,6 +228,10 @@ ifeq ($(ENABLE_SVG),true) LOCAL_CFLAGS += -DENABLE_SVG=1 endif +ifeq ($(ENABLE_WTF_USE_ACCELERATED_COMPOSITING),false) +LOCAL_CFLAGS += -DWTF_USE_ACCELERATED_COMPOSITING=0 +endif + ifeq ($(ENABLE_WTF_USE_ACCELERATED_COMPOSITING),true) LOCAL_CFLAGS += -DWTF_USE_ACCELERATED_COMPOSITING=1 endif diff --git a/WebCore/bindings/v8/V8Proxy.cpp b/WebCore/bindings/v8/V8Proxy.cpp index 9b1fff5..d13289e 100644 --- a/WebCore/bindings/v8/V8Proxy.cpp +++ b/WebCore/bindings/v8/V8Proxy.cpp @@ -818,10 +818,13 @@ bool V8Proxy::sourceLineNumber(int& result) frameSourceLine = v8::Local<v8::Function>::Cast(v8UtilityContext->Global()->Get(v8::String::New("frameSourceLine"))); if (frameSourceLine.IsEmpty()) return false; +#if 0 + // TODO(andreip): re-enable this after experimenting with partial snapshots v8::Handle<v8::Value> value = v8::Debug::Call(frameSourceLine); if (value.IsEmpty()) return false; result = value->Int32Value(); +#endif return true; } @@ -836,10 +839,13 @@ bool V8Proxy::sourceName(String& result) frameSourceName = v8::Local<v8::Function>::Cast(v8UtilityContext->Global()->Get(v8::String::New("frameSourceName"))); if (frameSourceName.IsEmpty()) return false; +#if 0 + // TODO(andreip): re-enable this after experimenting with partial snapshots v8::Handle<v8::Value> value = v8::Debug::Call(frameSourceName); if (value.IsEmpty()) return false; result = toWebCoreString(value); +#endif return true; } diff --git a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp index be275a8..fd1c91a 100644 --- a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp +++ b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp @@ -230,7 +230,13 @@ void GraphicsLayerAndroid::updateFixedPosition() top = convertLength(view->style()->top()); right = convertLength(view->style()->right()); bottom = convertLength(view->style()->bottom()); - m_contentLayer->setFixedPosition(left, top, right, bottom); + // We need to pass the size of the element to compute the final fixed + // position -- we can't use the layer's size as it could possibly differs. + // We also have to use the visible overflow and not just the size, + // as some child elements could be overflowing. + int w = view->rightVisibleOverflow() - view->leftVisibleOverflow(); + int h = view->bottomVisibleOverflow() - view->topVisibleOverflow(); + m_contentLayer->setFixedPosition(left, top, right, bottom, w, h); } } } @@ -319,11 +325,9 @@ void GraphicsLayerAndroid::setMasksToBounds(bool masksToBounds) void GraphicsLayerAndroid::setDrawsContent(bool drawsContent) { GraphicsLayer::setDrawsContent(drawsContent); - m_contentLayer->setDrawsContent(m_drawsContent); if (m_drawsContent) { m_haveContents = true; - m_contentLayer->setHaveContents(true); setNeedsDisplay(); } askForSync(); @@ -351,8 +355,6 @@ void GraphicsLayerAndroid::setContentsOpaque(bool opaque) LOG("(%x) setContentsOpaque (%d)", this, opaque); GraphicsLayer::setContentsOpaque(opaque); m_haveContents = true; - m_contentLayer->setHaveContents(true); - m_contentLayer->setDrawsContent(true); askForSync(); } @@ -431,8 +433,6 @@ bool GraphicsLayerAndroid::repaint(const FloatRect& rect) this, rect.x(), rect.y(), rect.width(), rect.height(), gPaused, m_needsRepaint, m_haveContents); - m_contentLayer->setDrawsContent(true); - if (!gPaused && m_haveContents && m_needsRepaint) { SkAutoPictureRecord arp(m_contentLayer->recordContext(), m_size.width(), m_size.height()); SkCanvas* recordingCanvas = arp.getRecordingCanvas(); @@ -796,16 +796,12 @@ void GraphicsLayerAndroid::setContentsToImage(Image* image) TLOG("(%x) setContentsToImage", this, image); if (image) { m_haveContents = true; - m_contentLayer->setHaveContents(true); - m_contentLayer->setDrawsContent(true); - m_contentLayer->setHaveImage(true); if (!m_haveImage) { m_haveImage = true; setNeedsDisplay(); askForSync(); } - } else - m_contentLayer->setHaveImage(false); + } } PlatformLayer* GraphicsLayerAndroid::platformLayer() const diff --git a/WebCore/platform/graphics/android/LayerAndroid.cpp b/WebCore/platform/graphics/android/LayerAndroid.cpp index 2dc8a05..0dedd64 100644 --- a/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -4,8 +4,11 @@ #if USE(ACCELERATED_COMPOSITING) #include "AndroidAnimation.h" -#include "FindCanvas.h" +#include "DrawExtra.h" +#include "SkCanvas.h" #include "SkDrawFilter.h" +#include "SkPaint.h" +#include "SkPicture.h" #include <wtf/CurrentTime.h> #define LAYER_DEBUG // Add diagonals for debugging @@ -43,14 +46,11 @@ class OpacityDrawFilter : public SkDrawFilter { LayerAndroid::LayerAndroid(bool isRootLayer) : SkLayer(), m_isRootLayer(isRootLayer), - m_haveContents(false), - m_drawsContent(true), - m_haveImage(false), m_haveClip(false), m_doRotation(false), m_isFixed(false), m_recordingPicture(0), - m_findOnPage(0), + m_extra(0), m_uniqueId(++gUniqueId) { m_angleTransform = 0; @@ -63,11 +63,8 @@ LayerAndroid::LayerAndroid(bool isRootLayer) : SkLayer(), LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer), m_isRootLayer(layer.m_isRootLayer), - m_haveContents(layer.m_haveContents), - m_drawsContent(layer.m_drawsContent), - m_haveImage(layer.m_haveImage), m_haveClip(layer.m_haveClip), - m_findOnPage(0), + m_extra(0), // deliberately not copied m_uniqueId(layer.m_uniqueId) { m_doRotation = layer.m_doRotation; @@ -82,6 +79,8 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer), m_fixedTop = layer.m_fixedTop; m_fixedRight = layer.m_fixedRight; m_fixedBottom = layer.m_fixedBottom; + m_fixedWidth = layer.m_fixedWidth; + m_fixedHeight = layer.m_fixedHeight; m_recordingPicture = layer.m_recordingPicture; SkSafeRef(m_recordingPicture); @@ -96,6 +95,23 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer), gDebugLayerAndroidInstances++; } +LayerAndroid::LayerAndroid(SkPicture* picture) : SkLayer(), + m_isRootLayer(true), + m_haveClip(false), + m_doRotation(false), + m_isFixed(false), + m_recordingPicture(picture), + m_extra(0), + m_uniqueId(-1) +{ + m_angleTransform = 0; + m_translation.set(0, 0); + m_scale.set(1, 1); + m_backgroundColor = 0; + SkSafeRef(m_recordingPicture); + gDebugLayerAndroidInstances++; +} + LayerAndroid::~LayerAndroid() { removeChildren(); @@ -151,13 +167,6 @@ void LayerAndroid::removeAnimation(const String& name) m_animations.remove(name); } -void LayerAndroid::setDrawsContent(bool drawsContent) -{ - m_drawsContent = drawsContent; - for (int i = 0; i < countChildren(); i++) - getChild(i)->setDrawsContent(drawsContent); -} - // We only use the bounding rect of the layer as mask... // TODO: use a real mask? void LayerAndroid::setMaskLayer(LayerAndroid* layer) @@ -174,8 +183,6 @@ void LayerAndroid::setMasksToBounds(bool masksToBounds) void LayerAndroid::setBackgroundColor(SkColor color) { m_backgroundColor = color; - setHaveContents(true); - setDrawsContent(true); } static int gDebugChildLevel; @@ -236,13 +243,6 @@ const LayerAndroid* LayerAndroid::find(int x, int y) const return 0; } -void LayerAndroid::setClip(SkCanvas* canvas) -{ - SkRect clip; - bounds(&clip); - canvas->clipRect(clip); -} - /////////////////////////////////////////////////////////////////////////////// void LayerAndroid::updatePositions(const SkRect& viewport) { @@ -259,12 +259,12 @@ void LayerAndroid::updatePositions(const SkRect& viewport) { if (m_fixedLeft.defined()) x = dx + m_fixedLeft.calcFloatValue(w); else if (m_fixedRight.defined()) - x = dx + w - m_fixedRight.calcFloatValue(w) - getSize().width(); + x = dx + w - m_fixedRight.calcFloatValue(w) - m_fixedWidth; if (m_fixedTop.defined()) y = dy + m_fixedTop.calcFloatValue(h); else if (m_fixedBottom.defined()) - y = dy + h - m_fixedBottom.calcFloatValue(h) - getSize().height(); + y = dy + h - m_fixedBottom.calcFloatValue(h) - m_fixedHeight; this->setPosition(x, y); matrix.reset(); @@ -283,13 +283,8 @@ void LayerAndroid::updatePositions(const SkRect& viewport) { // now apply it to our children int count = this->countChildren(); - if (count > 0) { - SkRect tmp = viewport; - // adjust the viewport by our (the parent) position - tmp.offset(-this->getPosition()); - for (int i = 0; i < count; i++) { - this->getChild(i)->updatePositions(tmp); - } + for (int i = 0; i < count; i++) { + this->getChild(i)->updatePositions(viewport); } } @@ -300,7 +295,7 @@ void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity) { canvas->clipRect(r); } - if (!m_haveImage && !m_drawsContent && !m_isRootLayer) + if (!m_isRootLayer) return; if (!prepareContext()) @@ -314,6 +309,8 @@ void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity) { canvas->setDrawFilter(new OpacityDrawFilter(canvasOpacity)); m_recordingPicture->draw(canvas); + if (m_extra) + m_extra->draw(canvas, this); #ifdef LAYER_DEBUG float w = getSize().width(); @@ -339,9 +336,6 @@ SkPicture* LayerAndroid::recordContext() bool LayerAndroid::prepareContext(bool force) { - if (!m_haveContents) - return false; - if (!m_isRootLayer) { if (force || !m_recordingPicture || (m_recordingPicture @@ -443,9 +437,6 @@ void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const writeln(file, indentLevel, "{"); writeHexVal(file, indentLevel + 1, "layer", (int)this); - writeIntVal(file, indentLevel + 1, "haveContents", m_haveContents); - writeIntVal(file, indentLevel + 1, "drawsContent", m_drawsContent); - writeIntVal(file, indentLevel + 1, "haveImage", m_haveImage); writeIntVal(file, indentLevel + 1, "clipRect", m_haveClip); writeFloatVal(file, indentLevel + 1, "opacity", getOpacity()); @@ -462,6 +453,8 @@ void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const writeLength(file, indentLevel + 1, "fixedTop", m_fixedTop); writeLength(file, indentLevel + 1, "fixedRight", m_fixedRight); writeLength(file, indentLevel + 1, "fixedBottom", m_fixedBottom); + writeIntVal(file, indentLevel + 1, "fixedWidth", m_fixedWidth); + writeIntVal(file, indentLevel + 1, "fixedHeight", m_fixedHeight); if (countChildren()) { writeln(file, indentLevel + 1, "children = ["); @@ -487,11 +480,11 @@ const LayerAndroid* LayerAndroid::findById(int match) const return 0; } -void LayerAndroid::setFindOnPage(FindOnPage* findOnPage) +void LayerAndroid::setExtra(DrawExtra* extra) { - m_findOnPage = findOnPage; + m_extra = extra; for (int i = 0; i < countChildren(); i++) - getChild(i)->setFindOnPage(findOnPage); + getChild(i)->setExtra(extra); } } // namespace WebCore diff --git a/WebCore/platform/graphics/android/LayerAndroid.h b/WebCore/platform/graphics/android/LayerAndroid.h index d3f2357..4f8a5fe 100644 --- a/WebCore/platform/graphics/android/LayerAndroid.h +++ b/WebCore/platform/graphics/android/LayerAndroid.h @@ -25,11 +25,16 @@ #include "StringHash.h" #include <wtf/HashMap.h> -class FindOnPage; class SkCanvas; class SkMatrix; class SkPicture; +namespace android { +class DrawExtra; +} + +using namespace android; + struct SkLength { enum SkLengthType { Undefined, Auto, Relative, Percent, Fixed, Static, Intrinsic, MinIntrinsic }; SkLengthType type; @@ -64,6 +69,7 @@ class LayerAndroid : public SkLayer { public: LayerAndroid(bool isRootLayer); LayerAndroid(const LayerAndroid& layer); + LayerAndroid(SkPicture* ); virtual ~LayerAndroid(); static int instancesCount(); @@ -82,28 +88,28 @@ public: rect.offset(m_translation.fX, m_translation.fY); return rect; } - void setFixedPosition(SkLength left, SkLength top, SkLength right, SkLength bottom) { + void setFixedPosition(SkLength left, // CSS left property + SkLength top, // CSS top property + SkLength right, // CSS right property + SkLength bottom, // CSS bottom property + int width, // visible overflow width + int height) { // visible overflow height m_fixedLeft = left; m_fixedTop = top; m_fixedRight = right; m_fixedBottom = bottom; + m_fixedWidth = width; + m_fixedHeight = height; m_isFixed = true; } void setBackgroundColor(SkColor color); - void setHaveContents(bool haveContents) { m_haveContents = haveContents; } - void setHaveImage(bool haveImage) { m_haveImage = haveImage; } - void setDrawsContent(bool drawsContent); - void setFindOnPage(FindOnPage* findOnPage); void setMaskLayer(LayerAndroid*); void setMasksToBounds(bool); + void setIsRootLayer(bool isRootLayer) { m_isRootLayer = isRootLayer; } - bool prepareContext(bool force = false); - void startRecording(); - void stopRecording(); SkPicture* recordContext(); - void setClip(SkCanvas* clip); void addAnimation(PassRefPtr<AndroidAnimation> anim); void removeAnimation(const String& name); @@ -131,20 +137,19 @@ public: LayerAndroid* getChild(int index) const { return static_cast<LayerAndroid*>(this->INHERITED::getChild(index)); } - bool haveClip() const { return m_haveClip; } + void setExtra(DrawExtra* extra); // does not assign ownership int uniqueId() const { return m_uniqueId; } protected: virtual void onDraw(SkCanvas*, SkScalar opacity); private: + bool prepareContext(bool force = false); bool boundsIsUnique(SkTDArray<SkRect>* region, const SkRect& local) const; void clipInner(SkTDArray<SkRect>* region, const SkRect& local) const; bool m_isRootLayer; - bool m_haveContents; bool m_drawsContent; - bool m_haveImage; bool m_haveClip; bool m_doRotation; bool m_isFixed; @@ -154,6 +159,9 @@ private: SkLength m_fixedTop; SkLength m_fixedRight; SkLength m_fixedBottom; + int m_fixedWidth; + int m_fixedHeight; + SkPoint m_translation; SkPoint m_scale; SkScalar m_angleTransform; @@ -163,7 +171,7 @@ private: typedef HashMap<String, RefPtr<AndroidAnimation> > KeyframesMap; KeyframesMap m_animations; - FindOnPage* m_findOnPage; + DrawExtra* m_extra; int m_uniqueId; typedef SkLayer INHERITED; @@ -171,6 +179,27 @@ private: } +#else + +class SkPicture; + +namespace WebCore { + +class LayerAndroid { +public: + LayerAndroid(SkPicture* picture) : + m_recordingPicture(picture), // does not assign ownership + m_uniqueId(-1) + {} + SkPicture* picture() const { return m_recordingPicture; } + int uniqueId() const { return m_uniqueId; } +private: + SkPicture* m_recordingPicture; + int m_uniqueId; +}; + +} + #endif // USE(ACCELERATED_COMPOSITING) #endif // LayerAndroid_h diff --git a/WebCore/platform/graphics/android/android_graphics.cpp b/WebCore/platform/graphics/android/android_graphics.cpp index af88b8c..fafd3df 100644 --- a/WebCore/platform/graphics/android/android_graphics.cpp +++ b/WebCore/platform/graphics/android/android_graphics.cpp @@ -23,13 +23,18 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" +#include "CachedPrefix.h" #include "android_graphics.h" +#include "CachedRoot.h" #include "IntRect.h" +#include "LayerAndroid.h" #include "SkCanvas.h" #include "SkCornerPathEffect.h" #include "SkPath.h" #include "SkRegion.h" +#include "WebViewCore.h" + +namespace android { /////////////////////////////////////////////////////////////////////////////// @@ -56,15 +61,26 @@ const static SkColor cursorPressedColors[] = { #define CURSOR_RING_INNER_DIAMETER SkFixedToScalar(SkIntToFixed(3)>>1) // 3/2 == 1.5 #define CURSOR_RING_OUTER_OUTSET 2 // used to inflate rects added to region -void CursorRing::DrawRing(SkCanvas* canvas, - const Vector<WebCore::IntRect>& rects, Flavor flavor) +void CursorRing::draw(SkCanvas* canvas, LayerAndroid* layer) { - unsigned rectCount = rects.size(); - SkRegion rgn; - SkPath path; +#if USE(ACCELERATED_COMPOSITING) + int layerId = m_node->isInLayer() ? m_frame->layer(m_node)->uniqueId() : -1; + if (layer->uniqueId() != layerId) + return; +#endif + if (canvas->quickReject(m_bounds, SkCanvas::kAA_EdgeType)) { + DBG_NAV_LOGD("canvas->quickReject cursorNode=%d (nodePointer=%p)" + " bounds=(%d,%d,w=%d,h=%d)", m_node->index(), m_node->nodePointer(), + m_bounds.x(), m_bounds.y(), m_bounds.width(), m_bounds.height()); + m_followedLink = false; + return; + } + unsigned rectCount = m_rings.size(); + SkRegion rgn; + SkPath path; for (unsigned i = 0; i < rectCount; i++) { - SkRect r(rects[i]); + SkRect r(m_rings[i]); SkIRect ir; r.round(&ir); @@ -76,15 +92,76 @@ void CursorRing::DrawRing(SkCanvas* canvas, SkPaint paint; paint.setAntiAlias(true); paint.setPathEffect(new SkCornerPathEffect(CURSOR_RING_ROUNDEDNESS))->unref(); - if (flavor >= NORMAL_ANIMATING) { // pressed - paint.setColor(cursorPressedColors[flavor - NORMAL_ANIMATING]); + if (m_flavor >= NORMAL_ANIMATING) { // pressed + paint.setColor(cursorPressedColors[m_flavor - NORMAL_ANIMATING]); canvas->drawPath(path, paint); } paint.setStyle(SkPaint::kStroke_Style); paint.setStrokeWidth(CURSOR_RING_OUTER_DIAMETER); - paint.setColor(cursorOuterColors[flavor]); + paint.setColor(cursorOuterColors[m_flavor]); canvas->drawPath(path, paint); paint.setStrokeWidth(CURSOR_RING_INNER_DIAMETER); - paint.setColor(cursorInnerColors[flavor]); + paint.setColor(cursorInnerColors[m_flavor]); canvas->drawPath(path, paint); } + +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; + } + m_isButton = false; + m_viewImpl->gButtonMutex.lock(); + // If this is a button drawn by us (rather than webkit) do not draw the + // cursor ring, since its cursor will be shown by a change in what we draw. + // 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(); + Container* end = m_viewImpl->m_buttons.end(); + for (Container* ptr = m_viewImpl->m_buttons.begin(); ptr != end; ptr++) { + if (ptr->matches(cursorPointer)) { + m_isButton = true; + break; + } + } + } + m_viewImpl->gButtonMutex.unlock(); + m_bounds = m_node->localBounds(m_frame); + m_viewImpl->updateCursorBounds(m_root, m_frame, m_node); + + bool useHitBounds = m_node->useHitBounds(); + if (useHitBounds) + m_bounds = m_node->localHitBounds(m_frame); + if (useHitBounds || m_node->useBounds()) { + m_rings.clear(); + m_rings.append(m_bounds); + } + m_bounds.inflate(SkScalarCeil(CURSOR_RING_OUTER_DIAMETER)); + if (!m_node->hasCursorRing() || (m_node->isPlugin() && m_node->isFocus())) + return false; + m_flavor = NORMAL_FLAVOR; + if (!m_isButton) { + m_flavor = m_node->isSyntheticLink() ? FAKE_FLAVOR : NORMAL_FLAVOR; + if (m_followedLink) { + m_flavor = static_cast<Flavor>(m_flavor + NORMAL_ANIMATING); + } +#if DEBUG_NAV_UI + const WebCore::IntRect& ring = m_rings[0]; + DBG_NAV_LOGD("cursorNode=%d (nodePointer=%p) flavor=%s rings=%d" + " (%d, %d, %d, %d) isPlugin=%s", + m_node->index(), m_node->nodePointer(), + m_flavor == FAKE_FLAVOR ? "FAKE_FLAVOR" : + m_flavor == NORMAL_ANIMATING ? "NORMAL_ANIMATING" : + m_flavor == FAKE_ANIMATING ? "FAKE_ANIMATING" : "NORMAL_FLAVOR", + m_rings.size(), ring.x(), ring.y(), ring.width(), ring.height(), + m_node->isPlugin() ? "true" : "false"); +#endif + } + return true; +} + +} diff --git a/WebCore/platform/graphics/android/android_graphics.h b/WebCore/platform/graphics/android/android_graphics.h index a286e3a..dbf1978 100644 --- a/WebCore/platform/graphics/android/android_graphics.h +++ b/WebCore/platform/graphics/android/android_graphics.h @@ -26,18 +26,23 @@ #ifndef android_graphics_DEFINED #define android_graphics_DEFINED -#include "wtf/Vector.h" - +#include "DrawExtra.h" +#include "IntRect.h" #include "SkTypes.h" - -class SkCanvas; +#include "wtf/Vector.h" namespace WebCore { - class IntRect; class GraphicsContext; } -SkCanvas* android_gc2canvas(WebCore::GraphicsContext* gc); +SkCanvas* android_gc2canvas(GraphicsContext* gc); + +namespace android { + +class CachedFrame; +class CachedNode; +class CachedRoot; +class WebViewCore; // Data and methods for cursor rings @@ -47,7 +52,7 @@ SkCanvas* android_gc2canvas(WebCore::GraphicsContext* gc); // used to inval rectangle enclosing pressed state of ring #define CURSOR_RING_OUTER_DIAMETER SkFixedToScalar(SkIntToFixed(13)>>2) // 13/4 == 3.25 -struct CursorRing { +class CursorRing : public DrawExtra { public: enum Flavor { NORMAL_FLAVOR, @@ -57,8 +62,23 @@ public: ANIMATING_COUNT = 2 }; - static void DrawRing(SkCanvas* , - const Vector<WebCore::IntRect>& rects, Flavor ); + CursorRing(WebViewCore* core) : m_viewImpl(core) {} + virtual ~CursorRing() {} + virtual void draw(SkCanvas* , LayerAndroid* ); + bool setup(); +private: + friend class WebView; + WebViewCore* m_viewImpl; // copy for convenience + WTF::Vector<IntRect> m_rings; + IntRect m_bounds; + const CachedRoot* m_root; + const CachedFrame* m_frame; + const CachedNode* m_node; + Flavor m_flavor; + bool m_followedLink; + bool m_isButton; }; +} + #endif diff --git a/WebKit/android/RenderSkinCombo.cpp b/WebKit/android/RenderSkinCombo.cpp index e15b3c3..6f88ee3 100644 --- a/WebKit/android/RenderSkinCombo.cpp +++ b/WebKit/android/RenderSkinCombo.cpp @@ -41,7 +41,9 @@ static bool s_decoded; // True if all assets were decoded static const int s_margin = 2; static const SkIRect s_mar = { s_margin, s_margin, RenderSkinCombo::extraWidth(), s_margin }; - +static SkIRect s_subset; + + RenderSkinCombo::RenderSkinCombo() { } @@ -54,6 +56,10 @@ void RenderSkinCombo::Init(android::AssetManager* am) // but is that necessary in the final version? s_decoded = RenderSkinAndroid::DecodeBitmap(am, "images/combobox-noHighlight.png", &s_bitmap[kNormal]); s_decoded = RenderSkinAndroid::DecodeBitmap(am, "images/combobox-disabled.png", &s_bitmap[kDisabled]) && s_decoded; + + int width = s_bitmap[kNormal].width(); + int height = s_bitmap[kNormal].height(); + s_subset.set(width - RenderSkinCombo::extraWidth() + s_margin, 0, width, height); } @@ -75,7 +81,19 @@ bool RenderSkinCombo::Draw(SkCanvas* canvas, Node* element, int x, int y, int wi canvas->drawRect(bounds, paint); bounds.set(SkIntToScalar(x), SkIntToScalar(y), SkIntToScalar(x + width), SkIntToScalar(y + height)); - SkNinePatch::DrawNine(canvas, bounds, s_bitmap[state], s_mar); + + if (style->borderLeftColor().isValid() || + style->borderRightColor().isValid() || + style->borderTopColor().isValid() || + style->borderBottomColor().isValid()) { + bounds.fLeft += SkIntToScalar(width - RenderSkinCombo::extraWidth()); + bounds.fRight -= SkIntToScalar(style->borderRightWidth()); + bounds.fTop += SkIntToScalar(style->borderTopWidth()); + bounds.fBottom -= SkIntToScalar(style->borderBottomWidth()); + canvas->drawBitmapRect(s_bitmap[state], &s_subset, bounds); + } else { + SkNinePatch::DrawNine(canvas, bounds, s_bitmap[state], s_mar); + } return false; } diff --git a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp index 8187871..5e121e6 100644 --- a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp +++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp @@ -374,7 +374,7 @@ void ChromeClientAndroid::exceededDatabaseQuota(Frame* frame, const String& name // If new quota is unavailable, we may be able to resolve the situation by shrinking the quota of an origin that asked for a lot but is only using a little. // If we find such a site, shrink it's quota and ask Java to try again. - if (m_newQuota == currentQuota && !m_triedToReclaimDBQuota) { + if ((unsigned long long) m_newQuota == currentQuota && !m_triedToReclaimDBQuota) { m_triedToReclaimDBQuota = true; // we should only try this once per quota overflow. unsigned long long reclaimedQuotaBytes = tryToReclaimDatabaseQuota(origin); @@ -397,7 +397,7 @@ static unsigned long long tryToReclaimDatabaseQuota(SecurityOrigin* originNeedin Vector<RefPtr<SecurityOrigin> > origins; tracker.origins(origins); unsigned long long reclaimedQuotaBytes = 0; - for (int i = 0; i < origins.size(); i++) { + for (unsigned i = 0; i < origins.size(); i++) { SecurityOrigin* originToReclaimFrom = origins[i].get(); // Don't try to reclaim from the origin that has exceeded its quota. diff --git a/WebKit/android/jni/WebCoreFrameBridge.cpp b/WebKit/android/jni/WebCoreFrameBridge.cpp index a233cf5..c1454e4 100644 --- a/WebKit/android/jni/WebCoreFrameBridge.cpp +++ b/WebKit/android/jni/WebCoreFrameBridge.cpp @@ -1393,7 +1393,10 @@ static jboolean HasPasswordField(JNIEnv *env, jobject obj) bool found = false; WTF::PassRefPtr<WebCore::HTMLCollection> form = pFrame->document()->forms(); WebCore::Node* node = form->firstItem(); - while (node && !found) { + // Null/Empty namespace means that node is not created in HTMLFormElement + // class, but just normal Element class. + while (node && !found && !node->namespaceURI().isNull() && + !node->namespaceURI().isEmpty()) { WTF::Vector<WebCore::HTMLFormControlElement*>& elements = ((WebCore::HTMLFormElement*)node)->formElements; size_t size = elements.size(); @@ -1423,7 +1426,8 @@ static jobjectArray GetUsernamePassword(JNIEnv *env, jobject obj) bool found = false; WTF::PassRefPtr<WebCore::HTMLCollection> form = pFrame->document()->forms(); WebCore::Node* node = form->firstItem(); - while (node && !found) { + while (node && !found && !node->namespaceURI().isNull() && + !node->namespaceURI().isEmpty()) { WTF::Vector<WebCore::HTMLFormControlElement*>& elements = ((WebCore::HTMLFormElement*)node)->formElements; size_t size = elements.size(); @@ -1468,7 +1472,8 @@ static void SetUsernamePassword(JNIEnv *env, jobject obj, bool found = false; WTF::PassRefPtr<WebCore::HTMLCollection> form = pFrame->document()->forms(); WebCore::Node* node = form->firstItem(); - while (node && !found) { + while (node && !found && !node->namespaceURI().isNull() && + !node->namespaceURI().isEmpty()) { WTF::Vector<WebCore::HTMLFormControlElement*>& elements = ((WebCore::HTMLFormElement*)node)->formElements; size_t size = elements.size(); @@ -1517,7 +1522,9 @@ static jobject GetFormTextData(JNIEnv *env, jobject obj) WebCore::HTMLFormElement* form; WebCore::HTMLInputElement* input; - for (WebCore::Node* node = collection->firstItem(); node; node = collection->nextItem()) { + for (WebCore::Node* node = collection->firstItem(); + node && !node->namespaceURI().isNull() && !node->namespaceURI().isEmpty(); + node = collection->nextItem()) { form = static_cast<WebCore::HTMLFormElement*>(node); if (form->autoComplete()) { WTF::Vector<WebCore::HTMLFormControlElement*> elements = form->formElements; diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp index fecacc9..57bc11c 100644 --- a/WebKit/android/jni/WebViewCore.cpp +++ b/WebKit/android/jni/WebViewCore.cpp @@ -685,6 +685,35 @@ void WebViewCore::updateButtonList(WTF::Vector<Container>* buttons) } } +// note: updateCursorBounds is called directly by the WebView thread +// This needs to be called each time we call CachedRoot::setCursor() with +// non-null CachedNode/CachedFrame, since otherwise the WebViewCore's data +// about the cursor is incorrect. When we call setCursor(0,0), we need +// to set hasCursorBounds to false. +void WebViewCore::updateCursorBounds(const CachedRoot* root, + const CachedFrame* cachedFrame, const CachedNode* cachedNode) +{ + LOG_ASSERT(root, "updateCursorBounds: root cannot be null"); + LOG_ASSERT(cachedNode, "updateCursorBounds: cachedNode cannot be null"); + LOG_ASSERT(cachedFrame, "updateCursorBounds: cachedFrame cannot be null"); + gCursorBoundsMutex.lock(); + m_hasCursorBounds = !cachedNode->isHidden(); + // If m_hasCursorBounds is false, we never look at the other + // values, so do not bother setting them. + if (m_hasCursorBounds) { + WebCore::IntRect bounds = cachedNode->bounds(cachedFrame); + if (m_cursorBounds != bounds) + DBG_NAV_LOGD("new cursor bounds=(%d,%d,w=%d,h=%d)", + bounds.x(), bounds.y(), bounds.width(), bounds.height()); + m_cursorBounds = bounds; + m_cursorHitBounds = cachedNode->hitBounds(cachedFrame); + m_cursorFrame = cachedFrame->framePointer(); + root->getSimulatedMousePosition(&m_cursorLocation); + m_cursorNode = cachedNode->nodePointer(); + } + gCursorBoundsMutex.unlock(); +} + void WebViewCore::clearContent() { DBG_SET_LOG(""); diff --git a/WebKit/android/jni/WebViewCore.h b/WebKit/android/jni/WebViewCore.h index 967023a..7bac254 100644 --- a/WebKit/android/jni/WebViewCore.h +++ b/WebKit/android/jni/WebViewCore.h @@ -70,6 +70,8 @@ class SkIRect; namespace android { + class CachedFrame; + class CachedNode; class CachedRoot; class ListBoxReply; @@ -439,6 +441,8 @@ namespace android { float scale() const { return m_scale; } float screenWidthScale() const { return m_screenWidthScale; } WebCore::Frame* mainFrame() const { return m_mainFrame; } + void updateCursorBounds(const CachedRoot* root, + const CachedFrame* cachedFrame, const CachedNode* cachedNode); void updateFrameCacheIfLoading(); // utility to split slow parts of the picture set diff --git a/WebKit/android/nav/CachedFrame.cpp b/WebKit/android/nav/CachedFrame.cpp index b1f4193..1bca22b 100644 --- a/WebKit/android/nav/CachedFrame.cpp +++ b/WebKit/android/nav/CachedFrame.cpp @@ -893,6 +893,18 @@ const CachedLayer* CachedFrame::layer(const CachedNode* node) const } #endif +WebCore::IntRect CachedFrame::localBounds(const CachedNode* node, + const WebCore::IntRect& rect) const +{ + DBG_NAV_LOGD("node=%p [%d] rect=(%d,%d,w=%d,h=%d)", + node, node->index(), rect.x(), rect.y(), rect.width(), rect.height()); +#if USE(ACCELERATED_COMPOSITING) + return layer(node)->localBounds(rect); +#else + return rect; +#endif +} + int CachedFrame::minWorkingHorizontal() const { return history()->minWorkingHorizontal(); diff --git a/WebKit/android/nav/CachedFrame.h b/WebKit/android/nav/CachedFrame.h index 613b2eb..146d325 100644 --- a/WebKit/android/nav/CachedFrame.h +++ b/WebKit/android/nav/CachedFrame.h @@ -113,6 +113,8 @@ public: #if USE(ACCELERATED_COMPOSITING) const CachedLayer* layer(const CachedNode* ) const; #endif + WebCore::IntRect localBounds(const CachedNode* , + const WebCore::IntRect& ) const; /** * Find the next textfield/textarea * @param start Must be a CachedNode in this CachedFrame's tree, or diff --git a/WebKit/android/nav/CachedLayer.cpp b/WebKit/android/nav/CachedLayer.cpp index dd64f05..12096c7 100644 --- a/WebKit/android/nav/CachedLayer.cpp +++ b/WebKit/android/nav/CachedLayer.cpp @@ -70,6 +70,14 @@ const LayerAndroid* CachedLayer::layer(const LayerAndroid* root) const return mLayer = root->findById(mUniqueId); } +// return bounds relative to enclosing layer as recorded when walking the dom +IntRect CachedLayer::localBounds(const IntRect& bounds) const +{ + IntRect temp = bounds; + temp.move(-mOffset.x(), -mOffset.y()); + return temp; +} + SkPicture* CachedLayer::picture(const LayerAndroid* root) const { const LayerAndroid* aLayer = layer(root); diff --git a/WebKit/android/nav/CachedLayer.h b/WebKit/android/nav/CachedLayer.h index d320b0c..c802407 100644 --- a/WebKit/android/nav/CachedLayer.h +++ b/WebKit/android/nav/CachedLayer.h @@ -45,9 +45,12 @@ public: bool operator<(const CachedLayer& l) const { return mCachedNodeIndex < l.mCachedNodeIndex; } + // FIXME: adjustBounds should be renamed globalBounds or toGlobal IntRect adjustBounds(const LayerAndroid* root, const IntRect& bounds) const; int cachedNodeIndex() const { return mCachedNodeIndex; } + const IntPoint& getOffset() const { return mOffset; } const LayerAndroid* layer(const LayerAndroid* root) const; + IntRect localBounds(const IntRect& bounds) const; SkPicture* picture(const LayerAndroid* root) const; void reset() { mLayer = 0; } void setCachedNodeIndex(int index) { mCachedNodeIndex = index; } diff --git a/WebKit/android/nav/CachedNode.cpp b/WebKit/android/nav/CachedNode.cpp index e5040ea..0c9d541 100644 --- a/WebKit/android/nav/CachedNode.cpp +++ b/WebKit/android/nav/CachedNode.cpp @@ -249,6 +249,31 @@ bool CachedNode::isTextField(const CachedFrame* frame) const return input ? input->isTextField() : false; } +void CachedNode::localCursorRings(const CachedFrame* frame, + WTF::Vector<WebCore::IntRect>* rings) const +{ + rings->clear(); + for (unsigned index = 0; index < mCursorRing.size(); index++) + rings->append(localRing(frame, index)); +} + +WebCore::IntRect CachedNode::localBounds(const CachedFrame* frame) const +{ + return mIsInLayer ? frame->localBounds(this, mBounds) : mBounds; +} + +WebCore::IntRect CachedNode::localHitBounds(const CachedFrame* frame) const +{ + return mIsInLayer ? frame->localBounds(this, mHitBounds) : mHitBounds; +} + +WebCore::IntRect CachedNode::localRing(const CachedFrame* frame, + size_t part) const +{ + const WebCore::IntRect& rect = mCursorRing.at(part); + return mIsInLayer ? frame->localBounds(this, rect) : rect; +} + void CachedNode::move(int x, int y) { mBounds.move(x, y); diff --git a/WebKit/android/nav/CachedNode.h b/WebKit/android/nav/CachedNode.h index a5fc0da..f3cfd98 100644 --- a/WebKit/android/nav/CachedNode.h +++ b/WebKit/android/nav/CachedNode.h @@ -125,6 +125,12 @@ public: bool isTextInput() const { return mType == TEXT_INPUT_CACHEDNODETYPE; } bool isTransparent() const { return mIsTransparent; } bool isUnclipped() const { return mIsUnclipped; } + // localXXX functions are used only for drawing cursor rings + WebCore::IntRect localBounds(const CachedFrame* ) const; + void localCursorRings(const CachedFrame* , + WTF::Vector<WebCore::IntRect>* ) const; + WebCore::IntRect localHitBounds(const CachedFrame* ) const; + WebCore::IntRect localRing(const CachedFrame* , size_t part) const; void move(int x, int y); int navableRects() const { return mNavableRects; } void* nodePointer() const { return mNode; } diff --git a/WebKit/android/nav/CachedRoot.h b/WebKit/android/nav/CachedRoot.h index ae1530f..735f23b 100644 --- a/WebKit/android/nav/CachedRoot.h +++ b/WebKit/android/nav/CachedRoot.h @@ -32,7 +32,6 @@ #include "SkRegion.h" #include "wtf/Vector.h" -class FindCanvas; class SkRect; namespace WebCore { @@ -43,6 +42,7 @@ namespace android { class CachedHistory; class CachedNode; +class FindCanvas; class CachedRoot : public CachedFrame { public: diff --git a/WebKit/android/nav/DrawExtra.h b/WebKit/android/nav/DrawExtra.h new file mode 100644 index 0000000..ca4e87a --- /dev/null +++ b/WebKit/android/nav/DrawExtra.h @@ -0,0 +1,47 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DrawExtra_h +#define DrawExtra_h + +class SkCanvas; + +namespace WebCore { + class LayerAndroid; +} + +using namespace WebCore; + +namespace android { + +class DrawExtra { +public: + virtual ~DrawExtra() {} + virtual void draw(SkCanvas* , LayerAndroid* ) = 0; +}; + +} + +#endif diff --git a/WebKit/android/nav/FindCanvas.cpp b/WebKit/android/nav/FindCanvas.cpp index b917eb9..3a0ef33 100644 --- a/WebKit/android/nav/FindCanvas.cpp +++ b/WebKit/android/nav/FindCanvas.cpp @@ -35,6 +35,8 @@ #include <utils/Log.h> +namespace android { + // MatchInfo methods //////////////////////////////////////////////////////////////////////////////// @@ -227,7 +229,7 @@ SkRect FindCanvas::addMatchPosH(int index, return r; } -void FindCanvas::drawLayers(WebCore::LayerAndroid* layer) { +void FindCanvas::drawLayers(LayerAndroid* layer) { #if USE(ACCELERATED_COMPOSITING) SkPicture* picture = layer->picture(); if (picture) { @@ -509,10 +511,15 @@ void FindOnPage::setUpFindPaint() { m_isFindPaintSetUp = true; } -WebCore::IntRect FindOnPage::currentMatchBounds() const { +IntRect FindOnPage::currentMatchBounds() const { + IntRect noBounds = IntRect(0, 0, 0, 0); if (!m_matches || !m_matches->size()) - return WebCore::IntRect(0, 0, 0, 0); - return (*m_matches)[m_findIndex].getLocation().getBounds(); + return noBounds; + MatchInfo& info = (*m_matches)[m_findIndex]; + // FIXME: this should test if the match in the layer is visible + if (info.isInLayer()) + return noBounds; + return info.getLocation().getBounds(); } // This function is only used by findNext and setMatches. In it, we store @@ -529,10 +536,10 @@ void FindOnPage::storeCurrentMatchLocation() { // matches than this, only draw the focused match. #define MAX_NUMBER_OF_MATCHES_TO_DRAW 101 -void FindOnPage::drawLayer(SkCanvas* canvas, const WebCore::IntRect* visRect, - int layerId) { +void FindOnPage::draw(SkCanvas* canvas, LayerAndroid* layer) { if (!m_matches || !m_matches->size()) return; + int layerId = layer->uniqueId(); if (m_findIndex >= m_matches->size()) m_findIndex = 0; const MatchInfo& matchInfo = (*m_matches)[m_findIndex]; @@ -561,8 +568,11 @@ void FindOnPage::drawLayer(SkCanvas* canvas, const WebCore::IntRect* visRect, const SkRegion& region = (*m_matches)[i].getLocation(); // Do not draw matches which intersect the current one, or if it is // offscreen - if (currentMatchRegion.intersects(region) - || (visRect && !region.intersects(*visRect))) + if (currentMatchRegion.intersects(region)) + continue; + SkRect bounds; + bounds.set(region.getBounds()); + if (canvas->quickReject(bounds, SkCanvas::kAA_EdgeType)) continue; drawMatch(region, canvas, false); } @@ -648,3 +658,5 @@ void FindOnPage::setMatches(WTF::Vector<MatchInfo>* matches) } } +} + diff --git a/WebKit/android/nav/FindCanvas.h b/WebKit/android/nav/FindCanvas.h index fd04bd0..0b896b8 100644 --- a/WebKit/android/nav/FindCanvas.h +++ b/WebKit/android/nav/FindCanvas.h @@ -26,6 +26,7 @@ #ifndef Find_Canvas_h #define Find_Canvas_h +#include "DrawExtra.h" #include "IntRect.h" #include "SkBounder.h" #include "SkCanvas.h" @@ -35,13 +36,7 @@ #include "icu/unicode/umachine.h" #include "wtf/Vector.h" -// class SkIRect; -// class SkRect; -// class SkTypeface; - -namespace WebCore { - class LayerAndroid; -} +namespace android { // Stores both region information and an SkPicture of the match, so that the // region can be drawn, followed by drawing the matching text on top of it. @@ -144,7 +139,7 @@ public: const SkPaint& paint) { } - void drawLayers(WebCore::LayerAndroid* ); + void drawLayers(LayerAndroid* ); int found() const { return mNumFound; } void setLayerId(int layerId) { mLayerId = layerId; } @@ -215,17 +210,17 @@ private: int mLayerId; }; -class FindOnPage { +class FindOnPage : public DrawExtra { public: FindOnPage() { m_matches = 0; m_hasCurrentLocation = false; m_isFindPaintSetUp = false; } - ~FindOnPage() { delete m_matches; } + virtual ~FindOnPage() { delete m_matches; } void clearCurrentLocation() { m_hasCurrentLocation = false; } - WebCore::IntRect currentMatchBounds() const; - void drawLayer(SkCanvas* canvas, const WebCore::IntRect* vis, int layerId); + IntRect currentMatchBounds() const; + virtual void draw(SkCanvas* , LayerAndroid* ); void findNext(bool forward); void setMatches(WTF::Vector<MatchInfo>* matches); private: @@ -246,4 +241,6 @@ private: unsigned m_findIndex; }; +} + #endif // Find_Canvas_h diff --git a/WebKit/android/nav/SelectText.cpp b/WebKit/android/nav/SelectText.cpp index d8b184a..f028a0f 100644 --- a/WebKit/android/nav/SelectText.cpp +++ b/WebKit/android/nav/SelectText.cpp @@ -26,17 +26,26 @@ #define LOG_TAG "webcoreglue" #include "CachedPrefix.h" +#include "CachedRoot.h" +#include "LayerAndroid.h" #include "SelectText.h" #include "SkBitmap.h" #include "SkBounder.h" #include "SkCanvas.h" #include "SkMatrix.h" #include "SkPicture.h" +#include "SkPixelXorXfermode.h" #include "SkPoint.h" #include "SkRect.h" #include "SkRegion.h" #include "SkUtils.h" +#ifdef DEBUG_NAV_UI +#include "CString.h" +#endif + +namespace android { + class CommonCheck : public SkBounder { public: CommonCheck() : mMatrix(NULL), mPaint(NULL) {} @@ -342,3 +351,105 @@ WebCore::String CopyPaste::text(const SkPicture& picture, const SkIRect& area, checker.drawPicture(const_cast<SkPicture&>(picture)); return extractor.text(); } + +void SelectText::draw(SkCanvas* canvas, LayerAndroid* layer) +{ + if (layer->picture() != m_picture) + return; + if (m_drawRegion) + drawSelectionRegion(canvas); + if (m_drawPointer) + drawSelectionPointer(canvas); +} + +void SelectText::drawSelectionPointer(SkCanvas* canvas) +{ + SkPath path; + if (m_extendSelection) + getSelectionCaret(&path); + else + getSelectionArrow(&path); + SkPaint paint; + paint.setAntiAlias(true); + paint.setStyle(SkPaint::kStroke_Style); + paint.setColor(SK_ColorBLACK); + SkPixelXorXfermode xorMode(SK_ColorWHITE); + if (m_extendSelection) + paint.setXfermode(&xorMode); + else + paint.setStrokeWidth(SK_Scalar1 * 2); + int sc = canvas->save(); + canvas->scale(m_inverseScale, m_inverseScale); + canvas->translate(SkIntToScalar(m_selectX), SkIntToScalar(m_selectY)); + canvas->drawPath(path, paint); + if (!m_extendSelection) { + paint.setStyle(SkPaint::kFill_Style); + paint.setColor(SK_ColorWHITE); + canvas->drawPath(path, paint); + } + canvas->restoreToCount(sc); +} + +void SelectText::drawSelectionRegion(SkCanvas* canvas) +{ + m_selRegion.setEmpty(); + SkRect visBounds; + if (!canvas->getClipBounds(&visBounds, SkCanvas::kAA_EdgeType)) + return; + SkIRect ivisBounds; + visBounds.round(&ivisBounds); + CopyPaste::buildSelection(*m_picture, ivisBounds, m_selStart, m_selEnd, + &m_selRegion); + SkPath path; + m_selRegion.getBoundaryPath(&path); + SkPaint paint; + paint.setAntiAlias(true); + paint.setColor(SkColorSetARGB(0x40, 255, 51, 204)); + canvas->drawPath(path, paint); +} + +const String SelectText::getSelection() +{ + String result = CopyPaste::text(*m_picture, m_visibleRect, m_selRegion); + DBG_NAV_LOGD("text=%s", result.latin1().data()); // uses CString + return result; +} + +void SelectText::getSelectionArrow(SkPath* path) +{ + const int arrow[] = { + 0, 14, 3, 11, 5, 15, 9, 15, 7, 11, 11, 11 + }; + for (unsigned index = 0; index < sizeof(arrow)/sizeof(arrow[0]); index += 2) + path->lineTo(SkIntToScalar(arrow[index]), SkIntToScalar(arrow[index + 1])); + path->close(); +} + +void SelectText::getSelectionCaret(SkPath* path) +{ + SkScalar height = SkIntToScalar(m_selStart.fBottom - m_selStart.fTop); + SkScalar dist = height / 4; + path->moveTo(0, -height / 2); + path->rLineTo(0, height); + path->rLineTo(-dist, dist); + path->rMoveTo(0, -SK_Scalar1/2); + path->rLineTo(dist * 2, 0); + path->rMoveTo(0, SK_Scalar1/2); + path->rLineTo(-dist, -dist); +} + +void SelectText::moveSelection(const SkPicture* picture, int x, int y, + bool extendSelection) +{ + if (!extendSelection) + m_picture = picture; + m_selEnd = CopyPaste::findClosest(*picture, m_visibleRect, x, y); + if (!extendSelection) + m_selStart = m_selEnd; + DBG_NAV_LOGD("x=%d y=%d extendSelection=%s m_selStart=(%d, %d, %d, %d)" + " m_selEnd=(%d, %d, %d, %d)", x, y, extendSelection ? "true" : "false", + m_selStart.fLeft, m_selStart.fTop, m_selStart.fRight, m_selStart.fBottom, + m_selEnd.fLeft, m_selEnd.fTop, m_selEnd.fRight, m_selEnd.fBottom); +} + +} diff --git a/WebKit/android/nav/SelectText.h b/WebKit/android/nav/SelectText.h index 32d8311..8174046 100644 --- a/WebKit/android/nav/SelectText.h +++ b/WebKit/android/nav/SelectText.h @@ -26,21 +26,59 @@ #ifndef SELECT_TEXT_H #define SELECT_TEXT_H +#include "DrawExtra.h" +#include "IntRect.h" #include "PlatformString.h" class SkPicture; struct SkIRect; -struct SkIPoint; class SkRegion; +namespace android { + +class CachedRoot; + class CopyPaste { public: static void buildSelection(const SkPicture& , const SkIRect& area, const SkIRect& selStart, const SkIRect& selEnd, SkRegion* region); static SkIRect findClosest(const SkPicture& , const SkIRect& area, int x, int y); - static WebCore::String text(const SkPicture& , const SkIRect& area, + static String text(const SkPicture& , const SkIRect& area, const SkRegion& ); }; +class SelectText : public DrawExtra { +public: + SelectText() { + m_selStart.setEmpty(); + m_selEnd.setEmpty(); + } + virtual void draw(SkCanvas* , LayerAndroid* ); + const String getSelection(); + void moveSelection(const SkPicture* , int x, int y, bool extendSelection); + void setDrawPointer(bool drawPointer) { m_drawPointer = drawPointer; } + void setDrawRegion(bool drawRegion) { m_drawRegion = drawRegion; } + void setVisibleRect(const IntRect& rect) { m_visibleRect = rect; } +private: + friend class WebView; + void drawSelectionPointer(SkCanvas* ); + void drawSelectionRegion(SkCanvas* ); + static void getSelectionArrow(SkPath* ); + void getSelectionCaret(SkPath* ); + SkIRect m_selStart; + SkIRect m_selEnd; + SkIRect m_visibleRect; + SkRegion m_selRegion; + const SkPicture* m_picture; + float m_inverseScale; + int m_selectX; + int m_selectY; + bool m_drawRegion; + bool m_drawPointer; + bool m_extendSelection; +}; + +} + #endif diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp index c64d36a..bcc6c26 100644 --- a/WebKit/android/nav/WebView.cpp +++ b/WebKit/android/nav/WebView.cpp @@ -34,6 +34,7 @@ #include "CachedNode.h" #include "CachedRoot.h" #include "CString.h" +#include "DrawExtra.h" #include "FindCanvas.h" #include "Frame.h" #include "GraphicsJNI.h" @@ -47,9 +48,7 @@ #include "SelectText.h" #include "SkCanvas.h" #include "SkDumpCanvas.h" -#include "SkPath.h" #include "SkPicture.h" -#include "SkPixelXorXfermode.h" #include "SkRect.h" #include "SkTime.h" #ifdef ANDROID_INSTRUMENT @@ -95,6 +94,13 @@ enum FrameCachePermission { AllowNewest }; +enum DrawExtras { // keep this in sync with WebView.java + DrawExtrasNone = 0, + DrawExtrasFind = 1, + DrawExtrasSelection = 2, + DrawExtrasCursorRing = 3 +}; + struct JavaGlue { jweak m_obj; jmethodID m_clearTextEntry; @@ -121,13 +127,14 @@ struct JavaGlue { jfieldID m_metricsScrollY; jfieldID m_metricsWidth; jfieldID m_metricsHeight; - jfieldID m_metricsScale; + jfieldID m_metricsInvScale; AutoJObject object(JNIEnv* env) { return getRealObject(env, m_obj); } } m_javaGlue; -WebView(JNIEnv* env, jobject javaWebView, int viewImpl) +WebView(JNIEnv* env, jobject javaWebView, int viewImpl) : + m_ring((WebViewCore*) viewImpl) { jclass clazz = env->FindClass("android/webkit/WebView"); // m_javaGlue = new JavaGlue; @@ -160,7 +167,7 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl) m_javaGlue.m_metricsScrollY = env->GetFieldID(metricsClass, "mScrollY", "I"); m_javaGlue.m_metricsWidth = env->GetFieldID(metricsClass, "mWidth", "I"); m_javaGlue.m_metricsHeight = env->GetFieldID(metricsClass, "mHeight", "I"); - m_javaGlue.m_metricsScale = env->GetFieldID(metricsClass, "mScale", "F"); + m_javaGlue.m_metricsInvScale = env->GetFieldID(metricsClass, "mInvScale", "F"); env->SetIntField(javaWebView, gWebViewField, (jint)this); m_viewImpl = (WebViewCore*) viewImpl; @@ -168,12 +175,10 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl) m_navPictureUI = 0; m_generation = 0; m_heightCanMeasure = false; - m_followedLink = false; + m_ring.m_followedLink = false; m_lastDx = 0; m_lastDxTime = 0; m_ringAnimationEnd = 0; - m_selStart.setEmpty(); - m_selEnd.setEmpty(); m_rootLayer = 0; } @@ -187,6 +192,7 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl) } delete m_frameCacheUI; delete m_navPictureUI; + delete m_rootLayer; } WebViewCore* getWebViewCore() const { @@ -272,7 +278,7 @@ void nativeRecordButtons(bool hasFocus, bool pressed, bool invalidate) // button if (!hasFocus) { state = WebCore::RenderSkinAndroid::kNormal; - } else if (m_followedLink || pressed) { + } else if (m_ring.m_followedLink || pressed) { state = WebCore::RenderSkinAndroid::kPressed; } else { state = WebCore::RenderSkinAndroid::kFocused; @@ -314,134 +320,102 @@ bool scrollRectOnScreen(int left, int top, int right, int bottom) return true; } -// draws the root matches only. Matches over layers are drawn by LayerAndroid -void drawMatches(SkCanvas* canvas) -{ - WebCore::IntRect visible; - getVisibleRect(&visible); - m_findOnPage.drawLayer(canvas, &visible, -1); - WebCore::IntRect currentMatchBounds = m_findOnPage.currentMatchBounds(); - if (currentMatchBounds.isEmpty()) - return; - scrollRectOnScreen(currentMatchBounds.x(), currentMatchBounds.y(), - currentMatchBounds.right(), currentMatchBounds.bottom()); -} - -FindOnPage* findOnPage() -{ - return m_viewImpl->m_findIsUp ? &m_findOnPage : 0; -} - void resetCursorRing() { - m_followedLink = false; + m_ring.m_followedLink = false; m_viewImpl->m_hasCursorBounds = false; } -void drawCursorRing(SkCanvas* canvas) +bool drawCursorPreamble(CachedRoot* root) { - CachedRoot* root = getFrameCache(AllowNewer); - if (!root) { - DBG_NAV_LOG("!root"); - resetCursorRing(); - return; - } const CachedFrame* frame; const CachedNode* node = root->currentCursor(&frame); if (!node) { DBG_NAV_LOGV("%s", "!node"); resetCursorRing(); - return; + return false; } if (node->isHidden()) { DBG_NAV_LOG("node->isHidden()"); m_viewImpl->m_hasCursorBounds = false; - return; + return false; } setVisibleRect(root); - WTF::Vector<WebCore::IntRect> rings; - node->cursorRings(frame, &rings); - if (!rings.size()) { - DBG_NAV_LOG("!rings.size()"); - m_viewImpl->m_hasCursorBounds = false; + m_ring.m_root = root; + m_ring.m_frame = frame; + m_ring.m_node = node; + return true; +} + +void drawCursorPostamble() +{ + if (!m_ring.m_isButton && m_ring.m_flavor < CursorRing::NORMAL_ANIMATING) return; + SkMSec time = SkTime::GetMSecs(); + if (time < m_ringAnimationEnd) { + // views assume that inval bounds coordinates are non-negative + WebCore::IntRect invalBounds(0, 0, INT_MAX, INT_MAX); + invalBounds.intersect(m_ring.m_bounds); + postInvalidateDelayed(m_ringAnimationEnd - time, invalBounds); + } else { + if (m_ring.m_followedLink) + hideCursor(); + m_ring.m_followedLink = false; + m_ring.m_flavor = static_cast<CursorRing::Flavor> + (m_ring.m_flavor - CursorRing::NORMAL_ANIMATING); } - bool isButton = false; - m_viewImpl->gButtonMutex.lock(); - // If this is a button drawn by us (rather than webkit) do not draw the - // cursor ring, since its cursor will be shown by a change in what we draw. - // 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*) node->nodePointer(); - Container* end = m_viewImpl->m_buttons.end(); - for (Container* ptr = m_viewImpl->m_buttons.begin(); ptr != end; ptr++) { - if (ptr->matches(cursorPointer)) { - isButton = true; - break; - } - } - } - m_viewImpl->gButtonMutex.unlock(); - WebCore::IntRect bounds = node->bounds(frame); - updateCursorBounds(root, frame, node); +} - bool useHitBounds = node->useHitBounds(); - if (useHitBounds) { - bounds = node->hitBounds(frame); +void drawExtras(SkCanvas* canvas, int extras) +{ + CachedRoot* root = getFrameCache(AllowNewer); + if (!root) { + DBG_NAV_LOG("!root"); + if (extras == DrawExtrasCursorRing) + resetCursorRing(); + return; } - if (useHitBounds || node->useBounds()) { - rings.clear(); - rings.append(bounds); + LayerAndroid mainPicture(m_navPictureUI); + DrawExtra* extra = 0; + switch (extras) { + case DrawExtrasFind: + extra = &m_findOnPage; + break; + case DrawExtrasSelection: + extra = &m_selectText; + break; + case DrawExtrasCursorRing: + if (drawCursorPreamble(root) && m_ring.setup()) { + if (!m_ring.m_isButton) + extra = &m_ring; + drawCursorPostamble(); + } + break; + default: + ; } - bounds.inflate(SkScalarCeil(CURSOR_RING_OUTER_DIAMETER)); - if (canvas->quickReject(bounds, SkCanvas::kAA_EdgeType)) { - DBG_NAV_LOGD("canvas->quickReject cursorNode=%d (nodePointer=%p)" - " bounds=(%d,%d,w=%d,h=%d)", node->index(), node->nodePointer(), - bounds.x(), bounds.y(), bounds.width(), bounds.height()); - m_followedLink = false; - return; + if (extra) + extra->draw(canvas, &mainPicture); + if (extras == DrawExtrasFind) { + IntRect currentMatchBounds = m_findOnPage.currentMatchBounds(); + if (!currentMatchBounds.isEmpty()) + scrollRectOnScreen(currentMatchBounds.x(), currentMatchBounds.y(), + currentMatchBounds.right(), currentMatchBounds.bottom()); } - if (!node->hasCursorRing() || (node->isPlugin() && node->isFocus())) +#if USE(ACCELERATED_COMPOSITING) + if (!m_rootLayer) return; - CursorRing::Flavor flavor = CursorRing::NORMAL_FLAVOR; - if (!isButton) { - flavor = node->isSyntheticLink() - ? CursorRing::FAKE_FLAVOR : CursorRing::NORMAL_FLAVOR; - if (m_followedLink) { - flavor = static_cast<CursorRing::Flavor> - (flavor + CursorRing::NORMAL_ANIMATING); - } -#if DEBUG_NAV_UI - const WebCore::IntRect& ring = rings[0]; - DBG_NAV_LOGD("cursorNode=%d (nodePointer=%p) flavor=%s rings=%d" - " (%d, %d, %d, %d) isPlugin=%s", - node->index(), node->nodePointer(), - flavor == CursorRing::FAKE_FLAVOR ? "FAKE_FLAVOR" : - flavor == CursorRing::NORMAL_ANIMATING ? "NORMAL_ANIMATING" : - flavor == CursorRing::FAKE_ANIMATING ? "FAKE_ANIMATING" : "NORMAL_FLAVOR", - rings.size(), ring.x(), ring.y(), ring.width(), ring.height(), - node->isPlugin() ? "true" : "false"); + m_rootLayer->setExtra(extra); + SkRect viewMetrics; + getViewMetrics(&viewMetrics); + // call this to be sure we've adjusted for any scrolling or animations + // before we actually draw + m_rootLayer->updatePositions(viewMetrics); + m_rootLayer->draw(canvas); #endif - } - if (isButton || flavor >= CursorRing::NORMAL_ANIMATING) { - SkMSec time = SkTime::GetMSecs(); - if (time < m_ringAnimationEnd) { - // views assume that inval bounds coordinates are non-negative - bounds.intersect(WebCore::IntRect(0, 0, INT_MAX, INT_MAX)); - postInvalidateDelayed(m_ringAnimationEnd - time, bounds); - } else { - if (m_followedLink) - hideCursor(); - m_followedLink = false; - flavor = static_cast<CursorRing::Flavor> - (flavor - CursorRing::NORMAL_ANIMATING); - } - } - if (!isButton) - CursorRing::DrawRing(canvas, rings, flavor); } + bool cursorIsTextInput(FrameCachePermission allowNewer) { CachedRoot* root = getFrameCache(allowNewer); @@ -636,9 +610,9 @@ void getViewMetrics(SkRect* viewMetrics) int scrollY = env->GetIntField(jMetrics, m_javaGlue.m_metricsScrollY); int width = env->GetIntField(jMetrics, m_javaGlue.m_metricsWidth); int height = env->GetIntField(jMetrics, m_javaGlue.m_metricsHeight); - float scale = env->GetFloatField(jMetrics, m_javaGlue.m_metricsScale); - viewMetrics->set(scrollX / scale, scrollY / scale, - (scrollX + width) / scale, (scrollY + height) / scale); + float invScale = env->GetFloatField(jMetrics, m_javaGlue.m_metricsInvScale); + viewMetrics->set(scrollX * invScale, scrollY * invScale, + (scrollX + width) * invScale, (scrollY + height) * invScale); env->DeleteLocalRef(jMetrics); checkException(env); } @@ -681,33 +655,6 @@ bool cursorWantsKeyEvents() return false; } -// This needs to be called each time we call CachedRoot::setCursor() with -// non-null CachedNode/CachedFrame, since otherwise the WebViewCore's data -// about the cursor is incorrect. When we call setCursor(0,0), we need -// to set m_viewImpl->hasCursorBounds to false. -void updateCursorBounds(const CachedRoot* root, const CachedFrame* cachedFrame, - const CachedNode* cachedNode) -{ - LOG_ASSERT(root, "updateCursorBounds: root cannot be null"); - LOG_ASSERT(cachedNode, "updateCursorBounds: cachedNode cannot be null"); - LOG_ASSERT(cachedFrame, "updateCursorBounds: cachedFrame cannot be null"); - m_viewImpl->gCursorBoundsMutex.lock(); - m_viewImpl->m_hasCursorBounds = !cachedNode->isHidden(); - // If m_viewImpl->m_hasCursorBounds is false, we never look at the other - // values, so do not bother setting them. - if (m_viewImpl->m_hasCursorBounds) { - WebCore::IntRect bounds = cachedNode->bounds(cachedFrame); - if (m_viewImpl->m_cursorBounds != bounds) - DBG_NAV_LOGD("new cursor bounds=(%d,%d,w=%d,h=%d)", - bounds.x(), bounds.y(), bounds.width(), bounds.height()); - m_viewImpl->m_cursorBounds = bounds; - m_viewImpl->m_cursorHitBounds = cachedNode->hitBounds(cachedFrame); - m_viewImpl->m_cursorFrame = cachedFrame->framePointer(); - root->getSimulatedMousePosition(&m_viewImpl->m_cursorLocation); - m_viewImpl->m_cursorNode = cachedNode->nodePointer(); - } - m_viewImpl->gCursorBoundsMutex.unlock(); -} /* returns true if the key had no effect (neither scrolled nor changed cursor) */ bool moveCursor(int keyCode, int count, bool ignoreScroll) @@ -734,8 +681,8 @@ bool moveCursor(int keyCode, int count, bool ignoreScroll) int dx = 0; int dy = 0; int counter = count; - if (!cursor || !m_followedLink) - root->setScrollOnly(m_followedLink); + if (!cursor || !m_ring.m_followedLink) + root->setScrollOnly(m_ring.m_followedLink); while (--counter >= 0) { WebCore::IntPoint scroll = WebCore::IntPoint(0, 0); cachedNode = root->moveCursor(direction, &cachedFrame, &scroll); @@ -767,7 +714,7 @@ bool moveCursor(int keyCode, int count, bool ignoreScroll) } bool result = false; if (cachedNode) { - updateCursorBounds(root, cachedFrame, cachedNode); + m_viewImpl->updateCursorBounds(root, cachedFrame, cachedNode); root->setCursor(const_cast<CachedFrame*>(cachedFrame), const_cast<CachedNode*>(cachedNode)); bool disableFocusController = cachedNode != root->currentFocus() @@ -843,7 +790,7 @@ void selectBestAt(const WebCore::IntRect& rect) } else { DBG_NAV_LOGD("CachedNode:%p (%d)", node, node->index()); root->rootHistory()->setMouseBounds(node->bounds(frame)); - updateCursorBounds(root, frame, node); + m_viewImpl->updateCursorBounds(root, frame, node); root->setCursor(const_cast<CachedFrame*>(frame), const_cast<CachedNode*>(node)); } @@ -884,7 +831,7 @@ bool pointInNavCache(int x, int y, int slop) bool motionUp(int x, int y, int slop) { bool pageScrolled = false; - m_followedLink = false; + m_ring.m_followedLink = false; IntRect rect = IntRect(x - slop, y - slop, slop * 2, slop * 2); int rx, ry; CachedRoot* root = getFrameCache(AllowNewer); @@ -913,7 +860,7 @@ bool motionUp(int x, int y, int slop) WebCore::IntRect navBounds = WebCore::IntRect(rx, ry, 1, 1); setNavBounds(navBounds); root->rootHistory()->setMouseBounds(navBounds); - updateCursorBounds(root, frame, result); + m_viewImpl->updateCursorBounds(root, frame, result); root->setCursor(const_cast<CachedFrame*>(frame), const_cast<CachedNode*>(result)); bool syntheticLink = result->isSyntheticLink(); @@ -958,7 +905,7 @@ void setFindIsUp(bool up) void setFollowedLink(bool followed) { - if ((m_followedLink = followed) != false) { + if ((m_ring.m_followedLink = followed) != false) { m_ringAnimationEnd = SkTime::GetMSecs() + 500; viewInvalidate(); } @@ -969,108 +916,40 @@ void setHeightCanMeasure(bool measure) m_heightCanMeasure = measure; } -SkIRect m_selStart, m_selEnd; -SkRegion m_selRegion; -#define MIN_ARROW_DISTANCE (20 * 20) - -void moveSelection(int x, int y, bool extendSelection) +String getSelection() { - CachedRoot* root = getFrameCache(DontAllowNewer); - if (!root) - return; - const SkPicture& picture = *m_navPictureUI; - WebCore::IntRect r; - getVisibleRect(&r); - SkIRect area; - area.set(r.x(), r.y(), r.right(), r.bottom()); - m_selEnd = CopyPaste::findClosest(picture, area, x, y); - if (!extendSelection) - m_selStart = m_selEnd; - DBG_NAV_LOGD("x=%d y=%d extendSelection=%s m_selStart=(%d, %d, %d, %d)" - " m_selEnd=(%d, %d, %d, %d)", x, y, extendSelection ? "true" : "false", - m_selStart.fLeft, m_selStart.fTop, m_selStart.fRight, m_selStart.fBottom, - m_selEnd.fLeft, m_selEnd.fTop, m_selEnd.fRight, m_selEnd.fBottom); -} - -const String getSelection() -{ - WebCore::IntRect r; - getVisibleRect(&r); - SkIRect area; - area.set(r.x(), r.y(), r.right(), r.bottom()); - String result = CopyPaste::text(*m_navPictureUI, area, m_selRegion); - DBG_NAV_LOGD("text=%s", result.latin1().data()); - return result; + return m_selectText.getSelection(); } -void drawSelectionRegion(SkCanvas* canvas) +void moveSelection(int x, int y, bool extendSelection) { - CachedRoot* root = getFrameCache(DontAllowNewer); + const CachedRoot* root = getFrameCache(DontAllowNewer); if (!root) return; - WebCore::IntRect r; - getVisibleRect(&r); - SkIRect area; - area.set(r.x(), r.y(), r.right(), r.bottom()); - m_selRegion.setEmpty(); - CopyPaste::buildSelection(*m_navPictureUI, area, m_selStart, m_selEnd, &m_selRegion); - SkPath path; - m_selRegion.getBoundaryPath(&path); - SkPaint paint; - paint.setAntiAlias(true); - paint.setColor(SkColorSetARGB(0x40, 255, 51, 204)); - canvas->drawPath(path, paint); -} - -void drawSelectionPointer(SkCanvas* canvas, float scale, int x, int y, bool ex) -{ - SkPath path; - if (ex) - getSelectionCaret(&path); - else - getSelectionArrow(&path); - SkPaint paint; - paint.setAntiAlias(true); - paint.setStyle(SkPaint::kStroke_Style); - paint.setColor(SK_ColorBLACK); - SkPixelXorXfermode xorMode(SK_ColorWHITE); - if (ex) - paint.setXfermode(&xorMode); - else - paint.setStrokeWidth(SK_Scalar1 * 2); - int sc = canvas->save(); - canvas->scale(scale, scale); - canvas->translate(SkIntToScalar(x), SkIntToScalar(y)); - canvas->drawPath(path, paint); - if (!ex) { - paint.setStyle(SkPaint::kFill_Style); - paint.setColor(SK_ColorWHITE); - canvas->drawPath(path, paint); - } - canvas->restoreToCount(sc); + SkPicture* picture = root->pictureAt(x, y); + // FIXME: use the visibleRect only for the main picture + // for layer pictures, use the equivalent of the canvas clipping rect + IntRect visibleRect; + getVisibleRect(&visibleRect); + m_selectText.setVisibleRect(visibleRect); + m_selectText.moveSelection(picture, x, y, extendSelection); } -void getSelectionArrow(SkPath* path) +void setSelectionPointer(bool set, float scale, int x, int y, + bool extendSelection) { - const int arrow[] = { - 0, 14, 3, 11, 5, 15, 9, 15, 7, 11, 11, 11 - }; - for (unsigned index = 0; index < sizeof(arrow)/sizeof(arrow[0]); index += 2) - path->lineTo(SkIntToScalar(arrow[index]), SkIntToScalar(arrow[index + 1])); - path->close(); + m_selectText.setDrawPointer(set); + if (!set) + return; + m_selectText.m_extendSelection = extendSelection; + m_selectText.m_inverseScale = scale; + m_selectText.m_selectX = x; + m_selectText.m_selectY = y; } -void getSelectionCaret(SkPath* path) +void setSelectionRegion(bool set) { - SkScalar height = SkIntToScalar(m_selStart.fBottom - m_selStart.fTop); - SkScalar dist = height / 4; - path->moveTo(0, -height / 2); - path->rLineTo(0, height); - path->rLineTo(-dist, dist); - path->rMoveTo(0, -SK_Scalar1/2); - path->rLineTo(dist * 2, 0); - path->rMoveTo(0, SK_Scalar1/2); - path->rLineTo(-dist, -dist); + m_selectText.setDrawRegion(set); } void sendMoveFocus(WebCore::Frame* framePtr, WebCore::Node* nodePtr) @@ -1208,6 +1087,7 @@ const LayerAndroid* rootLayer() const void setRootLayer(LayerAndroid* layer) { + delete m_rootLayer; m_rootLayer = layer; CachedRoot* root = getFrameCache(DontAllowNewer); if (!root) @@ -1222,13 +1102,14 @@ private: // local state for WebView WebViewCore* m_viewImpl; int m_generation; // associate unique ID with sent kit focus to match with ui SkPicture* m_navPictureUI; - bool m_followedLink; SkMSec m_ringAnimationEnd; // Corresponds to the same-named boolean on the java side. bool m_heightCanMeasure; int m_lastDx; SkMSec m_lastDxTime; + SelectText m_selectText; FindOnPage m_findOnPage; + CursorRing m_ring; LayerAndroid* m_rootLayer; }; // end of WebView class @@ -1401,12 +1282,6 @@ static bool nativeCursorIsAnchor(JNIEnv *env, jobject obj) return node ? node->isAnchor() : false; } -static bool nativeCursorIsInLayer(JNIEnv *env, jobject obj) -{ - const CachedNode* node = getCursorNode(env, obj); - return node ? node->isInLayer() : false; -} - static bool nativeCursorIsTextInput(JNIEnv *env, jobject obj) { const CachedNode* node = getCursorNode(env, obj); @@ -1432,68 +1307,20 @@ static void nativeDebugDump(JNIEnv *env, jobject obj) #endif } -static void nativeDrawMatches(JNIEnv *env, jobject obj, jobject canv) +static void nativeDrawExtras(JNIEnv *env, jobject obj, jobject canv, jint extras) { SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv); - if (!canv) { - DBG_NAV_LOG("!canv"); - return; - } - WebView* view = GET_NATIVE_VIEW(env, obj); - if (!view) { - DBG_NAV_LOG("!view"); - return; - } - view->drawMatches(canvas); + GET_NATIVE_VIEW(env, obj)->drawExtras(canvas, extras); } -static void nativeDrawLayers(JNIEnv *env, jobject obj, jint layer, jobject canv) +static bool nativeEvaluateLayersAnimations(JNIEnv *env, jobject obj) { - if (!env) - return; - if (!layer) - return; - if (!canv) - return; - #if USE(ACCELERATED_COMPOSITING) - LayerAndroid* layerImpl = reinterpret_cast<LayerAndroid*>(layer); - SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv); - WebView* view = GET_NATIVE_VIEW(env, obj); - SkRect viewMetrics; - view->getViewMetrics(&viewMetrics); - layerImpl->setFindOnPage(view->findOnPage()); - // call this to be sure we've adjusted for any scrolling or animations - // before we actually draw - layerImpl->updatePositions(viewMetrics); - layerImpl->draw(canvas); + const LayerAndroid* root = GET_NATIVE_VIEW(env, obj)->rootLayer(); + if (root) + return root->evaluateAnimations(); #endif -} - -static bool nativeEvaluateLayersAnimations(JNIEnv *env, jobject obj, jint layer) -{ - if (!env) - return false; - if (!layer) - return false; -#if USE(ACCELERATED_COMPOSITING) - LayerAndroid* layerImpl = reinterpret_cast<LayerAndroid*>(layer); - return layerImpl->evaluateAnimations(); -#else return false; -#endif -} - -static void nativeDestroyLayer(JNIEnv *env, jobject obj, jint layer) -{ - if (!env) - return; - if (!layer) - return; -#if USE(ACCELERATED_COMPOSITING) - LayerAndroid* layerImpl = reinterpret_cast<LayerAndroid*>(layer); - delete layerImpl; -#endif } static void nativeSetRootLayer(JNIEnv *env, jobject obj, jint layer) @@ -1504,52 +1331,6 @@ static void nativeSetRootLayer(JNIEnv *env, jobject obj, jint layer) #endif } -static void nativeDrawCursorRing(JNIEnv *env, jobject obj, jobject canv) -{ - SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv); - if (!canv) { - DBG_NAV_LOG("!canv"); - return; - } - WebView* view = GET_NATIVE_VIEW(env, obj); - if (!view) { - DBG_NAV_LOG("!view"); - return; - } - view->drawCursorRing(canvas); -} - -static void nativeDrawSelectionPointer(JNIEnv *env, jobject obj, - jobject canv, jfloat scale, jint x, jint y, bool ex) -{ - SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv); - if (!canv) { - DBG_NAV_LOG("!canv"); - return; - } - WebView* view = GET_NATIVE_VIEW(env, obj); - if (!view) { - DBG_NAV_LOG("!view"); - return; - } - view->drawSelectionPointer(canvas, scale, x, y, ex); -} - -static void nativeDrawSelectionRegion(JNIEnv *env, jobject obj, jobject canv) -{ - SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv); - if (!canv) { - DBG_NAV_LOG("!canv"); - return; - } - WebView* view = GET_NATIVE_VIEW(env, obj); - if (!view) { - DBG_NAV_LOG("!view"); - return; - } - view->drawSelectionRegion(canvas); -} - static jobject nativeImageURI(JNIEnv *env, jobject obj, jint x, jint y) { WebView* view = GET_NATIVE_VIEW(env, obj); @@ -1922,7 +1703,7 @@ static void nativeMoveCursorToNextTextInput(JNIEnv *env, jobject obj) return; const WebCore::IntRect& bounds = next->bounds(frame); root->rootHistory()->setMouseBounds(bounds); - view->updateCursorBounds(root, frame, next); + view->getWebViewCore()->updateCursorBounds(root, frame, next); root->setCursor(const_cast<CachedFrame*>(frame), const_cast<CachedNode*>(next)); view->sendMoveFocus(static_cast<WebCore::Frame*>(frame->framePointer()), @@ -1955,6 +1736,17 @@ static jobject nativeGetSelection(JNIEnv *env, jobject obj) return env->NewString((jchar*)selection.characters(), selection.length()); } +static void nativeSetSelectionPointer(JNIEnv *env, jobject obj, jboolean set, + jfloat scale, jint x, jint y, bool ex) +{ + GET_NATIVE_VIEW(env, obj)->setSelectionPointer(set, scale, x, y, ex); +} + +static void nativeSetSelectionRegion(JNIEnv *env, jobject obj, jboolean set) +{ + GET_NATIVE_VIEW(env, obj)->setSelectionRegion(set); +} + #ifdef ANDROID_DUMP_DISPLAY_TREE static void dumpToFile(const char text[], void* file) { fwrite(text, 1, strlen(text), reinterpret_cast<FILE*>(file)); @@ -2028,8 +1820,6 @@ static JNINativeMethod gJavaWebViewMethods[] = { (void*) nativeCursorIntersects }, { "nativeCursorIsAnchor", "()Z", (void*) nativeCursorIsAnchor }, - { "nativeCursorIsInLayer", "()Z", - (void*) nativeCursorIsInLayer }, { "nativeCursorIsTextInput", "()Z", (void*) nativeCursorIsTextInput }, { "nativeCursorPosition", "()Landroid/graphics/Point;", @@ -2042,22 +1832,12 @@ static JNINativeMethod gJavaWebViewMethods[] = { (void*) nativeDebugDump }, { "nativeDestroy", "()V", (void*) nativeDestroy }, - { "nativeDrawCursorRing", "(Landroid/graphics/Canvas;)V", - (void*) nativeDrawCursorRing }, - { "nativeDestroyLayer", "(I)V", - (void*) nativeDestroyLayer }, - { "nativeDrawLayers", "(ILandroid/graphics/Canvas;)V", - (void*) nativeDrawLayers }, - { "nativeEvaluateLayersAnimations", "(I)Z", - (void*) nativeEvaluateLayersAnimations }, - { "nativeDrawMatches", "(Landroid/graphics/Canvas;)V", - (void*) nativeDrawMatches }, - { "nativeDrawSelectionPointer", "(Landroid/graphics/Canvas;FIIZ)V", - (void*) nativeDrawSelectionPointer }, - { "nativeDrawSelectionRegion", "(Landroid/graphics/Canvas;)V", - (void*) nativeDrawSelectionRegion }, + { "nativeDrawExtras", "(Landroid/graphics/Canvas;I)V", + (void*) nativeDrawExtras }, { "nativeDumpDisplayTree", "(Ljava/lang/String;)V", (void*) nativeDumpDisplayTree }, + { "nativeEvaluateLayersAnimations", "()Z", + (void*) nativeEvaluateLayersAnimations }, { "nativeFindAll", "(Ljava/lang/String;Ljava/lang/String;)I", (void*) nativeFindAll }, { "nativeFindNext", "(Z)V", @@ -2126,6 +1906,10 @@ static JNINativeMethod gJavaWebViewMethods[] = { (void*) nativeSetHeightCanMeasure }, { "nativeSetRootLayer", "(I)V", (void*) nativeSetRootLayer }, + { "nativeSetSelectionPointer", "(ZFIIZ)V", + (void*) nativeSetSelectionPointer }, + { "nativeSetSelectionRegion", "(Z)V", + (void*) nativeSetSelectionRegion }, { "nativeTextGeneration", "()I", (void*) nativeTextGeneration }, { "nativeUpdateCachedTextfield", "(Ljava/lang/String;I)V", |
