Optimize egl cursor update events

Avoid invokeMethod on every cursor movement and use an event instead. This is more
lightweight and efficient. Also, there is no need to have a separate QObject just
for this.

Change-Id: I65ae202943eeb1e30cf22926576f84198f2487f8
Reviewed-by: Andy Nichols <andy.nichols@theqtcompany.com>
This commit is contained in:
Laszlo Agocs 2015-03-05 11:46:27 +01:00
parent 87af240c86
commit 4fe9798db3
2 changed files with 33 additions and 37 deletions

View File

@ -62,7 +62,7 @@ QEGLPlatformCursor::QEGLPlatformCursor(QPlatformScreen *screen)
m_textureCoordEntry(0),
m_textureEntry(0),
m_deviceListener(0),
m_updater(screen)
m_updateRequested(false)
{
QByteArray hideCursorVal = qgetenv("QT_QPA_EGLFS_HIDECURSOR");
if (!hideCursorVal.isEmpty())
@ -246,30 +246,43 @@ bool QEGLPlatformCursor::setCurrentCursor(QCursor *cursor)
}
#endif
void QEGLPlatformCursorUpdater::update(const QPoint &pos, const QRegion &rgn)
class CursorUpdateEvent : public QEvent
{
m_active = false;
QWindowSystemInterface::handleExposeEvent(m_screen->topLevelAt(pos), rgn);
QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
}
public:
CursorUpdateEvent(const QPoint &pos, const QRegion &rgn)
: QEvent(QEvent::Type(QEvent::User + 1)),
m_pos(pos),
m_region(rgn)
{ }
QPoint pos() const { return m_pos; }
QRegion region() const { return m_region; }
void QEGLPlatformCursorUpdater::scheduleUpdate(const QPoint &pos, const QRegion &rgn)
private:
QPoint m_pos;
QRegion m_region;
};
bool QEGLPlatformCursor::event(QEvent *e)
{
if (m_active)
return;
m_active = true;
// Must not flush the window system events directly from here since we are likely to
// be a called directly from QGuiApplication's processMouseEvents. Flushing events
// could cause reentering by dispatching more queued mouse events.
QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection,
Q_ARG(QPoint, pos), Q_ARG(QRegion, rgn));
if (e->type() == QEvent::User + 1) {
CursorUpdateEvent *ev = static_cast<CursorUpdateEvent *>(e);
m_updateRequested = false;
QWindowSystemInterface::handleExposeEvent(m_screen->topLevelAt(ev->pos()), ev->region());
QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
return true;
}
return QPlatformCursor::event(e);
}
void QEGLPlatformCursor::update(const QRegion &rgn)
{
m_updater.scheduleUpdate(m_cursor.pos, rgn);
if (!m_updateRequested) {
// Must not flush the window system events directly from here since we are likely to
// be a called directly from QGuiApplication's processMouseEvents. Flushing events
// could cause reentering by dispatching more queued mouse events.
m_updateRequested = true;
QCoreApplication::postEvent(this, new CursorUpdateEvent(m_cursor.pos, rgn));
}
}
QRect QEGLPlatformCursor::cursorRect() const

View File

@ -70,24 +70,6 @@ private:
QEGLPlatformCursor *m_cursor;
};
class QEGLPlatformCursorUpdater : public QObject
{
Q_OBJECT
public:
QEGLPlatformCursorUpdater(QPlatformScreen *screen)
: m_screen(screen), m_active(false) { }
void scheduleUpdate(const QPoint &pos, const QRegion &rgn);
private slots:
void update(const QPoint &pos, const QRegion &rgn);
private:
QPlatformScreen *m_screen;
bool m_active;
};
class QEGLPlatformCursor : public QPlatformCursor, protected QOpenGLFunctions
{
Q_OBJECT
@ -109,6 +91,7 @@ public:
void updateMouseStatus();
private:
bool event(QEvent *e) Q_DECL_OVERRIDE;
#ifndef QT_NO_CURSOR
bool setCurrentCursor(QCursor *cursor);
#endif
@ -150,7 +133,7 @@ private:
int m_textureCoordEntry;
int m_textureEntry;
QEGLPlatformCursorDeviceListener *m_deviceListener;
QEGLPlatformCursorUpdater m_updater;
bool m_updateRequested;
};
QT_END_NAMESPACE