Working cursor mirroring
This commit is contained in:
parent
757eaed57f
commit
4599a7afab
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include <KGlobalAccel>
|
||||
#include <KLocalizedString>
|
||||
#include <qt/QtCore/qbuffer.h>
|
||||
|
||||
Q_LOGGING_CATEGORY(KWIN_XR, "kwin.xr")
|
||||
|
||||
|
|
@ -47,6 +48,9 @@ BreezyDesktopEffect::BreezyDesktopEffect()
|
|||
}
|
||||
});
|
||||
|
||||
connect(effects, &EffectsHandler::cursorShapeChanged, this, &BreezyDesktopEffect::updateCursorImage);
|
||||
updateCursorImage();
|
||||
|
||||
setSource(QUrl::fromLocalFile(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kwin/effects/breezy_desktop/qml/main.qml"))));
|
||||
|
||||
m_xrRotationTimer = new QTimer(this);
|
||||
|
|
@ -54,14 +58,17 @@ BreezyDesktopEffect::BreezyDesktopEffect()
|
|||
connect(m_xrRotationTimer, &QTimer::timeout, this, &BreezyDesktopEffect::updateXrRotation);
|
||||
m_xrRotationTimer->start();
|
||||
|
||||
toggle();
|
||||
m_cursorUpdateTimer = new QTimer(this);
|
||||
connect(m_cursorUpdateTimer, &QTimer::timeout, this, &BreezyDesktopEffect::updateCursorPos);
|
||||
m_cursorUpdateTimer->setInterval(16); // ~60Hz
|
||||
m_cursorUpdateTimer->start();
|
||||
}
|
||||
|
||||
QVariantMap BreezyDesktopEffect::initialProperties(Output *screen)
|
||||
{
|
||||
return QVariantMap{
|
||||
{QStringLiteral("effect"), QVariant::fromValue(this)},
|
||||
{QStringLiteral("targetScreen"), QVariant::fromValue(screen)},
|
||||
{QStringLiteral("targetScreen"), QVariant::fromValue(screen)}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -111,6 +118,8 @@ void BreezyDesktopEffect::deactivate()
|
|||
}
|
||||
|
||||
m_shutdownTimer->start(animationDuration());
|
||||
disconnect(effects, &EffectsHandler::cursorShapeChanged, this, &BreezyDesktopEffect::updateCursorImage);
|
||||
m_cursorUpdateTimer->stop();
|
||||
showCursor();
|
||||
}
|
||||
|
||||
|
|
@ -239,89 +248,58 @@ void BreezyDesktopEffect::updateXrRotation() {
|
|||
}
|
||||
}
|
||||
|
||||
// show and hide cursor logic pulled from ZoomEffect
|
||||
GLTexture *BreezyDesktopEffect::ensureCursorTexture()
|
||||
QString BreezyDesktopEffect::cursorImageSource() const
|
||||
{
|
||||
if (!m_cursorTexture || m_cursorTextureDirty) {
|
||||
m_cursorTexture.reset();
|
||||
m_cursorTextureDirty = false;
|
||||
const auto cursor = effects->cursorImage();
|
||||
if (!cursor.image().isNull()) {
|
||||
m_cursorTexture = GLTexture::upload(cursor.image());
|
||||
if (!m_cursorTexture) {
|
||||
return nullptr;
|
||||
}
|
||||
m_cursorTexture->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
}
|
||||
return m_cursorTexture.get();
|
||||
return m_cursorImageSource;
|
||||
}
|
||||
|
||||
void BreezyDesktopEffect::markCursorTextureDirty()
|
||||
QPointF BreezyDesktopEffect::cursorPos() const
|
||||
{
|
||||
m_cursorTextureDirty = true;
|
||||
return m_cursorPos;
|
||||
}
|
||||
|
||||
void BreezyDesktopEffect::showCursor()
|
||||
{
|
||||
if (m_isMouseHidden) {
|
||||
disconnect(effects, &EffectsHandler::cursorShapeChanged, this, &BreezyDesktopEffect::markCursorTextureDirty);
|
||||
// show the previously hidden mouse-pointer again and free the loaded texture/picture.
|
||||
effects->showCursor();
|
||||
m_cursorTexture.reset();
|
||||
m_isMouseHidden = false;
|
||||
}
|
||||
}
|
||||
|
||||
void BreezyDesktopEffect::hideCursor()
|
||||
{
|
||||
qCCritical(KWIN_XR) << "\t\t\tBreezy - hide cursor";
|
||||
if (!m_isMouseHidden) {
|
||||
qCCritical(KWIN_XR) << "\t\t\tBreezy - hide cursor - ensure cursor texture";
|
||||
// try to load the cursor-theme into a OpenGL texture and if successful then hide the mouse-pointer
|
||||
GLTexture *texture = nullptr;
|
||||
if (effects->isOpenGLCompositing()) {
|
||||
qCCritical(KWIN_XR) << "\t\t\tBreezy - hide cursor - OpenGL compositing";
|
||||
texture = ensureCursorTexture();
|
||||
}
|
||||
if (texture) {
|
||||
qCCritical(KWIN_XR) << "\t\t\tBreezy - hide cursor - hiding cursor";
|
||||
effects->hideCursor();
|
||||
connect(effects, &EffectsHandler::cursorShapeChanged, this, &BreezyDesktopEffect::markCursorTextureDirty);
|
||||
m_isMouseHidden = true;
|
||||
}
|
||||
updateCursorImage();
|
||||
effects->hideCursor();
|
||||
m_isMouseHidden = true;
|
||||
}
|
||||
}
|
||||
|
||||
void BreezyDesktopEffect::paintScreen(const RenderTarget &renderTarget, const RenderViewport &viewport, int mask, const QRegion ®ion, Output *screen)
|
||||
{
|
||||
GLTexture *cursorTexture = ensureCursorTexture();
|
||||
if (cursorTexture) {
|
||||
const auto cursor = effects->cursorImage();
|
||||
QSizeF cursorSize = QSizeF(cursor.image().size()) / cursor.image().devicePixelRatio();
|
||||
|
||||
// Ensure cursor size doesn't exceed texture dimensions
|
||||
const QSize textureSize = cursorTexture->size();
|
||||
cursorSize = cursorSize.boundedTo(QSizeF(textureSize));
|
||||
void BreezyDesktopEffect::updateCursorImage()
|
||||
{
|
||||
const auto cursor = effects->cursorImage();
|
||||
if (!cursor.image().isNull()) {
|
||||
QByteArray data;
|
||||
QBuffer buffer(&data);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
cursor.image().save(&buffer, "PNG");
|
||||
|
||||
const QPointF p = (effects->cursorPos() - cursor.hotSpot());
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
auto s = ShaderManager::instance()->pushShader(ShaderTrait::MapTexture | ShaderTrait::TransformColorspace);
|
||||
s->setColorspaceUniforms(ColorDescription::sRGB, renderTarget.colorDescription(), RenderingIntent::Perceptual);
|
||||
QMatrix4x4 mvp = viewport.projectionMatrix();
|
||||
mvp.translate(p.x(), p.y());
|
||||
s->setUniform(GLShader::Mat4Uniform::ModelViewProjectionMatrix, mvp);
|
||||
cursorTexture->render(cursorSize);
|
||||
ShaderManager::instance()->popShader();
|
||||
glDisable(GL_BLEND);
|
||||
m_cursorImageSource = QStringLiteral("data:image/png;base64,%1").arg(QString::fromLatin1(data.toBase64()));
|
||||
} else {
|
||||
m_cursorImageSource = QString();
|
||||
}
|
||||
QuickSceneEffect::paintScreen(renderTarget, viewport, mask, region, screen);
|
||||
Q_EMIT cursorImageChanged();
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace KWin
|
||||
void BreezyDesktopEffect::updateCursorPos()
|
||||
{
|
||||
// Update cursor position from effects
|
||||
QPointF newPos = effects->cursorPos();
|
||||
if (m_cursorPos != newPos) {
|
||||
m_cursorPos = newPos;
|
||||
Q_EMIT cursorPosChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_breezydesktopeffect.cpp"
|
||||
|
|
@ -3,14 +3,12 @@
|
|||
#include <effect/quickeffect.h>
|
||||
|
||||
#include <QAction>
|
||||
#include <QImage>
|
||||
#include <QKeySequence>
|
||||
#include <QQuaternion>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
class GLTexture;
|
||||
class GLShader;
|
||||
|
||||
class BreezyDesktopEffect : public QuickSceneEffect
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
@ -22,6 +20,8 @@ namespace KWin
|
|||
Q_PROPERTY(BackgroundMode backgroundMode READ backgroundMode NOTIFY backgroundModeChanged)
|
||||
Q_PROPERTY(QColor backgroundColor READ backgroundColor NOTIFY backgroundColorChanged)
|
||||
Q_PROPERTY(QQuaternion xrRotation READ xrRotation NOTIFY xrRotationChanged)
|
||||
Q_PROPERTY(QString cursorImageSource READ cursorImageSource NOTIFY cursorImageChanged)
|
||||
Q_PROPERTY(QPointF cursorPos READ cursorPos NOTIFY cursorPosChanged)
|
||||
|
||||
public:
|
||||
enum class BackgroundMode
|
||||
|
|
@ -33,8 +33,6 @@ namespace KWin
|
|||
|
||||
BreezyDesktopEffect();
|
||||
|
||||
void paintScreen(const RenderTarget &renderTarget, const RenderViewport &viewport, int mask, const QRegion ®ion, Output *screen) override;
|
||||
|
||||
int requestedEffectChainPosition() const override;
|
||||
|
||||
int animationDuration() const;
|
||||
|
|
@ -44,11 +42,11 @@ namespace KWin
|
|||
bool mouseInvertedY() const;
|
||||
BackgroundMode backgroundMode() const;
|
||||
QColor backgroundColor() const;
|
||||
QString cursorImageSource() const;
|
||||
QPointF cursorPos() const;
|
||||
|
||||
void showCursor();
|
||||
void hideCursor();
|
||||
GLTexture *ensureCursorTexture();
|
||||
void markCursorTextureDirty();
|
||||
|
||||
QQuaternion xrRotation() const;
|
||||
|
||||
|
|
@ -57,6 +55,8 @@ namespace KWin
|
|||
void deactivate();
|
||||
void toggle();
|
||||
void updateXrRotation();
|
||||
void updateCursorImage();
|
||||
void updateCursorPos();
|
||||
|
||||
Q_SIGNALS:
|
||||
void faceDisplacementChanged();
|
||||
|
|
@ -68,6 +68,8 @@ namespace KWin
|
|||
void backgroundModeChanged();
|
||||
void backgroundColorChanged();
|
||||
void xrRotationChanged();
|
||||
void cursorImageChanged();
|
||||
void cursorPosChanged();
|
||||
|
||||
protected:
|
||||
QVariantMap initialProperties(Output *screen) override;
|
||||
|
|
@ -80,12 +82,13 @@ namespace KWin
|
|||
QList<QKeySequence> m_toggleShortcut;
|
||||
QList<ElectricBorder> m_borderActivate;
|
||||
QList<ElectricBorder> m_touchBorderActivate;
|
||||
std::unique_ptr<GLTexture> m_cursorTexture;
|
||||
bool m_cursorTextureDirty = false;
|
||||
QString m_cursorImageSource;
|
||||
bool m_isMouseHidden = false;
|
||||
|
||||
QQuaternion m_xrRotation;
|
||||
QTimer *m_xrRotationTimer = nullptr;
|
||||
QPointF m_cursorPos;
|
||||
QTimer *m_cursorUpdateTimer = nullptr;
|
||||
};
|
||||
|
||||
} // namespace KWin
|
||||
|
|
|
|||
|
|
@ -22,4 +22,18 @@ Item {
|
|||
visible: !model.window.minimized
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: cursorImg
|
||||
source: effect.cursorImageSource
|
||||
cache: false
|
||||
visible: true // TODO - cursor position bounds check?
|
||||
x: effect.cursorPos.x - desktopView.screen.geometry.x
|
||||
y: effect.cursorPos.y - desktopView.screen.geometry.y
|
||||
z: 9999 // ensure on top
|
||||
anchors.centerIn: undefined
|
||||
|
||||
layer.enabled: true
|
||||
layer.smooth: true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue