eglfs: Support dynamic mouse cursor show/hide with DRM HW cursor

Task-number: QTBUG-52743
Change-Id: I0bea1451dfe7b049c129b11716d593115e3d8374
Reviewed-by: Louai Al-Khanji <louai.al-khanji@qt.io>
This commit is contained in:
Laszlo Agocs 2016-04-22 16:38:32 +02:00
parent edc4f02410
commit c46f74d325
2 changed files with 81 additions and 8 deletions

View File

@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@ -41,6 +41,7 @@
#include <QtCore/QJsonArray>
#include <QtCore/QLoggingCategory>
#include <QtGui/QPainter>
#include <QtGui/private/qguiapplication_p.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
@ -62,13 +63,13 @@ QEglFSKmsCursor::QEglFSKmsCursor(QEglFSKmsScreen *screen)
, m_cursorSize(64, 64) // 64x64 is the old standard size, we now try to query the real size below
, m_bo(Q_NULLPTR)
, m_cursorImage(0, 0, 0, 0, 0, 0)
, m_visible(true)
, m_state(CursorPendingVisible)
{
QByteArray hideCursorVal = qgetenv("QT_QPA_EGLFS_HIDECURSOR");
if (!hideCursorVal.isEmpty())
m_visible = hideCursorVal.toInt() == 0;
if (!m_visible)
if (!hideCursorVal.isEmpty() && hideCursorVal.toInt()) {
m_state = CursorDisabled;
return;
}
uint64_t width, height;
if ((drmGetCap(m_screen->device()->fd(), DRM_CAP_CURSOR_WIDTH, &width) == 0)
@ -85,6 +86,12 @@ QEglFSKmsCursor::QEglFSKmsCursor(QEglFSKmsScreen *screen)
initCursorAtlas();
}
m_deviceListener = new QEglFSKmsCursorDeviceListener(this);
connect(QGuiApplicationPrivate::inputDeviceManager(), &QInputDeviceManager::deviceListChanged,
m_deviceListener, &QEglFSKmsCursorDeviceListener::onDeviceListChanged);
if (!m_deviceListener->hasMouse())
m_state = CursorPendingHidden;
#ifndef QT_NO_CURSOR
QCursor cursor(Qt::ArrowCursor);
changeCursor(&cursor, 0);
@ -94,6 +101,8 @@ QEglFSKmsCursor::QEglFSKmsCursor(QEglFSKmsScreen *screen)
QEglFSKmsCursor::~QEglFSKmsCursor()
{
delete m_deviceListener;
Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) {
QEglFSKmsScreen *kmsScreen = static_cast<QEglFSKmsScreen *>(screen);
drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0, 0);
@ -106,6 +115,31 @@ QEglFSKmsCursor::~QEglFSKmsCursor()
}
}
void QEglFSKmsCursor::updateMouseStatus()
{
const bool wasVisible = m_state == CursorVisible;
const bool visible = m_deviceListener->hasMouse();
if (visible == wasVisible)
return;
m_state = visible ? CursorPendingVisible : CursorPendingHidden;
#ifndef QT_NO_CURSOR
changeCursor(nullptr, m_screen->topLevelAt(pos()));
#endif
}
bool QEglFSKmsCursorDeviceListener::hasMouse() const
{
return QGuiApplicationPrivate::inputDeviceManager()->deviceCount(QInputDeviceManager::DeviceTypePointer) > 0;
}
void QEglFSKmsCursorDeviceListener::onDeviceListChanged(QInputDeviceManager::DeviceType type)
{
if (type == QInputDeviceManager::DeviceTypePointer)
m_cursor->updateMouseStatus();
}
void QEglFSKmsCursor::pointerEvent(const QMouseEvent &event)
{
setPos(event.screenPos().toPoint());
@ -119,7 +153,15 @@ void QEglFSKmsCursor::changeCursor(QCursor *windowCursor, QWindow *window)
if (!m_bo)
return;
if (!m_visible)
if (m_state == CursorPendingHidden) {
m_state = CursorHidden;
Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) {
QEglFSKmsScreen *kmsScreen = static_cast<QEglFSKmsScreen *>(screen);
drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0, 0);
}
}
if (m_state == CursorHidden || m_state == CursorDisabled)
return;
const Qt::CursorShape newShape = windowCursor ? windowCursor->shape() : Qt::ArrowCursor;
@ -159,6 +201,9 @@ void QEglFSKmsCursor::changeCursor(QCursor *windowCursor, QWindow *window)
uint32_t handle = gbm_bo_get_handle(m_bo).u32;
if (m_state == CursorPendingVisible)
m_state = CursorVisible;
Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) {
QEglFSKmsScreen *kmsScreen = static_cast<QEglFSKmsScreen *>(screen);
@ -206,7 +251,7 @@ void QEglFSKmsCursor::initCursorAtlas()
drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0, 0);
drmModeMoveCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0);
}
m_visible = false;
m_state = CursorDisabled;
return;
}

View File

@ -37,12 +37,29 @@
#include <qpa/qplatformcursor.h>
#include <QtCore/QList>
#include <QtGui/QImage>
#include <QtGui/private/qinputdevicemanager_p.h>
#include <gbm.h>
QT_BEGIN_NAMESPACE
class QEglFSKmsScreen;
class QEglFSKmsCursor;
class QEglFSKmsCursorDeviceListener : public QObject
{
Q_OBJECT
public:
QEglFSKmsCursorDeviceListener(QEglFSKmsCursor *cursor) : m_cursor(cursor) { }
bool hasMouse() const;
public slots:
void onDeviceListChanged(QInputDeviceManager::DeviceType type);
private:
QEglFSKmsCursor *m_cursor;
};
class QEglFSKmsCursor : public QPlatformCursor
{
@ -60,15 +77,26 @@ public:
QPoint pos() const Q_DECL_OVERRIDE;
void setPos(const QPoint &pos) Q_DECL_OVERRIDE;
void updateMouseStatus();
private:
void initCursorAtlas();
enum CursorState {
CursorDisabled,
CursorPendingHidden,
CursorHidden,
CursorPendingVisible,
CursorVisible
};
QEglFSKmsScreen *m_screen;
QSize m_cursorSize;
gbm_bo *m_bo;
QPoint m_pos;
QPlatformCursorImage m_cursorImage;
bool m_visible;
CursorState m_state;
QEglFSKmsCursorDeviceListener *m_deviceListener;
// cursor atlas information
struct CursorAtlas {