WebCore:
authortrey <trey@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 1 Jul 2004 02:07:43 +0000 (02:07 +0000)
committertrey <trey@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 1 Jul 2004 02:07:43 +0000 (02:07 +0000)
Dragging within a web view should be allowed to start when the window isn't key.

A few months ago, Chris made this work, but it relied on the fact that all dragging
was done in WebKit.  When WebCore got involved in dragging, it was broken.  Now we
have a new scheme that gets it working again that properly involves WebCore.

The general idea is that when AK asks us whether to accept the first mouse and do
"delayed window ordering", we must consult WC to see if we might start a drag.  In
addition, instead of these drags in non-active windows being started as a special
case in WK, they go through the normal WK-WC drag machinery.

        Reviewed by John.

        * khtml/khtml_part.cpp:
        (KHTMLPart::shouldDragAutoNode):  New x,y args.
        * khtml/khtml_part.h:
        * khtml/rendering/render_object.cpp:
        (RenderObject::draggableNode):  Pass through new x,y args.
        * khtml/rendering/render_object.h:
        * kwq/KWQKHTMLPart.h:
        (KWQKHTMLPart::setActivationEventNumber):  New setter.
        * kwq/KWQKHTMLPart.mm:
        (KWQKHTMLPart::KWQKHTMLPart):  Init new ivar.
        (KWQKHTMLPart::eventMayStartDrag):  New routine that checks if we might start
a drag in response to a mouseDown.
        (KWQKHTMLPart::khtmlMouseMoveEvent):  Pass x,y to the routine that finds a draggable
node.  This eventually gets back up to WK's _mayStartDragAtEventLocation:.
Delay requirement when dragging the selection now implemented here.
        (KWQKHTMLPart::khtmlMouseReleaseEvent):  Must avoid changing the selection if we
wind up here as part of the first click in a window (because we started handling
the click to possible start a drag, but that never came through).
        (KWQKHTMLPart::mouseDown): Save away event timestamp.
        (KWQKHTMLPart::shouldDragAutoNode):  Pass location up to WK instead of the
most recent event we stashed.
        * kwq/WebCoreBridge.h:
        * kwq/WebCoreBridge.mm:
        (-[WebCoreBridge setActivationEventNumber:]):  Trivial glue.
        (-[WebCoreBridge eventMayStartDrag:]):  Ditto.

WebKit:

Dragging within a web view should be allowed to start when the window isn't key.

A few months ago, Chris made this work, but it relied on the fact that all dragging
was done in WebKit.  When WebCore got involved in dragging, it was broken.  Now we
have a new scheme that gets it working again that properly involves WebCore.

The general idea is that when AK asks us whether to accept the first mouse and do
"delayed window ordering", we must consult WC to see if we might start a drag.  In
addition, instead of these drags in non-active windows being started as a special
case in WK, they go through the normal WK-WC drag machinery.  Finally to work in
frames we have to drill to the deepest hit view in acceptsFirstMouse, because previous
hacks to hitTest make the top-most WebHTMLView field all events for its view tree
(which leads to it fielding all acceptFirstMouse messages too).

        Reviewed by John.

        * WebCoreSupport.subproj/WebBridge.m:
        (-[WebBridge mayStartDragAtEventLocation:]):  Glue change for new arg type.
        * WebView.subproj/WebHTMLView.m:
        (-[WebHTMLView _startDraggingImage:at:operation:event:sourceIsDHTML:DHTMLWroteData:]):
firstMouseDownEvent ivar is no longer needed.
        (-[WebHTMLView _mayStartDragAtEventLocation:]):  Receives a location instead of a drag
event, since we need to do this work when we have no drag event.  This means the
check of the delay for text dragging is moved down to WebCore.
        (-[WebHTMLView acceptsFirstMouse:]):  Respond based on whether we might do a drag.
This includes drilling to the deepest view the event hits, whereas we used to only
respond considering the topmost WebHTMLView.
        (-[WebHTMLView shouldDelayWindowOrderingForEvent:]):  Ditto.
        (-[WebHTMLView mouseDown:]):  Get rid of special case where some activating
mouseDown events weren't sent to WC.  We need to go through the whole pipeline
now to get a drag started properly.
        (-[WebHTMLView mouseDragged:]):  Ditto, let WC start the drag.
        (-[WebHTMLView mouseUp:]):  firstMouseDownEvent ivar is no longer needed.
        * WebView.subproj/WebHTMLViewInternal.h:
        * WebView.subproj/WebHTMLViewPrivate.h:

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

14 files changed:
WebCore/ChangeLog-2005-08-23
WebCore/khtml/khtml_part.cpp
WebCore/khtml/khtml_part.h
WebCore/khtml/rendering/render_object.cpp
WebCore/khtml/rendering/render_object.h
WebCore/kwq/KWQKHTMLPart.h
WebCore/kwq/KWQKHTMLPart.mm
WebCore/kwq/WebCoreBridge.h
WebCore/kwq/WebCoreBridge.mm
WebKit/ChangeLog
WebKit/WebCoreSupport.subproj/WebBridge.m
WebKit/WebView.subproj/WebHTMLView.m
WebKit/WebView.subproj/WebHTMLViewInternal.h
WebKit/WebView.subproj/WebHTMLViewPrivate.h

index 8668db611593ebddb3fd412dbb88800e926bd232..5e1a8050e75a9f075bfd21304dd9271f13e924c0 100644 (file)
@@ -1,3 +1,44 @@
+2004-06-30  Trey Matteson  <trey@apple.com>
+
+       Dragging within a web view should be allowed to start when the window isn't key.
+
+       A few months ago, Chris made this work, but it relied on the fact that all dragging
+       was done in WebKit.  When WebCore got involved in dragging, it was broken.  Now we
+       have a new scheme that gets it working again that properly involves WebCore.
+
+       The general idea is that when AK asks us whether to accept the first mouse and do
+       "delayed window ordering", we must consult WC to see if we might start a drag.  In
+       addition, instead of these drags in non-active windows being started as a special
+       case in WK, they go through the normal WK-WC drag machinery.
+
+        Reviewed by John.
+
+        * khtml/khtml_part.cpp:
+        (KHTMLPart::shouldDragAutoNode):  New x,y args.
+        * khtml/khtml_part.h:
+        * khtml/rendering/render_object.cpp:
+        (RenderObject::draggableNode):  Pass through new x,y args.
+        * khtml/rendering/render_object.h:
+        * kwq/KWQKHTMLPart.h:
+        (KWQKHTMLPart::setActivationEventNumber):  New setter.
+        * kwq/KWQKHTMLPart.mm:
+        (KWQKHTMLPart::KWQKHTMLPart):  Init new ivar.
+        (KWQKHTMLPart::eventMayStartDrag):  New routine that checks if we might start
+       a drag in response to a mouseDown.
+        (KWQKHTMLPart::khtmlMouseMoveEvent):  Pass x,y to the routine that finds a draggable
+       node.  This eventually gets back up to WK's _mayStartDragAtEventLocation:.
+       Delay requirement when dragging the selection now implemented here.
+        (KWQKHTMLPart::khtmlMouseReleaseEvent):  Must avoid changing the selection if we
+       wind up here as part of the first click in a window (because we started handling
+       the click to possible start a drag, but that never came through).
+        (KWQKHTMLPart::mouseDown): Save away event timestamp.
+        (KWQKHTMLPart::shouldDragAutoNode):  Pass location up to WK instead of the
+       most recent event we stashed.
+        * kwq/WebCoreBridge.h:
+        * kwq/WebCoreBridge.mm:
+        (-[WebCoreBridge setActivationEventNumber:]):  Trivial glue.
+        (-[WebCoreBridge eventMayStartDrag:]):  Ditto.
+
 2004-06-29  Trey Matteson  <trey@apple.com>
 
        Need to tighten up JS error checking for requesting drag props
index 8ce13a50d27f59c55e418456bffc5c0cda66dc5b..5f0acadf38c02dac41010e608dbb9a372bbc3c64 100644 (file)
@@ -4265,7 +4265,7 @@ bool KHTMLPart::dndEnabled() const
   return d->m_bDnd;
 }
 
-bool KHTMLPart::shouldDragAutoNode(DOM::NodeImpl *node) const
+bool KHTMLPart::shouldDragAutoNode(DOM::NodeImpl *node, int x, int y) const
 {
     // No KDE impl yet
     return false;
index c151b45b34ac7c761f3edfc156c54ad591f00e00..87bae96d8a13dd0d91e92a72d45788cbe12bfca5 100644 (file)
@@ -302,7 +302,7 @@ public:
   /**
    * Implementation of CSS property -khtml-user-drag == auto
    */
-  virtual bool shouldDragAutoNode(DOM::NodeImpl*) const;
+  virtual bool shouldDragAutoNode(DOM::NodeImpl*, int x, int y) const;
   
   /**
    * Enables/disables Java applet support. Note that calling this function
index c2fdedd495e9325cb44e40f1e33e4061219d5517..39455e6c97669a0ee715239dfcf3b062bee51f1e 100644 (file)
@@ -1391,7 +1391,7 @@ bool RenderObject::shouldSelect() const
     return node->dispatchHTMLEvent(DOM::EventImpl::SELECTSTART_EVENT, true, true);
 }
 
-DOM::NodeImpl* RenderObject::draggableNode(bool dhtmlOK, bool uaOK, bool& dhtmlWillDrag) const
+DOM::NodeImpl* RenderObject::draggableNode(bool dhtmlOK, bool uaOK, int x, int y, bool& dhtmlWillDrag) const
 {
     if (!dhtmlOK && !uaOK)
         return 0;
@@ -1402,7 +1402,7 @@ DOM::NodeImpl* RenderObject::draggableNode(bool dhtmlOK, bool uaOK, bool& dhtmlW
         if (elt && elt->nodeType() == Node::TEXT_NODE) {
             // Since there's no way for the author to address the -khtml-user-drag style for a text node,
             // we use our own judgement.
-            if (uaOK && canvas()->view()->part()->shouldDragAutoNode(curr->node())) {
+            if (uaOK && canvas()->view()->part()->shouldDragAutoNode(curr->node(), x, y)) {
                 dhtmlWillDrag = false;
                 return curr->node();
             } else if (curr->shouldSelect()) {
@@ -1417,7 +1417,7 @@ DOM::NodeImpl* RenderObject::draggableNode(bool dhtmlOK, bool uaOK, bool& dhtmlW
                 dhtmlWillDrag = true;
                 return curr->node();
             } else if (uaOK && dragMode == DRAG_AUTO
-                       && canvas()->view()->part()->shouldDragAutoNode(curr->node()))
+                       && canvas()->view()->part()->shouldDragAutoNode(curr->node(), x, y))
             {
                 dhtmlWillDrag = false;
                 return curr->node();
index 33be31331334001e5dcb2b3bc45a0a67fd9d6bf2..925e26327c90bfd6ee415dc288b96fc9a532dc6b 100644 (file)
@@ -704,7 +704,7 @@ public:
     virtual void setSelectionState(SelectionState) {}
     bool shouldSelect() const;
 
-    DOM::NodeImpl* draggableNode(bool dhtmlOK, bool uaOK, bool& dhtmlWillDrag) const;
+    DOM::NodeImpl* draggableNode(bool dhtmlOK, bool uaOK, int x, int y, bool& dhtmlWillDrag) const;
 
     /**
      * Returns the content coordinates of the caret within this render object.
index 8aed3334892351d172fd5ad48e13c4854a87cb2e..b2690e09335166259209159a325a9572ecead578 100644 (file)
@@ -231,7 +231,9 @@ public:
     void mouseMoved(NSEvent *);
     bool keyEvent(NSEvent *);
     bool lastEventIsMouseUp();
+    void setActivationEventNumber(int num) { _activationEventNumber = num; }
 
+    bool eventMayStartDrag(NSEvent *);
     void dragSourceMovedTo(const QPoint &loc);
     void dragSourceEndedAt(const QPoint &loc, NSDragOperation operation);
 
@@ -317,7 +319,7 @@ public:
     void partClearedInBegin();
     
     // Implementation of CSS property -khtml-user-drag == auto
-    bool shouldDragAutoNode(DOM::NodeImpl*) const;
+    bool shouldDragAutoNode(DOM::NodeImpl*, int x, int y) const;
 
 private:
     virtual void khtmlMousePressEvent(khtml::MousePressEvent *);
@@ -363,6 +365,8 @@ private:
     int _mouseDownWinX, _mouseDownWinY;
     // in our view's coords
     int _mouseDownX, _mouseDownY;
+    float _mouseDownTimestamp;
+    int _activationEventNumber;
     
     static NSEvent *_currentEvent;
     static NSResponder *_firstResponderAtMouseDownTime;
index db2aa4529f31fadb6e68c3744e91eb51261d4a9e..0e586134ccaa40a58a46073bb782d11aee4ef20f 100644 (file)
@@ -179,6 +179,7 @@ KWQKHTMLPart::KWQKHTMLPart()
     , _sendingEventToSubview(false)
     , _mouseDownMayStartDrag(false)
     , _mouseDownMayStartSelect(false)
+    , _activationEventNumber(0)
     , _formValuesAboutToBeSubmitted(nil)
     , _formAboutToBeSubmitted(nil)
     , _windowWidget(NULL)
@@ -1715,6 +1716,7 @@ void KWQKHTMLPart::khtmlMousePressEvent(MousePressEvent *event)
     // If we got the event back, that must mean it wasn't prevented,
     // so it's allowed to start a drag or selection.
     _mouseDownMayStartSelect = true;
+    // Careful that the drag starting logic stays in sync with eventMayStartDrag()
     _mouseDownMayStartDrag = singleClick;
 
     if (!passWidgetMouseDownEventToWidget(event)) {
@@ -1910,7 +1912,9 @@ NSView *KWQKHTMLPart::mouseDownViewIfStillGood()
 #define LinkDragHysteresis              40.0
 #define ImageDragHysteresis              5.0
 #define TextDragHysteresis               3.0
-#define GeneralDragHysterisis            3.0
+#define GeneralDragHysteresis            3.0
+
+#define TextDragDelay                    0.15
 
 bool KWQKHTMLPart::dragHysteresisExceeded(float dragLocationX, float dragLocationY) const
 {
@@ -1919,7 +1923,7 @@ bool KWQKHTMLPart::dragHysteresisExceeded(float dragLocationX, float dragLocatio
     float deltaX = QABS(dragX - _mouseDownX);
     float deltaY = QABS(dragY - _mouseDownY);
 
-    float threshold = GeneralDragHysterisis;
+    float threshold = GeneralDragHysteresis;
     if (_dragSrcIsImage) {
         threshold = ImageDragHysteresis;
     } else if (_dragSrcIsLink) {
@@ -1937,6 +1941,32 @@ bool KWQKHTMLPart::dispatchDragSrcEvent(int eventId, const QPoint &loc) const
     return !noDefaultProc;
 }
 
+bool KWQKHTMLPart::eventMayStartDrag(NSEvent *event)
+{
+    // This is a pre-flight check of whether the event might lead to a drag being started.  Be careful
+    // that its logic needs to stay in sync with khtmlMouseMoveEvent() and the way we set
+    // _mouseDownMayStartDrag in khtmlMousePressEvent
+    
+    if ([event type] != NSLeftMouseDown || [event clickCount] != 1) {
+        return false;
+    }
+    
+    BOOL DHTMLFlag, UAFlag;
+    [_bridge allowDHTMLDrag:&DHTMLFlag UADrag:&UAFlag];
+    if (!DHTMLFlag && !UAFlag) {
+        return false;
+    }
+
+    NSPoint loc = [event locationInWindow];
+    int mouseDownX, mouseDownY;
+    d->m_view->viewportToContents((int)loc.x, (int)loc.y, mouseDownX, mouseDownY);
+    RenderObject::NodeInfo nodeInfo(true, false);
+    renderer()->layer()->nodeAtPoint(nodeInfo, mouseDownX, mouseDownY);
+    bool srcIsDHTML;
+    Node possibleSrc = nodeInfo.innerNode()->renderer()->draggableNode(DHTMLFlag, UAFlag, mouseDownX, mouseDownY, srcIsDHTML);
+    return !possibleSrc.isNull();
+}
+
 void KWQKHTMLPart::khtmlMouseMoveEvent(MouseMoveEvent *event)
 {
     KWQ_BLOCK_EXCEPTIONS;
@@ -1951,6 +1981,8 @@ void KWQKHTMLPart::khtmlMouseMoveEvent(MouseMoveEvent *event)
             return;
         }
 
+        // Careful that the drag starting logic stays in sync with eventMayStartDrag()
+    
        if (_mouseDownMayStartDrag && _dragSrc.isNull()) {
             BOOL tempFlag1, tempFlag2;
             [_bridge allowDHTMLDrag:&tempFlag1 UADrag:&tempFlag2];
@@ -1965,7 +1997,7 @@ void KWQKHTMLPart::khtmlMouseMoveEvent(MouseMoveEvent *event)
             // try to find an element that wants to be dragged
             RenderObject::NodeInfo nodeInfo(true, false);
             renderer()->layer()->nodeAtPoint(nodeInfo, _mouseDownX, _mouseDownY);
-            _dragSrc = nodeInfo.innerNode()->renderer()->draggableNode(_dragSrcMayBeDHTML, _dragSrcMayBeUA, _dragSrcIsDHTML);
+            _dragSrc = nodeInfo.innerNode()->renderer()->draggableNode(_dragSrcMayBeDHTML, _dragSrcMayBeUA, _mouseDownX, _mouseDownY, _dragSrcIsDHTML);
             if (_dragSrc.isNull()) {
                 _mouseDownMayStartDrag = false;     // no element is draggable
             } else {
@@ -1979,6 +2011,16 @@ void KWQKHTMLPart::khtmlMouseMoveEvent(MouseMoveEvent *event)
                 _dragSrcInSelection = isPointInsideSelection(_mouseDownX, _mouseDownY);
             }                
         }
+        
+        // For drags starting in the selection, the user must wait between the mousedown and mousedrag,
+        // or else we bail on the dragging stuff and allow selection to occur
+        if (_mouseDownMayStartDrag && _dragSrcInSelection && [_currentEvent timestamp] - _mouseDownTimestamp < TextDragDelay) {
+            _mouseDownMayStartDrag = false;
+            // ...but if this was the first click in the window, we don't even want to start selection
+            if (_activationEventNumber == [_currentEvent eventNumber]) {
+                _mouseDownMayStartSelect = false;
+            }
+        }
 
         if (_mouseDownMayStartDrag) {
             // We are starting a text/image/url drag, so the cursor should be an arrow
@@ -2173,7 +2215,14 @@ void KWQKHTMLPart::khtmlMouseReleaseEvent(MouseReleaseEvent *event)
 {
     NSView *view = mouseDownViewIfStillGood();
     if (!view) {
-        KHTMLPart::khtmlMouseReleaseEvent(event);
+        // If this was the first click in the window, we don't even want to clear the selection.
+        // This case occurs when the user clicks on a draggable element, since we have to process
+        // the mouse down and drag events to see if we might start a drag.  For other first clicks
+        // in a window, we just don't acceptFirstMouse, and the whole down-drag-up sequence gets
+        // ignored upstream of this layer.
+        if (_activationEventNumber != [_currentEvent eventNumber]) {
+            KHTMLPart::khtmlMouseReleaseEvent(event);
+        }
         return;
     }
     
@@ -2275,6 +2324,7 @@ void KWQKHTMLPart::mouseDown(NSEvent *event)
     _mouseDownWinX = (int)loc.x;
     _mouseDownWinY = (int)loc.y;
     d->m_view->viewportToContents(_mouseDownWinX, _mouseDownWinY, _mouseDownX, _mouseDownY);
+    _mouseDownTimestamp = [event timestamp];
 
     NSResponder *oldFirstResponderAtMouseDownTime = _firstResponderAtMouseDownTime;
     // Unlike other places in WebCore where we get the first
@@ -2459,14 +2509,17 @@ void KWQKHTMLPart::mouseMoved(NSEvent *event)
 }
 
 // Called as we walk up the element chain for nodes with CSS property -khtml-user-drag == auto
-bool KWQKHTMLPart::shouldDragAutoNode(DOM::NodeImpl* node) const
+bool KWQKHTMLPart::shouldDragAutoNode(DOM::NodeImpl* node, int x, int y) const
 {
     // We assume that WebKit only cares about dragging things that can be leaf nodes (text, images, urls).
     // This saves a bunch of expensive calls (creating WC and WK element dicts) as we walk farther up
     // the node hierarchy, and we also don't have to cook up a way to ask WK about non-leaf nodes
     // (since right now WK just hit-tests using a cached lastMouseDown).
-    if (!node->hasChildNodes()) {
-        return [_bridge mayStartDragWithMouseDragged:_currentEvent];
+    if (!node->hasChildNodes() && d->m_view) {
+        int windowX, windowY;
+        d->m_view->contentsToViewport(x, y, windowX, windowY);
+        NSPoint eventLoc = {windowX, windowY};
+        return [_bridge mayStartDragAtEventLocation:eventLoc];
     } else {
         return NO;
     }
index ba3b5c377a6368522248ef653bb71e7135c13315..ef6af6e360e22fce6a490c84a9ecd2ba3782bde9 100644 (file)
@@ -189,6 +189,7 @@ typedef enum {
 
 - (void)setShowsFirstResponder:(BOOL)flag;
 
+- (void)setActivationEventNumber:(int)num;
 - (void)mouseDown:(NSEvent *)event;
 - (void)mouseUp:(NSEvent *)event;
 - (void)mouseMoved:(NSEvent *)event;
@@ -319,6 +320,7 @@ typedef enum {
 - (WebScriptObject *)windowScriptObject;
 - (NPObject *)windowScriptNPObject;
 
+- (BOOL)eventMayStartDrag:(NSEvent *)event;
 - (NSDragOperation)dragOperationForDraggingInfo:(id <NSDraggingInfo>)info;
 - (void)dragExitedWithDraggingInfo:(id <NSDraggingInfo>)info;
 - (BOOL)concludeDragForDraggingInfo:(id <NSDraggingInfo>)info;
@@ -440,7 +442,7 @@ typedef enum {
 - (void)allowDHTMLDrag:(BOOL *)flagDHTML UADrag:(BOOL *)flagUA;
 - (BOOL)startDraggingImage:(NSImage *)dragImage at:(NSPoint)dragLoc operation:(NSDragOperation)op event:(NSEvent *)event sourceIsDHTML:(BOOL)flag DHTMLWroteData:(BOOL)dhtmlWroteData;
 - (void)handleAutoscrollForMouseDragged:(NSEvent *)event;
-- (BOOL)mayStartDragWithMouseDragged:(NSEvent *)event;
+- (BOOL)mayStartDragAtEventLocation:(NSPoint)location;
 
 - (int)historyLength;
 - (void)goBackOrForward:(int)distance;
index d13662978ce46e3f55da43f1e4428baed2df495d..3c306cdeb48aaf3944b2549a1a7464c5ad1cc6fd 100644 (file)
@@ -759,6 +759,11 @@ static BOOL nowPrinting(WebCoreBridge *self)
     _part->view()->initScrollBars();
 }
 
+- (void)setActivationEventNumber:(int)num
+{
+    _part->setActivationEventNumber(num);
+}
+
 - (void)mouseDown:(NSEvent *)event
 {
     _part->mouseDown(event);
@@ -1570,6 +1575,11 @@ static HTMLFormElementImpl *formElementFromDOMElement(DOMElement *element)
 
 // [info draggingLocation] is in window coords
 
+- (BOOL)eventMayStartDrag:(NSEvent *)event
+{
+    return _part ? _part->eventMayStartDrag(event) : NO;
+}
+
 - (NSDragOperation)dragOperationForDraggingInfo:(id <NSDraggingInfo>)info
 {
     NSDragOperation op = NSDragOperationNone;
index 942b4dff4a9ab8bfe7fba8ae1e0cdb9c820aaf60..5ff93bda181c2dec452f26f2241092ad2a510b68 100644 (file)
@@ -1,3 +1,41 @@
+2004-06-30  Trey Matteson  <trey@apple.com>
+
+       Dragging within a web view should be allowed to start when the window isn't key.
+
+       A few months ago, Chris made this work, but it relied on the fact that all dragging
+       was done in WebKit.  When WebCore got involved in dragging, it was broken.  Now we
+       have a new scheme that gets it working again that properly involves WebCore.
+
+       The general idea is that when AK asks us whether to accept the first mouse and do
+       "delayed window ordering", we must consult WC to see if we might start a drag.  In
+       addition, instead of these drags in non-active windows being started as a special
+       case in WK, they go through the normal WK-WC drag machinery.  Finally to work in
+       frames we have to drill to the deepest hit view in acceptsFirstMouse, because previous
+       hacks to hitTest make the top-most WebHTMLView field all events for its view tree
+       (which leads to it fielding all acceptFirstMouse messages too).
+
+        Reviewed by John.
+
+        * WebCoreSupport.subproj/WebBridge.m:
+        (-[WebBridge mayStartDragAtEventLocation:]):  Glue change for new arg type.
+        * WebView.subproj/WebHTMLView.m:
+        (-[WebHTMLView _startDraggingImage:at:operation:event:sourceIsDHTML:DHTMLWroteData:]):
+       firstMouseDownEvent ivar is no longer needed.
+        (-[WebHTMLView _mayStartDragAtEventLocation:]):  Receives a location instead of a drag
+       event, since we need to do this work when we have no drag event.  This means the
+       check of the delay for text dragging is moved down to WebCore.
+        (-[WebHTMLView acceptsFirstMouse:]):  Respond based on whether we might do a drag.
+       This includes drilling to the deepest view the event hits, whereas we used to only
+       respond considering the topmost WebHTMLView.
+        (-[WebHTMLView shouldDelayWindowOrderingForEvent:]):  Ditto.
+        (-[WebHTMLView mouseDown:]):  Get rid of special case where some activating
+       mouseDown events weren't sent to WC.  We need to go through the whole pipeline
+       now to get a drag started properly.
+        (-[WebHTMLView mouseDragged:]):  Ditto, let WC start the drag.
+        (-[WebHTMLView mouseUp:]):  firstMouseDownEvent ivar is no longer needed.
+        * WebView.subproj/WebHTMLViewInternal.h:
+        * WebView.subproj/WebHTMLViewPrivate.h:
+
 2004-06-25  Trey Matteson  <trey@apple.com>
 
        Added new utility method.
index d1283aeeccb571943b5cd4823e449884eaa98891..5d63e76767792d2c3b29a1decd9f772570f29a2a 100644 (file)
@@ -1023,13 +1023,13 @@ static BOOL loggedObjectCacheSize = NO;
     [docView _handleAutoscrollForMouseDragged:event];
 }
 
-- (BOOL)mayStartDragWithMouseDragged:(NSEvent *)event
+- (BOOL)mayStartDragAtEventLocation:(NSPoint)location
 {
     WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
 
     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
 
-    return [docView _mayStartDragWithMouseDragged:event];
+    return [docView _mayStartDragAtEventLocation:location];
 }
 
 - (int)historyLength
index 205f0dad3bbf094e2cdad0e32215412acb78a124..20ef8f35093246783c2ff4920003632577dfa9be 100644 (file)
@@ -52,8 +52,6 @@
 
 #import <CoreGraphics/CGContextGState.h>
 
-#define TextDragDelay                    0.15
-
 // By imaging to a width a little wider than the available pixels,
 // thin pages will be scaled down a little, matching the way they
 // print in IE and Camino. This lets them use fewer sheets than they
@@ -781,9 +779,6 @@ static WebHTMLView *lastHitView = nil;
 
 - (BOOL)_startDraggingImage:(NSImage *)wcDragImage at:(NSPoint)wcDragLoc operation:(NSDragOperation)op event:(NSEvent *)mouseDraggedEvent sourceIsDHTML:(BOOL)srcIsDHTML DHTMLWroteData:(BOOL)dhtmlWroteData
 {
-    // Once we start a drag session we may not get a mouseup, so clear this out here as well as mouseUp:
-    _private->firstMouseDownEvent = nil;
-
     NSPoint mouseDownPoint = [self convertPoint:[_private->mouseDownEvent locationInWindow] fromView:nil];
     NSDictionary *element = [self elementAtPoint:mouseDownPoint];
 
@@ -919,9 +914,9 @@ static WebHTMLView *lastHitView = nil;
     [self _startAutoscrollTimer:event];
 }
 
-- (BOOL)_mayStartDragWithMouseDragged:(NSEvent *)mouseDraggedEvent
+- (BOOL)_mayStartDragAtEventLocation:(NSPoint)location
 {
-    NSPoint mouseDownPoint = [self convertPoint:[_private->mouseDownEvent locationInWindow] fromView:nil];
+    NSPoint mouseDownPoint = [self convertPoint:location fromView:nil];
     NSDictionary *mouseDownElement = [self elementAtPoint:mouseDownPoint];
 
     if ([mouseDownElement objectForKey: WebElementImageURLKey] != nil && 
@@ -936,7 +931,6 @@ static WebHTMLView *lastHitView = nil;
     }
     
     if ([[mouseDownElement objectForKey:WebElementIsSelectedKey] boolValue] &&
-        (([mouseDraggedEvent timestamp] - [_private->mouseDownEvent timestamp]) > TextDragDelay) &&
         (_private->dragSourceActionMask & WebDragSourceActionSelection)) {
         return YES;
     }
@@ -1729,22 +1723,37 @@ static WebHTMLView *lastHitView = nil;
     [[self _pluginController] destroyAllPlugins];
 }
 
-- (BOOL)_isSelectionEvent:(NSEvent *)event
-{
-    NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
-    return [[[self elementAtPoint:point] objectForKey:WebElementIsSelectedKey] boolValue];
-}
-
 - (BOOL)acceptsFirstMouse:(NSEvent *)event
 {
-    // We don't retain this because we never dispatch to it; we only check its value.
-    _private->firstMouseDownEvent = event;
-    return [self _isSelectionEvent:event];
+    // We hack AK's hitTest method to catch all events at the topmost WebHTMLView.  However, for
+    // the purposes of this method we want to really query the deepest view, so we forward to it.
+    forceRealHitTest = YES;
+    NSView *hitView = [[[self window] contentView] hitTest:[event locationInWindow]];
+    forceRealHitTest = NO;
+    
+    if ([hitView isKindOfClass:[self class]]) {
+        WebHTMLView *hitHTMLView = (WebHTMLView *)hitView;
+        [[hitHTMLView _bridge] setActivationEventNumber:[event eventNumber]];
+        return [[hitHTMLView _bridge] eventMayStartDrag:event];
+    } else {
+        return [hitView acceptsFirstMouse:event];
+    }
 }
 
 - (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent *)event
 {
-    return [self _isSelectionEvent:event];
+    // We hack AK's hitTest method to catch all events at the topmost WebHTMLView.  However, for
+    // the purposes of this method we want to really query the deepest view, so we forward to it.
+    forceRealHitTest = YES;
+    NSView *hitView = [[[self window] contentView] hitTest:[event locationInWindow]];
+    forceRealHitTest = NO;
+    
+    if ([hitView isKindOfClass:[self class]]) {
+        WebHTMLView *hitHTMLView = (WebHTMLView *)hitView;
+        return [[hitHTMLView _bridge] eventMayStartDrag:event];
+    } else {
+        return [hitView shouldDelayWindowOrderingForEvent:event];
+    }
 }
 
 - (void)mouseDown:(NSEvent *)event
@@ -1764,12 +1773,9 @@ static WebHTMLView *lastHitView = nil;
     // Don't do any mouseover while the mouse is down.
     [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_updateMouseoverWithFakeEvent) object:nil];
 
-    // Don't tell WebCore about the first mouse down event since only dragging can occur on the first mouse down.
-    if (_private->firstMouseDownEvent != event) {
-        // Let KHTML get a chance to deal with the event. This will call back to us
-        // to start the autoscroll timer if appropriate.
-        [[self _bridge] mouseDown:event];
-    }
+    // Let KHTML get a chance to deal with the event. This will call back to us
+    // to start the autoscroll timer if appropriate.
+    [[self _bridge] mouseDown:event];
 }
 
 - (void)dragImage:(NSImage *)dragImage
@@ -1793,14 +1799,7 @@ static WebHTMLView *lastHitView = nil;
 
 - (void)mouseDragged:(NSEvent *)event
 {
-    // If this drag started from a mouse down in an inactive window, we only allow it to drag out an existing selection, so don't tell WebCore about it.
-    if (_private->mouseDownEvent == _private->firstMouseDownEvent) {
-        // Handle the drag directly instead of getting callbacks from WebCore.
-        // FIXME - how does this play with DHTML dragging?
-        if ([self _mayStartDragWithMouseDragged:event]) {
-            [self _startDraggingImage:nil at:NSZeroPoint operation:NSDragOperationNone event:event sourceIsDHTML:NO DHTMLWroteData:NO];
-        }
-    } else if (!_private->ignoringMouseDraggedEvents) {
+    if (!_private->ignoringMouseDraggedEvents) {
         [[self _bridge] mouseDragged:event];
     }
 }
@@ -1983,7 +1982,6 @@ static WebHTMLView *lastHitView = nil;
 
 - (void)mouseUp:(NSEvent *)event
 {
-    _private->firstMouseDownEvent = nil;
     [self _stopAutoscrollTimer];
     [[self _bridge] mouseUp:event];
     [self _updateMouseoverWithFakeEvent];
index 7f7643d4912610fd99698de180161be37c8f288a..1aed5dc7992b04a507d425a3f5eff21483737082 100644 (file)
@@ -22,7 +22,6 @@
     BOOL subviewsSetAside;
 
     NSEvent *mouseDownEvent;
-    NSEvent *firstMouseDownEvent;
 
     NSURL *draggingImageURL;
     unsigned int dragSourceActionMask;
index 8d042f2c1f75b66c47279da2503d254b30cadddd..8260297ec2babcc49919b54bd9f905d94a2ccc31 100644 (file)
@@ -47,7 +47,7 @@
 - (NSImage *)_dragImageForLinkElement:(NSDictionary *)element;
 - (BOOL)_startDraggingImage:(NSImage *)dragImage at:(NSPoint)dragLoc operation:(NSDragOperation)op event:(NSEvent *)event sourceIsDHTML:(BOOL)flag DHTMLWroteData:(BOOL)dhtmlWroteData;
 - (void)_handleAutoscrollForMouseDragged:(NSEvent *)event;
-- (BOOL)_mayStartDragWithMouseDragged:(NSEvent *)event;
+- (BOOL)_mayStartDragAtEventLocation:(NSPoint)location;
 
 - (WebPluginController *)_pluginController;