plugins/shakecursor: Display default cursor shape
At the moment, the shake cursor respects the current cursor shape. But there are couple of drawbacks behind doing it: the first is that it's very likely that the cursor pixmap has low resolution, the second is the cursor can be hidden client-side. This change makes the shake cursor plugin load the Xcursor theme with a high enough size and display the default cursor shape regardless of what the client has set in order to address the two aforementioned issues.
This commit is contained in:
parent
6a2bc79dae
commit
28b396f44c
4 changed files with 105 additions and 11 deletions
|
@ -6,16 +6,39 @@
|
|||
|
||||
#include "plugins/shakecursor/shakecursor.h"
|
||||
#include "cursor.h"
|
||||
#include "cursorsource.h"
|
||||
#include "effect/effecthandler.h"
|
||||
#include "input_event.h"
|
||||
#include "plugins/shakecursor/shakecursorconfig.h"
|
||||
#include "pointer_input.h"
|
||||
#include "scene/cursoritem.h"
|
||||
#include "scene/imageitem.h"
|
||||
#include "scene/itemrenderer.h"
|
||||
#include "scene/workspacescene.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
ShakeCursorItem::ShakeCursorItem(const KXcursorTheme &theme, Item *parent)
|
||||
: Item(parent)
|
||||
{
|
||||
m_source = std::make_unique<ShapeCursorSource>();
|
||||
m_source->setTheme(theme);
|
||||
m_source->setShape(Qt::ArrowCursor);
|
||||
|
||||
refresh();
|
||||
connect(m_source.get(), &CursorSource::changed, this, &ShakeCursorItem::refresh);
|
||||
}
|
||||
|
||||
void ShakeCursorItem::refresh()
|
||||
{
|
||||
if (!m_imageItem) {
|
||||
m_imageItem = scene()->renderer()->createImageItem(this);
|
||||
}
|
||||
m_imageItem->setImage(m_source->image());
|
||||
m_imageItem->setPosition(-m_source->hotspot());
|
||||
m_imageItem->setSize(m_source->image().deviceIndependentSize());
|
||||
}
|
||||
|
||||
ShakeCursorEffect::ShakeCursorEffect()
|
||||
: m_cursor(Cursors::self()->mouse())
|
||||
{
|
||||
|
@ -121,7 +144,12 @@ void ShakeCursorEffect::magnify(qreal magnification)
|
|||
if (!m_cursorItem) {
|
||||
effects->hideCursor();
|
||||
|
||||
m_cursorItem = std::make_unique<CursorItem>(effects->scene()->overlayItem());
|
||||
const qreal maxScale = ShakeCursorConfig::magnification() + 4 * ShakeCursorConfig::overMagnification();
|
||||
if (m_cursorTheme.name() != m_cursor->themeName() || m_cursorTheme.size() != m_cursor->themeSize() || m_cursorTheme.devicePixelRatio() != maxScale) {
|
||||
m_cursorTheme = KXcursorTheme(m_cursor->themeName(), m_cursor->themeSize(), maxScale);
|
||||
}
|
||||
|
||||
m_cursorItem = std::make_unique<ShakeCursorItem>(m_cursorTheme, effects->scene()->overlayItem());
|
||||
m_cursorItem->setPosition(m_cursor->pos());
|
||||
connect(m_cursor, &Cursor::posChanged, m_cursorItem.get(), [this]() {
|
||||
m_cursorItem->setPosition(m_cursor->pos());
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include "effect/effect.h"
|
||||
#include "input_event_spy.h"
|
||||
#include "plugins/shakecursor/shakedetector.h"
|
||||
#include "scene/cursoritem.h"
|
||||
#include "utils/xcursortheme.h"
|
||||
|
||||
#include <QTimer>
|
||||
#include <QVariantAnimation>
|
||||
|
@ -18,6 +20,21 @@ namespace KWin
|
|||
|
||||
class Cursor;
|
||||
class CursorItem;
|
||||
class ShapeCursorSource;
|
||||
|
||||
class ShakeCursorItem : public Item
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ShakeCursorItem(const KXcursorTheme &theme, Item *parent);
|
||||
|
||||
private:
|
||||
void refresh();
|
||||
|
||||
std::unique_ptr<ImageItem> m_imageItem;
|
||||
std::unique_ptr<ShapeCursorSource> m_source;
|
||||
};
|
||||
|
||||
class ShakeCursorEffect : public Effect, public InputEventSpy
|
||||
{
|
||||
|
@ -45,7 +62,8 @@ private:
|
|||
ShakeDetector m_shakeDetector;
|
||||
|
||||
Cursor *m_cursor;
|
||||
std::unique_ptr<CursorItem> m_cursorItem;
|
||||
std::unique_ptr<ShakeCursorItem> m_cursorItem;
|
||||
KXcursorTheme m_cursorTheme;
|
||||
qreal m_targetMagnification = 1.0;
|
||||
qreal m_currentMagnification = 1.0;
|
||||
};
|
||||
|
|
|
@ -31,8 +31,15 @@ public:
|
|||
class KXcursorThemePrivate : public QSharedData
|
||||
{
|
||||
public:
|
||||
void load(const QString &themeName, int size, qreal devicePixelRatio);
|
||||
void loadCursors(const QString &packagePath, int size, qreal devicePixelRatio);
|
||||
KXcursorThemePrivate();
|
||||
KXcursorThemePrivate(const QString &themeName, int size, qreal devicePixelRatio);
|
||||
|
||||
void load();
|
||||
void loadCursors(const QString &packagePath);
|
||||
|
||||
QString name;
|
||||
int size = 0;
|
||||
qreal devicePixelRatio = 0;
|
||||
|
||||
QHash<QByteArray, QList<KXcursorSprite>> registry;
|
||||
};
|
||||
|
@ -81,6 +88,17 @@ std::chrono::milliseconds KXcursorSprite::delay() const
|
|||
return d->delay;
|
||||
}
|
||||
|
||||
KXcursorThemePrivate::KXcursorThemePrivate()
|
||||
{
|
||||
}
|
||||
|
||||
KXcursorThemePrivate::KXcursorThemePrivate(const QString &themeName, int size, qreal devicePixelRatio)
|
||||
: name(themeName)
|
||||
, size(size)
|
||||
, devicePixelRatio(devicePixelRatio)
|
||||
{
|
||||
}
|
||||
|
||||
static QList<KXcursorSprite> loadCursor(const QString &filePath, int desiredSize, qreal devicePixelRatio)
|
||||
{
|
||||
QFile file(filePath);
|
||||
|
@ -127,7 +145,7 @@ static QList<KXcursorSprite> loadCursor(const QString &filePath, int desiredSize
|
|||
return sprites;
|
||||
}
|
||||
|
||||
void KXcursorThemePrivate::loadCursors(const QString &packagePath, int size, qreal devicePixelRatio)
|
||||
void KXcursorThemePrivate::loadCursors(const QString &packagePath)
|
||||
{
|
||||
const QDir dir(packagePath);
|
||||
QFileInfoList entries = dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot);
|
||||
|
@ -177,14 +195,14 @@ static QStringList searchPaths()
|
|||
return paths;
|
||||
}
|
||||
|
||||
void KXcursorThemePrivate::load(const QString &themeName, int size, qreal devicePixelRatio)
|
||||
void KXcursorThemePrivate::load()
|
||||
{
|
||||
const QStringList paths = searchPaths();
|
||||
|
||||
QStack<QString> stack;
|
||||
QSet<QString> loaded;
|
||||
|
||||
stack.push(themeName);
|
||||
stack.push(name);
|
||||
|
||||
while (!stack.isEmpty()) {
|
||||
const QString themeName = stack.pop();
|
||||
|
@ -199,7 +217,7 @@ void KXcursorThemePrivate::load(const QString &themeName, int size, qreal device
|
|||
if (!dir.exists()) {
|
||||
continue;
|
||||
}
|
||||
loadCursors(dir.filePath(QStringLiteral("cursors")), size, devicePixelRatio);
|
||||
loadCursors(dir.filePath(QStringLiteral("cursors")));
|
||||
if (inherits.isEmpty()) {
|
||||
const KConfig config(dir.filePath(QStringLiteral("index.theme")), KConfig::NoGlobals);
|
||||
inherits << KConfigGroup(&config, QStringLiteral("Icon Theme")).readEntry("Inherits", QStringList());
|
||||
|
@ -219,9 +237,9 @@ KXcursorTheme::KXcursorTheme()
|
|||
}
|
||||
|
||||
KXcursorTheme::KXcursorTheme(const QString &themeName, int size, qreal devicePixelRatio)
|
||||
: d(new KXcursorThemePrivate)
|
||||
: d(new KXcursorThemePrivate(themeName, size, devicePixelRatio))
|
||||
{
|
||||
d->load(themeName, size, devicePixelRatio);
|
||||
d->load();
|
||||
}
|
||||
|
||||
KXcursorTheme::KXcursorTheme(const KXcursorTheme &other)
|
||||
|
@ -249,6 +267,21 @@ bool KXcursorTheme::operator!=(const KXcursorTheme &other)
|
|||
return !(*this == other);
|
||||
}
|
||||
|
||||
QString KXcursorTheme::name() const
|
||||
{
|
||||
return d->name;
|
||||
}
|
||||
|
||||
int KXcursorTheme::size() const
|
||||
{
|
||||
return d->size;
|
||||
}
|
||||
|
||||
qreal KXcursorTheme::devicePixelRatio() const
|
||||
{
|
||||
return d->devicePixelRatio;
|
||||
}
|
||||
|
||||
bool KXcursorTheme::isEmpty() const
|
||||
{
|
||||
return d->registry.isEmpty();
|
||||
|
|
|
@ -109,6 +109,21 @@ public:
|
|||
bool operator==(const KXcursorTheme &other);
|
||||
bool operator!=(const KXcursorTheme &other);
|
||||
|
||||
/**
|
||||
* The name of the requested Xcursor theme.
|
||||
*/
|
||||
QString name() const;
|
||||
|
||||
/**
|
||||
* The size of the requested Xcursor theme.
|
||||
*/
|
||||
int size() const;
|
||||
|
||||
/**
|
||||
* The scale factor of the requested Xcursor theme.
|
||||
*/
|
||||
qreal devicePixelRatio() const;
|
||||
|
||||
/**
|
||||
* Returns @c true if the Xcursor theme is empty; otherwise returns @c false.
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue