xcursortheme.cpp 3.02 KB
Newer Older
1
/*
Vlad Zahorodnii's avatar
Vlad Zahorodnii committed
2
3
4
5
    SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org>

    SPDX-License-Identifier: GPL-2.0-or-later
*/
6
7
8
9

#include "xcursortheme.h"
#include "3rdparty/xcursor.h"

10
11
12
#include <QMap>
#include <QSharedData>

13
14
15
namespace KWin
{

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class KXcursorSpritePrivate : public QSharedData
{
public:
    QImage data;
    QPoint hotspot;
    std::chrono::milliseconds delay;
};

class KXcursorThemePrivate : public QSharedData
{
public:
    QMap<QByteArray, QVector<KXcursorSprite>> registry;
    qreal devicePixelRatio = 1;
};

31
KXcursorSprite::KXcursorSprite()
32
33
34
35
36
37
38
39
40
41
42
43
44
45
    : d(new KXcursorSpritePrivate)
{
}

KXcursorSprite::KXcursorSprite(const KXcursorSprite &other)
    : d(other.d)
{
}

KXcursorSprite::~KXcursorSprite()
{
}

KXcursorSprite &KXcursorSprite::operator=(const KXcursorSprite &other)
46
{
47
48
    d = other.d;
    return *this;
49
50
51
52
}

KXcursorSprite::KXcursorSprite(const QImage &data, const QPoint &hotspot,
                               const std::chrono::milliseconds &delay)
53
    : d(new KXcursorSpritePrivate)
54
{
55
56
57
    d->data = data;
    d->hotspot = hotspot;
    d->delay = delay;
58
59
60
61
}

QImage KXcursorSprite::data() const
{
62
    return d->data;
63
64
65
66
}

QPoint KXcursorSprite::hotspot() const
{
67
    return d->hotspot;
68
69
70
71
}

std::chrono::milliseconds KXcursorSprite::delay() const
{
72
    return d->delay;
73
74
75
76
}

static void load_callback(XcursorImages *images, void *data)
{
77
    KXcursorThemePrivate *themePrivate = static_cast<KXcursorThemePrivate *>(data);
78
79
80
81
82
83
84
    QVector<KXcursorSprite> sprites;

    for (int i = 0; i < images->nimage; ++i) {
        const XcursorImage *nativeCursorImage = images->images[i];
        const QPoint hotspot(nativeCursorImage->xhot, nativeCursorImage->yhot);
        const std::chrono::milliseconds delay(nativeCursorImage->delay);

85
        QImage data(nativeCursorImage->width, nativeCursorImage->height, QImage::Format_ARGB32_Premultiplied);
86
87
        memcpy(data.bits(), nativeCursorImage->pixels, data.sizeInBytes());

88
        sprites.append(KXcursorSprite(data, hotspot / themePrivate->devicePixelRatio, delay));
89
90
    }

91
    themePrivate->registry.insert(images->name, sprites);
92
93
94
    XcursorImagesDestroy(images);
}

95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
KXcursorTheme::KXcursorTheme()
    : d(new KXcursorThemePrivate)
{
}

KXcursorTheme::KXcursorTheme(const KXcursorTheme &other)
    : d(other.d)
{
}

KXcursorTheme::~KXcursorTheme()
{
}

KXcursorTheme &KXcursorTheme::operator=(const KXcursorTheme &other)
{
    d = other.d;
    return *this;
}

115
116
qreal KXcursorTheme::devicePixelRatio() const
{
117
    return d->devicePixelRatio;
118
119
120
121
}

bool KXcursorTheme::isEmpty() const
{
122
    return d->registry.isEmpty();
123
124
125
126
}

QVector<KXcursorSprite> KXcursorTheme::shape(const QByteArray &name) const
{
127
    return d->registry.value(name);
128
129
130
131
132
}

KXcursorTheme KXcursorTheme::fromTheme(const QString &themeName, int size, qreal dpr)
{
    KXcursorTheme theme;
133
134
    KXcursorThemePrivate *themePrivate = theme.d;
    themePrivate->devicePixelRatio = dpr;
135
136

    const QByteArray nativeThemeName = themeName.toUtf8();
137
    xcursor_load_theme(nativeThemeName, size * dpr, load_callback, themePrivate);
138
139
140
141
142

    return theme;
}

} // namespace KWin