Salome HOME
Join modifications from branch BR_DEBUG_3_2_0b1
[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 #include <X11/X.h>
34 #include <X11/Xlib.h>
35 #include <X11/Xutil.h>
36 #include <X11/Xatom.h>
37 #include <X11/keysym.h>
38
39 #include "SVTK_SpaceMouse.h"
40
41 SVTK_SpaceMouse* SVTK_SpaceMouse::myInstance = 0;
42
43 /*!
44   \return shared instance of object (creates if there is no one)
45 */
46 SVTK_SpaceMouse* SVTK_SpaceMouse::getInstance()
47 {
48   if ( !myInstance )
49     myInstance = new SVTK_SpaceMouse();
50   return myInstance;
51 }
52
53 /*!
54   Constructor
55 */
56 SVTK_SpaceMouse::SVTK_SpaceMouse()
57 {
58   win = InputFocus;
59   spaceMouseOn = 0;
60 }
61
62 /*!
63   Initialization
64 */
65 int SVTK_SpaceMouse::initialize( Display *display, Window window )
66 {
67  XMotionEvent        = XInternAtom( display, "MotionEvent",        1 );
68  XButtonPressEvent   = XInternAtom( display, "ButtonPressEvent",   1 );
69  XButtonReleaseEvent = XInternAtom( display, "ButtonReleaseEvent", 1 );
70  XCommandEvent       = XInternAtom( display, "CommandEvent",       1 );
71
72  spaceMouseOn = (XMotionEvent        != 0) && 
73                 (XButtonPressEvent   != 0) && 
74                 (XButtonReleaseEvent != 0) && 
75                 (XCommandEvent       != 0);
76  if ( !spaceMouseOn )
77   return 0;
78
79  spaceMouseOn = setWindow( display, window );
80  if ( !spaceMouseOn )
81   return 0;
82  
83  return spaceMouseOn; 
84 }
85
86 static int errorCallback( Display *display, XErrorEvent *Error )
87 {
88   char msg[ 128 ];
89   if ( Error->error_code != BadWindow ) {
90     XGetErrorText( display,Error->error_code,msg,sizeof( msg ) );
91     fprintf( stderr, "SpaceMouse reported error = %s. Exit ... \n", msg );
92   }
93   return 0;
94 }
95
96 /*!
97   Initialize by window
98 */
99 int SVTK_SpaceMouse::setWindow( Display *display, Window window )
100 {
101   XTextProperty winName;
102   XEvent xEvent;
103   Atom type;
104   int format;
105   unsigned long NItems, BytesReturn;
106   unsigned char *PropReturn;
107   Window root;
108   int result;
109   int (*errorHandler)(Display *,XErrorEvent *);
110
111   result = 1;
112   errorHandler = XSetErrorHandler( errorCallback );
113  
114   root = RootWindow( display, DefaultScreen(display) );
115
116   PropReturn = NULL;
117   XGetWindowProperty( display, root, XCommandEvent, 0,1, 0,
118                       AnyPropertyType, &type, &format, &NItems,
119                       &BytesReturn, &PropReturn );
120
121   win = InputFocus;
122   if ( PropReturn != NULL ) {
123     win = *(Window *) PropReturn;
124     XFree( PropReturn );
125   }
126   else
127     return result = 0;
128
129   if ( XGetWMName( display, win, &winName ) == 0 )
130     return result = 0;
131
132   if ( strcmp( (char *) "Magellan Window", (char *) winName.value) != 0 )
133     return result = 0;
134
135   xEvent.type = ClientMessage;
136   xEvent.xclient.format = 16;
137   xEvent.xclient.send_event = 0;
138   xEvent.xclient.display = display;
139   xEvent.xclient.window = win;
140   xEvent.xclient.message_type = XCommandEvent;
141   
142   xEvent.xclient.data.s[0] = (short) ((window>>16)&0x0000FFFF);
143   xEvent.xclient.data.s[1] = (short)  (window&0x0000FFFF);
144   xEvent.xclient.data.s[2] = 27695;
145
146   if ( XSendEvent( display, win, 0, 0x0000, &xEvent ) == 0 )
147     return result = 0;
148
149   XFlush( display );
150
151   XSetErrorHandler( errorHandler );
152   return result;
153 }
154
155 /*!
156   Close
157 */
158 int SVTK_SpaceMouse::close(Display *display)
159 {
160   initialize( display, (Window)InputFocus );
161   spaceMouseOn = 0;
162   
163   return 1;
164 }
165
166 /*!
167   Custom event handler
168 */
169 int SVTK_SpaceMouse::translateEvent( Display* display, XEvent* xEvent, MoveEvent* spaceMouseEvent,
170                     double scale, double rScale )
171 {
172   if ( !spaceMouseOn )
173     return 0;
174
175   if ( xEvent->type == ClientMessage ) {
176     if ( xEvent->xclient.message_type == XMotionEvent ) {
177       spaceMouseEvent->type = SpaceMouseMove;
178       spaceMouseEvent->data[ x ] =
179         xEvent->xclient.data.s[2] * scale;
180       spaceMouseEvent->data[ y ] =
181         xEvent->xclient.data.s[3] * scale;
182       spaceMouseEvent->data[ z ] =
183         xEvent->xclient.data.s[4] * scale;
184       spaceMouseEvent->data[ a ] =
185         xEvent->xclient.data.s[5] * rScale;
186       spaceMouseEvent->data[ b ] =
187         xEvent->xclient.data.s[6] * rScale;
188       spaceMouseEvent->data[ c ] =
189         xEvent->xclient.data.s[7] * rScale;
190       spaceMouseEvent->period = xEvent->xclient.data.s[8];
191       return 1;
192     }
193     else if ( xEvent->xclient.message_type == XButtonPressEvent ) {
194       spaceMouseEvent->type = SpaceButtonPress;
195       spaceMouseEvent->button = xEvent->xclient.data.s[2];
196       return 2;
197     }
198     else if ( xEvent->xclient.message_type == XButtonReleaseEvent ) {
199       spaceMouseEvent->type = SpaceButtonRelease;
200       spaceMouseEvent->button = xEvent->xclient.data.s[2];
201       return 3;
202     }
203   }
204   return (!display);
205 }
206