From 802abade4f3db88d752b49fedb4c3285ff35c2e8 Mon Sep 17 00:00:00 2001 From: Eric Johnston Date: Mon, 15 Jul 2013 18:16:50 -0700 Subject: [PATCH] Fixed problem in idle(), causing events to stack up. The problem was that idle() was set on a zero-ms timer (using idleTimer->start(0)), and the time is then self-regulated by returning early if it's not time yet. Because of this, Qt stays perpetually in the timer servicing, instead of processing events. This causes keys and menu items to be delayed if the user drags the mouse before activating them, especially at low frame rates. It also causes very-delayed multitouch response. The fix I've applied is to reset the idle timer after servicing the idle. I've set it to 2ms because I noticed that 1ms didn't always clear out all of the events. We can tune it to whatever we need, or even calculate it based on the time it took us to service the idle. --- interface/src/Application.cpp | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5ad1a46c39..4ea6e0bf84 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -82,6 +82,7 @@ const glm::vec3 START_LOCATION(4.f, 0.f, 5.f); // Where one's own node begins const int IDLE_SIMULATE_MSECS = 16; // How often should call simulate and other stuff // in the idle loop? (60 FPS is default) +static QTimer* idleTimer = NULL; const int STARTUP_JITTER_SAMPLES = PACKET_LENGTH_SAMPLES_PER_CHANNEL / 2; // Startup optimistically with small jitter buffer that @@ -341,7 +342,7 @@ void Application::initializeGL() { timer->start(1000); // call our idle function whenever we can - QTimer* idleTimer = new QTimer(this); + idleTimer = new QTimer(this); connect(idleTimer, SIGNAL(timeout()), SLOT(idle())); idleTimer->start(0); _idleLoopStdev.reset(); @@ -973,19 +974,9 @@ void Application::idle() { gettimeofday(&check, NULL); // Only run simulation code if more than IDLE_SIMULATE_MSECS have passed since last time we ran - sendPostedEvents(NULL, QEvent::TouchBegin); - sendPostedEvents(NULL, QEvent::TouchUpdate); - sendPostedEvents(NULL, QEvent::TouchEnd); double timeSinceLastUpdate = diffclock(&_lastTimeUpdated, &check); if (timeSinceLastUpdate > IDLE_SIMULATE_MSECS) { - - // If we're using multi-touch look, immediately process any - // touch events, and no other events. - // This is necessary because id the idle() call takes longer than the - // interval between idle() calls, the event loop never gets to run, - // and touch events get delayed. - const float BIGGEST_DELTA_TIME_SECS = 0.25f; update(glm::clamp((float)timeSinceLastUpdate / 1000.f, 0.f, BIGGEST_DELTA_TIME_SECS)); _glWidget->updateGL(); @@ -998,6 +989,9 @@ void Application::idle() { _idleLoopMeasuredJitter = _idleLoopStdev.getStDev(); _idleLoopStdev.reset(); } + + // After finishing all of the above work, restart the idle timer, allowing 2ms to process events. + idleTimer->start(2); } } void Application::terminate() {