Unsolved Mouse events starving timer on Mac OS X?
-
Has anyone encountered similar issue where mouse move events are getting triggered so often that the timer event end up getting delayed? This is on Qt 5.4.1 and Mac OS X. It's quite difficult to reproduce but when it does, my logging shows the mouse move event for my graphics widget was getting triggered a large number of times before the timer event went off. The timer was set to trigger every 30ms. This usually happens when I am using the trackpad and moving the cursor slowly.
-
Hi,
Qt 5.4.1 is pretty old, can you check against a more current version like 5.12.3 or even the latest Qt 5.13 beta ?
By the way what version of macOS are you running ?
-
Hi,
We are in the process of updating Qt for future major releases, but for previously released versions of our software, updating Qt would be too big a risk for patch releases.
We last saw the issue on Mac OS X 10.11 (our software supports Mac OS X 10.7 and above). The issue seems fairly intermittent though.
-
What is your application doing when the slowdown occurs ?
-
The application allows user to drag a ellipse around a 2D map. On both Windows and Mac, we are seeing a spike to 100% CPU usage of a thread when the ellipse is moved, doing a profile on Windows, most of the calls were mainly the blend_color_argb.
We did observe something that might be related. On Mac we were testing the issue on a laptop and the lag in the timer during mouse movement seems more obvious (e.g. the timer can be delay by seconds) when the battery is low (around 20%) and the laptop is unplugged. Not sure if there is any power saving features on Mac that might have caused the issue.
-
What kind of laptop is it ?
-
It's an early 2015 Macbook Air.
-
We recently updated to Qt 5.12.3 and the problem appears to have worsen, the event queue appears to be flooded by mouse move events and timer event are not getting triggered within the desired interval while the mouse is moving rapidly. Anyone encountered similar issue?
-
Can you test with a more recent release ?
Note that I have not seen that behaviour so if you can provide a minimal compilable example showing that it will be really helpful.
-
Haven't got around to trying 5.12.6 yet, but I did more debugging, it seems potentially related to how long the processing in the mouse move event took. In my simple test, I am just using QThread::msleep() to simulate processing. In the code example below, I found if the mouseMoveEvent() took longer than 5 milliseconds (i.e. via msleep), the timer would not trigger promptly. If I move the mouse cursor rapidly, the output log would be filled with "Mouse move" with potentially no entry of "Timer event" until the mouse movement comes to a stop.
class MovableWidget : public QGraphicsWidget { public: MovableWidget() { setFlag(ItemIsMovable); } protected: void mouseMoveEvent( QGraphicsSceneMouseEvent* e ) { qDebug() << "Mouse move"; QThread::msleep(5); QGraphicsWidget::mouseMoveEvent(e); } QRectF boundingRect() const { return QRectF(-NodeRadius, -NodeRadius, NodeRadius * 2, NodeRadius * 2); } QPainterPath shape() const { QPainterPath path; path.addEllipse(-NodeRadius, -NodeRadius, NodeRadius * 2, NodeRadius * 2); return path; } void paint( QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* ) { QPen pen(QColor(255, 0, 0, 255), 2); pen.setCosmetic(true); painter->setRenderHint(QPainter::Antialiasing); painter->setPen(pen); painter->setBrush(Qt::NoBrush); painter->drawEllipse(QPointF(), NodeRadius, NodeRadius); } private: enum Node { NodeRadius = 12 }; }; class ObjectWithTimer : public QObject { public: ObjectWithTimer( QObject* parent = 0 ) : QObject(parent) { startTimer(20); } protected: void timerEvent( QTimerEvent* e ) override { qDebug() << "Timer event"; } }; int Application::exec() { ObjectWithTimer* timerObject = new ObjectWithTimer; QGraphicsScene* scene = new QGraphicsScene; QGraphicsView* view = new QGraphicsView(scene); view->resize(500, 500); MovableWidget* widget = new MovableWidget; scene->addItem(widget); widget->setPos(250, 250); view->show(); return QApplication::exec(); }
-
Just tested the code against Qt 5.12.6, and it's similar and not sure if it matters, but the starving of the timer event only became more obvious when the sleep is 7ms instead of 5ms.
-
Don't suppose anyone know about this issue? Otherwise I will create a bug report.
-
@Thuan_Firelight
ok,
first of QThread::sleep will prevent all signals from being processed, that means the timer is ineffective during that sleep.What is your heavy operation in mousemoveevent ? maybe it's something that can be guarded / parallelized
-
Think I have worked out the cause of the issue. In our UI, we had a QLabel that was displaying the position of the moved widget and QLabel.setText was called on each mouse move (via signal and slot). The QLabel was nested in some layout with other custom widgets and QLabels.
Found a forum thread on that issue and it seems setting a fixed size on the QLabel addressed the performance issue (probably due to layout changes as the QLabel resizes to accommodate the text?).
Does that sound something that would cause a performance hit? On Windows we do notice the movement of the widget is a bit laggy but doesn't starve the timer. On Mac, it seems the movement is a lot smoother but it starves the timer.
-
@Thuan_Firelight said in Mouse events starving timer on Mac OS X?:
Does that sound something that would cause a performance hit?
yes, that sounds like a very reasonable explanation to your issue :)