Event refactoring.
authorhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 30 Sep 2006 09:30:31 +0000 (09:30 +0000)
committerhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 30 Sep 2006 09:30:31 +0000 (09:30 +0000)
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@16683 268f45cc-cd09-0410-ab3c-d52691b4dbfc

12 files changed:
WebCore/ChangeLog
WebCore/bridge/mac/FrameMac.h
WebCore/bridge/mac/FrameMac.mm
WebCore/bridge/mac/FrameViewMac.mm
WebCore/page/Frame.cpp
WebCore/page/Frame.h
WebCore/page/FrameView.cpp
WebCore/page/FrameView.h
WebCore/platform/ScrollBar.h
WebCore/platform/Widget.h
WebCore/platform/win/TemporaryLinkStubs.cpp
WebCore/rendering/RenderView.cpp

index 48598b2842fe9923ca0f924970c7e4e6e78a42b5..904b0dea02fad9e9619cc9e83971f6170d08704f 100644 (file)
@@ -1,3 +1,49 @@
+2006-09-30  Dave Hyatt  <hyatt@apple.com>
+
+        Refactor subframe event handling to hide more of the Mac-specific logic from the cross-platform code.
+        Stub out a capturing API that mimics the way Web browsers capture events and route them to specific
+        subframes while the mouse is down.
+      
+        Reviewed by mitzpettel
+
+        * bridge/mac/FrameMac.h:
+        * bridge/mac/FrameMac.mm:
+        (WebCore::FrameMac::passWidgetMouseDownEventToWidget):
+        (WebCore::FrameMac::passWheelEventToWidget):
+        * bridge/mac/FrameViewMac.mm:
+        (WebCore::FrameView::passMousePressEventToSubframe):
+        (WebCore::FrameView::passMouseMoveEventToSubframe):
+        (WebCore::FrameView::passMouseReleaseEventToSubframe):
+        (WebCore::FrameView::passWheelEventToSubframe):
+        * page/Frame.cpp:
+        * page/Frame.h:
+        * page/FrameView.cpp:
+        (WebCore::subframeForTargetNode):
+        (WebCore::FrameView::handleMousePressEvent):
+        (WebCore::FrameView::handleMouseDoubleClickEvent):
+        (WebCore::FrameView::handleMouseMoveEvent):
+        (WebCore::FrameView::handleMouseReleaseEvent):
+        (WebCore::FrameView::handleWheelEvent):
+        * page/FrameView.h:
+        * platform/ScrollBar.h:
+        (WebCore::ScrollBar::handleMouseMoveEvent):
+        (WebCore::ScrollBar::handleMouseOutEvent):
+        * platform/Widget.h:
+        (WebCore::Widget::handleMouseMoveEvent):
+        (WebCore::Widget::handleMouseReleaseEvent):
+        * platform/win/TemporaryLinkStubs.cpp:
+        (FrameView::passMousePressEventToSubframe):
+        (FrameView::passMouseMoveEventToSubframe):
+        (FrameView::passMouseReleaseEventToSubframe):
+        (FrameView::passWheelEventToSubframe):
+        (Widget::capturingMouse):
+        (Widget::setCapturingMouse):
+        (Widget::capturingTarget):
+        (Widget::capturingChild):
+        (Widget::setCapturingChild):
+        * rendering/RenderView.cpp:
+        (WebCore::RenderView::paintBoxDecorations):
+
 2006-09-29  MorganL  <morganl.webkit@yahoo.com>
 
         Reviewed by Adele.
index c73e36ee5a4d2cf739721a69571ba76862fa8fee..ba3c3a5c9a8104451a988651fb12a8da20d7a83c 100644 (file)
@@ -226,9 +226,11 @@ public:
     
     bool sendContextMenuEvent(NSEvent*);
 
-    virtual bool passMouseDownEventToWidget(Widget*);
-    virtual bool passSubframeEventToSubframe(MouseEventWithHitTestResults&, Frame* subframePart);
-    virtual bool passWheelEventToChildWidget(Node*);
+    bool passWidgetMouseDownEventToWidget(const MouseEventWithHitTestResults&);
+    bool passWidgetMouseDownEventToWidget(RenderWidget*);
+    bool passMouseDownEventToWidget(Widget*);
+    bool passSubframeEventToSubframe(MouseEventWithHitTestResults&, Frame* subframePart);
+    bool passWheelEventToWidget(Widget*);
     
     NSString* searchForLabelsAboveCell(RegularExpression* regExp, HTMLTableCellElement* cell);
     NSString* searchForLabelsBeforeElement(NSArray* labels, Element* element);
index bc0d3d15f08eca780640b9693b848e213ed892d4..1b08cf4b6fe5709f31f088b25927263043d80c15 100644 (file)
@@ -1401,6 +1401,32 @@ void FrameMac::handleMousePressEvent(const MouseEventWithHitTestResults& event)
     }
 }
 
+bool FrameMac::passWidgetMouseDownEventToWidget(const MouseEventWithHitTestResults& event)
+{
+    // Figure out which view to send the event to.
+    RenderObject *target = event.targetNode() ? event.targetNode()->renderer() : 0;
+    if (!target)
+        return false;
+    
+    Widget* widget = event.scrollbar();
+    if (!widget) {
+        if (!target->isWidget())
+            return false;
+        widget = static_cast<RenderWidget*>(target)->widget();
+    }
+    
+    // Doubleclick events don't exist in Cocoa.  Since passWidgetMouseDownEventToWidget will
+    // just pass _currentEvent down to the widget,  we don't want to call it for events that
+    // don't correspond to Cocoa events.  The mousedown/ups will have already been passed on as
+    // part of the pressed/released handling.
+    return passMouseDownEventToWidget(widget);
+}
+
+bool FrameMac::passWidgetMouseDownEventToWidget(RenderWidget *renderWidget)
+{
+    return passMouseDownEventToWidget(renderWidget->widget());
+}
+
 bool FrameMac::passMouseDownEventToWidget(Widget* widget)
 {
     // FIXME: this method always returns true
@@ -1916,20 +1942,13 @@ bool FrameMac::passSubframeEventToSubframe(MouseEventWithHitTestResults& event,
     return false;
 }
 
-bool FrameMac::passWheelEventToChildWidget(Node *node)
+bool FrameMac::passWheelEventToWidget(Widget* widget)
 {
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
         
-    if ([_currentEvent type] != NSScrollWheel || _sendingEventToSubview || !node
+    if ([_currentEvent type] != NSScrollWheel || _sendingEventToSubview || !widget
         return false;
     else {
-        RenderObject *renderer = node->renderer();
-        if (!renderer || !renderer->isWidget())
-            return false;
-        Widget *widget = static_cast<RenderWidget*>(renderer)->widget();
-        if (!widget)
-            return false;
-            
         NSView *nodeView = widget->getView();
         ASSERT(nodeView);
         ASSERT([nodeView superview]);
index e021881e0381e2c6246f7f6064c8187bc8c7de62..c8dfeb87241cb7ef632d01b229b04de16dafce32 100644 (file)
@@ -52,4 +52,24 @@ void FrameView::updateDashboardRegions()
     }
 }
 
+bool FrameView::passMousePressEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe)
+{
+    return Mac(m_frame.get())->passSubframeEventToSubframe(mev, subframe);
+}
+
+bool FrameView::passMouseMoveEventToSubframe(MouseEventWithHitTestResults&, Frame*)
+{
+    return Mac(m_frame.get())->passSubframeEventToSubframe(mev, subframe);
+}
+
+bool FrameView::passMouseReleaseEventToSubframe(MouseEventWithHitTestResults&, Frame*)
+{
+    return Mac(m_frame.get())->passSubframeEventToSubframe(mev, subframe);
+}
+
+bool FrameView::passWheelEventToSubframe(PlatformWheelEvent&, Frame*)
+{
+    return Mac(m_frame.get())->passWheelEventToWidget(subframe);
+}
+    
 }
index 94178eabe4cf6f465d79716401b678207f838e69..00a27ef81786974a48efa3093dfd694599ac9ab7 100644 (file)
@@ -3250,39 +3250,6 @@ bool Frame::canMouseDownStartSelect(Node* node)
     return true;
 }
 
-void Frame::handleMouseReleaseDoubleClickEvent(const MouseEventWithHitTestResults& event)
-{
-    passWidgetMouseDownEventToWidget(event, true);
-}
-
-bool Frame::passWidgetMouseDownEventToWidget(const MouseEventWithHitTestResults& event, bool isDoubleClick)
-{
-    // Figure out which view to send the event to.
-    RenderObject *target = event.targetNode() ? event.targetNode()->renderer() : 0;
-    if (!target)
-        return false;
-    
-    Widget* widget = event.scrollbar();
-    if (!widget) {
-        if (!target->isWidget())
-            return false;
-        widget = static_cast<RenderWidget*>(target)->widget();
-    }
-    
-    // Doubleclick events don't exist in Cocoa.  Since passWidgetMouseDownEventToWidget will
-    // just pass _currentEvent down to the widget,  we don't want to call it for events that
-    // don't correspond to Cocoa events.  The mousedown/ups will have already been passed on as
-    // part of the pressed/released handling.
-    if (!isDoubleClick)
-        return passMouseDownEventToWidget(widget);
-    return true;
-}
-
-bool Frame::passWidgetMouseDownEventToWidget(RenderWidget *renderWidget)
-{
-    return passMouseDownEventToWidget(renderWidget->widget());
-}
-
 void Frame::clearTimers(FrameView *view)
 {
     if (view) {
index 12e716b017e8144d9bd10c42f099d6d184f99f99..ea42b24a6119ed652ddde5b0f750f8cf7216d4a9 100644 (file)
@@ -521,7 +521,6 @@ public:
    */
   KURL completeURL(const DeprecatedString& url);
 
-  virtual void handleMouseReleaseDoubleClickEvent(const MouseEventWithHitTestResults&);
   virtual void handleMousePressEvent(const MouseEventWithHitTestResults&);
   virtual void handleMouseMoveEvent(const MouseEventWithHitTestResults&);
   virtual void handleMouseReleaseEvent(const MouseEventWithHitTestResults&);
@@ -579,8 +578,6 @@ public:
   virtual void openURLRequest(const ResourceRequest&) = 0;
   virtual void submitForm(const ResourceRequest&) = 0;
   virtual void urlSelected(const ResourceRequest&) = 0;
-  virtual bool passSubframeEventToSubframe(MouseEventWithHitTestResults&, Frame* subframePart = 0) = 0;
-  virtual bool passWheelEventToChildWidget(Node*) = 0;
   virtual bool lastEventIsMouseUp() const = 0;
   virtual String overrideMediaType() const = 0;
   virtual void redirectDataToPlugin(Widget* pluginWidget) { }
@@ -716,9 +713,6 @@ private:
   bool scrollbarsVisible();
   void scrollToAnchor(const KURL&);
   bool canMouseDownStartSelect(Node*);
-  bool passWidgetMouseDownEventToWidget(const MouseEventWithHitTestResults&, bool isDoubleClick);
-  bool passWidgetMouseDownEventToWidget(RenderWidget*);
-  virtual bool passMouseDownEventToWidget(Widget*) = 0;
 
   void clearTimers();
   static void clearTimers(FrameView*);
index d189909913f3c96f8fd2107bde7af24dbbbc467c..eb2c10bfc0f32c6d9d2058b7047e1d90654c06dd 100644 (file)
@@ -551,12 +551,12 @@ void FrameView::layout(bool allowSubtree)
 //
 /////////////////
 
-static Frame* subframeForEvent(const MouseEventWithHitTestResults& mev)
+static Frame* subframeForTargetNode(Node* node)
 {
-    if (!mev.targetNode())
+    if (!node)
         return 0;
 
-    RenderObject* renderer = mev.targetNode()->renderer();
+    RenderObject* renderer = node->renderer();
     if (!renderer || !renderer->isWidget())
         return 0;
 
@@ -584,7 +584,8 @@ void FrameView::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
     
     MouseEventWithHitTestResults mev = prepareMouseEvent(false, true, false, mouseEvent);
 
-    if (m_frame->passSubframeEventToSubframe(mev)) {
+    Frame* subframe = subframeForTargetNode(mev.targetNode());
+    if (subframe && passMousePressEventToSubframe(mev, subframe)) {
         invalidateClick();
         return;
     }
@@ -623,6 +624,7 @@ void FrameView::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
     }
 }
 
+// This method only exists for platforms that don't know how to deliver 
 void FrameView::handleMouseDoubleClickEvent(const PlatformMouseEvent& mouseEvent)
 {
     if (!m_frame->document())
@@ -635,8 +637,8 @@ void FrameView::handleMouseDoubleClickEvent(const PlatformMouseEvent& mouseEvent
     d->m_currentMousePosition = convertFromContainingWindow(mouseEvent.pos());
 
     MouseEventWithHitTestResults mev = prepareMouseEvent(false, true, false, mouseEvent);
-
-    if (m_frame->passSubframeEventToSubframe(mev))
+    Frame* subframe = subframeForTargetNode(mev.targetNode());
+    if (subframe && passMousePressEventToSubframe(mev, subframe))
         return;
 
     d->clickCount = mouseEvent.clickCount();
@@ -645,11 +647,8 @@ void FrameView::handleMouseDoubleClickEvent(const PlatformMouseEvent& mouseEvent
     if (mev.targetNode() == d->clickNode)
         dispatchMouseEvent(clickEvent, mev.targetNode(), true, d->clickCount, mouseEvent, true);
 
-    // Qt delivers a release event AND a double click event.
-    if (!swallowEvent) {
+    if (!swallowEvent)
         m_frame->handleMouseReleaseEvent(mev);
-        m_frame->handleMouseReleaseDoubleClickEvent(mev);
-    }
 
     invalidateClick();
 }
@@ -783,14 +782,14 @@ void FrameView::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent)
         d->mousePressed, true, mouseEvent);
 
     if (d->oldSubframe && d->oldSubframe->tree()->isDescendantOf(m_frame.get()))
-        m_frame->passSubframeEventToSubframe(mev, d->oldSubframe.get());
+        passMouseMoveEventToSubframe(mev, d->oldSubframe.get());
 
     bool swallowEvent = dispatchMouseEvent(mousemoveEvent, mev.targetNode(), false, 0, mouseEvent, true);
     
     if (d->oldScrollBar != mev.scrollbar()) {
         // Send mouse exited to the old scrollbar.
         if (d->oldScrollBar)
-            d->oldScrollBar->mouseExited();
+            d->oldScrollBar->handleMouseOutEvent(mouseEvent);
         d->oldScrollBar = mev.scrollbar();
     }
 
@@ -800,13 +799,12 @@ void FrameView::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent)
     if (!swallowEvent)
         m_frame->handleMouseMoveEvent(mev);
     
-    RefPtr<Frame> newSubframe = subframeForEvent(mev);
-    
+    RefPtr<Frame> newSubframe = subframeForTargetNode(mev.targetNode());
     if (newSubframe && d->oldSubframe != newSubframe)
-        m_frame->passSubframeEventToSubframe(mev, newSubframe.get());
+        passMouseMoveEventToSubframe(mev, newSubframe.get());
     else {
         if (mev.scrollbar() && !d->mousePressed)
-            mev.scrollbar()->mouseMoved(mouseEvent); // Handle hover effects on platforms that support visual feedback on scrollbar hovering.
+            mev.scrollbar()->handleMouseMoveEvent(mouseEvent); // Handle hover effects on platforms that support visual feedback on scrollbar hovering.
         setCursor(selectCursor(mev, m_frame.get(), d->mousePressed));
     }
 
@@ -840,8 +838,8 @@ void FrameView::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent)
     }
 
     MouseEventWithHitTestResults mev = prepareMouseEvent(false, false, false, mouseEvent);
-
-    if (m_frame->passSubframeEventToSubframe(mev))
+    Frame* subframe = subframeForTargetNode(mev.targetNode());
+    if (subframe && passMouseReleaseEventToSubframe(mev, subframe))
         return;
 
     bool swallowEvent = dispatchMouseEvent(mouseupEvent, mev.targetNode(), true, d->clickCount, mouseEvent, false);
@@ -1239,8 +1237,8 @@ void FrameView::handleWheelEvent(PlatformWheelEvent& e)
             RenderObject::NodeInfo hitTestResult(true, false);
             doc->renderer()->layer()->hitTest(hitTestResult, vPoint); 
             Node *node = hitTestResult.innerNode();
-
-            if (m_frame->passWheelEventToChildWidget(node)) {
+            Frame* subframe = subframeForTargetNode(node);
+            if (subframe && passWheelEventToSubframe(e, subframe)) {
                 e.accept();
                 return;
             }
index 08cff47fed929f01aaff4200dec71bed4ec19411..9e91eb3383a9e8ab0b47c0551c1483d125fd56a9 100644 (file)
@@ -136,10 +136,15 @@ public:
 
     void handleMousePressEvent(const PlatformMouseEvent&);
     void handleMouseDoubleClickEvent(const PlatformMouseEvent&);
-    void handleMouseMoveEvent(const PlatformMouseEvent&);
-    void handleMouseReleaseEvent(const PlatformMouseEvent&);
+    virtual void handleMouseMoveEvent(const PlatformMouseEvent&);
+    virtual void handleMouseReleaseEvent(const PlatformMouseEvent&);
     void handleWheelEvent(PlatformWheelEvent&);
 
+    bool passMousePressEventToSubframe(MouseEventWithHitTestResults&, Frame*);
+    bool passMouseMoveEventToSubframe(MouseEventWithHitTestResults&, Frame*);
+    bool passMouseReleaseEventToSubframe(MouseEventWithHitTestResults&, Frame*);
+    bool passWheelEventToSubframe(PlatformWheelEvent&, Frame*);
+
     bool mousePressed();
 
     void doAutoScroll();
index 851fbf99f3ff8fe1bd19b3e1b76dbc1c88463dcb..ff5e70b4ff74690d59bae06c288eeaf7f537b552 100644 (file)
@@ -100,8 +100,8 @@ public:
     // These methods are used for platform scrollbars to give :hover feedback.  They will not get called
     // when the mouse went down in a scrollbar, since it is assumed the scrollbar will start
     // grabbing all events in that case anyway.
-    virtual void mouseMoved(const PlatformMouseEvent&) {};
-    virtual void mouseExited() {};
+    virtual void handleMouseMoveEvent(const PlatformMouseEvent&) {};
+    virtual void handleMouseOutEvent(const PlatformMouseEvent&) {};
 
 protected:
     virtual void updateThumbPosition() = 0;
index bc74a741e0adebb06d789c26f64992eb6419590b..7deccd8104d0f72c802574ec0a0afce0584e8f0d 100644 (file)
@@ -56,6 +56,7 @@ namespace WebCore {
     class IntPoint;
     class IntRect;
     class IntSize;
+    class PlatformMouseEvent;
     class WidgetClient;
     class WidgetPrivate;
 
@@ -147,6 +148,16 @@ namespace WebCore {
 
         void setParent(Widget*);
         Widget* parent() const;
+
+        bool capturingMouse() const;
+        void setCapturingMouse(bool);
+        Widget* capturingTarget();
+        Widget* capturingChild();
+        void setCapturingChild(Widget*);
+        
+        // These methods will be called on a widget while it is capturing the mouse.
+        virtual void handleMouseMoveEvent(const PlatformMouseEvent&) {};
+        virtual void handleMouseReleaseEvent(const PlatformMouseEvent&) {};
 #endif
 
 #if PLATFORM(GDK)
index 4b71cad35cc6b393f6fd79ac17796afd5208d818..0e82f6b02b5f26ba2f46feda26b9ef315467aeeb 100644 (file)
@@ -78,6 +78,10 @@ using namespace WebCore;
 } while (0)
 
 void FrameView::updateBorder() { notImplemented(); }
+bool FrameView::passMousePressEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe) { return true; }
+bool FrameView::passMouseMoveEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe) { return true; }
+bool FrameView::passMouseReleaseEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe) { return true; }
+bool FrameView::passWheelEventToSubframe(PlatformWheelEvent& e, Frame* subframe) { return false; }
 
 void Widget::enableFlushDrawing() { notImplemented(); }
 bool Widget::isEnabled() const { notImplemented(); return 0; }
@@ -85,7 +89,12 @@ Widget::FocusPolicy Widget::focusPolicy() const { notImplemented(); return NoFoc
 void Widget::disableFlushDrawing() { notImplemented(); }
 GraphicsContext* Widget::lockDrawingFocus() { notImplemented(); return 0; }
 void Widget::unlockDrawingFocus(GraphicsContext*) { notImplemented(); }
-
+bool Widget::capturingMouse() const { return false; }
+void Widget::setCapturingMouse(bool capturingMouse) { }
+Widget* Widget::capturingTarget() { return this; }
+Widget* Widget::capturingChild() { return 0; }
+void Widget::setCapturingChild(Widget* w) {}
+}
 JavaAppletWidget::JavaAppletWidget(IntSize const&,Element*,WTF::HashMap<String,String> const&) { notImplemented(); }
 
 void TextField::selectAll() { notImplemented(); }
index 7833aaecde81892a2e4fa8a37b4d68c75b5389b6..b02711940d9ea86e45eeec2ec3af02186c734698 100644 (file)
@@ -191,13 +191,13 @@ void RenderView::paintBoxDecorations(PaintInfo& i, int _tx, int _ty)
             frameView()->setUseSlowRepaints();
     }
     
-    if ((firstChild() && firstChild()->style()->visibility() == VISIBLE) || !view())
+    if (elt || (firstChild() && firstChild()->style()->visibility() == VISIBLE) || !view())
         return;
 
     // This code typically only executes if the root element's visibility has been set to hidden.
     // Only fill with white if we're the root document, since iframes/frames with
     // no background in the child document should show the parent's background.
-    if (elt || view()->isTransparent())
+    if (view()->isTransparent())
         frameView()->setUseSlowRepaints(); // The parent must show behind the child.
     else {
         Color baseColor = frameView()->baseBackgroundColor();