Skip to content

Commit 2e33d50

Browse files
authored
Fix Linux and Windows spinOnce behaviour (#5542)
* Fix Linux and Windows spinOnce behaviour Repeatedly calling processEvents is necessary to service the message queue in a timely manner. On Windows this also avoids the problem of missing WM_QUIT messages due to being stuck in a modal event loop, most commonly resizing or moving the window. * Avoid busy waiting and add failsafe one-shot timer
1 parent e816414 commit 2e33d50

File tree

1 file changed

+18
-5
lines changed

1 file changed

+18
-5
lines changed

visualization/src/pcl_visualizer.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -593,11 +593,24 @@ pcl::visualization::PCLVisualizer::spinOnce (int time, bool force_redraw)
593593

594594
#if VTK_MAJOR_VERSION >= 9 && (VTK_MINOR_VERSION != 0 || VTK_BUILD_VERSION != 0) && (VTK_MINOR_VERSION != 0 || VTK_BUILD_VERSION != 1)
595595
// All VTK 9 versions, except 9.0.0 and 9.0.1
596-
if(interactor_->IsA("vtkXRenderWindowInteractor")) {
597-
DO_EVERY (1.0 / interactor_->GetDesiredUpdateRate (),
598-
interactor_->ProcessEvents ();
599-
std::this_thread::sleep_for (std::chrono::milliseconds (time));
600-
);
596+
if (interactor_->IsA("vtkXRenderWindowInteractor") || interactor_->IsA("vtkWin32RenderWindowInteractor")) {
597+
const auto start_time = std::chrono::steady_clock::now();
598+
const auto stop_time = start_time + std::chrono::milliseconds(time);
599+
600+
// Older versions of VTK 9 block for up to 1s or more on X11 when there are no events.
601+
// So add a one-shot timer to guarantee an event will happen roughly by the time the user expects this function to return
602+
// https://gitlab.kitware.com/vtk/vtk/-/issues/18951#note_1351387
603+
interactor_->CreateOneShotTimer(time);
604+
605+
// Process any pending events at least once, this could take a while due to a long running render event
606+
interactor_->ProcessEvents();
607+
608+
// Wait for the requested amount of time to have elapsed or exit immediately via GetDone being true when terminateApp is called
609+
while(std::chrono::steady_clock::now() < stop_time && !interactor_->GetDone() )
610+
{
611+
interactor_->ProcessEvents();
612+
std::this_thread::sleep_for(std::chrono::milliseconds(1));
613+
}
601614
}
602615
else
603616
#endif

0 commit comments

Comments
 (0)