WebCore:
authorandersca <andersca@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 12 Jul 2006 10:33:17 +0000 (10:33 +0000)
committerandersca <andersca@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 12 Jul 2006 10:33:17 +0000 (10:33 +0000)
2006-07-12  Anders Carlsson  <acarlsson@apple.com>

        Reviewed by Maciej.

        <rdar://problem/4586665> REGRESSION: autorestore.apple.com: Crashes Safari in WebCore::Widget::client() const

        * bridge/mac/FrameMac.h:
        Add focusCallResultedInViewBeingCreated argument.

        * bridge/mac/FrameMac.mm:
        (WebCore::FrameMac::nextKeyViewInFrame):
        If the call to focus() caused the node to get a native widget, set focusCallResultedInViewBeingCreated to true.

        (WebCore::FrameMac::nextKeyViewInFrameHierarchy):
        Don't reset the focus node if focusCallResultedInViewBeingCreated is true. Also, add magic to prevent setting
        a text field as the first responder if its field editor already is the current first responder.

        * page/FrameView.cpp:
        (WebCore::FrameView::handleMousePressEvent):
        In some cases, get the event target node again after dispatching the mouse event.

LayoutTests:

2006-07-12  Anders Carlsson  <acarlsson@apple.com>

        Reviewed by Maciej.

        <rdar://problem/4586665> REGRESSION: autorestore.apple.com: Crashes Safari in WebCore::Widget::client() const

        * fast/forms/input-type-change-in-onfocus-keyboard-expected.txt: Added.
        * fast/forms/input-type-change-in-onfocus-keyboard.html: Added.
        * fast/forms/input-type-change-in-onfocus-mouse-expected.txt: Added.
        * fast/forms/input-type-change-in-onfocus-mouse.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@15387 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/forms/input-type-change-in-onfocus-keyboard-expected.txt [new file with mode: 0644]
LayoutTests/fast/forms/input-type-change-in-onfocus-keyboard.html [new file with mode: 0644]
LayoutTests/fast/forms/input-type-change-in-onfocus-mouse-expected.txt [new file with mode: 0644]
LayoutTests/fast/forms/input-type-change-in-onfocus-mouse.html [new file with mode: 0644]
WebCore/ChangeLog
WebCore/bridge/mac/FrameMac.h
WebCore/bridge/mac/FrameMac.mm
WebCore/page/FrameView.cpp

index 74362b0..a7ac886 100644 (file)
@@ -1,3 +1,14 @@
+2006-07-12  Anders Carlsson  <acarlsson@apple.com>
+
+        Reviewed by Maciej.
+
+        <rdar://problem/4586665> REGRESSION: autorestore.apple.com: Crashes Safari in WebCore::Widget::client() const
+
+        * fast/forms/input-type-change-in-onfocus-keyboard-expected.txt: Added.
+        * fast/forms/input-type-change-in-onfocus-keyboard.html: Added.
+        * fast/forms/input-type-change-in-onfocus-mouse-expected.txt: Added.
+        * fast/forms/input-type-change-in-onfocus-mouse.html: Added.
+
 2006-07-12  Adele Peterson  <adele@apple.com>
 
         Reviewed by Maciej.
diff --git a/LayoutTests/fast/forms/input-type-change-in-onfocus-keyboard-expected.txt b/LayoutTests/fast/forms/input-type-change-in-onfocus-keyboard-expected.txt
new file mode 100644 (file)
index 0000000..9369272
--- /dev/null
@@ -0,0 +1,5 @@
+
+This tests that changing an input element's type in its onfocus handler does not cause its onblur handler to be called. If this test is successful, "SUCCESS" should be shown below.
+
+SUCCESS
+
diff --git a/LayoutTests/fast/forms/input-type-change-in-onfocus-keyboard.html b/LayoutTests/fast/forms/input-type-change-in-onfocus-keyboard.html
new file mode 100644 (file)
index 0000000..bc69f3d
--- /dev/null
@@ -0,0 +1,31 @@
+<html>
+<head>
+    <script>
+    function runTest() {
+        if (window.layoutTestController)
+            layoutTestController.dumpAsText();
+        else {
+            alert('This test does not work in Safari.');
+            return;
+        }
+            
+        onblurCalled = false;
+
+        // Simulate a tab. 
+        eventSender.keyDown('\t', new Array());
+
+        if (onblurCalled)
+            return;
+        
+        document.getElementById('result').innerHTML = 'SUCCESS';        
+    }
+    </script>
+</head>
+<body onload="runTest()">
+    <input type="text" onfocus="this.setAttribute('type', 'password')" onblur="onblurCalled = true;">
+    <p>
+    This tests that changing an input element's type in its onfocus handler does not cause its onblur handler to be called. If this test is successful, "SUCCESS" should be shown below.
+    </p>
+    <div id="result">FAILURE</div>
+</body>
+</html>
diff --git a/LayoutTests/fast/forms/input-type-change-in-onfocus-mouse-expected.txt b/LayoutTests/fast/forms/input-type-change-in-onfocus-mouse-expected.txt
new file mode 100644 (file)
index 0000000..9369272
--- /dev/null
@@ -0,0 +1,5 @@
+
+This tests that changing an input element's type in its onfocus handler does not cause its onblur handler to be called. If this test is successful, "SUCCESS" should be shown below.
+
+SUCCESS
+
diff --git a/LayoutTests/fast/forms/input-type-change-in-onfocus-mouse.html b/LayoutTests/fast/forms/input-type-change-in-onfocus-mouse.html
new file mode 100644 (file)
index 0000000..f22c642
--- /dev/null
@@ -0,0 +1,33 @@
+<html>
+<head>
+    <script>
+    function runTest() {
+        if (window.layoutTestController)
+            layoutTestController.dumpAsText();
+        else {
+            alert('This test does not work in Safari.');
+            return;
+        }
+            
+        onblurCalled = false;
+
+        // Simulate a mouse click.
+        eventSender.mouseMoveTo(15, 15);
+        eventSender.mouseDown();
+        eventSender.mouseUp();
+        
+        if (onblurCalled) 
+            return;
+
+        document.getElementById('result').innerHTML = 'SUCCESS';        
+    }
+    </script>
+</head>
+<body onload="runTest()">
+    <input id="input" type="text" onfocus="this.setAttribute('type', 'password')" onblur="onblurCalled = true;">
+    <p>
+    This tests that changing an input element's type in its onfocus handler does not cause its onblur handler to be called. If this test is successful, "SUCCESS" should be shown below.
+    </p>
+    <div id="result">FAILURE</div>
+</body>
+</html>
index 8374c06..fda4f6d 100644 (file)
@@ -1,3 +1,24 @@
+2006-07-12  Anders Carlsson  <acarlsson@apple.com>
+
+        Reviewed by Maciej.
+
+        <rdar://problem/4586665> REGRESSION: autorestore.apple.com: Crashes Safari in WebCore::Widget::client() const
+
+        * bridge/mac/FrameMac.h:
+        Add focusCallResultedInViewBeingCreated argument. 
+        
+        * bridge/mac/FrameMac.mm:
+        (WebCore::FrameMac::nextKeyViewInFrame):
+        If the call to focus() caused the node to get a native widget, set focusCallResultedInViewBeingCreated to true.
+        
+        (WebCore::FrameMac::nextKeyViewInFrameHierarchy):
+        Don't reset the focus node if focusCallResultedInViewBeingCreated is true. Also, add magic to prevent setting
+        a text field as the first responder if its field editor already is the current first responder.
+        
+        * page/FrameView.cpp:
+        (WebCore::FrameView::handleMousePressEvent):
+        In some cases, get the event target node again after dispatching the mouse event.
+
 2006-07-12  Beth Dakin  <bdakin@apple.com>
 
         Reviewed by Adele.
index bacfc36..81445aa 100644 (file)
@@ -326,7 +326,7 @@ private:
     
     NSView* mouseDownViewIfStillGood();
 
-    NSView* nextKeyViewInFrame(Node* startingPoint, SelectionDirection);
+    NSView* nextKeyViewInFrame(Node* startingPoint, SelectionDirection, bool* focusCallResultedInViewBeingCreated = 0);
     static NSView* documentViewForNode(Node*);
     
     bool dispatchCPPEvent(const AtomicString &eventType, ClipboardMac::AccessPolicy policy);
index 9734310..daa9a8a 100644 (file)
@@ -870,7 +870,7 @@ String FrameMac::mimeTypeForFileName(const String& fileName) const
     return String();
 }
 
-NSView* FrameMac::nextKeyViewInFrame(Node* node, SelectionDirection direction)
+NSView* FrameMac::nextKeyViewInFrame(Node* node, SelectionDirection direction, bool* focusCallResultedInViewBeingCreated)
 {
     Document* doc = document();
     if (!doc)
@@ -885,8 +885,13 @@ NSView* FrameMac::nextKeyViewInFrame(Node* node, SelectionDirection direction)
         RenderObject* renderer = node->renderer();
         if (!renderer->isWidget()) {
             static_cast<Element*>(node)->focus(); 
-            [_bridge willMakeFirstResponderForNodeFocus];
-            return [_bridge documentView];
+            // The call to focus might have triggered event handlers that change the renderer type.
+            // FIXME: When all input elements are native, we won't need this extra check
+            if ((renderer = node->renderer()) && !renderer->isWidget()) {
+                [_bridge willMakeFirstResponderForNodeFocus];
+                return [_bridge documentView];
+            } else if (focusCallResultedInViewBeingCreated)
+                *focusCallResultedInViewBeingCreated = true;
         }
 
         if (Widget* widget = static_cast<RenderWidget*>(renderer)->widget()) {
@@ -903,15 +908,30 @@ NSView* FrameMac::nextKeyViewInFrame(Node* node, SelectionDirection direction)
 
 NSView *FrameMac::nextKeyViewInFrameHierarchy(Node *node, SelectionDirection direction)
 {
-    NSView *next = nextKeyViewInFrame(node, direction);
+    bool focusCallResultedInViewBeingCreated = false;
+    NSView *next = nextKeyViewInFrame(node, direction, &focusCallResultedInViewBeingCreated);
     if (!next)
         if (FrameMac *parent = Mac(tree()->parent()))
             next = parent->nextKeyViewInFrameHierarchy(ownerElement(), direction);
     
     // remove focus from currently focused node if we're giving focus to another view
-    if (next && (next != [_bridge documentView]))
+    // unless the other view was created as a result of calling focus in nextKeyViewWithFrame.
+    // FIXME: The focusCallResultedInViewBeingCreated calls can be removed when all input element types
+    // have been made native.
+    if (next && (next != [_bridge documentView] && !focusCallResultedInViewBeingCreated))
         if (Document *doc = document())
             doc->setFocusNode(0);
+
+    // The common case where a view was created is when an <input> element changed from native 
+    // to non-native. When this happens, HTMLGenericFormElement::attach() method will call setFocus()
+    // on the widget. For views with a field editor, setFocus() will set the active responder to be the field editor. 
+    // In this case, we want to return the field editor as the next key view. Otherwise, the focus will be lost
+    // and a blur message will be sent. 
+    // FIXME: This code can be removed when all input element types are native.
+    if (focusCallResultedInViewBeingCreated) {
+        if ([[next window] firstResponder] == [[next window] fieldEditor:NO forObject:next])
+            return [[next window] fieldEditor:NO forObject:next];
+    }
     
     return next;
 }
index 930ec64..89ec180 100644 (file)
@@ -574,6 +574,13 @@ void FrameView::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
     bool swallowEvent = dispatchMouseEvent(mousedownEvent, mev.targetNode(), true, d->clickCount, mouseEvent, true);
 
     if (!swallowEvent) {
+        // Refetch the event target node if it currently is the shadow node inside an <input> element.
+        // If a mouse event handler changes the input element type to one that has a widget associated,
+        // we'd like to Frame::handleMousePressEvent to pass the event to the widget and thus the
+        // event target node can't still be the shadow node.
+        if (mev.targetNode()->isShadowNode() && mev.targetNode()->shadowParentNode()->hasTagName(inputTag))
+            mev = prepareMouseEvent(true, true, false, mouseEvent);
+
         m_frame->handleMousePressEvent(mev);
         // Many AK widgets run their own event loops and consume events while the mouse is down.
         // When they finish, currentEvent is the mouseUp that they exited on.  We need to update