summaryrefslogtreecommitdiffstats
path: root/Source/WebKit
diff options
context:
space:
mode:
authorJohn Reck <jreck@google.com>2012-02-01 09:47:34 -0800
committerJohn Reck <jreck@google.com>2012-02-01 15:06:40 -0800
commita21f4ae9448c287a3af2010accf179c8d54dcfe4 (patch)
tree7d649d83e8fb4d8da450121a9ee15eaf738cfadc /Source/WebKit
parent241f50e7db9a790bba271aebe4b276375c33a172 (diff)
downloadexternal_webkit-a21f4ae9448c287a3af2010accf179c8d54dcfe4.zip
external_webkit-a21f4ae9448c287a3af2010accf179c8d54dcfe4.tar.gz
external_webkit-a21f4ae9448c287a3af2010accf179c8d54dcfe4.tar.bz2
Fix text selection on iframes
Change-Id: Ie1943ef0ba2d353fac20ff67f78a1647921daec4
Diffstat (limited to 'Source/WebKit')
-rw-r--r--Source/WebKit/android/jni/WebViewCore.cpp97
-rw-r--r--Source/WebKit/android/jni/WebViewCore.h9
-rw-r--r--Source/WebKit/android/nav/DrawExtra.cpp5
-rw-r--r--Source/WebKit/android/nav/DrawExtra.h3
4 files changed, 69 insertions, 45 deletions
diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp
index fd1a833..40b59f1 100644
--- a/Source/WebKit/android/jni/WebViewCore.cpp
+++ b/Source/WebKit/android/jni/WebViewCore.cpp
@@ -1660,48 +1660,54 @@ static IntRect getAbsoluteBoundingBox(Node* node) {
return rect;
}
+WebCore::Frame* WebViewCore::focusedFrame() const
+{
+ return m_mainFrame->page()->focusController()->focusedOrMainFrame();
+}
+
VisiblePosition WebViewCore::visiblePositionForContentPoint(int x, int y)
{
- IntPoint point(x, y);
+ return visiblePositionForContentPoint(IntPoint(x, y));
+}
+VisiblePosition WebViewCore::visiblePositionForContentPoint(const IntPoint& point)
+{
// Hit test of this kind required for this to work inside input fields
- HitTestRequest request(HitTestRequest::Active | HitTestRequest::MouseMove | HitTestRequest::ReadOnly);
-
- // Look for the inner-most frame containing the hit. Its document
- // contains the document with the selected text.
- Frame* frame = m_mainFrame;
- Frame* hitFrame = m_mainFrame;
- Node* node = 0;
- IntPoint localPoint = point;
- do {
- HitTestResult result(localPoint);
- frame = hitFrame;
- frame->document()->renderView()->layer()->hitTest(request, result);
- node = result.innerNode();
- if (!node)
- return VisiblePosition();
-
- if (node->isFrameOwnerElement())
- hitFrame = static_cast<HTMLFrameOwnerElement*>(node)->contentFrame();
- localPoint = result.localPoint();
- } while (hitFrame && hitFrame != frame);
+ HitTestRequest request(HitTestRequest::Active
+ | HitTestRequest::MouseMove
+ | HitTestRequest::ReadOnly);
+ HitTestResult result(point);
+ focusedFrame()->document()->renderView()->layer()->hitTest(request, result);
+ // Matching the logic in MouseEventWithHitTestResults::targetNode()
+ Node* node = result.innerNode();
+ if (!node)
+ return VisiblePosition();
Element* element = node->parentElement();
if (!node->inDocument() && element && element->inDocument())
node = element;
- RenderObject* renderer = node->renderer();
- return renderer->positionForPoint(localPoint);
+ return node->renderer()->positionForPoint(result.localPoint());
}
void WebViewCore::selectWordAt(int x, int y)
{
- IntPoint point(x, y);
+ HitTestResult hoverResult;
+ moveMouse(m_mainFrame, x, y, &hoverResult);
+ if (hoverResult.innerNode()) {
+ Node* node = hoverResult.innerNode();
+ Frame* frame = node->document()->frame();
+ Page* page = m_mainFrame->document()->page();
+ page->focusController()->setFocusedFrame(frame);
+ }
+
+ IntPoint point = convertGlobalContentToFrameContent(IntPoint(x, y));
// Hit test of this kind required for this to work inside input fields
HitTestRequest request(HitTestRequest::Active);
HitTestResult result(point);
- m_mainFrame->document()->renderView()->layer()->hitTest(request, result);
+
+ focusedFrame()->document()->renderView()->layer()->hitTest(request, result);
// Matching the logic in MouseEventWithHitTestResults::targetNode()
Node* node = result.innerNode();
@@ -1711,7 +1717,7 @@ void WebViewCore::selectWordAt(int x, int y)
if (!node->inDocument() && element && element->inDocument())
node = element;
- SelectionController* sc = m_mainFrame->selection();
+ SelectionController* sc = focusedFrame()->selection();
if (!sc->contains(point) && (node->isContentEditable() || node->isTextNode()) && !result.isLiveLink()
&& node->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true))) {
VisiblePosition pos(node->renderer()->positionForPoint(result.localPoint()));
@@ -1801,6 +1807,7 @@ SelectText* WebViewCore::createSelectText(const VisibleSelection& selection)
return 0;
SelectText* selectTextContainer = new SelectText();
+ IntPoint frameOffset = convertGlobalContentToFrameContent(IntPoint());
Node* stopNode = range->pastLastNode();
for (Node* node = range->firstNode(); node != stopNode; node = node->traverseNextNode()) {
@@ -1814,30 +1821,41 @@ SelectText* WebViewCore::createSelectText(const VisibleSelection& selection)
platformLayerIdFromNode(node, &layer);
Vector<IntRect> rects;
renderText->absoluteRectsForRange(rects, startOffset, endOffset, true);
- selectTextContainer->addHighlightRegion(layer, rects);
+ selectTextContainer->addHighlightRegion(layer, rects, frameOffset);
}
IntRect caretRect;
int layerId;
selectTextContainer->setBaseFirst(selection.isBaseFirst());
- ALOGD("isBaseFirst: %s", selectTextContainer->isBaseFirst() ? "true" : "false");
setCaretInfo(selection.visibleStart(), SelectText::StartHandle, selectTextContainer);
setCaretInfo(selection.visibleEnd(), SelectText::EndHandle, selectTextContainer);
+ selectTextContainer->caretRect(SelectText::StartHandle)
+ .move(-frameOffset.x(), -frameOffset.y());
+ selectTextContainer->caretRect(SelectText::EndHandle)
+ .move(-frameOffset.x(), -frameOffset.y());
selectTextContainer->setText(range->text());
return selectTextContainer;
}
+IntPoint WebViewCore::convertGlobalContentToFrameContent(const IntPoint& point)
+{
+ IntPoint frameOffset(-m_scrollOffsetX, -m_scrollOffsetY);
+ frameOffset = focusedFrame()->view()->windowToContents(frameOffset);
+ return IntPoint(point.x() + frameOffset.x(), point.y() + frameOffset.y());
+}
+
void WebViewCore::selectText(int startX, int startY, int endX, int endY)
{
- SelectionController* sc = m_mainFrame->selection();
- VisiblePosition startPosition(visiblePositionForContentPoint(startX, startY));
- VisiblePosition endPosition(visiblePositionForContentPoint(endX, endY));
+ SelectionController* sc = focusedFrame()->selection();
+ IntPoint startPoint = convertGlobalContentToFrameContent(IntPoint(startX, startY));
+ VisiblePosition startPosition(visiblePositionForContentPoint(startPoint));
+ IntPoint endPoint = convertGlobalContentToFrameContent(IntPoint(endX, endY));
+ VisiblePosition endPosition(visiblePositionForContentPoint(endPoint));
- if (startPosition.isNull() || endPosition.isNull() || startPosition == endPosition) {
+ if (startPosition.isNull() || endPosition.isNull() || startPosition == endPosition)
return;
- }
// Ensure startPosition is before endPosition
if (comparePositions(startPosition, endPosition) > 0)
@@ -1865,9 +1883,8 @@ void WebViewCore::selectText(int startX, int startY, int endX, int endY)
}
VisibleSelection selection(startPosition, endPosition);
- if (selection.isRange() && sc->shouldChangeSelection(selection)) {
+ if (selection.isRange() && sc->shouldChangeSelection(selection))
sc->setSelection(selection);
- }
}
// get the highlight rectangles for the touch point (x, y) with the slop
@@ -2336,7 +2353,7 @@ void WebViewCore::moveFocus(WebCore::Frame* frame, WebCore::Node* node)
}
// Update mouse position
-void WebViewCore::moveMouse(WebCore::Frame* frame, int x, int y)
+void WebViewCore::moveMouse(WebCore::Frame* frame, int x, int y, HitTestResult* hoveredNode)
{
DBG_NAV_LOGD("frame=%p x=%d y=%d scrollOffset=(%d,%d)", frame,
x, y, m_scrollOffsetX, m_scrollOffsetY);
@@ -2349,7 +2366,7 @@ void WebViewCore::moveMouse(WebCore::Frame* frame, int x, int y)
WebCore::PlatformMouseEvent mouseEvent(m_mousePos, m_mousePos,
WebCore::NoButton, WebCore::MouseEventMoved, 1, false, false, false,
false, WTF::currentTime());
- frame->eventHandler()->handleMouseMoveEvent(mouseEvent);
+ frame->eventHandler()->handleMouseMoveEvent(mouseEvent, hoveredNode);
#if ENABLE(ANDROID_NAVCACHE)
updateCacheOnNodeChange();
#endif
@@ -3909,7 +3926,7 @@ void WebViewCore::updateTextSelection()
int end = 0;
if (focusNode)
getSelectionOffsets(focusNode, start, end);
- SelectText* selectText = createSelectText(m_mainFrame->selection()->selection());
+ SelectText* selectText = createSelectText(focusedFrame()->selection()->selection());
env->CallVoidMethod(javaObject.get(),
m_javaGlue->m_updateTextSelection, reinterpret_cast<int>(focusNode),
start, end, m_textGeneration, selectText);
@@ -5002,7 +5019,7 @@ static void SelectText(JNIEnv* env, jobject obj, jint nativeClass,
static void ClearSelection(JNIEnv* env, jobject obj, jint nativeClass)
{
WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
- viewImpl->mainFrame()->selection()->clear();
+ viewImpl->focusedFrame()->selection()->clear();
}
static void SelectWordAt(JNIEnv* env, jobject obj, jint nativeClass, jint x, jint y)
@@ -5014,7 +5031,7 @@ static void SelectWordAt(JNIEnv* env, jobject obj, jint nativeClass, jint x, jin
static void SelectAll(JNIEnv* env, jobject obj, jint nativeClass)
{
WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
- viewImpl->mainFrame()->selection()->selectAll();
+ viewImpl->focusedFrame()->selection()->selectAll();
}
// ----------------------------------------------------------------------------
diff --git a/Source/WebKit/android/jni/WebViewCore.h b/Source/WebKit/android/jni/WebViewCore.h
index cb345dd..9fc55d1 100644
--- a/Source/WebKit/android/jni/WebViewCore.h
+++ b/Source/WebKit/android/jni/WebViewCore.h
@@ -305,7 +305,7 @@ namespace android {
void recordPicture(SkPicture* picture);
void moveFocus(WebCore::Frame* frame, WebCore::Node* node);
- void moveMouse(WebCore::Frame* frame, int x, int y);
+ void moveMouse(WebCore::Frame* frame, int x, int y, HitTestResult* hoveredNode = 0);
void moveMouseIfLatest(int moveGeneration,
WebCore::Frame* frame, int x, int y);
@@ -547,6 +547,7 @@ namespace android {
float scale() const { return m_scale; }
float textWrapScale() const { return m_screenWidth * m_scale / m_textWrapWidth; }
WebCore::Frame* mainFrame() const { return m_mainFrame; }
+ WebCore::Frame* focusedFrame() const;
void updateCursorBounds(const CachedRoot* root,
const CachedFrame* cachedFrame, const CachedNode* cachedNode);
@@ -607,6 +608,9 @@ namespace android {
void selectText(int startX, int startY, int endX, int endY);
void selectWordAt(int x, int y);
+ // Converts from the global content coordinates that WebView sends
+ // to frame-local content coordinates using the focused frame
+ IntPoint convertGlobalContentToFrameContent(const IntPoint& point);
static void layerToAbsoluteOffset(const LayerAndroid* layer, IntPoint& offset);
/**
@@ -708,8 +712,9 @@ namespace android {
static WebCore::Position getPositionForOffset(Node* node, int offset);
VisiblePosition visiblePositionForContentPoint(int x, int y);
+ VisiblePosition visiblePositionForContentPoint(const IntPoint& point);
void selectWordAroundPosition(Frame* frame, VisiblePosition pos);
- static SelectText* createSelectText(const VisibleSelection&);
+ SelectText* createSelectText(const VisibleSelection&);
// called from constructor, to add this to a global list
static void addInstance(WebViewCore*);
diff --git a/Source/WebKit/android/nav/DrawExtra.cpp b/Source/WebKit/android/nav/DrawExtra.cpp
index 564cc21..2f57dc1 100644
--- a/Source/WebKit/android/nav/DrawExtra.cpp
+++ b/Source/WebKit/android/nav/DrawExtra.cpp
@@ -51,7 +51,8 @@ SkRegion* RegionLayerDrawExtra::getHighlightRegionsForLayer(const LayerAndroid*
return m_highlightRegions.get(layerId);
}
-void RegionLayerDrawExtra::addHighlightRegion(const LayerAndroid* layer, const Vector<IntRect>& rects)
+void RegionLayerDrawExtra::addHighlightRegion(const LayerAndroid* layer, const Vector<IntRect>& rects,
+ const IntPoint& additionalOffset)
{
if (rects.isEmpty())
return;
@@ -61,7 +62,7 @@ void RegionLayerDrawExtra::addHighlightRegion(const LayerAndroid* layer, const V
region = new SkRegion();
m_highlightRegions.set(layerId, region);
}
- IntPoint offset;
+ IntPoint offset = additionalOffset;
WebViewCore::layerToAbsoluteOffset(layer, offset);
for (size_t i = 0; i < rects.size(); i++) {
IntRect r = rects.at(i);
diff --git a/Source/WebKit/android/nav/DrawExtra.h b/Source/WebKit/android/nav/DrawExtra.h
index 0cee861..83e7dcd 100644
--- a/Source/WebKit/android/nav/DrawExtra.h
+++ b/Source/WebKit/android/nav/DrawExtra.h
@@ -65,7 +65,8 @@ public:
RegionLayerDrawExtra();
virtual ~RegionLayerDrawExtra();
- void addHighlightRegion(const LayerAndroid* layer, const Vector<IntRect>& rects);
+ void addHighlightRegion(const LayerAndroid* layer, const Vector<IntRect>& rects,
+ const IntPoint& additionalOffset = IntPoint());
virtual void draw(SkCanvas*, LayerAndroid*);
virtual void drawGL(GLExtras*, const LayerAndroid*);