17 #include "CursorImageProvider.h" 23 #include <QSvgRenderer> 25 CursorImageProvider *CursorImageProvider::m_instance =
nullptr;
30 BuiltInCursorImage::BuiltInCursorImage()
32 const char *svgString =
33 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>" 35 " xmlns:dc=\"http://purl.org/dc/elements/1.1/\"" 36 " xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"" 37 " xmlns:svg=\"http://www.w3.org/2000/svg\"" 38 " xmlns=\"http://www.w3.org/2000/svg\"" 41 " style=\"fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:40;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1\"" 42 " d=\"M 20.504,50.94931 460.42533,518.14486 266.47603,515.61948 366.48114,719.16522 274.05218,770.68296 172.53185,559.56112 20.504,716.13476 Z\" />" 45 qimage = QImage(20, 32, QImage::Format_ARGB32);
46 qimage.fill(Qt::transparent);
47 QPainter imagePainter(&qimage);
49 QSvgRenderer *svgRenderer =
new QSvgRenderer(QByteArray(svgString));
50 svgRenderer->render(&imagePainter);
58 BlankCursorImage::BlankCursorImage()
60 qimage = QImage(1, 1, QImage::Format_ARGB32);
61 qimage.fill(Qt::transparent);
68 CustomCursorImage::CustomCursorImage(
const QCursor &cursor)
70 qimage = cursor.pixmap().toImage();
71 hotspot = cursor.hotSpot();
77 XCursorImage::XCursorImage(
const QString &theme,
const QString &file)
78 : xcursorImages(nullptr)
82 int preferredCursorHeightPx = 32;
84 xcursorImages = XcursorLibraryLoadImages(QFile::encodeName(file), QFile::encodeName(theme),
85 preferredCursorHeightPx);
92 if ( xcursorImages->nimage > 0) {
93 XcursorImage *xcursorImage = xcursorImages->images[0];
95 qimage = QImage((uchar*)xcursorImage->pixels,
96 xcursorImage->width, xcursorImage->height, QImage::Format_ARGB32);
98 hotspot.setX(xcursorImage->xhot);
99 hotspot.setY(xcursorImage->yhot);
103 XCursorImage::~XCursorImage()
105 XcursorImagesDestroy(xcursorImages);
111 CursorImageProvider::CursorImageProvider()
112 : QQuickImageProvider(QQuickImageProvider::Image)
115 qFatal(
"Cannot have multiple CursorImageProvider instances");
119 m_fallbackNames[QStringLiteral(
"closedhand")].append(QStringLiteral(
"grabbing"));
120 m_fallbackNames[QStringLiteral(
"closedhand")].append(QStringLiteral(
"dnd-none"));
122 m_fallbackNames[QStringLiteral(
"dnd-copy")].append(QStringLiteral(
"dnd-none"));
123 m_fallbackNames[QStringLiteral(
"dnd-copy")].append(QStringLiteral(
"grabbing"));
124 m_fallbackNames[QStringLiteral(
"dnd-copy")].append(QStringLiteral(
"closedhand"));
126 m_fallbackNames[QStringLiteral(
"dnd-move")].append(QStringLiteral(
"dnd-none"));
127 m_fallbackNames[QStringLiteral(
"dnd-move")].append(QStringLiteral(
"grabbing"));
128 m_fallbackNames[QStringLiteral(
"dnd-move")].append(QStringLiteral(
"closedhand"));
130 m_fallbackNames[QStringLiteral(
"dnd-link")].append(QStringLiteral(
"dnd-none"));
131 m_fallbackNames[QStringLiteral(
"dnd-link")].append(QStringLiteral(
"grabbing"));
132 m_fallbackNames[QStringLiteral(
"dnd-link")].append(QStringLiteral(
"closedhand"));
134 m_fallbackNames[QStringLiteral(
"forbidden")].append(QStringLiteral(
"crossed_circle"));
135 m_fallbackNames[QStringLiteral(
"forbidden")].append(QStringLiteral(
"not-allowed"));
136 m_fallbackNames[QStringLiteral(
"forbidden")].append(QStringLiteral(
"circle"));
138 m_fallbackNames[QStringLiteral(
"hand")].append(QStringLiteral(
"pointing_hand"));
139 m_fallbackNames[QStringLiteral(
"hand")].append(QStringLiteral(
"pointer"));
141 m_fallbackNames[QStringLiteral(
"ibeam")].append(QStringLiteral(
"xterm"));
142 m_fallbackNames[QStringLiteral(
"ibeam")].append(QStringLiteral(
"text"));
144 m_fallbackNames[QStringLiteral(
"left_ptr")].append(QStringLiteral(
"default"));
145 m_fallbackNames[QStringLiteral(
"left_ptr")].append(QStringLiteral(
"top_left_arrow"));
146 m_fallbackNames[QStringLiteral(
"left_ptr")].append(QStringLiteral(
"left_arrow"));
148 m_fallbackNames[QStringLiteral(
"left_ptr_watch")].append(QStringLiteral(
"half-busy"));
149 m_fallbackNames[QStringLiteral(
"left_ptr_watch")].append(QStringLiteral(
"progress"));
151 m_fallbackNames[QStringLiteral(
"size_bdiag")].append(QStringLiteral(
"fd_double_arrow"));
152 m_fallbackNames[QStringLiteral(
"size_bdiag")].append(QStringLiteral(
"nesw-resize"));
154 m_fallbackNames[QStringLiteral(
"size_fdiag")].append(QStringLiteral(
"bd_double_arrow"));
155 m_fallbackNames[QStringLiteral(
"size_fdiag")].append(QStringLiteral(
"nwse-resize"));
157 m_fallbackNames[QStringLiteral(
"size_hor")].append(QStringLiteral(
"sb_h_double_arrow"));
158 m_fallbackNames[QStringLiteral(
"size_hor")].append(QStringLiteral(
"ew-resize"));
159 m_fallbackNames[QStringLiteral(
"size_hor")].append(QStringLiteral(
"h_double_arrow"));
161 m_fallbackNames[QStringLiteral(
"size_ver")].append(QStringLiteral(
"sb_v_double_arrow"));
162 m_fallbackNames[QStringLiteral(
"size_ver")].append(QStringLiteral(
"ns-resize"));
163 m_fallbackNames[QStringLiteral(
"size_ver")].append(QStringLiteral(
"v_double_arrow"));
165 m_fallbackNames[QStringLiteral(
"split_h")].append(QStringLiteral(
"sb_h_double_arrow"));
166 m_fallbackNames[QStringLiteral(
"split_h")].append(QStringLiteral(
"col-resize"));
168 m_fallbackNames[QStringLiteral(
"split_v")].append(QStringLiteral(
"sb_v_double_arrow"));
169 m_fallbackNames[QStringLiteral(
"split_v")].append(QStringLiteral(
"row-resize"));
171 m_fallbackNames[QStringLiteral(
"up_arrow")].append(QStringLiteral(
"sb_up_arrow"));
173 m_fallbackNames[QStringLiteral(
"watch")].append(QStringLiteral(
"wait"));
175 m_fallbackNames[QStringLiteral(
"whats_this")].append(QStringLiteral(
"left_ptr_help"));
176 m_fallbackNames[QStringLiteral(
"whats_this")].append(QStringLiteral(
"help"));
177 m_fallbackNames[QStringLiteral(
"whats_this")].append(QStringLiteral(
"question_arrow"));
179 m_fallbackNames[QStringLiteral(
"xterm")].append(QStringLiteral(
"ibeam"));
182 CursorImageProvider::~CursorImageProvider()
185 QList< QMap<QString, CursorImage*> > cursorList = m_cursors.values();
187 for (
int i = 0; i < cursorList.count(); ++i) {
188 QList<CursorImage*> cursorImageList = cursorList[i].values();
189 for (
int j = 0; j < cursorImageList.count(); ++j) {
190 delete cursorImageList[j];
196 m_instance =
nullptr;
199 QImage CursorImageProvider::requestImage(
const QString &cursorThemeAndName, QSize *size,
const QSize & )
201 CursorImage *cursorImage = fetchCursor(cursorThemeAndName);
202 size->setWidth(cursorImage->qimage.width());
203 size->setHeight(cursorImage->qimage.height());
205 return cursorImage->qimage;
208 QPoint CursorImageProvider::hotspot(
const QString &themeName,
const QString &cursorName)
210 CursorImage *cursorImage = fetchCursor(themeName, cursorName);
212 return cursorImage->hotspot;
218 CursorImage *CursorImageProvider::fetchCursor(
const QString &cursorThemeAndName)
223 QStringList themeAndNameList = cursorThemeAndName.split(
'/');
224 if (themeAndNameList.size() != 2) {
227 themeName = themeAndNameList[0];
228 cursorName = themeAndNameList[1];
231 return fetchCursor(themeName, cursorName);
234 CursorImage *CursorImageProvider::fetchCursor(
const QString &themeName,
const QString &cursorName)
236 CursorImage *cursorImage = fetchCursorHelper(themeName, cursorName);
239 if (cursorImage->qimage.isNull()) {
240 if (m_fallbackNames.contains(cursorName)) {
241 const QStringList &fallbackNames = m_fallbackNames[cursorName];
243 while (cursorImage->qimage.isNull() && i < fallbackNames.count()) {
244 qDebug().nospace() <<
"CursorImageProvider: "<< cursorName <<
" not found, trying " << fallbackNames.at(i);
245 cursorImage = fetchCursorHelper(themeName, fallbackNames.at(i));
252 if (cursorImage->qimage.isNull() && cursorName != QLatin1String(
"left_ptr")) {
253 qDebug() <<
"CursorImageProvider:" << cursorName
254 <<
"not found (nor its fallbacks, if any). Going for \"left_ptr\" as a last resort.";
255 cursorImage = fetchCursorHelper(themeName, QStringLiteral(
"left_ptr"));
258 if (cursorImage->qimage.isNull()) {
260 qWarning() <<
"CursorImageProvider: couldn't find any cursors. Using the built-in one";
261 if (!m_builtInCursorImage) {
262 m_builtInCursorImage.reset(
new BuiltInCursorImage);
264 cursorImage = m_builtInCursorImage.data();
270 CursorImage *CursorImageProvider::fetchCursorHelper(
const QString &themeName,
const QString &cursorName)
272 if (cursorName == QLatin1String(
"blank")) {
273 return &m_blankCursorImage;
274 }
else if (cursorName == QLatin1String(
"custom")) {
275 return m_customCursorImage.data();
277 QMap<QString, CursorImage*> &themeCursors = m_cursors[themeName];
279 if (!themeCursors.contains(cursorName)) {
280 themeCursors[cursorName] =
new XCursorImage(themeName, cursorName);
283 return themeCursors[cursorName];
287 void CursorImageProvider::setCustomCursor(
const QCursor &customCursor)
289 if (customCursor.pixmap().isNull()) {
290 m_customCursorImage.reset();
292 m_customCursorImage.reset(
new CustomCursorImage(customCursor));