From 678bf80365739c91d415135fb18a55b75f76b512 Mon Sep 17 00:00:00 2001 From: Paul Choisel Date: Thu, 9 Jul 2020 09:37:48 +0200 Subject: [PATCH] Restore multiple RenderWindowInteractor functionality. Since VTK9, on Linux, vtkXRenderWindowInteractor is not capable of handling having multiple RenderWindowInteractor, while this functionality was supported in VTK8.2 and is still working on Windows (VTK9). This commit restores the ability to manage several instances by storing a pointer to each declared RenderWindowInteractor in a static vector, and dispatching the events to the right Interactor. --- Rendering/UI/vtkXRenderWindowInteractor.cxx | 92 +++++++++++++++++---- 1 file changed, 77 insertions(+), 15 deletions(-) diff --git a/Rendering/UI/vtkXRenderWindowInteractor.cxx b/Rendering/UI/vtkXRenderWindowInteractor.cxx index f5762f70a98..72f8004179e 100644 --- a/Rendering/UI/vtkXRenderWindowInteractor.cxx +++ b/Rendering/UI/vtkXRenderWindowInteractor.cxx @@ -14,6 +14,7 @@ =========================================================================*/ #include "vtkXRenderWindowInteractor.h" +#include #include #include #include @@ -128,11 +129,15 @@ public: } } + static std::vector Instances; + private: int TimerIdCount; std::map LocalToTimer; }; +std::vector vtkXRenderWindowInteractorInternals::Instances; + // for some reason the X11 def of KeySym is getting messed up typedef XID vtkKeySym; @@ -189,6 +194,7 @@ void vtkXRenderWindowInteractor::TerminateApp() XSendEvent(client.display, client.window, True, NoEventMask, reinterpret_cast(&client)); XFlush(client.display); + this->RenderWindow->Finalize(); } void vtkXRenderWindowInteractor::ProcessEvents() @@ -207,30 +213,84 @@ void vtkXRenderWindowInteractor::ProcessEvents() // loop is exited. void vtkXRenderWindowInteractor::StartEventLoop() { - int X11fd = ConnectionNumber(this->DisplayId); + std::vector rwiFileDescriptors; fd_set in_fds; struct timeval tv; + struct timeval minTv; + + for (auto rwi : vtkXRenderWindowInteractorInternals::Instances) + { + rwi->Done = false; + rwiFileDescriptors.push_back(ConnectionNumber(rwi->DisplayId)); + } - this->Done = false; + bool done = true; do { - if (XPending(this->DisplayId) == 0) + bool wait = true; + done = true; + minTv.tv_sec = 1000; + minTv.tv_usec = 1000; + XEvent event; + for (auto rwi = vtkXRenderWindowInteractorInternals::Instances.begin(); + rwi != vtkXRenderWindowInteractorInternals::Instances.end();) { - // get how long to wait for the next timer - this->Internal->GetTimeToNextTimer(tv); - // select will wait until 'tv' elapses or something else wakes us - FD_ZERO(&in_fds); - FD_SET(X11fd, &in_fds); - select(X11fd + 1, &in_fds, nullptr, nullptr, &tv); + + if (XPending((*rwi)->DisplayId) == 0) + { + // get how long to wait for the next timer + (*rwi)->Internal->GetTimeToNextTimer(tv); + minTv.tv_sec = std::min(tv.tv_sec, minTv.tv_sec); + minTv.tv_usec = std::min(tv.tv_usec, minTv.tv_usec); + } + else + { + // If events are pending, dispatch them to the right RenderWindowInteractor + XNextEvent((*rwi)->DisplayId, &event); + (*rwi)->DispatchEvent(&event); + wait = false; + } + (*rwi)->FireTimers(); + + // Check if all RenderWindowInteractors have been terminated + done = done && (*rwi)->Done; + + // If current RenderWindowInteractor have been terminated, handle its last event, + // then remove it from the Instance vector + if ((*rwi)->Done) + { + // Empty the event list + while (XPending((*rwi)->DisplayId) != 0) + { + XNextEvent((*rwi)->DisplayId, &event); + (*rwi)->DispatchEvent(&event); + } + // Adjust the file descriptors vector + int rwiPosition = + std::distance(vtkXRenderWindowInteractorInternals::Instances.begin(), rwi); + rwi = vtkXRenderWindowInteractorInternals::Instances.erase(rwi); + rwiFileDescriptors.erase(rwiFileDescriptors.begin() + rwiPosition); + } + else + { + ++rwi; + } } - else + + if (wait && !done) { - XEvent event; - XNextEvent(this->DisplayId, &event); - this->DispatchEvent(&event); + // select will wait until 'tv' elapses or something else wakes us + FD_ZERO(&in_fds); + for (auto rwiFileDescriptor : rwiFileDescriptors) + { + FD_SET(rwiFileDescriptor, &in_fds); + } + int maxFileDescriptor = + *std::max_element(rwiFileDescriptors.begin(), rwiFileDescriptors.end()); + select(maxFileDescriptor + 1, &in_fds, nullptr, nullptr, &minTv); } - this->FireTimers(); - } while (!this->Done); + + } while (!done); } //------------------------------------------------------------------------------ @@ -266,6 +326,8 @@ void vtkXRenderWindowInteractor::Initialize() ren->SetDisplayId(this->DisplayId); } + vtkXRenderWindowInteractorInternals::Instances.push_back(this); + size = ren->GetActualSize(); size[0] = ((size[0] > 0) ? size[0] : 300); size[1] = ((size[1] > 0) ? size[1] : 300); -- GitLab