# Update widget state on viewport change

**URL:** https://discourse.vtk.org/t/update-widget-state-on-viewport-change/13211
**Category:** Support
**Tags:** code
**Created:** [January 31, 2024, 11:38pm UTC](https://discourse.vtk.org/t/update-widget-state-on-viewport-change/13211 "2024-01-31T23:38:24Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![DrPepperJo](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/d/0ea827/32.png) [@DrPepperJo](https://discourse.vtk.org/u/DrPepperJo)
#### Post date: [January 31, 2024, 11:38pm UTC](https://discourse.vtk.org/t/update-widget-state-on-viewport-change/13211/1 "2024-01-31T23:38:24Z")

</div>

Below, I’ve provided a minimal running example for a problem I encounter frequently in my projects. To reproduce, do the following:

1. Place the mouse over the border of one of the border widgets.
2. Press “t” to toggle the viewports of the two renderers.
3. Press the left mouse button and drag the border of the border widget.
4. Observe that the border widget being changed is the one that was “selected” before the “t” was pressed, not the one in the current renderer.

The problem occurs, because the widget is in an interactable state when the “t” is pressed. This state is only updated when the mouse is moved. In this example, the mouse is not moved, but the content below the mouse pointer is changed, so the widget state is outdated. I encounter this kind of problem in similar ways for slightly other use cases. What is the preferred way to deal with this problem?

```auto
#include <vtkObjectFactory.h>
#include <vtkRenderer.h>
#include <vtkInteractorStyleUser.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkBorderWidget.h>

static double constexpr viewportTop[4]{ 0., .5, 1., 1. };
static double constexpr viewportBottom[4]{ 0., 0., 1., .5 };

class InteractorStyle : public vtkInteractorStyleUser
{
public:
  static InteractorStyle * New();
  vtkTypeMacro( InteractorStyle, vtkInteractorStyleUser );

  void setEnvironment( vtkRenderer * renderer1, vtkRenderer * renderer2 )
  {
    m_renderer1 = renderer1;
    m_renderer2 = renderer2;
  }

  void OnChar() override
  {
    if( 't' == Interactor->GetKeyCode() )
    {
      m_toggled = !m_toggled;
      m_renderer1->SetViewport( m_toggled ? viewportBottom : viewportTop );
      m_renderer2->SetViewport( m_toggled ? viewportTop : viewportBottom );
      Interactor->Render();
    }
    else InteractorStyle::OnChar();
  }
  
private:
  vtkRenderer * m_renderer1{};
  vtkRenderer * m_renderer2{};
  bool m_toggled{ false };
};

vtkStandardNewMacro( InteractorStyle );

int main( int, char * [] )
{
  vtkNew< vtkRenderWindow > renderWindow;

  vtkNew< InteractorStyle > interactorStyle;
  vtkNew< vtkRenderWindowInteractor > renderWindowInteractor;
  renderWindowInteractor->SetInteractorStyle( interactorStyle );
  renderWindowInteractor->SetRenderWindow( renderWindow );

  vtkNew< vtkRenderer > renderer1;
  vtkNew< vtkRenderer > renderer2;
  renderer1->SetBackground( 0.3, 0.3, 0.3 );
  renderer2->SetBackground( .5, .5, .5 );
  renderer1->SetViewport( viewportTop );
  renderer2->SetViewport( viewportBottom );
  renderWindow->AddRenderer( renderer1 );
  renderWindow->AddRenderer( renderer2 );

  vtkNew< vtkBorderWidget > borderWidget1;
  vtkNew< vtkBorderWidget > borderWidget2;
  borderWidget1->SetInteractor( renderWindowInteractor );
  borderWidget2->SetInteractor( renderWindowInteractor );
  borderWidget1->CreateDefaultRepresentation();
  borderWidget2->CreateDefaultRepresentation();
  borderWidget1->SetDefaultRenderer( renderer1 );
  borderWidget2->SetDefaultRenderer( renderer2 );
  borderWidget1->SetEnabled( true );
  borderWidget2->SetEnabled( true );

  interactorStyle->setEnvironment( renderer1, renderer2 );

  renderWindowInteractor->Start();

  return EXIT_SUCCESS;
}

```

---

<div class="post-metadata">

### Author: ![DrPepperJo](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/d/0ea827/32.png) [@DrPepperJo](https://discourse.vtk.org/u/DrPepperJo)
#### Post date: [February 11, 2024, 4:37pm UTC](https://discourse.vtk.org/t/update-widget-state-on-viewport-change/13211/2 "2024-02-11T16:37:17Z")

</div>

Since have been no replies yet, I figured I come up with a suggestion that I couldn’t get to work. Maybe someone can help me out with that approach.

I figured, as the state is not updated, because the content is moved instead of the mouse, one way to deal with this could be to manually trigger a mouse event. I tried calling

```auto
InvokeEvent( vtkCommand::MouseMoveEvent );

```

inside the `OnChar()` function, but it doesn’t work. So the question would be: How do I effectively trigger a manual `MouseMoveEvent`?

---

<div class="post-metadata">

### Author: ![jaswantp](https://discourse.vtk.org/user_avatar/discourse.vtk.org/jaswantp/32/10046_2.png) [@jaswantp](https://discourse.vtk.org/u/jaswantp)
#### Post date: [February 11, 2024, 7:40pm UTC](https://discourse.vtk.org/t/update-widget-state-on-viewport-change/13211/3 "2024-02-11T19:40:44Z")

</div>

> [@DrPepperJo](#):
>
> So the question would be: How do I effectively trigger a manual `MouseMoveEvent`?

It helps to think about the flow of events when a mouse move occurs. The VTK render window interactor is notified of mouse events from the OS event system. Such events are then massaged into the VTK’s definition of events ex: `vtkCommand::MouseMoveEvent` The VTK event-observer system then propagates those through out VTK, to interactor style, widgets, render window, etc.

For the event to be effective, you have to invoke it on the interactor, not on the style. Here’s working code. Also fixed a stack overflow caused by the line of code which executes when the keycode is not `t` inside your `InteractorStyle::OnChar` 😉

```cpp
// main.cpp
#include <vtkCommand.h>
#include <vtkObjectFactory.h>
#include <vtkRenderer.h>
#include <vtkInteractorStyleUser.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkBorderWidget.h>

static double constexpr viewportTop[4]{ 0., .5, 1., 1. };
static double constexpr viewportBottom[4]{ 0., 0., 1., .5 };

class InteractorStyle : public vtkInteractorStyleUser
{
public:
  static InteractorStyle * New();
  vtkTypeMacro( InteractorStyle, vtkInteractorStyleUser );

  void setEnvironment( vtkRenderer * renderer1, vtkRenderer * renderer2 )
  {
    m_renderer1 = renderer1;
    m_renderer2 = renderer2;
  }

  void OnChar() override
  {
    if( 't' == Interactor->GetKeyCode() )
    {
      m_toggled = !m_toggled;
      m_renderer1->SetViewport( m_toggled ? viewportBottom : viewportTop );
      m_renderer2->SetViewport( m_toggled ? viewportTop : viewportBottom );
      Interactor->InvokeEvent(vtkCommand::MouseMoveEvent);
      Interactor->Render();
    }
    else Superclass::OnChar();
  }
  
private:
  vtkRenderer * m_renderer1{};
  vtkRenderer * m_renderer2{};
  bool m_toggled{ false };
};

vtkStandardNewMacro( InteractorStyle );

int main( int, char * [] )
{
  vtkNew< vtkRenderWindow > renderWindow;

  vtkNew< InteractorStyle > interactorStyle;
  vtkNew< vtkRenderWindowInteractor > renderWindowInteractor;
  renderWindowInteractor->SetInteractorStyle( interactorStyle );
  renderWindowInteractor->SetRenderWindow( renderWindow );

  vtkNew< vtkRenderer > renderer1;
  vtkNew< vtkRenderer > renderer2;
  renderer1->SetBackground( 0.0, 0.0, 1.0 );
  renderer2->SetBackground( .5, .5, .5 );
  renderer1->SetViewport( viewportTop );
  renderer2->SetViewport( viewportBottom );
  renderWindow->AddRenderer( renderer1 );
  renderWindow->AddRenderer( renderer2 );

  vtkNew< vtkBorderWidget > borderWidget1;
  vtkNew< vtkBorderWidget > borderWidget2;
  borderWidget1->SetInteractor( renderWindowInteractor );
  borderWidget2->SetInteractor( renderWindowInteractor );
  borderWidget1->CreateDefaultRepresentation();
  borderWidget2->CreateDefaultRepresentation();
  borderWidget1->SetDefaultRenderer( renderer1 );
  borderWidget2->SetDefaultRenderer( renderer2 );
  borderWidget1->SetEnabled( true );
  borderWidget2->SetEnabled( true );

  interactorStyle->setEnvironment( renderer1, renderer2 );

  // render once to show the widgets.
  renderWindow->Render();
  renderWindowInteractor->Start();

  return EXIT_SUCCESS;
}

```

```C
# CMakeLists.txt
cmake_minimum_required(VERSION 3.12)
project(BorderWidgetDiscourse)
find_package(VTK COMPONENTS
  InteractionStyle
  InteractionWidgets
  RenderingCore
  RenderingOpenGL2
  RenderingUI)
add_executable(main main.cpp)
target_link_libraries(main PRIVATE ${VTK_LIBRARIES})

```

Tested by:

```shell
$ cmake -S . -B out -DVTK_DIR=/path/to/vtk/build
$ cmake --build out
$ ./out/main

```

---

<div class="post-metadata">

### Author: ![DrPepperJo](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/d/0ea827/32.png) [@DrPepperJo](https://discourse.vtk.org/u/DrPepperJo)
#### Post date: [February 11, 2024, 8:03pm UTC](https://discourse.vtk.org/t/update-widget-state-on-viewport-change/13211/4 "2024-02-11T20:03:01Z")

</div>

> [@jaswantp](#):
>
> For the event to be effective, you have to invoke it on the interactor, not on the style. Here’s working code.

Thank you very much, it works like a charm!

> [@jaswantp](#):
>
> Also fixed a stack overflow caused by the line of code which executes when the keycode is not `t` inside your `InteractorStyle::OnChar` 😉

Thanks, even in a minimal example, I managed to sneak in a really stupid bug 🙂 .
