/* * Copyright (C) 2015 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License version 3, as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include "CursorImageProvider.h" #include #include #include #include CursorImageProvider *CursorImageProvider::m_instance = nullptr; ///// // BuiltInCursorImage BuiltInCursorImage::BuiltInCursorImage() { const char *svgString = "" "" " " ""; qimage = QImage(20, 32, QImage::Format_ARGB32); QPainter imagePainter(&qimage); QSvgRenderer *svgRenderer = new QSvgRenderer(QByteArray(svgString)); svgRenderer->render(&imagePainter); delete svgRenderer; } ///// // XCursorImage XCursorImage::XCursorImage(const QString &theme, const QString &file) : xcursorImages(nullptr) { xcursorImages = XcursorLibraryLoadImages(QFile::encodeName(file), QFile::encodeName(theme), 32); if (!xcursorImages) { return; } bool loaded = false; for (int i = 0; i < xcursorImages->nimage && !loaded; ++i) { XcursorImage *xcursorImage = xcursorImages->images[i]; if (xcursorImage->size == 32) { qimage = QImage((uchar*)xcursorImage->pixels, xcursorImage->width, xcursorImage->height, QImage::Format_ARGB32); hotspot.setX(xcursorImage->xhot); hotspot.setY(xcursorImage->yhot); loaded = true; } } } XCursorImage::~XCursorImage() { XcursorImagesDestroy(xcursorImages); } ///// // CursorImageProvider CursorImageProvider::CursorImageProvider() : QQuickImageProvider(QQuickImageProvider::Image) { if (m_instance) { qFatal("Cannot have multiple CursorImageProvider instances"); } m_instance = this; } CursorImageProvider::~CursorImageProvider() { { QList< QMap > cursorList = m_cursors.values(); for (int i = 0; i < cursorList.count(); ++i) { QList cursorImageList = cursorList[i].values(); for (int j = 0; j < cursorImageList.count(); ++j) { delete cursorImageList[j]; } } } m_cursors.clear(); m_instance = nullptr; } QImage CursorImageProvider::requestImage(const QString &cursorThemeAndName, QSize *size, const QSize & /*requestedSize*/) { CursorImage *cursorImage = fetchCursor(cursorThemeAndName); size->setWidth(cursorImage->qimage.width()); size->setHeight(cursorImage->qimage.height()); return cursorImage->qimage; } QPoint CursorImageProvider::hotspot(const QString &themeName, const QString &cursorName) { CursorImage *cursorImage = fetchCursor(themeName, cursorName); if (cursorImage) { return cursorImage->hotspot; } else { return QPoint(0,0); } } CursorImage *CursorImageProvider::fetchCursor(const QString &cursorThemeAndName) { QString themeName; QString cursorName; { QStringList themeAndNameList = cursorThemeAndName.split("/"); if (themeAndNameList.size() != 2) { return nullptr; } themeName = themeAndNameList[0]; cursorName = themeAndNameList[1]; } return fetchCursor(themeName, cursorName); } CursorImage *CursorImageProvider::fetchCursor(const QString &themeName, const QString &cursorName) { CursorImage *cursorImage = fetchCursorHelper(themeName, cursorName); // Try some fallbacks if (cursorImage->qimage.isNull()) { if (cursorName == "ibeam") { qDebug() << "CursorImageProvider: \"ibeam\" not found, falling back to \"xterm\""; cursorImage = fetchCursorHelper(themeName, "xterm"); } else if (cursorName == "xterm") { qDebug() << "CursorImageProvider: \"xterm\" not found, falling back to \"ibeam\""; cursorImage = fetchCursorHelper(themeName, "ibeam"); } } // if it all fails, there must be at least a left_ptr if (cursorImage->qimage.isNull() && cursorName != "left_ptr") { qDebug() << "CursorImageProvider:" << cursorName << "not found (nor its fallbacks, if any). Going for \"left_ptr\" as a last resort."; cursorImage = fetchCursorHelper(themeName, "left_ptr"); } if (cursorImage->qimage.isNull()) { // finally, go for the built-in cursor qWarning() << "CursorImageProvider: couldn't find any cursors. Using the built-in one"; if (!m_builtInCursorImage) { m_builtInCursorImage.reset(new BuiltInCursorImage); } cursorImage = m_builtInCursorImage.data(); } return cursorImage; } CursorImage *CursorImageProvider::fetchCursorHelper(const QString &themeName, const QString &cursorName) { QMap &themeCursors = m_cursors[themeName]; if (!themeCursors.contains(cursorName)) { themeCursors[cursorName] = new XCursorImage(themeName, cursorName); } return themeCursors[cursorName]; }