Make sure the Windows dnd operation terminates

I've seen a weird edge case where this doesn't happen once, but i
haven't been able to reproduce it. Hopefully this fixes it.
This commit is contained in:
Robbert van der Helm
2021-07-12 12:21:52 +02:00
parent 11d3ec9010
commit a478436af6
2 changed files with 27 additions and 7 deletions
+16 -4
View File
@@ -194,9 +194,9 @@ WineXdndProxy::Handle WineXdndProxy::get_handle() {
return Handle(instance); return Handle(instance);
} }
void WineXdndProxy::begin_xdnd( void WineXdndProxy::begin_xdnd(const boost::container::small_vector_base<
const boost::container::small_vector_base<boost::filesystem::path>& boost::filesystem::path>& file_paths,
file_paths) { HWND tracker_window) {
if (file_paths.empty()) { if (file_paths.empty()) {
throw std::runtime_error("Cannot drag-and-drop without any files"); throw std::runtime_error("Cannot drag-and-drop without any files");
} }
@@ -236,6 +236,7 @@ void WineXdndProxy::begin_xdnd(
// the left mouse button gets released. Because Wine is also blocking the // the left mouse button gets released. Because Wine is also blocking the
// GUI thread, we need to do our XDND polling from another thread. Luckily // GUI thread, we need to do our XDND polling from another thread. Luckily
// the X11 API is thread safe. // the X11 API is thread safe.
this->tracker_window = tracker_window;
xdnd_handler = Win32Thread([&]() { run_xdnd_loop(); }); xdnd_handler = Win32Thread([&]() { run_xdnd_loop(); });
} }
@@ -479,6 +480,9 @@ void WineXdndProxy::run_xdnd_loop() {
// In case that window somehow becomes unresponsive or disappears, we // In case that window somehow becomes unresponsive or disappears, we
// will set a timeout here to avoid hanging // will set a timeout here to avoid hanging
if (std::chrono::steady_clock::now() - wait_start > 5s) { if (std::chrono::steady_clock::now() - wait_start > 5s) {
// Just to make it extra clear that we don't want to interfere with
// Wine's own drag-and-drop if we reach a timeout
drop_finished = false;
maybe_leave_last_window(); maybe_leave_last_window();
break; break;
} }
@@ -535,6 +539,12 @@ void WineXdndProxy::run_xdnd_loop() {
} }
} }
// Make sure the Windows drag-and-drop operation doesn't get stuck for
// whatever reason (it shouldn't but who knows)
if (drop_finished) {
PostMessageW(tracker_window, WM_QUIT, 0, 0);
}
end_xdnd(); end_xdnd();
} }
@@ -841,8 +851,10 @@ void CALLBACK dnd_winevent_callback(HWINEVENTHOOK /*hWinEventHook*/,
return; return;
} }
PostMessageW(hwnd, WM_QUIT, 0, 0);
try { try {
instance->begin_xdnd(dragged_files); instance->begin_xdnd(dragged_files, hwnd);
} catch (const std::exception& error) { } catch (const std::exception& error) {
std::cerr << "XDND initialization failed:" << std::endl; std::cerr << "XDND initialization failed:" << std::endl;
std::cerr << error.what() << std::endl; std::cerr << error.what() << std::endl;
+11 -3
View File
@@ -136,9 +136,9 @@ class WineXdndProxy {
* Initiate the XDDN protocol by taking ownership of the `XdndSelection` * Initiate the XDDN protocol by taking ownership of the `XdndSelection`
* selection and setting up the event listeners. * selection and setting up the event listeners.
*/ */
void begin_xdnd( void begin_xdnd(const boost::container::small_vector_base<
const boost::container::small_vector_base<boost::filesystem::path>& boost::filesystem::path>& file_paths,
file_paths); HWND tracker_window);
/** /**
* Release ownership of the selection stop listening for X11 events. * Release ownership of the selection stop listening for X11 events.
@@ -240,6 +240,14 @@ class WineXdndProxy {
*/ */
std::string dragged_files_uri_list; std::string dragged_files_uri_list;
/**
* Wine's tracker window for tracking the drag-and-drop operation. When the
* XDND operation succeeds, we make sure to close this window to avoid the
* potential for weird race conditions where the plugin may still think
* we're doing drag-and-drop.
*/
HWND tracker_window;
/** /**
* We need to poll for mouse position changes from another thread, because * We need to poll for mouse position changes from another thread, because
* when the drag-and-drop operation starts Wine will be blocking the GUI * when the drag-and-drop operation starts Wine will be blocking the GUI