diff --git a/Rendering/UI/vtkXRenderWindowInteractor.cxx b/Rendering/UI/vtkXRenderWindowInteractor.cxx index 055f406c98c93408ab768c4d2cf909f7385c08e3..f78301f348a228653ba54f058cbc9f3711fe3c47 100644 --- a/Rendering/UI/vtkXRenderWindowInteractor.cxx +++ b/Rendering/UI/vtkXRenderWindowInteractor.cxx @@ -144,17 +144,13 @@ public: static std::set<vtkXRenderWindowInteractor*> Instances; - struct FDWaitInformation + struct LoopInformation { // whether application was terminated bool Done = false; - // whether `WaitForEvents` invokes `select` with a timeout argument. - bool UseTimeout = false; // the number of events dispatched by `ProcessEvents()` uint64_t NumEventsDispatched = 0; - // the timeout value provided to `select`. waits until an event occurs or this interval expires. - timeval WaitInterval; - } FDWaitInfo; + } LoopInfo; int DisplayConnection; private: @@ -232,25 +228,17 @@ void vtkXRenderWindowInteractor::TerminateApp() void vtkXRenderWindowInteractor::ProcessEvents() { auto& internals = (*this->Internal); - auto& done = internals.FDWaitInfo.Done; - auto& evCount = internals.FDWaitInfo.NumEventsDispatched; - auto& waitTv = internals.FDWaitInfo.WaitInterval; - auto& useTimeout = internals.FDWaitInfo.UseTimeout; + auto& done = internals.LoopInfo.Done; + auto& evCount = internals.LoopInfo.NumEventsDispatched; // reset vars which help VTK wait for new events or timer timeouts. done = true; evCount = 0; - useTimeout = false; for (auto rwi = vtkXRenderWindowInteractorInternals::Instances.begin(); rwi != vtkXRenderWindowInteractorInternals::Instances.end();) { XEvent event; - if (XPending((*rwi)->DisplayId) == 0) - { - // get how long to wait for the next timer - useTimeout = (*rwi)->Internal->GetTimeToNextTimer(waitTv); - } while (XPending((*rwi)->DisplayId) != 0) { // If events are pending, dispatch them to the right RenderWindowInteractor @@ -285,20 +273,44 @@ void vtkXRenderWindowInteractor::ProcessEvents() ++rwi; } } + this->Done = done; } //------------------------------------------------------------------------------ void vtkXRenderWindowInteractor::WaitForEvents() { - auto& internals = (*this->Internal); - auto& fdWaitInfo = (internals.FDWaitInfo); + bool useTimeout = false; + timeval soonestTimer; + + // check to see how long we wait for the next timer + for (auto rwi : vtkXRenderWindowInteractorInternals::Instances) + { + if (rwi->Done) + continue; + + timeval t; + bool haveTimer = rwi->Internal->GetTimeToNextTimer(t); + if (haveTimer) + { + if (!useTimeout) + { + useTimeout = true; + soonestTimer = t; + } + else if (timercmp(&t, &soonestTimer, <)) + { + soonestTimer = t; + } + } + } + fd_set in_fds; // select will wait until 'tv' elapses or something else wakes us FD_ZERO(&in_fds); int maxFd = -1; - timeval* timeout = fdWaitInfo.UseTimeout ? &fdWaitInfo.WaitInterval : nullptr; + timeval* timeout = useTimeout ? &soonestTimer : nullptr; for (auto rwi : vtkXRenderWindowInteractorInternals::Instances) { if (!rwi->Done) @@ -330,11 +342,11 @@ void vtkXRenderWindowInteractor::StartEventLoop() do { auto& internals = (*this->Internal); - auto& fdWaitInfo = (internals.FDWaitInfo); + auto& loopInfo = (internals.LoopInfo); // process pending events. this->ProcessEvents(); // wait for events only if no events were dispatched and application is not yet terminated. - if (!fdWaitInfo.NumEventsDispatched && !fdWaitInfo.Done) + if (!loopInfo.NumEventsDispatched && !loopInfo.Done) { this->WaitForEvents(); }