WebKit2: add support for drag and drop
authorenrica@apple.com <enrica@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 20 Jan 2011 01:56:45 +0000 (01:56 +0000)
committerenrica@apple.com <enrica@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 20 Jan 2011 01:56:45 +0000 (01:56 +0000)
https://bugs.webkit.org/show_bug.cgi?id=52343
<rdar://problem/7660558>

Reviewed by Darin Adler.

This patch contains the remaining work to support drag and drop on Mac.
I've added a PasteboardTypes class to encapsulate all the pasteboard formats
supported for drag and drop.
In this implementation we don't support the promised types, since I could not
find an efficient way to do this across processes.
The bulk of the patch consists in creating a shareable bitmap for the drag image,
pass its handle to the UI process and create a new NSImage from it to be given to
AppKit for dragging.
I've added the missing implementation of the methods in the drag client to hook
up the placement of the data in the pasteboard.

* Shared/mac/PasteboardTypes.h: Added.
* Shared/mac/PasteboardTypes.mm: Added.
(WebKit::PasteboardTypes::forEditing):
(WebKit::PasteboardTypes::forURL):
(WebKit::PasteboardTypes::forImages):
(WebKit::PasteboardTypes::forImagesWithArchive):
* UIProcess/API/mac/PageClientImpl.h:
* UIProcess/API/mac/PageClientImpl.mm:
(WebKit::PageClientImpl::setDragImage): Added.
* UIProcess/API/mac/WKView.mm:
(-[WKView _registerDraggedTypes]): Refactored to use the new PasteboardTypes class.
(-[WKView initWithFrame:contextRef:pageGroupRef:]):
(-[WKView _setMouseDownEvent:]):
(-[WKView _mouseHandler:]):
(-[WKView mouseDown:]):
(-[WKView mouseUp:]):
(-[WKView mouseDragged:]):
(-[WKView draggedImage:endedAt:operation:]):
(-[WKView draggingEntered:]):
(-[WKView _setDragImage:at:linkDrag:]):
* UIProcess/API/mac/WKViewInternal.h:
* UIProcess/PageClient.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::setDragImage):
(WebKit::WebPageProxy::dragEnded):
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:
* WebKit2.xcodeproj/project.pbxproj:
* WebProcess/WebCoreSupport/WebDragClient.cpp:
* WebProcess/WebCoreSupport/WebDragClient.h:
* WebProcess/WebCoreSupport/mac/WebDragClientMac.mm: Added.
(WebKit::fontFromNSFont):
(WebKit::WebDragClient::startDrag): Added implementation.
(WebKit::WebDragClient::createDragImageForLink): Ditto.
(WebKit::writeURL): Helper function.
(WebKit::writeImage): Helper function.
(WebKit::WebDragClient::declareAndWriteDragImage): Added implementation.
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::dragEnded):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:

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

18 files changed:
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/mac/PasteboardTypes.h [new file with mode: 0644]
Source/WebKit2/Shared/mac/PasteboardTypes.mm [new file with mode: 0644]
Source/WebKit2/UIProcess/API/mac/PageClientImpl.h
Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm
Source/WebKit2/UIProcess/API/mac/WKView.mm
Source/WebKit2/UIProcess/API/mac/WKViewInternal.h
Source/WebKit2/UIProcess/PageClient.h
Source/WebKit2/UIProcess/WebPageProxy.cpp
Source/WebKit2/UIProcess/WebPageProxy.h
Source/WebKit2/UIProcess/WebPageProxy.messages.in
Source/WebKit2/WebKit2.xcodeproj/project.pbxproj
Source/WebKit2/WebProcess/WebCoreSupport/WebDragClient.cpp
Source/WebKit2/WebProcess/WebCoreSupport/WebDragClient.h
Source/WebKit2/WebProcess/WebCoreSupport/mac/WebDragClientMac.mm [new file with mode: 0644]
Source/WebKit2/WebProcess/WebPage/WebPage.cpp
Source/WebKit2/WebProcess/WebPage/WebPage.h
Source/WebKit2/WebProcess/WebPage/WebPage.messages.in

index d737116..d142803 100644 (file)
@@ -1,3 +1,64 @@
+2011-01-19  Enrica Casucci  <enrica@apple.com>
+
+        Reviewed by Darin Adler.
+
+        WebKit2: add support for drag and drop
+        https://bugs.webkit.org/show_bug.cgi?id=52343
+        <rdar://problem/7660558>
+        
+        This patch contains the remaining work to support drag and drop on Mac.
+        I've added a PasteboardTypes class to encapsulate all the pasteboard formats
+        supported for drag and drop.
+        In this implementation we don't support the promised types, since I could not
+        find an efficient way to do this across processes.
+        The bulk of the patch consists in creating a shareable bitmap for the drag image,
+        pass its handle to the UI process and create a new NSImage from it to be given to
+        AppKit for dragging.
+        I've added the missing implementation of the methods in the drag client to hook
+        up the placement of the data in the pasteboard.
+        
+        * Shared/mac/PasteboardTypes.h: Added.
+        * Shared/mac/PasteboardTypes.mm: Added.
+        (WebKit::PasteboardTypes::forEditing):
+        (WebKit::PasteboardTypes::forURL):
+        (WebKit::PasteboardTypes::forImages):
+        (WebKit::PasteboardTypes::forImagesWithArchive):
+        * UIProcess/API/mac/PageClientImpl.h:
+        * UIProcess/API/mac/PageClientImpl.mm:
+        (WebKit::PageClientImpl::setDragImage): Added.
+        * UIProcess/API/mac/WKView.mm:
+        (-[WKView _registerDraggedTypes]): Refactored to use the new PasteboardTypes class.
+        (-[WKView initWithFrame:contextRef:pageGroupRef:]):
+        (-[WKView _setMouseDownEvent:]):
+        (-[WKView _mouseHandler:]):
+        (-[WKView mouseDown:]):
+        (-[WKView mouseUp:]):
+        (-[WKView mouseDragged:]):
+        (-[WKView draggedImage:endedAt:operation:]):
+        (-[WKView draggingEntered:]):
+        (-[WKView _setDragImage:at:linkDrag:]):
+        * UIProcess/API/mac/WKViewInternal.h:
+        * UIProcess/PageClient.h:
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::setDragImage):
+        (WebKit::WebPageProxy::dragEnded):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+        * WebKit2.xcodeproj/project.pbxproj:
+        * WebProcess/WebCoreSupport/WebDragClient.cpp:
+        * WebProcess/WebCoreSupport/WebDragClient.h:
+        * WebProcess/WebCoreSupport/mac/WebDragClientMac.mm: Added.
+        (WebKit::fontFromNSFont):
+        (WebKit::WebDragClient::startDrag): Added implementation.
+        (WebKit::WebDragClient::createDragImageForLink): Ditto.
+        (WebKit::writeURL): Helper function.
+        (WebKit::writeImage): Helper function.
+        (WebKit::WebDragClient::declareAndWriteDragImage): Added implementation.
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::dragEnded):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+
 2011-01-19  Anders Carlsson  <andersca@apple.com>
 
         Reviewed by Dan Bernstein.
diff --git a/Source/WebKit2/Shared/mac/PasteboardTypes.h b/Source/WebKit2/Shared/mac/PasteboardTypes.h
new file mode 100644 (file)
index 0000000..712c4c0
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2011 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 INC. AND ITS CONTRIBUTORS ``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 INC. OR ITS 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 PasteboardTypes_h
+#define PasteboardTypes_h
+
+namespace WebKit {
+
+class PasteboardTypes {
+public:
+    static NSString * const WebArchivePboardType;
+    static NSString * const WebURLsWithTitlesPboardType;
+    static NSString * const WebURLPboardType;
+    static NSString * const WebURLNamePboardType;
+    
+    static NSArray *forEditing();
+    static NSArray *forURL();
+    static NSArray *forImages();
+    static NSArray *forImagesWithArchive();
+};
+
+} // namespace WebKit
+
+#endif // PasteboardTypes_h
diff --git a/Source/WebKit2/Shared/mac/PasteboardTypes.mm b/Source/WebKit2/Shared/mac/PasteboardTypes.mm
new file mode 100644 (file)
index 0000000..380e24c
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2011 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 INC. AND ITS CONTRIBUTORS ``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 INC. OR ITS 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 "PasteboardTypes.h"
+#import <wtf/RetainPtr.h>
+
+namespace WebKit {
+
+NSString * const PasteboardTypes::WebArchivePboardType = @"Apple Web Archive pasteboard type";
+NSString * const PasteboardTypes::WebURLsWithTitlesPboardType = @"WebURLsWithTitlesPboardType";
+NSString * const PasteboardTypes::WebURLPboardType = @"public.url";
+NSString * const PasteboardTypes::WebURLNamePboardType = @"public.url-name";
+
+static inline NSArray *retain(NSArray *array)
+{
+    CFRetain(array);
+    return array;
+}
+    
+NSArray* PasteboardTypes::forEditing()
+{
+    static NSArray *types = retain([NSArray arrayWithObjects:WebArchivePboardType, NSHTMLPboardType, NSFilenamesPboardType, NSTIFFPboardType, NSPDFPboardType,
+#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
+        NSPICTPboardType,
+#endif
+        NSURLPboardType, NSRTFDPboardType, NSRTFPboardType, NSStringPboardType, NSColorPboardType, kUTTypePNG, nil]);
+    return types;
+}
+
+NSArray* PasteboardTypes::forURL()
+{
+    static NSArray *types = retain([NSArray arrayWithObjects:WebURLsWithTitlesPboardType, NSURLPboardType, WebURLPboardType,  WebURLNamePboardType, NSStringPboardType, NSFilenamesPboardType, nil]);
+    return types;
+}
+
+NSArray* PasteboardTypes::forImages()
+{
+    static NSArray *types = retain([NSArray arrayWithObjects:NSTIFFPboardType, WebURLsWithTitlesPboardType, NSURLPboardType, WebURLPboardType, WebURLNamePboardType, NSStringPboardType, nil]);
+    return types;
+}
+
+NSArray* PasteboardTypes::forImagesWithArchive()
+{
+    static NSArray *types = retain([NSArray arrayWithObjects:NSTIFFPboardType, WebURLsWithTitlesPboardType, NSURLPboardType, WebURLPboardType, WebURLNamePboardType, NSStringPboardType, NSRTFDPboardType, WebArchivePboardType, nil]);
+    return types;
+}
+    
+} // namespace WebKit
index 35a72c6..625b8f6 100644 (file)
@@ -70,6 +70,7 @@ private:
     virtual void clearAllEditCommands();
     virtual void setEditCommandState(const String& commandName, bool isEnabled, int state);
     virtual void interceptKeyEvent(const NativeWebKeyboardEvent& event, Vector<WebCore::KeypressCommand>& commandName, uint32_t selectionStart, uint32_t selectionEnd, Vector<WebCore::CompositionUnderline>& underlines);
+    virtual void setDragImage(const WebCore::IntPoint& clientPosition, const WebCore::IntSize& imageSize, PassRefPtr<ShareableBitmap> dragImage, bool isLinkDrag);
 
     virtual WebCore::FloatRect convertToDeviceSpace(const WebCore::FloatRect&);
     virtual WebCore::FloatRect convertToUserSpace(const WebCore::FloatRect&);
index 5c00aff..60be5bc 100644 (file)
@@ -37,6 +37,7 @@
 #import <WebCore/Cursor.h>
 #import <WebCore/FloatRect.h>
 #import <WebCore/FoundationExtras.h>
+#import <WebCore/GraphicsContext.h>
 #import <WebCore/KeyboardEvent.h>
 #import <wtf/PassOwnPtr.h>
 #import <wtf/text/CString.h>
@@ -278,6 +279,14 @@ void PageClientImpl::interceptKeyEvent(const NativeWebKeyboardEvent& event, Vect
     [m_wkView _getTextInputState:selectionStart selectionEnd:selectionEnd underlines:underlines];
 }
 
+void PageClientImpl::setDragImage(const IntPoint& clientPosition, const IntSize& imageSize, PassRefPtr<ShareableBitmap> dragImage, bool isLinkDrag)
+{
+    OwnPtr<GraphicsContext> graphicsContext = dragImage->createGraphicsContext();
+    RetainPtr<NSImage> dragNSImage(AdoptNS, [[NSImage alloc] initWithCGImage:CGBitmapContextCreateImage(graphicsContext->platformContext()) size:imageSize]);
+    [dragNSImage.get() setFlipped:YES];
+    [m_wkView _setDragImage:dragNSImage.get() at:clientPosition linkDrag:isLinkDrag];
+}
+    
 FloatRect PageClientImpl::convertToDeviceSpace(const FloatRect& rect)
 {
     return [m_wkView _convertToDeviceSpace:rect];
index d634909..60dc40f 100644 (file)
@@ -35,6 +35,7 @@
 #import "NativeWebKeyboardEvent.h"
 #import "PDFViewController.h"
 #import "PageClientImpl.h"
+#import "PasteboardTypes.h"
 #import "PrintInfo.h"
 #import "RunLoop.h"
 #import "TextChecker.h"
@@ -138,6 +139,9 @@ NSString* const WebKitOriginalBottomPrintingMarginKey = @"WebKitOriginalBottomMa
 
     bool _inBecomeFirstResponder;
     bool _inResignFirstResponder;
+    NSEvent *_mouseDownEvent;
+    BOOL _ignoringMouseDraggedEvents;
+    BOOL _dragHasStarted;
 }
 @end
 
@@ -198,21 +202,10 @@ static bool useNewDrawingArea()
     return [self initWithFrame:frame contextRef:contextRef pageGroupRef:nil];
 }
 
-static NSString * const WebArchivePboardType = @"Apple Web Archive pasteboard type";
-static NSString * const WebURLsWithTitlesPboardType = @"WebURLsWithTitlesPboardType";
-static NSString * const WebURLPboardType = @"public.url";
-static NSString * const WebURLNamePboardType = @"public.url-name";
-
 - (void)_registerDraggedTypes
 {
-    NSArray *editableTypes = [NSArray arrayWithObjects:WebArchivePboardType, NSHTMLPboardType, NSFilenamesPboardType, NSTIFFPboardType, NSPDFPboardType,
-#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
-        NSPICTPboardType,
-#endif
-        NSURLPboardType, NSRTFDPboardType, NSRTFPboardType, NSStringPboardType, NSColorPboardType, kUTTypePNG, nil];
-    NSArray *URLTypes = [NSArray arrayWithObjects:WebURLsWithTitlesPboardType, NSURLPboardType, WebURLPboardType,  WebURLNamePboardType, NSStringPboardType, NSFilenamesPboardType, nil];
-    NSMutableSet *types = [[NSMutableSet alloc] initWithArray:editableTypes];
-    [types addObjectsFromArray:URLTypes];
+    NSMutableSet *types = [[NSMutableSet alloc] initWithArray:PasteboardTypes::forEditing()];
+    [types addObjectsFromArray:PasteboardTypes::forURL()];
     [self registerForDraggedTypes:[types allObjects]];
     [types release];
 }
@@ -238,6 +231,8 @@ static NSString * const WebURLNamePboardType = @"public.url-name";
     _data->_pageClient = PageClientImpl::create(self);
     _data->_page = toImpl(contextRef)->createWebPage(_data->_pageClient.get(), toImpl(pageGroupRef));
     _data->_page->initializeWebPage();
+    _data->_mouseDownEvent = nil;
+    _data->_ignoringMouseDraggedEvents = NO;
 
     [self _registerDraggedTypes];
 
@@ -732,6 +727,17 @@ static void speakString(WKStringRef string, WKErrorRef error, void*)
     return YES;
 }
 
+- (void)_setMouseDownEvent:(NSEvent *)event
+{
+    ASSERT(!event || [event type] == NSLeftMouseDown || [event type] == NSRightMouseDown || [event type] == NSOtherMouseDown);
+    
+    if (event == _data->_mouseDownEvent)
+        return;
+    
+    [_data->_mouseDownEvent release];
+    _data->_mouseDownEvent = [event retain];
+}
+
 #define EVENT_HANDLER(Selector, Type) \
     - (void)Selector:(NSEvent *)theEvent \
     { \
@@ -754,21 +760,35 @@ EVENT_HANDLER(scrollWheel, Wheel)
 
 #undef EVENT_HANDLER
 
-#define MOUSE_EVENT_HANDLER(Selector) \
-    - (void)Selector:(NSEvent *)theEvent \
-    { \
-        NSInputManager *currentInputManager = [NSInputManager currentInputManager]; \
-        if ([currentInputManager wantsToHandleMouseEvents] && [currentInputManager handleMouseEvent:theEvent]) \
-            return; \
-        WebMouseEvent webEvent = WebEventFactory::createWebMouseEvent(theEvent, self); \
-        _data->_page->handleMouseEvent(webEvent); \
-    }
+- (void)_mouseHandler:(NSEvent *)event
+{
+    NSInputManager *currentInputManager = [NSInputManager currentInputManager];
+    if ([currentInputManager wantsToHandleMouseEvents] && [currentInputManager handleMouseEvent:event])
+        return;
+    WebMouseEvent webEvent = WebEventFactory::createWebMouseEvent(event, self);
+    _data->_page->handleMouseEvent(webEvent);
+}
+
+- (void)mouseDown:(NSEvent *)event
+{
+    [self _setMouseDownEvent:event];
+    _data->_ignoringMouseDraggedEvents = NO;
+    _data->_dragHasStarted = NO;
+    [self _mouseHandler:event];
+}
 
-MOUSE_EVENT_HANDLER(mouseDown)
-MOUSE_EVENT_HANDLER(mouseDragged)
-MOUSE_EVENT_HANDLER(mouseUp)
+- (void)mouseUp:(NSEvent *)event
+{
+    [self _setMouseDownEvent:nil];
+    [self _mouseHandler:event];
+}
 
-#undef MOUSE_EVENT_HANDLER
+- (void)mouseDragged:(NSEvent *)event
+{
+    if (_data->_ignoringMouseDraggedEvents)
+        return;
+    [self _mouseHandler:event];
+}
 
 - (void)doCommandBySelector:(SEL)selector
 {
@@ -1042,6 +1062,17 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde
     return resultRect;
 }
 
+- (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation
+{
+    NSPoint windowImageLoc = [[self window] convertScreenToBase:aPoint];
+    NSPoint windowMouseLoc = windowImageLoc;
+   
+    // Prevent queued mouseDragged events from coming after the drag and fake mouseUp event.
+    _data->_ignoringMouseDraggedEvents = YES;
+    
+    _data->_page->dragEnded(IntPoint(windowMouseLoc), globalPoint(windowMouseLoc, [self window]), operation);
+}
+
 - (DragApplicationFlags)applicationFlags:(id <NSDraggingInfo>)draggingInfo
 {
     uint32_t flags = 0;
@@ -1061,7 +1092,8 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde
     IntPoint client([self convertPoint:[draggingInfo draggingLocation] fromView:nil]);
     IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
     DragData dragData(draggingInfo, client, global, static_cast<DragOperation>([draggingInfo draggingSourceOperationMask]), [self applicationFlags:draggingInfo]);
-    
+
+    _data->_page->resetDragOperation();
     _data->_page->performDragControllerAction(DragControllerActionEntered, &dragData, [[draggingInfo draggingPasteboard] name]);
     return NSDragOperationCopy;
 }
@@ -1870,4 +1902,22 @@ static float currentPrintOperationScale()
     _data->_pdfViewController->setZoomFactor(zoomFactor);
 }
 
+- (void)_setDragImage:(NSImage *)image at:(NSPoint)clientPoint linkDrag:(BOOL)linkDrag
+{
+    // We need to prevent re-entering this call to avoid crashing in AppKit.
+    // Given the asynchronous nature of WebKit2 this can now happen.
+    if (_data->_dragHasStarted)
+        return;
+    
+    _data->_dragHasStarted = YES;
+    [super dragImage:image
+                  at:clientPoint
+              offset:NSZeroSize
+               event:(linkDrag) ? [NSApp currentEvent] :_data->_mouseDownEvent
+          pasteboard:[NSPasteboard pasteboardWithName:NSDragPboard]
+              source:self
+           slideBack:YES];
+    _data->_dragHasStarted = NO;
+}
+
 @end
index 1c70b38..cba241d 100644 (file)
@@ -62,5 +62,6 @@ namespace WebKit {
 - (void)_didFinishLoadingDataForCustomRepresentation:(const CoreIPC::DataReference&)dataReference;
 - (double)_customRepresentationZoomFactor;
 - (void)_setCustomRepresentationZoomFactor:(double)zoomFactor;
+- (void)_setDragImage:(NSImage *)image at:(NSPoint)clientPoint linkDrag:(BOOL)linkDrag;
 
 @end
index 4b0a1f4..e483aef 100644 (file)
@@ -26,6 +26,7 @@
 #ifndef PageClient_h
 #define PageClient_h
 
+#include "ShareableBitmap.h"
 #include "WebPageProxy.h"
 #include "WebPopupMenuProxy.h"
 #include <wtf/Forward.h>
@@ -98,7 +99,8 @@ public:
     virtual void setEditCommandState(const String& commandName, bool isEnabled, int state) = 0;
 #if PLATFORM(MAC)
     virtual void accessibilityChildTokenReceived(const CoreIPC::DataReference&) = 0;
-    virtual void interceptKeyEvent(const NativeWebKeyboardEvent&, Vector<WebCore::KeypressCommand>&, uint32_t, uint32_t, Vector<WebCore::CompositionUnderline>&) = 0;
+    virtual void interceptKeyEvent(const NativeWebKeyboardEvent&, Vector<WebCore::KeypressCommand>& commandName, uint32_t selectionStart, uint32_t selectionEnd, Vector<WebCore::CompositionUnderline>& underlines) = 0;
+    virtual void setDragImage(const WebCore::IntPoint& clientPosition, const WebCore::IntSize& imageSize, PassRefPtr<ShareableBitmap> dragImage, bool isLinkDrag) = 0;
 #endif
 #if PLATFORM(WIN)
     virtual void compositionSelectionChanged(bool) = 0;
index f76972d..cca2d7c 100644 (file)
@@ -617,6 +617,24 @@ void WebPageProxy::didPerformDragControllerAction(uint64_t resultOperation)
     m_currentDragOperation = static_cast<DragOperation>(resultOperation);
 }
 
+#if PLATFORM(MAC)
+void WebPageProxy::setDragImage(const WebCore::IntPoint& clientPosition, const IntSize& imageSize, const SharedMemory::Handle& dragImageHandle, bool isLinkDrag)
+{
+    RefPtr<ShareableBitmap> dragImage = ShareableBitmap::create(imageSize, dragImageHandle);
+    if (!dragImage)
+        return;
+    
+    m_pageClient->setDragImage(clientPosition, imageSize, dragImage.release(), isLinkDrag);
+}
+#endif
+
+void WebPageProxy::dragEnded(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition, uint64_t operation)
+{
+    if (!isValid())
+        return;
+    process()->send(Messages::WebPage::DragEnded(clientPosition, globalPosition, operation), m_pageID);
+}
+
 void WebPageProxy::handleMouseEvent(const WebMouseEvent& event)
 {
     if (!isValid())
index 8456c9c..ad8424e 100644 (file)
@@ -286,7 +286,10 @@ public:
     // Drag and drop support.
     void performDragControllerAction(DragControllerAction, WebCore::DragData*, const String&);
     void didPerformDragControllerAction(uint64_t resultOperation);
-
+    void dragEnded(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition, uint64_t operation);
+#if PLATFORM(MAC)
+    void setDragImage(const WebCore::IntPoint& clientPosition, const WebCore::IntSize& imageSize, const SharedMemory::Handle& dragImageHandle, bool isLinkDrag);
+#endif
     void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*);
     void didReceiveSyncMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*, CoreIPC::ArgumentEncoder*);
 
index 2d576be..7b63eff 100644 (file)
@@ -189,4 +189,7 @@ messages -> WebPageProxy {
     
     # Drag and drop.
     DidPerformDragControllerAction(uint64_t resultOperation)
+#if PLATFORM(MAC)
+    SetDragImage(WebCore::IntPoint clientPosition, WebCore::IntSize imageSize, WebKit::SharedMemory::Handle dragImageHandle, bool linkDrag)
+#endif
 }
index 20143f5..b83c16c 100644 (file)
                C0E3AA7C1209E83C00A49D01 /* Module.h in Headers */ = {isa = PBXBuildFile; fileRef = C0E3AA441209E2BA00A49D01 /* Module.h */; };
                C517388112DF8F4F00EE3F47 /* DragControllerAction.h in Headers */ = {isa = PBXBuildFile; fileRef = C517388012DF8F4F00EE3F47 /* DragControllerAction.h */; };
                C5237F6012441CA300780472 /* WebEditorClientMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = C5237F5F12441CA300780472 /* WebEditorClientMac.mm */; };
+               C574A37712E6099D002DFE98 /* WebDragClientMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = C554FFA212E4E8EA002F22C0 /* WebDragClientMac.mm */; };
+               C574A58112E66681002DFE98 /* PasteboardTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = C574A57F12E66681002DFE98 /* PasteboardTypes.h */; };
+               C574A58212E66681002DFE98 /* PasteboardTypes.mm in Sources */ = {isa = PBXBuildFile; fileRef = C574A58012E66681002DFE98 /* PasteboardTypes.mm */; };
                D3B9484611FF4B6500032B39 /* WebPopupMenu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3B9484211FF4B6500032B39 /* WebPopupMenu.cpp */; };
                D3B9484711FF4B6500032B39 /* WebPopupMenu.h in Headers */ = {isa = PBXBuildFile; fileRef = D3B9484311FF4B6500032B39 /* WebPopupMenu.h */; };
                D3B9484811FF4B6500032B39 /* WebSearchPopupMenu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3B9484411FF4B6500032B39 /* WebSearchPopupMenu.cpp */; };
                C0E3AA481209E45000A49D01 /* ModuleMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ModuleMac.mm; sourceTree = "<group>"; };
                C517388012DF8F4F00EE3F47 /* DragControllerAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DragControllerAction.h; sourceTree = "<group>"; };
                C5237F5F12441CA300780472 /* WebEditorClientMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebEditorClientMac.mm; sourceTree = "<group>"; };
+               C554FFA212E4E8EA002F22C0 /* WebDragClientMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebDragClientMac.mm; sourceTree = "<group>"; };
+               C574A57F12E66681002DFE98 /* PasteboardTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PasteboardTypes.h; sourceTree = "<group>"; };
+               C574A58012E66681002DFE98 /* PasteboardTypes.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PasteboardTypes.mm; sourceTree = "<group>"; };
                D3B9484211FF4B6500032B39 /* WebPopupMenu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebPopupMenu.cpp; sourceTree = "<group>"; };
                D3B9484311FF4B6500032B39 /* WebPopupMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPopupMenu.h; sourceTree = "<group>"; };
                D3B9484411FF4B6500032B39 /* WebSearchPopupMenu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebSearchPopupMenu.cpp; sourceTree = "<group>"; };
                BC111ADE112F5B9A00337BAB /* mac */ = {
                        isa = PBXGroup;
                        children = (
+                               C554FFA212E4E8EA002F22C0 /* WebDragClientMac.mm */,
                                51021E9B12B16788005C033C /* WebContextMenuClientMac.mm */,
                                F6A25FD812ADC6BD00DC40CC /* WebDatabaseManagerMac.mm */,
                                C5237F5F12441CA300780472 /* WebEditorClientMac.mm */,
                BC111B5A112F628200337BAB /* mac */ = {
                        isa = PBXGroup;
                        children = (
+                               C574A57F12E66681002DFE98 /* PasteboardTypes.h */,
+                               C574A58012E66681002DFE98 /* PasteboardTypes.mm */,
                                1A6F9FB611E1408500DB1371 /* CommandLineMac.cpp */,
                                C02BFF1D1251502E009CCBEA /* NativeWebKeyboardEventMac.mm */,
                                BCF505E61243047B005955AE /* PlatformCertificateInfo.mm */,
                                1A64256812DE42EC00CAAE2C /* BackingStore.h in Headers */,
                                C517388112DF8F4F00EE3F47 /* DragControllerAction.h in Headers */,
                                1AA2E51D12E4C05E00BC4966 /* CGUtilities.h in Headers */,
+                               C574A58112E66681002DFE98 /* PasteboardTypes.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                1A64256912DE42EC00CAAE2C /* BackingStore.cpp in Sources */,
                                1A64292D12DE5F9800CAAE2C /* BackingStoreMac.mm in Sources */,
                                1AA2E51E12E4C05E00BC4966 /* CGUtilities.cpp in Sources */,
+                               C574A37712E6099D002DFE98 /* WebDragClientMac.mm in Sources */,
+                               C574A58212E66681002DFE98 /* PasteboardTypes.mm in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index d11017f..e3d401d 100644 (file)
@@ -50,6 +50,7 @@ DragSourceAction WebDragClient::dragSourceActionMaskForPoint(const IntPoint& win
     return DragSourceActionAny;
 }
 
+#if !PLATFORM(MAC)
 void WebDragClient::startDrag(DragImageRef, const IntPoint&, const IntPoint&, Clipboard*, Frame*, bool)
 {
 }
@@ -59,6 +60,7 @@ DragImageRef WebDragClient::createDragImageForLink(KURL&, const String&, Frame*)
     notImplemented();
     return 0;
 }
+#endif
 
 void WebDragClient::dragControllerDestroyed()
 {
index ce123c8..6f7cf85 100644 (file)
@@ -48,6 +48,9 @@ private:
     virtual void startDrag(WebCore::DragImageRef dragImage, const WebCore::IntPoint& dragImageOrigin, const WebCore::IntPoint& eventPos, WebCore::Clipboard*, WebCore::Frame*, bool linkDrag = false);
     virtual WebCore::DragImageRef createDragImageForLink(WebCore::KURL&, const String& label, WebCore::Frame*);
 
+#if PLATFORM(MAC)
+    virtual void declareAndWriteDragImage(NSPasteboard*, DOMElement*, NSURL*, NSString*, WebCore::Frame*);
+#endif
     virtual void dragControllerDestroyed();
 
     WebPage* m_page;
diff --git a/Source/WebKit2/WebProcess/WebCoreSupport/mac/WebDragClientMac.mm b/Source/WebKit2/WebProcess/WebCoreSupport/mac/WebDragClientMac.mm
new file mode 100644 (file)
index 0000000..9952e3f
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2011 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 INC. AND ITS CONTRIBUTORS ``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 INC. OR ITS 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 "PasteboardTypes.h"
+#import "ShareableBitmap.h"
+#import "WebCoreArgumentCoders.h"
+#import "WebDragClient.h"
+#import "WebPage.h"
+#import "WebPageProxyMessages.h"
+#import <WebCore/CachedImage.h>
+#import <WebCore/DOMPrivate.h>
+#import <WebCore/DOMElementInternal.h>
+#import <WebCore/FrameView.h>
+#import <WebCore/GraphicsContext.h>
+#import <WebCore/LegacyWebArchive.h>
+#import <WebCore/RenderImage.h>
+#import <WebCore/StringTruncator.h>
+#import <wtf/StdLibExtras.h>
+#import <WebKit/WebKitNSStringExtras.h>
+#import <WebKit/WebNSURLExtras.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+const float DragLabelBorderX = 4;
+//Keep border_y in synch with DragController::LinkDragBorderInset
+const float DragLabelBorderY = 2;
+const float DragLabelRadius = 5;
+const float LabelBorderYOffset = 2;
+
+const float MinDragLabelWidthBeforeClip = 120;
+const float MaxDragLabelWidth = 320;
+
+const float DragLinkLabelFontsize = 11;
+const float DragLinkUrlFontSize = 10;
+
+using namespace WebCore;
+
+static Font& fontFromNSFont(NSFont *font)
+{
+    static NSFont *currentFont;
+    DEFINE_STATIC_LOCAL(Font, currentRenderer, ());
+    
+    if ([font isEqual:currentFont])
+        return currentRenderer;
+    if (currentFont)
+        CFRelease(currentFont);
+    currentFont = font;
+    CFRetain(currentFont);
+    currentRenderer = Font(FontPlatformData(font, [font pointSize]), ![[NSGraphicsContext currentContext] isDrawingToScreen]);
+    return currentRenderer;
+}
+    
+void WebDragClient::startDrag(DragImageRef dragImage, const IntPoint& at, const IntPoint& eventPos, Clipboard* clipboard, Frame* frame, bool linkDrag)
+{
+    if (!frame)
+        return;
+    ASSERT(clipboard);
+    
+    NSImage *dragNSImage = dragImage.get();
+    RefPtr<ShareableBitmap> dragShareableImage = ShareableBitmap::createShareable(IntSize([dragNSImage size]));
+    OwnPtr<GraphicsContext> graphicsContext = dragShareableImage->createGraphicsContext();
+
+    [NSGraphicsContext saveGraphicsState];
+    NSGraphicsContext* bitmapContext = [NSGraphicsContext graphicsContextWithGraphicsPort:graphicsContext->platformContext() flipped:YES];
+    [NSGraphicsContext setCurrentContext: bitmapContext];
+    
+    [dragNSImage drawInRect:NSMakeRect(0, 0, [dragNSImage size].width , [dragNSImage size].height) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1];
+    [NSGraphicsContext restoreGraphicsState];
+    SharedMemory::Handle handle;
+    if (!dragShareableImage->createHandle(handle))
+        return;
+    IntPoint clientPoint(at);
+    m_page->send(Messages::WebPageProxy::SetDragImage(clientPoint, IntSize([dragNSImage size]), handle, linkDrag));
+}
+
+DragImageRef WebDragClient::createDragImageForLink(KURL& url, const String& title, Frame* frame)
+{
+    if (!frame)
+        return nil;
+    NSString *label = 0;
+    if (!title.isEmpty())
+        label = title;
+    NSURL *cocoaURL = url;
+    NSString *urlString = [cocoaURL _web_userVisibleString];
+    
+    BOOL drawURLString = YES;
+    BOOL clipURLString = NO;
+    BOOL clipLabelString = NO;
+    
+    if (!label) {
+        drawURLString = NO;
+        label = urlString;
+    }
+    
+    NSFont *labelFont = [[NSFontManager sharedFontManager] convertFont:[NSFont systemFontOfSize:DragLinkLabelFontsize]
+                                                           toHaveTrait:NSBoldFontMask];
+    NSFont *urlFont = [NSFont systemFontOfSize:DragLinkUrlFontSize];
+    NSSize labelSize;
+    labelSize.width = [label _web_widthWithFont: labelFont];
+    labelSize.height = [labelFont ascender] - [labelFont descender];
+    if (labelSize.width > MaxDragLabelWidth){
+        labelSize.width = MaxDragLabelWidth;
+        clipLabelString = YES;
+    }
+    
+    NSSize imageSize;
+    imageSize.width = labelSize.width + DragLabelBorderX * 2;
+    imageSize.height = labelSize.height + DragLabelBorderY * 2;
+    if (drawURLString) {
+        NSSize urlStringSize;
+        urlStringSize.width = [urlString _web_widthWithFont: urlFont];
+        urlStringSize.height = [urlFont ascender] - [urlFont descender];
+        imageSize.height += urlStringSize.height;
+        if (urlStringSize.width > MaxDragLabelWidth) {
+            imageSize.width = max(MaxDragLabelWidth + DragLabelBorderY * 2, MinDragLabelWidthBeforeClip);
+            clipURLString = YES;
+        } else
+            imageSize.width = max(labelSize.width + DragLabelBorderX * 2, urlStringSize.width + DragLabelBorderX * 2);
+    }
+    NSImage *dragImage = [[[NSImage alloc] initWithSize: imageSize] autorelease];
+    [dragImage lockFocus];
+    
+    [[NSColor colorWithDeviceRed: 0.7f green: 0.7f blue: 0.7f alpha: 0.8f] set];
+    
+    // Drag a rectangle with rounded corners
+    NSBezierPath *path = [NSBezierPath bezierPath];
+    [path appendBezierPathWithOvalInRect: NSMakeRect(0, 0, DragLabelRadius * 2, DragLabelRadius * 2)];
+    [path appendBezierPathWithOvalInRect: NSMakeRect(0, imageSize.height - DragLabelRadius * 2, DragLabelRadius * 2, DragLabelRadius * 2)];
+    [path appendBezierPathWithOvalInRect: NSMakeRect(imageSize.width - DragLabelRadius * 2, imageSize.height - DragLabelRadius * 2, DragLabelRadius * 2, DragLabelRadius * 2)];
+    [path appendBezierPathWithOvalInRect: NSMakeRect(imageSize.width - DragLabelRadius * 2, 0, DragLabelRadius * 2, DragLabelRadius * 2)];
+    
+    [path appendBezierPathWithRect: NSMakeRect(DragLabelRadius, 0, imageSize.width - DragLabelRadius * 2, imageSize.height)];
+    [path appendBezierPathWithRect: NSMakeRect(0, DragLabelRadius, DragLabelRadius + 10, imageSize.height - 2 * DragLabelRadius)];
+    [path appendBezierPathWithRect: NSMakeRect(imageSize.width - DragLabelRadius - 20, DragLabelRadius, DragLabelRadius + 20, imageSize.height - 2 * DragLabelRadius)];
+    [path fill];
+    
+    NSColor *topColor = [NSColor colorWithDeviceWhite:0.0f alpha:0.75f];
+    NSColor *bottomColor = [NSColor colorWithDeviceWhite:1.0f alpha:0.5f];
+    if (drawURLString) {
+        if (clipURLString)
+            //urlString = [WebStringTruncator centerTruncateString: urlString toWidth:imageSize.width - (DragLabelBorderX * 2) withFont:urlFont];
+            urlString = StringTruncator::centerTruncate(urlString, imageSize.width - (DragLabelBorderX * 2), fontFromNSFont(urlFont));       
+        [urlString _web_drawDoubledAtPoint:NSMakePoint(DragLabelBorderX, DragLabelBorderY - [urlFont descender]) 
+                              withTopColor:topColor bottomColor:bottomColor font:urlFont];
+    }
+    
+    if (clipLabelString)
+        //label = [WebStringTruncator rightTruncateString: label toWidth:imageSize.width - (DragLabelBorderX * 2) withFont:labelFont];
+        label = StringTruncator::rightTruncate(label, imageSize.width - (DragLabelBorderX * 2), fontFromNSFont(labelFont));
+    [label _web_drawDoubledAtPoint:NSMakePoint (DragLabelBorderX, imageSize.height - LabelBorderYOffset - [labelFont pointSize])
+                      withTopColor:topColor bottomColor:bottomColor font:labelFont];
+    
+    [dragImage unlockFocus];
+    
+    return dragImage;
+}
+
+static void writeURL(NSPasteboard* pasteboard, NSURL* URL, NSString* title, NSArray* types)
+{
+    ASSERT(URL);
+    
+    if (![title length]) {
+        title = [[URL path] lastPathComponent];
+        if (![title length])
+            title = [URL _web_userVisibleString];
+    }
+    
+    if ([types containsObject:NSURLPboardType])
+        [URL writeToPasteboard:pasteboard];
+    if ([types containsObject:PasteboardTypes::WebURLPboardType])
+        [pasteboard setString:[URL _web_originalDataAsString] forType:PasteboardTypes::WebURLPboardType];
+    if ([types containsObject:PasteboardTypes::WebURLNamePboardType])
+        [pasteboard setString:title forType:PasteboardTypes::WebURLNamePboardType];
+    if ([types containsObject:NSStringPboardType])
+        [pasteboard setString:[URL _web_userVisibleString] forType:NSStringPboardType];
+    if ([types containsObject:PasteboardTypes::WebURLsWithTitlesPboardType]) {
+        NSArray* URLs = [NSArray arrayWithObject:URL];
+        unsigned count = [URLs count];
+        
+        if (!count || [pasteboard availableTypeFromArray:[NSArray arrayWithObject:PasteboardTypes::WebURLsWithTitlesPboardType]] == nil)
+            return;
+
+        NSArray* titles = [NSArray arrayWithObject:title];
+        
+        if (count != [titles count])
+            titles = nil;
+        
+        NSMutableArray* URLStrings = [NSMutableArray arrayWithCapacity:count];
+        NSMutableArray* titlesOrEmptyStrings = [NSMutableArray arrayWithCapacity:count];
+        for (unsigned index = 0; index < count; ++index) {
+            [URLStrings addObject:[[URLs objectAtIndex:index] _web_originalDataAsString]];
+            [titlesOrEmptyStrings addObject:(titles == nil) ? @"" : [[titles objectAtIndex:index] _webkit_stringByTrimmingWhitespace]];
+        }
+        
+        [pasteboard setPropertyList:[NSArray arrayWithObjects:URLStrings, titlesOrEmptyStrings, nil]
+                            forType:PasteboardTypes::WebURLsWithTitlesPboardType];
+    }
+}
+    
+static void writeImage(NSPasteboard* pasteboard, NSImage *image, DOMElement* element, NSURL* URL, NSString* title, LegacyWebArchive* archive, NSArray* types)
+{
+    ASSERT(image || element);
+    ASSERT(URL);
+    
+    writeURL(pasteboard, URL, title, types);
+    
+    if ([types containsObject:NSTIFFPboardType]) {
+        // FIXME: we should add handling of promised types.
+        if (image)
+            [pasteboard setData:[image TIFFRepresentation] forType:NSTIFFPboardType];
+        else if (element)
+            [pasteboard setData:[element _imageTIFFRepresentation] forType:NSTIFFPboardType];
+    }
+    
+    if (archive && [types containsObject:PasteboardTypes::WebArchivePboardType])
+        [pasteboard setData:[[(NSData *)archive->rawDataRepresentation().get() retain] autorelease] forType:PasteboardTypes::WebArchivePboardType];
+}
+    
+void WebDragClient::declareAndWriteDragImage(NSPasteboard* pasteboard, DOMElement* element, NSURL* URL, NSString* title, WebCore::Frame*)
+{
+    ASSERT(element);
+    ASSERT(pasteboard && pasteboard == [NSPasteboard pasteboardWithName:NSDragPboard]);
+    
+    NSString *extension = @"";
+    if (RenderObject* renderer = core(element)->renderer()) {
+        if (renderer->isImage()) {
+            if (CachedImage* image = toRenderImage(renderer)->cachedImage()) {
+                extension = image->image()->filenameExtension();
+                if (![extension length])
+                    return;
+            }
+        }
+    }
+    
+    RefPtr<LegacyWebArchive> archive = LegacyWebArchive::create(core(element));
+    NSMutableArray *types = [[NSMutableArray alloc] initWithObjects:NSFilesPromisePboardType, nil];
+    [types addObjectsFromArray:(archive) ? PasteboardTypes::forImagesWithArchive() : PasteboardTypes::forImages()];
+    [pasteboard declareTypes:types owner:nil];    
+    writeImage(pasteboard, nil, element, URL, title, archive.get(), types);
+    [types release];
+    
+    NSArray *extensions = [[NSArray alloc] initWithObjects:extension, nil];
+    [pasteboard setPropertyList:extensions forType:NSFilesPromisePboardType];
+    [extensions release];
+}
+
+} // namespace WebKit
index f66a598..8e7e6fd 100644 (file)
@@ -1309,6 +1309,20 @@ void WebPage::performDragControllerAction(uint64_t action, WebCore::IntPoint cli
     }
 }
 
+void WebPage::dragEnded(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t operation)
+{
+    IntPoint adjustedClientPosition(clientPosition.x() + m_page->dragController()->dragOffset().x(), clientPosition.y() + m_page->dragController()->dragOffset().y());
+    IntPoint adjustedGlobalPosition(globalPosition.x() + m_page->dragController()->dragOffset().x(), globalPosition.y() + m_page->dragController()->dragOffset().y());
+    
+    m_page->dragController()->dragEnded();
+    FrameView* view = m_page->mainFrame()->view();
+    if (!view)
+        return;
+    // FIXME: These are fake modifier keys here, but they should be real ones instead.
+    PlatformMouseEvent event(adjustedClientPosition, adjustedGlobalPosition, LeftButton, MouseEventMoved, 0, false, false, false, false, currentTime());
+    m_page->mainFrame()->eventHandler()->dragSourceEndedAt(event, (DragOperation)operation);
+}
+
 WebEditCommand* WebPage::webEditCommand(uint64_t commandID)
 {
     return m_editCommandMap.get(commandID).get();
index 4618625..353c085 100644 (file)
@@ -300,6 +300,7 @@ public:
 
     void replaceSelectionWithText(WebCore::Frame*, const String&);
     void performDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, const WTF::String& dragStorageName, uint32_t flags);
+    void dragEnded(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t operation);
 
     void beginPrinting(uint64_t frameID, const PrintInfo&);
     void endPrinting();
index c697c13..3272886 100644 (file)
@@ -99,6 +99,7 @@ messages -> WebPage {
 
     # Drag and drop.
     PerformDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, WTF::String dragStorageName, uint32_t flags)
+    DragEnded(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t operation)
 
     # Popup menu.
     DidChangeSelectedIndexForActivePopupMenu(int32_t newIndex);