Salome HOME
Join modifications from BR_Dev_For_4_0 tag V4_1_1.
[modules/gui.git] / src / SVTK / SVTK_SpaceMouse.cxx
1 //  SALOME VTKViewer : build VTK viewer into Salome desktop
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //
23 //
24 //  File   : SVTK_SpaceMouse.cxx
25 //  Author : Alexander SLADKOV
26 //  Module : SALOME
27 //  $Header$
28
29 #include <string.h>
30 #include <math.h>
31 #include <stdio.h>
32
33 #ifndef WIN32
34 #include <X11/X.h>
35 #include <X11/Xlib.h>
36 #include <X11/Xutil.h>
37 #include <X11/Xatom.h>
38 #include <X11/keysym.h>
39 #endif
40
41 #include "SVTK_SpaceMouse.h"
42
43 SVTK_SpaceMouse* SVTK_SpaceMouse::myInstance = 0;
44
45 /*!
46   \return shared instance of object (creates if there is no one)
47 */
48 SVTK_SpaceMouse* SVTK_SpaceMouse::getInstance()
49 {
50   if ( !myInstance )
51     myInstance = new SVTK_SpaceMouse();
52   return myInstance;
53 }
54
55 /*!
56   Constructor
57 */
58 SVTK_SpaceMouse::SVTK_SpaceMouse()
59 {
60 #ifndef WIN32
61   win = InputFocus;
62 #endif
63   spaceMouseOn = 0;
64 }
65
66 #ifndef WIN32
67
68 /*!
69   Initialization
70 */
71 int SVTK_SpaceMouse::initialize( Display *display, Window window )
72 {
73  XMotionEvent        = XInternAtom( display, "MotionEvent",        1 );
74  XButtonPressEvent   = XInternAtom( display, "ButtonPressEvent",   1 );
75  XButtonReleaseEvent = XInternAtom( display, "ButtonReleaseEvent", 1 );
76  XCommandEvent       = XInternAtom( display, "CommandEvent",       1 );
77
78  spaceMouseOn = (XMotionEvent        != 0) && 
79                 (XButtonPressEvent   != 0) && 
80                 (XButtonReleaseEvent != 0) && 
81                 (XCommandEvent       != 0);
82  if ( !spaceMouseOn )
83   return 0;
84
85  spaceMouseOn = setWindow( display, window );
86  if ( !spaceMouseOn )
87   return 0;
88  
89  return spaceMouseOn; 
90 }
91
92 static int errorCallback( Display *display, XErrorEvent *Error )
93 {
94   char msg[ 128 ];
95   if ( Error->error_code != BadWindow ) {
96     XGetErrorText( display,Error->error_code,msg,sizeof( msg ) );
97     fprintf( stderr, "SpaceMouse reported error = %s. Exit ... \n", msg );
98   }
99   return 0;
100 }
101
102 /*!
103   Initialize by window
104 */
105 int SVTK_SpaceMouse::setWindow( Display *display, Window window )
106 {
107   XTextProperty winName;
108   XEvent xEvent;
109   Atom type;
110   int format;
111   unsigned long NItems, BytesReturn;
112   unsigned char *PropReturn;
113   Window root;
114   int result;
115   int (*errorHandler)(Display *,XErrorEvent *);
116
117   result = 1;
118   errorHandler = XSetErrorHandler( errorCallback );
119  
120   root = RootWindow( display, DefaultScreen(display) );
121
122   PropReturn = NULL;
123   XGetWindowProperty( display, root, XCommandEvent, 0,1, 0,
124                       AnyPropertyType, &type, &format, &NItems,
125                       &BytesReturn, &PropReturn );
126
127   win = InputFocus;
128   if ( PropReturn != NULL ) {
129     win = *(Window *) PropReturn;
130     XFree( PropReturn );
131   }
132   else
133     return result = 0;
134
135   if ( XGetWMName( display, win, &winName ) == 0 )
136     return result = 0;
137
138   if ( strcmp( (char *) "Magellan Window", (char *) winName.value) != 0 )
139     return result = 0;
140
141   xEvent.type = ClientMessage;
142   xEvent.xclient.format = 16;
143   xEvent.xclient.send_event = 0;
144   xEvent.xclient.display = display;
145   xEvent.xclient.window = win;
146   xEvent.xclient.message_type = XCommandEvent;
147   
148   xEvent.xclient.data.s[0] = (short) ((window>>16)&0x0000FFFF);
149   xEvent.xclient.data.s[1] = (short)  (window&0x0000FFFF);
150   xEvent.xclient.data.s[2] = 27695;
151
152   if ( XSendEvent( display, win, 0, 0x0000, &xEvent ) == 0 )
153     return result = 0;
154
155   XFlush( display );
156
157   XSetErrorHandler( errorHandler );
158   return result;
159 }
160
161 /*!
162   Close
163 */
164 int SVTK_SpaceMouse::close(Display *display)
165 {
166   initialize( display, (Window)InputFocus );
167   spaceMouseOn = 0;
168   
169   return 1;
170 }
171
172 /*!
173   Custom event handler
174 */
175 int SVTK_SpaceMouse::translateEvent( Display* display, XEvent* xEvent, MoveEvent* spaceMouseEvent,
176                     double scale, double rScale )
177 {
178   if ( !spaceMouseOn )
179     return 0;
180
181   if ( xEvent->type == ClientMessage ) {
182     if ( xEvent->xclient.message_type == XMotionEvent ) {
183       spaceMouseEvent->type = SpaceMouseMove;
184       spaceMouseEvent->data[ x ] =
185         xEvent->xclient.data.s[2] * scale;
186       spaceMouseEvent->data[ y ] =
187         xEvent->xclient.data.s[3] * scale;
188       spaceMouseEvent->data[ z ] =
189         xEvent->xclient.data.s[4] * scale;
190       spaceMouseEvent->data[ a ] =
191         xEvent->xclient.data.s[5] * rScale;
192       spaceMouseEvent->data[ b ] =
193         xEvent->xclient.data.s[6] * rScale;
194       spaceMouseEvent->data[ c ] =
195         xEvent->xclient.data.s[7] * rScale;
196       spaceMouseEvent->period = xEvent->xclient.data.s[8];
197       return 1;
198     }
199     else if ( xEvent->xclient.message_type == XButtonPressEvent ) {
200       spaceMouseEvent->type = SpaceButtonPress;
201       spaceMouseEvent->button = xEvent->xclient.data.s[2];
202       return 2;
203     }
204     else if ( xEvent->xclient.message_type == XButtonReleaseEvent ) {
205       spaceMouseEvent->type = SpaceButtonRelease;
206       spaceMouseEvent->button = xEvent->xclient.data.s[2];
207       return 3;
208     }
209   }
210   return (!display);
211 }
212
213 #endif