WebDragClient.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*
  2. * Copyright (C) 2007 Apple Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
  14. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  16. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
  17. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  18. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  19. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  20. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  21. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  23. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #include "config.h"
  26. #include "WebDragClient.h"
  27. #include "WebDropSource.h"
  28. #include "WebKitGraphics.h"
  29. #include "WebView.h"
  30. #include <WebCore/Clipboard.h>
  31. #include <WebCore/DragController.h>
  32. #include <WebCore/DragData.h>
  33. #include <WebCore/EventHandler.h>
  34. #include <WebCore/Page.h>
  35. #include <WebCore/Pasteboard.h>
  36. #include <WebCore/PlatformMouseEvent.h>
  37. #include <WebCore/Frame.h>
  38. #include <WebCore/FrameView.h>
  39. #include <WebCore/GraphicsContext.h>
  40. #include <shlobj.h>
  41. using namespace WebCore;
  42. static DWORD draggingSourceOperationMaskToDragCursors(DragOperation op)
  43. {
  44. DWORD result = DROPEFFECT_NONE;
  45. if (op == DragOperationEvery)
  46. return DROPEFFECT_COPY | DROPEFFECT_LINK | DROPEFFECT_MOVE;
  47. if (op & DragOperationCopy)
  48. result |= DROPEFFECT_COPY;
  49. if (op & DragOperationLink)
  50. result |= DROPEFFECT_LINK;
  51. if (op & DragOperationMove)
  52. result |= DROPEFFECT_MOVE;
  53. if (op & DragOperationGeneric)
  54. result |= DROPEFFECT_MOVE;
  55. return result;
  56. }
  57. WebDragClient::WebDragClient(WebView* webView)
  58. : m_webView(webView)
  59. {
  60. ASSERT(webView);
  61. }
  62. DragDestinationAction WebDragClient::actionMaskForDrag(DragData* dragData)
  63. {
  64. COMPtr<IWebUIDelegate> delegateRef = 0;
  65. //Default behaviour (eg. no delegate, or callback not implemented) is to allow
  66. //any action
  67. WebDragDestinationAction mask = WebDragDestinationActionAny;
  68. if (SUCCEEDED(m_webView->uiDelegate(&delegateRef)))
  69. delegateRef->dragDestinationActionMaskForDraggingInfo(m_webView, dragData->platformData(), &mask);
  70. return (DragDestinationAction)mask;
  71. }
  72. void WebDragClient::willPerformDragDestinationAction(DragDestinationAction action, DragData* dragData)
  73. {
  74. //Default delegate for willPerformDragDestinationAction has no side effects
  75. //so we just call the delegate, and don't worry about whether it's implemented
  76. COMPtr<IWebUIDelegate> delegateRef = 0;
  77. if (SUCCEEDED(m_webView->uiDelegate(&delegateRef)))
  78. delegateRef->willPerformDragDestinationAction(m_webView, (WebDragDestinationAction)action, dragData->platformData());
  79. }
  80. DragSourceAction WebDragClient::dragSourceActionMaskForPoint(const IntPoint& windowPoint)
  81. {
  82. COMPtr<IWebUIDelegate> delegateRef = 0;
  83. WebDragSourceAction action = WebDragSourceActionAny;
  84. POINT localpt = core(m_webView)->mainFrame()->view()->windowToContents(windowPoint);
  85. if (SUCCEEDED(m_webView->uiDelegate(&delegateRef)))
  86. delegateRef->dragSourceActionMaskForPoint(m_webView, &localpt, &action);
  87. return (DragSourceAction)action;
  88. }
  89. void WebDragClient::willPerformDragSourceAction(DragSourceAction action, const IntPoint& intPoint, Clipboard* clipboard)
  90. {
  91. COMPtr<IWebUIDelegate> uiDelegate;
  92. if (!SUCCEEDED(m_webView->uiDelegate(&uiDelegate)))
  93. return;
  94. POINT point = intPoint;
  95. COMPtr<IDataObject> dataObject = clipboard->pasteboard().dataObject();
  96. COMPtr<IDataObject> newDataObject;
  97. HRESULT result = uiDelegate->willPerformDragSourceAction(m_webView, static_cast<WebDragSourceAction>(action), &point, dataObject.get(), &newDataObject);
  98. if (result == S_OK && newDataObject != dataObject)
  99. const_cast<Pasteboard&>(clipboard->pasteboard()).setExternalDataObject(newDataObject.get());
  100. }
  101. void WebDragClient::startDrag(DragImageRef image, const IntPoint& imageOrigin, const IntPoint& dragPoint, Clipboard* clipboard, Frame* frame, bool isLink)
  102. {
  103. //FIXME: Allow UIDelegate to override behaviour <rdar://problem/5015953>
  104. //We liberally protect everything, to protect against a load occurring mid-drag
  105. RefPtr<Frame> frameProtector = frame;
  106. COMPtr<IDragSourceHelper> helper;
  107. COMPtr<IDataObject> dataObject;
  108. COMPtr<WebView> viewProtector = m_webView;
  109. COMPtr<IDropSource> source;
  110. if (FAILED(WebDropSource::createInstance(m_webView, &source)))
  111. return;
  112. dataObject = clipboard->pasteboard().dataObject();
  113. if (source && (image || dataObject)) {
  114. if (image) {
  115. if(SUCCEEDED(CoCreateInstance(CLSID_DragDropHelper, 0, CLSCTX_INPROC_SERVER,
  116. IID_IDragSourceHelper,(LPVOID*)&helper))) {
  117. BITMAP b;
  118. GetObject(image, sizeof(BITMAP), &b);
  119. SHDRAGIMAGE sdi;
  120. sdi.sizeDragImage.cx = b.bmWidth;
  121. sdi.sizeDragImage.cy = b.bmHeight;
  122. sdi.crColorKey = 0xffffffff;
  123. sdi.hbmpDragImage = image;
  124. sdi.ptOffset.x = dragPoint.x() - imageOrigin.x();
  125. sdi.ptOffset.y = dragPoint.y() - imageOrigin.y();
  126. if (isLink)
  127. sdi.ptOffset.y = b.bmHeight - sdi.ptOffset.y;
  128. helper->InitializeFromBitmap(&sdi, dataObject.get());
  129. }
  130. }
  131. DWORD okEffect = draggingSourceOperationMaskToDragCursors(m_webView->page()->dragController()->sourceDragOperation());
  132. DWORD effect = DROPEFFECT_NONE;
  133. COMPtr<IWebUIDelegate> ui;
  134. HRESULT hr = E_NOTIMPL;
  135. if (SUCCEEDED(m_webView->uiDelegate(&ui))) {
  136. COMPtr<IWebUIDelegatePrivate> uiPrivate;
  137. if (SUCCEEDED(ui->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&uiPrivate)))
  138. hr = uiPrivate->doDragDrop(m_webView, dataObject.get(), source.get(), okEffect, &effect);
  139. }
  140. if (hr == E_NOTIMPL)
  141. hr = DoDragDrop(dataObject.get(), source.get(), okEffect, &effect);
  142. DragOperation operation = DragOperationNone;
  143. if (hr == DRAGDROP_S_DROP) {
  144. if (effect & DROPEFFECT_COPY)
  145. operation = DragOperationCopy;
  146. else if (effect & DROPEFFECT_LINK)
  147. operation = DragOperationLink;
  148. else if (effect & DROPEFFECT_MOVE)
  149. operation = DragOperationMove;
  150. }
  151. frame->eventHandler()->dragSourceEndedAt(generateMouseEvent(m_webView, false), operation);
  152. }
  153. }
  154. void WebDragClient::dragControllerDestroyed()
  155. {
  156. delete this;
  157. }