Salome HOME
459eb6bcd4912d339d8870147c1d0245e1334830
[modules/gui.git] / src / SVTK / SVTK_SpaceMouse.cxx
1 // Copyright (C) 2007-2023  CEA, EDF, 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 #include <QtGlobal>
32
33 #if !defined WIN32 && !defined __APPLE__
34 #include <X11/X.h>
35 #include <X11/Xutil.h>
36 #include <X11/Xatom.h>
37 #include <X11/keysym.h>
38 #include <xcb/xcb.h>
39 #endif
40
41 #include "SVTK_SpaceMouse.h"
42
43 SVTK_SpaceMouseXCB* SVTK_SpaceMouseXCB::myInstance = 0;
44
45 /*!
46   Constructor
47 */
48 SVTK_SpaceMouse::SVTK_SpaceMouse()
49 {
50   spaceMouseOn = 0;
51 }
52
53 /*!
54   Constructor
55 */
56 SVTK_SpaceMouseXCB::SVTK_SpaceMouseXCB()
57 : SVTK_SpaceMouse()
58 {
59 #if !defined WIN32 && !defined __APPLE__
60   win = InputFocus;
61 #endif
62 }
63
64 /*!
65   \return shared instance of object (creates if there is no one)
66 */
67 SVTK_SpaceMouseXCB* SVTK_SpaceMouseXCB::getInstance()
68 {
69   if ( !myInstance )
70     myInstance = new SVTK_SpaceMouseXCB();
71   return myInstance;
72 }
73 /*!
74   Initialization
75 */
76 #if !defined WIN32 && !defined __APPLE__
77 int SVTK_SpaceMouseXCB::initialize( xcb_connection_t *connection, xcb_window_t window )
78 {
79   // make request
80   xcb_intern_atom_cookie_t cookie = xcb_intern_atom (connection, 0, strlen("XCB_MOTION_NOTIFY"), "XCB_MOTION_NOTIFY" );
81   // get response
82   xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply ( connection, cookie, NULL );
83   XCBMotionEvent = reply->atom;
84   cookie = xcb_intern_atom (connection, 0, strlen("XCB_BUTTON_PRESS"), "XCB_BUTTON_PRESS" );
85   reply = xcb_intern_atom_reply ( connection, cookie, NULL );
86   XCBButtonPressEvent = reply->atom;
87   cookie = xcb_intern_atom (connection, 0, strlen("XCB_BUTTON_RELEASE"), "XCB_BUTTON_RELEASE" );
88   reply = xcb_intern_atom_reply ( connection, cookie, NULL );
89   XCBButtonReleaseEvent = reply->atom;
90
91   free (reply);
92
93   spaceMouseOn = (XCBMotionEvent        != 0) &&
94                  (XCBButtonPressEvent   != 0) &&
95                  (XCBButtonReleaseEvent != 0);
96   if ( !spaceMouseOn )
97     return 0;
98
99   spaceMouseOn = setWindow( connection, window );
100   if ( !spaceMouseOn )
101     return 0;
102
103   return spaceMouseOn;
104 }
105
106 /*!
107   Initialize by window
108 */
109 int SVTK_SpaceMouseXCB::setWindow( xcb_connection_t *connection, xcb_window_t window )
110 {
111   xcb_client_message_event_t xcbEvent;
112   xcb_window_t root_window = 0; // todo: initial value (if screen is null, see below)
113   xcb_screen_t* screen;
114   xcb_generic_error_t* error;
115   xcb_void_cookie_t cookie;
116
117   screen = xcb_setup_roots_iterator ( xcb_get_setup ( connection ) ).data;
118
119   /* root window */
120   if ( screen )
121     root_window = screen->root;
122
123   xcb_get_property_cookie_t prop_cookie;
124   xcb_get_property_reply_t* prop_reply;
125   prop_cookie = xcb_get_property (connection, 0, root_window, XCB_ATOM_WM_NAME,
126                                   XCB_ATOM_STRING, 0, 0);
127
128   win = InputFocus;
129
130   if (( prop_reply = xcb_get_property_reply ( connection, prop_cookie, NULL ) ))
131   {
132     int len = xcb_get_property_value_length( prop_reply );
133
134     if ( len == 0 )
135     {
136       free(prop_reply);
137       return 0;
138     }
139
140     if ( strcmp( (char *) "Magellan Window", (char *) xcb_get_property_value( prop_reply ) ) != 0 )
141       return 0;
142
143     win = * ( xcb_window_t * ) xcb_get_property_value( prop_reply );
144   }
145
146   free(prop_reply);
147
148   xcbEvent.response_type = XCB_CLIENT_MESSAGE;
149   xcbEvent.format = 16;
150   xcbEvent.sequence = 0;
151   xcbEvent.window = win;
152
153   xcbEvent.data.data16[0] = (short) ((window>>16)&0x0000FFFF);
154   xcbEvent.data.data16[1] = (short)  (window&0x0000FFFF);
155   xcbEvent.data.data16[2] = 27695;
156
157   cookie = xcb_send_event( connection, 0, win, 0x0000, (const char *)&xcbEvent );
158
159
160   if (( error = xcb_request_check( connection, cookie )))
161   {
162     if ( error->error_code != BadWindow )
163     {
164       fprintf ( stderr, "SpaceMouse reported error = %d. Exit ... \n", error->error_code);
165     }
166     return 0;
167   }
168
169   xcb_flush(connection);
170
171   return 1;
172 }
173
174 /*!
175   Close
176 */
177 int SVTK_SpaceMouseXCB::close(xcb_connection_t *connection)
178 {
179   initialize( connection, (xcb_window_t)InputFocus );
180   spaceMouseOn = 0;
181
182   return 1;
183 }
184
185 /*!
186   Custom event handler
187 */
188 int SVTK_SpaceMouseXCB::translateEvent( xcb_connection_t* connection, xcb_client_message_event_t* xcbEvent, MoveEvent* spaceMouseEvent,
189                     double scale, double rScale )
190 {
191   if ( !spaceMouseOn )
192     return 0;
193
194   if ( xcbEvent->response_type == XCB_CLIENT_MESSAGE ) {
195     if ( xcbEvent->type == XCBMotionEvent ) {
196       spaceMouseEvent->type = SpaceMouseMove;
197       spaceMouseEvent->data[ x ] =
198         xcbEvent->data.data16[2] * scale;
199       spaceMouseEvent->data[ y ] =
200         xcbEvent->data.data16[3] * scale;
201       spaceMouseEvent->data[ z ] =
202         xcbEvent->data.data16[4] * scale;
203       spaceMouseEvent->data[ a ] =
204         xcbEvent->data.data16[5] * rScale;
205       spaceMouseEvent->data[ b ] =
206         xcbEvent->data.data16[6] * rScale;
207       spaceMouseEvent->data[ c ] =
208         xcbEvent->data.data16[7] * rScale;
209       spaceMouseEvent->period = xcbEvent->data.data16[8];
210       return 1;
211     }
212     else if ( xcbEvent->type == XCBButtonPressEvent ) {
213       spaceMouseEvent->type = SpaceButtonPress;
214       spaceMouseEvent->button = xcbEvent->data.data16[2];
215       return 2;
216     }
217     else if ( xcbEvent->type == XCBButtonReleaseEvent ) {
218       spaceMouseEvent->type = SpaceButtonRelease;
219       spaceMouseEvent->button = xcbEvent->data.data16[2];
220       return 3;
221     }
222   }
223   return (!connection);
224 }
225 #endif