Notify effects when the screen gets locked
EffectsHandlerImpl starts to monitor DBus for the screen being locked and provides this information to the Effect system by allowing them to ask whether the screen is currently locked and by emitting a signal when the screen gets locked/unlocked. This information is needed to ensure that no private data is shown on the screen. The following effects are adjusted: * taskbar thumbnails * thumbnail aside * mouse mark * screen shot BUG: 255712 FIXED-IN: 4.11 REVIEW: 108670
This commit is contained in:
parent
beb00478e1
commit
10c07080bb
11 changed files with 182 additions and 6 deletions
|
@ -176,6 +176,8 @@ qt4_add_dbus_adaptor( kwin_KDEINIT_SRCS org.kde.kwin.Effects.xml effects.h KWin:
|
|||
|
||||
qt4_add_dbus_interface( kwin_KDEINIT_SRCS
|
||||
${KDEBASE_WORKSPACE_SOURCE_DIR}/ksmserver/org.kde.KSMServerInterface.xml ksmserver_interface)
|
||||
qt4_add_dbus_interface( kwin_KDEINIT_SRCS
|
||||
${KDEBASE_WORKSPACE_SOURCE_DIR}/ksmserver/screenlocker/dbus/org.freedesktop.ScreenSaver.xml screenlocker_interface)
|
||||
|
||||
qt4_add_resources( kwin_KDEINIT_SRCS resources.qrc )
|
||||
|
||||
|
|
103
effects.cpp
103
effects.cpp
|
@ -45,6 +45,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <QFile>
|
||||
#include <QtCore/QFutureWatcher>
|
||||
#include <QtCore/QtConcurrentRun>
|
||||
#include <QDBusServiceWatcher>
|
||||
#include <QDBusPendingCallWatcher>
|
||||
|
||||
#include "kdebug.h"
|
||||
#include "klibrary.h"
|
||||
|
@ -60,10 +62,104 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "composite.h"
|
||||
#include "xcbutils.h"
|
||||
|
||||
// dbus generated
|
||||
#include "screenlocker_interface.h"
|
||||
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
static const QString SCREEN_LOCKER_SERVICE_NAME = QString("org.freedesktop.ScreenSaver");
|
||||
|
||||
ScreenLockerWatcher::ScreenLockerWatcher(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_interface(NULL)
|
||||
, m_serviceWatcher(new QDBusServiceWatcher(this))
|
||||
, m_locked(false)
|
||||
{
|
||||
connect(m_serviceWatcher, SIGNAL(serviceOwnerChanged(QString,QString,QString)), SLOT(serviceOwnerChanged(QString,QString,QString)));
|
||||
m_serviceWatcher->setWatchMode(QDBusServiceWatcher::WatchForOwnerChange);
|
||||
m_serviceWatcher->addWatchedService(SCREEN_LOCKER_SERVICE_NAME);
|
||||
// check whether service is registered
|
||||
QFutureWatcher<QDBusReply<bool> > *watcher = new QFutureWatcher<QDBusReply<bool> >(this);
|
||||
connect(watcher, SIGNAL(finished()), SLOT(serviceRegisteredQueried()));
|
||||
connect(watcher, SIGNAL(canceled()), watcher, SLOT(deleteLater()));
|
||||
watcher->setFuture(QtConcurrent::run(QDBusConnection::sessionBus().interface(),
|
||||
&QDBusConnectionInterface::isServiceRegistered,
|
||||
SCREEN_LOCKER_SERVICE_NAME));
|
||||
}
|
||||
|
||||
ScreenLockerWatcher::~ScreenLockerWatcher()
|
||||
{
|
||||
}
|
||||
|
||||
void ScreenLockerWatcher::serviceOwnerChanged(const QString &serviceName, const QString &oldOwner, const QString &newOwner)
|
||||
{
|
||||
Q_UNUSED(oldOwner)
|
||||
if (serviceName != SCREEN_LOCKER_SERVICE_NAME) {
|
||||
return;
|
||||
}
|
||||
delete m_interface;
|
||||
m_interface = NULL;
|
||||
m_locked = false;
|
||||
if (!newOwner.isEmpty()) {
|
||||
m_interface = new OrgFreedesktopScreenSaverInterface(newOwner, QString(), QDBusConnection::sessionBus(), this);
|
||||
connect(m_interface, SIGNAL(ActiveChanged(bool)), SLOT(setLocked(bool)));
|
||||
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(m_interface->GetActive(), this);
|
||||
connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), SLOT(activeQueried(QDBusPendingCallWatcher*)));
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenLockerWatcher::serviceRegisteredQueried()
|
||||
{
|
||||
QFutureWatcher<QDBusReply<bool> > *watcher = dynamic_cast<QFutureWatcher<QDBusReply<bool> > *>(sender());
|
||||
if (!watcher) {
|
||||
return;
|
||||
}
|
||||
const QDBusReply<bool> &reply = watcher->result();
|
||||
if (reply.isValid() && reply.value()) {
|
||||
QFutureWatcher<QDBusReply<QString> > *ownerWatcher = new QFutureWatcher<QDBusReply<QString> >(this);
|
||||
connect(ownerWatcher, SIGNAL(finished()), SLOT(serviceOwnerQueried()));
|
||||
connect(ownerWatcher, SIGNAL(canceled()), ownerWatcher, SLOT(deleteLater()));
|
||||
ownerWatcher->setFuture(QtConcurrent::run(QDBusConnection::sessionBus().interface(),
|
||||
&QDBusConnectionInterface::serviceOwner,
|
||||
SCREEN_LOCKER_SERVICE_NAME));
|
||||
}
|
||||
watcher->deleteLater();
|
||||
}
|
||||
|
||||
void ScreenLockerWatcher::serviceOwnerQueried()
|
||||
{
|
||||
QFutureWatcher<QDBusReply<QString> > *watcher = dynamic_cast<QFutureWatcher<QDBusReply<QString> > *>(sender());
|
||||
if (!watcher) {
|
||||
return;
|
||||
}
|
||||
const QDBusReply<QString> reply = watcher->result();
|
||||
if (reply.isValid()) {
|
||||
serviceOwnerChanged(SCREEN_LOCKER_SERVICE_NAME, QString(), reply.value());
|
||||
}
|
||||
|
||||
watcher->deleteLater();
|
||||
}
|
||||
|
||||
void ScreenLockerWatcher::activeQueried(QDBusPendingCallWatcher *watcher)
|
||||
{
|
||||
QDBusPendingReply<bool> reply = *watcher;
|
||||
if (!reply.isError()) {
|
||||
setLocked(reply.value());
|
||||
}
|
||||
watcher->deleteLater();
|
||||
}
|
||||
|
||||
void ScreenLockerWatcher::setLocked(bool activated)
|
||||
{
|
||||
if (m_locked == activated) {
|
||||
return;
|
||||
}
|
||||
m_locked = activated;
|
||||
emit locked(m_locked);
|
||||
}
|
||||
|
||||
//---------------------
|
||||
// Static
|
||||
|
||||
|
@ -112,6 +208,7 @@ EffectsHandlerImpl::EffectsHandlerImpl(Compositor *compositor, Scene *scene)
|
|||
, mouse_poll_ref_count(0)
|
||||
, m_compositor(compositor)
|
||||
, m_scene(scene)
|
||||
, m_screenLockerWatcher(new ScreenLockerWatcher(this))
|
||||
{
|
||||
new EffectsAdaptor(this);
|
||||
QDBusConnection dbus = QDBusConnection::sessionBus();
|
||||
|
@ -144,6 +241,7 @@ EffectsHandlerImpl::EffectsHandlerImpl(Compositor *compositor, Scene *scene)
|
|||
#ifdef KWIN_BUILD_SCREENEDGES
|
||||
connect(ScreenEdges::self(), SIGNAL(approaching(ElectricBorder,qreal,QRect)), SIGNAL(screenEdgeApproaching(ElectricBorder,qreal,QRect)));
|
||||
#endif
|
||||
connect(m_screenLockerWatcher, SIGNAL(locked(bool)), SIGNAL(screenLockingChanged(bool)));
|
||||
// connect all clients
|
||||
foreach (Client *c, ws->clientList()) {
|
||||
setupClientConnections(c);
|
||||
|
@ -1536,6 +1634,11 @@ QString EffectsHandlerImpl::supportInformation(const QString &name) const
|
|||
return QString();
|
||||
}
|
||||
|
||||
bool EffectsHandlerImpl::isScreenLocked() const
|
||||
{
|
||||
return m_screenLockerWatcher->isLocked();
|
||||
}
|
||||
|
||||
//****************************************
|
||||
// EffectWindowImpl
|
||||
//****************************************
|
||||
|
|
30
effects.h
30
effects.h
|
@ -30,8 +30,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <QHash>
|
||||
#include <Plasma/FrameSvg>
|
||||
|
||||
|
||||
class QDBusPendingCallWatcher;
|
||||
class QDBusServiceWatcher;
|
||||
class KService;
|
||||
class OrgFreedesktopScreenSaverInterface;
|
||||
|
||||
|
||||
namespace KWin
|
||||
|
@ -44,6 +46,7 @@ class Client;
|
|||
class Compositor;
|
||||
class Deleted;
|
||||
class Unmanaged;
|
||||
class ScreenLockerWatcher;
|
||||
|
||||
class EffectsHandlerImpl : public EffectsHandler
|
||||
{
|
||||
|
@ -160,6 +163,7 @@ public:
|
|||
virtual EffectFrame* effectFrame(EffectFrameStyle style, bool staticSize, const QPoint& position, Qt::Alignment alignment) const;
|
||||
|
||||
virtual QVariant kwinOption(KWinOption kwopt);
|
||||
virtual bool isScreenLocked() const;
|
||||
|
||||
// internal (used by kwin core or compositing code)
|
||||
void startPaint();
|
||||
|
@ -241,6 +245,7 @@ private:
|
|||
Compositor *m_compositor;
|
||||
Scene *m_scene;
|
||||
QList< InputWindowPair > input_windows;
|
||||
ScreenLockerWatcher *m_screenLockerWatcher;
|
||||
};
|
||||
|
||||
class EffectWindowImpl : public EffectWindow
|
||||
|
@ -386,6 +391,29 @@ private:
|
|||
GLShader* m_shader;
|
||||
};
|
||||
|
||||
class ScreenLockerWatcher : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ScreenLockerWatcher(QObject *parent = 0);
|
||||
virtual ~ScreenLockerWatcher();
|
||||
bool isLocked() const {
|
||||
return m_locked;
|
||||
}
|
||||
Q_SIGNALS:
|
||||
void locked(bool locked);
|
||||
private Q_SLOTS:
|
||||
void setLocked(bool activated);
|
||||
void activeQueried(QDBusPendingCallWatcher *watcher);
|
||||
void serviceOwnerChanged(const QString &serviceName, const QString &oldOwner, const QString &newOwner);
|
||||
void serviceRegisteredQueried();
|
||||
void serviceOwnerQueried();
|
||||
private:
|
||||
OrgFreedesktopScreenSaverInterface *m_interface;
|
||||
QDBusServiceWatcher *m_serviceWatcher;
|
||||
bool m_locked;
|
||||
};
|
||||
|
||||
inline
|
||||
QList<EffectWindow*> EffectsHandlerImpl::elevatedWindows() const
|
||||
{
|
||||
|
|
|
@ -59,6 +59,7 @@ MouseMarkEffect::MouseMarkEffect()
|
|||
connect(a, SIGNAL(triggered(bool)), this, SLOT(clearLast()));
|
||||
connect(effects, SIGNAL(mouseChanged(QPoint,QPoint,Qt::MouseButtons,Qt::MouseButtons,Qt::KeyboardModifiers,Qt::KeyboardModifiers)),
|
||||
this, SLOT(slotMouseChanged(QPoint,QPoint,Qt::MouseButtons,Qt::MouseButtons,Qt::KeyboardModifiers,Qt::KeyboardModifiers)));
|
||||
connect(effects, SIGNAL(screenLockingChanged(bool)), SLOT(screenLockingChanged(bool)));
|
||||
reconfigure(ReconfigureAll);
|
||||
arrow_start = NULL_POINT;
|
||||
effects->startMousePolling(); // We require it to detect activation as well
|
||||
|
@ -239,9 +240,22 @@ MouseMarkEffect::Mark MouseMarkEffect::createArrow(QPoint arrow_start, QPoint ar
|
|||
return ret;
|
||||
}
|
||||
|
||||
void MouseMarkEffect::screenLockingChanged(bool locked)
|
||||
{
|
||||
if (!marks.isEmpty() || !drawing.isEmpty()) {
|
||||
effects->addRepaintFull();
|
||||
}
|
||||
// disable mouse polling while screen is locked.
|
||||
if (locked) {
|
||||
effects->stopMousePolling();
|
||||
} else {
|
||||
effects->startMousePolling();
|
||||
}
|
||||
}
|
||||
|
||||
bool MouseMarkEffect::isActive() const
|
||||
{
|
||||
return !marks.isEmpty() || !drawing.isEmpty();
|
||||
return (!marks.isEmpty() || !drawing.isEmpty()) && !effects->isScreenLocked();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ private slots:
|
|||
void slotMouseChanged(const QPoint& pos, const QPoint& old,
|
||||
Qt::MouseButtons buttons, Qt::MouseButtons oldbuttons,
|
||||
Qt::KeyboardModifiers modifiers, Qt::KeyboardModifiers oldmodifiers);
|
||||
void screenLockingChanged(bool locked);
|
||||
private:
|
||||
typedef QVector< QPoint > Mark;
|
||||
static Mark createArrow(QPoint arrow_start, QPoint arrow_end);
|
||||
|
|
|
@ -353,7 +353,7 @@ void ScreenShotEffect::convertFromGLImage(QImage &img, int w, int h)
|
|||
|
||||
bool ScreenShotEffect::isActive() const
|
||||
{
|
||||
return m_scheduledScreenshot != NULL;
|
||||
return m_scheduledScreenshot != NULL && !effects->isScreenLocked();
|
||||
}
|
||||
|
||||
void ScreenShotEffect::windowClosed( EffectWindow* w )
|
||||
|
|
|
@ -41,6 +41,7 @@ TaskbarThumbnailEffect::TaskbarThumbnailEffect()
|
|||
connect(effects, SIGNAL(windowDeleted(KWin::EffectWindow*)), this, SLOT(slotWindowDeleted(KWin::EffectWindow*)));
|
||||
connect(effects, SIGNAL(windowDamaged(KWin::EffectWindow*,QRect)), this, SLOT(slotWindowDamaged(KWin::EffectWindow*,QRect)));
|
||||
connect(effects, SIGNAL(propertyNotify(KWin::EffectWindow*,long)), this, SLOT(slotPropertyNotify(KWin::EffectWindow*,long)));
|
||||
connect(effects, SIGNAL(screenLockingChanged(bool)), SLOT(screenLockingChanged()));
|
||||
}
|
||||
|
||||
TaskbarThumbnailEffect::~TaskbarThumbnailEffect()
|
||||
|
@ -147,9 +148,16 @@ void TaskbarThumbnailEffect::slotPropertyNotify(EffectWindow* w, long a)
|
|||
}
|
||||
}
|
||||
|
||||
void TaskbarThumbnailEffect::screenLockingChanged()
|
||||
{
|
||||
foreach (EffectWindow *window, thumbnails.uniqueKeys()) {
|
||||
window->addRepaintFull();
|
||||
}
|
||||
}
|
||||
|
||||
bool TaskbarThumbnailEffect::isActive() const
|
||||
{
|
||||
return !thumbnails.isEmpty();
|
||||
return !thumbnails.isEmpty() && !effects->isScreenLocked();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -45,6 +45,7 @@ public Q_SLOTS:
|
|||
void slotWindowDeleted(KWin::EffectWindow *w);
|
||||
void slotWindowDamaged(KWin::EffectWindow* w, const QRect& damage);
|
||||
void slotPropertyNotify(KWin::EffectWindow *w, long atom);
|
||||
void screenLockingChanged();
|
||||
private:
|
||||
struct Data {
|
||||
Window window; // thumbnail of this window
|
||||
|
|
|
@ -42,6 +42,7 @@ ThumbnailAsideEffect::ThumbnailAsideEffect()
|
|||
connect(effects, SIGNAL(windowClosed(KWin::EffectWindow*)), this, SLOT(slotWindowClosed(KWin::EffectWindow*)));
|
||||
connect(effects, SIGNAL(windowGeometryShapeChanged(KWin::EffectWindow*,QRect)), this, SLOT(slotWindowGeometryShapeChanged(KWin::EffectWindow*,QRect)));
|
||||
connect(effects, SIGNAL(windowDamaged(KWin::EffectWindow*,QRect)), this, SLOT(slotWindowDamaged(KWin::EffectWindow*,QRect)));
|
||||
connect(effects, SIGNAL(screenLockingChanged(bool)), SLOT(repaintAll()));
|
||||
reconfigure(ReconfigureAll);
|
||||
}
|
||||
|
||||
|
@ -182,7 +183,7 @@ void ThumbnailAsideEffect::repaintAll()
|
|||
|
||||
bool ThumbnailAsideEffect::isActive() const
|
||||
{
|
||||
return !windows.isEmpty();
|
||||
return !windows.isEmpty() && !effects->isScreenLocked();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -68,11 +68,11 @@ private slots:
|
|||
void slotWindowGeometryShapeChanged(KWin::EffectWindow *w, const QRect &old);
|
||||
void slotWindowDamaged(KWin::EffectWindow* w, const QRect& damage);
|
||||
virtual bool isActive() const;
|
||||
void repaintAll();
|
||||
private:
|
||||
void addThumbnail(EffectWindow* w);
|
||||
void removeThumbnail(EffectWindow* w);
|
||||
void arrange();
|
||||
void repaintAll();
|
||||
struct Data {
|
||||
EffectWindow* window; // the same like the key in the hash (makes code simpler)
|
||||
int index;
|
||||
|
|
|
@ -875,6 +875,18 @@ public:
|
|||
**/
|
||||
virtual void reloadEffect(Effect *effect) = 0;
|
||||
|
||||
/**
|
||||
* Whether the screen is currently considered as locked.
|
||||
* Note for technical reasons this is not always possible to detect. The screen will only
|
||||
* be considered as locked if the screen locking process implements the
|
||||
* org.freedesktop.ScreenSaver interface.
|
||||
*
|
||||
* @returns @c true if the screen is currently locked, @c false otherwise
|
||||
* @see screenLockingChanged
|
||||
* @since 4.11
|
||||
**/
|
||||
virtual bool isScreenLocked() const = 0;
|
||||
|
||||
/**
|
||||
* Sends message over DCOP to reload given effect.
|
||||
* @param effectname effect's name without "kwin4_effect_" prefix.
|
||||
|
@ -1155,6 +1167,12 @@ Q_SIGNALS:
|
|||
* @since 4.9
|
||||
*/
|
||||
void activityRemoved(const QString &id);
|
||||
/**
|
||||
* This signal is emitted when the screen got locked or unlocked.
|
||||
* @param locked @c true if the screen is now locked, @c false if it is now unlocked
|
||||
* @since 4.11
|
||||
**/
|
||||
void screenLockingChanged(bool locked);
|
||||
|
||||
/**
|
||||
* This signels is emitted when ever the stacking order is change, ie. a window is risen
|
||||
|
|
Loading…
Reference in a new issue