Wine/Wayland hides the cursor as follows: [ 853107.473] -> wl_pointer@15.set_cursor(172832, wl_surface@38, 0, 0) ... [ 858989.757] -> wl_surface@38.destroy() [ 858989.759] -> wl_pointer@15.set_cursor(172832, nil, 0, 0) i.e. it destroys the cursor surface, then calls wl_pointer.set_cursor(). SurfaceCursorSource stores the wl_surface in a QPointer, furthermore it is going to emit the changed signal, which is needed to force the CursorItem to update its content, only if either a new hotspot or a surface has been passed to SurfaceCursorSource::update(). So what happens is the following: - The SurfaceInterface object is destroyed and the QPointer resets its value to nullptr - SurfaceCursorSource::update(nullptr, QPointF(0, 0)) gets called in response to wl_pointer@15.set_cursor(nil, 0, 0) - but since m_surface has been implicitly reset to nullptr, no changed signal is going to be emitted This change addresses the issue by making the SurfaceCursorSource track the SurfaceInterface's destroyed signal. BUG: 480582
96 lines
1.8 KiB
C++
96 lines
1.8 KiB
C++
/*
|
|
SPDX-FileCopyrightText: 2022 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "utils/xcursortheme.h"
|
|
|
|
#include <QImage>
|
|
#include <QObject>
|
|
#include <QPoint>
|
|
#include <QTimer>
|
|
|
|
namespace KWin
|
|
{
|
|
|
|
class SurfaceInterface;
|
|
|
|
/**
|
|
* The CursorSource class represents the contents of the Cursor.
|
|
*/
|
|
class KWIN_EXPORT CursorSource : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
explicit CursorSource(QObject *parent = nullptr);
|
|
|
|
QSizeF size() const;
|
|
QPointF hotspot() const;
|
|
|
|
Q_SIGNALS:
|
|
void changed();
|
|
|
|
protected:
|
|
QSizeF m_size = QSizeF(0, 0);
|
|
QPointF m_hotspot;
|
|
};
|
|
|
|
/**
|
|
* The ShapeCursorSource class represents the contents of a shape in the cursor theme.
|
|
*/
|
|
class KWIN_EXPORT ShapeCursorSource : public CursorSource
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
explicit ShapeCursorSource(QObject *parent = nullptr);
|
|
|
|
QImage image() const;
|
|
|
|
QByteArray shape() const;
|
|
void setShape(const QByteArray &shape);
|
|
void setShape(Qt::CursorShape shape);
|
|
|
|
KXcursorTheme theme() const;
|
|
void setTheme(const KXcursorTheme &theme);
|
|
|
|
private:
|
|
void refresh();
|
|
void selectNextSprite();
|
|
void selectSprite(int index);
|
|
|
|
KXcursorTheme m_theme;
|
|
QByteArray m_shape;
|
|
QList<KXcursorSprite> m_sprites;
|
|
QTimer m_delayTimer;
|
|
QImage m_image;
|
|
int m_currentSprite = -1;
|
|
};
|
|
|
|
/**
|
|
* The SurfaceCursorSource class repsents the contents of a cursor backed by a wl_surface.
|
|
*/
|
|
class KWIN_EXPORT SurfaceCursorSource : public CursorSource
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
explicit SurfaceCursorSource(QObject *parent = nullptr);
|
|
|
|
SurfaceInterface *surface() const;
|
|
|
|
public Q_SLOTS:
|
|
void update(SurfaceInterface *surface, const QPointF &hotspot);
|
|
|
|
private:
|
|
void refresh();
|
|
void reset();
|
|
|
|
SurfaceInterface *m_surface = nullptr;
|
|
};
|
|
|
|
} // namespace KWin
|