[effects] Delay taking screenshot into next rendering cycle
Summary: For windows the screenshot effect already delayed the rendering into the next cycle. But for the fullscreen variants which save to a file the Screenshot effect did try to take the shot directly. This can be problematic as e.g. the OpenGL context might not be bound at all. Also this makes it impossible to screenshot multiple screens together in the Wayland case. This change delays the DBus replies, schedules the geometry and takes the screenshot in the next rendering pass. It does not fix the multiscreen wayland problem yet. Reviewers: #kwin Subscribers: kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D3052icc-effect-5.14.5
parent
b545785325
commit
e9b25f176a
|
@ -41,6 +41,7 @@ bool ScreenShotEffect::supported()
|
||||||
|
|
||||||
ScreenShotEffect::ScreenShotEffect()
|
ScreenShotEffect::ScreenShotEffect()
|
||||||
: m_scheduledScreenshot(0)
|
: m_scheduledScreenshot(0)
|
||||||
|
, m_replyConnection(QDBusConnection::sessionBus())
|
||||||
{
|
{
|
||||||
connect ( effects, SIGNAL(windowClosed(KWin::EffectWindow*)), SLOT(windowClosed(KWin::EffectWindow*)) );
|
connect ( effects, SIGNAL(windowClosed(KWin::EffectWindow*)), SLOT(windowClosed(KWin::EffectWindow*)) );
|
||||||
QDBusConnection::sessionBus().registerObject(QStringLiteral("/Screenshot"), this, QDBusConnection::ExportScriptableContents);
|
QDBusConnection::sessionBus().registerObject(QStringLiteral("/Screenshot"), this, QDBusConnection::ExportScriptableContents);
|
||||||
|
@ -177,6 +178,11 @@ void ScreenShotEffect::postPaintScreen()
|
||||||
}
|
}
|
||||||
m_scheduledScreenshot = NULL;
|
m_scheduledScreenshot = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!m_scheduledGeometry.isNull()) {
|
||||||
|
m_replyConnection.send(m_replyMessage.createReply(blitScreenshot(m_scheduledGeometry)));
|
||||||
|
m_scheduledGeometry = QRect();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenShotEffect::screenshotWindowUnderCursor(int mask)
|
void ScreenShotEffect::screenshotWindowUnderCursor(int mask)
|
||||||
|
@ -210,17 +216,62 @@ void ScreenShotEffect::screenshotForWindow(qulonglong winid, int mask)
|
||||||
|
|
||||||
QString ScreenShotEffect::screenshotFullscreen()
|
QString ScreenShotEffect::screenshotFullscreen()
|
||||||
{
|
{
|
||||||
return blitScreenshot(effects->virtualScreenGeometry());
|
if (!calledFromDBus()) {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
if (!m_scheduledGeometry.isNull()) {
|
||||||
|
sendErrorReply(QDBusError::Failed, "A screenshot is already been taken");
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
m_replyConnection = connection();
|
||||||
|
m_replyMessage = message();
|
||||||
|
setDelayedReply(true);
|
||||||
|
m_scheduledGeometry = effects->virtualScreenGeometry();
|
||||||
|
effects->addRepaintFull();
|
||||||
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ScreenShotEffect::screenshotScreen(int screen)
|
QString ScreenShotEffect::screenshotScreen(int screen)
|
||||||
{
|
{
|
||||||
return blitScreenshot(effects->clientArea(FullScreenArea, screen, 0));
|
if (!calledFromDBus()) {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
if (!m_scheduledGeometry.isNull()) {
|
||||||
|
sendErrorReply(QDBusError::Failed, "A screenshot is already been taken");
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
m_scheduledGeometry = effects->clientArea(FullScreenArea, screen, 0);
|
||||||
|
if (m_scheduledGeometry.isNull()) {
|
||||||
|
sendErrorReply(QDBusError::Failed, "Invalid screen requested");
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
m_replyConnection = connection();
|
||||||
|
m_replyMessage = message();
|
||||||
|
setDelayedReply(true);
|
||||||
|
effects->addRepaint(m_scheduledGeometry);
|
||||||
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ScreenShotEffect::screenshotArea(int x, int y, int width, int height)
|
QString ScreenShotEffect::screenshotArea(int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
return blitScreenshot(QRect(x, y, width, height));
|
if (!calledFromDBus()) {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
if (!m_scheduledGeometry.isNull()) {
|
||||||
|
sendErrorReply(QDBusError::Failed, "A screenshot is already been taken");
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
m_scheduledGeometry = QRect(x, y, width, height);
|
||||||
|
if (m_scheduledGeometry.isNull() || m_scheduledGeometry.isEmpty()) {
|
||||||
|
m_scheduledGeometry = QRect();
|
||||||
|
sendErrorReply(QDBusError::Failed, "Invalid area requested");
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
m_replyConnection = connection();
|
||||||
|
m_replyMessage = message();
|
||||||
|
setDelayedReply(true);
|
||||||
|
effects->addRepaint(m_scheduledGeometry);
|
||||||
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ScreenShotEffect::blitScreenshot(const QRect &geometry)
|
QString ScreenShotEffect::blitScreenshot(const QRect &geometry)
|
||||||
|
@ -321,7 +372,7 @@ void ScreenShotEffect::convertFromGLImage(QImage &img, int w, int h)
|
||||||
|
|
||||||
bool ScreenShotEffect::isActive() const
|
bool ScreenShotEffect::isActive() const
|
||||||
{
|
{
|
||||||
return m_scheduledScreenshot != NULL && !effects->isScreenLocked();
|
return (m_scheduledScreenshot != NULL || !m_scheduledGeometry.isNull()) && !effects->isScreenLocked();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenShotEffect::windowClosed( EffectWindow* w )
|
void ScreenShotEffect::windowClosed( EffectWindow* w )
|
||||||
|
|
|
@ -22,13 +22,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#define KWIN_SCREENSHOT_H
|
#define KWIN_SCREENSHOT_H
|
||||||
|
|
||||||
#include <kwineffects.h>
|
#include <kwineffects.h>
|
||||||
|
#include <QDBusContext>
|
||||||
|
#include <QDBusConnection>
|
||||||
|
#include <QDBusMessage>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
|
|
||||||
namespace KWin
|
namespace KWin
|
||||||
{
|
{
|
||||||
|
|
||||||
class ScreenShotEffect : public Effect
|
class ScreenShotEffect : public Effect, protected QDBusContext
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_CLASSINFO("D-Bus Interface", "org.kde.kwin.Screenshot")
|
Q_CLASSINFO("D-Bus Interface", "org.kde.kwin.Screenshot")
|
||||||
|
@ -86,6 +89,9 @@ private:
|
||||||
QString blitScreenshot(const QRect &geometry);
|
QString blitScreenshot(const QRect &geometry);
|
||||||
EffectWindow *m_scheduledScreenshot;
|
EffectWindow *m_scheduledScreenshot;
|
||||||
ScreenShotType m_type;
|
ScreenShotType m_type;
|
||||||
|
QRect m_scheduledGeometry;
|
||||||
|
QDBusConnection m_replyConnection;
|
||||||
|
QDBusMessage m_replyMessage;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
Loading…
Reference in New Issue