vtkXRenderWindowInteractor: ProcessEvents does not work

The ProcessEvents() method of vtkRenderWindowInteractor can be used to implement custom event loops.

I used the method on a Ubuntu LTs 18.04 Machine with vtk 9.
My setup worked when i called the Start() method but not when i called ProcessEvents() in my custom loop.

Looking into the source code the vtkXRenderWindowInteractor (the ubuntu subclass) uses a BreakLoopFlag instead of the Common Done flag to handle the loop in the StartEventLoop method (Done is used in all other vtkRenderWindowInteractor subclasses).

The BreakLoopFlag can not be accessed from the BaseClass and it is initialized at 1, which causes ProcessEvents() to immediately return without processing any events.

So i guess this is an implementation bug and the vtkXRenderWindowInteractor should be changed to use the Done flag which is accessible from the base class.

Cc: @ken-martin

Tom can you try your suggested change and see if it works? If so you or I can whip up a quick MR for it.

I tested it and it works. I would be happy if you do the MR, but apparently i cant upload the fixed files.

Can paste a diff here, if so I’ll create the MR etc

Diffs of the header and source. Maybe ive gone a bit over board and removed all functions with BreakLoopFlag (which are unneccessary), which may break existing implementations that specifically used vtkXRenderWindowInteractor.

If this is an issue just change
BreakLoopFlagOff and On to set Done instead of BreakLoopFlag.

diff --git a/Rendering/UI/vtkXRenderWindowInteractor.h b/Rendering/UI/vtkXRenderWindowInteractor.h
index d5555cafde…f6fe969d51 100644
— a/Rendering/UI/vtkXRenderWindowInteractor.h
+++ b/Rendering/UI/vtkXRenderWindowInteractor.h
@@ -65,18 +65,6 @@ public:
*/
void ProcessEvents() override;

  • //@{

  • /**

    • The BreakLoopFlag is checked in the Start() method.
    • Setting it to anything other than zero will cause
    • the interactor loop to terminate and return to the
    • calling function.
  • */

  • vtkGetMacro(BreakLoopFlag, int);

  • void SetBreakLoopFlag(int);

  • void BreakLoopFlagOff();

  • void BreakLoopFlagOn();

  • //@}

    //@{
    /**
    @@ -143,7 +131,6 @@ protected:

    void FireTimers();

  • static int BreakLoopFlag;

    /**

    • This will start up the X event loop and never return. If you

diff --git a/Rendering/UI/vtkXRenderWindowInteractor.cxx b/Rendering/UI/vtkXRenderWindowInteractor.cxx
index 0cce4d9771…fead37c302 100644
— a/Rendering/UI/vtkXRenderWindowInteractor.cxx
+++ b/Rendering/UI/vtkXRenderWindowInteractor.cxx
@@ -138,8 +138,6 @@ private:
std::map<int, vtkXRenderWindowInteractorTimer> LocalToTimer;
};

-int vtkXRenderWindowInteractor::BreakLoopFlag = 1;

// for some reason the X11 def of KeySym is getting messed up
typedef XID vtkKeySym;

@@ -172,12 +170,12 @@ vtkXRenderWindowInteractor::~vtkXRenderWindowInteractor()
// This results in Start() returning to its caller.
void vtkXRenderWindowInteractor::TerminateApp()
{

  • if (this->BreakLoopFlag)
  • if (this->Done)
    {
    return;
    }
  • this->BreakLoopFlag = 1;
  • this->Done=1;

    // Send a VTK_BreakXtLoop ClientMessage event to be sure we pop out of the
    // event loop. This “wakes up” the event loop. Otherwise, it might sit idle
    @@ -198,34 +196,10 @@ void vtkXRenderWindowInteractor::TerminateApp()
    XFlush(client.display);
    }

-void vtkXRenderWindowInteractor::SetBreakLoopFlag(int f)
-{

  • if (f)
  • {
  • this->BreakLoopFlagOn();
  • }
  • else
  • {
  • this->BreakLoopFlagOff();
  • }
    -}

-void vtkXRenderWindowInteractor::BreakLoopFlagOff()
-{

  • this->BreakLoopFlag = 0;
  • this->Modified();
    -}

-void vtkXRenderWindowInteractor::BreakLoopFlagOn()
-{

  • this->TerminateApp();
  • this->Modified();
    -}

void vtkXRenderWindowInteractor::ProcessEvents()
{
XEvent event;

  • while (XPending(this->DisplayId) && this->BreakLoopFlag == 0)
  • while (XPending(this->DisplayId) && this->Done == 0)
    {
    XNextEvent(this->DisplayId, &event);
    this->DispatchEvent(&event);
    @@ -242,7 +216,7 @@ void vtkXRenderWindowInteractor::StartEventLoop()
    fd_set in_fds;
    struct timeval tv;
  • this->BreakLoopFlag = 0;
  • this->Done = 0;
    do
    {
    if (XPending(this->DisplayId) == 0)
    @@ -267,7 +241,7 @@ void vtkXRenderWindowInteractor::StartEventLoop()
    this->DispatchEvent(&event);
    }
    this->FireTimers();
  • } while (this->BreakLoopFlag == 0);
  • } while (this->Done == 0);
    }

//-------------------------------------------------------------------------
@@ -384,7 +358,7 @@ void vtkXRenderWindowInteractor::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);

  • os << indent << "BreakLoopFlag: " << (this->BreakLoopFlag ? “On\n” : “Off\n”);
  • os << indent << "Done: " << (this->Done ? “Yes\n” : “No\n”);
    }

//-------------------------------------------------------------------------

Thanks MR here https://gitlab.kitware.com/vtk/vtk/-/merge_requests/6687

1 Like