Salome HOME
a2ace80c4869a4b49126991a87bacf7140e0c809
[modules/gui.git] / src / SVTK / SVTK_SpaceMouse.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  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, or (at your option) any later version.
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 //  SALOME VTKViewer : build VTK viewer into Salome desktop
24 //  File   : SVTK_SpaceMouse.cxx
25 //  Author : Alexander SLADKOV
26
27 #include <string.h>
28 #include <math.h>
29 #include <stdio.h>
30
31 #ifndef WIN32
32 #include <X11/X.h>
33 #include <X11/Xlib.h>
34 #include <X11/Xutil.h>
35 #include <X11/Xatom.h>
36 #include <X11/keysym.h>
37 #endif
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 #ifndef WIN32
59   win = InputFocus;
60 #endif
61   spaceMouseOn = 0;
62 }
63
64 #ifndef WIN32
65
66 /*!
67   Initialization
68 */
69 int SVTK_SpaceMouse::initialize( Display *display, Window window )
70 {
71  XMotionEvent        = XInternAtom( display, "MotionEvent",        1 );
72  XButtonPressEvent   = XInternAtom( display, "ButtonPressEvent",   1 );
73  XButtonReleaseEvent = XInternAtom( display, "ButtonReleaseEvent", 1 );
74  XCommandEvent       = XInternAtom( display, "CommandEvent",       1 );
75
76  spaceMouseOn = (XMotionEvent        != 0) && 
77                 (XButtonPressEvent   != 0) && 
78                 (XButtonReleaseEvent != 0) && 
79                 (XCommandEvent       != 0);
80  if ( !spaceMouseOn )
81   return 0;
82
83  spaceMouseOn = setWindow( display, window );
84  if ( !spaceMouseOn )
85   return 0;
86  
87  return spaceMouseOn; 
88 }
89
90 static int errorCallback( Display *display, XErrorEvent *Error )
91 {
92   char msg[ 128 ];
93   if ( Error->error_code != BadWindow ) {
94     XGetErrorText( display,Error->error_code,msg,sizeof( msg ) );
95     fprintf( stderr, "SpaceMouse reported error = %s. Exit ... \n", msg );
96   }
97   return 0;
98 }
99
100 /*!
101   Initialize by window
102 */
103 int SVTK_SpaceMouse::setWindow( Display *display, Window window )
104 {
105   XTextProperty winName;
106   XEvent xEvent;
107   Atom type;
108   int format;
109   unsigned long NItems, BytesReturn;
110   unsigned char *PropReturn;
111   Window root;
112   int result;
113   int (*errorHandler)(Display *,XErrorEvent *);
114
115   result = 1;
116   errorHandler = XSetErrorHandler( errorCallback );
117  
118   root = RootWindow( display, DefaultScreen(display) );
119
120   PropReturn = NULL;
121   XGetWindowProperty( display, root, XCommandEvent, 0,1, 0,
122                       AnyPropertyType, &type, &format, &NItems,
123                       &BytesReturn, &PropReturn );
124
125   win = InputFocus;
126   if ( PropReturn != NULL ) {
127     win = *(Window *) PropReturn;
128     XFree( PropReturn );
129   }
130   else
131     return result = 0;
132
133   if ( XGetWMName( display, win, &winName ) == 0 )
134     return result = 0;
135
136   if ( strcmp( (char *) "Magellan Window", (char *) winName.value) != 0 )
137     return result = 0;
138
139   xEvent.type = ClientMessage;
140   xEvent.xclient.format = 16;
141   xEvent.xclient.send_event = 0;
142   xEvent.xclient.display = display;
143   xEvent.xclient.window = win;
144   xEvent.xclient.message_type = XCommandEvent;
145   
146   xEvent.xclient.data.s[0] = (short) ((window>>16)&0x0000FFFF);
147   xEvent.xclient.data.s[1] = (short)  (window&0x0000FFFF);
148   xEvent.xclient.data.s[2] = 27695;
149
150   if ( XSendEvent( display, win, 0, 0x0000, &xEvent ) == 0 )
151     return result = 0;
152
153   XFlush( display );
154
155   XSetErrorHandler( errorHandler );
156   return result;
157 }
158
159 /*!
160   Close
161 */
162 int SVTK_SpaceMouse::close(Display *display)
163 {
164   initialize( display, (Window)InputFocus );
165   spaceMouseOn = 0;
166   
167   return 1;
168 }
169
170 /*!
171   Custom event handler
172 */
173 int SVTK_SpaceMouse::translateEvent( Display* display, XEvent* xEvent, MoveEvent* spaceMouseEvent,
174                     double scale, double rScale )
175 {
176   if ( !spaceMouseOn )
177     return 0;
178
179   if ( xEvent->type == ClientMessage ) {
180     if ( xEvent->xclient.message_type == XMotionEvent ) {
181       spaceMouseEvent->type = SpaceMouseMove;
182       spaceMouseEvent->data[ x ] =
183         xEvent->xclient.data.s[2] * scale;
184       spaceMouseEvent->data[ y ] =
185         xEvent->xclient.data.s[3] * scale;
186       spaceMouseEvent->data[ z ] =
187         xEvent->xclient.data.s[4] * scale;
188       spaceMouseEvent->data[ a ] =
189         xEvent->xclient.data.s[5] * rScale;
190       spaceMouseEvent->data[ b ] =
191         xEvent->xclient.data.s[6] * rScale;
192       spaceMouseEvent->data[ c ] =
193         xEvent->xclient.data.s[7] * rScale;
194       spaceMouseEvent->period = xEvent->xclient.data.s[8];
195       return 1;
196     }
197     else if ( xEvent->xclient.message_type == XButtonPressEvent ) {
198       spaceMouseEvent->type = SpaceButtonPress;
199       spaceMouseEvent->button = xEvent->xclient.data.s[2];
200       return 2;
201     }
202     else if ( xEvent->xclient.message_type == XButtonReleaseEvent ) {
203       spaceMouseEvent->type = SpaceButtonRelease;
204       spaceMouseEvent->button = xEvent->xclient.data.s[2];
205       return 3;
206     }
207   }
208   return (!display);
209 }
210
211 #endif