37 , m_cursorSize(64, 64)
39 , m_cursorImage(
nullptr,
nullptr, 0, 0, 0, 0)
40 , m_state(CursorPendingVisible)
41 , m_deviceListener(
nullptr)
43 QByteArray hideCursorVal = qgetenv(
"QT_QPA_EGLFS_HIDECURSOR");
44 if (!hideCursorVal.isEmpty() && hideCursorVal.toInt()) {
45 m_state = CursorDisabled;
49 uint64_t width, height;
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!");
64 m_deviceListener =
new QEglFSKmsGbmCursorDeviceListener(
this);
65 connect(QGuiApplicationPrivate::inputDeviceManager(), &QInputDeviceManager::deviceListChanged,
66 m_deviceListener, &QEglFSKmsGbmCursorDeviceListener::onDeviceListChanged);
67 if (!m_deviceListener->hasMouse())
68 m_state = CursorPendingHidden;
71 QCursor cursor(Qt::ArrowCursor);
72 changeCursor(&cursor,
nullptr);
79 delete m_deviceListener;
81 for (QPlatformScreen *screen : m_screen->virtualSiblings()) {
82 QEglFSKmsScreen *kmsScreen =
static_cast<QEglFSKmsScreen *>(screen);
83 drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0, 0);
84 drmModeMoveCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0);
131 if (m_state == CursorPendingHidden) {
132 m_state = CursorHidden;
133 for (QPlatformScreen *screen : m_screen->virtualSiblings()) {
134 QEglFSKmsScreen *kmsScreen =
static_cast<QEglFSKmsScreen *>(screen);
135 drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0, 0);
139 if (m_state == CursorHidden || m_state == CursorDisabled)
142 const Qt::CursorShape newShape = windowCursor ? windowCursor->shape() : Qt::ArrowCursor;
143 if (newShape == Qt::BitmapCursor) {
144 m_cursorImage.set(windowCursor->pixmap().toImage(),
145 windowCursor->hotSpot().x(),
146 windowCursor->hotSpot().y());
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),
164 if (m_cursorImage.image()->width() > m_cursorSize.width() || m_cursorImage.image()->height() > m_cursorSize.height())
165 qWarning(
"Cursor larger than %dx%d, cursor will be clipped.", m_cursorSize.width(), m_cursorSize.height());
167 QImage cursorImage(m_cursorSize, QImage::Format_ARGB32);
168 cursorImage.fill(Qt::transparent);
171 painter.begin(&cursorImage);
172 painter.drawImage(0, 0, *m_cursorImage.image());
175 gbm_bo_write(m_bo, cursorImage.constBits(), cursorImage.sizeInBytes());
177 uint32_t handle = gbm_bo_get_handle(m_bo).u32;
179 if (m_state == CursorPendingVisible)
180 m_state = CursorVisible;
182 for (QPlatformScreen *screen : m_screen->virtualSiblings()) {
183 QEglFSKmsScreen *kmsScreen =
static_cast<QEglFSKmsScreen *>(screen);
184 if (kmsScreen->isCursorOutOfRange())
186 int status = drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, handle,
187 m_cursorSize.width(), m_cursorSize.height());
189 qWarning(
"Could not set cursor on screen %s: %d", kmsScreen->name().toLatin1().constData(), status);
201 for (QPlatformScreen *screen : m_screen->virtualSiblings()) {
202 QEglFSKmsScreen *kmsScreen =
static_cast<QEglFSKmsScreen *>(screen);
203 const QRect screenGeom = kmsScreen->geometry();
204 const QPoint origin = screenGeom.topLeft();
205 const QPoint localPos = pos - origin;
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())
211 if (!kmsScreen->isCursorOutOfRange()) {
212 kmsScreen->setCursorOutOfRange(
true);
213 drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0, 0);
217 if (kmsScreen->isCursorOutOfRange() && m_bo) {
218 kmsScreen->setCursorOutOfRange(
false);
219 uint32_t handle = gbm_bo_get_handle(m_bo).u32;
220 ret = drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id,
221 handle, m_cursorSize.width(), m_cursorSize.height());
223 ret = drmModeMoveCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id,
224 adjustedLocalPos.x(), adjustedLocalPos.y());
229 qWarning(
"Failed to move cursor on screen %s: %d", kmsScreen->name().toLatin1().constData(), ret);
231 kmsScreen->handleCursorMove(pos);