Commit 847fd1be authored by François Bertel's avatar François Bertel
Browse files

ENH: Added 3DConnexion device support under X11 with Qt.

parent 023e6f22
......@@ -30,6 +30,8 @@ INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_SOURCE_DIR}
)
INCLUDE_DIRECTORIES(${VTK_TDX_INCLUDE_PATH})
QT4_WRAP_UI(UI_SRCS GUI4.ui)
QT4_WRAP_CPP(MOC_SRCS GUI4.h)
SET(SRCS ${SRCS} ${MOC_SRCS} GUI4.cxx GUI4.h)
......
......@@ -24,17 +24,16 @@
!!! license.
=========================================================================*/
#include "qapplication.h"
#include "QVTKApplication.h"
#include "GUI4.h"
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QVTKApplication app(argc, argv);
GUI4 widget;
widget.show();
return app.exec();
}
......@@ -2,14 +2,18 @@
SET ( QVTKLibSrcs
vtkEventQtSlotConnect.cxx
vtkQtConnection.cxx
QVTKApplication.cxx
QVTKInteractor.cxx
QVTKWidget.cxx
vtkTDxQtUnixDevices.cxx
)
SET ( QVTKMocHeaders
QVTKApplication.h
QVTKInteractor.h
QVTKWidget.h
vtkQtConnection.h
vtkTDxQtUnixDevices.h
)
SET ( QVTKNonMocHeaders
......@@ -117,6 +121,19 @@ SET ( PluginMocHeaders
SET_SOURCE_FILES_PROPERTIES(Q4VTKWidgetPlugin.cxx PROPERTIES
OBJECT_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/QVTKWidget.xpm)
# vtkConfigure.h is in ${VTK_BINARY_DIR}
# vtkABI.h in in ${VTK_SOURCE_DIR}/Common
# QVTKWin32Header.h is in ${VTK_SOURCE_DIR}/GUISupport/Qt
# vtkTDxConfigure.h is in ${VTK_BINARY_DIR}/Rendering
# qglobal.h (defines Q_WS_X11) is in ${QT_INCLUDE_DIR}/QtCore
SET(MOC_INCLUDE_DIRS ${MOC_INCLUDE_DIRS}
${QT_INCLUDE_DIR}
${QT_INCLUDE_DIR}/QtCore
${VTK_BINARY_DIR}/Rendering
${VTK_SOURCE_DIR}/GUISupport/Qt
${VTK_BINARY_DIR}
${VTK_SOURCE_DIR}/Common)
# Reduce the number of dirs that get included on moc command line
# since it causes issues on Windows 2000.
GET_DIRECTORY_PROPERTY(include_dirs_tmp INCLUDE_DIRECTORIES)
......
/*=========================================================================
Program: Visualization Toolkit
Module: vtkActor.h
Copyright (c) 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 "QVTKApplication.h"
#if defined(VTK_USE_TDX) && defined(Q_WS_X11)
#include "vtkTDxQtUnixDevices.h"
#include <QWidget>
#include <X11/Xlib.h> // Needed for X types used in the public interface
#endif
QVTKApplication::QVTKApplication(int &argc, char **argv)
: QApplication(argc,argv)
{
#if defined(VTK_USE_TDX) && defined(Q_WS_X11)
this->Devices=new vtkTDxQtUnixDevices;
QObject::connect(this->Devices,SIGNAL(CreateDevice(vtkTDxDevice *)),
this,SLOT(setDevice(vtkTDxDevice *)));
#endif
}
QVTKApplication::~QVTKApplication()
{
#if defined(VTK_USE_TDX) && defined(Q_WS_X11)
delete this->Devices;
#endif
}
#if defined(VTK_USE_TDX) && defined(Q_WS_X11)
bool QVTKApplication::x11EventFilter(XEvent *event)
{
// the only lines required in this method
this->Devices->ProcessEvent(
static_cast<vtkTDxUnixDeviceXEvent *>(event));
return false;
}
#endif
void QVTKApplication::setDevice(vtkTDxDevice *device)
{
#if defined(VTK_USE_TDX) && defined(Q_WS_X11)
emit CreateDevice(device);
#else
(void)device; // to avoid warnings.
#endif
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtkActor.h
Copyright (c) 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.
=========================================================================*/
// .NAME QVTKApplication - A superclass for QApplication using VTK.
// .SECTION Description
// This is a superclass for QApplication using VTK. It essentially redefined
// x11EventFilter() in order to catch X11 ClientMessage coming from the
// 3DConnexion driver.
//
// You don't have to inherit from QVTKApplication to be able to use VTK:
// you can reimplement QVTKApplication(), ~QVTKApplication(), x11EventFilter(),
// setDevice(), CreateDevice() in your own subclass of QApplication.
// It you don't, VTK will work but without the 3Dconnexion device under X11.
// In this case, QVTKApplication provides a model of implementation.
// .SECTION See Also
// vtkTDxQtUnixDevices QVTKWidget
#ifndef __QVTKApplication_h
#define __QVTKApplication_h
#include <QApplication>
#include "QVTKWin32Header.h" // for QVTK_EXPORT
#include "vtkTDxConfigure.h" // defines VTK_USE_TDX
#ifdef VTK_USE_TDX
class vtkTDxDevice;
#ifdef Q_WS_X11
class vtkTDxQtUnixDevices;
#endif
#endif
class QVTK_EXPORT QVTKApplication : public QApplication
{
Q_OBJECT
public:
QVTKApplication(int &argc, char **argv);
~QVTKApplication();
#if defined(VTK_USE_TDX) && defined(Q_WS_X11)
virtual bool x11EventFilter(XEvent *event);
#endif
public Q_SLOTS:
// Description:
// Slot to receive signal CreateDevice coming from vtkTDxQtUnixDevices.
// It re-emit signal CreateDevice (to QVTKWidget slots)
// No-op if not X11 (ie Q_WS_X11 is not defined).
void setDevice(vtkTDxDevice *device);
Q_SIGNALS:
// Description:
// Signal for VTKWidget slots.
void CreateDevice(vtkTDxDevice *device);
protected:
#if defined(VTK_USE_TDX) && defined(Q_WS_X11)
vtkTDxQtUnixDevices *Devices;
#endif
};
#endif
......@@ -43,6 +43,10 @@
# include "vtkTDxMacDevice.h"
#endif
#if defined(VTK_USE_TDX) && defined(Q_WS_X11)
# include "vtkTDxUnixDevice.h"
#endif
#include <QEvent>
#include <QSignalMapper>
#include <QTimer>
......@@ -91,6 +95,9 @@ QVTKInteractor::QVTKInteractor()
#if defined(VTK_USE_TDX) && defined(Q_WS_MAC)
this->Device=vtkTDxMacDevice::New();
#endif
#if defined(VTK_USE_TDX) && defined(Q_WS_X11)
this->Device=0;
#endif
}
void QVTKInteractor::Initialize()
......@@ -122,6 +129,23 @@ void QVTKInteractor::Initialize()
this->Enable();
}
#if defined(VTK_USE_TDX) && defined(Q_WS_X11)
// ----------------------------------------------------------------------------
vtkTDxUnixDevice *QVTKInteractor::GetDevice()
{
return this->Device;
}
// ----------------------------------------------------------------------------
void QVTKInteractor::SetDevice(vtkTDxDevice *device)
{
if(this->Device!=device)
{
this->Device=static_cast<vtkTDxUnixDevice *>(device);
}
}
#endif
/*! start method for interactor
*/
......@@ -153,6 +177,12 @@ void QVTKInteractor::StartListening()
this->Device->Initialize();
}
#endif
#if defined(VTK_USE_TDX) && defined(Q_WS_X11)
if(this->UseTDx && this->Device!=0)
{
this->Device->SetInteractor(this);
}
#endif
}
// ----------------------------------------------------------------------------
......@@ -170,6 +200,14 @@ void QVTKInteractor::StopListening()
this->Device->Close();
}
#endif
#if defined(VTK_USE_TDX) && defined(Q_WS_X11)
if(this->UseTDx && this->Device!=0)
{
// this assumes that a outfocus event is emitted prior
// a infocus event on another widget.
this->Device->SetInteractor(0);
}
#endif
}
......@@ -200,6 +238,9 @@ QVTKInteractor::~QVTKInteractor()
#if defined(VTK_USE_TDX) && defined(Q_WS_MAC)
this->Device->Delete();
#endif
#if defined(VTK_USE_TDX) && defined(Q_WS_X11)
this->Device=0;
#endif
}
/*! create Qt timer with an interval of 10 msec.
......
......@@ -50,6 +50,10 @@ class vtkTDxWinDevice;
#if defined(VTK_USE_TDX) && defined(Q_WS_MAC)
class vtkTDxMacDevice;
#endif
#if defined(VTK_USE_TDX) && defined(Q_WS_X11)
class vtkTDxDevice;
class vtkTDxUnixDevice;
#endif
class QVTKInteractorInternal;
......@@ -86,6 +90,11 @@ public:
// timer event slot
virtual void TimerEvent(int timerId);
#if defined(VTK_USE_TDX) && defined(Q_WS_X11)
virtual vtkTDxUnixDevice *GetDevice();
virtual void SetDevice(vtkTDxDevice *device);
#endif
protected:
// constructor
QVTKInteractor();
......@@ -102,6 +111,9 @@ protected:
#if defined(VTK_USE_TDX) && defined(Q_WS_MAC)
vtkTDxMacDevice *Device;
#endif
#if defined(VTK_USE_TDX) && defined(Q_WS_X11)
vtkTDxUnixDevice *Device;
#endif
private:
......
......@@ -60,6 +60,10 @@
#include "vtkImageData.h"
#include "vtkPointData.h"
#if defined(VTK_USE_TDX) && defined(Q_WS_X11)
# include "vtkTDxUnixDevice.h"
#endif
// function to dirty cache when a render occurs.
static void dirty_cache(vtkObject *, unsigned long, void *, void *);
......@@ -125,6 +129,15 @@ void QVTKWidget::SetUseTDx(bool useTDx)
if(useTDx!=this->UseTDx)
{
this->UseTDx=useTDx;
if(this->UseTDx)
{
#if defined(VTK_USE_TDX) && defined(Q_WS_X11)
QObject::connect(QApplication::instance(),
SIGNAL(CreateDevice(vtkTDxDevice *)),
this,
SLOT(setDevice(vtkTDxDevice *)));
#endif
}
}
}
......@@ -571,7 +584,7 @@ void QVTKWidget::focusInEvent(QFocusEvent* e)
// does an update because the color group's
// active status changes. We don't even use
// color groups so we do nothing here.
// also pass to interactor
mIrenAdapter->ProcessEvent(e, this->GetInteractor());
}
......@@ -583,7 +596,7 @@ void QVTKWidget::focusOutEvent(QFocusEvent* e)
// does an update because the color group's
// active status changes. We don't even use
// color groups so we do nothing here.
// also pass to interactor
mIrenAdapter->ProcessEvent(e, this->GetInteractor());
}
......@@ -654,6 +667,19 @@ QPaintEngine* QVTKWidget::paintEngine() const
#endif
#endif
// Description:
// Receive notification of the creation of the TDxDevice
void QVTKWidget::setDevice(vtkTDxDevice *device)
{
#if defined(VTK_USE_TDX) && defined(Q_WS_X11)
if(this->GetInteractor()->GetDevice()!=device)
{
this->GetInteractor()->SetDevice(device);
}
#else
(void)device; // to avoid warnings.
#endif
}
void QVTKWidget::x11_setup_window()
{
......
......@@ -174,6 +174,11 @@ public Q_SLOTS:
// the render window and the cachedImageClean() signal is emitted.
void saveImageToCache();
// Description:
// Receive notification of the creation of the TDxDevice.
// Only relevant for Unix.
void setDevice(vtkTDxDevice *device);
protected:
// overloaded resize handler
virtual void resizeEvent(QResizeEvent* event);
......
/*=========================================================================
Program: Visualization Toolkit
Module: vtkDepthPeelingPass.cxx
Copyright (c) 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 "vtkTDxQtUnixDevices.h"
#include <vtksys/stl/map>
#include <QApplication> // topLevelWidgets()
#include <QWidget>
#include <X11/Xlib.h> // Needed for X types used in the public interface
#include "vtkSmartPointer.h"
class vtkLessThanWindowId
{
public:
bool operator()(const vtkTDxUnixDeviceWindow &w1,
const vtkTDxUnixDeviceWindow &w2) const
{
return w1<w2;
}
};
typedef vtkstd::map<vtkTDxUnixDeviceWindow, vtkSmartPointer<vtkTDxUnixDevice>,
vtkLessThanWindowId> vtkWindowIdToDevice;
class vtkTDxQtUnixDevicesPrivate
{
public:
vtkWindowIdToDevice Map;
};
// ----------------------------------------------------------------------------
vtkTDxQtUnixDevices::vtkTDxQtUnixDevices()
{
this->Private=new vtkTDxQtUnixDevicesPrivate;
}
// ----------------------------------------------------------------------------
vtkTDxQtUnixDevices::~vtkTDxQtUnixDevices()
{
cout << "delete private" << endl;
delete this->Private;
}
// ----------------------------------------------------------------------------
void vtkTDxQtUnixDevices::ProcessEvent(vtkTDxUnixDeviceXEvent *e)
{
const XEvent *event=static_cast<const XEvent *>(e);
// Find the real X11 window id.
QWidgetList l=static_cast<QApplication *>(QApplication::instance())
->topLevelWidgets();
int winIdLast=0;
foreach(QWidget *w,l)
{
if(!w->isHidden())
{
winIdLast=w->winId();
}
}
vtkTDxUnixDeviceWindow winId=static_cast<vtkTDxUnixDeviceWindow>(winIdLast);
// ;event->xany.window;
if(winId!=0)
{
vtkWindowIdToDevice::iterator it=this->Private->Map.find(winId);
vtkSmartPointer<vtkTDxUnixDevice> device=0;
if(it==this->Private->Map.end())
{
// not yet created.
device=vtkSmartPointer<vtkTDxUnixDevice>::New();
this->Private->Map.insert(
vtkstd::pair<const vtkTDxUnixDeviceWindow ,vtkSmartPointer<vtkTDxUnixDevice> >(
winId,device));
device->SetDisplayId(event->xany.display);
device->SetWindowId(winId);
device->SetInteractor(0);
device->Initialize();
if(!device->GetInitialized())
{
vtkGenericWarningMacro("failed to initialize device.");
}
else
{
cout << "device initialized on window" << winId << hex << winId << dec;
emit CreateDevice(device);
}
}
else
{
device=(*it).second;
}
if(event->type==ClientMessage) // 33
{
bool caught=false;
if(device->GetInitialized())
{
caught=device->ProcessEvent(e);
}
}
}
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtkActor.h
Copyright (c) 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.
=========================================================================*/
// .NAME vtkTDxQtUnixDevices - Manage a list vtkTDXUnixDevice(s).
// .SECTION Description
// This class is essentially a map between a X11 window id and a
// vtkTDXUnixDevice. It is uses internally by QVTKApplication.
//
// .SECTION See Also
// vtkTDxUnixDevice QVTKWidget QVTKApplication
#ifndef __vtkTDxQtUnixDevices_h
#define __vtkTDxQtUnixDevices_h
#include <QObject>
#include "QVTKWin32Header.h" // for QVTK_EXPORT
#include "vtkTDxUnixDevice.h" // required for vtkTDxUnixDeviceXEvent
class vtkTDxQtUnixDevicesPrivate;
class QVTK_EXPORT vtkTDxQtUnixDevices : public QObject
{
Q_OBJECT
public:
vtkTDxQtUnixDevices();
~vtkTDxQtUnixDevices();
// Description;
// Process X11 event `e'. Create a device and emit signal CreateDevice if it
// does not exist yet.
// \pre e_exists: e!=0
void ProcessEvent(vtkTDxUnixDeviceXEvent *e);
signals:
// Description:
// This signal should be connected to a slot in the QApplication.
// The slot in the QApplication is supposed to remit this signal.
// The QVTKWidget have slot to receive this signal from the QApplication.
void CreateDevice(vtkTDxDevice *device);
protected:
vtkTDxQtUnixDevicesPrivate *Private;
private:
vtkTDxQtUnixDevices(const vtkTDxQtUnixDevices&); // Not implemented.
void operator=(const vtkTDxQtUnixDevices&); // Not implemented.
};
#endif
......@@ -54,10 +54,9 @@ vtkRenderWindowInteractor *vtkTDxDevice::GetInteractor() const
// Set the interactor on which events will be invoked.
// Initial value is 0.
// Called by the Interactor itself ONLY.
// \pre not_yet_initialized: !GetInitialized()
// It can be called if the device is initialized or not.
void vtkTDxDevice::SetInteractor(vtkRenderWindowInteractor *i)
{
assert("pre: not_yet_initialized" && !this->GetInitialized());
if(this->Interactor!=i)
{
this->Interactor=i;
......
......@@ -58,7 +58,7 @@ public:
// Set the interactor on which events will be invoked.
// Initial value is 0.
// Called by the Interactor itself ONLY.
// \pre not_yet_initialized: !GetInitialized()
// It can be called if the device is initialized or not.
void SetInteractor(vtkRenderWindowInteractor *i);
protected:
......
......@@ -122,7 +122,6 @@ void vtkTDxUnixDevice::Initialize()
assert("pre: not_yet_initialized" && !this->GetInitialized());
assert("pre: valid_display" && this->GetDisplayId()!=0);
assert("pre: valid_window" && this->GetWindowId()!=0);
assert("pre: valid_interactor" && this->GetInteractor()!=0);
int status=MagellanInit(static_cast<Display *>(this->DisplayId),
static_cast<Window>(this->WindowId));
......@@ -213,22 +212,30 @@ bool vtkTDxUnixDevice::ProcessEvent(const vtkTDxUnixDeviceXEvent *e)
motionInfo.AxisY=axis[1]/motionInfo.Angle;
motionInfo.AxisZ=axis[2]/motionInfo.Angle;
}
this->Interactor->InvokeEvent(vtkCommand::TDxMotionEvent,&motionInfo);
if(this->Interactor!=0)
{
this->Interactor->InvokeEvent(vtkCommand::TDxMotionEvent,&motionInfo);
}
result=true;
break;
case MagellanInputButtonPressEvent:
vtkDebugMacro(<< "it is MagellanInputButtonPressEvent");
buttonInfo=info.MagellanButton;
this->Interactor->InvokeEvent(vtkCommand::TDxButtonPressEvent,
&buttonInfo);
if(this->Interactor!=0)
{
this->Interactor->InvokeEvent(vtkCommand::TDxButtonPressEvent,
&buttonInfo);
}
result=true;
break;
case MagellanInputButtonReleaseEvent:
vtkDebugMacro(<< "it is MagellanInputButtonReleaseEvent");
buttonInfo=info.MagellanButton;