[GtkGLExt] vtk + gtk - out of border bug



Hi,
2 attached c++ files show implementation of vtk binding to gtk (based
on gtkglext) - I was told that there vtk simply draws into a gtk
widget.
On windows (linux works fine) I get problems with resizing app's
window containing this vtkGtk widget (see attached image - red arrow)
- vtk stuff gets out of its borders. The question is: how does vtk
determines the dimensions of the widget it has to draw to? what can be
done about it?
thank you in advance
Zeev Pekar
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    $RCSfile: vtkGtkRenderWindowInteractor.cxx,v $
  Language:  C++
  Date:      $Date: 2002/11/22 16:25:58 $
  Version:   $Revision: 0.1 $

  Based on wvXRenderWindowInteractor and wxVTKRenderWindowInteractor.

  Copyright (c) 2004 Dov Grobgeld <dov grobgeld weizmann ac il>

  Based on code copyright by: Ken Martin, Will Schroeder, Bill Lorensen   

  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even 
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#ifndef __vtkGtkRenderWindowInteractor_h
#define __vtkGtkRenderWindowInteractor_h

//===========================================================
// now we define the C++ class

#include "vtkRenderWindowInteractor.h"
#include "vtkRenderWindow.h"
#include "gtk/gtk.h"

class VTK_RENDERING_EXPORT vtkGtkRenderWindowInteractor : public vtkRenderWindowInteractor
{
public:
  // Constructor
  vtkGtkRenderWindowInteractor();

  // Destructor
  ~vtkGtkRenderWindowInteractor();

  // Object factory. TBD.
  static vtkGtkRenderWindowInteractor *New();

  // vtkRenderWindowInteractor overrides
  void Initialize();
  void Enable();
  void Disable();
  void Start();
  void UpdateSize(int x, int y);
  int CreateTimer(int timertype);
  int DestroyTimer();
  void TerminateApp() {};
  void Render();

  // accessor function for drawing area used for gl interaction
  GtkWidget *get_drawing_area() { return drawing_area; }

  // Make all callback friends
  friend void     cb_realize   (GtkWidget*, gpointer user_data);
  friend gboolean cb_configure (GtkWidget *widget,
				GdkEventConfigure *event,
				gpointer user_data);
  friend gboolean cb_expose    (GtkWidget *widget,
				GdkEventExpose *event,
				gpointer user_data);
  friend gboolean cb_key_press_event(GtkWidget *widget,
			        GdkEventKey *event,
				gpointer user_data);
  friend gboolean cb_key_release_event(GtkWidget *widget,
			        GdkEventKey *event,
				gpointer user_data);
  friend gboolean cb_button_press_event(GtkWidget *widget,
		                GdkEventButton *event,
				gpointer user_data);
  friend gboolean cb_button_release_event(GtkWidget *widget,
			        GdkEventButton *event,
				gpointer user_data);
  friend gboolean cb_motion_notify_event(GtkWidget *widget,
		                GdkEventMotion *event,
				gpointer user_data);
  friend gboolean cb_scroll_event(GtkWidget *widget,
		                GdkEventScroll *event,
				gpointer user_data);

  // Dov - timeout callback - will have to cast the user_data...
  friend gboolean vtkGtkRenderWindowInteractorTimer(gpointer user_data);

 protected:
  int ActiveButton;
  int RenderAllowed;
  long GetHandle();
  int Stereo;

 private:
  long Handle;
  bool Created;
  int RenderWhenDisabled;
  int UseCaptureMouse;
  GtkWidget *drawing_area;
  gint last_xpos, last_ypos, last_key_state;
  // Flag used to break timer loop
  bool do_break_timer;

  void update_mouse_pos();
};

#endif



/*=========================================================================

  Program:   Visualization Toolkit
  Module:    $RCSfile: vtkGtkRenderWindowInteractor.cxx,v $
  Language:  C++
  Date:      $Date: 2002/11/22 16:25:58 $
  Version:   $Revision: 0.1 $

  Based on wvXRenderWindowInteractor and wxVTKRenderWindowInteractor.

  Copyright (c) 2007 Dov Grobgeld <dov grobgeld gmail com>

  Based on code copyright by: Ken Martin, Will Schroeder, Bill Lorensen   

  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even 
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkGtkRenderWindowInteractor.h"
#include "vtkRenderer.h"
#include "vtkCamera.h"
#include "vtkCommand.h"
#include <gtk/gtk.h>
#include <gtk/gtkgl.h>
#ifdef G_OS_WIN32
#include "gdk/gdkwin32.h"
#else
#include <gdk/gdkx.h>
#endif
#include <gdk/gdk.h>
#include <gdk/gdkprivate.h>

void     cb_realize          (GtkWidget*,
                              gpointer user_data);
gboolean cb_expose           (GtkWidget *widget,
                              GdkEventExpose *event,
                              gpointer user_data);
gboolean cb_key_press_event  (GtkWidget *widget,
                              GdkEventKey *event,
                              gpointer user_data);
gboolean cb_key_release_event(GtkWidget *widget,
                              GdkEventKey *event,
                              gpointer user_data);
gboolean cb_button_press_event(GtkWidget *widget,
                               GdkEventButton *event,
                               gpointer user_data);
gboolean cb_button_release_event(GtkWidget *widget,
                                 GdkEventButton *event,
                                 gpointer user_data);
gboolean cb_motion_notify_event(GtkWidget *widget,
                                GdkEventMotion *event,
                                gpointer user_data);
gboolean cb_scroll_event        (GtkWidget      *widget,
                                 GdkEventScroll *event,
                                 gpointer        user_data);
gboolean cb_configure(GtkWidget *widget,
                      GdkEventConfigure *event,
                      gpointer user_data);
gboolean vtkGtkRenderWindowInteractorTimer(gpointer client_data);


// Construct an instance so that the light follows the camera motion.
vtkGtkRenderWindowInteractor::vtkGtkRenderWindowInteractor()
  : vtkRenderWindowInteractor()
  , RenderAllowed(false)
  , RenderWhenDisabled(true)
  , Created(true)
  , UseCaptureMouse(false)
  , Handle(0)
  , Stereo(0)
  , ActiveButton(0)
  , last_xpos(0)
  , last_ypos(0)
  , last_key_state(0)
  , do_break_timer(false)
{
  GdkGLConfig *glconfig;

  drawing_area = gtk_drawing_area_new();
  GTK_WIDGET_SET_FLAGS (drawing_area, GTK_CAN_FOCUS);

  gtk_widget_set_events(GTK_WIDGET(drawing_area),
			GDK_EXPOSURE_MASK
			| GDK_STRUCTURE_MASK
			| GDK_PROPERTY_CHANGE_MASK
			| GDK_POINTER_MOTION_MASK 
			| GDK_POINTER_MOTION_HINT_MASK 
			| GDK_BUTTON_PRESS_MASK
			| GDK_BUTTON_RELEASE_MASK
			| GDK_KEY_PRESS_MASK
			| GDK_KEY_RELEASE_MASK
			| GDK_LEAVE_NOTIFY_MASK
			| GDK_ENTER_NOTIFY_MASK
			);
  
  glconfig = gdk_gl_config_new_by_mode (GdkGLConfigMode(GDK_GL_MODE_RGB    |
							GDK_GL_MODE_DEPTH  |
							GDK_GL_MODE_DOUBLE));

  /* Set OpenGL-capability to the widget. */
  gtk_widget_set_gl_capability (drawing_area,
                                glconfig,
                                NULL,
                                TRUE,
                                GDK_GL_RGBA_TYPE);

  gtk_widget_set_double_buffered(drawing_area,
                                 FALSE);
  
  g_signal_connect(drawing_area, "realize",
		   G_CALLBACK(&cb_realize),
		   (gpointer)this);
  g_signal_connect(drawing_area, "configure_event",
		   G_CALLBACK(&cb_configure),
		   (gpointer)this);
  g_signal_connect(drawing_area, "expose_event",
		   G_CALLBACK(&cb_expose),
		   (gpointer)this);
  g_signal_connect(drawing_area, "key_press_event",
		   G_CALLBACK(&cb_key_press_event),
		   (gpointer)this);
  g_signal_connect(drawing_area, "key_release_event",
		   G_CALLBACK(&cb_key_release_event),
		   (gpointer)this);
  g_signal_connect(drawing_area, "button_press_event",
		   G_CALLBACK(&cb_button_press_event),
		   (gpointer)this);
  g_signal_connect(drawing_area, "button_release_event",
		   G_CALLBACK(&cb_button_release_event),
		   (gpointer)this);
  g_signal_connect(drawing_area, "scroll_event",  
		   G_CALLBACK(&cb_scroll_event),
		   (gpointer)this);
  g_signal_connect(drawing_area, "motion_notify_event",
		   G_CALLBACK(&cb_motion_notify_event),
		   (gpointer)this);

  // Copied from wxVTKRenderWindowInteractor... What is it for?
  vtkRenderWindowInteractor::SetRenderWindow(vtkRenderWindow::New());
  RenderWindow->Delete();
}

vtkGtkRenderWindowInteractor * vtkGtkRenderWindowInteractor::New()
{
  // we are not registered in the objectfactor
  return new vtkGtkRenderWindowInteractor;
}

// Todo constructor with more options...

vtkGtkRenderWindowInteractor::~vtkGtkRenderWindowInteractor()
{
  gtk_widget_destroy(drawing_area);
}

// Initializes the event handlers using a parent widget that you have
// provided.  This assumes that you want to own the event loop.
void vtkGtkRenderWindowInteractor::Initialize()
{
  Enable();
  RenderWindow->Start();

  Initialized = 1;
}

void vtkGtkRenderWindowInteractor::Enable()
{
  if (Enabled)
    return;

  Enabled = true;
  Modified();
}

void vtkGtkRenderWindowInteractor::Disable()
{
  if (!Enabled)
    return;

  Enabled = false;
  Modified();
}

void vtkGtkRenderWindowInteractor::Start()
{
  fprintf(stderr, "Interactor cannot control event loop!\n");
}

void vtkGtkRenderWindowInteractor::UpdateSize(int x,int y)
{
  // if the size changed send this on to the RenderWindow
  if ((x != this->Size[0]) || (y != this->Size[1]))
  {
    this->Size[0] = x;
    this->Size[1] = y;
    this->RenderWindow->SetSize(x,y);
  }
}

int vtkGtkRenderWindowInteractor::CreateTimer(int timertype) 
{
  
  if (timertype == VTKI_TIMER_FIRST)
  {
    // We use a repeating timer? Do we need to keep an id for it?
    g_timeout_add(10, &vtkGtkRenderWindowInteractorTimer, (gpointer)(this));
    this->do_break_timer = false;
  }

  return 1;
}

int vtkGtkRenderWindowInteractor::DestroyTimer() 
{
  this->do_break_timer = true;
  return 1;
}

long vtkGtkRenderWindowInteractor::GetHandle()
{
#ifdef G_OS_WIN32
  return (long)GDK_WINDOW_HWND(drawing_area->window);
#else
  return (long)GDK_WINDOW_XWINDOW(drawing_area->window);
#endif
}

void vtkGtkRenderWindowInteractor::Render()
{
  RenderAllowed = 1;
  if (!RenderWhenDisabled)
  {
    // tbd - check if parent is enabled
  }

  if (RenderAllowed)
  {
    if (Handle && (Handle == GetHandle()) )
    {
      RenderWindow->Render();
    }

    // TBD for reparenting
  }
}

void vtkGtkRenderWindowInteractor::update_mouse_pos()
{
  GdkModifierType mask;
  gdk_window_get_pointer(drawing_area->window,
			 &last_xpos,
			 &last_ypos,
			 &mask);
  last_key_state = mask;
}

gboolean vtkGtkRenderWindowInteractorTimer(gpointer client_data)
{
  vtkGtkRenderWindowInteractor *rwi = (vtkGtkRenderWindowInteractor *)client_data;

  if (rwi->do_break_timer) {
    return FALSE;
  }
  
  if (rwi->Enabled) 
  {
    rwi->InvokeEvent(vtkCommand::TimerEvent,NULL);
  }

  return TRUE;
}

void cb_realize(GtkWidget*,
		gpointer user_data)
{
  vtkGtkRenderWindowInteractor *rwi = (vtkGtkRenderWindowInteractor *)user_data;
  
  if (!rwi->Handle)
  {
    rwi->Handle = rwi->GetHandle();
    rwi->RenderWindow->SetWindowId((void*)rwi->Handle);
  }

  // get vtk to render to the drawing area
  //  rwi->Render();
}

gboolean cb_configure(GtkWidget *widget,
		  GdkEventConfigure *event,
		  gpointer user_data)
{
  vtkGtkRenderWindowInteractor *rwi = (vtkGtkRenderWindowInteractor *)user_data;

  rwi->UpdateSize(event->width, event->height);

  if (!rwi->Enabled)
  {
    return TRUE;
  }

  rwi->InvokeEvent(vtkCommand::ConfigureEvent, NULL);
  
  // get vtk to render to the drawing area
  rwi->Render();

  return TRUE;
}

// I'm rendering everytime I'm getting an expose event. Perhaps this
// is a waist of time...
gboolean cb_expose(GtkWidget *widget,
		   GdkEventExpose *event,
		   gpointer user_data)
{
  vtkGtkRenderWindowInteractor *rwi = (vtkGtkRenderWindowInteractor *)user_data;
  rwi->Render();
  return TRUE;
}

gboolean
cb_key_press_event(GtkWidget *widget,
		   GdkEventKey *event,
		   gpointer user_data)
{
  vtkGtkRenderWindowInteractor *rwi = (vtkGtkRenderWindowInteractor *)user_data;
  gint keyval = event->keyval;
  char key = 0;

  if (keyval < 256)
  {
    // Todo: Unicode in non-Unicode mode??
    key = (char)keyval;
  }

  rwi->update_mouse_pos();

  rwi->SetEventInformationFlipY(rwi->last_xpos,
				rwi->last_ypos,
				event->state & GDK_CONTROL_MASK,
				event->state & GDK_SHIFT_MASK,
				key,
				0,
				NULL);

  rwi->last_key_state = event->state;
  
  rwi->InvokeEvent(vtkCommand::KeyPressEvent, NULL);
  rwi->InvokeEvent(vtkCommand::CharEvent, NULL);

  return true;
}

gboolean
cb_key_release_event(GtkWidget *widget,
		     GdkEventKey *event,
		     gpointer user_data)
{
  vtkGtkRenderWindowInteractor *rwi = (vtkGtkRenderWindowInteractor *)user_data;
  gint keyval = event->keyval;
  char key = 0;

  if (keyval < 256)
  {
    // Todo: Unicode in non-Unicode mode??
    key = (char)keyval;
  }

  rwi->update_mouse_pos();
  rwi->SetEventInformationFlipY(rwi->last_xpos,
				rwi->last_ypos,
				event->state & GDK_CONTROL_MASK,
				event->state & GDK_SHIFT_MASK,
				key,
				0,
				NULL);

  rwi->last_key_state = event->state;
  
  rwi->InvokeEvent(vtkCommand::KeyReleaseEvent, NULL);

  return TRUE;
}


gboolean
cb_button_press_event(GtkWidget *widget,
		      GdkEventButton *event,
		      gpointer user_data)
{
  vtkGtkRenderWindowInteractor *rwi = (vtkGtkRenderWindowInteractor *)user_data;
  gint button = event->button;
  
  if (!rwi->Enabled || rwi->ActiveButton != 0)
    return true;

  rwi->update_mouse_pos();
  rwi->SetEventInformationFlipY(rwi->last_xpos,
				rwi->last_ypos,
				rwi->last_key_state & GDK_CONTROL_MASK,
				rwi->last_key_state & GDK_SHIFT_MASK,
				'\0',
				0,
				NULL);
  
  rwi->ActiveButton = button;

  switch (button) {
  case 1:
    rwi->InvokeEvent(vtkCommand::LeftButtonPressEvent, NULL);
    break;
  case 2:
    rwi->InvokeEvent(vtkCommand::MiddleButtonPressEvent, NULL);
    break;
  case 3:
    rwi->InvokeEvent(vtkCommand::RightButtonPressEvent, NULL);
    break;
  default:
    // Ignore other buttons at the moment
    break;
  }

  // Do we need to worry about capturing the mouse
  return TRUE;
}

gboolean
cb_scroll_event(GtkWidget *widget,
                GdkEventScroll *event,
                gpointer user_data)
{
  vtkGtkRenderWindowInteractor *rwi = (vtkGtkRenderWindowInteractor *)user_data;
  gint direction = event->direction;
  double focalPt[3];
  double distance = 0;
  double zoom = 1.0;
  
  if (!rwi->Enabled || rwi->ActiveButton != 0)
    return true;

  if (direction) 
    zoom = 0.9;
  else 
    zoom = 1.1;

  vtkRenderer *ren = rwi->FindPokedRenderer(rwi->last_xpos,
                                            rwi->last_ypos);

  ren->GetActiveCamera()->Zoom(zoom);
  rwi->RenderWindow->Render();
    
  return TRUE;
}

gboolean
cb_button_release_event(GtkWidget *widget,
			GdkEventButton *event,
			gpointer user_data)
{
  vtkGtkRenderWindowInteractor *rwi = (vtkGtkRenderWindowInteractor *)user_data;
  gint button = event->button;

  // is this right?
  if (!rwi->Enabled || rwi->ActiveButton != button)
    return true;

  rwi->update_mouse_pos();
  rwi->SetEventInformationFlipY(rwi->last_xpos,
				rwi->last_ypos,
				rwi->last_key_state & GDK_CONTROL_MASK,
				rwi->last_key_state & GDK_SHIFT_MASK,
				'\0',
				0,
				NULL);
  switch (button) {
  case 1:
    rwi->InvokeEvent(vtkCommand::LeftButtonReleaseEvent, NULL);
    break;
  case 2:
    rwi->InvokeEvent(vtkCommand::MiddleButtonReleaseEvent, NULL);
    break;
  case 3:
    rwi->InvokeEvent(vtkCommand::RightButtonReleaseEvent, NULL);
    break;
  default:
    // Ignore other buttons at the moment
    break;
  }

  rwi->ActiveButton = 0;
}

gboolean
cb_motion_notify_event(GtkWidget *widget,
		       GdkEventMotion *event,
		       gpointer user_data)
{
  vtkGtkRenderWindowInteractor *rwi = (vtkGtkRenderWindowInteractor *)user_data;

  rwi->update_mouse_pos();
  rwi->SetEventInformationFlipY(rwi->last_xpos,
				rwi->last_ypos,
				rwi->last_key_state & GDK_CONTROL_MASK,
				rwi->last_key_state & GDK_SHIFT_MASK,
				'\0',
				0,
				NULL);

  rwi->InvokeEvent(vtkCommand::MouseMoveEvent, NULL);

  return true;
}

Attachment: outOfBorderBug.jpg
Description: JPEG image



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]