+ fixes #0001477: Spaceball becomes uncontrollable for large FreeCAD Documnets on X11 (spacenav)
This commit is contained in:
parent
85bf3ab9f4
commit
490f041717
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user