2007-02-18 Oliver Hunt <oliver@apple.com>
authoroliver <oliver@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 18 Feb 2007 12:30:55 +0000 (12:30 +0000)
committeroliver <oliver@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 18 Feb 2007 12:30:55 +0000 (12:30 +0000)
        Reviewed by Adam.
WebCore:
        More drag and drop migration, now the entirety of the
        drag initiation logic has been rendered platform independent
        This has required a number of new interfaces, and a reasonable
        amount of logic migration.

        As a side effect, this patch also fixes rdar://problem/4945341

        There are some basic Qt stubs that should stop the build from failing,
        however the absence of ClipboardQt means any attempt to initiate a drag
        may cause a crash.

        * WebCore.exp:
           Exporting new symbols

        * WebCore.xcodeproj/project.pbxproj:
           New files

        * dom/Clipboard.cpp:
        (WebCore::Clipboard::canSaveAsWebArchive):
          Migrated from WebKit

        * dom/Clipboard.h:
          Added more methods to allow Clipboard to be used as a
          platform independent container for drag and drop

        * page/DragClient.h:
        (WebCore::DragClient::declareAndWriteDragImage):
          This is a mac only helper function, so i've made it have an empty implementation,
          that way we won't need a PLATFORM(MAC) block in SVGImageEmptyClients

        * page/DragController.cpp:
        (WebCore::DragController::dragExited):
        (WebCore::DragController::performDrag):
        (WebCore::DragController::tryDocumentDrag):
        (WebCore::DragController::tryDHTMLDrag):
          Using RefPtrs now
        (WebCore::getCachedImage):
        (WebCore::getImage):
          Helper functions
        (WebCore::dragLocForDHTMLDrag):
        (WebCore::dragLocForSelectionDrag):
        (WebCore::DragController::startDrag):
        (WebCore::DragController::doImageDrag):
        (WebCore::DragController::doSystemDrag):
          Logic that generates drag images and clipboard content, and
          initiates the actual system drag operation

        * page/DragController.h:
          Method and variable declarations

        * page/EventHandler.cpp:
        (WebCore::EventHandler::handleDrag):
          handleDrag is now platform independent
        (WebCore::EventHandler::handleTextInputEvent):
           formatting

        * page/EventHandler.h:
        (WebCore::EventHandler::eventLoopHandleMouseDragged):
          Forgot to define this stub function

        * page/Frame.h:
          Declaring dragImageForSelection to provide drag image for selected content

        * page/mac/DragControllerMac.mm:
          Defining drag images control vars

        * page/mac/EventHandlerMac.mm:
        (WebCore::EventHandler::createDraggingClipboard):
          Migrated old clipboard creation to here

        * page/mac/FrameMac.mm:
        (WebCore::Frame::dragImageForSelection):
          Wrap FrameMac::selectionImage

        * page/qt/DragControllerQt.cpp:
          Defining drag images control vars

        * page/qt/EventHandlerQt.cpp:
        (WebCore::EventHandler::createDraggingClipboard):
          stub

        * page/qt/FrameQt.cpp:
        (WebCore::Frame::dragImageForSelection):
          stub

        * platform/DragImage.cpp: Added.
        (WebCore::fitDragImageToMaxSize):
        (WebCore::createDragImageForSelection):
           Platform independent processing for drag images

        * platform/DragImage.h: Added.
           Declaring typedefs and wrapper functions to abstract the handling
           of drag images

        * platform/Pasteboard.h:
          Declaring extracted writeURL and writeSelection methods

        * platform/graphics/svg/SVGImageEmptyClients.h:
        (WebCore::SVGEmptyDragClient::willPerformDragSourceAction):
        (WebCore::SVGEmptyDragClient::startDrag):
        (WebCore::SVGEmptyDragClient::createDragImageForLink):
          Stubs FTW!

        * platform/mac/ClipboardMac.h:
        (WebCore::ClipboardMac::pasteboard):
          Provide accessor for underlying NSPasteboard

        * platform/mac/ClipboardMac.mm:
        (WebCore::ClipboardMac::hasData):
        (WebCore::ClipboardMac::writeRange):
        (WebCore::ClipboardMac::writeURL):
        (WebCore::ClipboardMac::declareAndWriteDragImage):
        (WebCore::ClipboardMac::createDragImage):
           Implemented new Clipboarid functionality.
        (WebCore::ClipboardMac::dragNSImage):
           Made this a const method

        * platform/mac/DragImageMac.mm: Added.
        (WebCore::dragImageSize):
        (WebCore::deleteDragImage):
        (WebCore::scaleDragImage):
        (WebCore::dissolveDragImageToFraction):
        (WebCore::createDragImageFromImage):
        (WebCore::createDragImageIconForCachedImage):
           Implemented platform specific DragImage functions

        * platform/mac/PasteboardMac.mm:
        (WebCore::writeSelection):
        (WebCore::Pasteboard::writeSelection):
        (WebCore::writeURL):
        (WebCore::Pasteboard::writeURL):
           Extracted member implementations of these functions, so that
           Clipboard could also make use of this functionality.
           Pasteboard methods now call the new non-member implementations.
           Also fixed implementations to respect the list of requested types.

        * platform/qt/DragImageQt.cpp: Added.
        (WebCore::dragImageSize):
        (WebCore::deleteDragImage):
        (WebCore::scaleDragImage):
        (WebCore::dissolveDragImageToFraction):
        (WebCore::createDragImageFromImage):
        (WebCore::createDragImageIconForCachedImage):
          Stubs

WebKit:
        Moving the drag initiation logic to WebCore.
        The redundant code in webkit will be moved out in a later patch.

        * WebCoreSupport/WebDragClient.h:
        * WebCoreSupport/WebDragClient.mm:
        (getTopHTMLView):
          Helper function
        (WebDragClient::willPerformDragSourceAction):
        (WebDragClient::startDrag):
        (WebDragClient::createDragImageForLink):
          Implemented new DragClient methods
        (WebDragClient::declareAndWriteDragImage):
          Helper function for the Mac to allow new drag and drop
          code to match behaviour

        * WebView/WebHTMLView.mm:
        (-[WebHTMLView _dragImageForURL:withLabel:]):
        (-[WebHTMLView _dragImageForLinkElement:]):
          Refactoring old _dragImageForLinkElement function so that
          the link drag image can be created with just a URL and label,
          rather than requiring the original element
        (-[WebHTMLView dragImage:at:offset:event:pasteboard:source:slideBack:]):
          Removed logic that is no longer necessary
        (-[WebHTMLView _mouseDownEvent]):
          The WebDragClient may need the original mouseDownEvent of a drag when initiating
          a drag
        * WebView/WebHTMLViewInternal.h:
          Declaring _mouseDownEvent

        * WebView/WebHTMLViewPrivate.h:
          Declaring _dragImageForURL

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

32 files changed:
WebCore/ChangeLog
WebCore/WebCore.exp
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/dom/Clipboard.cpp
WebCore/dom/Clipboard.h
WebCore/page/DragClient.h
WebCore/page/DragController.cpp
WebCore/page/DragController.h
WebCore/page/EventHandler.cpp
WebCore/page/EventHandler.h
WebCore/page/Frame.h
WebCore/page/mac/DragControllerMac.mm
WebCore/page/mac/EventHandlerMac.mm
WebCore/page/mac/FrameMac.mm
WebCore/page/qt/DragControllerQt.cpp
WebCore/page/qt/EventHandlerQt.cpp
WebCore/page/qt/FrameQt.cpp
WebCore/platform/DragImage.cpp [new file with mode: 0644]
WebCore/platform/DragImage.h [new file with mode: 0644]
WebCore/platform/Pasteboard.h
WebCore/platform/graphics/svg/SVGImageEmptyClients.h
WebCore/platform/mac/ClipboardMac.h
WebCore/platform/mac/ClipboardMac.mm
WebCore/platform/mac/DragImageMac.mm [new file with mode: 0644]
WebCore/platform/mac/PasteboardMac.mm
WebCore/platform/qt/DragImageQt.cpp [new file with mode: 0644]
WebKit/ChangeLog
WebKit/WebCoreSupport/WebDragClient.h
WebKit/WebCoreSupport/WebDragClient.mm
WebKit/WebView/WebHTMLView.mm
WebKit/WebView/WebHTMLViewInternal.h
WebKit/WebView/WebHTMLViewPrivate.h

index 019d82f..0b073a9 100644 (file)
@@ -1,3 +1,152 @@
+2007-02-18  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Adam.
+
+        More drag and drop migration, now the entirety of the
+        drag initiation logic has been rendered platform independent
+        This has required a number of new interfaces, and a reasonable
+        amount of logic migration.
+
+        As a side effect, this patch also fixes rdar://problem/4945341
+
+        There are some basic Qt stubs that should stop the build from failing,
+        however the absence of ClipboardQt means any attempt to initiate a drag 
+        may cause a crash.
+
+        * WebCore.exp:
+           Exporting new symbols
+
+        * WebCore.xcodeproj/project.pbxproj:
+           New files
+
+        * dom/Clipboard.cpp:
+        (WebCore::Clipboard::canSaveAsWebArchive):
+          Migrated from WebKit
+
+        * dom/Clipboard.h:
+          Added more methods to allow Clipboard to be used as a 
+          platform independent container for drag and drop
+
+        * page/DragClient.h:
+        (WebCore::DragClient::declareAndWriteDragImage):
+          This is a mac only helper function, so i've made it have an empty implementation,
+          that way we won't need a PLATFORM(MAC) block in SVGImageEmptyClients
+
+        * page/DragController.cpp:
+        (WebCore::DragController::dragExited):
+        (WebCore::DragController::performDrag):
+        (WebCore::DragController::tryDocumentDrag): 
+        (WebCore::DragController::tryDHTMLDrag):
+          Using RefPtrs now
+        (WebCore::getCachedImage):
+        (WebCore::getImage):
+          Helper functions                   
+        (WebCore::dragLocForDHTMLDrag):
+        (WebCore::dragLocForSelectionDrag):
+        (WebCore::DragController::startDrag):
+        (WebCore::DragController::doImageDrag):
+        (WebCore::DragController::doSystemDrag):
+          Logic that generates drag images and clipboard content, and
+          initiates the actual system drag operation
+
+        * page/DragController.h:
+          Method and variable declarations
+
+        * page/EventHandler.cpp:
+        (WebCore::EventHandler::handleDrag):
+          handleDrag is now platform independent
+        (WebCore::EventHandler::handleTextInputEvent):
+           formatting
+
+        * page/EventHandler.h:
+        (WebCore::EventHandler::eventLoopHandleMouseDragged):
+          Forgot to define this stub function 
+
+        * page/Frame.h:
+          Declaring dragImageForSelection to provide drag image for selected content
+
+        * page/mac/DragControllerMac.mm:
+          Defining drag images control vars
+
+        * page/mac/EventHandlerMac.mm:
+        (WebCore::EventHandler::createDraggingClipboard):
+          Migrated old clipboard creation to here
+
+        * page/mac/FrameMac.mm:
+        (WebCore::Frame::dragImageForSelection):
+          Wrap FrameMac::selectionImage
+
+        * page/qt/DragControllerQt.cpp:
+          Defining drag images control vars
+
+        * page/qt/EventHandlerQt.cpp:
+        (WebCore::EventHandler::createDraggingClipboard):
+          stub
+
+        * page/qt/FrameQt.cpp:
+        (WebCore::Frame::dragImageForSelection):
+          stub
+
+        * platform/DragImage.cpp: Added.
+        (WebCore::fitDragImageToMaxSize):
+        (WebCore::createDragImageForSelection):
+           Platform independent processing for drag images
+
+        * platform/DragImage.h: Added.
+           Declaring typedefs and wrapper functions to abstract the handling
+           of drag images 
+
+        * platform/Pasteboard.h:
+          Declaring extracted writeURL and writeSelection methods
+
+        * platform/graphics/svg/SVGImageEmptyClients.h:
+        (WebCore::SVGEmptyDragClient::willPerformDragSourceAction):
+        (WebCore::SVGEmptyDragClient::startDrag):
+        (WebCore::SVGEmptyDragClient::createDragImageForLink):
+          Stubs FTW!
+
+        * platform/mac/ClipboardMac.h:
+        (WebCore::ClipboardMac::pasteboard):
+          Provide accessor for underlying NSPasteboard
+
+        * platform/mac/ClipboardMac.mm:
+        (WebCore::ClipboardMac::hasData):
+        (WebCore::ClipboardMac::writeRange):
+        (WebCore::ClipboardMac::writeURL):
+        (WebCore::ClipboardMac::declareAndWriteDragImage):
+        (WebCore::ClipboardMac::createDragImage):
+           Implemented new Clipboarid functionality.
+        (WebCore::ClipboardMac::dragNSImage):
+           Made this a const method
+
+        * platform/mac/DragImageMac.mm: Added.
+        (WebCore::dragImageSize):
+        (WebCore::deleteDragImage):
+        (WebCore::scaleDragImage):
+        (WebCore::dissolveDragImageToFraction):
+        (WebCore::createDragImageFromImage):
+        (WebCore::createDragImageIconForCachedImage):
+           Implemented platform specific DragImage functions
+
+        * platform/mac/PasteboardMac.mm:
+        (WebCore::writeSelection):
+        (WebCore::Pasteboard::writeSelection):
+        (WebCore::writeURL):
+        (WebCore::Pasteboard::writeURL):
+           Extracted member implementations of these functions, so that
+           Clipboard could also make use of this functionality.
+           Pasteboard methods now call the new non-member implementations.
+           Also fixed implementations to respect the list of requested types.
+
+        * platform/qt/DragImageQt.cpp: Added.
+        (WebCore::dragImageSize):
+        (WebCore::deleteDragImage):
+        (WebCore::scaleDragImage):
+        (WebCore::dissolveDragImageToFraction):
+        (WebCore::createDragImageFromImage):
+        (WebCore::createDragImageIconForCachedImage):  
+          Stubs
+
 2007-02-17  David Hyatt  <hyatt@apple.com>
 
         Fix textarea resizers to not fill with black by making sure the fill color starts off as
index 4e49e6b..5136c1c 100644 (file)
@@ -197,6 +197,7 @@ __ZN7WebCore12AtomicString3addEPNS_10StringImplE
 __ZN7WebCore12EventHandler10mouseMovedEP7NSEvent
 __ZN7WebCore12EventHandler10wheelEventEP7NSEvent
 __ZN7WebCore12EventHandler12mouseDraggedEP7NSEvent
+__ZN7WebCore12EventHandler14currentNSEventEv
 __ZN7WebCore12EventHandler20handleTextInputEventERKNS_6StringEPNS_5EventEbb
 __ZN7WebCore12EventHandler20hitTestResultAtPointERKNS_8IntPointEb
 __ZN7WebCore12EventHandler20sendContextMenuEventERKNS_18PlatformMouseEventE
index a04d1e9..9171774 100644 (file)
                A7CA595D0B27BD9E00FA021D /* DragController.h in Headers */ = {isa = PBXBuildFile; fileRef = A7CA595B0B27BD9E00FA021D /* DragController.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A7CA595E0B27BD9E00FA021D /* DragController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7CA595C0B27BD9E00FA021D /* DragController.cpp */; };
                A7CA59630B27C1F200FA021D /* DragClient.h in Headers */ = {isa = PBXBuildFile; fileRef = A7CA59620B27C1F200FA021D /* DragClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               A7CFB3D10B7ED10A0070C32D /* DragImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7CFB3CF0B7ED10A0070C32D /* DragImage.cpp */; };
+               A7CFB3D20B7ED10A0070C32D /* DragImage.h in Headers */ = {isa = PBXBuildFile; fileRef = A7CFB3D00B7ED10A0070C32D /* DragImage.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               A7CFB3D50B7ED1180070C32D /* DragImageMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = A7CFB3D40B7ED1180070C32D /* DragImageMac.mm */; };
                A7D3C5240B576B4B002CA450 /* PasteboardHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D3C5230B576B4B002CA450 /* PasteboardHelper.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A809F1470B73793A002E4D7F /* RenderSVGGradientStop.h in Headers */ = {isa = PBXBuildFile; fileRef = A809F1450B73793A002E4D7F /* RenderSVGGradientStop.h */; };
                A809F1480B73793B002E4D7F /* RenderSVGGradientStop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A809F1460B73793A002E4D7F /* RenderSVGGradientStop.cpp */; };
                A79546420B5C4CB4007B438F /* DragData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DragData.cpp; sourceTree = "<group>"; };
                A7B6E69D0B291A9600D0529F /* DragData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DragData.h; sourceTree = "<group>"; };
                A7CA595B0B27BD9E00FA021D /* DragController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DragController.h; sourceTree = "<group>"; };
-               A7CA595C0B27BD9E00FA021D /* DragController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DragController.cpp; sourceTree = "<group>"; };
+               A7CA595C0B27BD9E00FA021D /* DragController.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; path = DragController.cpp; sourceTree = "<group>"; };
                A7CA59620B27C1F200FA021D /* DragClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DragClient.h; sourceTree = "<group>"; };
+               A7CFB3CF0B7ED10A0070C32D /* DragImage.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DragImage.cpp; sourceTree = "<group>"; };
+               A7CFB3D00B7ED10A0070C32D /* DragImage.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DragImage.h; sourceTree = "<group>"; };
+               A7CFB3D40B7ED1180070C32D /* DragImageMac.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = DragImageMac.mm; sourceTree = "<group>"; };
                A7D3C5230B576B4B002CA450 /* PasteboardHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PasteboardHelper.h; sourceTree = "<group>"; };
                A809F1450B73793A002E4D7F /* RenderSVGGradientStop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGGradientStop.h; sourceTree = "<group>"; };
                A809F1460B73793A002E4D7F /* RenderSVGGradientStop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGGradientStop.cpp; sourceTree = "<group>"; };
                6582A14809999D6C00BEEB6D /* mac */ = {
                        isa = PBXGroup;
                        children = (
+                               A7CFB3D40B7ED1180070C32D /* DragImageMac.mm */,
                                A795463D0B5C4C80007B438F /* DragDataMac.mm */,
                                06027CB20B1CC03D00884B2D /* ContextMenuItemMac.mm */,
                                65A640F00533BB1F0085E777 /* BlockExceptions.h */,
                                F587853C02DE375901EA4122 /* DeprecatedValueListImpl.cpp */,
                                F587853B02DE375901EA4122 /* DeprecatedValueListImpl.h */,
                                A7B6E69D0B291A9600D0529F /* DragData.h */,
+                               A7CFB3D00B7ED10A0070C32D /* DragImage.h */,
+                               A7CFB3CF0B7ED10A0070C32D /* DragImage.cpp */,
                                934FE9E40B5CA539003E4A73 /* FileChooser.cpp */,
                                066C772A0AB603B700238CC4 /* FileChooser.h */,
                                BC6D6DD009AF906600F59759 /* Font.cpp */,
                        isa = PBXHeadersBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               A7CFB3D20B7ED10A0070C32D /* DragImage.h in Headers */,
                                A7D3C5240B576B4B002CA450 /* PasteboardHelper.h in Headers */,
                                A718760E0B2A120100A16ECE /* DragActions.h in Headers */,
                                A7B6E69F0B291A9600D0529F /* DragData.h in Headers */,
                0867D690FE84028FC02AAC07 /* Project object */ = {
                        isa = PBXProject;
                        buildConfigurationList = 149C284308902B11008A9EFC /* Build configuration list for PBXProject "WebCore" */;
+                       compatibilityVersion = "Xcode 2.4";
                        hasScannedForEncodings = 1;
                        knownRegions = (
                                English,
                        productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
                        projectDirPath = "";
                        projectRoot = "";
+                       shouldCheckCompatibility = 1;
                        targets = (
                                93F198A508245E59001E9ABC /* WebCore */,
                                DD041FBE09D9DDBE0010AF2A /* Derived Sources */,
                                933A142E0B7D188600A53FFD /* TextEvent.cpp in Sources */,
                                933A14AA0B7D1D0900A53FFD /* DOMTextEvent.mm in Sources */,
                                933A14B80B7D1D5200A53FFD /* JSTextEvent.cpp in Sources */,
+                               A7CFB3D10B7ED10A0070C32D /* DragImage.cpp in Sources */,
+                               A7CFB3D50B7ED1180070C32D /* DragImageMac.mm in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 7b6a5db..16ceeb3 100755 (executable)
 #include "config.h"
 #include "Clipboard.h"
 
+#include "DOMImplementation.h"
+#include "Frame.h"
+#include "FrameLoader.h"
+#include "Image.h"
+#include "PlugInInfoStore.h"
+
 namespace WebCore {
 
+bool Clipboard::canSaveAsWebArchive(Frame* frame)
+{
+    ASSERT(frame);
+    String mimeType = frame->loader()->responseMIMEType();
+    
+    return !(DOMImplementation::isTextMIMEType(mimeType) ||
+             Image::supportsType(mimeType) ||
+             PlugInInfoStore::supportsMIMEType(mimeType));
+}
+    
 void Clipboard::setAccessPolicy(ClipboardAccessPolicy policy)
 {
     // once you go numb, can never go back
index d1f3d88..0a33532 100644 (file)
 #include "AtomicString.h"
 #include "ClipboardAccessPolicy.h"
 #include "DragActions.h"
+#include "DragImage.h"
 #include "Node.h"
 #include "Shared.h"
 
 namespace WebCore {
 
     class CachedImage;
+    class Element;
+    class Frame;
+    class Image;
     class IntPoint;
+    class KURL;
+    class Range;
+    class String;
 
     // State available during IE's events for drag and drop and copy/paste
     class Clipboard : public Shared<Clipboard> {
@@ -65,7 +72,15 @@ namespace WebCore {
         virtual void setDragImage(CachedImage*, const IntPoint&) = 0;
         virtual Node* dragImageElement() = 0;
         virtual void setDragImageElement(Node*, const IntPoint&) = 0;
+        
+        //Provides the DOM specified 
+        virtual DragImageRef createDragImage(IntPoint& dragLoc) const = 0;
+        virtual void declareAndWriteDragImage(Element*, const KURL&, const String& title, Frame*) = 0;
+        virtual void writeURL(const KURL&, const String&, Frame*) = 0;
+        virtual void writeRange(Range*, Frame*) = 0;
 
+        virtual bool hasData() = 0;
+        
         void setAccessPolicy(ClipboardAccessPolicy);
 
         bool sourceOperation(DragOperation&) const;
@@ -74,6 +89,7 @@ namespace WebCore {
         void setDestinationOperation(DragOperation);
         
         void setDragHasStarted() { m_dragStarted = true; }
+        static bool canSaveAsWebArchive(Frame*);
     protected:
         ClipboardAccessPolicy policy() const { return m_policy; }
         bool dragStarted() const { return m_dragStarted; }
index c39e582..c13f056 100644 (file)
 #define DragClient_h
 
 #include "DragActions.h"
+#include "DragImage.h"
 #include "IntPoint.h"
 
-namespace WebCore {
+#if PLATFORM(MAC)
+#ifdef __OBJC__
+@class DOMElement;
+@class NSURL;
+@class NSString;
+@class NSPasteboard;
+#else
+class DOMElement;
+class NSURL;
+class NSString;
+class NSPasteboard;
+#endif
+#endif
 
+namespace WebCore {
+    
+    class Clipboard;
     class DragData;
+    class Frame;
+    class Image;
+    class HTMLImageElement;
     
     class DragClient {
     public:
         virtual void willPerformDragDestinationAction(DragDestinationAction, DragData*) = 0;
+        virtual void willPerformDragSourceAction(DragSourceAction, const IntPoint&, Clipboard*) = 0;
         virtual DragDestinationAction actionMaskForDrag(DragData*) = 0;
-        virtual void dragControllerDestroyed() = 0;
-        
         //We work in window rather than view coordinates here
         virtual DragSourceAction dragSourceActionMaskForPoint(const IntPoint& windowPoint) = 0;
-
+        
+        virtual void startDrag(DragImageRef dragImage, const IntPoint& dragImageOrigin, const IntPoint& eventPos, Clipboard*, Frame*, bool linkDrag = false) = 0;
+        virtual DragImageRef createDragImageForLink(KURL&, const String& label, Frame*) = 0;
+        
+        virtual void dragControllerDestroyed() = 0;
+#if PLATFORM(MAC)
+        //Mac specific helper functions to allow access to functionality in webkit -- such as 
+        //web archives and NSPasteboard extras 
+        //not abstract as that would require another #if PLATFORM(MAC) for the SVGImage client empty impl
+        virtual void declareAndWriteDragImage(NSPasteboard*, DOMElement*, NSURL*, NSString*, Frame*, bool canSaveAsWebArchive) {};
+#endif
+        
         virtual ~DragClient() {};
     };
     
index ddfc54f..2a1c855 100644 (file)
 #include "EventHandler.h"
 #include "DragClient.h"
 #include "DragData.h"
+#include "FloatRect.h"
 #include "Frame.h"
 #include "FrameLoader.h"
 #include "FrameView.h"
 #include "HTMLAnchorElement.h"
+#include "Image.h"
 #include "markup.h"
 #include "MoveSelectionCommand.h"
 #include "Node.h"
 #include "Page.h"
+#include "PlugInInfoStore.h"
+#include "RenderImage.h"
 #include "ReplaceSelectionCommand.h"
 #include "ResourceRequest.h"
 #include "SelectionController.h"
 #include "Settings.h"
 #include "SystemTime.h"
 #include "Text.h"
-#include "wtf/RefPtr.h"
+#include <wtf/RefPtr.h>
 
 namespace WebCore {
 
@@ -167,7 +171,7 @@ void DragController::dragExited(DragData* dragData)
     ASSERT(dragData);
     Frame* mainFrame = m_page->mainFrame();
     
-    if (mainFrame->view()) {
+    if (RefPtr<FrameView> v = mainFrame->view()) {
         ClipboardAccessPolicy policy = mainFrame->loader()->baseURL().isLocalFile() ? ClipboardReadable : ClipboardTypesReadable;
         RefPtr<Clipboard> clipboard = dragData->createClipboard(policy);
         clipboard->setSourceOperation(dragData->draggingSourceOperationMask());
@@ -191,7 +195,7 @@ bool DragController::performDrag(DragData* dragData)
     if (m_isHandlingDrag) {
         ASSERT(m_dragDestinationAction & DragDestinationActionDHTML);
         m_client->willPerformDragDestinationAction(DragDestinationActionDHTML, dragData);
-        Frame* mainFrame = m_page->mainFrame();
+        RefPtr<Frame> mainFrame = m_page->mainFrame();
         if (mainFrame->view()) {
             // Sending an event can result in the destruction of the view and part.
             RefPtr<Clipboard> clipboard = dragData->createClipboard(ClipboardReadable);
@@ -251,7 +255,7 @@ DragOperation DragController::tryDocumentDrag(DragData* dragData, DragDestinatio
         operation = tryDHTMLDrag(dragData);
     m_isHandlingDrag = operation != DragOperationNone; 
 
-    FrameView *frameView = 0;
+    RefPtr<FrameView> frameView = 0;
     if (!m_document || !(frameView = m_document->view()))
         return operation;
     
@@ -386,8 +390,9 @@ DragOperation DragController::tryDHTMLDrag(DragData* dragData)
 {   
     ASSERT(dragData);
     DragOperation op = DragOperationNone;
-    Frame* frame = m_page->mainFrame();
-    if (!frame->view())
+    RefPtr<Frame> frame = m_page->mainFrame();
+    RefPtr<FrameView> viewProtector = frame->view();
+    if (!viewProtector)
         return DragOperationNone;
     
     ClipboardAccessPolicy policy = frame->loader()->baseURL().isLocalFile() ? ClipboardReadable : ClipboardTypesReadable;
@@ -448,5 +453,225 @@ bool DragController::mayStartDragAtEventLocation(const Frame* frame, const IntPo
     return false;
 
 }
-
+    
+static CachedImage* getCachedImage(Element* element)
+{
+    ASSERT(element);
+    RenderObject* renderer = element->renderer();
+    if (!renderer || !renderer->isImage()) 
+        return 0;
+    RenderImage* image = static_cast<RenderImage*>(renderer);
+    return image->cachedImage();
+}
+    
+static Image* getImage(Element* element)
+{
+    ASSERT(element);
+    RenderObject* renderer = element->renderer();
+    if (!renderer || !renderer->isImage()) 
+        return 0;
+    
+    RenderImage* image = static_cast<RenderImage*>(renderer);
+    if (image->cachedImage() && !image->cachedImage()->isErrorImage())
+        return image->cachedImage()->image();
+    return 0;
+}
+    
+static void prepareClipboardForImageDrag(Frame* src, Clipboard* clipboard, Element* node, const KURL& linkURL, const KURL& imageURL, const String& label)
+{
+    RefPtr<Range> range = src->document()->createRange();
+    ExceptionCode ec = 0;
+    range->selectNode(node, ec);
+    ASSERT(ec == 0);
+    src->selectionController()->setSelection(Selection(range.get(), DOWNSTREAM));           
+    clipboard->declareAndWriteDragImage(node, !linkURL.isEmpty() ? linkURL : imageURL, label, src);
+}
+    
+static IntPoint dragLocForDHTMLDrag(const IntPoint& mouseDraggedPoint, const IntPoint& dragOrigin, const IntPoint& dragImageOffset, bool isLinkImage)
+{
+    // dragImageOffset is the cursor position relative to the lower-left corner of the image.
+#if PLATFORM(MAC) 
+    // We add in the Y dimension because we are a flipped view, so adding moves the image down. 
+    const int yOffset = dragImageOffset.y();
+#else
+    const int yOffset = -dragImageOffset.y();
+#endif
+    
+    if (isLinkImage)
+        return IntPoint(mouseDraggedPoint.x() - dragImageOffset.x(), mouseDraggedPoint.y() + yOffset);
+    
+    return IntPoint(dragOrigin.x() - dragImageOffset.x(), dragOrigin.y() + yOffset);
+}
+    
+static IntPoint dragLocForSelectionDrag(Frame* src)
+{
+    IntRect draggingRect = enclosingIntRect(src->visibleSelectionRect());
+    int xpos = draggingRect.right();
+    xpos = draggingRect.x() < xpos ? draggingRect.x() : xpos;
+    int ypos = draggingRect.bottom();
+#if PLATFORM(MAC)
+    // Deal with flipped coordinates on Mac
+    ypos = draggingRect.y() > ypos ? draggingRect.y() : ypos;
+#else
+    ypos = draggingRect.y() < ypos ? draggingRect.y() : ypos;
+#endif
+    return IntPoint(xpos, ypos);
+}
+    
+bool DragController::startDrag(Frame* src, Clipboard* clipboard, DragOperation srcOp, const PlatformMouseEvent& dragEvent, const IntPoint& dragOrigin, bool isDHTMLDrag)
+{    
+    ASSERT(src);
+    ASSERT(clipboard);
+    
+    if (!src->view() || !src->renderer())
+        return false;
+    
+    HitTestResult dragSource = HitTestResult(dragOrigin);
+    dragSource = src->eventHandler()->hitTestResultAtPoint(dragOrigin, true);
+    KURL linkURL = dragSource.absoluteLinkURL();
+    KURL imageURL = dragSource.absoluteImageURL();
+    bool isSelected = dragSource.isSelected();
+    
+    IntPoint mouseDraggedPoint = src->view()->windowToContents(dragEvent.pos());
+    
+    m_draggingImageURL = KURL();
+    m_dragOperation = srcOp;
+    
+    DragImageRef dragImage = 0;
+    IntPoint dragLoc(0, 0);
+    IntPoint dragImageOffset(0, 0);
+    
+    if (isDHTMLDrag) 
+        dragImage = clipboard->createDragImage(dragImageOffset);
+    
+    // We allow DHTML/JS to set the drag image, even if its a link, image or text we're dragging.
+    // This is in the spirit of the IE API, which allows overriding of pasteboard data and DragOp.
+    if (dragImage) {
+        dragLoc = dragLocForDHTMLDrag(mouseDraggedPoint, dragOrigin, dragImageOffset, !linkURL.isEmpty());
+        m_dragOffset = dragImageOffset;
+    }
+    
+    bool startedDrag = true; // optimism - we almost always manage to start the drag
+    
+    Node* node = dragSource.innerNonSharedNode();
+    
+    if (!imageURL.isEmpty() && node && node->isElementNode()
+            && getImage(static_cast<Element*>(node)) 
+            && (m_dragSourceAction & DragSourceActionImage)) {
+        Element* element = static_cast<Element*>(node);
+        if (!clipboard->hasData()) {
+            m_draggingImageURL = imageURL; 
+            prepareClipboardForImageDrag(src, clipboard, element, linkURL, imageURL, dragSource.altDisplayString());
+        }
+        
+        m_client->willPerformDragSourceAction(DragSourceActionImage, dragOrigin, clipboard);
+        
+        if (!dragImage) {
+            IntRect imageRect = dragSource.imageRect();
+            imageRect.setLocation(m_page->mainFrame()->view()->windowToContents(src->view()->contentsToWindow(imageRect.location())));
+            doImageDrag(element, dragOrigin, dragSource.imageRect(), clipboard, src, m_dragOffset);
+        } else 
+            // DHTML defined drag image
+            doSystemDrag(dragImage, dragLoc, dragOrigin, clipboard, src, false);
+
+    } else if (!linkURL.isEmpty() && (m_dragSourceAction & DragSourceActionLink)) {
+        if (!clipboard->hasData()) 
+            clipboard->writeURL(linkURL, dragSource.textContent(), src);
+        
+        m_client->willPerformDragSourceAction(DragSourceActionLink, dragOrigin, clipboard);
+        if (!dragImage) {
+            dragImage = m_client->createDragImageForLink(linkURL, dragSource.textContent(), src);
+            IntSize size = dragImageSize(dragImage);
+            m_dragOffset = IntPoint(-size.width() / 2, -LinkDragBorderInset);
+            dragLoc = IntPoint(mouseDraggedPoint.x() + m_dragOffset.x(), mouseDraggedPoint.y() + m_dragOffset.y());
+        } 
+        doSystemDrag(dragImage, dragLoc, src->view()->contentsToWindow(mouseDraggedPoint), clipboard, src, true);
+    } else if (isSelected && (m_dragSourceAction & DragSourceActionSelection)) {
+        RefPtr<Range> selectionRange = src->selectionController()->toRange();
+        ASSERT(selectionRange);
+        if (!clipboard->hasData()) 
+            clipboard->writeRange(selectionRange.get(), src);
+        m_client->willPerformDragSourceAction(DragSourceActionSelection, dragOrigin, clipboard);
+        if (!dragImage) {
+            dragImage = createDragImageForSelection(src);
+            dragLoc = dragLocForSelectionDrag(src);
+            m_dragOffset = IntPoint((int)(dragOrigin.x() - dragLoc.x()), (int)(dragOrigin.y() - dragLoc.y()));
+        }
+        doSystemDrag(dragImage, dragLoc, dragOrigin, clipboard, src, false);
+    } else if (isDHTMLDrag) {
+        ASSERT(m_dragSourceAction & DragSourceActionDHTML);
+        m_client->willPerformDragSourceAction(DragSourceActionDHTML, dragOrigin, clipboard);
+        doSystemDrag(dragImage, dragLoc, dragOrigin, clipboard, src, false);
+    } else {
+        // Only way I know to get here is if to get here is if the original element clicked on in the mousedown is no longer
+        // under the mousedown point, so linkURL, imageURL and isSelected are all false/empty.
+        startedDrag = false;
+    }
+    
+    if (dragImage)
+        deleteDragImage(dragImage);
+    return startedDrag;
+}
+    
+void DragController::doImageDrag(Element* element, const IntPoint& dragOrigin, const IntRect& rect, Clipboard* clipboard, Frame* frame, IntPoint& dragImageOffset)
+{
+    IntPoint mouseDownPoint = dragOrigin;
+    DragImageRef dragImage;
+    IntPoint origin;
+    
+    Image* image = getImage(element);
+    if (image && image->size().height() * image->size().width() <= MaxOriginalImageArea) {
+        IntSize originalSize = rect.size();
+        origin = rect.location();
+        
+        dragImage = createDragImageFromImage(image);
+    
+        IntSize newSize;
+        if (dragImage) {
+            dragImage = fitDragImageToMaxSize(dragImage, MaxDragImageSize);
+            dragImage = dissolveDragImageToFraction(dragImage, DragImageAlpha);
+            newSize = dragImageSize(dragImage);
+        }
+        
+        // Properly orient the drag image and orient it differently if it's smaller than the original
+        float scale = newSize.width() / (float)originalSize.width();
+        float dx = origin.x() - mouseDownPoint.x();
+        dx *= scale;
+        origin.setX((int)(dx + 0.5));
+#if PLATFORM(MAC)
+        //Compensate for accursed flipped coordinates in cocoa
+        origin.setY(origin.y() + originalSize.height());
+#endif
+        float dy = origin.y() - mouseDownPoint.y();
+        dy *= scale;
+        origin.setY((int)(dy + 0.5));
+    } else {
+        dragImage = createDragImageIconForCachedImage(getCachedImage(element));
+        if (dragImage)
+            origin = IntPoint(DragIconRightInset - dragImageSize(dragImage).width(), DragIconBottomInset);
+    }
+    
+    dragImageOffset.setX(mouseDownPoint.x() + origin.x());
+    dragImageOffset.setY(mouseDownPoint.y() + origin.y());
+    doSystemDrag(dragImage, dragImageOffset, dragOrigin, clipboard, frame, false);
+    
+    deleteDragImage(dragImage);
+}
+    
+void DragController::doSystemDrag(DragImageRef image, const IntPoint& dragLoc, const IntPoint& eventPos, Clipboard* clipboard, Frame* frame, bool forLink)
+{
+    m_didInitiateDrag = true;
+    m_dragInitiator = frame->document();
+    // Protect this frame and view, as a load may occur mid drag and attempt to unload this frame
+    RefPtr<Frame> frameProtector = m_page->mainFrame();
+    RefPtr<FrameView> viewProtector = frameProtector->view();
+    m_client->startDrag(image, viewProtector->windowToContents(frame->view()->contentsToWindow(dragLoc)), eventPos, clipboard, frameProtector.get(), forLink);
+    
+    // Drag has ended, dragEnded *should* have been called, however it is possible  
+    // for the UIDelegate to take over the drag, and fail to send the appropriate
+    // drag termination event.  As dragEnded just resets drag variables, we just 
+    // call it anyway to be on the safe side
+    dragEnded();
+}
+    
 }
index ed17a37..615c791 100644 (file)
@@ -27,7 +27,9 @@
 #define DragController_h
 
 #include "DragActions.h"
+#include "DragImage.h"
 #include "IntPoint.h"
+#include "IntRect.h"
 #include "KURL.h"
 
 namespace WebCore {
@@ -36,8 +38,13 @@ namespace WebCore {
     class Document;
     class DragClient;
     class DragData;
+    class Element;
     class Frame;
+    class Image;
+    class Node;
     class Page;
+    class PlatformMouseEvent;
+    class Range;
     class SelectionController;
     
     class DragController {
@@ -74,6 +81,14 @@ namespace WebCore {
         bool mayStartDragAtEventLocation(const Frame*, const IntPoint& framePos);
         void dragEnded() { m_dragInitiator = 0; m_didInitiateDrag = false; }
         
+        bool startDrag(Frame* src, Clipboard*, DragOperation srcOp, const PlatformMouseEvent& dragEvent, const IntPoint& dragOrigin, bool isDHTMLDrag);
+        
+        static const int LinkDragBorderInset;
+        static const IntSize MaxDragImageSize;
+        static const int MaxOriginalImageArea;
+        static const int DragIconRightInset;
+        static const int DragIconBottomInset;        
+        static const float DragImageAlpha;
     private:
         bool canProcessDrag(DragData*);
         bool concludeDrag(DragData*, DragDestinationAction);
@@ -85,7 +100,11 @@ namespace WebCore {
         void cancelDrag();
         bool dragIsMove(SelectionController*, DragData*);
         bool isCopyKeyDown();
-        
+
+        IntRect selectionDraggingRect(Frame*);
+        bool doDrag(Frame* src, Clipboard* clipboard, DragImageRef dragImage, const KURL& linkURL, const KURL& imageURL, Node* node, IntPoint& dragLoc, IntPoint& dragImageOffset);
+        void doImageDrag(Element*, const IntPoint&, const IntRect&, Clipboard*, Frame*, IntPoint&);
+        void doSystemDrag(DragImageRef, const IntPoint&, const IntPoint&, Clipboard*, Frame*, bool forLink);
         Page* m_page;
         DragClient* m_client;
         
index 90fe8f3..9e9fcbf 100644 (file)
@@ -1353,9 +1353,133 @@ bool EventHandler::dispatchDragSrcEvent(const AtomicString& eventType, const Pla
 {
     return !dispatchDragEvent(eventType, dragState().m_dragSrc.get(), event, dragState().m_dragClipboard.get());
 }
-
+    
+bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event)
+{
+    if (event.event().button() != LeftButton || event.event().eventType() != MouseEventMoved) {
+        // If we allowed the other side of the bridge to handle a drag
+        // last time, then m_mousePressed might still be set. So we
+        // clear it now to make sure the next move after a drag
+        // doesn't look like a drag.
+        m_mousePressed = false;
+        return false;
+    }
+    
+    if (eventLoopHandleMouseDragged(event))
+        return true;
+    
+    // Careful that the drag starting logic stays in sync with eventMayStartDrag()
+    
+    if (m_mouseDownMayStartDrag && !dragState().m_dragSrc) {
+        allowDHTMLDrag(dragState().m_dragSrcMayBeDHTML, dragState().m_dragSrcMayBeUA);
+        if (!dragState().m_dragSrcMayBeDHTML && !dragState().m_dragSrcMayBeUA)
+            m_mouseDownMayStartDrag = false;     // no element is draggable
+    }
+    
+    if (m_mouseDownMayStartDrag && !dragState().m_dragSrc) {
+        // try to find an element that wants to be dragged
+        HitTestRequest request(true, false);
+        HitTestResult result(m_mouseDownPos);
+        m_frame->renderer()->layer()->hitTest(request, result);
+        Node* node = result.innerNode();
+        if (node && node->renderer())
+            dragState().m_dragSrc = node->renderer()->draggableNode(dragState().m_dragSrcMayBeDHTML, dragState().m_dragSrcMayBeUA,
+                                                                    m_mouseDownPos.x(), m_mouseDownPos.y(), dragState().m_dragSrcIsDHTML);
+        else
+            dragState().m_dragSrc = 0;
+        
+        if (!dragState().m_dragSrc)
+            m_mouseDownMayStartDrag = false;     // no element is draggable
+        else {
+            // remember some facts about this source, while we have a HitTestResult handy
+            node = result.URLElement();
+            dragState().m_dragSrcIsLink = node && node->isLink();
+            
+            node = result.innerNonSharedNode();
+            dragState().m_dragSrcIsImage = node && node->renderer() && node->renderer()->isImage();
+            
+            dragState().m_dragSrcInSelection = m_frame->selectionController()->contains(m_mouseDownPos);
+        }                
+    }
+    
+    // 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 (m_mouseDownMayStartDrag && dragState().m_dragSrcInSelection && event.event().timestamp() - m_mouseDownTimestamp < TextDragDelay) {
+        m_mouseDownMayStartDrag = false;
+        // ...but if this was the first click in the window, we don't even want to start selection
+        if (eventActivatedView(event.event()))
+            m_mouseDownMayStartSelect = false;
+    }
+    
+    if (!m_mouseDownMayStartDrag)
+        return !mouseDownMayStartSelect() && !m_mouseDownMayStartAutoscroll;
+    
+    // We are starting a text/image/url drag, so the cursor should be an arrow
+    m_frame->view()->setCursor(pointerCursor());
+    
+    if (!dragHysteresisExceeded(event.event().pos())) 
+        return true;
+    
+    // Once we're past the hysteresis point, we don't want to treat this gesture as a click
+    invalidateClick();
+    
+    DragOperation srcOp = DragOperationNone;        
+    if (dragState().m_dragSrcMayBeDHTML) {
+        freeClipboard();    // would only happen if we missed a dragEnd.  Do it anyway, just
+                            // to make sure it gets numbified
+        
+        dragState().m_dragClipboard = createDraggingClipboard();
+        
+        // Check to see if the is a DOM based drag, if it is get the DOM specified drag 
+        // image and offset
+        if (dragState().m_dragSrcIsDHTML) {
+            int srcX, srcY;
+            dragState().m_dragSrc->renderer()->absolutePosition(srcX, srcY);
+            IntSize delta = m_mouseDownPos - IntPoint(srcX, srcY);
+            dragState().m_dragClipboard->setDragImageElement(dragState().m_dragSrc.get(), IntPoint() + delta);
+        } 
+        
+        m_mouseDownMayStartDrag = dispatchDragSrcEvent(dragstartEvent, m_mouseDown)
+            && !m_frame->selectionController()->isInPasswordField();
+        
+        // Invalidate clipboard here against anymore pasteboard writing for security.  The drag
+        // image can still be changed as we drag, but not the pasteboard data.
+        dragState().m_dragClipboard->setAccessPolicy(ClipboardImageWritable);
+        
+        if (m_mouseDownMayStartDrag) {
+            // gather values from DHTML element, if it set any
+            dragState().m_dragClipboard->sourceOperation(srcOp);
+            
+            // Yuck, dragSourceMovedTo() can be called as a result of kicking off the drag with
+            // dragImage!  Because of that dumb reentrancy, we may think we've not started the
+            // drag when that happens.  So we have to assume it's started before we kick it off.
+            dragState().m_dragClipboard->setDragHasStarted();
+        }
+    }
+    
+    if (m_mouseDownMayStartDrag) {
+        DragController* dragController = m_frame->page() ? m_frame->page()->dragController() : 0;
+        bool startedDrag = dragController && dragController->startDrag(m_frame, dragState().m_dragClipboard.get(), srcOp, event.event(), m_mouseDownPos, dragState().m_dragSrcIsDHTML);
+        if (!startedDrag && dragState().m_dragSrcMayBeDHTML) {
+            // Drag was canned at the last minute - we owe m_dragSrc a DRAGEND event
+            PlatformMouseEvent event(PlatformMouseEvent::currentEvent);
+            dispatchDragSrcEvent(dragendEvent, event);
+            m_mouseDownMayStartDrag = false;
+        }
+    } 
+    
+    if (!m_mouseDownMayStartDrag) {
+        // something failed to start the drag, cleanup
+        freeClipboard();
+        dragState().m_dragSrc = 0;
+    }
+    
+    // No more default handling (like selection), whether we're past the hysteresis bounds or not
+    return true;
+}
+  
 bool EventHandler::handleTextInputEvent(const String& text, Event* underlyingEvent,
-    bool isLineBreak, bool isBackTab)
+                                        bool isLineBreak, bool isBackTab)
 {
     if (!m_frame)
         return false;
@@ -1373,7 +1497,8 @@ bool EventHandler::handleTextInputEvent(const String& text, Event* underlyingEve
     ExceptionCode ec;
     return target->dispatchEvent(event.release(), ec, true);
 }
-
+    
+    
 void EventHandler::defaultTextInputEventHandler(TextEvent* event)
 {
     String data = event->data();
index 96a9dd2..59b6d17 100644 (file)
@@ -170,7 +170,9 @@ private:
         RefPtr<Clipboard> m_dragClipboard; // used on only the source side of dragging
     };
     static EventHandlerDragState& dragState();
-
+    
+    Clipboard* createDraggingClipboard() const;
+    
     bool eventActivatedView(const PlatformMouseEvent&) const;
     void selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults& event);
 
@@ -243,6 +245,7 @@ private:
     NSView *mouseDownViewIfStillGood();
 #else
     bool eventLoopHandleMouseUp(const MouseEventWithHitTestResults&) { return false; }
+    bool eventLoopHandleMouseDragged(const MouseEventWithHitTestResults&) { return false; }
 #endif
 
     Frame* m_frame;
@@ -285,11 +288,11 @@ private:
     IntPoint m_currentMousePosition;
     IntPoint m_mouseDownPos; // in our view's coords
     double m_mouseDownTimestamp;
+    PlatformMouseEvent m_mouseDown;
 
 #if PLATFORM(MAC)
     NSView *m_mouseDownView;
     bool m_sendingEventToSubview;
-    PlatformMouseEvent m_mouseDown;
     int m_activationEventNumber;
 #endif
 
index 3b249c5..3a0a511 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "Color.h"
 #include "EditAction.h"
+#include "DragImage.h"
 #include "RenderLayer.h"
 #include "TextGranularity.h"
 #include <wtf/unicode/Unicode.h>
@@ -125,6 +126,8 @@ public:
     friend class FrameQt;
     friend class FrameWin;
 
+    DragImageRef dragImageForSelection();
+    
 private:
     FramePrivate* d;
 
index ad96c02..5ea0458 100644 (file)
 
 namespace WebCore {
 
+const int DragController::LinkDragBorderInset = -2;
+
+const IntSize DragController::MaxDragImageSize(400, 400);
+const int DragController::MaxOriginalImageArea = 1500 * 1500;
+const int DragController::DragIconRightInset = 7;
+const int DragController::DragIconBottomInset = 3;
+
+const float DragController::DragImageAlpha = 0.75f;
+
 bool DragController::isCopyKeyDown()
 {
     return [[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask;
index 0238d52..e458675 100644 (file)
@@ -30,6 +30,7 @@
 #include "ClipboardMac.h"
 #include "Cursor.h"
 #include "Document.h"
+#include "DragController.h"
 #include "EventNames.h"
 #include "FloatPoint.h"
 #include "FocusController.h"
@@ -340,148 +341,14 @@ bool EventHandler::eventLoopHandleMouseDragged(const MouseEventWithHitTestResult
     return true;
 }
     
-bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event)
+Clipboard* EventHandler::createDraggingClipboard() const 
 {
-    BEGIN_BLOCK_OBJC_EXCEPTIONS;
-    if (event.event().button() != LeftButton || event.event().eventType() != MouseEventMoved) {
-        // If we allowed the other side of the bridge to handle a drag
-        // last time, then m_mousePressed might still be set. So we
-        // clear it now to make sure the next move after a drag
-        // doesn't look like a drag.
-        m_mousePressed = false;
-        return false;
-    }
-    
-    if (eventLoopHandleMouseDragged(event))
-        return true;
-    
-    // Careful that the drag starting logic stays in sync with eventMayStartDrag()
-    
-    if (m_mouseDownMayStartDrag && !dragState().m_dragSrc) {
-        allowDHTMLDrag(dragState().m_dragSrcMayBeDHTML, dragState().m_dragSrcMayBeUA);
-        if (!dragState().m_dragSrcMayBeDHTML && !dragState().m_dragSrcMayBeUA)
-            m_mouseDownMayStartDrag = false;     // no element is draggable
-    }
-    
-    if (m_mouseDownMayStartDrag && !dragState().m_dragSrc) {
-        // try to find an element that wants to be dragged
-        HitTestRequest request(true, false);
-        HitTestResult result(m_mouseDownPos);
-        m_frame->renderer()->layer()->hitTest(request, result);
-        Node* node = result.innerNode();
-        if (node && node->renderer())
-            dragState().m_dragSrc = node->renderer()->draggableNode(dragState().m_dragSrcMayBeDHTML, dragState().m_dragSrcMayBeUA,
-                                                                    m_mouseDownPos.x(), m_mouseDownPos.y(), dragState().m_dragSrcIsDHTML);
-        else
-            dragState().m_dragSrc = 0;
-        
-        if (!dragState().m_dragSrc)
-            m_mouseDownMayStartDrag = false;     // no element is draggable
-        else {
-            // remember some facts about this source, while we have a HitTestResult handy
-            node = result.URLElement();
-            dragState().m_dragSrcIsLink = node && node->isLink();
-            
-            node = result.innerNonSharedNode();
-            dragState().m_dragSrcIsImage = node && node->renderer() && node->renderer()->isImage();
-            
-            dragState().m_dragSrcInSelection = m_frame->selectionController()->contains(m_mouseDownPos);
-        }                
-    }
-    
-    // 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 (m_mouseDownMayStartDrag && dragState().m_dragSrcInSelection && event.event().timestamp() - m_mouseDownTimestamp < TextDragDelay) {
-        m_mouseDownMayStartDrag = false;
-        // ...but if this was the first click in the window, we don't even want to start selection
-        if (eventActivatedView(event.event()))
-            m_mouseDownMayStartSelect = false;
-    }
-    
-    if (!m_mouseDownMayStartDrag)
-        return !mouseDownMayStartSelect() && !m_mouseDownMayStartAutoscroll;
-    
-    // We are starting a text/image/url drag, so the cursor should be an arrow
-    m_frame->view()->setCursor(pointerCursor());
-    
-    if (!dragHysteresisExceeded(event.event().pos())) 
-        return true;
-    
-    // Once we're past the hysteresis point, we don't want to treat this gesture as a click
-    invalidateClick();
-    
-    NSImage *dragImage = nil;       // we use these values if WC is out of the loop
-    NSPoint dragLoc = NSZeroPoint;
-    DragOperation srcOp = DragOperationNone;                
-    BOOL wcWrotePasteboard = NO;
-    if (dragState().m_dragSrcMayBeDHTML) {
-        NSPasteboard *pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard];
-        // Must be done before ondragstart adds types and data to the pboard,
-        // also done for security, as it erases data from the last drag
-        [pasteboard declareTypes:[NSArray array] owner:nil];
-        
-        freeClipboard();    // would only happen if we missed a dragEnd.  Do it anyway, just
-        // to make sure it gets numbified
-        dragState().m_dragClipboard = new ClipboardMac(true, pasteboard, ClipboardWritable, Mac(m_frame));
-        
-        // If this is drag of an element, get set up to generate a default image.  Otherwise
-        // WebKit will generate the default, the element doesn't override.
-        if (dragState().m_dragSrcIsDHTML) {
-            int srcX, srcY;
-            dragState().m_dragSrc->renderer()->absolutePosition(srcX, srcY);
-            IntSize delta = m_mouseDownPos - IntPoint(srcX, srcY);
-            dragState().m_dragClipboard->setDragImageElement(dragState().m_dragSrc.get(), IntPoint() + delta);
-        } 
-        
-        m_mouseDownMayStartDrag = dispatchDragSrcEvent(dragstartEvent, m_mouseDown)
-            && !m_frame->selectionController()->isInPasswordField();
-        
-        // Invalidate clipboard here against anymore pasteboard writing for security.  The drag
-        // image can still be changed as we drag, but not the pasteboard data.
-        dragState().m_dragClipboard->setAccessPolicy(ClipboardImageWritable);
-        
-        if (m_mouseDownMayStartDrag) {
-            // gather values from DHTML element, if it set any
-            dragState().m_dragClipboard->sourceOperation(srcOp);
-            
-            NSArray *types = [pasteboard types];
-            wcWrotePasteboard = types && [types count] > 0;
-            
-            if (dragState().m_dragSrcMayBeDHTML)
-                dragImage = static_cast<ClipboardMac*>(dragState().m_dragClipboard.get())->dragNSImage(dragLoc);
-            
-            // Yuck, dragSourceMovedTo() can be called as a result of kicking off the drag with
-            // dragImage!  Because of that dumb reentrancy, we may think we've not started the
-            // drag when that happens.  So we have to assume it's started before we kick it off.
-            dragState().m_dragClipboard->setDragHasStarted();
-        }
-    }
-    
-    if (m_mouseDownMayStartDrag) {
-        bool startedDrag = [Mac(m_frame)->bridge() startDraggingImage:dragImage at:dragLoc operation:srcOp event:currentEvent sourceIsDHTML:dragState().m_dragSrcIsDHTML DHTMLWroteData:wcWrotePasteboard];
-        if (!startedDrag && dragState().m_dragSrcMayBeDHTML) {
-            // WebKit canned the drag at the last minute - we owe m_dragSrc a DRAGEND event
-            PlatformMouseEvent event(PlatformMouseEvent::currentEvent);
-            dispatchDragSrcEvent(dragendEvent, event);
-            m_mouseDownMayStartDrag = false;
-        }
-    } 
-    
-    if (!m_mouseDownMayStartDrag) {
-        // something failed to start the drag, cleanup
-        freeClipboard();
-        dragState().m_dragSrc = 0;
-    }
-    
-    // No more default handling (like selection), whether we're past the hysteresis bounds or not
-    return true;   
-    
-    END_BLOCK_OBJC_EXCEPTIONS;
-    
-    return false;
-    
+    NSPasteboard *pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard];
+    // Must be done before ondragstart adds types and data to the pboard,
+    // also done for security, as it erases data from the last drag
+    [pasteboard declareTypes:[NSArray array] owner:nil];
+    return new ClipboardMac(true, pasteboard, ClipboardWritable, Mac(m_frame));
 }
-
     
 bool EventHandler::eventLoopHandleMouseUp(const MouseEventWithHitTestResults&)
 {
index 3f504bf..7e4a9e4 100644 (file)
@@ -982,5 +982,12 @@ void FrameMac::paintCustomHighlight(const AtomicString& type, const FloatRect& b
 {
     [_bridge paintCustomHighlight:type forBox:boxRect onLine:lineRect behindText:text entireLine:line];
 }
+    
+DragImageRef Frame::dragImageForSelection() 
+{
+    if (!selectionController()->isRange())
+        return nil;
+    return static_cast<FrameMac*>(this)->selectionImage();
+}
 
 } // namespace WebCore
index 29a4e6a..a0feeb8 100644 (file)
 namespace WebCore
 {
 
+// FIXME: These values are straight out of DragControllerMac, so probably have 
+// little correlation with Qt standards...
+const int DragController::LinkDragBorderInset = 2;
+const IntSize DragController::MaxDragImageSize(400, 400);
+const int DragController::MaxOriginalImageArea = 1500 * 1500;
+const int DragController::DragIconRightInset = 7;
+const int DragController::DragIconBottomInset = 3;
+
+const float DragController::DragImageAlpha = 0.75f;
+
+
 bool DragController::isCopyKeyDown()
 {
     return false;
index aac3020..f2d09de 100644 (file)
@@ -100,12 +100,6 @@ bool EventHandler::passMouseDownEventToWidget(Widget* widget)
     return false;
 }
 
-bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event)
-{
-    //notImplemented();
-    return false;
-}
-
 bool EventHandler::eventActivatedView(const PlatformMouseEvent&) const
 {
     //Qt has an activation event which is sent independently
@@ -125,6 +119,12 @@ bool EventHandler::passWheelEventToWidget(Widget* widget)
     notImplemented();
     return false;
 }
+    
+Clipboard* EventHandler::createDraggingClipboard() const 
+{
+    notImplemented();
+    return 0;
+}
 
 bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe)
 {
index 8748ce0..3709607 100644 (file)
@@ -272,5 +272,11 @@ PassRefPtr<KJS::Bindings::RootObject> FrameQt::createRootObject(void* nativeHand
     return rootObject.release();
 }
 
+DragImageRef Frame::dragImageForSelection() 
+{
+    return 0;
+}
+    
+
 }
 // vim: ts=4 sw=4 et
diff --git a/WebCore/platform/DragImage.cpp b/WebCore/platform/DragImage.cpp
new file mode 100644 (file)
index 0000000..df3cd9e
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "DragImage.h"
+#include "DragController.h"
+
+#include "Frame.h"
+
+namespace WebCore {
+    
+DragImageRef fitDragImageToMaxSize(DragImageRef image, const IntSize& size)
+{
+    float heightResizeRatio = 0.0f;
+    float widthResizeRatio = 0.0f;
+    float resizeRatio = 0.0f;
+    IntSize originalSize = dragImageSize(image);
+    
+    if (originalSize.width() > size.width()) {
+        widthResizeRatio = size.width() / (float)originalSize.width();
+        resizeRatio = widthResizeRatio;
+    }
+    
+    if (originalSize.height() > size.height()) {
+        heightResizeRatio = size.height() / (float)originalSize.height();
+        if ((resizeRatio == 0.0) || (resizeRatio > heightResizeRatio))
+            resizeRatio = heightResizeRatio;
+    }
+    
+    if (resizeRatio > 0.0)
+        return scaleDragImage(image, resizeRatio);
+    return image;
+    
+}
+    
+DragImageRef createDragImageForSelection(Frame* frame)
+{
+    DragImageRef image = frame->dragImageForSelection();
+    if (image)
+        dissolveDragImageToFraction(image, DragController::DragImageAlpha);
+    return image;
+}
+
+}
diff --git a/WebCore/platform/DragImage.h b/WebCore/platform/DragImage.h
new file mode 100644 (file)
index 0000000..4012487
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DragImage_h
+#define DragImage_h
+
+#include "IntSize.h"
+#include "RetainPtr.h"
+
+#if PLATFORM(MAC)
+#ifdef __OBJC__
+@class NSImage;
+#else
+class NSImage;
+#endif
+#elif PLATFORM(QT)
+class QImage;
+#elif PLATFORM(WIN)
+typedef struct HBITMAP__* HBITMAP;
+#endif
+
+//We need to #define YOffset as it needs to be shared with WebKit
+#define DragLabelBorderYOffset 2
+
+namespace WebCore {
+    
+    class CachedImage;
+    class Frame;
+    class Image;
+    class KURL;
+    class Range;
+    class String;
+    
+#if PLATFORM(MAC)
+    typedef RetainPtr<NSImage> DragImageRef;
+#elif PLATFORM(QT)
+    typedef QImage* DragImageRef;
+#elif PLATFORM(WIN)
+    typedef HBITMAP DragImageRef;
+#endif
+    
+    IntSize dragImageSize(DragImageRef);
+    
+    //These functions should be memory neutral, eg. if they return a newly allocated image, 
+    //they should release the input image.  As a corollary these methods don't guarantee
+    //the input image ref will still be valid after they have been called
+    DragImageRef fitDragImageToMaxSize(DragImageRef image, const IntSize& size);
+    DragImageRef scaleDragImage(DragImageRef, float);
+    DragImageRef dissolveDragImageToFraction(DragImageRef image, float delta);
+    
+    DragImageRef createDragImageFromImage(Image*);
+    DragImageRef createDragImageForSelection(Frame*);    
+    DragImageRef createDragImageIconForCachedImage(CachedImage*);
+    void deleteDragImage(DragImageRef);
+}
+
+
+#endif //!DragImage_h
index 88ebdae..37dc940 100644 (file)
@@ -36,6 +36,7 @@
 
 #if PLATFORM(MAC)
 class NSPasteboard;
+class NSArray;
 #endif
 
 #if PLATFORM(WIN)
@@ -59,9 +60,15 @@ class Frame;
 class KURL;
 class Range;
 class String;
-
+    
 class Pasteboard : Noncopyable {
 public:
+#if PLATFORM(MAC)
+    //Helper functions to allow Clipboard to share code
+    static void writeSelection(NSPasteboard* pasteboard, Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame);
+    static void writeURL(NSPasteboard* pasteboard, NSArray* types, const KURL& url, const String& titleStr, Frame* frame);
+#endif
+    
     static Pasteboard* generalPasteboard();
     void writeSelection(Range*, bool canSmartCopyOrDelete, Frame*);
     void writeURL(const KURL&, const String&, Frame* = 0);
index c082176..170ed66 100644 (file)
@@ -347,8 +347,11 @@ class SVGEmptyDragClient : public DragClient {
 public:
     virtual ~SVGEmptyDragClient() {}
     virtual void willPerformDragDestinationAction(DragDestinationAction, DragData*) { }
+    virtual void willPerformDragSourceAction(DragSourceAction, const IntPoint&, Clipboard*) { }
     virtual DragDestinationAction actionMaskForDrag(DragData*) { return DragDestinationActionNone; }
     virtual DragSourceAction dragSourceActionMaskForPoint(const IntPoint&) { return DragSourceActionNone; }
+    virtual void startDrag(DragImageRef, const IntPoint&, const IntPoint&, Clipboard*, Frame*, bool) { }
+    virtual DragImageRef createDragImageForLink(KURL&, const String& label, Frame*) { return 0; } 
     virtual void dragControllerDestroyed() { }
 };
     
index c10b891..e50b5fc 100644 (file)
@@ -58,7 +58,9 @@ public:
     void clearAllData();
     String getData(const String& type, bool& success) const;
     bool setData(const String& type, const String& data);
-        
+    
+    virtual bool hasData();
+    
     // extensions beyond IE's API
     virtual HashSet<String> types() const;
 
@@ -67,10 +69,15 @@ public:
     void setDragImage(CachedImage*, const IntPoint&);
     Node* dragImageElement();
     void setDragImageElement(Node *, const IntPoint&);
-
-    // Methods for getting info in Cocoa's type system
-    NSImage *dragNSImage(NSPoint&); // loc converted from dragLoc, based on whole image size
     
+    virtual DragImageRef createDragImage(IntPoint& dragLoc) const;
+    virtual void declareAndWriteDragImage(Element*, const KURL&, const String& title, Frame*);
+    virtual void writeRange(Range*, Frame* frame);
+    virtual void writeURL(const KURL&, const String&, Frame* frame);
+    
+    // Methods for getting info in Cocoa's type system
+    NSImage *dragNSImage(NSPoint&) const; // loc converted from dragLoc, based on whole image size
+    NSPasteboard *pasteboard() { return m_pasteboard.get(); }
 private:
     void setDragImage(CachedImage*, Node*, const IntPoint&);
 
index 4d04a17..7a37119 100644 (file)
 #import "ClipboardMac.h"
 
 #import "CachedImage.h"
+#import "Document.h"
+#import "DOMElementInternal.h"
+#import "DragClient.h"
+#import "DragController.h"
+#import "Editor.h"
 #import "EventHandler.h"
 #import "FloatRect.h"
 #import "FoundationExtras.h"
 #import "FrameMac.h"
+#import "HTMLImageElement.h"
 #import "Image.h"
+#import "Page.h"
+#import "Pasteboard.h"
+#import "Range.h"
+#import "RenderImage.h"
+#import "WebCoreFrameBridge.h"
 #import "WebCoreSystemInterface.h"
 
+@class WebArchive;
+
 namespace WebCore {
 
 ClipboardMac::ClipboardMac(bool forDragging, NSPasteboard *pasteboard, ClipboardAccessPolicy policy, FrameMac *frame)
@@ -50,6 +63,11 @@ ClipboardMac::~ClipboardMac()
 {
 }
 
+bool ClipboardMac::hasData()
+{
+    return m_pasteboard && [m_pasteboard.get() types] && [[m_pasteboard.get() types] count] > 0;
+}
+    
 bool ClipboardMac::isForDragging() const
 {
     return m_forDragging;
@@ -317,8 +335,37 @@ void ClipboardMac::setDragImage(CachedImage* image, Node *node, const IntPoint &
         // set the image way too late.
     }
 }
-
-NSImage *ClipboardMac::dragNSImage(NSPoint& loc)
+    
+void ClipboardMac::writeRange(Range* range, Frame* frame)
+{
+    ASSERT(range);
+    ASSERT(frame);
+    Pasteboard::writeSelection(m_pasteboard.get(), range, frame->editor()->smartInsertDeleteEnabled() && frame->selectionGranularity() == WordGranularity, frame);
+}
+    
+void ClipboardMac::writeURL(const KURL& url, const String& title, Frame* frame)
+{   
+    ASSERT(frame);
+    ASSERT(m_pasteboard);
+    Pasteboard::writeURL(m_pasteboard.get(), nil, url, title, frame);
+}
+    
+void ClipboardMac::declareAndWriteDragImage(Element* element, const KURL& url, const String& title, Frame* frame)
+{
+    ASSERT(frame);
+    if (Page* page = frame->page())
+        page->dragController()->client()->declareAndWriteDragImage(m_pasteboard.get(), [DOMElement _elementWith:element], url.getNSURL(), title, frame, Clipboard::canSaveAsWebArchive(frame));
+}
+    
+DragImageRef ClipboardMac::createDragImage(IntPoint& loc) const
+{
+    NSPoint nsloc = {loc.x(), loc.y()};
+    DragImageRef result = dragNSImage(nsloc);
+    loc = IntPoint(nsloc.x, nsloc.y);
+    return result;
+}
+    
+NSImage *ClipboardMac::dragNSImage(NSPoint& loc) const
 {
     NSImage *result = nil;
     if (m_dragImageElement) {
diff --git a/WebCore/platform/mac/DragImageMac.mm b/WebCore/platform/mac/DragImageMac.mm
new file mode 100644 (file)
index 0000000..e1d413d
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+#import "config.h"
+#import "DragImage.h"
+
+#import "CachedImage.h"
+#import "Image.h"
+#import "KURL.h"
+#import "PlatformString.h"
+#import "ResourceResponse.h"
+#import <FoundationExtras.h>
+
+namespace WebCore {
+
+
+
+IntSize dragImageSize(DragImageRef image)
+{
+    return (IntSize)[image.get() size];
+}
+
+void deleteDragImage(DragImageRef image)
+{
+    //DragImageRef is a RetainPtr, so we don't need to explicitly delete it
+}
+
+DragImageRef scaleDragImage(DragImageRef image, float scale)
+{
+    NSSize originalSize = [image.get() size];
+    NSSize newSize = NSMakeSize((originalSize.width * scale), (originalSize.height * scale));
+    newSize.width = roundf(newSize.width);
+    newSize.height = roundf(newSize.height);
+    [image.get() setScalesWhenResized:YES];
+    [image.get() setSize:newSize];
+    return image;
+}
+    
+DragImageRef dissolveDragImageToFraction(DragImageRef image, float delta)
+{
+    RetainPtr<NSImage> dissolvedImage(AdoptNS, [[NSImage alloc] initWithSize:[image.get() size]]);
+    
+    NSPoint point = [image.get() isFlipped] ? NSMakePoint(0, [image.get() size].height) : NSZeroPoint;
+    
+    // In this case the dragging image is always correct.
+    [dissolvedImage.get() setFlipped:[image.get() isFlipped]];
+    
+    [dissolvedImage.get() lockFocus];
+    [image.get() dissolveToPoint:point fraction: delta];
+    [dissolvedImage.get() unlockFocus];
+    
+    [image.get() lockFocus];
+    [dissolvedImage.get() compositeToPoint:point operation:NSCompositeCopy];
+    [image.get() unlockFocus];
+    
+    return image;
+}
+        
+DragImageRef createDragImageFromImage(Image* image)
+{
+    DragImageRef dragImage(AdoptNS, [image->getNSImage() copy]);
+    [dragImage.get() setSize:(NSSize)(image->size())];
+    return dragImage;
+}
+    
+DragImageRef createDragImageIconForCachedImage(CachedImage* image)
+{
+    const String& filename = image->response().suggestedFilename();
+    NSString *extension = nil;
+    int dotIndex = filename.reverseFind('.');
+    
+    if (dotIndex > 0 && dotIndex < (int)(filename.length() - 1)) // require that a . exists after the first character and before the last
+        extension = filename.substring(dotIndex + 1);
+    else
+        //It might be worth doing a further look up to pull the extension from the mimetype
+        extension = @"";
+    
+    return DragImageRef([[NSWorkspace sharedWorkspace] iconForFileType:extension]);
+     
+}
+    
+}
index 6011eba..2334d55 100644 (file)
@@ -114,8 +114,11 @@ static NSAttributedString *stripAttachmentCharacters(NSAttributedString *string)
     return result;
 }
 
-void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
+void Pasteboard::writeSelection(NSPasteboard* pasteboard, Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
 {
+    if (WebArchivePboardType == nil)
+        Pasteboard::generalPasteboard(); //Initialises pasteboard types
+    
     NSAttributedString *attributedString = [[[NSAttributedString alloc] _initWithDOMRange:[DOMRange _rangeWith:selectedRange]] autorelease];
 #ifdef BUILDING_ON_TIGER
     // 4930197: Mail overrides [WebHTMLView pasteboardTypesForSelection] in order to add another type to the pasteboard
@@ -130,28 +133,28 @@ void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete,
         [mutableTypes removeObject:NSRTFDPboardType];
         types = mutableTypes;
     }
-    [m_pasteboard declareTypes:types owner:nil];    
+    [pasteboard declareTypes:types owner:nil];    
 #else
     NSArray *types = selectionPasteboardTypes(canSmartCopyOrDelete, [attributedString containsAttachments]);
-    [m_pasteboard declareTypes:types owner:nil];
+    [pasteboard declareTypes:types owner:nil];
     frame->editor()->client()->didSetSelectionTypesForPasteboard();
 #endif
-
+    
     // Put HTML on the pasteboard.
     if ([types containsObject:WebArchivePboardType]) {
-        [m_pasteboard setData:frame->editor()->client()->dataForArchivedSelection(frame) forType:WebArchivePboardType];
+        [pasteboard setData:frame->editor()->client()->dataForArchivedSelection(frame) forType:WebArchivePboardType];
     }
-
+    
     // Put the attributed string on the pasteboard (RTF/RTFD format).
     if ([types containsObject:NSRTFDPboardType]) {
         NSData *RTFDData = [attributedString RTFDFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:nil];
-        [m_pasteboard setData:RTFDData forType:NSRTFDPboardType];
+        [pasteboard setData:RTFDData forType:NSRTFDPboardType];
     }
     if ([types containsObject:NSRTFPboardType]) {
         if ([attributedString containsAttachments])
             attributedString = stripAttachmentCharacters(attributedString);
         NSData *RTFData = [attributedString RTFFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:nil];
-        [m_pasteboard setData:RTFData forType:NSRTFPboardType];
+        [pasteboard setData:RTFData forType:NSRTFPboardType];
     }
     
     // Put plain string on the pasteboard.
@@ -164,40 +167,60 @@ void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete,
         
         NSString *NonBreakingSpaceString = [NSString stringWithCharacters:&noBreakSpace length:1];
         [s replaceOccurrencesOfString:NonBreakingSpaceString withString:@" " options:0 range:NSMakeRange(0, [s length])];
-        [m_pasteboard setString:s forType:NSStringPboardType];
+        [pasteboard setString:s forType:NSStringPboardType];
         [s release];
     }
     
     if ([types containsObject:WebSmartPastePboardType]) {
-        [m_pasteboard setData:nil forType:WebSmartPastePboardType];
+        [pasteboard setData:nil forType:WebSmartPastePboardType];
     }
 }
+    
+void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
+{
+    Pasteboard::writeSelection(m_pasteboard, selectedRange, canSmartCopyOrDelete, frame);
+}
 
-void Pasteboard::writeURL(const KURL& url, const String& titleStr, Frame* frame)
+void Pasteboard::writeURL(NSPasteboard* pasteboard, NSArray* types, const KURL& url, const String& titleStr, Frame* frame)
 {
+    if (WebArchivePboardType == nil)
+        Pasteboard::generalPasteboard(); //Initialises pasteboard types
+   
+    if (types == nil) {
+        types = writableTypesForURL();
+        [pasteboard declareTypes:types owner:nil];
+    }
+    
     ASSERT(!url.isEmpty());
     
     NSURL *URL = url.getNSURL();
     NSString *userVisibleString = frame->editor()->client()->userVisibleString(URL);
-
+    
     NSString *title = (NSString*)titleStr;
     if ([title length] == 0) {
         title = [[URL path] lastPathComponent];
         if ([title length] == 0)
             title = userVisibleString;
     }
-
-    NSArray *types = writableTypesForURL();
-    [m_pasteboard declareTypes:types owner:nil];
-
-    [m_pasteboard setPropertyList:[NSArray arrayWithObjects:[NSArray arrayWithObject:userVisibleString], 
-                                                            [NSArray arrayWithObject:(NSString*)titleStr.stripWhiteSpace()], 
-                                                            nil]
-                          forType:WebURLsWithTitlesPboardType];
-    [URL writeToPasteboard:m_pasteboard];
-    [m_pasteboard setString:userVisibleString forType:WebURLPboardType];
-    [m_pasteboard setString:title forType:WebURLNamePboardType];
-    [m_pasteboard setString:userVisibleString forType:NSStringPboardType];
+        
+    if ([types containsObject:WebURLsWithTitlesPboardType])
+        [pasteboard setPropertyList:[NSArray arrayWithObjects:[NSArray arrayWithObject:userVisibleString], 
+                                     [NSArray arrayWithObject:(NSString*)titleStr.stripWhiteSpace()], 
+                                     nil]
+                            forType:WebURLsWithTitlesPboardType];
+    if ([types containsObject:NSURLPboardType])
+        [URL writeToPasteboard:pasteboard];
+    if ([types containsObject:WebURLPboardType])
+        [pasteboard setString:userVisibleString forType:WebURLPboardType];
+    if ([types containsObject:WebURLNamePboardType])
+        [pasteboard setString:title forType:WebURLNamePboardType];
+    if ([types containsObject:NSStringPboardType])
+        [pasteboard setString:userVisibleString forType:NSStringPboardType];
+}
+    
+void Pasteboard::writeURL(const KURL& url, const String& titleStr, Frame* frame)
+{
+    Pasteboard::writeURL(m_pasteboard, nil, url, titleStr, frame);
 }
 
 
diff --git a/WebCore/platform/qt/DragImageQt.cpp b/WebCore/platform/qt/DragImageQt.cpp
new file mode 100644 (file)
index 0000000..017258c
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "DragImage.h"
+
+#include "CachedImage.h"
+#include "Image.h"
+
+namespace WebCore {
+
+IntSize dragImageSize(DragImageRef)
+{
+    return IntSize(0, 0);
+}
+
+void deleteDragImage(DragImageRef)
+{
+}
+
+DragImageRef scaleDragImage(DragImageRef image, float)
+{
+    return image;
+}
+    
+DragImageRef dissolveDragImageToFraction(DragImageRef image, float)
+{
+    return image;
+}
+        
+DragImageRef createDragImageFromImage(Image*)
+{
+    return 0;
+}
+    
+DragImageRef createDragImageIconForCachedImage(CachedImage*)
+{
+    return 0;     
+}
+    
+}
index a9197f7..a2226fb 100644 (file)
@@ -1,3 +1,39 @@
+2007-02-18  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Adam.
+
+        Moving the drag initiation logic to WebCore.
+        The redundant code in webkit will be moved out in a later patch.
+
+        * WebCoreSupport/WebDragClient.h:
+        * WebCoreSupport/WebDragClient.mm:
+        (getTopHTMLView):
+          Helper function
+        (WebDragClient::willPerformDragSourceAction):
+        (WebDragClient::startDrag):
+        (WebDragClient::createDragImageForLink):
+          Implemented new DragClient methods
+        (WebDragClient::declareAndWriteDragImage):
+          Helper function for the Mac to allow new drag and drop
+          code to match behaviour
+          
+        * WebView/WebHTMLView.mm:
+        (-[WebHTMLView _dragImageForURL:withLabel:]):
+        (-[WebHTMLView _dragImageForLinkElement:]):
+          Refactoring old _dragImageForLinkElement function so that 
+          the link drag image can be created with just a URL and label, 
+          rather than requiring the original element
+        (-[WebHTMLView dragImage:at:offset:event:pasteboard:source:slideBack:]):
+          Removed logic that is no longer necessary                 
+        (-[WebHTMLView _mouseDownEvent]):
+          The WebDragClient may need the original mouseDownEvent of a drag when initiating
+          a drag
+        * WebView/WebHTMLViewInternal.h:
+          Declaring _mouseDownEvent
+
+        * WebView/WebHTMLViewPrivate.h:
+          Declaring _dragImageForURL
+
 2007-02-16  John Sullivan  <sullivan@apple.com>
 
         Reviewed by Tim Hatcher
index cda0599..47c70fe 100644 (file)
@@ -31,9 +31,13 @@ class WebDragClient : public WebCore::DragClient {
 public:
     WebDragClient(WebView*);
     virtual void willPerformDragDestinationAction(WebCore::DragDestinationAction, WebCore::DragData*);
+    virtual void willPerformDragSourceAction(WebCore::DragSourceAction, const WebCore::IntPoint&, WebCore::Clipboard*);
     virtual WebCore::DragDestinationAction actionMaskForDrag(WebCore::DragData*);
     virtual void dragControllerDestroyed();
     virtual WebCore::DragSourceAction dragSourceActionMaskForPoint(const WebCore::IntPoint& windowPoint);
+    virtual void startDrag(WebCore::DragImageRef dragImage, const WebCore::IntPoint& dragPos, const WebCore::IntPoint& eventPos, WebCore::Clipboard*, WebCore::Frame*, bool linkDrag);
+    virtual WebCore::DragImageRef createDragImageForLink(WebCore::KURL& url, const WebCore::String& label, WebCore::Frame*);
+    virtual void declareAndWriteDragImage(NSPasteboard*, DOMElement*, NSURL*, NSString*, WebCore::Frame*, bool canSaveAsWebArchive);
 private:
     WebView* m_webView;
 };
index b75cd57..32b4eba 100644 (file)
 
 #import "WebDragClient.h"
 
+#import "WebArchive.h"
+#import "WebArchiver.h"
+#import "WebDOMOperations.h"
 #import "WebFrame.h"
+#import "WebFrameInternal.h"
+#import "WebHTMLViewInternal.h"
+#import "WebHTMLViewPrivate.h"
+#import "WebNSPasteboardExtras.h"
+#import "WebNSURLExtras.h"
 #import "WebUIDelegate.h"
+#import "WebUIDelegatePrivate.h"
 #import "WebViewInternal.h"
+#import <WebCore/ClipboardMac.h>
 #import <WebCore/DragData.h>
+#import <WebCore/EventHandler.h>
+#import <WebCore/FrameMac.h>
+#import <WebCore/FrameView.h>
+#import <WebCore/Image.h>
+#import <WebCore/Page.h>
+
+using namespace WebCore;
 
 WebDragClient::WebDragClient(WebView* webView)
     : m_webView(webView) 
 {
 }
 
+static WebHTMLView *getTopHTMLView(Frame* frame)
+{
+    ASSERT(frame);
+    ASSERT(frame->page());
+    return (WebHTMLView*)[[kit(frame->page()->mainFrame()) frameView] documentView];
+}
+
 WebCore::DragDestinationAction WebDragClient::actionMaskForDrag(WebCore::DragData* dragData)
 {
     return (WebCore::DragDestinationAction)[[m_webView _UIDelegateForwarder] webView:m_webView dragDestinationActionMaskForDraggingInfo:dragData->platformData()];
@@ -46,10 +70,70 @@ void WebDragClient::willPerformDragDestinationAction(WebCore::DragDestinationAct
 }
 
 
-WebCore::DragSourceAction WebDragClient::dragSourceActionMaskForPoint(const WebCore::IntPoint& windowPoint)
+WebCore::DragSourceAction WebDragClient::dragSourceActionMaskForPoint(const IntPoint& windowPoint)
 {
     NSPoint viewPoint = [m_webView convertPoint:windowPoint fromView:nil];
-    return (WebCore::DragSourceAction)[[m_webView _UIDelegateForwarder] webView:m_webView dragSourceActionMaskForPoint:viewPoint];
+    return (DragSourceAction)[[m_webView _UIDelegateForwarder] webView:m_webView dragSourceActionMaskForPoint:viewPoint];
+}
+
+void WebDragClient::willPerformDragSourceAction(WebCore::DragSourceAction action, const WebCore::IntPoint& mouseDownPoint, WebCore::Clipboard* clipboard)
+{
+    ASSERT(clipboard);
+    [[m_webView _UIDelegateForwarder] webView:m_webView willPerformDragSourceAction:(WebDragSourceAction)action fromPoint:mouseDownPoint withPasteboard:static_cast<WebCore::ClipboardMac*>(clipboard)->pasteboard()];
+}
+
+void WebDragClient::startDrag(DragImageRef dragImage, const IntPoint& at, const IntPoint& eventPos, Clipboard* clipboard, Frame* frame, bool linkDrag)
+{
+    if (!frame)
+        return;
+    ASSERT(clipboard);
+    RetainPtr<WebHTMLView> htmlView = (WebHTMLView*)[[kit(frame) frameView] documentView];
+    if (![htmlView.get() isKindOfClass:[WebHTMLView class]])
+        return;
+    
+    NSEvent *event = linkDrag ? frame->eventHandler()->currentNSEvent() : [htmlView.get() _mouseDownEvent];
+    WebHTMLView* topHTMLView = getTopHTMLView(frame);
+    RetainPtr<WebHTMLView> topViewProtector = topHTMLView;
+    
+    [topHTMLView _stopAutoscrollTimer];
+    NSPasteboard *pasteboard = static_cast<ClipboardMac*>(clipboard)->pasteboard();
+    
+    // note per kwebster, the offset arg below is always ignored in positioning the image
+    id UIDelegate = [m_webView UIDelegate];
+    if ([UIDelegate respondsToSelector:@selector(webView:dragImage:at:offset:event:pasteboard:source:slideBack:forView:)])
+        [UIDelegate webView:m_webView dragImage:dragImage.get() at:(NSPoint)at offset:NSMakeSize(0, 0) event:event pasteboard:pasteboard source:htmlView.get() slideBack:YES forView:topHTMLView];
+    else
+        [topHTMLView dragImage:dragImage.get() at:(NSPoint)at offset:NSMakeSize(0, 0) event:event pasteboard:pasteboard source:htmlView.get() slideBack:YES];
+}
+
+DragImageRef WebDragClient::createDragImageForLink(KURL& url, const String& title, Frame* frame)
+{
+    if (!frame)
+        return nil;
+    WebHTMLView* htmlView = (WebHTMLView*)[[kit(frame) frameView] documentView];
+    NSString *label = 0;
+    if (!title.isEmpty())
+        label = (NSString*)title;
+    return [htmlView _dragImageForURL:[url.getNSURL() _web_userVisibleString] withLabel:label];
+}
+
+
+void WebDragClient::declareAndWriteDragImage(NSPasteboard* pasteboard, DOMElement* element, NSURL* URL, NSString* title, WebCore::Frame* frame, bool canSaveAsWebArchive) 
+{
+    ASSERT(pasteboard);
+    ASSERT(element);
+    id source = (WebHTMLView*)[[kit(frame) frameView] documentView];        
+    
+    WebArchive *archive;
+    
+    // If the image element comes from an ImageDocument, we don't want to 
+    // create a web archive from the image element.
+    if (canSaveAsWebArchive)
+        archive = [element webArchive];
+    else
+        archive = [WebArchiver archiveMainResourceForFrame:kit(frame)];
+    ASSERT(archive);
+    [pasteboard _web_declareAndWriteDragImageForElement:element URL:URL title:title archive:archive source:source];
 }
 
 void WebDragClient::dragControllerDestroyed() 
index 2dd86fc..168e1ff 100644 (file)
@@ -174,6 +174,7 @@ extern "C" void *_NSSoftLinkingGetFrameworkFuncPtr(NSString *inUmbrellaFramework
 #define AUTOSCROLL_INTERVAL             0.1f
 
 #define DRAG_LABEL_BORDER_X             4.0f
+//Keep border_y in synch with DragController::LinkDragBorderInset
 #define DRAG_LABEL_BORDER_Y             2.0f
 #define DRAG_LABEL_RADIUS               5.0f
 #define DRAG_LABEL_BORDER_Y_OFFSET              2.0f
@@ -1255,23 +1256,18 @@ static NSURL* uniqueURLWithRelativePart(NSString *relativePart)
     return [NSArray arrayWithObjects:WebArchivePboardType, NSRTFDPboardType, NSRTFPboardType, NSStringPboardType, nil];
 }
 
-- (NSImage *)_dragImageForLinkElement:(NSDictionary *)element
+- (NSImage *)_dragImageForURL:(NSString*)urlString withLabel:(NSString*)label
 {
-    NSURL *linkURL = [element objectForKey: WebElementLinkURLKey];
-
     BOOL drawURLString = YES;
     BOOL clipURLString = NO, clipLabelString = NO;
     
-    NSString *label = [element objectForKey: WebElementLinkLabelKey];
-    NSString *urlString = [linkURL _web_userVisibleString];
-    
     if (!label) {
         drawURLString = NO;
         label = urlString;
     }
     
     NSFont *labelFont = [[NSFontManager sharedFontManager] convertFont:[NSFont systemFontOfSize:DRAG_LINK_LABEL_FONT_SIZE]
-                                                   toHaveTrait:NSBoldFontMask];
+                                                           toHaveTrait:NSBoldFontMask];
     NSFont *urlFont = [NSFont systemFontOfSize: DRAG_LINK_URL_FONT_SIZE];
     NSSize labelSize;
     labelSize.width = [label _web_widthWithFont: labelFont];
@@ -1311,27 +1307,36 @@ static NSURL* uniqueURLWithRelativePart(NSString *relativePart)
     [path appendBezierPathWithRect: NSMakeRect(0.0f, DRAG_LABEL_RADIUS, DRAG_LABEL_RADIUS + 10.0f, imageSize.height - 2.0f * DRAG_LABEL_RADIUS)];
     [path appendBezierPathWithRect: NSMakeRect(imageSize.width - DRAG_LABEL_RADIUS - 20.0f, DRAG_LABEL_RADIUS, DRAG_LABEL_RADIUS + 20.0f, imageSize.height - 2.0f * DRAG_LABEL_RADIUS)];
     [path fill];
-        
+    
     NSColor *topColor = [NSColor colorWithCalibratedWhite:0.0f alpha:0.75f];
     NSColor *bottomColor = [NSColor colorWithCalibratedWhite:1.0f alpha:0.5f];
     if (drawURLString) {
         if (clipURLString)
             urlString = [WebStringTruncator centerTruncateString: urlString toWidth:imageSize.width - (DRAG_LABEL_BORDER_X * 2.0f) withFont:urlFont];
-
+        
         [urlString _web_drawDoubledAtPoint:NSMakePoint(DRAG_LABEL_BORDER_X, DRAG_LABEL_BORDER_Y - [urlFont descender]) 
-             withTopColor:topColor bottomColor:bottomColor font:urlFont];
+                              withTopColor:topColor bottomColor:bottomColor font:urlFont];
     }
-
+    
     if (clipLabelString)
         label = [WebStringTruncator rightTruncateString: label toWidth:imageSize.width - (DRAG_LABEL_BORDER_X * 2.0f) withFont:labelFont];
     [label _web_drawDoubledAtPoint:NSMakePoint (DRAG_LABEL_BORDER_X, imageSize.height - DRAG_LABEL_BORDER_Y_OFFSET - [labelFont pointSize])
-             withTopColor:topColor bottomColor:bottomColor font:labelFont];
+                      withTopColor:topColor bottomColor:bottomColor font:labelFont];
     
     [dragImage unlockFocus];
     
     return dragImage;
 }
 
+- (NSImage *)_dragImageForLinkElement:(NSDictionary *)element
+{
+    NSURL *linkURL = [element objectForKey: WebElementLinkURLKey];
+    
+    NSString *label = [element objectForKey: WebElementLinkLabelKey];
+    NSString *urlString = [linkURL _web_userVisibleString];
+    return [self _dragImageForURL:urlString withLabel:label];
+}
+
 - (BOOL)_startDraggingImage:(NSImage *)wcDragImage at:(NSPoint)wcDragLoc operation:(NSDragOperation)op event:(NSEvent *)mouseDraggedEvent sourceIsDHTML:(BOOL)srcIsDHTML DHTMLWroteData:(BOOL)dhtmlWroteData
 {
     WebHTMLView *topHTMLView = [self _topHTMLView];
@@ -2883,29 +2888,8 @@ done:
            source:(id)source
         slideBack:(BOOL)slideBack
 {
-    [self _stopAutoscrollTimer];
-
-    WebHTMLView *topHTMLView = [self _topHTMLView];
-    if (self != topHTMLView) {
-        [topHTMLView dragImage:dragImage at:[self convertPoint:at toView:topHTMLView]
-            offset:offset event:event pasteboard:pasteboard source:source slideBack:slideBack];
-        return;
-    }
-
-    WebView *webView = [self _webView];
-    Page *page = core(webView);
-    ASSERT(page);
-    page->dragController()->setDidInitiateDrag(true);
-    
-    // Retain this view during the drag because it may be released before the drag ends.
-    [self retain];
-
-    id UIDelegate = [webView UIDelegate];
-    // If a delegate takes over the drag but never calls draggedImage: endedAt:, we'll leak the WebHTMLView.
-    if ([UIDelegate respondsToSelector:@selector(webView:dragImage:at:offset:event:pasteboard:source:slideBack:forView:)])
-        [UIDelegate webView:webView dragImage:dragImage at:at offset:offset event:event pasteboard:pasteboard source:source slideBack:slideBack forView:self];
-    else
-        [super dragImage:dragImage at:at offset:offset event:event pasteboard:pasteboard source:source slideBack:slideBack];
+    ASSERT(self == [self _topHTMLView]);
+    [super dragImage:dragImage at:at offset:offset event:event pasteboard:pasteboard source:source slideBack:slideBack];
 }
 
 - (void)mouseDragged:(NSEvent *)event
@@ -2981,9 +2965,6 @@ done:
                                              context:[[NSApp currentEvent] context]
                                          eventNumber:0 clickCount:0 pressure:0];
     [self mouseUp:fakeEvent]; // This will also update the mouseover state.
-    
-    // Balance the previous retain from when the drag started.
-    [self release];
 }
 
 - (NSArray *)namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination
@@ -4938,6 +4919,12 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
     return textView == _private->firstResponderTextViewAtMouseDownTime;
 }
 
+
+- (NSEvent *)_mouseDownEvent
+{
+    return _private->mouseDownEvent;
+}
+
 - (void)_pauseNullEventsForAllNetscapePlugins
 {
     NSArray *subviews = [self subviews];
index a4f5cad..22b08bd 100644 (file)
@@ -112,6 +112,7 @@ struct WebHTMLViewInterpretKeyEventsParameters;
 - (void)_hoverFeedbackSuspendedChanged;
 - (BOOL)_interceptEditingKeyEvent:(WebCore::KeyboardEvent *)event;
 - (DOMDocumentFragment*)_documentFragmentFromPasteboard:(NSPasteboard *)pasteboard;
+- (NSEvent *)_mouseDownEvent;
 #ifndef BUILDING_ON_TIGER
 - (BOOL)isGrammarCheckingEnabled;
 - (void)setGrammarCheckingEnabled:(BOOL)flag;
index f6e4eaa..9a25619 100644 (file)
@@ -69,6 +69,7 @@
 - (void)_frameOrBoundsChanged;
 
 - (NSImage *)_dragImageForLinkElement:(NSDictionary *)element;
+- (NSImage *)_dragImageForURL:(NSString*)linkURL withLabel:(NSString*)label;
 - (BOOL)_startDraggingImage:(NSImage *)dragImage at:(NSPoint)dragLoc operation:(NSDragOperation)op event:(NSEvent *)event sourceIsDHTML:(BOOL)flag DHTMLWroteData:(BOOL)dhtmlWroteData;
 - (void)_handleAutoscrollForMouseDragged:(NSEvent *)event;
 - (WebPluginController *)_pluginController;