18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2007 Apple Inc.  All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "WebDragClient.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "WebDropSource.h"
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "WebKitGraphics.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "WebView.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <shlobj.h>
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <WebCore/ClipboardWin.h>
35231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include <WebCore/DragController.h>
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <WebCore/DragData.h>
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <WebCore/FrameView.h>
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <WebCore/GraphicsContext.h>
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <WebCore/Page.h>
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace WebCore;
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
43231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockstatic DWORD draggingSourceOperationMaskToDragCursors(DragOperation op)
44231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
45231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    DWORD result = DROPEFFECT_NONE;
46231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (op == DragOperationEvery)
47231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return DROPEFFECT_COPY | DROPEFFECT_LINK | DROPEFFECT_MOVE;
48231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (op & DragOperationCopy)
49231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        result |= DROPEFFECT_COPY;
50231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (op & DragOperationLink)
51231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        result |= DROPEFFECT_LINK;
52231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (op & DragOperationMove)
53231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        result |= DROPEFFECT_MOVE;
54231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (op & DragOperationGeneric)
55231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        result |= DROPEFFECT_MOVE;
56231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return result;
57231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
58231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectWebDragClient::WebDragClient(WebView* webView)
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    : m_webView(webView)
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(webView);
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectDragDestinationAction WebDragClient::actionMaskForDrag(DragData* dragData)
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    COMPtr<IWebUIDelegate> delegateRef = 0;
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    //Default behaviour (eg. no delegate, or callback not implemented) is to allow
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    //any action
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebDragDestinationAction mask = WebDragDestinationActionAny;
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (SUCCEEDED(m_webView->uiDelegate(&delegateRef)))
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        delegateRef->dragDestinationActionMaskForDraggingInfo(m_webView, dragData->platformData(), &mask);
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return (DragDestinationAction)mask;
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid WebDragClient::willPerformDragDestinationAction(DragDestinationAction action, DragData* dragData)
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    //Default delegate for willPerformDragDestinationAction has no side effects
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    //so we just call the delegate, and don't worry about whether it's implemented
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    COMPtr<IWebUIDelegate> delegateRef = 0;
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (SUCCEEDED(m_webView->uiDelegate(&delegateRef)))
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        delegateRef->willPerformDragDestinationAction(m_webView, (WebDragDestinationAction)action, dragData->platformData());
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectDragSourceAction WebDragClient::dragSourceActionMaskForPoint(const IntPoint& windowPoint)
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project   COMPtr<IWebUIDelegate> delegateRef = 0;
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project   WebDragSourceAction action = WebDragSourceActionAny;
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project   POINT localpt = core(m_webView)->mainFrame()->view()->windowToContents(windowPoint);
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project   if (SUCCEEDED(m_webView->uiDelegate(&delegateRef)))
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project       delegateRef->dragSourceActionMaskForPoint(m_webView, &localpt, &action);
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project   return (DragSourceAction)action;
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid WebDragClient::willPerformDragSourceAction(DragSourceAction action, const IntPoint& intPoint, Clipboard* clipboard)
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    COMPtr<IWebUIDelegate> uiDelegate;
990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!SUCCEEDED(m_webView->uiDelegate(&uiDelegate)))
1000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return;
1010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    POINT point = intPoint;
1030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    COMPtr<IDataObject> dataObject = static_cast<ClipboardWin*>(clipboard)->dataObject();
1040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    COMPtr<IDataObject> newDataObject;
1060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    HRESULT result = uiDelegate->willPerformDragSourceAction(m_webView, static_cast<WebDragSourceAction>(action), &point, dataObject.get(), &newDataObject);
1070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (result == S_OK && newDataObject != dataObject)
1080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        static_cast<ClipboardWin*>(clipboard)->setExternalDataObject(newDataObject.get());
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid WebDragClient::startDrag(DragImageRef image, const IntPoint& imageOrigin, const IntPoint& dragPoint, Clipboard* clipboard, Frame* frame, bool isLink)
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    //FIXME: Allow UIDelegate to override behaviour <rdar://problem/5015953>
1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    //We liberally protect everything, to protect against a load occurring mid-drag
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RefPtr<Frame> frameProtector = frame;
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    COMPtr<IDragSourceHelper> helper;
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    COMPtr<IDataObject> dataObject;
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    COMPtr<WebView> viewProtector = m_webView;
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    COMPtr<IDropSource> source;
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (FAILED(WebDropSource::createInstance(m_webView, &source)))
1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    dataObject = static_cast<ClipboardWin*>(clipboard)->dataObject();
1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (source && (image || dataObject)) {
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (image) {
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if(SUCCEEDED(CoCreateInstance(CLSID_DragDropHelper, 0, CLSCTX_INPROC_SERVER,
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                IID_IDragSourceHelper,(LPVOID*)&helper))) {
1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                BITMAP b;
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                GetObject(image, sizeof(BITMAP), &b);
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                SHDRAGIMAGE sdi;
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                sdi.sizeDragImage.cx = b.bmWidth;
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                sdi.sizeDragImage.cy = b.bmHeight;
1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                sdi.crColorKey = 0xffffffff;
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                sdi.hbmpDragImage = image;
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                sdi.ptOffset.x = dragPoint.x() - imageOrigin.x();
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                sdi.ptOffset.y = dragPoint.y() - imageOrigin.y();
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (isLink)
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    sdi.ptOffset.y = b.bmHeight - sdi.ptOffset.y;
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                helper->InitializeFromBitmap(&sdi, dataObject.get());
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
145231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        DWORD okEffect = draggingSourceOperationMaskToDragCursors(m_webView->page()->dragController()->sourceDragOperation());
146cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        DWORD effect = DROPEFFECT_NONE;
1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        COMPtr<IWebUIDelegate> ui;
148cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        HRESULT hr = E_NOTIMPL;
1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (SUCCEEDED(m_webView->uiDelegate(&ui))) {
1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            COMPtr<IWebUIDelegatePrivate> uiPrivate;
1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (SUCCEEDED(ui->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&uiPrivate)))
152cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block                hr = uiPrivate->doDragDrop(m_webView, dataObject.get(), source.get(), okEffect, &effect);
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
154cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        if (hr == E_NOTIMPL)
155cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            hr = DoDragDrop(dataObject.get(), source.get(), okEffect, &effect);
156cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
157cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        DragOperation operation = DragOperationNone;
158cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        if (hr == DRAGDROP_S_DROP) {
159cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            if (effect & DROPEFFECT_COPY)
160cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block                operation = DragOperationCopy;
161cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            else if (effect & DROPEFFECT_LINK)
162cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block                operation = DragOperationLink;
163cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            else if (effect & DROPEFFECT_MOVE)
164cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block                operation = DragOperationMove;
165cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        }
166cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        frame->eventHandler()->dragSourceEndedAt(generateMouseEvent(m_webView, false), operation);
1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid WebDragClient::dragControllerDestroyed()
1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    delete this;
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
174