Changeset View
Changeset View
Standalone View
Standalone View
kcms/cursortheme/xcursor/xcursortheme.cpp
Show All 15 Lines | |||||
16 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 16 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
17 | * Boston, MA 02110-1301, USA. | 17 | * Boston, MA 02110-1301, USA. | ||
18 | */ | 18 | */ | ||
19 | 19 | | |||
20 | #include <KLocalizedString> | 20 | #include <KLocalizedString> | ||
21 | #include <KConfig> | 21 | #include <KConfig> | ||
22 | #include <KConfigGroup> | 22 | #include <KConfigGroup> | ||
23 | 23 | | |||
24 | #include <QGuiApplication> | | |||
25 | #include <QScreen> | | |||
26 | #include <QCursor> | 24 | #include <QCursor> | ||
27 | #include <QImage> | 25 | #include <QImage> | ||
28 | #include <QDir> | 26 | #include <QDir> | ||
29 | #include <QX11Info> | 27 | #include <QX11Info> | ||
30 | 28 | | |||
31 | #include <X11/Xlib.h> | 29 | #include <X11/Xlib.h> | ||
32 | #include <X11/Xcursor/Xcursor.h> | 30 | #include <X11/Xcursor/Xcursor.h> | ||
33 | 31 | | |||
34 | #include <KWindowSystem/fixx11h.h> | | |||
35 | #include "xcursortheme.h" | 32 | #include "xcursortheme.h" | ||
36 | 33 | | |||
37 | 34 | | |||
38 | // Static variable holding alternative names for some cursors | 35 | // Static variable holding alternative names for some cursors | ||
39 | QHash<QString, QString> XCursorTheme::alternatives; | 36 | QHash<QString, QString> XCursorTheme::alternatives; | ||
40 | 37 | | |||
41 | XCursorTheme::XCursorTheme(const QDir &themeDir) | 38 | XCursorTheme::XCursorTheme(const QDir &themeDir) | ||
42 | : CursorTheme(themeDir.dirName()) | 39 | : CursorTheme(themeDir.dirName()) | ||
43 | { | 40 | { | ||
44 | // Directory information | 41 | // Directory information | ||
45 | setName(themeDir.dirName()); | 42 | setName(themeDir.dirName()); | ||
46 | setPath(themeDir.path()); | 43 | setPath(themeDir.path()); | ||
47 | setIsWritable(QFileInfo(themeDir.path()).isWritable()); // ### perhaps this shouldn't be cached | 44 | setIsWritable(QFileInfo(themeDir.path()).isWritable()); // ### perhaps this shouldn't be cached | ||
48 | 45 | | |||
49 | if (themeDir.exists(QStringLiteral("index.theme"))) | 46 | if (themeDir.exists("index.theme")) | ||
50 | parseIndexFile(); | 47 | parseIndexFile(); | ||
51 | 48 | | |||
52 | QString cursorFile = path() + "/cursors/left_ptr"; | 49 | QString cursorFile = path() + "/cursors/left_ptr"; | ||
53 | QList<int> sizeList; | 50 | QList<int> sizeList; | ||
54 | XcursorImages *images = XcursorFilenameLoadAllImages(qPrintable(cursorFile)); | 51 | XcursorImages *images = XcursorFilenameLoadAllImages(qPrintable(cursorFile)); | ||
55 | if (images) | 52 | if (images) | ||
56 | { | 53 | { | ||
57 | for (int i = 0; i < images->nimage; ++i) | 54 | for (int i = 0; i < images->nimage; ++i) | ||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Line(s) | 98 | { | |||
102 | if (alternatives.isEmpty()) | 99 | if (alternatives.isEmpty()) | ||
103 | { | 100 | { | ||
104 | alternatives.reserve(18); | 101 | alternatives.reserve(18); | ||
105 | 102 | | |||
106 | // Qt uses non-standard names for some core cursors. | 103 | // Qt uses non-standard names for some core cursors. | ||
107 | // If Xcursor fails to load the cursor, Qt creates it with the correct name using the | 104 | // If Xcursor fails to load the cursor, Qt creates it with the correct name using the | ||
108 | // core protcol instead (which in turn calls Xcursor). We emulate that process here. | 105 | // core protcol instead (which in turn calls Xcursor). We emulate that process here. | ||
109 | // Note that there's a core cursor called cross, but it's not the one Qt expects. | 106 | // Note that there's a core cursor called cross, but it's not the one Qt expects. | ||
110 | alternatives.insert(QStringLiteral("cross"), QStringLiteral("crosshair")); | 107 | alternatives.insert("cross", "crosshair"); | ||
111 | alternatives.insert(QStringLiteral("up_arrow"), QStringLiteral("center_ptr")); | 108 | alternatives.insert("up_arrow", "center_ptr"); | ||
112 | alternatives.insert(QStringLiteral("wait"), QStringLiteral("watch")); | 109 | alternatives.insert("wait", "watch"); | ||
113 | alternatives.insert(QStringLiteral("ibeam"), QStringLiteral("xterm")); | 110 | alternatives.insert("ibeam", "xterm"); | ||
114 | alternatives.insert(QStringLiteral("size_all"), QStringLiteral("fleur")); | 111 | alternatives.insert("size_all", "fleur"); | ||
115 | alternatives.insert(QStringLiteral("pointing_hand"), QStringLiteral("hand2")); | 112 | alternatives.insert("pointing_hand", "hand2"); | ||
116 | 113 | | |||
117 | // Precomputed MD5 hashes for the hardcoded bitmap cursors in Qt and KDE. | 114 | // Precomputed MD5 hashes for the hardcoded bitmap cursors in Qt and KDE. | ||
118 | // Note that the MD5 hash for left_ptr_watch is for the KDE version of that cursor. | 115 | // Note that the MD5 hash for left_ptr_watch is for the KDE version of that cursor. | ||
119 | alternatives.insert(QStringLiteral("size_ver"), QStringLiteral("00008160000006810000408080010102")); | 116 | alternatives.insert("size_ver", "00008160000006810000408080010102"); | ||
120 | alternatives.insert(QStringLiteral("size_hor"), QStringLiteral("028006030e0e7ebffc7f7070c0600140")); | 117 | alternatives.insert("size_hor", "028006030e0e7ebffc7f7070c0600140"); | ||
121 | alternatives.insert(QStringLiteral("size_bdiag"), QStringLiteral("fcf1c3c7cd4491d801f1e1c78f100000")); | 118 | alternatives.insert("size_bdiag", "fcf1c3c7cd4491d801f1e1c78f100000"); | ||
122 | alternatives.insert(QStringLiteral("size_fdiag"), QStringLiteral("c7088f0f3e6c8088236ef8e1e3e70000")); | 119 | alternatives.insert("size_fdiag", "c7088f0f3e6c8088236ef8e1e3e70000"); | ||
123 | alternatives.insert(QStringLiteral("whats_this"), QStringLiteral("d9ce0ab605698f320427677b458ad60b")); | 120 | alternatives.insert("whats_this", "d9ce0ab605698f320427677b458ad60b"); | ||
124 | alternatives.insert(QStringLiteral("split_h"), QStringLiteral("14fef782d02440884392942c11205230")); | 121 | alternatives.insert("split_h", "14fef782d02440884392942c11205230"); | ||
125 | alternatives.insert(QStringLiteral("split_v"), QStringLiteral("2870a09082c103050810ffdffffe0204")); | 122 | alternatives.insert("split_v", "2870a09082c103050810ffdffffe0204"); | ||
126 | alternatives.insert(QStringLiteral("forbidden"), QStringLiteral("03b6e0fcb3499374a867c041f52298f0")); | 123 | alternatives.insert("forbidden", "03b6e0fcb3499374a867c041f52298f0"); | ||
127 | alternatives.insert(QStringLiteral("left_ptr_watch"), QStringLiteral("3ecb610c1bf2410f44200f48c40d3599")); | 124 | alternatives.insert("left_ptr_watch", "3ecb610c1bf2410f44200f48c40d3599"); | ||
128 | alternatives.insert(QStringLiteral("hand2"), QStringLiteral("e29285e634086352946a0e7090d73106")); | 125 | alternatives.insert("hand2", "e29285e634086352946a0e7090d73106"); | ||
129 | alternatives.insert(QStringLiteral("openhand"), QStringLiteral("9141b49c8149039304290b508d208c40")); | 126 | alternatives.insert("openhand", "9141b49c8149039304290b508d208c40"); | ||
130 | alternatives.insert(QStringLiteral("closedhand"), QStringLiteral("05e88622050804100c20044008402080")); | 127 | alternatives.insert("closedhand", "05e88622050804100c20044008402080"); | ||
131 | } | 128 | } | ||
132 | 129 | | |||
133 | return alternatives.value(name, QString()); | 130 | return alternatives.value(name, QString()); | ||
134 | } | 131 | } | ||
135 | 132 | | |||
136 | 133 | | |||
137 | XcursorImage *XCursorTheme::xcLoadImage(const QString &image, int size) const | 134 | XcursorImage *XCursorTheme::xcLoadImage(const QString &image, int size) const | ||
138 | { | 135 | { | ||
139 | QByteArray cursorName = QFile::encodeName(image); | 136 | QByteArray cursorName = QFile::encodeName(image); | ||
140 | QByteArray themeName = QFile::encodeName(name()); | 137 | QByteArray themeName = QFile::encodeName(name()); | ||
141 | 138 | | |||
142 | return XcursorLibraryLoadImage(cursorName, themeName, size); | 139 | return XcursorLibraryLoadImage(cursorName, themeName, size); | ||
143 | } | 140 | } | ||
144 | 141 | | |||
145 | 142 | | |||
146 | XcursorImages *XCursorTheme::xcLoadImages(const QString &image, int size) const | 143 | XcursorImages *XCursorTheme::xcLoadImages(const QString &image, int size) const | ||
147 | { | 144 | { | ||
148 | QByteArray cursorName = QFile::encodeName(image); | 145 | QByteArray cursorName = QFile::encodeName(image); | ||
149 | QByteArray themeName = QFile::encodeName(name()); | 146 | QByteArray themeName = QFile::encodeName(name()); | ||
150 | 147 | | |||
151 | return XcursorLibraryLoadImages(cursorName, themeName, size); | 148 | return XcursorLibraryLoadImages(cursorName, themeName, size); | ||
152 | } | 149 | } | ||
153 | 150 | | |||
154 | 151 | | |||
155 | int XCursorTheme::autodetectCursorSize() const | 152 | int XCursorTheme::defaultCursorSize() const | ||
156 | { | 153 | { | ||
157 | if (!QX11Info::isPlatformX11()) { | | |||
158 | if (QScreen *s = QGuiApplication::primaryScreen()) { | | |||
159 | return s->logicalDotsPerInchY() * 16 / 72; | | |||
160 | } | | |||
161 | // some default value | | |||
162 | return 16; | | |||
163 | } | | |||
164 | /* This code is basically borrowed from display.c of the XCursor library | 154 | /* This code is basically borrowed from display.c of the XCursor library | ||
165 | We can't use "int XcursorGetDefaultSize(Display *dpy)" because if | 155 | We can't use "int XcursorGetDefaultSize(Display *dpy)" because if | ||
166 | previously the cursor size was set to a custom value, it would return | 156 | previously the cursor size was set to a custom value, it would return | ||
167 | this custom value. */ | 157 | this custom value. */ | ||
168 | int size = 0; | 158 | int size = 0; | ||
169 | int dpi = 0; | 159 | int dpi = 0; | ||
170 | Display *dpy = QX11Info::display(); | 160 | Display *dpy = QX11Info::display(); | ||
171 | // The string "v" is owned and will be destroyed by Xlib | 161 | // The string "v" is owned and will be destroyed by Xlib | ||
Show All 15 Lines | 168 | { | |||
187 | size = dim / 48; | 177 | size = dim / 48; | ||
188 | } | 178 | } | ||
189 | return size; | 179 | return size; | ||
190 | } | 180 | } | ||
191 | 181 | | |||
192 | qulonglong XCursorTheme::loadCursor(const QString &name, int size) const | 182 | qulonglong XCursorTheme::loadCursor(const QString &name, int size) const | ||
193 | { | 183 | { | ||
194 | if (size <= 0) | 184 | if (size <= 0) | ||
195 | size = autodetectCursorSize(); | 185 | size = defaultCursorSize(); | ||
196 | 186 | | |||
197 | // Load the cursor images | 187 | // Load the cursor images | ||
198 | XcursorImages *images = xcLoadImages(name, size); | 188 | XcursorImages *images = xcLoadImages(name, size); | ||
199 | 189 | | |||
200 | if (!images) | 190 | if (!images) | ||
201 | images = xcLoadImages(findAlternative(name), size); | 191 | images = xcLoadImages(findAlternative(name), size); | ||
202 | 192 | | |||
203 | if (!images) | 193 | if (!images) | ||
204 | return None; | 194 | return None; | ||
205 | 195 | | |||
206 | // Create the cursor | 196 | // Create the cursor | ||
207 | Cursor handle = XcursorImagesLoadCursor(QX11Info::display(), images); | 197 | Cursor handle = XcursorImagesLoadCursor(QX11Info::display(), images); | ||
208 | XcursorImagesDestroy(images); | 198 | XcursorImagesDestroy(images); | ||
209 | 199 | | |||
210 | setCursorName(handle, name); | 200 | setCursorName(handle, name); | ||
211 | return handle; | 201 | return handle; | ||
212 | } | 202 | } | ||
213 | 203 | | |||
214 | 204 | | |||
215 | QImage XCursorTheme::loadImage(const QString &name, int size) const | 205 | QImage XCursorTheme::loadImage(const QString &name, int size) const | ||
216 | { | 206 | { | ||
217 | if (size <= 0) | 207 | if (size <= 0) | ||
218 | size = autodetectCursorSize(); | 208 | size = defaultCursorSize(); | ||
219 | 209 | | |||
220 | // Load the image | 210 | // Load the image | ||
221 | XcursorImage *xcimage = xcLoadImage(name, size); | 211 | XcursorImage *xcimage = xcLoadImage(name, size); | ||
222 | 212 | | |||
223 | if (!xcimage) | 213 | if (!xcimage) | ||
224 | xcimage = xcLoadImage(findAlternative(name), size); | 214 | xcimage = xcLoadImage(findAlternative(name), size); | ||
225 | 215 | | |||
226 | if (!xcimage) { | 216 | if (!xcimage) { | ||
Show All 13 Lines |