Reviewed by darin
<rdar://problem/
5136696> Selection is removed when focusing a node in another frame
Demonstrates bug:
* editing/selection/
5136696-expected.checksum: Added.
* editing/selection/
5136696-expected.png: Added.
* editing/selection/
5136696-expected.txt: Added.
* editing/selection/
5136696.html: Added.
WebCore:
Reviewed by darin
<rdar://problem/
5136696> Selection is removed when focusing a node in another frame
<rdar://problem/
5192388> WordPress: Can't insert links/images
Don't clear a selection when changing focus if the new
focus node is in a different frame than the old selection.
* dom/Document.cpp:
(WebCore::Document::setFocusedNode): Moved code to clear
selections to the FocusController, since it is Page level
and will know about the frame/document that contained the
old selection. Moved code to call shouldEndEditing to the
FocusController because selections are now cleared before
calling Document::setFocusedNode and shouldEndEditing must
be called before selections are cleared.
* dom/Element.cpp:
(WebCore::Element::blur): Call FocusController::setFocusNode
instead of Document::setFocusNode, if possible.
* page/EventHandler.cpp:
(WebCore::EventHandler::dispatchMouseEvent): Ditto.
* page/FocusController.cpp:
(WebCore::relinquishesEditingFocus): Moved from Document.cpp.
(WebCore::clearSelectionIfNeeded): Ditto. Don't clear if
the old selection is in a frame that's different than the
one that contains the new focus node.
(WebCore::FocusController::setFocusedNode): Moved code
here from Document::setFocusedNode.
* page/Frame.cpp:
(WebCore::Frame::setFocusedNodeIfNeeded): Call
FocusController::setFocusNode.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@21467
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2007-05-14 Justin Garcia <justin.garcia@apple.com>
+
+ Reviewed by darin
+
+ <rdar://problem/5136696> Selection is removed when focusing a node in another frame
+
+ Demonstrates bug:
+ * editing/selection/5136696-expected.checksum: Added.
+ * editing/selection/5136696-expected.png: Added.
+ * editing/selection/5136696-expected.txt: Added.
+ * editing/selection/5136696.html: Added.
+
2007-05-14 Kimmo Kinnunen <kimmok@iki.fi>
Tests for http://bugs.webkit.org/show_bug.cgi?id=10878
--- /dev/null
+2ee0d0aa57cf21885a4971be6ec16706
\ No newline at end of file
--- /dev/null
+layer at (0,0) size 800x600
+ RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderBlock {HTML} at (0,0) size 800x600
+ RenderBody {BODY} at (8,8) size 784x584
+ RenderBlock {P} at (0,0) size 784x18
+ RenderText {#text} at (0,0) size 666x18
+ text run at (0,0) width 666: "This tests to make sure that a selection in one from isn't cleared when focusing a node in a different frame."
+ RenderBlock (anonymous) at (0,34) size 784x177
+ RenderPartObject {IFRAME} at (0,0) size 304x154 [border: (2px inset #000000)]
+ layer at (0,0) size 300x150
+ RenderView at (0,0) size 300x150
+ layer at (0,0) size 300x150
+ RenderBlock {HTML} at (0,0) size 300x150
+ RenderBody {BODY} at (8,8) size 284x134 [bgcolor=#FFFFE0]
+ RenderText {#text} at (0,0) size 270x36
+ text run at (0,0) width 270: "This test should be selected, but this frame "
+ text run at (0,18) width 133: "shouldn't be focused."
+ RenderBR {BR} at (304,154) size 0x0
+ RenderTextControl {INPUT} at (2,156) size 217x19 [bgcolor=#FFFFFF] [border: (2px inset #000000)]
+ RenderText {#text} at (0,0) size 0x0
+ RenderText {#text} at (0,0) size 0x0
+layer at (13,201) size 211x13
+ RenderBlock {DIV} at (3,3) size 211x13
+ RenderText {#text} at (1,0) size 181x13
+ text run at (1,0) width 181: "This text field should be focused."
+selection start: position 0 of child 0 {#text} of child 0 {DIV} of child 5 {INPUT} of child 0 {BODY} of child 0 {HTML} of document
+selection end: position 34 of child 0 {#text} of child 0 {DIV} of child 5 {INPUT} of child 0 {BODY} of child 0 {HTML} of document
--- /dev/null
+<p>This tests to make sure that a selection in one from isn't cleared when focusing a node in a different frame.</p>
+<iframe border="1" src="../resources/contenteditable-iframe-src.html"></iframe><br>
+<input type="text" id="input" value="This text field should be focused." size="30">
+
+<script>
+function runTest() {
+ frame = frames[0];
+ frame.focus();
+ s = frame.getSelection();
+ s.setPosition(frame.document.body, 0);
+ frame.document.execCommand("InsertText", false, "This test should be selected, but this frame shouldn't be focused.");
+ frame.document.execCommand("SelectAll");
+ document.getElementById("input").focus();
+ if (window.layoutTestController)
+ window.layoutTestController.notifyDone();
+}
+if (window.layoutTestController)
+ window.layoutTestController.waitUntilDone();
+window.setTimeout(runTest, 200);
+</script>
+2007-05-14 Justin Garcia <justin.garcia@apple.com>
+
+ Reviewed by darin
+
+ <rdar://problem/5136696> Selection is removed when focusing a node in another frame
+ <rdar://problem/5192388> WordPress: Can't insert links/images
+
+ Don't clear a selection when changing focus if the new
+ focus node is in a different frame than the old selection.
+
+ * dom/Document.cpp:
+ (WebCore::Document::setFocusedNode): Moved code to clear
+ selections to the FocusController, since it is Page level
+ and will know about the frame/document that contained the
+ old selection. Moved code to call shouldEndEditing to the
+ FocusController because selections are now cleared before
+ calling Document::setFocusedNode and shouldEndEditing must
+ be called before selections are cleared.
+ * dom/Element.cpp:
+ (WebCore::Element::blur): Call FocusController::setFocusNode
+ instead of Document::setFocusNode, if possible.
+ * page/EventHandler.cpp:
+ (WebCore::EventHandler::dispatchMouseEvent): Ditto.
+ * page/FocusController.cpp:
+ (WebCore::relinquishesEditingFocus): Moved from Document.cpp.
+ (WebCore::clearSelectionIfNeeded): Ditto. Don't clear if
+ the old selection is in a frame that's different than the
+ one that contains the new focus node.
+ (WebCore::FocusController::setFocusedNode): Moved code
+ here from Document::setFocusedNode.
+ * page/Frame.cpp:
+ (WebCore::Frame::setFocusedNodeIfNeeded): Call
+ FocusController::setFocusNode.
+
2007-05-14 Geoffrey Garen <ggaren@apple.com>
Reviewed by Darin Adler.
return static_cast<RenderWidget*>(renderer)->widget();
}
-static bool relinquishesEditingFocus(Node *node)
-{
- ASSERT(node);
- ASSERT(node->isContentEditable());
-
- Node *root = node->rootEditableElement();
- Frame* frame = node->document()->frame();
- if (!frame || !root)
- return false;
-
- return frame->editor()->shouldEndEditing(rangeOfContents(root).get());
-}
-
static bool acceptsEditingFocus(Node *node)
{
ASSERT(node);
return frame->editor()->shouldBeginEditing(rangeOfContents(root).get());
}
-static void clearSelectionIfNeeded(Frame* frame, Node* newFocusedNode)
-{
- if (!frame)
- return;
-
- // Clear the selection when changing the focus node to null or to a node that is not
- // contained by the current selection.
- Node* startContainer = frame->selectionController()->start().node();
- if (!newFocusedNode || (startContainer && startContainer != newFocusedNode && !(startContainer->isDescendantOf(newFocusedNode)) && startContainer->shadowAncestorNode() != newFocusedNode))
- frame->selectionController()->clear();
-}
-
DeprecatedPtrList<Document>* Document::changedDocuments = 0;
// FrameView might be 0
if (m_focusedNode == newFocusedNode)
return true;
-
- if (m_focusedNode && m_focusedNode.get() == m_focusedNode->rootEditableElement() && !relinquishesEditingFocus(m_focusedNode.get()))
- return false;
bool focusChangeBlocked = false;
RefPtr<Node> oldFocusedNode = m_focusedNode;
m_focusedNode = 0;
- clearSelectionIfNeeded(frame(), newFocusedNode.get());
// Remove focus from the existing focus node (if any)
if (oldFocusedNode && !oldFocusedNode->m_inDetach) {
focusChangeBlocked = true;
newFocusedNode = 0;
}
- clearSelectionIfNeeded(frame(), newFocusedNode.get());
EventTargetNodeCast(oldFocusedNode.get())->dispatchUIEvent(DOMFocusOutEvent);
if (m_focusedNode) {
// handler shifted focus
focusChangeBlocked = true;
newFocusedNode = 0;
}
- clearSelectionIfNeeded(frame(), newFocusedNode.get());
if ((oldFocusedNode.get() == this) && oldFocusedNode->hasOneRef())
return true;
{
stopUpdateFocusAppearanceTimer();
Document* doc = document();
- if (doc->focusedNode() == this)
- doc->setFocusedNode(0);
+ if (doc->focusedNode() == this) {
+ if (doc->frame())
+ doc->frame()->page()->focusController()->setFocusedNode(0);
+ else
+ doc->setFocusedNode(0);
+ }
}
void Element::stopUpdateFocusAppearanceTimer()
// If focus shift is blocked, we eat the event. Note we should never clear swallowEvent
// if the page already set it (e.g., by canceling default behavior).
if (node && node->isMouseFocusable()) {
- if (!m_frame->document()->setFocusedNode(node))
+ if (!m_frame->page()->focusController()->setFocusedNode(node))
swallowEvent = true;
} else if (!node || !node->focused()) {
if (!m_frame->document()->setFocusedNode(0))
return true;
}
+static bool relinquishesEditingFocus(Node *node)
+{
+ ASSERT(node);
+ ASSERT(node->isContentEditable());
+
+ Node* root = node->rootEditableElement();
+ Frame* frame = node->document()->frame();
+ if (!frame || !root)
+ return false;
+
+ return frame->editor()->shouldEndEditing(rangeOfContents(root).get());
+}
+
+static void clearSelectionIfNeeded(Frame* oldFocusedFrame, Node* newFocusedNode)
+{
+ if (!oldFocusedFrame)
+ return;
+
+ if (newFocusedNode && oldFocusedFrame->document() != newFocusedNode->document())
+ return;
+
+ SelectionController* s = oldFocusedFrame->selectionController();
+ if (s->isNone())
+ return;
+
+ Node* selectionStartNode = s->selection().start().node();
+ if (selectionStartNode == newFocusedNode || selectionStartNode->isDescendantOf(newFocusedNode) || selectionStartNode->shadowAncestorNode() == newFocusedNode)
+ return;
+
+ s->clear();
+}
+
bool FocusController::setFocusedNode(Node* node)
{
RefPtr<Frame> oldFocusedFrame = focusedFrame();
RefPtr<Document> oldDocument = oldFocusedFrame ? oldFocusedFrame->document() : 0;
+ Node* oldFocusedNode = oldDocument ? oldDocument->focusedNode() : 0;
+ if (oldFocusedNode == node)
+ return true;
+
+ if (oldFocusedNode && oldFocusedNode->rootEditableElement() == oldFocusedNode && !relinquishesEditingFocus(oldFocusedNode))
+ return false;
+
+ clearSelectionIfNeeded(oldFocusedFrame.get(), node);
+
if (!node) {
if (oldDocument)
oldDocument->setFocusedNode(0);
// so add the !isFrameElement check here. There's probably a better way to make this
// work in the long term, but this is the safest fix at this time.
if (target && target->isMouseFocusable() && !isFrameElement(target)) {
- document()->setFocusedNode(target);
+ page()->focusController()->setFocusedNode(target);
return;
}
renderer = renderer->parent();