diff options
-rw-r--r-- | WebCore/config.h | 2 | ||||
-rw-r--r-- | WebCore/rendering/InlineTextBox.cpp | 53 | ||||
-rw-r--r-- | WebCore/rendering/InlineTextBox.h | 10 | ||||
-rw-r--r-- | WebCore/rendering/RenderText.cpp | 17 | ||||
-rw-r--r-- | WebKit/android/jni/WebHistory.cpp | 4 | ||||
-rw-r--r-- | WebKit/android/jni/WebViewCore.cpp | 53 | ||||
-rw-r--r-- | WebKit/android/jni/WebViewCore.h | 8 | ||||
-rw-r--r-- | WebKit/android/nav/SelectText.cpp | 10 | ||||
-rw-r--r-- | WebKit/android/nav/WebView.cpp | 5 |
9 files changed, 133 insertions, 29 deletions
diff --git a/WebCore/config.h b/WebCore/config.h index b2af90a..7174c4b 100644 --- a/WebCore/config.h +++ b/WebCore/config.h @@ -148,6 +148,8 @@ #define ANDROID_FIX +#define ANDROID_DISABLE_ROUNDING_HACKS + // Ensure that the fixed elements are always relative to the top document. #define ANDROID_FIXED_ELEMENTS diff --git a/WebCore/rendering/InlineTextBox.cpp b/WebCore/rendering/InlineTextBox.cpp index 575bdf2..2bec8a1 100644 --- a/WebCore/rendering/InlineTextBox.cpp +++ b/WebCore/rendering/InlineTextBox.cpp @@ -158,8 +158,15 @@ IntRect InlineTextBox::selectionRect(int tx, int ty, int startPos, int endPos) ePos = len; } +#ifdef ANDROID_DISABLE_ROUNDING_HACKS + TextRun textRun = TextRun(characters, len, textObj->allowTabs(), textPos(), m_toAdd, !isLeftToRightDirection(), m_dirOverride); + if (m_disableRoundingHacks) + textRun.disableRoundingHacks(); + IntRect r = enclosingIntRect(f.selectionRectForText(textRun, IntPoint(), selHeight, sPos, ePos)); +#else IntRect r = enclosingIntRect(f.selectionRectForText(TextRun(characters, len, textObj->allowTabs(), textPos(), m_toAdd, !isLeftToRightDirection(), m_dirOverride), IntPoint(), selHeight, sPos, ePos)); +#endif int logicalWidth = r.width(); if (r.x() > m_logicalWidth) @@ -555,6 +562,10 @@ void InlineTextBox::paint(PaintInfo& paintInfo, int tx, int ty) adjustCharactersAndLengthForHyphen(charactersWithHyphen, styleToUse, characters, length); TextRun textRun(characters, length, textRenderer()->allowTabs(), textPos(), m_toAdd, !isLeftToRightDirection(), m_dirOverride || styleToUse->visuallyOrdered()); +#ifdef ANDROID_DISABLE_ROUNDING_HACKS + if (m_disableRoundingHacks) + textRun.disableRoundingHacks(); +#endif int sPos = 0; int ePos = 0; @@ -689,9 +700,17 @@ void InlineTextBox::paintSelection(GraphicsContext* context, const IntPoint& box int selHeight = selectionHeight(); IntPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY); context->clip(IntRect(localOrigin, IntSize(m_logicalWidth, selHeight))); +#ifdef ANDROID_DISABLE_ROUNDING_HACKS + TextRun textRun = TextRun(characters, length, textRenderer()->allowTabs(), textPos(), m_toAdd, + !isLeftToRightDirection(), m_dirOverride || style->visuallyOrdered()); + if (m_disableRoundingHacks) + textRun.disableRoundingHacks(); + context->drawHighlightForText(font, textRun, localOrigin, selHeight, c, style->colorSpace(), sPos, ePos); +#else context->drawHighlightForText(font, TextRun(characters, length, textRenderer()->allowTabs(), textPos(), m_toAdd, !isLeftToRightDirection(), m_dirOverride || style->visuallyOrdered()), localOrigin, selHeight, c, style->colorSpace(), sPos, ePos); +#endif context->restore(); } @@ -713,9 +732,17 @@ void InlineTextBox::paintCompositionBackground(GraphicsContext* context, const I int deltaY = renderer()->style()->isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop(); int selHeight = selectionHeight(); IntPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY); +#ifdef ANDROID_DISABLE_ROUNDING_HACKS + TextRun textRun = TextRun(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, + !isLeftToRightDirection(), m_dirOverride || style->visuallyOrdered()); + if (m_disableRoundingHacks) + textRun.disableRoundingHacks(); + context->drawHighlightForText(font, textRun, localOrigin, selHeight, c, style->colorSpace(), sPos, ePos); +#else context->drawHighlightForText(font, TextRun(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, !isLeftToRightDirection(), m_dirOverride || style->visuallyOrdered()), localOrigin, selHeight, c, style->colorSpace(), sPos, ePos); +#endif context->restore(); } @@ -876,6 +903,10 @@ void InlineTextBox::paintSpellingOrGrammarMarker(GraphicsContext* pt, const IntP int selHeight = selectionHeight(); IntPoint startPoint(boxOrigin.x(), boxOrigin.y() - deltaY); TextRun run(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, !isLeftToRightDirection(), m_dirOverride || style->visuallyOrdered()); +#ifdef ANDROID_DISABLE_ROUNDING_HACKS + if (m_disableRoundingHacks) + run.disableRoundingHacks(); +#endif IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, startPoint, selHeight, startPosition, endPosition)); start = markerRect.x() - startPoint.x(); @@ -920,6 +951,10 @@ void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, const IntPoint& bo int sPos = max(marker.startOffset - m_start, (unsigned)0); int ePos = min(marker.endOffset - m_start, (unsigned)m_len); TextRun run(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, !isLeftToRightDirection(), m_dirOverride || style->visuallyOrdered()); +#ifdef ANDROID_DISABLE_ROUNDING_HACKS + if (m_disableRoundingHacks) + run.disableRoundingHacks(); +#endif // Always compute and store the rect associated with this marker. The computed rect is in absolute coordinates. IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, IntPoint(m_x, selectionTop()), selHeight, sPos, ePos)); @@ -948,6 +983,10 @@ void InlineTextBox::computeRectForReplacementMarker(const DocumentMarker& marker int sPos = max(marker.startOffset - m_start, (unsigned)0); int ePos = min(marker.endOffset - m_start, (unsigned)m_len); TextRun run(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, !isLeftToRightDirection(), m_dirOverride || style->visuallyOrdered()); +#ifdef ANDROID_DISABLE_ROUNDING_HACKS + if (m_disableRoundingHacks) + run.disableRoundingHacks(); +#endif IntPoint startPoint = IntPoint(m_x, y); // Compute and store the rect associated with this marker. @@ -1099,8 +1138,15 @@ int InlineTextBox::offsetForPosition(int lineOffset, bool includePartialGlyphs) RenderText* text = toRenderText(renderer()); RenderStyle* style = text->style(m_firstLine); const Font* f = &style->font(); +#ifdef ANDROID_DISABLE_ROUNDING_HACKS + TextRun textRun = TextRun(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, !isLeftToRightDirection(), m_dirOverride || style->visuallyOrdered()); + if (m_disableRoundingHacks) + textRun.disableRoundingHacks(); + return f->offsetForPosition(textRun, lineOffset - logicalLeft(), includePartialGlyphs); +#else return f->offsetForPosition(TextRun(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, !isLeftToRightDirection(), m_dirOverride || style->visuallyOrdered()), lineOffset - logicalLeft(), includePartialGlyphs); +#endif } int InlineTextBox::positionForOffset(int offset) const @@ -1116,8 +1162,15 @@ int InlineTextBox::positionForOffset(int offset) const int from = !isLeftToRightDirection() ? offset - m_start : 0; int to = !isLeftToRightDirection() ? m_len : offset - m_start; // FIXME: Do we need to add rightBearing here? +#ifdef ANDROID_DISABLE_ROUNDING_HACKS + TextRun textRun = TextRun(text->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, !isLeftToRightDirection(), m_dirOverride); + if (m_disableRoundingHacks) + textRun.disableRoundingHacks(); + return enclosingIntRect(f.selectionRectForText(textRun, IntPoint(logicalLeft(), 0), 0, from, to)).right(); +#else return enclosingIntRect(f.selectionRectForText(TextRun(text->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, !isLeftToRightDirection(), m_dirOverride), IntPoint(logicalLeft(), 0), 0, from, to)).right(); +#endif } bool InlineTextBox::containsCaretOffset(int offset) const diff --git a/WebCore/rendering/InlineTextBox.h b/WebCore/rendering/InlineTextBox.h index bc2219b..e19da2e 100644 --- a/WebCore/rendering/InlineTextBox.h +++ b/WebCore/rendering/InlineTextBox.h @@ -39,13 +39,20 @@ Color correctedTextColor(Color textColor, Color backgroundColor); class InlineTextBox : public InlineBox { public: +#ifdef ANDROID_DISABLE_ROUNDING_HACKS + InlineTextBox(RenderObject* obj, bool disableRoundingHacks = false) +#else InlineTextBox(RenderObject* obj) +#endif : InlineBox(obj) , m_prevTextBox(0) , m_nextTextBox(0) , m_start(0) , m_len(0) , m_truncation(cNoTruncation) +#ifdef ANDROID_DISABLE_ROUNDING_HACKS + , m_disableRoundingHacks(disableRoundingHacks) +#endif { } @@ -139,6 +146,9 @@ private: unsigned short m_truncation; // Where to truncate when text overflow is applied. We use special constants to // denote no truncation (the whole run paints) and full truncation (nothing paints at all). +#ifdef ANDROID_DISABLE_ROUNDING_HACKS + bool m_disableRoundingHacks; +#endif protected: void paintCompositionBackground(GraphicsContext*, const IntPoint& boxOrigin, RenderStyle*, const Font&, int startPos, int endPos); diff --git a/WebCore/rendering/RenderText.cpp b/WebCore/rendering/RenderText.cpp index 7635d07..b1e9413 100644 --- a/WebCore/rendering/RenderText.cpp +++ b/WebCore/rendering/RenderText.cpp @@ -1158,10 +1158,27 @@ void RenderText::dirtyLineBoxes(bool fullLayout) } m_linesDirty = false; } +#ifdef ANDROID_DISABLE_ROUNDING_HACKS +static bool disableRoundingHacks(RenderText* renderText) +{ + RenderObject* renderer = renderText; + while (renderer) { + if (renderer->isTextControl()) { + return true; + } + renderer = renderer->parent(); + } + return false; +} +#endif InlineTextBox* RenderText::createTextBox() { +#ifdef ANDROID_DISABLE_ROUNDING_HACKS + return new (renderArena()) InlineTextBox(this, disableRoundingHacks(this)); +#else return new (renderArena()) InlineTextBox(this); +#endif } InlineTextBox* RenderText::createInlineTextBox() diff --git a/WebKit/android/jni/WebHistory.cpp b/WebKit/android/jni/WebHistory.cpp index 7f3e4e3..52d9f61 100644 --- a/WebKit/android/jni/WebHistory.cpp +++ b/WebKit/android/jni/WebHistory.cpp @@ -168,8 +168,8 @@ static void WebHistoryInflate(JNIEnv* env, jobject obj, jint frame, jbyteArray d // Inflate the history tree into one HistoryItem or null if the inflation // failed. RefPtr<WebCore::HistoryItem> newItem = WebCore::HistoryItem::create(); - RefPtr<WebHistoryItem> bridge = adoptRef(new WebHistoryItem(env, obj, newItem.get())); - newItem->setBridge(bridge.get()); + WebHistoryItem* bridge = new WebHistoryItem(env, obj, newItem.get()); + newItem->setBridge(bridge); // Inflate the item recursively. If it fails, that is ok. We'll have an // incomplete HistoryItem but that is better than crashing due to a null diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp index 110ce94..3de3810 100644 --- a/WebKit/android/jni/WebViewCore.cpp +++ b/WebKit/android/jni/WebViewCore.cpp @@ -2579,9 +2579,25 @@ public: // Response used for a multiple selection listbox if the user did not change // anything, in which case -2 is used. + // Also used by a listbox which has single selection but a size is set. virtual void replyInt(int index) { - LOG_ASSERT(-2 == index, "ListBoxReply::replyInt should only be called with -2"); + if (-2 == index) { + // Special value for cancel. Do nothing. + return; + } + // If the select element no longer exists, due to a page change, etc, + // silently return. + if (!m_select || !CacheBuilder::validNode(m_viewImpl->m_mainFrame, + m_frame, m_select)) + return; + // Use a pointer to HTMLSelectElement's superclass, where + // listToOptionIndex is public + SelectElement* selectElement = m_select; + int optionIndex = selectElement->listToOptionIndex(index); + m_select->setSelectedIndex(optionIndex, true); + m_select->dispatchFormControlChangeEvent(); + m_viewImpl->contentInvalidate(m_select->getRect()); } // Response if the listbox allows multiple selection. array stores the listIndices @@ -2750,8 +2766,9 @@ bool WebViewCore::key(const PlatformKeyboardEvent& event) return eventHandler->keyEvent(event); } -// For when the user clicks the trackball -void WebViewCore::click(WebCore::Frame* frame, WebCore::Node* node) { +// For when the user clicks the trackball, presses dpad center, or types into an +// unfocused textfield. In the latter case, 'fake' will be true +void WebViewCore::click(WebCore::Frame* frame, WebCore::Node* node, bool fake) { if (!node) { WebCore::IntPoint pt = m_mousePos; pt.move(m_scrollOffsetX, m_scrollOffsetY); @@ -2768,7 +2785,7 @@ void WebViewCore::click(WebCore::Frame* frame, WebCore::Node* node) { = static_cast<EditorClientAndroid*>( m_mainFrame->editor()->client()); client->setShouldChangeSelectedRange(false); - handleMouseClick(frame, node); + handleMouseClick(frame, node, fake); client->setShouldChangeSelectedRange(true); } } @@ -2874,7 +2891,7 @@ void WebViewCore::touchUp(int touchGeneration, } DBG_NAV_LOGD("touchGeneration=%d handleMouseClick frame=%p node=%p" " x=%d y=%d", touchGeneration, frame, node, x, y); - handleMouseClick(frame, node); + handleMouseClick(frame, node, false); } // Return the RenderLayer for the given RenderObject only if the layer is @@ -2923,7 +2940,9 @@ static void scrollLayer(WebCore::RenderObject* renderer, WebCore::IntPoint* pos) } // Common code for both clicking with the trackball and touchUp -bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* nodePtr) +// Also used when typing into a non-focused textfield to give the textfield focus, +// in which case, 'fake' is set to true +bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* nodePtr, bool fake) { m_lastClickWasOnTextInput = false; bool valid = framePtr == NULL @@ -3023,14 +3042,16 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node autoFill->formFieldFocused(static_cast<HTMLFormControlElement*>(focusNode)); } #endif - RenderTextControl* rtc - = static_cast<RenderTextControl*> (renderer); - requestKeyboardWithSelection(focusNode, rtc->selectionStart(), - rtc->selectionEnd()); - } else { + if (!fake) { + RenderTextControl* rtc + = static_cast<RenderTextControl*> (renderer); + requestKeyboardWithSelection(focusNode, rtc->selectionStart(), + rtc->selectionEnd()); + } + } else if (!fake) { requestKeyboard(false); } - } else { + } else if (!fake){ // If the selection is contentEditable, show the keyboard so the // user can type. Otherwise hide the keyboard because no text // input is needed. @@ -3040,7 +3061,7 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node clearTextEntry(); } } - } else { + } else if (!fake) { // There is no focusNode, so the keyboard is not needed. clearTextEntry(); } @@ -3537,7 +3558,7 @@ static jboolean Key(JNIEnv *env, jobject obj, jint keyCode, jint unichar, unichar, repeatCount, isDown, isShift, isAlt, isSym)); } -static void Click(JNIEnv *env, jobject obj, int framePtr, int nodePtr) +static void Click(JNIEnv *env, jobject obj, int framePtr, int nodePtr, jboolean fake) { #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); @@ -3546,7 +3567,7 @@ static void Click(JNIEnv *env, jobject obj, int framePtr, int nodePtr) LOG_ASSERT(viewImpl, "viewImpl not set in Click"); viewImpl->click(reinterpret_cast<WebCore::Frame*>(framePtr), - reinterpret_cast<WebCore::Node*>(nodePtr)); + reinterpret_cast<WebCore::Node*>(nodePtr), fake); } static void ContentInvalidateAll(JNIEnv *env, jobject obj) @@ -4160,7 +4181,7 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { (void*) FocusBoundsChanged } , { "nativeKey", "(IIIZZZZ)Z", (void*) Key }, - { "nativeClick", "(II)V", + { "nativeClick", "(IIZ)V", (void*) Click }, { "nativeContentInvalidateAll", "()V", (void*) ContentInvalidateAll }, diff --git a/WebKit/android/jni/WebViewCore.h b/WebKit/android/jni/WebViewCore.h index ae5a65f..dc93de9 100644 --- a/WebKit/android/jni/WebViewCore.h +++ b/WebKit/android/jni/WebViewCore.h @@ -325,9 +325,11 @@ namespace android { bool key(const WebCore::PlatformKeyboardEvent& event); /** - * Handle (trackball) click event from Java + * Handle (trackball) click event / dpad center press from Java. + * Also used when typing into an unfocused textfield, in which case 'fake' + * will be true. */ - void click(WebCore::Frame* frame, WebCore::Node* node); + void click(WebCore::Frame* frame, WebCore::Node* node, bool fake); /** * Handle touch event @@ -630,7 +632,7 @@ namespace android { SkPicture* rebuildPicture(const SkIRect& inval); void rebuildPictureSet(PictureSet* ); void sendNotifyProgressFinished(); - bool handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* nodePtr); + bool handleMouseClick(WebCore::Frame*, WebCore::Node*, bool); WebCore::HTMLAnchorElement* retrieveAnchorElement(int x, int y); WebCore::HTMLElement* retrieveElement(int x, int y, const WebCore::QualifiedName& ); diff --git a/WebKit/android/nav/SelectText.cpp b/WebKit/android/nav/SelectText.cpp index f2d7521..ff69ddd 100644 --- a/WebKit/android/nav/SelectText.cpp +++ b/WebKit/android/nav/SelectText.cpp @@ -608,11 +608,11 @@ public: } // cx and cy are the distances from the tested center // The center distance is used when the test point is over the text - int cx = INT_MAX; - int cy = INT_MAX; - if (ignoreColumn && dy == 0 && mDy == 0) { - cy = std::abs(((testBounds.fTop + testBounds.fBottom) >> 1) + int cx = std::abs(((testBounds.fLeft + testBounds.fRight) >> 1) + - mFocusX); + int cy = std::abs(((testBounds.fTop + testBounds.fBottom) >> 1) - mFocusY); + if (ignoreColumn && dy == 0 && mDy == 0) { if (mCy < cy) { #ifdef EXTRA_NOISY_LOGGING DBG_NAV_LOGD("FirstCheck reject cy=%d mCy=%d", cy, mCy); @@ -621,8 +621,6 @@ public: } if (mCy == cy) { if (dx == 0 && mDx == 0) { - cx = std::abs(((testBounds.fLeft + testBounds.fRight) >> 1) - - mFocusX); if (mCx < cx) { #ifdef EXTRA_NOISY_LOGGING DBG_NAV_LOGD("FirstCheck reject cx=%d mCx=%d", cx, mCx); diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp index 8252bb8..76feacd 100644 --- a/WebKit/android/nav/WebView.cpp +++ b/WebKit/android/nav/WebView.cpp @@ -840,8 +840,9 @@ bool moveCursor(int keyCode, int count, bool ignoreScroll) m_viewImpl->updateCursorBounds(root, cachedFrame, cachedNode); root->setCursor(const_cast<CachedFrame*>(cachedFrame), const_cast<CachedNode*>(cachedNode)); - bool clearTextEntry = cachedNode != root->currentFocus() - && cachedNode->wantsKeyEvents(); + const CachedNode* focus = root->currentFocus(); + bool clearTextEntry = cachedNode != focus && focus + && cachedNode->nodePointer() != focus->nodePointer() && focus->isTextInput(); sendMoveMouseIfLatest(clearTextEntry); sendMoveSelection((WebCore::Frame*) cachedFrame->framePointer(), (WebCore::Node*) cachedNode->nodePointer()); |