From 93326f3e50458fb7843a91cee0e4f2d24f2b158f Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Sun, 10 Mar 2024 12:36:00 +0200 Subject: [PATCH] Revert "plugins/zoom: Port to CursorItem" This reverts commit e40f632c9bddd0d76cb91ab787621288d3da5570. It broke non default mouse tracking modes. There are just too many options, so revert the change instead. --- src/plugins/zoom/zoom.cpp | 86 ++++++++++++++++++++++++++++++--------- src/plugins/zoom/zoom.h | 8 ++-- 2 files changed, 71 insertions(+), 23 deletions(-) diff --git a/src/plugins/zoom/zoom.cpp b/src/plugins/zoom/zoom.cpp index 2f1c811a48..e9ee2c081e 100644 --- a/src/plugins/zoom/zoom.cpp +++ b/src/plugins/zoom/zoom.cpp @@ -26,11 +26,8 @@ #include "core/rendertarget.h" #include "core/renderviewport.h" -#include "cursor.h" #include "effect/effecthandler.h" #include "opengl/glutils.h" -#include "scene/cursoritem.h" -#include "scene/workspacescene.h" using namespace std::chrono_literals; @@ -46,6 +43,7 @@ ZoomEffect::ZoomEffect() , mouseTracking(MouseTrackingProportional) , mousePointer(MousePointerScale) , focusDelay(350) // in milliseconds + , isMouseHidden(false) , xMove(0) , yMove(0) , moveFactor(20.0) @@ -161,12 +159,36 @@ bool ZoomEffect::isTextCaretTrackingEnabled() const #endif } +GLTexture *ZoomEffect::ensureCursorTexture() +{ + 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(); +} + +void ZoomEffect::markCursorTextureDirty() +{ + m_cursorTextureDirty = true; +} + void ZoomEffect::showCursor() { - if (m_cursorHidden) { - m_cursorItem.reset(); - m_cursorHidden = false; + if (isMouseHidden) { + disconnect(effects, &EffectsHandler::cursorShapeChanged, this, &ZoomEffect::markCursorTextureDirty); + // show the previously hidden mouse-pointer again and free the loaded texture/picture. effects->showCursor(); + m_cursorTexture.reset(); + isMouseHidden = false; } } @@ -175,17 +197,16 @@ void ZoomEffect::hideCursor() if (mouseTracking == MouseTrackingProportional && mousePointer == MousePointerKeep) { return; // don't replace the actual cursor by a static image for no reason. } - if (!m_cursorHidden) { - effects->hideCursor(); - m_cursorHidden = true; - - if (mousePointer == MousePointerKeep || mousePointer == MousePointerScale) { - Cursor *cursor = Cursors::self()->mouse(); - m_cursorItem = std::make_unique(effects->scene()->overlayItem()); - m_cursorItem->setPosition(cursor->pos()); - connect(cursor, &Cursor::posChanged, m_cursorItem.get(), [this, cursor]() { - m_cursorItem->setPosition(cursor->pos()); - }); + if (!isMouseHidden) { + // try to load the cursor-theme into a OpenGL texture and if successful then hide the mouse-pointer + GLTexture *texture = nullptr; + if (effects->isOpenGLCompositing()) { + texture = ensureCursorTexture(); + } + if (texture) { + effects->hideCursor(); + connect(effects, &EffectsHandler::cursorShapeChanged, this, &ZoomEffect::markCursorTextureDirty); + isMouseHidden = true; } } } @@ -245,9 +266,6 @@ void ZoomEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseco showCursor(); } else { hideCursor(); - if (mousePointer == MousePointerScale) { - m_cursorItem->setTransform(QTransform::fromScale(zoom, zoom)); - } } effects->prePaintScreen(data, presentTime); @@ -386,6 +404,34 @@ void ZoomEffect::paintScreen(const RenderTarget &renderTarget, const RenderViewp offscreen.texture->render(offscreen.viewport.size() * scale); } ShaderManager::instance()->popShader(); + + if (mousePointer != MousePointerHide) { + // Draw the mouse-texture at the position matching to zoomed-in image of the desktop. Hiding the + // previous mouse-cursor and drawing our own fake mouse-cursor is needed to be able to scale the + // mouse-cursor up and to re-position those mouse-cursor to match to the chosen zoom-level. + + GLTexture *cursorTexture = ensureCursorTexture(); + if (cursorTexture) { + const auto cursor = effects->cursorImage(); + QSizeF cursorSize = QSizeF(cursor.image().size()) / cursor.image().devicePixelRatio(); + if (mousePointer == MousePointerScale) { + cursorSize *= zoom; + } + + const QPointF p = (effects->cursorPos() - cursor.hotSpot()) * zoom + QPoint(xTranslation, yTranslation); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + auto s = ShaderManager::instance()->pushShader(ShaderTrait::MapTexture | ShaderTrait::TransformColorspace); + s->setColorspaceUniformsFromSRGB(renderTarget.colorDescription()); + QMatrix4x4 mvp = viewport.projectionMatrix(); + mvp.translate(p.x() * scale, p.y() * scale); + s->setUniform(GLShader::Mat4Uniform::ModelViewProjectionMatrix, mvp); + cursorTexture->render(cursorSize * scale); + ShaderManager::instance()->popShader(); + glDisable(GL_BLEND); + } + } } void ZoomEffect::postPaintScreen() diff --git a/src/plugins/zoom/zoom.h b/src/plugins/zoom/zoom.h index bcb51db866..8e1e364552 100644 --- a/src/plugins/zoom/zoom.h +++ b/src/plugins/zoom/zoom.h @@ -23,7 +23,6 @@ namespace KWin class ZoomAccessibilityIntegration; #endif -class CursorItem; class GLFramebuffer; class GLTexture; class GLVertexBuffer; @@ -97,7 +96,9 @@ private: QRect viewport; }; + GLTexture *ensureCursorTexture(); OffscreenData *ensureOffscreenData(const RenderTarget &renderTarget, const RenderViewport &viewport, Output *screen); + void markCursorTextureDirty(); #if HAVE_ACCESSIBILITY ZoomAccessibilityIntegration *m_accessibilityIntegration = nullptr; @@ -126,8 +127,9 @@ private: QPoint prevPoint; QTime lastMouseEvent; QTime lastFocusEvent; - std::unique_ptr m_cursorItem; - bool m_cursorHidden = false; + std::unique_ptr m_cursorTexture; + bool m_cursorTextureDirty = false; + bool isMouseHidden; QTimeLine timeline; int xMove, yMove; double moveFactor;