File indexing completed on 2024-05-05 05:38:31

0001 /*
0002     SPDX-FileCopyrightText: 2018 Kai Uwe Broulik <kde@privat.broulik.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #include "server.h"
0008 #include "server_p.h"
0009 #include "serverinfo.h"
0010 
0011 #include "notification.h"
0012 #include "notification_p.h"
0013 
0014 #include "debug.h"
0015 
0016 #include <KStartupInfo>
0017 #include <KWaylandExtras>
0018 #include <KWindowSystem>
0019 #include <QDebug>
0020 
0021 using namespace NotificationManager;
0022 
0023 Server::Server(QObject *parent)
0024     : QObject(parent)
0025     , d(new ServerPrivate(this))
0026 {
0027     connect(d.get(), &ServerPrivate::validChanged, this, &Server::validChanged);
0028     connect(d.get(), &ServerPrivate::inhibitedChanged, this, [this] {
0029         Q_EMIT inhibitedChanged(inhibited());
0030     });
0031     connect(d.get(), &ServerPrivate::externalInhibitedChanged, this, [this] {
0032         Q_EMIT inhibitedByApplicationChanged(inhibitedByApplication());
0033     });
0034     connect(d.get(), &ServerPrivate::externalInhibitionsChanged, this, &Server::inhibitionApplicationsChanged);
0035     connect(d.get(), &ServerPrivate::serviceOwnershipLost, this, &Server::serviceOwnershipLost);
0036 }
0037 
0038 Server::~Server() = default;
0039 
0040 Server &Server::self()
0041 {
0042     static Server s_self;
0043     return s_self;
0044 }
0045 
0046 Server *Server::create(QQmlEngine *, QJSEngine *)
0047 {
0048     QQmlEngine::setObjectOwnership(&Server::self(), QQmlEngine::CppOwnership);
0049     return &Server::self();
0050 }
0051 
0052 bool Server::init()
0053 {
0054     return d->init();
0055 }
0056 
0057 bool Server::isValid() const
0058 {
0059     return d->m_valid;
0060 }
0061 
0062 ServerInfo *Server::currentOwner() const
0063 {
0064     return d->currentOwner();
0065 }
0066 
0067 void Server::closeNotification(uint notificationId, CloseReason reason)
0068 {
0069     Q_EMIT notificationRemoved(notificationId, reason);
0070     Q_EMIT d->NotificationClosed(notificationId, static_cast<uint>(reason)); // tell on DBus
0071 }
0072 
0073 void Server::invokeAction(uint notificationId,
0074                           const QString &actionName,
0075                           const QString &xdgActivationAppId,
0076                           Notifications::InvokeBehavior behavior,
0077                           QWindow *window)
0078 {
0079     if (KWindowSystem::isPlatformWayland()) {
0080         const quint32 launchedSerial = KWaylandExtras::lastInputSerial(window);
0081         auto conn = std::make_shared<QMetaObject::Connection>();
0082         *conn = connect(KWaylandExtras::self(),
0083                         &KWaylandExtras::xdgActivationTokenArrived,
0084                         this,
0085                         [this, actionName, notificationId, launchedSerial, conn, behavior](quint32 serial, const QString &token) {
0086                             if (serial == launchedSerial) {
0087                                 disconnect(*conn);
0088                                 Q_EMIT d->ActivationToken(notificationId, token);
0089                                 Q_EMIT d->ActionInvoked(notificationId, actionName);
0090 
0091                                 if (behavior & Notifications::Close) {
0092                                     Q_EMIT d->CloseNotification(notificationId);
0093                                 }
0094                             }
0095                         });
0096         KWaylandExtras::requestXdgActivationToken(window, launchedSerial, xdgActivationAppId);
0097     } else {
0098         KStartupInfoId startupId;
0099         startupId.initId();
0100 
0101         Q_EMIT d->ActivationToken(notificationId, QString::fromUtf8(startupId.id()));
0102 
0103         Q_EMIT d->ActionInvoked(notificationId, actionName);
0104         if (behavior & Notifications::Close) {
0105             Q_EMIT d->CloseNotification(notificationId);
0106         }
0107     }
0108 }
0109 
0110 void Server::reply(const QString &dbusService, uint notificationId, const QString &text, Notifications::InvokeBehavior behavior)
0111 {
0112     d->sendReplyText(dbusService, notificationId, text, behavior);
0113 }
0114 
0115 uint Server::add(const Notification &notification)
0116 {
0117     return d->add(notification);
0118 }
0119 
0120 bool Server::inhibited() const
0121 {
0122     return d->inhibited();
0123 }
0124 
0125 void Server::setInhibited(bool inhibited)
0126 {
0127     d->setInhibited(inhibited);
0128 }
0129 
0130 bool Server::inhibitedByApplication() const
0131 {
0132     return d->externalInhibited();
0133 }
0134 
0135 QStringList Server::inhibitionApplications() const
0136 {
0137     QStringList applications;
0138     const auto inhibitions = d->externalInhibitions();
0139     applications.reserve(inhibitions.count());
0140     for (const auto &inhibition : inhibitions) {
0141         applications.append(!inhibition.applicationName.isEmpty() ? inhibition.applicationName : inhibition.desktopEntry);
0142     }
0143     return applications;
0144 }
0145 
0146 QStringList Server::inhibitionReasons() const
0147 {
0148     QStringList reasons;
0149     const auto inhibitions = d->externalInhibitions();
0150     reasons.reserve(inhibitions.count());
0151     for (const auto &inhibition : inhibitions) {
0152         reasons.append(inhibition.reason);
0153     }
0154     return reasons;
0155 }
0156 
0157 void Server::clearInhibitions()
0158 {
0159     d->clearExternalInhibitions();
0160 }
0161 
0162 #include "moc_server.cpp"