~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to kcontrol/input/xcursor/xcursortheme.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright © 2006-2007 Fredrik Höglund <fredrik@kde.org>
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU General Public
 
6
 * License version 2 or at your option version 3 as published 
 
7
 * by the Free Software Foundation.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 * General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; see the file COPYING.  If not, write to
 
16
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
17
 * Boston, MA 02110-1301, USA.
 
18
 */
 
19
 
 
20
#include <KLocale>
 
21
#include <KConfig>
 
22
#include <KConfigGroup>
 
23
 
 
24
#include <QCursor>
 
25
#include <QImage>
 
26
#include <QDir>
 
27
#include <QX11Info>
 
28
 
 
29
#include <X11/Xlib.h>
 
30
#include <X11/Xcursor/Xcursor.h>
 
31
 
 
32
#include "xcursortheme.h"
 
33
 
 
34
 
 
35
// Static variable holding alternative names for some cursors
 
36
QHash<QString, QString> XCursorTheme::alternatives;
 
37
 
 
38
XCursorTheme::XCursorTheme(const QDir &themeDir)
 
39
    : LegacyTheme(themeDir.dirName(), i18n("No description available"))
 
40
{
 
41
    // Directory information
 
42
    setName(themeDir.dirName());
 
43
    setPath(themeDir.path());
 
44
    setIsWritable(QFileInfo(themeDir.path()).isWritable()); // ### perhaps this shouldn't be cached
 
45
 
 
46
    if (themeDir.exists("index.theme"))
 
47
        parseIndexFile();
 
48
}
 
49
 
 
50
 
 
51
void XCursorTheme::parseIndexFile()
 
52
{
 
53
    KConfig config(path() + "/index.theme", KConfig::NoGlobals);
 
54
    KConfigGroup cg(&config, "Icon Theme");
 
55
 
 
56
    m_title       = cg.readEntry("Name",     m_title);
 
57
    m_description = cg.readEntry("Comment",  m_description);
 
58
    m_sample      = cg.readEntry("Example",  m_sample);
 
59
    m_hidden      = cg.readEntry("Hidden",   false);
 
60
    m_inherits    = cg.readEntry("Inherits", QStringList());
 
61
}
 
62
 
 
63
 
 
64
QString XCursorTheme::findAlternative(const QString &name) const
 
65
{
 
66
    if (alternatives.isEmpty())
 
67
    {
 
68
        alternatives.reserve(18);
 
69
 
 
70
        // Qt uses non-standard names for some core cursors.
 
71
        // If Xcursor fails to load the cursor, Qt creates it with the correct name using the
 
72
        // core protcol instead (which in turn calls Xcursor). We emulate that process here.
 
73
        // Note that there's a core cursor called cross, but it's not the one Qt expects.
 
74
        alternatives.insert("cross",          "crosshair");
 
75
        alternatives.insert("up_arrow",       "center_ptr");
 
76
        alternatives.insert("wait",           "watch");
 
77
        alternatives.insert("ibeam",          "xterm");
 
78
        alternatives.insert("size_all",       "fleur");
 
79
        alternatives.insert("pointing_hand",  "hand2");
 
80
 
 
81
        // Precomputed MD5 hashes for the hardcoded bitmap cursors in Qt and KDE.
 
82
        // Note that the MD5 hash for left_ptr_watch is for the KDE version of that cursor.
 
83
        alternatives.insert("size_ver",       "00008160000006810000408080010102");
 
84
        alternatives.insert("size_hor",       "028006030e0e7ebffc7f7070c0600140");
 
85
        alternatives.insert("size_bdiag",     "c7088f0f3e6c8088236ef8e1e3e70000");
 
86
        alternatives.insert("size_fdiag",     "fcf1c3c7cd4491d801f1e1c78f100000");
 
87
        alternatives.insert("whats_this",     "d9ce0ab605698f320427677b458ad60b");
 
88
        alternatives.insert("split_h",        "14fef782d02440884392942c11205230");
 
89
        alternatives.insert("split_v",        "2870a09082c103050810ffdffffe0204");
 
90
        alternatives.insert("forbidden",      "03b6e0fcb3499374a867c041f52298f0");
 
91
        alternatives.insert("left_ptr_watch", "3ecb610c1bf2410f44200f48c40d3599");
 
92
        alternatives.insert("hand2",          "e29285e634086352946a0e7090d73106");
 
93
        alternatives.insert("openhand",       "9141b49c8149039304290b508d208c40");
 
94
        alternatives.insert("closedhand",     "05e88622050804100c20044008402080");
 
95
    }
 
96
 
 
97
    return alternatives.value(name, QString());
 
98
}
 
99
 
 
100
 
 
101
XcursorImage *XCursorTheme::xcLoadImage(const QString &image, int size) const
 
102
{
 
103
    QByteArray cursorName = QFile::encodeName(image);
 
104
    QByteArray themeName  = QFile::encodeName(name());
 
105
 
 
106
    return XcursorLibraryLoadImage(cursorName, themeName, size);
 
107
}
 
108
 
 
109
 
 
110
XcursorImages *XCursorTheme::xcLoadImages(const QString &image, int size) const
 
111
{
 
112
    QByteArray cursorName = QFile::encodeName(image);
 
113
    QByteArray themeName  = QFile::encodeName(name());
 
114
 
 
115
    return XcursorLibraryLoadImages(cursorName, themeName, size);
 
116
}
 
117
 
 
118
 
 
119
QCursor XCursorTheme::loadCursor(const QString &name, int size) const
 
120
{
 
121
    if (size == -1)
 
122
        size = XcursorGetDefaultSize(QX11Info::display());
 
123
 
 
124
    // Load the cursor images
 
125
    XcursorImages *images = xcLoadImages(name, size);
 
126
 
 
127
    if (!images)
 
128
        images = xcLoadImages(findAlternative(name), size);
 
129
 
 
130
    // Fall back to a legacy cursor
 
131
    if (!images)
 
132
        return LegacyTheme::loadCursor(name);
 
133
 
 
134
    // Create the cursor
 
135
    Cursor handle = XcursorImagesLoadCursor(QX11Info::display(), images);
 
136
    QCursor cursor = QCursor(Qt::HANDLE(handle)); // QCursor takes ownership of the handle
 
137
    XcursorImagesDestroy(images);
 
138
 
 
139
    setCursorName(cursor, name);
 
140
    return cursor;
 
141
}
 
142
 
 
143
 
 
144
QImage XCursorTheme::loadImage(const QString &name, int size) const
 
145
{
 
146
    if (size == -1)
 
147
        size = XcursorGetDefaultSize(QX11Info::display());
 
148
 
 
149
    // Load the image
 
150
    XcursorImage *xcimage = xcLoadImage(name, size);
 
151
 
 
152
    if (!xcimage)
 
153
        xcimage = xcLoadImage(findAlternative(name), size);
 
154
 
 
155
    // Fall back to a legacy cursor
 
156
    if (!xcimage)
 
157
        return LegacyTheme::loadImage(name);
 
158
 
 
159
    // Convert the XcursorImage to a QImage, and auto-crop it
 
160
    QImage image((uchar *)xcimage->pixels, xcimage->width, xcimage->height,
 
161
                 QImage::Format_ARGB32_Premultiplied );
 
162
 
 
163
    image = autoCropImage(image);
 
164
    XcursorImageDestroy(xcimage);
 
165
 
 
166
    return image;
 
167
}
 
168