Drop Cursor::image()
Use CursorSource::image() instead. Cursor caching in the ScreenCastStream has been changed so QImage::cacheKey() is not being used. This is rather a preparation for making kwin grab the contents of the cursor scene.
This commit is contained in:
parent
af7c1db43b
commit
3d5b5844d0
6 changed files with 47 additions and 39 deletions
|
@ -1090,7 +1090,7 @@ void PointerInputTest::testCursorImage()
|
|||
input()->pointer()->warp(QPointF(800, 800));
|
||||
auto p = input()->pointer();
|
||||
// at the moment it should be the fallback cursor
|
||||
const QImage fallbackCursor = cursor->image();
|
||||
const QImage fallbackCursor = kwinApp()->cursorImage().image();
|
||||
QVERIFY(!fallbackCursor.isNull());
|
||||
|
||||
// create a window
|
||||
|
@ -1107,7 +1107,7 @@ void PointerInputTest::testCursorImage()
|
|||
// move cursor to center of window, this should first set a null pointer, so we still show old cursor
|
||||
input()->pointer()->warp(window->frameGeometry().center());
|
||||
QCOMPARE(p->focus(), window);
|
||||
QCOMPARE(cursor->image(), fallbackCursor);
|
||||
QCOMPARE(kwinApp()->cursorImage().image(), fallbackCursor);
|
||||
QVERIFY(enteredSpy.wait());
|
||||
|
||||
// create a cursor on the pointer
|
||||
|
@ -1121,13 +1121,13 @@ void PointerInputTest::testCursorImage()
|
|||
cursorSurface->commit();
|
||||
pointer->setCursor(cursorSurface.get(), QPoint(5, 5));
|
||||
QVERIFY(cursorRenderedSpy.wait());
|
||||
QCOMPARE(cursor->image(), red);
|
||||
QCOMPARE(kwinApp()->cursorImage().image(), red);
|
||||
QCOMPARE(cursor->hotspot(), QPoint(5, 5));
|
||||
// change hotspot
|
||||
pointer->setCursor(cursorSurface.get(), QPoint(6, 6));
|
||||
Test::flushWaylandConnection();
|
||||
QTRY_COMPARE(cursor->hotspot(), QPoint(6, 6));
|
||||
QCOMPARE(cursor->image(), red);
|
||||
QCOMPARE(kwinApp()->cursorImage().image(), red);
|
||||
|
||||
// change the buffer
|
||||
QImage blue = QImage(QSize(10, 10), QImage::Format_ARGB32_Premultiplied);
|
||||
|
@ -1137,7 +1137,7 @@ void PointerInputTest::testCursorImage()
|
|||
cursorSurface->damage(QRect(0, 0, 10, 10));
|
||||
cursorSurface->commit();
|
||||
QVERIFY(cursorRenderedSpy.wait());
|
||||
QTRY_COMPARE(cursor->image(), blue);
|
||||
QTRY_COMPARE(kwinApp()->cursorImage().image(), blue);
|
||||
QCOMPARE(cursor->hotspot(), QPoint(6, 6));
|
||||
|
||||
// scaled cursor
|
||||
|
@ -1150,19 +1150,19 @@ void PointerInputTest::testCursorImage()
|
|||
cursorSurface->damage(QRect(0, 0, 20, 20));
|
||||
cursorSurface->commit();
|
||||
QVERIFY(cursorRenderedSpy.wait());
|
||||
QTRY_COMPARE(cursor->image(), blueScaled);
|
||||
QTRY_COMPARE(kwinApp()->cursorImage().image(), blueScaled);
|
||||
QCOMPARE(cursor->hotspot(), QPoint(6, 6)); // surface-local (so not changed)
|
||||
|
||||
// hide the cursor
|
||||
pointer->setCursor(nullptr);
|
||||
Test::flushWaylandConnection();
|
||||
QTRY_VERIFY(cursor->image().isNull());
|
||||
QTRY_VERIFY(kwinApp()->cursorImage().image().isNull());
|
||||
|
||||
// move cursor somewhere else, should reset to fallback cursor
|
||||
input()->pointer()->warp(window->frameGeometry().bottomLeft() + QPoint(20, 20));
|
||||
QVERIFY(!p->focus());
|
||||
QVERIFY(!cursor->image().isNull());
|
||||
QCOMPARE(cursor->image(), fallbackCursor);
|
||||
QVERIFY(!kwinApp()->cursorImage().image().isNull());
|
||||
QCOMPARE(kwinApp()->cursorImage().image(), fallbackCursor);
|
||||
}
|
||||
|
||||
class HelperEffect : public Effect
|
||||
|
@ -1183,7 +1183,6 @@ void PointerInputTest::testEffectOverrideCursorImage()
|
|||
|
||||
// we need a pointer to get the enter event and set a cursor
|
||||
auto pointer = m_seat->createPointer(m_seat);
|
||||
auto cursor = Cursors::self()->mouse();
|
||||
QVERIFY(pointer);
|
||||
QVERIFY(pointer->isValid());
|
||||
QSignalSpy enteredSpy(pointer, &KWayland::Client::Pointer::entered);
|
||||
|
@ -1191,7 +1190,7 @@ void PointerInputTest::testEffectOverrideCursorImage()
|
|||
// move cursor somewhere the new window won't open
|
||||
input()->pointer()->warp(QPointF(800, 800));
|
||||
// here we should have the fallback cursor
|
||||
const QImage fallback = cursor->image();
|
||||
const QImage fallback = kwinApp()->cursorImage().image();
|
||||
QVERIFY(!fallback.isNull());
|
||||
|
||||
// now let's create a window
|
||||
|
@ -1210,33 +1209,33 @@ void PointerInputTest::testEffectOverrideCursorImage()
|
|||
input()->pointer()->warp(window->frameGeometry().center());
|
||||
QVERIFY(enteredSpy.wait());
|
||||
// cursor image should still be fallback
|
||||
QCOMPARE(cursor->image(), fallback);
|
||||
QCOMPARE(kwinApp()->cursorImage().image(), fallback);
|
||||
|
||||
// now create an effect and set an override cursor
|
||||
std::unique_ptr<HelperEffect> effect(new HelperEffect);
|
||||
effects->startMouseInterception(effect.get(), Qt::SizeAllCursor);
|
||||
const QImage sizeAll = cursor->image();
|
||||
const QImage sizeAll = kwinApp()->cursorImage().image();
|
||||
QVERIFY(!sizeAll.isNull());
|
||||
QVERIFY(sizeAll != fallback);
|
||||
QVERIFY(leftSpy.wait());
|
||||
|
||||
// let's change to arrow cursor, this should be our fallback
|
||||
effects->defineCursor(Qt::ArrowCursor);
|
||||
QCOMPARE(cursor->image(), fallback);
|
||||
QCOMPARE(kwinApp()->cursorImage().image(), fallback);
|
||||
|
||||
// back to size all
|
||||
effects->defineCursor(Qt::SizeAllCursor);
|
||||
QCOMPARE(cursor->image(), sizeAll);
|
||||
QCOMPARE(kwinApp()->cursorImage().image(), sizeAll);
|
||||
|
||||
// move cursor outside the window area
|
||||
input()->pointer()->warp(QPointF(800, 800));
|
||||
// and end the override, which should switch to fallback
|
||||
effects->stopMouseInterception(effect.get());
|
||||
QCOMPARE(cursor->image(), fallback);
|
||||
QCOMPARE(kwinApp()->cursorImage().image(), fallback);
|
||||
|
||||
// start mouse interception again
|
||||
effects->startMouseInterception(effect.get(), Qt::SizeAllCursor);
|
||||
QCOMPARE(cursor->image(), sizeAll);
|
||||
QCOMPARE(kwinApp()->cursorImage().image(), sizeAll);
|
||||
|
||||
// move cursor to area of window
|
||||
input()->pointer()->warp(window->frameGeometry().center());
|
||||
|
@ -1247,7 +1246,7 @@ void PointerInputTest::testEffectOverrideCursorImage()
|
|||
// after ending the interception we should get an enter event
|
||||
effects->stopMouseInterception(effect.get());
|
||||
QVERIFY(enteredSpy.wait());
|
||||
QVERIFY(cursor->image().isNull());
|
||||
QVERIFY(kwinApp()->cursorImage().image().isNull());
|
||||
}
|
||||
|
||||
void PointerInputTest::testPopup()
|
||||
|
|
|
@ -175,14 +175,6 @@ bool Cursor::isOnOutput(Output *output) const
|
|||
return geometry().intersects(output->geometry());
|
||||
}
|
||||
|
||||
QImage Cursor::image() const
|
||||
{
|
||||
if (Q_UNLIKELY(!m_source)) {
|
||||
return QImage();
|
||||
}
|
||||
return m_source->image();
|
||||
}
|
||||
|
||||
QPointF Cursor::hotspot() const
|
||||
{
|
||||
if (Q_UNLIKELY(!m_source)) {
|
||||
|
|
|
@ -168,7 +168,6 @@ public:
|
|||
*/
|
||||
xcb_cursor_t x11Cursor(const QByteArray &name);
|
||||
|
||||
QImage image() const;
|
||||
QPointF hotspot() const;
|
||||
QRectF geometry() const;
|
||||
QRectF rect() const;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "core/outputbackend.h"
|
||||
#include "core/session.h"
|
||||
#include "cursor.h"
|
||||
#include "cursorsource.h"
|
||||
#include "effects.h"
|
||||
#include "input.h"
|
||||
#include "inputmethod.h"
|
||||
|
@ -641,7 +642,10 @@ ScreenLockerWatcher *Application::screenLockerWatcher() const
|
|||
PlatformCursorImage Application::cursorImage() const
|
||||
{
|
||||
Cursor *cursor = Cursors::self()->currentCursor();
|
||||
return PlatformCursorImage(cursor->image(), cursor->hotspot());
|
||||
if (CursorSource *source = cursor->source()) {
|
||||
return PlatformCursorImage(source->image(), source->hotspot());
|
||||
}
|
||||
return PlatformCursorImage();
|
||||
}
|
||||
|
||||
void Application::startInteractiveWindowSelection(std::function<void(KWin::Window *)> callback, const QByteArray &cursorName)
|
||||
|
|
|
@ -413,10 +413,12 @@ bool ScreenCastStream::createStream()
|
|||
}
|
||||
|
||||
if (m_cursor.mode == KWaylandServer::ScreencastV1Interface::Embedded) {
|
||||
connect(Cursors::self(), &Cursors::currentCursorChanged, this, &ScreenCastStream::invalidateCursor);
|
||||
connect(Cursors::self(), &Cursors::positionChanged, this, [this] {
|
||||
recordFrame({});
|
||||
});
|
||||
} else if (m_cursor.mode == KWaylandServer::ScreencastV1Interface::Metadata) {
|
||||
connect(Cursors::self(), &Cursors::currentCursorChanged, this, &ScreenCastStream::invalidateCursor);
|
||||
connect(Cursors::self(), &Cursors::positionChanged, this, &ScreenCastStream::recordCursor);
|
||||
}
|
||||
|
||||
|
@ -524,7 +526,8 @@ void ScreenCastStream::recordFrame(const QRegion &_damagedRegion)
|
|||
QImage dest(data, size.width(), size.height(), stride, hasAlpha ? QImage::Format_RGBA8888_Premultiplied : QImage::Format_RGB888);
|
||||
QPainter painter(&dest);
|
||||
const auto position = (cursor->pos() - m_cursor.viewport.topLeft() - cursor->hotspot()) * m_cursor.scale;
|
||||
painter.drawImage(QRect{position.toPoint(), cursor->image().size()}, cursor->image());
|
||||
const PlatformCursorImage cursorImage = kwinApp()->cursorImage();
|
||||
painter.drawImage(QRect{position.toPoint(), cursorImage.image().size()}, cursorImage.image());
|
||||
}
|
||||
} else {
|
||||
auto &buf = m_dmabufDataForPwBuffer[buffer];
|
||||
|
@ -542,7 +545,16 @@ void ScreenCastStream::recordFrame(const QRegion &_damagedRegion)
|
|||
|
||||
auto cursor = Cursors::self()->currentCursor();
|
||||
if (m_cursor.mode == KWaylandServer::ScreencastV1Interface::Embedded && exclusiveContains(m_cursor.viewport, cursor->pos())) {
|
||||
if (!cursor->image().isNull()) {
|
||||
if (m_cursor.invalid) {
|
||||
m_cursor.invalid = false;
|
||||
const PlatformCursorImage cursorImage = kwinApp()->cursorImage();
|
||||
if (cursorImage.isNull()) {
|
||||
m_cursor.texture = nullptr;
|
||||
} else {
|
||||
m_cursor.texture = std::make_unique<GLTexture>(cursorImage.image());
|
||||
}
|
||||
}
|
||||
if (m_cursor.texture) {
|
||||
GLFramebuffer::pushFramebuffer(buf->framebuffer());
|
||||
|
||||
QRect r(QPoint(), size);
|
||||
|
@ -552,13 +564,9 @@ void ScreenCastStream::recordFrame(const QRegion &_damagedRegion)
|
|||
mvp.ortho(r);
|
||||
shader->setUniform(GLShader::ModelViewProjectionMatrix, mvp);
|
||||
|
||||
if (!m_cursor.texture || m_cursor.lastKey != cursor->image().cacheKey()) {
|
||||
m_cursor.texture.reset(new GLTexture(cursor->image()));
|
||||
}
|
||||
|
||||
m_cursor.texture->setContentTransform(TextureTransforms());
|
||||
const auto cursorRect = cursorGeometry(cursor);
|
||||
mvp.translate(cursorRect.left(), r.height() - cursorRect.top() - cursor->image().height());
|
||||
mvp.translate(cursorRect.left(), r.height() - cursorRect.top() - m_cursor.texture->height());
|
||||
shader->setUniform(GLShader::ModelViewProjectionMatrix, mvp);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
|
@ -626,6 +634,11 @@ void ScreenCastStream::addDamage(spa_buffer *spaBuffer, const QRegion &damagedRe
|
|||
}
|
||||
}
|
||||
|
||||
void ScreenCastStream::invalidateCursor()
|
||||
{
|
||||
m_cursor.invalid = true;
|
||||
}
|
||||
|
||||
void ScreenCastStream::recordCursor()
|
||||
{
|
||||
Q_ASSERT(!m_stopped);
|
||||
|
@ -815,12 +828,11 @@ void ScreenCastStream::sendCursorData(Cursor *cursor, spa_meta_cursor *spa_meta_
|
|||
spa_meta_cursor->hotspot.y = cursor->hotspot().y() * m_cursor.scale;
|
||||
spa_meta_cursor->bitmap_offset = 0;
|
||||
|
||||
const QImage image = cursor->image();
|
||||
if (image.cacheKey() == m_cursor.lastKey) {
|
||||
if (!m_cursor.invalid) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_cursor.lastKey = image.cacheKey();
|
||||
m_cursor.invalid = false;
|
||||
spa_meta_cursor->bitmap_offset = sizeof(struct spa_meta_cursor);
|
||||
|
||||
const QSize targetSize = (cursor->rect().size() * m_cursor.scale).toSize();
|
||||
|
@ -842,6 +854,7 @@ void ScreenCastStream::sendCursorData(Cursor *cursor, spa_meta_cursor *spa_meta_
|
|||
QImage::Format_RGBA8888_Premultiplied);
|
||||
dest.fill(Qt::transparent);
|
||||
|
||||
const QImage image = kwinApp()->cursorImage().image();
|
||||
if (!image.isNull()) {
|
||||
QPainter painter(&dest);
|
||||
painter.drawImage(QRect({0, 0}, targetSize), image);
|
||||
|
|
|
@ -65,6 +65,7 @@ public:
|
|||
void setCursorMode(KWaylandServer::ScreencastV1Interface::CursorMode mode, qreal scale, const QRectF &viewport);
|
||||
|
||||
public Q_SLOTS:
|
||||
void invalidateCursor();
|
||||
void recordCursor();
|
||||
|
||||
Q_SIGNALS:
|
||||
|
@ -117,10 +118,10 @@ private:
|
|||
const QSize bitmapSize = QSize(256, 256);
|
||||
qreal scale = 1;
|
||||
QRectF viewport;
|
||||
qint64 lastKey = 0;
|
||||
QRectF lastRect;
|
||||
std::unique_ptr<GLTexture> texture;
|
||||
bool visible = false;
|
||||
bool invalid = true;
|
||||
} m_cursor;
|
||||
QRectF cursorGeometry(Cursor *cursor) const;
|
||||
|
||||
|
|
Loading…
Reference in a new issue