38 , m_cursorSize(64, 64)
40 , m_cursorImage(
nullptr,
nullptr, 0, 0, 0, 0)
41 , m_state(CursorPendingVisible)
42 , m_deviceListener(
nullptr)
44 QByteArray hideCursorVal = qgetenv(
"QT_QPA_EGLFS_HIDECURSOR");
45 if (!hideCursorVal.isEmpty() && hideCursorVal.toInt()) {
46 m_state = CursorDisabled;
50 uint64_t width, height;
53 m_cursorSize.setWidth(width);
54 m_cursorSize.setHeight(height);
57 m_bo = gbm_bo_create(
static_cast<QEglFSKmsGbmDevice *>(m_screen->device())->gbmDevice(), m_cursorSize.width(), m_cursorSize.height(),
58 GBM_FORMAT_ARGB8888, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
60 qWarning(
"Could not create buffer for cursor!");
65 m_deviceListener =
new QEglFSKmsGbmCursorDeviceListener(
this);
66 connect(QGuiApplicationPrivate::inputDeviceManager(), &QInputDeviceManager::deviceListChanged,
67 m_deviceListener, &QEglFSKmsGbmCursorDeviceListener::onDeviceListChanged);
68 if (!m_deviceListener->hasMouse())
69 m_state = CursorPendingHidden;
72 QCursor cursor(Qt::ArrowCursor);
73 changeCursor(&cursor,
nullptr);
80 delete m_deviceListener;
82 for (QPlatformScreen *screen : m_screen->virtualSiblings()) {
83 QEglFSKmsScreen *kmsScreen =
static_cast<QEglFSKmsScreen *>(screen);
84 drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0, 0);
85 drmModeMoveCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0);
132 if (m_state == CursorPendingHidden) {
133 m_state = CursorHidden;
134 for (QPlatformScreen *screen : m_screen->virtualSiblings()) {
135 QEglFSKmsScreen *kmsScreen =
static_cast<QEglFSKmsScreen *>(screen);
136 drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0, 0);
140 if (m_state == CursorHidden || m_state == CursorDisabled)
143 const Qt::CursorShape newShape = windowCursor ? windowCursor->shape() : Qt::ArrowCursor;
144 if (newShape == Qt::BitmapCursor) {
145 m_cursorImage.set(windowCursor->pixmap().toImage(),
146 windowCursor->hotSpot().x(),
147 windowCursor->hotSpot().y());
150 const int width = m_cursorAtlas.cursorWidth;
151 const int height = m_cursorAtlas.cursorHeight;
152 const qreal ws = (qreal)m_cursorAtlas.cursorWidth / m_cursorAtlas.width;
153 const qreal hs = (qreal)m_cursorAtlas.cursorHeight / m_cursorAtlas.height;
155 QRect textureRect(ws * (newShape % m_cursorAtlas.cursorsPerRow) * m_cursorAtlas.width,
156 hs * (newShape / m_cursorAtlas.cursorsPerRow) * m_cursorAtlas.height,
159 QPoint hotSpot = m_cursorAtlas.hotSpots[newShape];
160 m_cursorImage.set(m_cursorAtlas.image.copy(textureRect),
165 if (m_cursorImage.image()->width() > m_cursorSize.width() || m_cursorImage.image()->height() > m_cursorSize.height())
166 qWarning(
"Cursor larger than %dx%d, cursor will be clipped.", m_cursorSize.width(), m_cursorSize.height());
168 QImage cursorImage(m_cursorSize, QImage::Format_ARGB32);
169 cursorImage.fill(Qt::transparent);
172 painter.begin(&cursorImage);
173 painter.drawImage(0, 0, *m_cursorImage.image());
176 gbm_bo_write(m_bo, cursorImage.constBits(), cursorImage.sizeInBytes());
178 uint32_t handle = gbm_bo_get_handle(m_bo).u32;
180 if (m_state == CursorPendingVisible)
181 m_state = CursorVisible;
183 for (QPlatformScreen *screen : m_screen->virtualSiblings()) {
184 QEglFSKmsScreen *kmsScreen =
static_cast<QEglFSKmsScreen *>(screen);
185 if (kmsScreen->isCursorOutOfRange())
187 int status = drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, handle,
188 m_cursorSize.width(), m_cursorSize.height());
190 qWarning(
"Could not set cursor on screen %s: %d", kmsScreen->name().toLatin1().constData(), status);
202 for (QPlatformScreen *screen : m_screen->virtualSiblings()) {
203 QEglFSKmsScreen *kmsScreen =
static_cast<QEglFSKmsScreen *>(screen);
204 const QRect screenGeom = kmsScreen->geometry();
205 const QPoint origin = screenGeom.topLeft();
206 const QPoint localPos = pos - origin;
207 const QPoint adjustedLocalPos = localPos - m_cursorImage.hotspot();
209 if (localPos.x() < 0 || localPos.y() < 0
210 || localPos.x() >= screenGeom.width() || localPos.y() >= screenGeom.height())
212 if (!kmsScreen->isCursorOutOfRange()) {
213 kmsScreen->setCursorOutOfRange(
true);
214 drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0, 0);
218 if (kmsScreen->isCursorOutOfRange() && m_bo) {
219 kmsScreen->setCursorOutOfRange(
false);
220 uint32_t handle = gbm_bo_get_handle(m_bo).u32;
221 ret = drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id,
222 handle, m_cursorSize.width(), m_cursorSize.height());
224 ret = drmModeMoveCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id,
225 adjustedLocalPos.x(), adjustedLocalPos.y());
230 qWarning(
"Failed to move cursor on screen %s: %d", kmsScreen->name().toLatin1().constData(), ret);
232 kmsScreen->handleCursorMove(pos);