diff --git a/autotests/mock_effectshandler.h b/autotests/mock_effectshandler.h --- a/autotests/mock_effectshandler.h +++ b/autotests/mock_effectshandler.h @@ -237,6 +237,10 @@ m_animationsSuported = set; } + KWin::PlatformCursorImage cursorImage() const override { + return KWin::PlatformCursorImage(); + } + private: bool m_animationsSuported = true; }; diff --git a/effects.h b/effects.h --- a/effects.h +++ b/effects.h @@ -228,6 +228,8 @@ bool animationsSupported() const override; + PlatformCursorImage cursorImage() const override; + Scene *scene() const { return m_scene; } diff --git a/effects.cpp b/effects.cpp --- a/effects.cpp +++ b/effects.cpp @@ -1559,6 +1559,11 @@ e->perform(Effect::HighlightWindows, QVariantList{QVariant::fromValue(windows)}); } +PlatformCursorImage EffectsHandlerImpl::cursorImage() const +{ + return kwinApp()->platform()->cursorImage(); +} + //**************************************** // EffectWindowImpl //**************************************** diff --git a/effects/screenshot/screenshot.cpp b/effects/screenshot/screenshot.cpp --- a/effects/screenshot/screenshot.cpp +++ b/effects/screenshot/screenshot.cpp @@ -369,20 +369,13 @@ } void ScreenShotEffect::grabPointerImage(QImage& snapshot, int offsetx, int offsety) -// Uses the X11_EXTENSIONS_XFIXES_H extension to grab the pointer image, and overlays it onto the snapshot. { - QScopedPointer cursor( - xcb_xfixes_get_cursor_image_reply(xcbConnection(), - xcb_xfixes_get_cursor_image_unchecked(xcbConnection()), - NULL)); - if (cursor.isNull()) + const auto cursor = effects->cursorImage(); + if (cursor.image().isNull()) return; - QImage qcursorimg((uchar *) xcb_xfixes_get_cursor_image_cursor_image(cursor.data()), cursor->width, cursor->height, - QImage::Format_ARGB32_Premultiplied); - QPainter painter(&snapshot); - painter.drawImage(QPointF(cursor->x - cursor->xhot - offsetx, cursor->y - cursor ->yhot - offsety), qcursorimg); + painter.drawImage(effects->cursorPos() - cursor.hotSpot() - QPoint(offsetx, offsety), cursor.image()); } void ScreenShotEffect::convertFromGLImage(QImage &img, int w, int h) diff --git a/effects/zoom/zoom.cpp b/effects/zoom/zoom.cpp --- a/effects/zoom/zoom.cpp +++ b/effects/zoom/zoom.cpp @@ -188,23 +188,17 @@ void ZoomEffect::recreateTexture() { effects->makeOpenGLContextCurrent(); - // load the cursor-theme image from the Xcursor-library - xcb_xfixes_get_cursor_image_cookie_t keks = xcb_xfixes_get_cursor_image_unchecked(xcbConnection()); - xcb_xfixes_get_cursor_image_reply_t *ximg = xcb_xfixes_get_cursor_image_reply(xcbConnection(), keks, 0); - if (ximg) { - // turn the XcursorImage into a QImage that will be used to create the GLTexture/XRenderPicture. - imageWidth = ximg->width; - imageHeight = ximg->height; - cursorHotSpot = QPoint(ximg->xhot, ximg->yhot); - uint32_t *bits = xcb_xfixes_get_cursor_image_cursor_image(ximg); - QImage img((uchar*)bits, imageWidth, imageHeight, QImage::Format_ARGB32_Premultiplied); + const auto cursor = effects->cursorImage(); + if (!cursor.image().isNull()) { + imageWidth = cursor.image().width(); + imageHeight = cursor.image().height(); + cursorHotSpot = cursor.hotSpot(); if (effects->isOpenGLCompositing()) - texture.reset(new GLTexture(img)); + texture.reset(new GLTexture(cursor.image())); #ifdef KWIN_HAVE_XRENDER_COMPOSITING if (effects->compositingType() == XRenderCompositing) - xrenderPicture.reset(new XRenderPicture(img)); + xrenderPicture.reset(new XRenderPicture(cursor.image())); #endif - free(ximg); } else { qCDebug(KWINEFFECTS) << "Falling back to proportional mouse tracking!"; diff --git a/libkwineffects/CMakeLists.txt b/libkwineffects/CMakeLists.txt --- a/libkwineffects/CMakeLists.txt +++ b/libkwineffects/CMakeLists.txt @@ -5,7 +5,7 @@ VARIABLE_PREFIX KWINEFFECTS VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kwineffects_version.h" PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KWinEffectsConfigVersion.cmake" - SOVERSION 9 + SOVERSION 10 ) ### xrenderutils lib ### diff --git a/libkwineffects/kwineffects.h b/libkwineffects/kwineffects.h --- a/libkwineffects/kwineffects.h +++ b/libkwineffects/kwineffects.h @@ -1186,6 +1186,13 @@ virtual bool animationsSupported() const = 0; /** + * The current cursor image of the Platform. + * @see cursorPos + * @since 5.9 + **/ + virtual PlatformCursorImage cursorImage() const = 0; + + /** * @return @ref KConfigGroup which holds given effect's config options **/ static KConfigGroup effectConfig(const QString& effectname); diff --git a/libkwineffects/kwinglobals.h b/libkwineffects/kwinglobals.h --- a/libkwineffects/kwinglobals.h +++ b/libkwineffects/kwinglobals.h @@ -22,6 +22,8 @@ #define KWIN_LIB_KWINGLOBALS_H #include +#include +#include #include #include #include @@ -197,6 +199,36 @@ return screen ? screen->height_in_pixels : 0; } +/** + * Short wrapper for a cursor image provided by the Platform. + * @since 5.9 + **/ +class PlatformCursorImage { +public: + explicit PlatformCursorImage() + : m_image() + , m_hotSpot() + { + } + explicit PlatformCursorImage(const QImage &image, const QPoint &hotSpot) + : m_image(image) + , m_hotSpot(hotSpot) + { + } + virtual ~PlatformCursorImage() = default; + + QImage image() const { + return m_image; + } + QPoint hotSpot() const { + return m_hotSpot; + } + +private: + QImage m_image; + QPoint m_hotSpot; +}; + } // namespace #define KWIN_SINGLETON_VARIABLE(ClassName, variableName) \ diff --git a/platform.h b/platform.h --- a/platform.h +++ b/platform.h @@ -20,6 +20,7 @@ #ifndef KWIN_PLATFORM_H #define KWIN_PLATFORM_H #include +#include #include #include #include @@ -161,6 +162,17 @@ QPoint softwareCursorHotspot() const; void markCursorAsRendered(); + /** + * Returns a PlatformCursorImage. By default this is created by softwareCursor and + * softwareCursorHotspot. An implementing subclass can use this to provide a better + * suited PlatformCursorImage. + * + * @see softwareCursor + * @see softwareCursorHotspot + * @since 5.9 + **/ + virtual PlatformCursorImage cursorImage() const; + bool handlesOutputs() const { return m_handlesOutputs; } diff --git a/platform.cpp b/platform.cpp --- a/platform.cpp +++ b/platform.cpp @@ -54,6 +54,11 @@ return input()->pointer()->cursorHotSpot(); } +PlatformCursorImage Platform::cursorImage() const +{ + return PlatformCursorImage(softwareCursor(), softwareCursorHotspot()); +} + Screens *Platform::createScreens(QObject *parent) { Q_UNUSED(parent) diff --git a/plugins/platforms/x11/standalone/x11_platform.h b/plugins/platforms/x11/standalone/x11_platform.h --- a/plugins/platforms/x11/standalone/x11_platform.h +++ b/plugins/platforms/x11/standalone/x11_platform.h @@ -49,6 +49,8 @@ bool openGLCompositingIsBroken() const override; void createOpenGLSafePoint(OpenGLSafePoint safePoint) override; + PlatformCursorImage cursorImage() const override; + private: /** * Tests whether GLX is supported and returns @c true diff --git a/plugins/platforms/x11/standalone/x11_platform.cpp b/plugins/platforms/x11/standalone/x11_platform.cpp --- a/plugins/platforms/x11/standalone/x11_platform.cpp +++ b/plugins/platforms/x11/standalone/x11_platform.cpp @@ -208,4 +208,21 @@ group.sync(); } +PlatformCursorImage X11StandalonePlatform::cursorImage() const +{ + auto c = kwinApp()->x11Connection(); + QScopedPointer cursor( + xcb_xfixes_get_cursor_image_reply(c, + xcb_xfixes_get_cursor_image_unchecked(c), + nullptr)); + if (cursor.isNull()) { + return PlatformCursorImage(); + } + + QImage qcursorimg((uchar *) xcb_xfixes_get_cursor_image_cursor_image(cursor.data()), cursor->width, cursor->height, + QImage::Format_ARGB32_Premultiplied); + // deep copy of image as the data is going to be freed + return PlatformCursorImage(qcursorimg.copy(), QPoint(cursor->xhot, cursor->yhot)); +} + }