|
|
|
/**************************************************************************
|
|
|
|
* Copyright (C) 2006-2007 by Danny Kukawka *
|
|
|
|
* <dkukawka@suse.de>, <danny.kukawka@web.de> *
|
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of version 2 of the GNU General Public License *
|
|
|
|
* as published by the Free Software Foundation. *
|
|
|
|
* *
|
|
|
|
* This program is distributed in the hope that it will be useful, *
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
|
|
* GNU General Public License for more details. *
|
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU General Public License *
|
|
|
|
* along with this program; if not, write to the *
|
|
|
|
* Free Software Foundation, Inc., *
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \file dbusInterface.cpp
|
|
|
|
* \brief In this file can be found the functionality to connect to
|
|
|
|
* the D-Bus, to handle D-Bus session management
|
|
|
|
* \author Danny Kukawka, <dkukawka@suse.de>, <danny.kukawka@web.de>
|
|
|
|
* \date 2006-2007
|
|
|
|
*/
|
|
|
|
|
|
|
|
// QT - Header
|
|
|
|
#include <tqtimer.h>
|
|
|
|
|
|
|
|
// KDE Header
|
|
|
|
#include <tdelocale.h>
|
|
|
|
|
|
|
|
// DBUS - Header
|
|
|
|
#include "dbus/dbus-shared.h"
|
|
|
|
#include "dbusInterface.h"
|
|
|
|
#include <tqdbusdatalist.h>
|
|
|
|
#include <tqdbusdatamap.h>
|
|
|
|
#include <tqdbuserror.h>
|
|
|
|
#include <tqdbusmessage.h>
|
|
|
|
#include <tqdbusvariant.h>
|
|
|
|
|
|
|
|
// system headers
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#define DBUS_CONN_NAME "TDEPowersave"
|
|
|
|
|
|
|
|
static void* myInstance = 0;
|
|
|
|
|
|
|
|
/*! The default constructor of the class dbusInterface. */
|
|
|
|
dbusInterface::dbusInterface():
|
|
|
|
dBusConn(),
|
|
|
|
dBusWatch(0),
|
|
|
|
dBusLocal(0),
|
|
|
|
systemdSession(),
|
|
|
|
systemdSeat(0),
|
|
|
|
systemdInhibit(-1),
|
|
|
|
consolekitSession(),
|
|
|
|
consolekitSeat(0)
|
|
|
|
{
|
|
|
|
kdDebugFuncIn(trace);
|
|
|
|
|
|
|
|
// add pointer to this for filter_function()
|
|
|
|
myInstance=this;
|
|
|
|
|
|
|
|
// init connection to dbus
|
|
|
|
initDBUS();
|
|
|
|
|
|
|
|
kdDebugFuncOut(trace);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! This is the default destructor of class dbusPowersaveConnection. */
|
|
|
|
dbusInterface::~dbusInterface(){
|
|
|
|
kdDebugFuncIn(trace);
|
|
|
|
|
|
|
|
close();
|
|
|
|
myInstance = NULL;
|
|
|
|
|
|
|
|
kdDebugFuncOut(trace);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* This function return information about connection status to the DBUS daemon.
|
|
|
|
* \return boolean with the state of the connection to D-Bus
|
|
|
|
* \retval true if connected
|
|
|
|
* \retval false if disconnected
|
|
|
|
*/
|
|
|
|
bool dbusInterface::isConnectedToDBUS() {
|
|
|
|
return dBusConn.isConnected();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* 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 dbusInterface::reconnect() {
|
|
|
|
// close D-Bus connection
|
|
|
|
close();
|
|
|
|
// init D-Bus conntection
|
|
|
|
return (initDBUS());
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* This function close the connection to powersave over the D-Bus daemon.
|
|
|
|
* \return boolean with the result of the operation
|
|
|
|
* \retval true if successful closed the connection
|
|
|
|
* \retval false if any problems
|
|
|
|
*/
|
|
|
|
bool dbusInterface::close() {
|
|
|
|
if( dBusConn.isConnected() ) {
|
|
|
|
if( dBusWatch ) {
|
|
|
|
delete dBusWatch;
|
|
|
|
}
|
|
|
|
if( dBusLocal ) {
|
|
|
|
delete dBusLocal;
|
|
|
|
}
|
|
|
|
if( systemdSeat ) {
|
|
|
|
delete systemdSeat;
|
|
|
|
}
|
|
|
|
if( consolekitSeat ) {
|
|
|
|
delete consolekitSeat;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dBusConn.closeConnection(DBUS_CONN_NAME);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* This function initialise the connection to the D-Bus daemon.
|
|
|
|
* \return boolean with the result of the operation
|
|
|
|
* \retval true if successful initialised D-Bus connection
|
|
|
|
* \retval false if unsuccessful
|
|
|
|
*/
|
|
|
|
bool dbusInterface::initDBUS(){
|
|
|
|
kdDebugFuncIn(trace);
|
|
|
|
|
|
|
|
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(reconnect()));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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&)));
|
|
|
|
|
|
|
|
// 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&)));
|
|
|
|
|
|
|
|
// find already running SystemD
|
|
|
|
TQT_DBusProxy checkSystemD(DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, dBusConn);
|
|
|
|
if( checkSystemD.canSend() ) {
|
|
|
|
TQValueList<TQT_DBusData> 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() ) {
|
|
|
|
onServiceRegistered(SYSTEMD_LOGIN1_SERVICE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// find already running ConsoleKit
|
|
|
|
TQT_DBusProxy checkConsoleKit(DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, dBusConn);
|
|
|
|
if( checkConsoleKit.canSend() ) {
|
|
|
|
TQValueList<TQT_DBusData> params;
|
|
|
|
params << TQT_DBusData::fromString(CK_SERVICE);
|
|
|
|
TQT_DBusMessage reply = checkConsoleKit.sendWithReply("NameHasOwner", params);
|
|
|
|
if (reply.type() == TQT_DBusMessage::ReplyMessage && reply.count() == 1 && reply[0].toBool() ) {
|
|
|
|
onServiceRegistered(CK_SERVICE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
kdDebugFuncOut(trace);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* This function handles signals from the D-Bus daemon.
|
|
|
|
*/
|
|
|
|
void dbusInterface::handleDBusSignal(const TQT_DBusMessage& msg) {
|
|
|
|
// dbus terminated
|
|
|
|
if( msg.path() == DBUS_PATH_LOCAL
|
|
|
|
&& msg.interface() == DBUS_INTERFACE_LOCAL
|
|
|
|
&& msg.member() == "Disconnected" ) {
|
|
|
|
close();
|
|
|
|
TQTimer::singleShot(1000, this, TQT_SLOT(reconnect()));
|
|
|
|
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
|
|
|
|
onServiceRegistered(msg[0].toString());
|
|
|
|
}
|
|
|
|
if( msg[2].toString().isEmpty() ) {
|
|
|
|
// new-owner is empty
|
|
|
|
onServiceUnregistered(msg[0].toString());
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// systemd session changed
|
|
|
|
if( systemdSeat && systemdSeat->canSend()
|
|
|
|
&& msg.path() == systemdSeat->path()
|
|
|
|
&& msg.interface() == DBUS_INTERFACE_PROPERTIES
|
|
|
|
&& msg.member() == "PropertiesChanged"
|
|
|
|
&& msg[0].toString() == SYSTEMD_LOGIN1_SEAT_IFACE) {
|
|
|
|
bool activeSessionProperty = false;
|
|
|
|
TQT_DBusDataMap<TQString> map = msg[1].toStringKeyMap();
|
|
|
|
TQT_DBusDataMap<TQString>::const_iterator it = map.begin();
|
|
|
|
for (; !activeSessionProperty && it != map.end(); ++it) {
|
|
|
|
if( it.key() != "ActiveSession" ) {
|
|
|
|
activeSessionProperty = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TQValueList<TQString> list = msg[2].toList().toStringList();
|
|
|
|
TQValueList<TQString>::const_iterator it1 = list.begin();
|
|
|
|
for (; !activeSessionProperty && it1 != list.end(); ++it1) {
|
|
|
|
if( (*it1) == "ActiveSession" ) {
|
|
|
|
activeSessionProperty = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( activeSessionProperty ) {
|
|
|
|
emit activeSessionChanged(checkActiveSession());
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// consolekit session changed
|
|
|
|
if( consolekitSeat && consolekitSeat->canSend()
|
|
|
|
&& msg.path() == consolekitSeat->path()
|
|
|
|
&& msg.interface() == CK_SEAT_IFACE
|
|
|
|
&& msg.member() == "ActiveSessionChanged") {
|
|
|
|
emit activeSessionChanged(msg[0].toString() == TQString(consolekitSession));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* This function handles dBus service registering
|
|
|
|
*/
|
|
|
|
void dbusInterface::onServiceRegistered(const TQString& service) {
|
|
|
|
if( service == SYSTEMD_LOGIN1_SERVICE ) {
|
|
|
|
// get current session
|
|
|
|
TQT_DBusProxy managerIface(SYSTEMD_LOGIN1_SERVICE, SYSTEMD_LOGIN1_PATH, SYSTEMD_LOGIN1_MANAGER_IFACE, dBusConn);
|
|
|
|
systemdSession = TQT_DBusObjectPath();
|
|
|
|
if( managerIface.canSend() ) {
|
|
|
|
TQValueList<TQT_DBusData> params;
|
|
|
|
params << TQT_DBusData::fromUInt32( getpid() );
|
|
|
|
TQT_DBusMessage reply = managerIface.sendWithReply("GetSessionByPID", params);
|
|
|
|
if (reply.type() == TQT_DBusMessage::ReplyMessage && reply.count() == 1 ) {
|
|
|
|
systemdSession = reply[0].toObjectPath();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( !systemdSession.isValid() ) {
|
|
|
|
kdWarning() << "The session is not registered with systemd" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// get session seat
|
|
|
|
TQT_DBusProxy sessionProperties(SYSTEMD_LOGIN1_SERVICE, systemdSession, DBUS_INTERFACE_PROPERTIES, dBusConn);
|
|
|
|
TQT_DBusObjectPath seat;
|
|
|
|
if( sessionProperties.canSend() ) {
|
|
|
|
TQValueList<TQT_DBusData> params;
|
|
|
|
params
|
|
|
|
<< TQT_DBusData::fromString( SYSTEMD_LOGIN1_SESSION_IFACE )
|
|
|
|
<< TQT_DBusData::fromString( "Seat" );
|
|
|
|
TQT_DBusMessage reply = sessionProperties.sendWithReply("Get", params);
|
|
|
|
if (reply.type() == TQT_DBusMessage::ReplyMessage && reply.count() == 1 ) {
|
|
|
|
seat = reply[0].toVariant().value.toStruct()[1].toObjectPath();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( !seat.isValid() ) {
|
|
|
|
kdWarning() << "Unable to associate systemd session with a seat" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// watch session changes
|
|
|
|
systemdSeat = new TQT_DBusProxy(SYSTEMD_LOGIN1_SERVICE, seat, DBUS_INTERFACE_PROPERTIES, dBusConn);
|
|
|
|
TQObject::connect(systemdSeat, TQT_SIGNAL(dbusSignal(const TQT_DBusMessage&)),
|
|
|
|
this, TQT_SLOT(handleDBusSignal(const TQT_DBusMessage&)));
|
|
|
|
|
|
|
|
// inhibit systemd handling of power/sleep/hibernate/lid buttons
|
|
|
|
// http://www.freedesktop.org/wiki/Software/systemd/inhibit
|
|
|
|
if( !systemdInhibit.isValid() && managerIface.canSend() ) {
|
|
|
|
TQValueList<TQT_DBusData> params;
|
|
|
|
params
|
|
|
|
<< TQT_DBusData::fromString("handle-power-key:handle-suspend-key:handle-hibernate-key:handle-lid-switch") // what
|
|
|
|
<< TQT_DBusData::fromString("TDEPowersave") // who
|
|
|
|
<< TQT_DBusData::fromString("TDE handles power events") // why
|
|
|
|
<< TQT_DBusData::fromString("block"); // mode
|
|
|
|
TQT_DBusMessage reply = managerIface.sendWithReply("Inhibit", params);
|
|
|
|
if (reply.type() == TQT_DBusMessage::ReplyMessage && reply.count() == 1 ) {
|
|
|
|
systemdInhibit = reply[0].toUnixFd();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if( service == CK_SERVICE ) {
|
|
|
|
// get current session
|
|
|
|
TQT_DBusProxy managerIface(CK_SERVICE, CK_MANAGER_OBJECT, CK_MANAGER_IFACE, dBusConn);
|
|
|
|
consolekitSession = TQT_DBusObjectPath();
|
|
|
|
if( managerIface.canSend() ) {
|
|
|
|
TQValueList<TQT_DBusData> params;
|
|
|
|
params << TQT_DBusData::fromUInt32( getpid() );
|
|
|
|
TQT_DBusMessage reply = managerIface.sendWithReply("GetSessionForUnixProcess", params);
|
|
|
|
if (reply.type() == TQT_DBusMessage::ReplyMessage && reply.count() == 1 ) {
|
|
|
|
consolekitSession = reply[0].toObjectPath();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( !consolekitSession.isValid() ) {
|
|
|
|
kdWarning() << "The session is not registered with consolekit" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// get session seat
|
|
|
|
TQT_DBusObjectPath seat;
|
|
|
|
if( dBusConn.isConnected() ) {
|
|
|
|
TQT_DBusMessage msg = TQT_DBusMessage::methodCall(CK_SERVICE, consolekitSession, CK_SESSION_IFACE, "GetSeatId");
|
|
|
|
TQT_DBusMessage reply = dBusConn.sendWithReply(msg);
|
|
|
|
if (reply.type() == TQT_DBusMessage::ReplyMessage && reply.count() == 1 ) {
|
|
|
|
seat = reply[0].toObjectPath();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( !seat.isValid() ) {
|
|
|
|
kdWarning() << "Unable to associate consolekit session with a seat" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// watch session changes
|
|
|
|
consolekitSeat = new TQT_DBusProxy(CK_SERVICE, seat, CK_SEAT_IFACE, dBusConn);
|
|
|
|
TQObject::connect(consolekitSeat, TQT_SIGNAL(dbusSignal(const TQT_DBusMessage&)),
|
|
|
|
this, TQT_SLOT(handleDBusSignal(const TQT_DBusMessage&)));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* This function handles dBus service unregistering
|
|
|
|
*/
|
|
|
|
void dbusInterface::onServiceUnregistered(const TQString& service) {
|
|
|
|
if( service == SYSTEMD_LOGIN1_SERVICE ) {
|
|
|
|
systemdSession = TQT_DBusObjectPath();
|
|
|
|
if( systemdSeat ) {
|
|
|
|
delete systemdSeat;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if( service == CK_SERVICE ) {
|
|
|
|
consolekitSession = TQT_DBusObjectPath();
|
|
|
|
if( consolekitSeat ) {
|
|
|
|
delete consolekitSeat;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* This functions is used to check if session is active
|
|
|
|
*/
|
|
|
|
bool dbusInterface::checkActiveSession() {
|
|
|
|
if( systemdSeat && systemdSeat->canSend() ) {
|
|
|
|
TQT_DBusObjectPath activeSession;
|
|
|
|
TQValueList<TQT_DBusData> params;
|
|
|
|
params
|
|
|
|
<< TQT_DBusData::fromString( SYSTEMD_LOGIN1_SEAT_IFACE )
|
|
|
|
<< TQT_DBusData::fromString( "ActiveSession" );
|
|
|
|
TQT_DBusMessage reply = systemdSeat->sendWithReply("Get", params);
|
|
|
|
if (reply.type() == TQT_DBusMessage::ReplyMessage && reply.count() == 1 ) {
|
|
|
|
activeSession = reply[0].toVariant().value.toStruct()[1].toObjectPath();
|
|
|
|
return (activeSession == systemdSession);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( consolekitSeat && consolekitSeat->canSend() ) {
|
|
|
|
TQT_DBusObjectPath activeSession;
|
|
|
|
TQValueList<TQT_DBusData> params;
|
|
|
|
TQT_DBusMessage reply = consolekitSeat->sendWithReply("GetActiveSession", params);
|
|
|
|
if (reply.type() == TQT_DBusMessage::ReplyMessage && reply.count() == 1 ) {
|
|
|
|
activeSession = reply[0].toObjectPath();
|
|
|
|
return (activeSession == consolekitSession);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "dbusInterface.moc"
|