57namespace pulp::view::win_drop {
60std::string wide_to_utf8(
const wchar_t* w,
int wlen) {
61 if (!w || wlen <= 0)
return {};
62 int n = WideCharToMultiByte(CP_UTF8, 0, w, wlen,
nullptr, 0,
nullptr,
nullptr);
63 if (n <= 0)
return {};
64 std::string out(
static_cast<size_t>(n),
'\0');
65 WideCharToMultiByte(CP_UTF8, 0, w, wlen, out.data(), n,
nullptr,
nullptr);
71DropData extract_idata_drop(IDataObject* data) {
73 if (!data)
return out;
76 FORMATETC fmt_files{CF_HDROP,
nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
78 if (data->GetData(&fmt_files, &stg) == S_OK) {
79 if (
auto hdrop =
static_cast<HDROP
>(GlobalLock(stg.hGlobal))) {
80 const UINT
count = DragQueryFileW(hdrop, 0xFFFFFFFF,
nullptr, 0);
81 out.type = DropData::Type::files;
82 for (UINT i = 0;
i <
count; ++
i) {
83 const UINT len = DragQueryFileW(hdrop, i,
nullptr, 0);
84 std::wstring buf(len + 1, L
'\0');
85 const UINT got = DragQueryFileW(hdrop, i, buf.data(),
86 static_cast<UINT
>(buf.size()));
87 if (got > 0) out.file_paths.push_back(wide_to_utf8(buf.data(),
88 static_cast<int>(got)));
90 GlobalUnlock(stg.hGlobal);
92 ReleaseStgMedium(&stg);
93 if (!out.file_paths.empty())
return out;
97 FORMATETC fmt_text{CF_UNICODETEXT,
nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
99 if (data->GetData(&fmt_text, &stg_text) == S_OK) {
100 if (
auto* w =
static_cast<const wchar_t*
>(GlobalLock(stg_text.hGlobal))) {
101 out.type = DropData::Type::text;
102 out.text = wide_to_utf8(w,
static_cast<int>(wcslen(w)));
103 GlobalUnlock(stg_text.hGlobal);
105 ReleaseStgMedium(&stg_text);
114class PulpWinDropTarget :
public IDropTarget {
116 PulpWinDropTarget(View& root, HWND hwnd, std::function<Point(Point)> to_root)
117 : root_(root), hwnd_(hwnd), to_root_(std::
move(to_root)) {}
120 Point to_root_point(POINTL pt)
const {
122 ScreenToClient(hwnd_, &p);
123 Point client{
static_cast<float>(
p.x),
static_cast<float>(
p.y)};
124 return to_root_ ? to_root_(client) : client;
128 HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,
void** ppv)
override {
129 if (riid == IID_IUnknown || riid == IID_IDropTarget) {
130 *ppv =
static_cast<IDropTarget*
>(
this);
135 return E_NOINTERFACE;
137 ULONG STDMETHODCALLTYPE AddRef()
override {
138 return static_cast<ULONG
>(++ref_);
140 ULONG STDMETHODCALLTYPE
Release()
override {
141 const long r = --ref_;
142 if (r == 0)
delete this;
143 return static_cast<ULONG
>(
r);
147 HRESULT STDMETHODCALLTYPE DragEnter(IDataObject* data, DWORD, POINTL pt,
148 DWORD* effect)
override {
149 pending_ = extract_idata_drop(data);
152 *
effect =
ok ? DROPEFFECT_COPY : DROPEFFECT_NONE;
155 HRESULT STDMETHODCALLTYPE DragOver(DWORD, POINTL pt, DWORD* effect)
override {
158 *
effect =
ok ? DROPEFFECT_COPY : DROPEFFECT_NONE;
161 HRESULT STDMETHODCALLTYPE DragLeave()
override {
166 HRESULT STDMETHODCALLTYPE
Drop(IDataObject* data, DWORD, POINTL pt,
167 DWORD* effect)
override {
168 DropData
d = extract_idata_drop(data);
170 *
effect =
ok ? DROPEFFECT_COPY : DROPEFFECT_NONE;
178 std::function<Point(Point)> to_root_;
179 DragSession session_;
200class DropTargetRegistration {
202 DropTargetRegistration() =
default;
203 DropTargetRegistration(
const DropTargetRegistration&) =
delete;
204 DropTargetRegistration& operator=(
const DropTargetRegistration&) =
delete;
205 ~DropTargetRegistration() { reset(); }
210 bool register_for(View& root, HWND hwnd, std::function<Point(Point)> to_root) {
212 if (!hwnd)
return false;
213 const HRESULT hr = OleInitialize(
nullptr);
214 if (hr != S_OK && hr != S_FALSE) {
215 runtime::log_warn(
"DropTargetRegistration: OleInitialize failed "
216 "(0x{:08x}); drag-drop disabled",
217 static_cast<unsigned>(hr));
220 ole_initialized_ =
true;
222 target_ =
new PulpWinDropTarget(root, hwnd, std::move(to_root));
223 if (RegisterDragDrop(hwnd, target_) != S_OK) {
224 runtime::log_warn(
"DropTargetRegistration: RegisterDragDrop failed");
236 if (hwnd_) RevokeDragDrop(hwnd_);
241 if (ole_initialized_) {
243 ole_initialized_ =
false;
247 bool registered() const noexcept {
return target_ !=
nullptr; }
250 bool ole_initialized_ =
false;
251 HWND hwnd_ =
nullptr;
252 PulpWinDropTarget* target_ =
nullptr;
@ Release
Definition instrument_envelope.hpp:14
@ ok
Definition analyzer_provider.hpp:58
@ count
sentinel: number of real capabilities (keep LAST)
Definition canvas_capability.hpp:38
@ Drop
Definition capability_tables.hpp:23
@ d
Definition pitch.hpp:22
@ effect
Definition lfo.hpp:68
@ i
Definition formant_filter_bank.hpp:20
@ move
Definition web_event_translate.hpp:110
bool dispatch_drop(View &root, DragSession &session, const DropData &data, Point root_pos)
bool dispatch_drag_enter(View &root, DragSession &session, const DropData &data, Point root_pos)
void dispatch_drag_exit(View &root, DragSession &session)
@ r
Definition input_events.hpp:41
@ n
Definition input_events.hpp:40
@ p
Definition input_events.hpp:40