You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
193 lines
4.0 KiB
193 lines
4.0 KiB
/* |
|
SPDX-FileCopyrightText: 2022 Vlad Zahorodnii <vlad.zahorodnii@kde.org> |
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later |
|
*/ |
|
|
|
#include "cursorsource.h" |
|
#include "cursor.h" |
|
#include "wayland/surface.h" |
|
|
|
namespace KWin |
|
{ |
|
|
|
CursorSource::CursorSource(QObject *parent) |
|
: QObject(parent) |
|
{ |
|
} |
|
|
|
bool CursorSource::isBlank() const |
|
{ |
|
return m_size.isEmpty(); |
|
} |
|
|
|
QSizeF CursorSource::size() const |
|
{ |
|
return m_size; |
|
} |
|
|
|
QPointF CursorSource::hotspot() const |
|
{ |
|
return m_hotspot; |
|
} |
|
|
|
void CursorSource::frame(std::chrono::milliseconds timestamp) |
|
{ |
|
} |
|
|
|
ShapeCursorSource::ShapeCursorSource(QObject *parent) |
|
: CursorSource(parent) |
|
{ |
|
m_delayTimer.setSingleShot(true); |
|
connect(&m_delayTimer, &QTimer::timeout, this, &ShapeCursorSource::selectNextSprite); |
|
} |
|
|
|
QImage ShapeCursorSource::image() const |
|
{ |
|
return m_image; |
|
} |
|
|
|
QByteArray ShapeCursorSource::shape() const |
|
{ |
|
return m_shape; |
|
} |
|
|
|
void ShapeCursorSource::setShape(const QByteArray &shape) |
|
{ |
|
if (m_shape != shape) { |
|
m_shape = shape; |
|
refresh(); |
|
} |
|
} |
|
|
|
void ShapeCursorSource::setShape(Qt::CursorShape shape) |
|
{ |
|
setShape(CursorShape(shape).name()); |
|
} |
|
|
|
CursorTheme ShapeCursorSource::theme() const |
|
{ |
|
return m_theme; |
|
} |
|
|
|
void ShapeCursorSource::setTheme(const CursorTheme &theme) |
|
{ |
|
if (m_theme != theme) { |
|
m_theme = theme; |
|
refresh(); |
|
} |
|
} |
|
|
|
void ShapeCursorSource::refresh() |
|
{ |
|
m_currentSprite = -1; |
|
m_delayTimer.stop(); |
|
|
|
m_sprites = m_theme.shape(m_shape); |
|
if (m_sprites.isEmpty()) { |
|
const auto alternativeNames = CursorShape::alternatives(m_shape); |
|
for (const QByteArray &alternativeName : alternativeNames) { |
|
m_sprites = m_theme.shape(alternativeName); |
|
if (!m_sprites.isEmpty()) { |
|
break; |
|
} |
|
} |
|
} |
|
|
|
if (!m_sprites.isEmpty()) { |
|
selectSprite(0); |
|
} |
|
} |
|
|
|
void ShapeCursorSource::selectNextSprite() |
|
{ |
|
selectSprite((m_currentSprite + 1) % m_sprites.size()); |
|
} |
|
|
|
void ShapeCursorSource::selectSprite(int index) |
|
{ |
|
if (m_currentSprite == index) { |
|
return; |
|
} |
|
const CursorSprite &sprite = m_sprites[index]; |
|
m_currentSprite = index; |
|
m_image = sprite.data(); |
|
m_size = QSizeF(m_image.size()) / m_image.devicePixelRatio(); |
|
m_hotspot = sprite.hotspot(); |
|
if (sprite.delay().count() && m_sprites.size() > 1) { |
|
m_delayTimer.start(sprite.delay()); |
|
} |
|
Q_EMIT changed(); |
|
} |
|
|
|
SurfaceCursorSource::SurfaceCursorSource(QObject *parent) |
|
: CursorSource(parent) |
|
{ |
|
} |
|
|
|
SurfaceInterface *SurfaceCursorSource::surface() const |
|
{ |
|
return m_surface; |
|
} |
|
|
|
void SurfaceCursorSource::frame(std::chrono::milliseconds timestamp) |
|
{ |
|
if (m_surface) { |
|
m_surface->traverseTree([×tamp](SurfaceInterface *surface) { |
|
surface->frameRendered(timestamp.count()); |
|
}); |
|
} |
|
} |
|
|
|
void SurfaceCursorSource::refresh() |
|
{ |
|
m_size = m_surface->size(); |
|
m_hotspot -= m_surface->offset(); |
|
Q_EMIT changed(); |
|
} |
|
|
|
void SurfaceCursorSource::reset() |
|
{ |
|
m_size = QSizeF(0, 0); |
|
m_hotspot = QPointF(0, 0); |
|
m_surface = nullptr; |
|
Q_EMIT changed(); |
|
} |
|
|
|
void SurfaceCursorSource::update(SurfaceInterface *surface, const QPointF &hotspot) |
|
{ |
|
bool dirty = false; |
|
|
|
if (m_hotspot != hotspot) { |
|
dirty = true; |
|
m_hotspot = hotspot; |
|
} |
|
|
|
if (m_surface != surface) { |
|
dirty = true; |
|
|
|
if (m_surface) { |
|
disconnect(m_surface, &SurfaceInterface::committed, this, &SurfaceCursorSource::refresh); |
|
disconnect(m_surface, &SurfaceInterface::destroyed, this, &SurfaceCursorSource::reset); |
|
} |
|
|
|
m_surface = surface; |
|
|
|
if (m_surface) { |
|
m_size = surface->size(); |
|
|
|
connect(m_surface, &SurfaceInterface::committed, this, &SurfaceCursorSource::refresh); |
|
connect(m_surface, &SurfaceInterface::destroyed, this, &SurfaceCursorSource::reset); |
|
} else { |
|
m_size = QSizeF(0, 0); |
|
} |
|
} |
|
|
|
if (dirty) { |
|
Q_EMIT changed(); |
|
} |
|
} |
|
|
|
} // namespace KWin |
|
|
|
#include "moc_cursorsource.cpp"
|
|
|