summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk4
-rw-r--r--WebCore/bindings/v8/V8Proxy.cpp6
-rw-r--r--WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp20
-rw-r--r--WebCore/platform/graphics/android/LayerAndroid.cpp81
-rw-r--r--WebCore/platform/graphics/android/LayerAndroid.h57
-rw-r--r--WebCore/platform/graphics/android/android_graphics.cpp99
-rw-r--r--WebCore/platform/graphics/android/android_graphics.h38
-rw-r--r--WebKit/android/RenderSkinCombo.cpp22
-rw-r--r--WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp4
-rw-r--r--WebKit/android/jni/WebCoreFrameBridge.cpp15
-rw-r--r--WebKit/android/jni/WebViewCore.cpp29
-rw-r--r--WebKit/android/jni/WebViewCore.h4
-rw-r--r--WebKit/android/nav/CachedFrame.cpp12
-rw-r--r--WebKit/android/nav/CachedFrame.h2
-rw-r--r--WebKit/android/nav/CachedLayer.cpp8
-rw-r--r--WebKit/android/nav/CachedLayer.h3
-rw-r--r--WebKit/android/nav/CachedNode.cpp25
-rw-r--r--WebKit/android/nav/CachedNode.h6
-rw-r--r--WebKit/android/nav/CachedRoot.h2
-rw-r--r--WebKit/android/nav/DrawExtra.h47
-rw-r--r--WebKit/android/nav/FindCanvas.cpp28
-rw-r--r--WebKit/android/nav/FindCanvas.h21
-rw-r--r--WebKit/android/nav/SelectText.cpp111
-rw-r--r--WebKit/android/nav/SelectText.h42
-rw-r--r--WebKit/android/nav/WebView.cpp506
25 files changed, 710 insertions, 482 deletions
diff --git a/Android.mk b/Android.mk
index f40613f..0d8d847 100644
--- a/Android.mk
+++ b/Android.mk
@@ -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",