10#include <QtCore/QFile>
11#include <QtCore/QJsonDocument>
12#include <QtCore/QJsonObject>
13#include <QtCore/QJsonArray>
14#include <QtCore/QLoggingCategory>
15#include <QtGui/QPainter>
16#include <QtGui/private/qguiapplication_p.h>
19#include <xf86drmMode.h>
21#ifndef DRM_CAP_CURSOR_WIDTH
22#define DRM_CAP_CURSOR_WIDTH 0x8
25#ifndef DRM_CAP_CURSOR_HEIGHT
26#define DRM_CAP_CURSOR_HEIGHT 0x9
37 , m_cursorSize(64, 64)
39 , m_cursorImage(
nullptr,
nullptr, 0, 0, 0, 0)
40 , m_state(CursorPendingVisible)
41 , m_deviceListener(
nullptr)
45 m_state = CursorDisabled;
52 m_cursorSize.setWidth(
width);
53 m_cursorSize.setHeight(
height);
56 m_bo = gbm_bo_create(
static_cast<QEglFSKmsGbmDevice *
>(m_screen->device())->
gbmDevice(), m_cursorSize.width(), m_cursorSize.height(),
57 GBM_FORMAT_ARGB8888, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
59 qWarning(
"Could not create buffer for cursor!");
67 if (!m_deviceListener->hasMouse())
68 m_state = CursorPendingHidden;
72 changeCursor(&
cursor,
nullptr);
79 delete m_deviceListener;
95 const bool wasVisible = m_state == CursorVisible;
96 const bool visible = m_deviceListener->
hasMouse();
97 if (visible == wasVisible)
100 m_state = visible ? CursorPendingVisible : CursorPendingHidden;
131 if (m_state == CursorPendingHidden) {
132 m_state = CursorHidden;
139 if (m_state == CursorHidden || m_state == CursorDisabled)
149 const int width = m_cursorAtlas.cursorWidth;
150 const int height = m_cursorAtlas.cursorHeight;
151 const qreal ws = (
qreal)m_cursorAtlas.cursorWidth / m_cursorAtlas.width;
152 const qreal hs = (
qreal)m_cursorAtlas.cursorHeight / m_cursorAtlas.height;
154 QRect textureRect(ws * (newShape % m_cursorAtlas.cursorsPerRow) * m_cursorAtlas.width,
155 hs * (newShape / m_cursorAtlas.cursorsPerRow) * m_cursorAtlas.height,
158 QPoint hotSpot = m_cursorAtlas.hotSpots[newShape];
159 m_cursorImage.
set(m_cursorAtlas.image.copy(textureRect),
165 qWarning(
"Cursor larger than %dx%d, cursor will be clipped.", m_cursorSize.
width(), m_cursorSize.
height());
177 uint32_t
handle = gbm_bo_get_handle(m_bo).u32;
179 if (m_state == CursorPendingVisible)
180 m_state = CursorVisible;
206 const QPoint adjustedLocalPos = localPos - m_cursorImage.
hotspot();
208 if (localPos.
x() < 0 || localPos.
y() < 0
209 || localPos.
x() >= screenGeom.
width() || localPos.
y() >= screenGeom.
height())
219 uint32_t
handle = gbm_bo_get_handle(m_bo).u32;
224 adjustedLocalPos.
x(), adjustedLocalPos.
y());
236void QEglFSKmsGbmCursor::initCursorAtlas()
240 json =
":/cursor.json";
242 qCDebug(qLcEglfsKmsDebug) <<
"Initializing cursor atlas from" << json;
251 m_state = CursorDisabled;
258 QString atlas =
object.value(
"image"_L1).toString();
261 const int cursorsPerRow =
object.value(
"cursorsPerRow"_L1).toDouble();
263 m_cursorAtlas.cursorsPerRow = cursorsPerRow;
265 const QJsonArray hotSpots =
object.value(
"hotSpots"_L1).toArray();
267 for (
int i = 0;
i < hotSpots.
count();
i++) {
269 m_cursorAtlas.hotSpots << hotSpot;
273 m_cursorAtlas.cursorWidth =
image.width() / m_cursorAtlas.cursorsPerRow;
274 m_cursorAtlas.cursorHeight =
image.height() / ((
Qt::LastCursor + cursorsPerRow) / cursorsPerRow);
275 m_cursorAtlas.width =
image.width();
276 m_cursorAtlas.height =
image.height();
277 m_cursorAtlas.image =
image;
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
int toInt(bool *ok=nullptr, int base=10) const
Returns the byte array converted to an int using base base, which is ten by default.
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
The QCursor class provides a mouse cursor with an arbitrary shape.
QPixmap pixmap() const
Returns the cursor pixmap.
Qt::CursorShape shape() const
Returns the cursor shape identifier.
QPoint hotSpot() const
Returns the cursor hot spot, or (0, 0) if it is one of the standard cursors.
void onDeviceListChanged(QInputDeviceManager::DeviceType type)
void pointerEvent(const QMouseEvent &event) override
This method is called by Qt whenever a QMouseEvent is generated by the underlying pointer input.
void changeCursor(QCursor *windowCursor, QWindow *window) override
This method is called by Qt whenever the cursor graphic should be changed.
void setPos(const QPoint &pos) override
QPoint pos() const override
gbm_device * gbmDevice() const
QString name() const override
QList< QPlatformScreen * > virtualSiblings() const override
Returns a list of all the platform screens that are part of the same virtual desktop.
void setCursorOutOfRange(bool b)
QEglFSKmsDevice * device() const
bool isCursorOutOfRange() const
void handleCursorMove(const QPoint &pos)
QWindow * topLevelAt(const QPoint &point) const override
Return the given top level window for a given position.
QRect geometry() const override
Reimplement in subclass to return the pixel geometry of the screen.
bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
static QInputDeviceManager * inputDeviceManager()
QByteArray readAll()
Reads all remaining data from the device, and returns it as a byte array.
qsizetype sizeInBytes() const
int width() const
Returns the width of the image.
int height() const
Returns the height of the image.
void fill(uint pixel)
Fills the entire image with the given pixelValue.
const uchar * constBits() const
Returns a pointer to the first pixel data.
QImage convertToFormat(Format f, Qt::ImageConversionFlags flags=Qt::AutoColor) const &
\inmodule QtCore\reentrant
qsizetype count() const
Same as size().
\inmodule QtCore\reentrant
QJsonObject object() const
Returns the QJsonObject contained in the document.
static QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error=nullptr)
Parses json as a UTF-8 encoded JSON document, and creates a QJsonDocument from it.
\inmodule QtCore\reentrant
The QPainter class performs low-level painting on widgets and other paint devices.
bool begin(QPaintDevice *)
Begins painting the paint device and returns true if successful; otherwise returns false.
void drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect, Qt::ImageConversionFlags flags=Qt::AutoColor)
Draws the rectangular portion source of the given image into the target rectangle in the paint device...
QImage toImage() const
Converts the pixmap to a QImage.
\inmodule QtCore\reentrant
constexpr int x() const noexcept
Returns the x coordinate of this point.
constexpr int y() const noexcept
Returns the y coordinate of this point.
\inmodule QtCore\reentrant
constexpr int height() const noexcept
Returns the height of the rectangle.
constexpr QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
constexpr int width() const noexcept
Returns the width of the rectangle.
constexpr int height() const noexcept
Returns the height.
constexpr int width() const noexcept
Returns the width.
\macro QT_RESTRICTED_CAST_FROM_ASCII
QByteArray toLatin1() const &
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Combined button and popup list for selecting options.
#define DRM_CAP_CURSOR_HEIGHT
#define DRM_CAP_CURSOR_WIDTH
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
GLuint64 GLenum void * handle
GLint GLsizei GLsizei height
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
static double toDouble(Value v)
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)