diff options
Diffstat (limited to 'WebKit')
| -rw-r--r-- | WebKit/android/RenderSkinCombo.cpp | 22 | ||||
| -rw-r--r-- | WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp | 4 | ||||
| -rw-r--r-- | WebKit/android/jni/WebCoreFrameBridge.cpp | 15 | ||||
| -rw-r--r-- | WebKit/android/jni/WebViewCore.cpp | 29 | ||||
| -rw-r--r-- | WebKit/android/jni/WebViewCore.h | 4 | ||||
| -rw-r--r-- | WebKit/android/nav/CachedFrame.cpp | 12 | ||||
| -rw-r--r-- | WebKit/android/nav/CachedFrame.h | 2 | ||||
| -rw-r--r-- | WebKit/android/nav/CachedLayer.cpp | 8 | ||||
| -rw-r--r-- | WebKit/android/nav/CachedLayer.h | 3 | ||||
| -rw-r--r-- | WebKit/android/nav/CachedNode.cpp | 25 | ||||
| -rw-r--r-- | WebKit/android/nav/CachedNode.h | 6 | ||||
| -rw-r--r-- | WebKit/android/nav/CachedRoot.h | 2 | ||||
| -rw-r--r-- | WebKit/android/nav/DrawExtra.h | 47 | ||||
| -rw-r--r-- | WebKit/android/nav/FindCanvas.cpp | 28 | ||||
| -rw-r--r-- | WebKit/android/nav/FindCanvas.h | 21 | ||||
| -rw-r--r-- | WebKit/android/nav/SelectText.cpp | 111 | ||||
| -rw-r--r-- | WebKit/android/nav/SelectText.h | 42 | ||||
| -rw-r--r-- | WebKit/android/nav/WebView.cpp | 506 |
18 files changed, 495 insertions, 392 deletions
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", |
