1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qfbcursor_p.h"
5#include "qfbscreen_p.h"
6#include <QtGui/QPainter>
7#include <QtGui/private/qguiapplication_p.h>
8
9QT_BEGIN_NAMESPACE
10
11bool QFbCursorDeviceListener::hasMouse() const
12{
13 return QGuiApplicationPrivate::inputDeviceManager()->deviceCount(type: QInputDeviceManager::DeviceTypePointer) > 0;
14}
15
16void QFbCursorDeviceListener::onDeviceListChanged(QInputDeviceManager::DeviceType type)
17{
18 if (type == QInputDeviceManager::DeviceTypePointer)
19 m_cursor->updateMouseStatus();
20}
21
22QFbCursor::QFbCursor(QFbScreen *screen)
23 : mVisible(true),
24 mScreen(screen),
25 mDirty(false),
26 mOnScreen(false),
27 mCursorImage(nullptr),
28 mDeviceListener(nullptr)
29{
30 const char *envVar = "QT_QPA_FB_HIDECURSOR";
31 if (qEnvironmentVariableIsSet(varName: envVar))
32 mVisible = qEnvironmentVariableIntValue(varName: envVar) == 0;
33 if (!mVisible)
34 return;
35
36 mCursorImage.reset(other: new QPlatformCursorImage(0, 0, 0, 0, 0, 0));
37 setCursor(Qt::ArrowCursor);
38
39 mDeviceListener = new QFbCursorDeviceListener(this);
40 connect(sender: QGuiApplicationPrivate::inputDeviceManager(), signal: &QInputDeviceManager::deviceListChanged,
41 context: mDeviceListener, slot: &QFbCursorDeviceListener::onDeviceListChanged);
42 updateMouseStatus();
43}
44
45QFbCursor::~QFbCursor()
46{
47 delete mDeviceListener;
48}
49
50QRect QFbCursor::getCurrentRect() const
51{
52 QRect rect = mCursorImage->image()->rect().translated(dx: -mCursorImage->hotspot().x(),
53 dy: -mCursorImage->hotspot().y());
54 rect.translate(p: m_pos);
55 QPoint mScreenOffset = mScreen->geometry().topLeft();
56 rect.translate(p: -mScreenOffset); // global to local translation
57 return rect;
58}
59
60QPoint QFbCursor::pos() const
61{
62 return m_pos;
63}
64
65void QFbCursor::setPos(const QPoint &pos)
66{
67 QGuiApplicationPrivate::inputDeviceManager()->setCursorPos(pos);
68 m_pos = pos;
69 if (!mVisible)
70 return;
71 mCurrentRect = getCurrentRect();
72 if (mOnScreen || mScreen->geometry().intersects(r: mCurrentRect.translated(p: mScreen->geometry().topLeft())))
73 setDirty();
74}
75
76void QFbCursor::pointerEvent(const QMouseEvent &e)
77{
78 if (e.type() != QEvent::MouseMove)
79 return;
80 m_pos = e.globalPosition().toPoint();
81 if (!mVisible)
82 return;
83 mCurrentRect = getCurrentRect();
84 if (mOnScreen || mScreen->geometry().intersects(r: mCurrentRect.translated(p: mScreen->geometry().topLeft())))
85 setDirty();
86}
87
88QRect QFbCursor::drawCursor(QPainter & painter)
89{
90 if (!mVisible)
91 return QRect();
92
93 mDirty = false;
94 if (mCurrentRect.isNull())
95 return QRect();
96
97 // We need this because the cursor might be mDirty due to moving off mScreen
98 QPoint mScreenOffset = mScreen->geometry().topLeft();
99 // global to local translation
100 if (!mCurrentRect.translated(p: mScreenOffset).intersects(r: mScreen->geometry()))
101 return QRect();
102
103 mPrevRect = mCurrentRect;
104 painter.drawImage(r: mPrevRect, image: *mCursorImage->image());
105 mOnScreen = true;
106 return mPrevRect;
107}
108
109QRect QFbCursor::dirtyRect()
110{
111 if (mOnScreen) {
112 mOnScreen = false;
113 return mPrevRect;
114 }
115 return QRect();
116}
117
118void QFbCursor::setCursor(Qt::CursorShape shape)
119{
120 if (mCursorImage)
121 mCursorImage->set(shape);
122}
123
124void QFbCursor::setCursor(const QImage &image, int hotx, int hoty)
125{
126 if (mCursorImage)
127 mCursorImage->set(image, hx: hotx, hy: hoty);
128}
129
130void QFbCursor::setCursor(const uchar *data, const uchar *mask, int width, int height, int hotX, int hotY)
131{
132 if (mCursorImage)
133 mCursorImage->set(data, mask, width, height, hotX, hotY);
134}
135
136#ifndef QT_NO_CURSOR
137void QFbCursor::changeCursor(QCursor * widgetCursor, QWindow *window)
138{
139 Q_UNUSED(window);
140 if (!mVisible)
141 return;
142 const Qt::CursorShape shape = widgetCursor ? widgetCursor->shape() : Qt::ArrowCursor;
143
144 if (shape == Qt::BitmapCursor) {
145 // application supplied cursor
146 QPoint spot = widgetCursor->hotSpot();
147 setCursor(image: widgetCursor->pixmap().toImage(), hotx: spot.x(), hoty: spot.y());
148 } else {
149 // system cursor
150 setCursor(shape);
151 }
152 mCurrentRect = getCurrentRect();
153 QPoint mScreenOffset = mScreen->geometry().topLeft(); // global to local translation
154 if (mOnScreen || mScreen->geometry().intersects(r: mCurrentRect.translated(p: mScreenOffset)))
155 setDirty();
156}
157#endif
158
159void QFbCursor::setDirty()
160{
161 if (!mVisible)
162 return;
163
164 if (!mDirty) {
165 mDirty = true;
166 mScreen->scheduleUpdate();
167 }
168}
169
170void QFbCursor::updateMouseStatus()
171{
172 mVisible = mDeviceListener ? mDeviceListener->hasMouse() : false;
173 mScreen->setDirty(mVisible ? getCurrentRect() : lastPainted());
174}
175
176QT_END_NAMESPACE
177
178#include "moc_qfbcursor_p.cpp"
179

source code of qtbase/src/platformsupport/fbconvenience/qfbcursor.cpp