[50460] | 1 | /* $Id: UIDnDDropSource_win.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
|
---|
| 2 | /** @file
|
---|
[52727] | 3 | * VBox Qt GUI - UIDnDDropSource class implementation for Windows. This implements
|
---|
[50460] | 4 | * the IDropSource interface.
|
---|
| 5 | */
|
---|
| 6 |
|
---|
| 7 | /*
|
---|
[98103] | 8 | * Copyright (C) 2014-2023 Oracle and/or its affiliates.
|
---|
[50460] | 9 | *
|
---|
[96407] | 10 | * This file is part of VirtualBox base platform packages, as
|
---|
| 11 | * available from https://www.virtualbox.org.
|
---|
| 12 | *
|
---|
| 13 | * This program is free software; you can redistribute it and/or
|
---|
| 14 | * modify it under the terms of the GNU General Public License
|
---|
| 15 | * as published by the Free Software Foundation, in version 3 of the
|
---|
| 16 | * License.
|
---|
| 17 | *
|
---|
| 18 | * This program is distributed in the hope that it will be useful, but
|
---|
| 19 | * WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
| 21 | * General Public License for more details.
|
---|
| 22 | *
|
---|
| 23 | * You should have received a copy of the GNU General Public License
|
---|
| 24 | * along with this program; if not, see <https://www.gnu.org/licenses>.
|
---|
| 25 | *
|
---|
| 26 | * SPDX-License-Identifier: GPL-3.0-only
|
---|
[50460] | 27 | */
|
---|
| 28 |
|
---|
[52730] | 29 | #undef LOG_GROUP
|
---|
[50460] | 30 | #define LOG_GROUP LOG_GROUP_GUEST_DND
|
---|
| 31 | #include <VBox/log.h>
|
---|
| 32 |
|
---|
[54555] | 33 | #include <iprt/assert.h>
|
---|
[52730] | 34 | #include <iprt/thread.h>
|
---|
| 35 |
|
---|
[58212] | 36 | /* Qt includes: */
|
---|
| 37 | #include <QApplication>
|
---|
| 38 |
|
---|
| 39 | /* Windows includes: */
|
---|
| 40 | #include <QApplication>
|
---|
[62679] | 41 | #include <iprt/win/windows.h>
|
---|
[50460] | 42 | #include <new> /* For bad_alloc. */
|
---|
| 43 |
|
---|
| 44 | #include "UIDnDDropSource_win.h"
|
---|
[58212] | 45 | #include "UIDnDDataObject_win.h"
|
---|
[50460] | 46 |
|
---|
[58212] | 47 | UIDnDDropSource::UIDnDDropSource(QWidget *pParent, UIDnDDataObject *pDataObject)
|
---|
[83801] | 48 | : m_pParent(pParent)
|
---|
[58212] | 49 | , m_pDataObject(pDataObject)
|
---|
[83801] | 50 | , m_cRefCount(1)
|
---|
[58212] | 51 | , m_dwCurEffect(DROPEFFECT_NONE)
|
---|
| 52 | , m_uCurAction(Qt::IgnoreAction)
|
---|
[50460] | 53 | {
|
---|
[58212] | 54 | LogFlowFunc(("pParent=0x%p\n", m_pParent));
|
---|
[50460] | 55 | }
|
---|
| 56 |
|
---|
| 57 | UIDnDDropSource::~UIDnDDropSource(void)
|
---|
| 58 | {
|
---|
[58212] | 59 | LogFlowFunc(("mRefCount=%RU32\n", m_cRefCount));
|
---|
[50460] | 60 | }
|
---|
| 61 |
|
---|
| 62 | /*
|
---|
| 63 | * IUnknown methods.
|
---|
| 64 | */
|
---|
| 65 |
|
---|
| 66 | STDMETHODIMP_(ULONG) UIDnDDropSource::AddRef(void)
|
---|
| 67 | {
|
---|
[58212] | 68 | LogFlowFunc(("mRefCount=%RU32\n", m_cRefCount + 1));
|
---|
| 69 | return (ULONG)InterlockedIncrement(&m_cRefCount);
|
---|
[50460] | 70 | }
|
---|
| 71 |
|
---|
| 72 | STDMETHODIMP_(ULONG) UIDnDDropSource::Release(void)
|
---|
| 73 | {
|
---|
[58212] | 74 | Assert(m_cRefCount > 0);
|
---|
| 75 | LogFlowFunc(("mRefCount=%RU32\n", m_cRefCount - 1));
|
---|
| 76 | LONG lCount = InterlockedDecrement(&m_cRefCount);
|
---|
| 77 | if (lCount <= 0)
|
---|
[50460] | 78 | {
|
---|
| 79 | delete this;
|
---|
| 80 | return 0;
|
---|
| 81 | }
|
---|
| 82 |
|
---|
[58212] | 83 | return (ULONG)lCount;
|
---|
[50460] | 84 | }
|
---|
| 85 |
|
---|
| 86 | STDMETHODIMP UIDnDDropSource::QueryInterface(REFIID iid, void **ppvObject)
|
---|
| 87 | {
|
---|
| 88 | AssertPtrReturn(ppvObject, E_INVALIDARG);
|
---|
| 89 |
|
---|
| 90 | if ( iid == IID_IDropSource
|
---|
| 91 | || iid == IID_IUnknown)
|
---|
| 92 | {
|
---|
| 93 | AddRef();
|
---|
| 94 | *ppvObject = this;
|
---|
| 95 | return S_OK;
|
---|
| 96 | }
|
---|
| 97 |
|
---|
| 98 | *ppvObject = 0;
|
---|
| 99 | return E_NOINTERFACE;
|
---|
| 100 | }
|
---|
| 101 |
|
---|
| 102 | /*
|
---|
| 103 | * IDropSource methods.
|
---|
| 104 | */
|
---|
| 105 |
|
---|
| 106 | /**
|
---|
| 107 | * The system informs us about whether we should continue the drag'n drop
|
---|
| 108 | * operation or not, depending on the sent key states.
|
---|
| 109 | *
|
---|
| 110 | * @return HRESULT
|
---|
| 111 | */
|
---|
| 112 | STDMETHODIMP UIDnDDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD dwKeyState)
|
---|
| 113 | {
|
---|
[58212] | 114 | LogFlowFunc(("fEscapePressed=%RTbool, dwKeyState=0x%x, m_dwCurEffect=%RI32, m_uCurAction=%RU32\n",
|
---|
| 115 | RT_BOOL(fEscapePressed), dwKeyState, m_dwCurEffect, m_uCurAction));
|
---|
[50460] | 116 |
|
---|
| 117 | /* ESC pressed? Bail out. */
|
---|
| 118 | if (fEscapePressed)
|
---|
| 119 | {
|
---|
[58212] | 120 | m_dwCurEffect = DROPEFFECT_NONE;
|
---|
| 121 | m_uCurAction = Qt::IgnoreAction;
|
---|
[50460] | 122 |
|
---|
[56780] | 123 | LogRel2(("DnD: User cancelled dropping data to the host\n"));
|
---|
[50460] | 124 | return DRAGDROP_S_CANCEL;
|
---|
| 125 | }
|
---|
| 126 |
|
---|
| 127 | bool fDropContent = false;
|
---|
| 128 |
|
---|
| 129 | /* Left mouse button released? Start "drop" action. */
|
---|
| 130 | if ((dwKeyState & MK_LBUTTON) == 0)
|
---|
[56780] | 131 | fDropContent = true;
|
---|
| 132 | /** @todo Make this configurable? */
|
---|
| 133 |
|
---|
| 134 | if (fDropContent)
|
---|
| 135 | {
|
---|
[58212] | 136 | if (m_pDataObject)
|
---|
| 137 | m_pDataObject->Signal();
|
---|
| 138 |
|
---|
[56780] | 139 | LogRel2(("DnD: User dropped data to the host\n"));
|
---|
[50460] | 140 | return DRAGDROP_S_DROP;
|
---|
[56780] | 141 | }
|
---|
[50460] | 142 |
|
---|
[58212] | 143 | QApplication::processEvents();
|
---|
| 144 |
|
---|
[50460] | 145 | /* No change, just continue. */
|
---|
| 146 | return S_OK;
|
---|
| 147 | }
|
---|
| 148 |
|
---|
| 149 | /**
|
---|
| 150 | * The drop target gives our source feedback about whether
|
---|
| 151 | * it can handle our data or not.
|
---|
| 152 | *
|
---|
| 153 | * @return HRESULT
|
---|
| 154 | */
|
---|
| 155 | STDMETHODIMP UIDnDDropSource::GiveFeedback(DWORD dwEffect)
|
---|
| 156 | {
|
---|
[58212] | 157 | Qt::DropActions dropActions = Qt::IgnoreAction;
|
---|
[50460] | 158 |
|
---|
| 159 | LogFlowFunc(("dwEffect=0x%x\n", dwEffect));
|
---|
| 160 | if (dwEffect)
|
---|
| 161 | {
|
---|
| 162 | if (dwEffect & DROPEFFECT_COPY)
|
---|
| 163 | dropActions |= Qt::CopyAction;
|
---|
| 164 | if (dwEffect & DROPEFFECT_MOVE)
|
---|
| 165 | dropActions |= Qt::MoveAction;
|
---|
| 166 | if (dwEffect & DROPEFFECT_LINK)
|
---|
| 167 | dropActions |= Qt::LinkAction;
|
---|
[58212] | 168 |
|
---|
| 169 | m_dwCurEffect = dwEffect;
|
---|
[50460] | 170 | }
|
---|
| 171 |
|
---|
[58212] | 172 | m_uCurAction = dropActions;
|
---|
[50460] | 173 |
|
---|
| 174 | return DRAGDROP_S_USEDEFAULTCURSORS;
|
---|
| 175 | }
|
---|
| 176 |
|
---|