1 // Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // SALOME VTKViewer : build VTK viewer into Salome desktop
24 // File : SVTK_SpaceMouse.cxx
25 // Author : Alexander SLADKOV
35 #include <X11/Xutil.h>
36 #include <X11/Xatom.h>
37 #include <X11/keysym.h>
38 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
45 #include "SVTK_SpaceMouse.h"
47 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
48 SVTK_SpaceMouseX* SVTK_SpaceMouseX::myInstance = 0;
50 SVTK_SpaceMouseXCB* SVTK_SpaceMouseXCB::myInstance = 0;
56 SVTK_SpaceMouse::SVTK_SpaceMouse()
60 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
64 SVTK_SpaceMouseX::SVTK_SpaceMouseX()
73 \return shared instance of object (creates if there is no one)
75 SVTK_SpaceMouseX* SVTK_SpaceMouseX::getInstance()
78 myInstance = new SVTK_SpaceMouseX();
84 static int errorCallback( Display *display, XErrorEvent *Error )
87 if ( Error->error_code != BadWindow ) {
88 XGetErrorText( display,Error->error_code,msg,sizeof( msg ) );
89 fprintf( stderr, "SpaceMouse reported error = %s. Exit ... \n", msg );
97 int SVTK_SpaceMouseX::initialize( Display *display, Window window )
99 XMotionEvent = XInternAtom( display, "MotionEvent", 1 );
100 XButtonPressEvent = XInternAtom( display, "ButtonPressEvent", 1 );
101 XButtonReleaseEvent = XInternAtom( display, "ButtonReleaseEvent", 1 );
102 XCommandEvent = XInternAtom( display, "CommandEvent", 1 );
104 spaceMouseOn = (XMotionEvent != 0) &&
105 (XButtonPressEvent != 0) &&
106 (XButtonReleaseEvent != 0) &&
107 (XCommandEvent != 0);
111 spaceMouseOn = setWindow( display, window );
121 int SVTK_SpaceMouseX::setWindow( Display *display, Window window )
123 XTextProperty winName;
127 unsigned long NItems, BytesReturn;
128 unsigned char *PropReturn;
130 int (*errorHandler)(Display *,XErrorEvent *);
132 errorHandler = XSetErrorHandler( errorCallback );
134 root = RootWindow( display, DefaultScreen(display) );
137 XGetWindowProperty( display, root, XCommandEvent, 0,1, 0,
138 AnyPropertyType, &type, &format, &NItems,
139 &BytesReturn, &PropReturn );
142 if ( PropReturn != NULL ) {
143 win = *(Window *) PropReturn;
149 if ( XGetWMName( display, win, &winName ) == 0 )
152 if ( strcmp( (char *) "Magellan Window", (char *) winName.value) != 0 )
155 xEvent.type = ClientMessage;
156 xEvent.xclient.format = 16;
157 xEvent.xclient.send_event = 0;
158 xEvent.xclient.display = display;
159 xEvent.xclient.window = win;
160 xEvent.xclient.message_type = XCommandEvent;
162 xEvent.xclient.data.s[0] = (short) ((window>>16)&0x0000FFFF);
163 xEvent.xclient.data.s[1] = (short) (window&0x0000FFFF);
164 xEvent.xclient.data.s[2] = 27695;
166 if ( XSendEvent( display, win, 0, 0x0000, &xEvent ) == 0 )
171 XSetErrorHandler( errorHandler );
178 int SVTK_SpaceMouseX::close(Display *display)
180 initialize( display, (Window)InputFocus );
189 int SVTK_SpaceMouseX::translateEvent( Display* display, XEvent* xEvent, MoveEvent* spaceMouseEvent,
190 double scale, double rScale )
195 if ( xEvent->type == ClientMessage ) {
196 if ( xEvent->xclient.message_type == XMotionEvent ) {
197 spaceMouseEvent->type = SpaceMouseMove;
198 spaceMouseEvent->data[ x ] =
199 xEvent->xclient.data.s[2] * scale;
200 spaceMouseEvent->data[ y ] =
201 xEvent->xclient.data.s[3] * scale;
202 spaceMouseEvent->data[ z ] =
203 xEvent->xclient.data.s[4] * scale;
204 spaceMouseEvent->data[ a ] =
205 xEvent->xclient.data.s[5] * rScale;
206 spaceMouseEvent->data[ b ] =
207 xEvent->xclient.data.s[6] * rScale;
208 spaceMouseEvent->data[ c ] =
209 xEvent->xclient.data.s[7] * rScale;
210 spaceMouseEvent->period = xEvent->xclient.data.s[8];
213 else if ( xEvent->xclient.message_type == XButtonPressEvent ) {
214 spaceMouseEvent->type = SpaceButtonPress;
215 spaceMouseEvent->button = xEvent->xclient.data.s[2];
218 else if ( xEvent->xclient.message_type == XButtonReleaseEvent ) {
219 spaceMouseEvent->type = SpaceButtonRelease;
220 spaceMouseEvent->button = xEvent->xclient.data.s[2];
232 SVTK_SpaceMouseXCB::SVTK_SpaceMouseXCB()
241 \return shared instance of object (creates if there is no one)
243 SVTK_SpaceMouseXCB* SVTK_SpaceMouseXCB::getInstance()
246 myInstance = new SVTK_SpaceMouseXCB();
253 int SVTK_SpaceMouseXCB::initialize( xcb_connection_t *connection, xcb_window_t window )
256 xcb_intern_atom_cookie_t cookie = xcb_intern_atom (connection, 0, strlen("XCB_MOTION_NOTIFY"), "XCB_MOTION_NOTIFY" );
258 xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply ( connection, cookie, NULL );
259 XCBMotionEvent = reply->atom;
260 cookie = xcb_intern_atom (connection, 0, strlen("XCB_BUTTON_PRESS"), "XCB_BUTTON_PRESS" );
261 reply = xcb_intern_atom_reply ( connection, cookie, NULL );
262 XCBButtonPressEvent = reply->atom;
263 cookie = xcb_intern_atom (connection, 0, strlen("XCB_BUTTON_RELEASE"), "XCB_BUTTON_RELEASE" );
264 reply = xcb_intern_atom_reply ( connection, cookie, NULL );
265 XCBButtonReleaseEvent = reply->atom;
269 spaceMouseOn = (XCBMotionEvent != 0) &&
270 (XCBButtonPressEvent != 0) &&
271 (XCBButtonReleaseEvent != 0);
275 spaceMouseOn = setWindow( connection, window );
285 int SVTK_SpaceMouseXCB::setWindow( xcb_connection_t *connection, xcb_window_t window )
287 xcb_client_message_event_t xcbEvent;
288 xcb_window_t root_window;
289 xcb_screen_t* screen;
290 xcb_generic_error_t* error;
291 xcb_void_cookie_t cookie;
293 screen = xcb_setup_roots_iterator ( xcb_get_setup ( connection ) ).data;
297 root_window = screen->root;
299 xcb_get_property_cookie_t prop_cookie;
300 xcb_get_property_reply_t* prop_reply;
301 prop_cookie = xcb_get_property (connection, 0, root_window, XCB_ATOM_WM_NAME,
302 XCB_ATOM_STRING, 0, 0);
306 if (( prop_reply = xcb_get_property_reply ( connection, prop_cookie, NULL ) ))
308 int len = xcb_get_property_value_length( prop_reply );
316 if ( strcmp( (char *) "Magellan Window", (char *) xcb_get_property_value( prop_reply ) ) != 0 )
319 win = * ( xcb_window_t * ) xcb_get_property_value( prop_reply );
324 xcbEvent.response_type = XCB_CLIENT_MESSAGE;
325 xcbEvent.format = 16;
326 xcbEvent.sequence = 0;
327 xcbEvent.window = win;
329 xcbEvent.data.data16[0] = (short) ((window>>16)&0x0000FFFF);
330 xcbEvent.data.data16[1] = (short) (window&0x0000FFFF);
331 xcbEvent.data.data16[2] = 27695;
333 cookie = xcb_send_event( connection, 0, win, 0x0000, (const char *)&xcbEvent );
336 if (( error = xcb_request_check( connection, cookie )))
338 if ( error->error_code != BadWindow )
340 fprintf ( stderr, "SpaceMouse reported error = %d. Exit ... \n", error->error_code);
345 xcb_flush(connection);
353 int SVTK_SpaceMouseXCB::close(xcb_connection_t *connection)
355 initialize( connection, (xcb_window_t)InputFocus );
364 int SVTK_SpaceMouseXCB::translateEvent( xcb_connection_t* connection, xcb_client_message_event_t* xcbEvent, MoveEvent* spaceMouseEvent,
365 double scale, double rScale )
370 if ( xcbEvent->response_type == XCB_CLIENT_MESSAGE ) {
371 if ( xcbEvent->type == XCBMotionEvent ) {
372 spaceMouseEvent->type = SpaceMouseMove;
373 spaceMouseEvent->data[ x ] =
374 xcbEvent->data.data16[2] * scale;
375 spaceMouseEvent->data[ y ] =
376 xcbEvent->data.data16[3] * scale;
377 spaceMouseEvent->data[ z ] =
378 xcbEvent->data.data16[4] * scale;
379 spaceMouseEvent->data[ a ] =
380 xcbEvent->data.data16[5] * rScale;
381 spaceMouseEvent->data[ b ] =
382 xcbEvent->data.data16[6] * rScale;
383 spaceMouseEvent->data[ c ] =
384 xcbEvent->data.data16[7] * rScale;
385 spaceMouseEvent->period = xcbEvent->data.data16[8];
388 else if ( xcbEvent->type == XCBButtonPressEvent ) {
389 spaceMouseEvent->type = SpaceButtonPress;
390 spaceMouseEvent->button = xcbEvent->data.data16[2];
393 else if ( xcbEvent->type == XCBButtonReleaseEvent ) {
394 spaceMouseEvent->type = SpaceButtonRelease;
395 spaceMouseEvent->button = xcbEvent->data.data16[2];
399 return (!connection);