diff --git a/effects/CMakeLists.txt b/effects/CMakeLists.txt
index 6e1e4e3202..57f1262a53 100644
--- a/effects/CMakeLists.txt
+++ b/effects/CMakeLists.txt
@@ -8,6 +8,9 @@ kde4_no_enable_final(kwineffects)
macro( KWIN4_ADD_EFFECT name )
kde4_add_plugin( kwin4_effect_${name} ${ARGN} )
target_link_libraries( kwin4_effect_${name} kwineffects ${KDE4_KDEUI_LIBS} kephal ${KDE4_PLASMA_LIBS} ${X11_Xfixes_LIB} ${X11_Xcursor_LIB})
+ if (X11_Xfixes_FOUND)
+ target_link_libraries(kwin4_effect_${name} ${X11_Xfixes_LIB})
+ endif (X11_Xfixes_FOUND)
install( TARGETS kwin4_effect_${name} DESTINATION ${PLUGIN_INSTALL_DIR} )
endmacro( KWIN4_ADD_EFFECT )
diff --git a/effects/screenshot/screenshot.cpp b/effects/screenshot/screenshot.cpp
index aaafc1f6ff..3d6bd4505c 100644
--- a/effects/screenshot/screenshot.cpp
+++ b/effects/screenshot/screenshot.cpp
@@ -20,9 +20,13 @@ along with this program. If not, see .
*********************************************************************/
#include "screenshot.h"
#include
-#include
-#include
-#include
+#include
+#include
+#include
+#include
+
+#include
+#include
namespace KWin
{
@@ -38,15 +42,14 @@ bool ScreenShotEffect::supported()
ScreenShotEffect::ScreenShotEffect()
: m_scheduledScreenshot( 0 )
{
- KActionCollection* actionCollection = new KActionCollection( this );
- KAction* cubeAction = static_cast< KAction* >( actionCollection->addAction( "Screenshot Effect" ));
- cubeAction->setText( i18n("Save screenshot of active window" ));
- cubeAction->setGlobalShortcut( KShortcut(), KAction::ActiveShortcut);
- connect( cubeAction, SIGNAL(triggered(bool)), SLOT(screenshot()) );
+ QDBusConnection::sessionBus().registerObject( "/Screenshot", this, QDBusConnection::ExportScriptableContents );
+ QDBusConnection::sessionBus().registerService( "org.kde.kwin.Screenshot" );
}
ScreenShotEffect::~ScreenShotEffect()
{
+ QDBusConnection::sessionBus().unregisterObject( "/Screenshot" );
+ QDBusConnection::sessionBus().unregisterService( "org.kde.kwin.Screenshot" );
}
void ScreenShotEffect::postPaintScreen()
{
@@ -71,13 +74,36 @@ void ScreenShotEffect::postPaintScreen()
double top = 0;
double right = m_scheduledScreenshot->width();
double bottom = m_scheduledScreenshot->height();
- foreach( const WindowQuad& quad, d.quads )
+ if( m_scheduledScreenshot->hasDecoration() && m_type & INCLUDE_DECORATION )
{
- // we need this loop to include the decoration padding
- left = qMin(left, quad.left());
- top = qMin(top, quad.top());
- right = qMax(right, quad.right());
- bottom = qMax(bottom, quad.bottom());
+ foreach( const WindowQuad& quad, d.quads )
+ {
+ // we need this loop to include the decoration padding
+ left = qMin(left, quad.left());
+ top = qMin(top, quad.top());
+ right = qMax(right, quad.right());
+ bottom = qMax(bottom, quad.bottom());
+ }
+ }
+ else if( m_scheduledScreenshot->hasDecoration() )
+ {
+ WindowQuadList newQuads;
+ left = m_scheduledScreenshot->width();
+ top = m_scheduledScreenshot->height();
+ right = 0;
+ bottom = 0;
+ foreach( const WindowQuad& quad, d.quads )
+ {
+ if( quad.type() == WindowQuadContents )
+ {
+ newQuads << quad;
+ left = qMin(left, quad.left());
+ top = qMin(top, quad.top());
+ right = qMax(right, quad.right());
+ bottom = qMax(bottom, quad.bottom());
+ }
+ }
+ d.quads = newQuads;
}
int width = right - left;
int height = bottom - top;
@@ -103,17 +129,12 @@ void ScreenShotEffect::postPaintScreen()
tex->unbind();
delete tex;
ScreenShotEffect::convertFromGLImage( img, width, height );
-
- // save screenshot in home directory
- QString filePart( QDir::homePath() + '/' + m_scheduledScreenshot->caption() );
- QString file( filePart + ".png" );
- int counter = 1;
- while( QFile::exists( file ) )
+ if( m_type & INCLUDE_CURSOR )
{
- file = QString( filePart + '_' + QString::number( counter ) + ".png" );
- counter++;
+ grabPointerImage( img, m_scheduledScreenshot->x() + left, m_scheduledScreenshot->y() + top );
}
- img.save( file );
+ m_lastScreenshot = QPixmap::fromImage( img );
+ emit screenshotCreated( m_lastScreenshot.handle() );
}
delete offscreenTexture;
delete target;
@@ -121,13 +142,46 @@ void ScreenShotEffect::postPaintScreen()
}
}
-void ScreenShotEffect::screenshot()
+void ScreenShotEffect::screenshotWindowUnderCursor(int mask)
{
- EffectWindow* w = effects->activeWindow();
- m_scheduledScreenshot = w;
- w->addRepaintFull();
+ m_type = (ScreenShotType)mask;
+ const QPoint cursor = effects->cursorPos();
+ foreach( EffectWindow* w, effects->stackingOrder() )
+ {
+ if( w->geometry().contains( cursor ) && w->isOnCurrentDesktop() && !w->isMinimized() )
+ {
+ m_scheduledScreenshot = w;
+ }
+ }
+ if( m_scheduledScreenshot )
+ {
+ m_scheduledScreenshot->addRepaintFull();
+ }
}
+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 )
+ 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::Format_ARGB32_Premultiplied);
+
+ QPainter painter(&snapshot);
+ painter.drawImage(QPointF(xcursorimg->x - xcursorimg->xhot - offsetx, xcursorimg->y - xcursorimg ->yhot - offsety), qcursorimg);
+
+ XFree(xcursorimg);
+}
+
void ScreenShotEffect::convertFromGLImage(QImage &img, int w, int h)
{
// from QtOpenGL/qgl.cpp
diff --git a/effects/screenshot/screenshot.h b/effects/screenshot/screenshot.h
index 41cc8b006f..b1d98e8fbc 100644
--- a/effects/screenshot/screenshot.h
+++ b/effects/screenshot/screenshot.h
@@ -23,6 +23,7 @@ along with this program. If not, see .
#include
#include
+#include
namespace KWin
{
@@ -30,7 +31,13 @@ namespace KWin
class ScreenShotEffect : public QObject, public Effect
{
Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "org.kde.kwin.Screenshot")
public:
+ enum ScreenShotType
+ {
+ INCLUDE_DECORATION = 1 << 0,
+ INCLUDE_CURSOR = 1 << 1
+ };
ScreenShotEffect();
virtual ~ScreenShotEffect();
virtual void postPaintScreen();
@@ -38,10 +45,16 @@ class ScreenShotEffect : public QObject, public Effect
static bool supported();
static void convertFromGLImage(QImage &img, int w, int h);
public Q_SLOTS:
- void screenshot();
+ Q_SCRIPTABLE void screenshotWindowUnderCursor( int mask = 0 );
+
+ Q_SIGNALS:
+ Q_SCRIPTABLE void screenshotCreated( qulonglong handle );
private:
+ void grabPointerImage( QImage& snapshot, int offsetx, int offsety );
EffectWindow *m_scheduledScreenshot;
+ ScreenShotType m_type;
+ QPixmap m_lastScreenshot;
};
} // namespace