Hi there,
I've written a class I called SpaceTravelerCtrlDevice (I've got a SpaceTraveler ...) which is supposed to wrap the functionalities of the xdrvlib and is based on the xapp.c from the 3dconnexion sdk. Its supposed to use the xdrvlib without showing any window. (Because I'm controlling a robot with it and not some graphical application...).
This class has the functions
SpaceTravelerCtrlDevice::startX()
-> Open connection to X server
-> Create a simple window (XCreateSimpleWindow)
-> Map this window (I also tried to leave this out...)
-> Move the window outside of the visible region of my screen (so a user won't see a window popping up when calling startX() )
-> Call MagellanInit
-> Withdraw the window with XWithdrawWindow. (Because I don't want this window to show as I'm using Qt for the interface to my application... I want to be able to use my spacemouse without Qt though, as nextEvent() must be called from a thread running much faster than any Qt GUI thread...)
SpaceTravelerCtrlDevice::nextEvent() (continuousely called during an own thread)
-> get the next client message, read motion or button data and pass it on to the application.
SpaceTravelerCtrlDevice::stopX()
-> shutdown and close everything
This class then runs in an own thread (boost threads) and continuousely calls XNextEvent (or XCheckTypedWindowEvent) to get the next spacemouse event from the X server. I've also written a testprogram where I test the functionality of this class (prints motion and button events to a shell).
This is where my problem starts... The test program sometimes works perfectly returning all events from my spacemouse and sometimes does not return anything at all (although my thread continuousely keeps flushing and checking for new events...)
startX() , stopX() and nextEvent() basically hold the same code as xapp.c except that it does not create a graphical content and withdraws the X-window before it starts the event querying thread.
To track my problem I used XEventsQueued in its different modes to check how many events are allready in the event queue. In cases where my test program does not return any events (even though I'm moving the spacemouse) the event queue remains empty (XEventsQueued returns zero in any mode). The test programs from the sdk xvalue and xcube always run perfectly though.
I was wondering if anyone ever had a similar problem or situation at hand or could give me a hint where this behavior might come from. (I'm out of ideas at the moment...)
Some system specs:
"uname -s -r -m":
Linux 2.6.22.2-custom i686 (Debian) -> custom because we had to recompile the kernel with the 1394 modules included...
"g++ -v":
Target: i486-linux-gnu
Configured with: ...
Thread model: posix
gcc version 4.2.3 20071014 (prerelease) (Debian 4.2.2-3)
"/etc/3DxWare/daemon/3dxsrv -v":
3DxWareUNIX = V1.2.9, ID 3149
Thanks in advance for any help,
Chris
How to use the xdrvlib without showing any window
Moderator: Moderators
Hi Chris,
I must admit I've never tried to use an unmapped window for this, but this may work as well, since the window as a receiver for the XClientMessages still exists.
If you close the window you have announced to the driver via MagellanInit() or MagellanSetWindow() then the driver loses its destination and will send its data to the window that the focus is on. This is also why the XEventsQueued() doesn't tell you anything after the call to stopX(), I think.
Our driver uses XClientMessages to send the device data to applications and therefore relies on X11. You'll have to have at least this single XWindow that acts for you as receiver!
If you want to work without X11 at all I'm sorry to tell you, but I don't have a solution for you at the moment.
Regards,
Christian
3Dconnexion
Does stopX() just unmap or close the window?startX() , stopX() and nextEvent() basically hold the same code as xapp.c except that it does not create a graphical content and withdraws the X-window before it starts the event querying thread.
I must admit I've never tried to use an unmapped window for this, but this may work as well, since the window as a receiver for the XClientMessages still exists.
If you close the window you have announced to the driver via MagellanInit() or MagellanSetWindow() then the driver loses its destination and will send its data to the window that the focus is on. This is also why the XEventsQueued() doesn't tell you anything after the call to stopX(), I think.
Our driver uses XClientMessages to send the device data to applications and therefore relies on X11. You'll have to have at least this single XWindow that acts for you as receiver!
If you want to work without X11 at all I'm sorry to tell you, but I don't have a solution for you at the moment.
Regards,
Christian
3Dconnexion
Hi Christian,
When starting the event gathering thread of my SpaceTravelerCtrlDevice, startX() is called. Then nextEvent() will be continuousely invoked until someone calls stopX() which destroys the window and closes the connection to the X server...
I've now tried several versions with mappend and unmapped windows and both seem to work out. The only problem I have is that both sometimes work and sometimes don't...
To be honest I'm starting to think that there might be something wrong with my X server although the demo programs xcube and xvalue always work (which suggests that there is something wrong with my initializiation code).
If added my initialization code bellow. The code within nextEvent() looks pretty much the same as within xapp.c form the sdk, except that I pass the events on with a boost signal. If you find something fishy within startX() it would be great if you could point me to it. Thanks a lot for your reply.
Regards,
Chris
#############################
SpaceTravelerCtrlDevice::startThread()
{
this->startX();
// After calling BoostThread::startThread() SpaceTravelerCtrlDevice::nextEvent() will be continuosely called ...
BoostThread::startThread(); // SpaceTravelerCtrlDevice inherits from my BoosThread class (has been tested and works...)
}
#############################
SpaceTravelerCtrlDevice::startX()
{
if( _xdisplay != NULL )
{
ERR_MSG( "Cannot open connection to X server! Connection already established!",
ERR_DISPLAY_DURATION );
return;
}
Window root; // the root xwindow
int32_t screennumber;
int32_t width;
int32_t height;
_xdisplay = XOpenDisplay( NULL );
if( _xdisplay == NULL )
{
ERR_MSG( "Cannot open display! Exiting...", ERR_DISPLAY_DURATION);
return;
}
root = DefaultRootWindow( _xdisplay ); // returns the root window of the default screen
screennumber = DefaultScreen( _xdisplay ); // returns the screen id -> localhost:number.screen_number ex. ":0"
width = 1;
height = 1;
_xwindow = XCreateSimpleWindow( _xdisplay,
root,
0,0,
width, height,
20,
BlackPixel(_xdisplay, screennumber ),
WhitePixel(_xdisplay, screennumber ) );
char* windName = "Magellan 3D Controller" ;
XTextProperty windowName;
XStringListToTextProperty( &windName, 1, &windowName );
XSizeHints* sizehints = XAllocSizeHints();
XWMHints* wmhints = XAllocWMHints();
XClassHint* classhints = XAllocClassHint();
if( (sizehints == NULL) || (wmhints == NULL) || (classhints == NULL) )
{
ERR_MSG( "Cannot allocate memory! Exiting...", ERR_DISPLAY_DURATION );
return;
};
wmhints->initial_state = NormalState;
wmhints->input = TRUE;
wmhints->flags = StateHint | InputHint;
classhints->res_name = "Magellan 3D Controller";
classhints->res_class = "BasicWindow" ;
XSetWMProperties( _xdisplay,
_xwindow,
&windowName,
NULL,
NULL, 0,
sizehints,
wmhints,
classhints );
width = XDisplayWidth( _xdisplay, XDefaultScreen( _xdisplay ) );
height = XDisplayHeight( _xdisplay, XDefaultScreen( _xdisplay ) );
XMapWindow( _xdisplay, _xwindow );
// move it out of the way such that it won't pop up if you start the application...
XMoveWindow( _xdisplay, _xwindow, width, height );
if( !MagellanInit( _xdisplay, _xwindow ) )
{
ERR_MSG( "No driver running. Exiting...", ERR_DISPLAY_DURATION );
exit(-1);
}
// hide the window but still receive XEvents
//XWithdrawWindow( _xdisplay, _xwindow, 0 );
//XUnmapWindow( _xdisplay, _xwindow ); // does not seem to influence the event gathering
}
When starting the event gathering thread of my SpaceTravelerCtrlDevice, startX() is called. Then nextEvent() will be continuousely invoked until someone calls stopX() which destroys the window and closes the connection to the X server...
I've now tried several versions with mappend and unmapped windows and both seem to work out. The only problem I have is that both sometimes work and sometimes don't...
To be honest I'm starting to think that there might be something wrong with my X server although the demo programs xcube and xvalue always work (which suggests that there is something wrong with my initializiation code).
If added my initialization code bellow. The code within nextEvent() looks pretty much the same as within xapp.c form the sdk, except that I pass the events on with a boost signal. If you find something fishy within startX() it would be great if you could point me to it. Thanks a lot for your reply.
Regards,
Chris
#############################
SpaceTravelerCtrlDevice::startThread()
{
this->startX();
// After calling BoostThread::startThread() SpaceTravelerCtrlDevice::nextEvent() will be continuosely called ...
BoostThread::startThread(); // SpaceTravelerCtrlDevice inherits from my BoosThread class (has been tested and works...)
}
#############################
SpaceTravelerCtrlDevice::startX()
{
if( _xdisplay != NULL )
{
ERR_MSG( "Cannot open connection to X server! Connection already established!",
ERR_DISPLAY_DURATION );
return;
}
Window root; // the root xwindow
int32_t screennumber;
int32_t width;
int32_t height;
_xdisplay = XOpenDisplay( NULL );
if( _xdisplay == NULL )
{
ERR_MSG( "Cannot open display! Exiting...", ERR_DISPLAY_DURATION);
return;
}
root = DefaultRootWindow( _xdisplay ); // returns the root window of the default screen
screennumber = DefaultScreen( _xdisplay ); // returns the screen id -> localhost:number.screen_number ex. ":0"
width = 1;
height = 1;
_xwindow = XCreateSimpleWindow( _xdisplay,
root,
0,0,
width, height,
20,
BlackPixel(_xdisplay, screennumber ),
WhitePixel(_xdisplay, screennumber ) );
char* windName = "Magellan 3D Controller" ;
XTextProperty windowName;
XStringListToTextProperty( &windName, 1, &windowName );
XSizeHints* sizehints = XAllocSizeHints();
XWMHints* wmhints = XAllocWMHints();
XClassHint* classhints = XAllocClassHint();
if( (sizehints == NULL) || (wmhints == NULL) || (classhints == NULL) )
{
ERR_MSG( "Cannot allocate memory! Exiting...", ERR_DISPLAY_DURATION );
return;
};
wmhints->initial_state = NormalState;
wmhints->input = TRUE;
wmhints->flags = StateHint | InputHint;
classhints->res_name = "Magellan 3D Controller";
classhints->res_class = "BasicWindow" ;
XSetWMProperties( _xdisplay,
_xwindow,
&windowName,
NULL,
NULL, 0,
sizehints,
wmhints,
classhints );
width = XDisplayWidth( _xdisplay, XDefaultScreen( _xdisplay ) );
height = XDisplayHeight( _xdisplay, XDefaultScreen( _xdisplay ) );
XMapWindow( _xdisplay, _xwindow );
// move it out of the way such that it won't pop up if you start the application...
XMoveWindow( _xdisplay, _xwindow, width, height );
if( !MagellanInit( _xdisplay, _xwindow ) )
{
ERR_MSG( "No driver running. Exiting...", ERR_DISPLAY_DURATION );
exit(-1);
}
// hide the window but still receive XEvents
//XWithdrawWindow( _xdisplay, _xwindow, 0 );
//XUnmapWindow( _xdisplay, _xwindow ); // does not seem to influence the event gathering
}
Hi Chris,
regarding your startX() and from what I see there is nothing "fishy" This part looks good to me and I don't think its a problem with your X Server since you say that xcube demo and xvalue always work. I tend to think that there may be still a glitch somewhere in your code.
Since I don't know of your source internals and how the thread(s) work together I just can provide you with some wild guesses/tips:
Do you initialize Xlibs support for concurrent threads (XInitThreads()) and do you secure every section where _xdisplay is accessed by different threads with XLockDisplay() and XUnlockDisplay()?
Can you modify your code to work just single threaded to see if there might be an issue with multi threading?
Since I don't know the Boost library/classes I'm not sure how this continous calls to your method nextEvent() (I think there you use XNextEvent() and so on like in the SDK) work with or affect the behaviour of XNextEvent().
I hope I could give you - at least - some interesting pointers to look at when debugging.
Please let me know if you have additional questions and comments or if you found the solution!
Regards,
Christian
3Dconnexion
regarding your startX() and from what I see there is nothing "fishy" This part looks good to me and I don't think its a problem with your X Server since you say that xcube demo and xvalue always work. I tend to think that there may be still a glitch somewhere in your code.
Since I don't know of your source internals and how the thread(s) work together I just can provide you with some wild guesses/tips:
Do you initialize Xlibs support for concurrent threads (XInitThreads()) and do you secure every section where _xdisplay is accessed by different threads with XLockDisplay() and XUnlockDisplay()?
Can you modify your code to work just single threaded to see if there might be an issue with multi threading?
Since I don't know the Boost library/classes I'm not sure how this continous calls to your method nextEvent() (I think there you use XNextEvent() and so on like in the SDK) work with or affect the behaviour of XNextEvent().
I hope I could give you - at least - some interesting pointers to look at when debugging.
Please let me know if you have additional questions and comments or if you found the solution!
Regards,
Christian
3Dconnexion