Skip to content

Commit 2bd7599

Browse files
committed
fix drag-and-drop in windows
1 parent 621cadc commit 2bd7599

5 files changed

+489
-31
lines changed

platform/windows/SCsub

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ common_win = [
2323
"gl_manager_windows_angle.cpp",
2424
"wgl_detect_version.cpp",
2525
"rendering_context_driver_vulkan_windows.cpp",
26+
"drop_target_windows.cpp",
2627
]
2728

2829
if env.msvc:

platform/windows/display_server_windows.cpp

+29-31
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
#include "display_server_windows.h"
3232

33+
#include "drop_target_windows.h"
3334
#include "os_windows.h"
3435
#include "wgl_detect_version.h"
3536

@@ -1600,11 +1601,17 @@ void DisplayServerWindows::delete_sub_window(WindowID p_window) {
16001601
}
16011602
#endif
16021603

1603-
if ((tablet_get_current_driver() == "wintab") && wintab_available && windows[p_window].wtctx) {
1604-
wintab_WTClose(windows[p_window].wtctx);
1605-
windows[p_window].wtctx = nullptr;
1604+
if ((tablet_get_current_driver() == "wintab") && wintab_available && wd.wtctx) {
1605+
wintab_WTClose(wd.wtctx);
1606+
wd.wtctx = nullptr;
1607+
}
1608+
1609+
if (wd.drop_target != nullptr) {
1610+
RevokeDragDrop(wd.hWnd);
1611+
wd.drop_target->Release();
16061612
}
1607-
DestroyWindow(windows[p_window].hWnd);
1613+
1614+
DestroyWindow(wd.hWnd);
16081615
windows.erase(p_window);
16091616

16101617
if (last_focused_window == p_window) {
@@ -1702,7 +1709,14 @@ void DisplayServerWindows::window_set_drop_files_callback(const Callable &p_call
17021709
_THREAD_SAFE_METHOD_
17031710

17041711
ERR_FAIL_COND(!windows.has(p_window));
1705-
windows[p_window].drop_files_callback = p_callable;
1712+
WindowData &window_data = windows[p_window];
1713+
1714+
window_data.drop_files_callback = p_callable;
1715+
1716+
if (window_data.drop_target == nullptr) {
1717+
window_data.drop_target = memnew(DropTargetWindows(&window_data));
1718+
ERR_FAIL_COND(RegisterDragDrop(window_data.hWnd, window_data.drop_target) != S_OK);
1719+
}
17061720
}
17071721

17081722
void DisplayServerWindows::window_set_title(const String &p_title, WindowID p_window) {
@@ -5264,32 +5278,6 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
52645278
}
52655279
}
52665280
} break;
5267-
case WM_DROPFILES: {
5268-
HDROP hDropInfo = (HDROP)wParam;
5269-
const int buffsize = 4096;
5270-
WCHAR buf[buffsize];
5271-
5272-
int fcount = DragQueryFileW(hDropInfo, 0xFFFFFFFF, nullptr, 0);
5273-
5274-
Vector<String> files;
5275-
5276-
for (int i = 0; i < fcount; i++) {
5277-
DragQueryFileW(hDropInfo, i, buf, buffsize);
5278-
String file = String::utf16((const char16_t *)buf);
5279-
files.push_back(file);
5280-
}
5281-
5282-
if (files.size() && windows[window_id].drop_files_callback.is_valid()) {
5283-
Variant v_files = files;
5284-
const Variant *v_args[1] = { &v_files };
5285-
Variant ret;
5286-
Callable::CallError ce;
5287-
windows[window_id].drop_files_callback.callp((const Variant **)&v_args, 1, ret, ce);
5288-
if (ce.error != Callable::CallError::CALL_OK) {
5289-
ERR_PRINT(vformat("Failed to execute drop files callback: %s.", Variant::get_callable_error_text(windows[window_id].drop_files_callback, v_args, 1, ce)));
5290-
}
5291-
}
5292-
} break;
52935281
default: {
52945282
if (user_proc) {
52955283
return CallWindowProcW(user_proc, hWnd, uMsg, wParam, lParam);
@@ -6112,6 +6100,8 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
61126100
FreeLibrary(comctl32);
61136101
}
61146102

6103+
OleInitialize(nullptr);
6104+
61156105
memset(&wc, 0, sizeof(WNDCLASSEXW));
61166106
wc.cbSize = sizeof(WNDCLASSEXW);
61176107
wc.style = CS_OWNDC | CS_DBLCLKS;
@@ -6538,6 +6528,12 @@ DisplayServerWindows::~DisplayServerWindows() {
65386528
wintab_WTClose(windows[MAIN_WINDOW_ID].wtctx);
65396529
windows[MAIN_WINDOW_ID].wtctx = nullptr;
65406530
}
6531+
6532+
if (windows[MAIN_WINDOW_ID].drop_target != nullptr) {
6533+
RevokeDragDrop(windows[MAIN_WINDOW_ID].hWnd);
6534+
windows[MAIN_WINDOW_ID].drop_target->Release();
6535+
}
6536+
65416537
DestroyWindow(windows[MAIN_WINDOW_ID].hWnd);
65426538
}
65436539

@@ -6569,4 +6565,6 @@ DisplayServerWindows::~DisplayServerWindows() {
65696565
if (tts) {
65706566
memdelete(tts);
65716567
}
6568+
6569+
OleUninitialize();
65726570
}

platform/windows/display_server_windows.h

+7
Original file line numberDiff line numberDiff line change
@@ -356,9 +356,13 @@ typedef enum _SHC_PROCESS_DPI_AWARENESS {
356356
SHC_PROCESS_PER_MONITOR_DPI_AWARE = 2,
357357
} SHC_PROCESS_DPI_AWARENESS;
358358

359+
class DropTargetWindows;
360+
359361
class DisplayServerWindows : public DisplayServer {
360362
// No need to register with GDCLASS, it's platform-specific and nothing is added.
361363

364+
friend class DropTargetWindows;
365+
362366
_THREAD_SAFE_CLASS_
363367

364368
// UXTheme API
@@ -519,6 +523,9 @@ class DisplayServerWindows : public DisplayServer {
519523
Callable input_text_callback;
520524
Callable drop_files_callback;
521525

526+
// OLE API
527+
DropTargetWindows *drop_target = nullptr;
528+
522529
WindowID transient_parent = INVALID_WINDOW_ID;
523530
HashSet<WindowID> transient_children;
524531

0 commit comments

Comments
 (0)