diff --git a/startkde/CMakeLists.txt b/startkde/CMakeLists.txt --- a/startkde/CMakeLists.txt +++ b/startkde/CMakeLists.txt @@ -1,6 +1,7 @@ add_subdirectory(kcminit) add_subdirectory(kstartupconfig) add_subdirectory(ksyncdbusenv) +add_subdirectory(waitforname) #FIXME: reconsider, looks fishy if(NOT CMAKE_INSTALL_PREFIX STREQUAL "/usr") @@ -15,4 +16,4 @@ install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/startkde DESTINATION ${KDE_INSTALL_BINDIR}) install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/startplasmacompositor DESTINATION ${KDE_INSTALL_BINDIR}) install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/startplasma DESTINATION ${KDE_INSTALL_LIBEXECDIR}) -endif() \ No newline at end of file +endif() diff --git a/startkde/waitforname/CMakeLists.txt b/startkde/waitforname/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/startkde/waitforname/CMakeLists.txt @@ -0,0 +1,22 @@ + +set(plasma_waitforname_SRCS + waiter.cpp + main.cpp + ) + +ecm_qt_declare_logging_category(plasma_waitforname_SRCS HEADER debug_p.h IDENTIFIER LOG_PLASMA CATEGORY_NAME org.kde.knotifications) +ecm_mark_nongui_executable(ksyncdbusenv) + +add_executable(plasma_waitforname ${plasma_waitforname_SRCS}) + +target_link_libraries(plasma_waitforname + Qt5::DBus + ) + +configure_file(org.freedesktop.Notifications.service.in + ${CMAKE_CURRENT_BINARY_DIR}/org.freedesktop.Notifications.service) + +install(TARGETS plasma_waitforname ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.freedesktop.Notifications.service + DESTINATION ${KDE_INSTALL_DBUSSERVICEDIR}) + diff --git a/startkde/waitforname/main.cpp b/startkde/waitforname/main.cpp new file mode 100644 --- /dev/null +++ b/startkde/waitforname/main.cpp @@ -0,0 +1,31 @@ +/* + * Copyright © 2017 Valerio Pilo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 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 Library 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. + */ + +#include "waiter.h" + + +int main(int argc, char **argv) +{ + Waiter app(argc, argv); + + if (!app.waitForService()) { + return 0; + } + + return app.exec(); +} diff --git a/startkde/waitforname/org.freedesktop.Notifications.service.in b/startkde/waitforname/org.freedesktop.Notifications.service.in new file mode 100644 --- /dev/null +++ b/startkde/waitforname/org.freedesktop.Notifications.service.in @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=org.freedesktop.Notifications +Exec=@CMAKE_INSTALL_PREFIX@/bin/plasma_waitforname org.freedesktop.Notifications diff --git a/startkde/waitforname/waiter.h b/startkde/waitforname/waiter.h new file mode 100644 --- /dev/null +++ b/startkde/waitforname/waiter.h @@ -0,0 +1,42 @@ +/* + * Copyright © 2017 Valerio Pilo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 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 Library 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. + */ + +#pragma once + +#include +#include +#include + + +class Waiter : public QCoreApplication { + Q_OBJECT + +public: + Waiter(int argc, char **argv); + bool waitForService(); + +private Q_SLOTS: + void registered(); + void timeout(); + +private: + constexpr static const int dbusTimeoutSec = 60; + + QString mService = QStringLiteral("org.freedesktop.Notifications"); + QTimer mTimeoutTimer; +}; diff --git a/startkde/waitforname/waiter.cpp b/startkde/waitforname/waiter.cpp new file mode 100644 --- /dev/null +++ b/startkde/waitforname/waiter.cpp @@ -0,0 +1,94 @@ +/* + * Copyright © 2017 Valerio Pilo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 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 Library 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. + */ + +#include +#include + +#include +#include +#include + +#include + +#include "waiter.h" +#include "debug_p.h" + + +constexpr static const char dbusServiceName[] = "org.freedesktop.Notifications"; + + +Waiter::Waiter(int argc, char **argv) + : QCoreApplication(argc, argv) + , mService(dbusServiceName) { + setApplicationName(QStringLiteral("plasma_waitforname")); + setApplicationVersion(QStringLiteral("1.0")); + + QCommandLineParser parser; + parser.setApplicationDescription(QStringLiteral("Waits for D-Bus registration of the Notifications service.\n" + "Prevents notifications from being processed before the desktop is ready.")); + parser.addHelpOption(); + parser.addVersionOption(); + parser.addPositionalArgument(QStringLiteral("service"), + QStringLiteral("Optionally listen for a service different than '%1'").arg(mService), + QStringLiteral("[service]")); + parser.process(*this); + + const QStringList args = parser.positionalArguments(); + if (!args.isEmpty()) { + mService = args.at(0); + } +} + +bool Waiter::waitForService() { + QDBusConnection sessionBus = QDBusConnection::sessionBus(); + + if (sessionBus.interface()->isServiceRegistered(mService)) { + qCDebug(LOG_PLASMA) << "WaitForName: Service" << mService << "is already registered"; + return false; + } + + qCDebug(LOG_PLASMA) << "WaitForName: Waiting for appearance of service" << mService << "for" << dbusTimeoutSec << "seconds"; + + QDBusServiceWatcher* watcher = new QDBusServiceWatcher(this); + watcher->setConnection(sessionBus); + watcher->setWatchMode(QDBusServiceWatcher::WatchForRegistration); + watcher->addWatchedService(mService); + connect(watcher, &QDBusServiceWatcher::serviceRegistered, + this, &Waiter::registered); + + mTimeoutTimer.setSingleShot(true); + mTimeoutTimer.setInterval(dbusTimeoutSec * 1000); + connect(&mTimeoutTimer, &QTimer::timeout, this, &Waiter::timeout); + mTimeoutTimer.start(); + + return true; +} + +void Waiter::registered() { + qCDebug(LOG_PLASMA) << "WaitForName: Service was registered after" << (dbusTimeoutSec - (mTimeoutTimer.remainingTime() / 1000)) << "seconds"; + mTimeoutTimer.stop(); + exit(0); +} + +void Waiter::timeout() { + qCInfo(LOG_PLASMA) << "WaitForName: Service was not registered within timeout"; + exit(1); +} + + +#include "waiter.moc"