I found the issue!

Here's the deal, as I mentioned before this issue exists in both linux and windows (I don't have a mac but I assume it would be the same). I fixed it in linux, I'll leave windows to you guys since I don't know much about it, the issue is in the event processing function, for linux its void LinuxMouse::_processXEvents() . As the fps falls there are an increasing number of events to frames, in the old code the entire event stack is processed each frame, however the relative motion is calculated each event, rather than each frame resulting in only the very last events relative motion to be passed to the application. This finally results in the mouse becoming slower and slower as the fps drops in the application, and becoming essentially unusable below 30fps. The following code resolves that issue by simply querying the mouse one time each call. Using this code all of the ogre sample apps, the ois console app, and my app

, work perfect at very very low fps, the mouse moves at the same speed if your running at 2fps or 2000fps. To test in any app, or the oisconsole you can increase the usleep/sleep to 500000 instead of just 50 or 500, when moving the mouse you will see that the values change at the same general pace.
void LinuxMouse::_processXEvents()
{
Window u1; int u2;
Window current_win;
int x, y;
unsigned int mmask;
if ( XQueryPointer(display, window, &u1, ¤t_win, &u2, &u2, &x, &y, &mmask) )
{
//Ignore out of bounds mouse if we just warped
if( mWarped && (x < 5 || x > mState.width - 5 || y < 5 || y > mState.height - 5))
{
}
else if (!(oldXMouseX == x && oldXMouseY == y))
{
//Compute this frames Relative X & Y motion
mState.X.rel = x - oldXMouseX;
mState.Y.rel = y - oldXMouseY;
//Store old values for next time to compute relative motion
oldXMouseX = x;
oldXMouseY = y;
mState.X.abs += mState.X.rel;
mState.Y.abs += mState.Y.rel;
//Check to see if we are grabbing the mouse to the window (requires clipping and warping)
if( grabMouse )
{
if( mState.X.abs < 0 )
mState.X.abs = 0;
else if( mState.X.abs > mState.width )
mState.X.abs = mState.width;
if( mState.Y.abs < 0 )
mState.Y.abs = 0;
else if( mState.Y.abs > mState.height )
mState.Y.abs = mState.height;
if( mouseFocusLost == false )
{
//Keep mouse in window (fudge factor)
if(x < 5 || x > mState.width - 5 ||
y < 5 || y > mState.height - 5 )
{
oldXMouseX = mState.width >> 1; //center x
oldXMouseY = mState.height >> 1; //center y
XWarpPointer(display, None, window, 0, 0, 0, 0, oldXMouseX, oldXMouseY);
mWarped = true;
}
}
}
mMoved = true;
}
}
//X11 Button Events: 1=left 2=middle 3=right; Our Bit Postion: 1=Left 2=Right 3=Middle
char mask[4] = {0,1,4,2};
XEvent event;
//Poll x11 for events mouse events
while( XPending(display) > 0 )
{
XNextEvent(display, &event);
//if( event.type == MotionNotify )
//{ //Mouse moved
//}
if( event.type == ButtonPress )
{ //Button down
static_cast<LinuxInputManager*>(mCreator)->_setGrabState(true);
if( event.xbutton.button < 4 )
{
mState.buttons |= mask[event.xbutton.button];
if( mBuffered && mListener )
if( mListener->mousePressed( MouseEvent( this, mState ),
(MouseButtonID)(mask[event.xbutton.button] >> 1)) == false )
return;
}
}
else if( event.type == ButtonRelease )
{ //Button up
if( event.xbutton.button < 4 )
{
mState.buttons &= ~mask[event.xbutton.button];
if( mBuffered && mListener )
if( mListener->mouseReleased( MouseEvent( this, mState ),
(MouseButtonID)(mask[event.xbutton.button] >> 1)) == false )
return;
}
//The Z axis gets pushed/released pair message (this is up)
else if( event.xbutton.button == 4 )
{
mState.Z.rel += 120;
mState.Z.abs += 120;
mMoved = true;
}
//The Z axis gets pushed/released pair message (this is down)
else if( event.xbutton.button == 5 )
{
mState.Z.rel -= 120;
mState.Z.abs -= 120;
mMoved = true;
}
}
}
}