/*========================================================================= Program: Visualization Toolkit Module: vtkTDxUnixDevice.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 "vtkTDxUnixDevice.h" #include #include // Needed for X types used in the public interface // Display *DisplayId; // Actually a "Display *" but we cannot include Xlib.h // Window WindowId; // Actually a "Window" but we cannot include Xlib.h #define SGI // Used in xdrvlib.h to define ParameterCheck // xdrvlib.h does not have the usual __cplusplus extern "C" guard extern "C" { #include "xdrvlib.h" // Magellan X-Window driver API. } #include "vtkTDxMotionEventInfo.h" #include "vtkCommand.h" #include "vtkObjectFactory.h" #include "vtkRenderWindowInteractor.h" #include "vtkMath.h" vtkStandardNewMacro(vtkTDxUnixDevice); // ---------------------------------------------------------------------------- // Description: // Default constructor. Just set initial values for // DisplayId (0), WindowId (0)), TranslationScale (1.0), // RotationScale (1.0). vtkTDxUnixDevice::vtkTDxUnixDevice() { this->DisplayId=0; this->WindowId=0; this->TranslationScale=1.0; this->RotationScale=1.0; this->Interactor=0; // this->DebugOn(); } // ---------------------------------------------------------------------------- // Description: // Destructor. If the device is not initialized, do nothing. If the device // is initialized, close the device. vtkTDxUnixDevice::~vtkTDxUnixDevice() { if(this->Initialized) { this->Close(); } } // ---------------------------------------------------------------------------- // Description: // Get the ID of the X Display. Initial value is 0. vtkTDxUnixDeviceDisplay *vtkTDxUnixDevice::GetDisplayId() const { return this->DisplayId; } // ---------------------------------------------------------------------------- // Description: // Get the ID of the X Window. Initial value is 0. vtkTDxUnixDeviceWindow vtkTDxUnixDevice::GetWindowId() const { return this->WindowId; } // ---------------------------------------------------------------------------- // Description: // Set the ID of the X Display. // \pre not_yet_initialized: !GetInitialized() void vtkTDxUnixDevice::SetDisplayId(vtkTDxUnixDeviceDisplay *id) { assert("pre: not_yet_initialized" && !this->GetInitialized()); if(this->DisplayId!=id) { this->DisplayId=id; this->Modified(); } } // ---------------------------------------------------------------------------- // Description: // Set the ID of the X Window. // \pre not_yet_initialized: !GetInitialized() void vtkTDxUnixDevice::SetWindowId(vtkTDxUnixDeviceWindow id) { assert("pre: not_yet_initialized" && !this->GetInitialized()); if(this->WindowId!=id) { this->WindowId=id; this->Modified(); } } // ---------------------------------------------------------------------------- // Description: // Initialize the device with the current display and window ids. // It updates the value of GetInitialized(). // Initialization can fail. You must look for the value of // GetInitialized() before processing further. // \pre not_yet_initialized: !GetInitialized() // \pre valid_display: GetDisplayId()!=0 // \pre valid_window: GetWindowId()!=0 // \pre valid_interactor: GetInteractor()!=0 void vtkTDxUnixDevice::Initialize() { assert("pre: not_yet_initialized" && !this->GetInitialized()); assert("pre: valid_display" && this->GetDisplayId()!=0); assert("pre: valid_window" && this->GetWindowId()!=0); int status=MagellanInit(static_cast(this->DisplayId), static_cast(this->WindowId)); this->Initialized=status==1; } // ---------------------------------------------------------------------------- // Description: // Close the device. This is called by the destructor. // You don't have to close the device explicitly, as the destructor do it // automatically, but you can. // \pre initialized: GetInitialized(). // \post restored: !GetInitialized() void vtkTDxUnixDevice::Close() { assert("pre: initialized" && this->GetInitialized()); vtkDebugMacro(<< "Close()" ); MagellanClose(static_cast(this->DisplayId)); this->Initialized=false; assert("post: restored" && !this->GetInitialized()); } // ---------------------------------------------------------------------------- // Description: // Translate the X11 event by invoking a VTK event, if the event came from // the device. // Return true if the event passed in argument was effectively an event from // the device, return false otherwise. // \pre initialized: GetInitialized() // \pre e_exists: e!=0 // \pre e_is_client_message: e->type==ClientMessage bool vtkTDxUnixDevice::ProcessEvent(const vtkTDxUnixDeviceXEvent *e) { assert("pre: initialized" && this->GetInitialized()); assert("pre: e_exists" && e!=0); assert("pre: e_is_client_message" && static_cast(e)->type==ClientMessage); MagellanFloatEvent info; const XEvent *event=static_cast(e); int deviceEvent=MagellanTranslateEvent( static_cast(this->DisplayId), const_cast(event), &info, this->TranslationScale, this->RotationScale); vtkDebugMacro(<< "deviceEvent=" << deviceEvent); vtkTDxMotionEventInfo motionInfo; int buttonInfo; double axis[3]; bool result; switch(deviceEvent) { case MagellanInputMotionEvent: vtkDebugMacro(<< "it is MagellanInputMotionEvent"); MagellanRemoveMotionEvents(static_cast(this->DisplayId)); motionInfo.X=info.MagellanData[MagellanX]; motionInfo.Y=info.MagellanData[MagellanY]; // On Unix, the Z axis is reversed (wrong). We want to have a // right-handed coordinate system, so positive Z has to come towards us, // as on Windows. motionInfo.Z=-info.MagellanData[MagellanZ]; axis[0]=info.MagellanData[MagellanA]; axis[1]=info.MagellanData[MagellanB]; // On Unix, the Z axis is reserved (wrong). axis[2]=-info.MagellanData[MagellanC]; motionInfo.Angle=vtkMath::Norm(axis); if(motionInfo.Angle==0.0) { motionInfo.AxisX=0.0; motionInfo.AxisY=0.0; motionInfo.AxisZ=1.0; } else { motionInfo.AxisX=axis[0]/motionInfo.Angle; motionInfo.AxisY=axis[1]/motionInfo.Angle; motionInfo.AxisZ=axis[2]/motionInfo.Angle; } if(this->Interactor!=0) { this->Interactor->InvokeEvent(vtkCommand::TDxMotionEvent,&motionInfo); } result=true; break; case MagellanInputButtonPressEvent: vtkDebugMacro(<< "it is MagellanInputButtonPressEvent"); buttonInfo=info.MagellanButton; if(this->Interactor!=0) { this->Interactor->InvokeEvent(vtkCommand::TDxButtonPressEvent, &buttonInfo); } result=true; break; case MagellanInputButtonReleaseEvent: vtkDebugMacro(<< "it is MagellanInputButtonReleaseEvent"); buttonInfo=info.MagellanButton; if(this->Interactor!=0) { this->Interactor->InvokeEvent(vtkCommand::TDxButtonReleaseEvent, &buttonInfo); } result=true; break; default: vtkDebugMacro(<< "it is not a Magellan event"); result=false; break; } return result; } // ---------------------------------------------------------------------------- // Description: // Set the sensitivity of the device for the current application. // A neutral value is 1.0. // \pre initialized: GetInitialized() void vtkTDxUnixDevice::SetSensitivity(double sensitivity) { assert("pre: initialized" && this->GetInitialized()); MagellanApplicationSensitivity(static_cast(this->DisplayId), sensitivity); } // ---------------------------------------------------------------------------- void vtkTDxUnixDevice::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "RotationScale: " << this->RotationScale << endl; os << indent << "TranslationScale: " << this->TranslationScale << endl; }