From a8d432483204f80e11c83ea9dbc311882d9289d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sl=C3=A1vek=20Banko?= Date: Tue, 25 Feb 2014 19:17:41 +0100 Subject: Add systemd support into kdesktop + response to systemd signal Lock() + setting SetIdleHint(true / false) by screen saver activity --- kdesktop/CMakeLists.txt | 5 +- kdesktop/lockeng.cc | 196 +++++++++++++++++++++++++++++++++++++++++++++++- kdesktop/lockeng.h | 15 ++++ 3 files changed, 214 insertions(+), 2 deletions(-) (limited to 'kdesktop') diff --git a/kdesktop/CMakeLists.txt b/kdesktop/CMakeLists.txt index 0acb0a48a..80ea9c21a 100644 --- a/kdesktop/CMakeLists.txt +++ b/kdesktop/CMakeLists.txt @@ -32,11 +32,14 @@ include_directories( ${CMAKE_SOURCE_DIR}/libkonq ${TDE_INCLUDE_DIR} ${TQT_INCLUDE_DIRS} + ${DBUS_INCLUDE_DIRS} + ${DBUS_1_TQT_INCLUDE_DIRS} ) link_directories( ${TQT_LIBRARY_DIRS} ${LIBART_LIBRARY_DIRS} + ${DBUS_1_TQT_LIBRARY_DIRS} ) @@ -95,7 +98,7 @@ tde_add_tdeinit_executable( ${target} AUTOMOC kdesktopsettings-static bgnd-static dmctl-static konq-shared tdeutils-shared ${XRENDER_LIBRARIES} ${XCURSOR_LIBRARIES} Xext dl - ${XSS_LIBRARIES} + ${XSS_LIBRARIES} ${DBUS_1_TQT_LIBRARIES} ) diff --git a/kdesktop/lockeng.cc b/kdesktop/lockeng.cc index 79d3e6771..6d7131253 100644 --- a/kdesktop/lockeng.cc +++ b/kdesktop/lockeng.cc @@ -21,10 +21,25 @@ #include #include +#include +#include +#include +#include +#include +#include + #include "lockeng.h" #include "lockeng.moc" #include "kdesktopsettings.h" +#define SYSTEMD_LOGIN1_SERVICE "org.freedesktop.login1" +#define SYSTEMD_LOGIN1_PATH "/org/freedesktop/login1" +#define SYSTEMD_LOGIN1_MANAGER_IFACE "org.freedesktop.login1.Manager" +#define SYSTEMD_LOGIN1_SESSION_IFACE "org.freedesktop.login1.Session" +#define SYSTEMD_LOGIN1_SEAT_IFACE "org.freedesktop.login1.Seat" + +#define DBUS_CONN_NAME "kdesktop_lock" + #include "xautolock_c.h" extern xautolock_corner_t xautolock_corners[ 4 ]; @@ -62,7 +77,10 @@ SaverEngine::SaverEngine() mBlankOnly(false), mSAKProcess(NULL), mTerminationRequested(false), - mSaverProcessReady(false) + mSaverProcessReady(false), + dBusLocal(0), + dBusWatch(0), + systemdSession(0) { struct sigaction act; @@ -121,6 +139,8 @@ SaverEngine::SaverEngine() { kdDebug( 1204 ) << "Failed to start kdesktop_lock!" << endl; } + + dBusConnect(); } //--------------------------------------------------------------------------- @@ -136,6 +156,8 @@ SaverEngine::~SaverEngine() mLockProcess.detach(); // don't kill it if we crash delete mXAutoLock; + dBusClose(); + // Restore X screensaver parameters XSetScreenSaver(tqt_xdisplay(), mXTimeout, mXInterval, mXBlanking, mXExposures); @@ -467,6 +489,12 @@ void SaverEngine::stopLockProcess() } processLockTransactions(); mState = Waiting; + + if( systemdSession && systemdSession->canSend() ) { + TQValueList params; + params << TQT_DBusData::fromBool(false); + TQT_DBusMessage reply = systemdSession->sendWithReply("SetIdleHint", params); + } } void SaverEngine::recoverFromHackingAttempt() @@ -523,6 +551,12 @@ void SaverEngine::slotLockProcessWaiting() void SaverEngine::slotLockProcessFullyActivated() { mState = Saving; + + if( systemdSession && systemdSession->canSend() ) { + TQValueList params; + params << TQT_DBusData::fromBool(true); + TQT_DBusMessage reply = systemdSession->sendWithReply("SetIdleHint", params); + } } void SaverEngine::slotLockProcessReady() @@ -550,6 +584,12 @@ void SaverEngine::lockProcessWaiting() } processLockTransactions(); mState = Waiting; + + if( systemdSession && systemdSession->canSend() ) { + TQValueList params; + params << TQT_DBusData::fromBool(false); + TQT_DBusMessage reply = systemdSession->sendWithReply("SetIdleHint", params); + } } //--------------------------------------------------------------------------- @@ -590,3 +630,157 @@ xautolock_corner_t SaverEngine::applyManualSettings(int action) return ca_nothing; } } + +/*! + * This function try a reconnect to D-Bus. + * \return boolean with the result of the operation + * \retval true if successful reconnected to D-Bus + * \retval false if unsuccessful + */ +bool SaverEngine::dBusReconnect() { + // close D-Bus connection + dBusClose(); + // init D-Bus conntection + return (dBusConnect()); +} + +/*! + * This function is used to close D-Bus connection. + */ +void SaverEngine::dBusClose() { + if( dBusConn.isConnected() ) { + if( dBusLocal ) { + delete dBusLocal; + dBusLocal = 0; + } + if( dBusWatch ) { + delete dBusWatch; + dBusWatch = 0; + } + if( systemdSession ) { + delete systemdSession; + systemdSession = 0; + } + } + dBusConn.closeConnection(DBUS_CONN_NAME); +} + +/*! + * This function is used to connect to D-Bus. + */ +bool SaverEngine::dBusConnect() { + dBusConn = TQT_DBusConnection::addConnection(TQT_DBusConnection::SystemBus, DBUS_CONN_NAME); + if( !dBusConn.isConnected() ) { + kdError() << "Failed to open connection to system message bus: " << dBusConn.lastError().message() << endl; + TQTimer::singleShot(4000, this, TQT_SLOT(dBusReconnect())); + return false; + } + + // watcher for Disconnect signal + dBusLocal = new TQT_DBusProxy(DBUS_SERVICE_DBUS, DBUS_PATH_LOCAL, DBUS_INTERFACE_LOCAL, dBusConn); + TQObject::connect(dBusLocal, TQT_SIGNAL(dbusSignal(const TQT_DBusMessage&)), + this, TQT_SLOT(handleDBusSignal(const TQT_DBusMessage&))); + + // watcher for NameOwnerChanged signals + dBusWatch = new TQT_DBusProxy(DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, dBusConn); + TQObject::connect(dBusWatch, TQT_SIGNAL(dbusSignal(const TQT_DBusMessage&)), + this, TQT_SLOT(handleDBusSignal(const TQT_DBusMessage&))); + + // find already running SystemD + TQT_DBusProxy checkSystemD(DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, dBusConn); + if( checkSystemD.canSend() ) { + TQValueList params; + params << TQT_DBusData::fromString(SYSTEMD_LOGIN1_SERVICE); + TQT_DBusMessage reply = checkSystemD.sendWithReply("NameHasOwner", params); + if (reply.type() == TQT_DBusMessage::ReplyMessage && reply.count() == 1 && reply[0].toBool() ) { + onDBusServiceRegistered(SYSTEMD_LOGIN1_SERVICE); + } + } + return true; +} + +/*! + * This function handles D-Bus service registering + */ +void SaverEngine::onDBusServiceRegistered(const TQString& service) { + if( service == SYSTEMD_LOGIN1_SERVICE ) { + // get current systemd session + TQT_DBusProxy managerIface(SYSTEMD_LOGIN1_SERVICE, SYSTEMD_LOGIN1_PATH, SYSTEMD_LOGIN1_MANAGER_IFACE, dBusConn); + TQT_DBusObjectPath systemdSessionPath = TQT_DBusObjectPath(); + if( managerIface.canSend() ) { + TQValueList params; + params << TQT_DBusData::fromUInt32( getpid() ); + TQT_DBusMessage reply = managerIface.sendWithReply("GetSessionByPID", params); + if (reply.type() == TQT_DBusMessage::ReplyMessage && reply.count() == 1 ) { + systemdSessionPath = reply[0].toObjectPath(); + } + } + // wather for systemd session signals + if( systemdSessionPath.isValid() ) { + systemdSession = new TQT_DBusProxy(SYSTEMD_LOGIN1_SERVICE, systemdSessionPath, SYSTEMD_LOGIN1_SESSION_IFACE, dBusConn); + TQObject::connect(systemdSession, TQT_SIGNAL(dbusSignal(const TQT_DBusMessage&)), + this, TQT_SLOT(handleDBusSignal(const TQT_DBusMessage&))); + } + return; + } +} + +/*! + * This function handles D-Bus service unregistering + */ +void SaverEngine::onDBusServiceUnregistered(const TQString& service) { + if( service == SYSTEMD_LOGIN1_SERVICE ) { + if( systemdSession ) { + delete systemdSession; + systemdSession = 0; + } + return; + } +} + +/*! + * This function handles signals from the D-Bus daemon. + */ +void SaverEngine::handleDBusSignal(const TQT_DBusMessage& msg) { + // dbus terminated + if( msg.path() == DBUS_PATH_LOCAL + && msg.interface() == DBUS_INTERFACE_LOCAL + && msg.member() == "Disconnected" ) { + dBusClose(); + TQTimer::singleShot(1000, this, TQT_SLOT(dBusReconnect())); + return; + } + + // service registered / unregistered + if( msg.path() == DBUS_PATH_DBUS + && msg.interface() == DBUS_INTERFACE_DBUS + && msg.member() == "NameOwnerChanged" ) { + if( msg[1].toString().isEmpty() ) { + // old-owner is empty + onDBusServiceRegistered(msg[0].toString()); + } + if( msg[2].toString().isEmpty() ) { + // new-owner is empty + onDBusServiceUnregistered(msg[0].toString()); + } + return; + } + + // systemd signal Lock() + if( systemdSession && systemdSession->canSend() + && msg.path() == systemdSession->path() + && msg.interface() == SYSTEMD_LOGIN1_SESSION_IFACE + && msg.member() == "Lock") { + lock(); + return; + } + + // systemd signal Unlock() + if( systemdSession && systemdSession->canSend() + && msg.path() == systemdSession->path() + && msg.interface() == SYSTEMD_LOGIN1_SESSION_IFACE + && msg.member() == "Unlock") { + // unlock? + return; + } +} diff --git a/kdesktop/lockeng.h b/kdesktop/lockeng.h index b211c73e9..70bde3281 100644 --- a/kdesktop/lockeng.h +++ b/kdesktop/lockeng.h @@ -15,7 +15,11 @@ #include "xautolock.h" #include "xautolock_c.h" +#include + class DCOPClientTransaction; +class TQT_DBusMessage; +class TQT_DBusProxy; //=========================================================================== /** @@ -82,6 +86,7 @@ public slots: void slotLockProcessWaiting(); void slotLockProcessFullyActivated(); void slotLockProcessReady(); + void handleDBusSignal(const TQT_DBusMessage&); protected slots: void idleTimeout(); @@ -98,8 +103,14 @@ private slots: void enableExports(); void recoverFromHackingAttempt(); + bool dBusReconnect(); + private: bool restartDesktopLockProcess(); + void dBusClose(); + bool dBusConnect(); + void onDBusServiceRegistered(const TQString&); + void onDBusServiceUnregistered(const TQString&); protected: enum LockType { DontLock, DefaultLock, ForceLock, SecureDialog }; @@ -131,6 +142,10 @@ private: TDEProcess* mSAKProcess; bool mTerminationRequested; bool mSaverProcessReady; + TQT_DBusConnection dBusConn; + TQT_DBusProxy* dBusLocal; + TQT_DBusProxy* dBusWatch; + TQT_DBusProxy* systemdSession; }; #endif -- cgit v1.2.1