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);
}
void WineXdndProxy::begin_xdnd(
const boost::container::small_vector_base<boost::filesystem::path>&
file_paths) {
void WineXdndProxy::begin_xdnd(const boost::container::small_vector_base<
boost::filesystem::path>& file_paths,
HWND tracker_window) {
if (file_paths.empty()) {
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
// GUI thread, we need to do our XDND polling from another thread. Luckily
// the X11 API is thread safe.
this->tracker_window = tracker_window;
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
// will set a timeout here to avoid hanging
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();
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();
}
@@ -841,8 +851,10 @@ void CALLBACK dnd_winevent_callback(HWINEVENTHOOK /*hWinEventHook*/,
return;
}
PostMessageW(hwnd, WM_QUIT, 0, 0);
try {
instance->begin_xdnd(dragged_files);
instance->begin_xdnd(dragged_files, hwnd);
} catch (const std::exception& error) {
std::cerr << "XDND initialization failed:" << 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`
* selection and setting up the event listeners.
*/
void begin_xdnd(
const boost::container::small_vector_base<boost::filesystem::path>&
file_paths);
void begin_xdnd(const boost::container::small_vector_base<
boost::filesystem::path>& file_paths,
HWND tracker_window);
/**
* Release ownership of the selection stop listening for X11 events.
@@ -240,6 +240,14 @@ class WineXdndProxy {
*/
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
* when the drag-and-drop operation starts Wine will be blocking the GUI