Skip to content

Commit

Permalink
+ fixes #1477: Spaceball becomes uncontrollable for large FreeCAD Doc…
Browse files Browse the repository at this point in the history
…umnets on X11 (spacenav)
  • Loading branch information
wwmayer committed Mar 18, 2014
1 parent 85bf3ab commit 490f041
Showing 1 changed file with 93 additions and 11 deletions.
104 changes: 93 additions & 11 deletions src/Gui/GuiApplicationNativeEventAware.cpp
Expand Up @@ -311,16 +311,83 @@ void Gui::GUIApplicationNativeEventAware::importSettings()
bool Gui::GUIApplicationNativeEventAware::x11EventFilter(XEvent *event)
{
#ifdef SPNAV_FOUND
spnav_event navEvent;
if (!spnav_x11_event(event, &navEvent))
return false;
/*
First we check if we have a motion flush event:
- If there are unprocessed motion events we are in a flooding situation.
In that case we wait with generating a Spaceball event.
- A motion event counter of 0 indicates that FreeCAD is ready to process
the event. A Spaceball event, using the saved motion data, is posted.
*/
static Display* display = QX11Info::display();
static Atom motion_flush_event = XInternAtom(display, "FCMotionFlushEvent", false);
static int nMotionEvents = 0;

QWidget *currentWidget = this->focusWidget();
if (!currentWidget)
currentWidget = mainWindow;

if (event->type == ClientMessage)
{
Atom message_type = event->xclient.message_type;

if (message_type == motion_flush_event)
{
nMotionEvents--;
if (nMotionEvents == 0)
{
importSettings();

Spaceball::MotionEvent *motionEvent = new Spaceball::MotionEvent();

motionEvent->setTranslations(motionDataArray[0], motionDataArray[1], motionDataArray[2]);
motionEvent->setRotations(motionDataArray[3], motionDataArray[4], motionDataArray[5]);

this->postEvent(currentWidget, motionEvent);
}

return true;
} // XEvent: motion_flush_event
} // XEvent: ClientMessage

/*
From here on we deal with spacenav events only:
- motion: The event data is saved and a self addressed flush event
is sent through the window system (XEvent).
In the case of an event flooding, the motion data is added up.
- button: A Spaceball event is posted (QInputEvent).
*/
spnav_event navEvent;
if (!spnav_x11_event(event, &navEvent))
return false;

if (navEvent.type == SPNAV_EVENT_MOTION)
{
/*
If the motion data of the preceding event has not been processed
through posting an Spaceball event (flooding situation),
the motion data provided by the incoming event is added to the saved data.
*/
int dx, dy, dz, drx, dry, drz;

if (nMotionEvents == 0)
{
dx = 0;
dy = 0;
dz = 0;
drx = 0;
dry = 0;
drz = 0;
}
else
{
dx = motionDataArray[0];
dy = motionDataArray[1];
dz = motionDataArray[2];
drx = motionDataArray[3];
dry = motionDataArray[4];
drz = motionDataArray[5];
}

motionDataArray[0] = navEvent.motion.x;
motionDataArray[1] = navEvent.motion.y;
motionDataArray[2] = navEvent.motion.z;
Expand All @@ -329,14 +396,29 @@ bool Gui::GUIApplicationNativeEventAware::x11EventFilter(XEvent *event)
motionDataArray[5] = navEvent.motion.rz;

if (!setOSIndependentMotionData()) return false;
importSettings();

Spaceball::MotionEvent *motionEvent = new Spaceball::MotionEvent();

motionEvent->setTranslations(motionDataArray[0], motionDataArray[1], motionDataArray[2]);
motionEvent->setRotations(motionDataArray[3], motionDataArray[4], motionDataArray[5]);

this->postEvent(currentWidget, motionEvent);

motionDataArray[0] += dx;
motionDataArray[1] += dy;
motionDataArray[2] += dz;
motionDataArray[3] += drx;
motionDataArray[4] += dry;
motionDataArray[5] += drz;

/*
Send a self addressed flush event through the window system. This will
trigger a Spaceball event if FreeCAD is ready to do so.
*/
nMotionEvents++;
XClientMessageEvent flushEvent;

flushEvent.display = display;
flushEvent.window = event->xclient.window;
flushEvent.type = ClientMessage;
flushEvent.format = 8;
flushEvent.message_type = motion_flush_event;

XSendEvent (display, flushEvent.window, False, 0, (XEvent*)&flushEvent); // siehe spnavd, False, 0

return true;
}

Expand Down

0 comments on commit 490f041

Please sign in to comment.