diff --git a/effects/CMakeLists.txt b/effects/CMakeLists.txt
index 6d2457cdf2..b64b5c2e62 100644
--- a/effects/CMakeLists.txt
+++ b/effects/CMakeLists.txt
@@ -3,7 +3,7 @@ kde4_no_enable_final(kwineffects)
macro( KWIN4_ADD_EFFECT_BACKEND name )
kde4_add_plugin( ${name} ${ARGN} )
- target_link_libraries( ${name} kwineffects ${KDE4_KDEUI_LIBS} ${KDE4_PLASMA_LIBS} ${X11_Xfixes_LIB} ${X11_Xcursor_LIB} ${X11_LIBRARIES} ${XCB_XCB_LIBRARIES} ${X11_XCB_LIBRARIES}
+ target_link_libraries( ${name} kwineffects ${KDE4_KDEUI_LIBS} ${KDE4_PLASMA_LIBS} ${X11_Xfixes_LIB} ${X11_Xcursor_LIB} ${X11_LIBRARIES} ${XCB_XCB_LIBRARIES} ${XCB_IMAGE_LIBRARIES} ${X11_XCB_LIBRARIES}
${XCB_XFIXES_LIBRARIES})
endmacro( KWIN4_ADD_EFFECT_BACKEND )
diff --git a/effects/screenshot/screenshot.cpp b/effects/screenshot/screenshot.cpp
index d3e33c8baf..02f02363b4 100644
--- a/effects/screenshot/screenshot.cpp
+++ b/effects/screenshot/screenshot.cpp
@@ -26,9 +26,7 @@ along with this program. If not, see .
#include
#include
#include
-
-#include
-#include
+#include
namespace KWin
{
@@ -55,6 +53,24 @@ ScreenShotEffect::~ScreenShotEffect()
QDBusConnection::sessionBus().unregisterObject("/Screenshot");
QDBusConnection::sessionBus().unregisterService("org.kde.kwin.Screenshot");
}
+
+#ifdef KWIN_HAVE_XRENDER_COMPOSITING
+static QImage xPictureToImage(xcb_render_picture_t srcPic, const QRect &geometry, xcb_image_t **xImage)
+{
+ xcb_pixmap_t xpix = xcb_generate_id(connection());
+ xcb_create_pixmap(connection(), 32, xpix, rootWindow(), geometry.width(), geometry.height());
+ XRenderPicture pic(xpix, 32);
+ xcb_render_composite(connection(), XCB_RENDER_PICT_OP_SRC, srcPic, XCB_RENDER_PICTURE_NONE, pic,
+ geometry.x(), geometry.y(), 0, 0, 0, 0, geometry.width(), geometry.height());
+ xcb_flush(connection());
+ *xImage = xcb_image_get(connection(), xpix, 0, 0, geometry.width(), geometry.height(), ~0, XCB_IMAGE_FORMAT_Z_PIXMAP);
+ QImage img((*xImage)->data, (*xImage)->width, (*xImage)->height, (*xImage)->stride, QImage::Format_ARGB32_Premultiplied);
+ // TODO: byte order might need swapping
+ xcb_free_pixmap(connection(), xpix);
+ return img;
+}
+#endif
+
void ScreenShotEffect::postPaintScreen()
{
effects->postPaintScreen();
@@ -129,18 +145,12 @@ void ScreenShotEffect::postPaintScreen()
ScreenShotEffect::convertFromGLImage(img, width, height);
}
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
+ xcb_image_t *xImage = NULL;
if (effects->compositingType() == XRenderCompositing) {
setXRenderOffscreen(true);
effects->drawWindow(m_scheduledScreenshot, mask, QRegion(0, 0, width, height), d);
if (xRenderOffscreenTarget()) {
- xcb_pixmap_t xpix = xcb_generate_id(connection());
- xcb_create_pixmap(connection(), 32, xpix, rootWindow(), width, height);
- // TODO: Qt5 - convert from xpixmap to QImage without a QPixmap
- QPixmap pixmap = QPixmap::fromX11Pixmap(xpix);
- xcb_render_composite(connection(), XCB_RENDER_PICT_OP_SRC, xRenderOffscreenTarget(),
- XCB_RENDER_PICTURE_NONE, pixmap.x11PictureHandle(), 0, 0, 0, 0, 0, 0, width, height);
- img = pixmap.toImage().copy(0, 0, width, height);
- xcb_free_pixmap(connection(), xpix);
+ img = xPictureToImage(xRenderOffscreenTarget(), QRect(0, 0, width, height), &xImage);
}
setXRenderOffscreen(false);
}
@@ -150,18 +160,22 @@ void ScreenShotEffect::postPaintScreen()
grabPointerImage(img, m_scheduledScreenshot->x() + left, m_scheduledScreenshot->y() + top);
}
- m_lastScreenshot = QPixmap::fromImage(img);
- if (m_lastScreenshot.handle() == 0) {
- Pixmap xpix = XCreatePixmap(display(), rootWindow(), m_lastScreenshot.width(),
- m_lastScreenshot.height(), 32);
- m_lastScreenshot = QPixmap::fromX11Pixmap(xpix, QPixmap::ExplicitlyShared);
- QPainter p(&m_lastScreenshot);
- p.setCompositionMode(QPainter::CompositionMode_Source);
- p.drawImage(QPoint(0, 0), img);
- p.end();
- XSync(display(), False);
+ const int depth = img.depth();
+ xcb_pixmap_t xpix = xcb_generate_id(connection());
+ xcb_create_pixmap(connection(), depth, xpix, rootWindow(), img.width(), img.height());
+
+ xcb_gcontext_t cid = xcb_generate_id(connection());
+ xcb_create_gc(connection(), cid, xpix, 0, NULL);
+ xcb_put_image(connection(), XCB_IMAGE_FORMAT_Z_PIXMAP, xpix, cid, img.width(), img.height(),
+ 0, 0, 0, depth, img.byteCount(), img.constBits());
+ xcb_free_gc(connection(), cid);
+ xcb_flush(connection());
+ emit screenshotCreated(xpix);
+#ifdef KWIN_HAVE_XRENDER_COMPOSITING
+ if (xImage) {
+ xcb_image_destroy(xImage);
}
- emit screenshotCreated(m_lastScreenshot.handle());
+#endif
}
m_scheduledScreenshot = NULL;
}
@@ -280,16 +294,12 @@ QString ScreenShotEffect::blitScreenshot(const QRect &geometry)
ScreenShotEffect::convertFromGLImage(img, geometry.width(), geometry.height());
}
+#ifdef KWIN_HAVE_XRENDER_COMPOSITING
+ xcb_image_t *xImage = NULL;
+#endif
if (effects->compositingType() == XRenderCompositing) {
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
- QPixmap buffer(geometry.size());
- if (buffer.handle() == 0) {
- Pixmap xpix = XCreatePixmap(display(), rootWindow(), geometry.width(), geometry.height(), 32);
- buffer = QPixmap::fromX11Pixmap(xpix, QPixmap::ExplicitlyShared);
- }
- XRenderComposite(display(), PictOpSrc, effects->xrenderBufferPicture(), None, buffer.x11PictureHandle(),
- 0, 0, 0, 0, geometry.x(), geometry.y(), geometry.width(), geometry.height());
- img = buffer.toImage();
+ img = xPictureToImage(effects->xrenderBufferPicture(), geometry, &xImage);
#endif
}
@@ -300,6 +310,11 @@ QString ScreenShotEffect::blitScreenshot(const QRect &geometry)
return QString();
}
img.save(&temp);
+#ifdef KWIN_HAVE_XRENDER_COMPOSITING
+ if (xImage) {
+ xcb_image_destroy(xImage);
+ }
+#endif
temp.close();
return temp.fileName();
#endif
@@ -308,24 +323,18 @@ QString ScreenShotEffect::blitScreenshot(const QRect &geometry)
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.
{
- XFixesCursorImage *xcursorimg = XFixesGetCursorImage(QX11Info::display());
- if (!xcursorimg)
+ QScopedPointer cursor(
+ xcb_xfixes_get_cursor_image_reply(connection(),
+ xcb_xfixes_get_cursor_image_unchecked(connection()),
+ NULL));
+ if (cursor.isNull())
return;
- //Annoyingly, xfixes specifies the data to be 32bit, but places it in an unsigned long *
- //which can be 64 bit. So we need to iterate over a 64bit structure to put it in a 32bit
- //structure.
- QVarLengthArray< quint32 > pixels(xcursorimg->width * xcursorimg->height);
- for (int i = 0; i < xcursorimg->width * xcursorimg->height; ++i)
- pixels[i] = xcursorimg->pixels[i] & 0xffffffff;
-
- QImage qcursorimg((uchar *) pixels.data(), xcursorimg->width, xcursorimg->height,
+ 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(xcursorimg->x - xcursorimg->xhot - offsetx, xcursorimg->y - xcursorimg ->yhot - offsety), qcursorimg);
-
- XFree(xcursorimg);
+ painter.drawImage(QPointF(cursor->x - cursor->xhot - offsetx, cursor->y - cursor ->yhot - offsety), qcursorimg);
}
void ScreenShotEffect::convertFromGLImage(QImage &img, int w, int h)
diff --git a/effects/screenshot/screenshot.h b/effects/screenshot/screenshot.h
index 18b50023bc..f541575915 100644
--- a/effects/screenshot/screenshot.h
+++ b/effects/screenshot/screenshot.h
@@ -84,7 +84,6 @@ private:
void restoreMatrix();
EffectWindow *m_scheduledScreenshot;
ScreenShotType m_type;
- QPixmap m_lastScreenshot;
};
} // namespace