File indexing completed on 2024-04-28 15:29:11

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 2009 Marco Martin <notmart@gmail.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "kstatusnotifieritemdbus_p.h"
0009 #include "debug_p.h"
0010 #include "kstatusnotifieritem.h"
0011 #include "kstatusnotifieritemprivate_p.h"
0012 
0013 #include <QMenu>
0014 
0015 #include <KWindowInfo>
0016 #include <kwindowsystem.h>
0017 
0018 #include "statusnotifierwatcher_interface.h"
0019 
0020 #include "statusnotifieritemadaptor.h"
0021 
0022 #ifdef Q_OS_WIN64
0023 __inline int toInt(WId wid)
0024 {
0025     return (int)((__int64)wid);
0026 }
0027 
0028 #else
0029 __inline int toInt(WId wid)
0030 {
0031     return (int)wid;
0032 }
0033 #endif
0034 
0035 // Marshall the ImageStruct data into a D-BUS argument
0036 const QDBusArgument &operator<<(QDBusArgument &argument, const KDbusImageStruct &icon)
0037 {
0038     argument.beginStructure();
0039     argument << icon.width;
0040     argument << icon.height;
0041     argument << icon.data;
0042     argument.endStructure();
0043     return argument;
0044 }
0045 
0046 // Retrieve the ImageStruct data from the D-BUS argument
0047 const QDBusArgument &operator>>(const QDBusArgument &argument, KDbusImageStruct &icon)
0048 {
0049     qint32 width;
0050     qint32 height;
0051     QByteArray data;
0052 
0053     argument.beginStructure();
0054     argument >> width;
0055     argument >> height;
0056     argument >> data;
0057     argument.endStructure();
0058 
0059     icon.width = width;
0060     icon.height = height;
0061     icon.data = data;
0062 
0063     return argument;
0064 }
0065 
0066 // Marshall the ImageVector data into a D-BUS argument
0067 const QDBusArgument &operator<<(QDBusArgument &argument, const KDbusImageVector &iconVector)
0068 {
0069     argument.beginArray(qMetaTypeId<KDbusImageStruct>());
0070     for (int i = 0; i < iconVector.size(); ++i) {
0071         argument << iconVector[i];
0072     }
0073     argument.endArray();
0074     return argument;
0075 }
0076 
0077 // Retrieve the ImageVector data from the D-BUS argument
0078 const QDBusArgument &operator>>(const QDBusArgument &argument, KDbusImageVector &iconVector)
0079 {
0080     argument.beginArray();
0081     iconVector.clear();
0082 
0083     while (!argument.atEnd()) {
0084         KDbusImageStruct element;
0085         argument >> element;
0086         iconVector.append(element);
0087     }
0088 
0089     argument.endArray();
0090 
0091     return argument;
0092 }
0093 
0094 // Marshall the ToolTipStruct data into a D-BUS argument
0095 const QDBusArgument &operator<<(QDBusArgument &argument, const KDbusToolTipStruct &toolTip)
0096 {
0097     argument.beginStructure();
0098     argument << toolTip.icon;
0099     argument << toolTip.image;
0100     argument << toolTip.title;
0101     argument << toolTip.subTitle;
0102     argument.endStructure();
0103     return argument;
0104 }
0105 
0106 // Retrieve the ToolTipStruct data from the D-BUS argument
0107 const QDBusArgument &operator>>(const QDBusArgument &argument, KDbusToolTipStruct &toolTip)
0108 {
0109     QString icon;
0110     KDbusImageVector image;
0111     QString title;
0112     QString subTitle;
0113 
0114     argument.beginStructure();
0115     argument >> icon;
0116     argument >> image;
0117     argument >> title;
0118     argument >> subTitle;
0119     argument.endStructure();
0120 
0121     toolTip.icon = icon;
0122     toolTip.image = image;
0123     toolTip.title = title;
0124     toolTip.subTitle = subTitle;
0125 
0126     return argument;
0127 }
0128 
0129 int KStatusNotifierItemDBus::s_serviceCount = 0;
0130 
0131 KStatusNotifierItemDBus::KStatusNotifierItemDBus(KStatusNotifierItem *parent)
0132     : QObject(parent)
0133     , m_statusNotifierItem(parent)
0134     , m_connId(QStringLiteral("org.kde.StatusNotifierItem-%1-%2").arg(QCoreApplication::applicationPid()).arg(++s_serviceCount))
0135     , m_dbus(QDBusConnection(m_connId))
0136 {
0137     m_dbus = QDBusConnection::connectToBus(QDBusConnection::SessionBus, m_connId);
0138 
0139     new StatusNotifierItemAdaptor(this);
0140     qCDebug(LOG_KNOTIFICATIONS) << "service is" << m_connId;
0141     m_dbus.registerObject(QStringLiteral("/StatusNotifierItem"), this);
0142 }
0143 
0144 KStatusNotifierItemDBus::~KStatusNotifierItemDBus()
0145 {
0146     m_dbus.unregisterObject(QStringLiteral("/StatusNotifierItem"));
0147     m_dbus.disconnectFromBus(m_connId);
0148 }
0149 
0150 QDBusConnection KStatusNotifierItemDBus::dbusConnection() const
0151 {
0152     return m_dbus;
0153 }
0154 
0155 QString KStatusNotifierItemDBus::service() const
0156 {
0157     return m_dbus.baseService();
0158 }
0159 
0160 bool KStatusNotifierItemDBus::ItemIsMenu() const
0161 {
0162     return (m_statusNotifierItem->d->associatedWidget == m_statusNotifierItem->d->menu);
0163 }
0164 
0165 // DBUS slots
0166 
0167 QString KStatusNotifierItemDBus::Category() const
0168 {
0169     return QLatin1String(m_statusNotifierItem->metaObject()
0170                              ->enumerator(m_statusNotifierItem->metaObject()->indexOfEnumerator("ItemCategory"))
0171                              .valueToKey(m_statusNotifierItem->category()));
0172 }
0173 
0174 QString KStatusNotifierItemDBus::Title() const
0175 {
0176     return m_statusNotifierItem->title();
0177 }
0178 
0179 QString KStatusNotifierItemDBus::Id() const
0180 {
0181     return m_statusNotifierItem->id();
0182 }
0183 
0184 QString KStatusNotifierItemDBus::Status() const
0185 {
0186     return QLatin1String(m_statusNotifierItem->metaObject()
0187                              ->enumerator(m_statusNotifierItem->metaObject()->indexOfEnumerator("ItemStatus"))
0188                              .valueToKey(m_statusNotifierItem->status()));
0189 }
0190 
0191 int KStatusNotifierItemDBus::WindowId() const
0192 {
0193     if (m_statusNotifierItem->d->associatedWidget && m_statusNotifierItem->d->associatedWidget != m_statusNotifierItem->d->menu) {
0194         return toInt(m_statusNotifierItem->d->associatedWidget->winId());
0195     } else {
0196         return 0;
0197     }
0198 }
0199 
0200 // Icon
0201 
0202 QString KStatusNotifierItemDBus::IconName() const
0203 {
0204     return m_statusNotifierItem->iconName();
0205 }
0206 
0207 KDbusImageVector KStatusNotifierItemDBus::IconPixmap() const
0208 {
0209     return m_statusNotifierItem->d->serializedIcon;
0210 }
0211 
0212 QString KStatusNotifierItemDBus::OverlayIconName() const
0213 {
0214     return m_statusNotifierItem->overlayIconName();
0215 }
0216 
0217 KDbusImageVector KStatusNotifierItemDBus::OverlayIconPixmap() const
0218 {
0219     return m_statusNotifierItem->d->serializedOverlayIcon;
0220 }
0221 
0222 // Requesting attention icon and movie
0223 
0224 QString KStatusNotifierItemDBus::AttentionIconName() const
0225 {
0226     return m_statusNotifierItem->attentionIconName();
0227 }
0228 
0229 KDbusImageVector KStatusNotifierItemDBus::AttentionIconPixmap() const
0230 {
0231     return m_statusNotifierItem->d->serializedAttentionIcon;
0232 }
0233 
0234 QString KStatusNotifierItemDBus::AttentionMovieName() const
0235 {
0236     return m_statusNotifierItem->d->movieName;
0237 }
0238 
0239 // ToolTip
0240 
0241 KDbusToolTipStruct KStatusNotifierItemDBus::ToolTip() const
0242 {
0243     KDbusToolTipStruct toolTip;
0244     toolTip.icon = m_statusNotifierItem->toolTipIconName();
0245     toolTip.image = m_statusNotifierItem->d->serializedToolTipIcon;
0246     toolTip.title = m_statusNotifierItem->toolTipTitle();
0247     toolTip.subTitle = m_statusNotifierItem->toolTipSubTitle();
0248 
0249     return toolTip;
0250 }
0251 
0252 QString KStatusNotifierItemDBus::IconThemePath() const
0253 {
0254     return m_statusNotifierItem->d->iconThemePath;
0255 }
0256 
0257 // Menu
0258 QDBusObjectPath KStatusNotifierItemDBus::Menu() const
0259 {
0260     return QDBusObjectPath(m_statusNotifierItem->d->menuObjectPath);
0261 }
0262 
0263 // Interaction
0264 
0265 void KStatusNotifierItemDBus::ContextMenu(int x, int y)
0266 {
0267     if (!m_statusNotifierItem->d->menu) {
0268         return;
0269     }
0270 
0271     // TODO: nicer placement, possible?
0272     if (!m_statusNotifierItem->d->menu->isVisible()) {
0273         m_statusNotifierItem->d->menu->popup(QPoint(x, y));
0274     } else {
0275         m_statusNotifierItem->d->menu->hide();
0276     }
0277 }
0278 
0279 void KStatusNotifierItemDBus::Activate(int x, int y)
0280 {
0281     m_statusNotifierItem->activate(QPoint(x, y));
0282 }
0283 
0284 void KStatusNotifierItemDBus::SecondaryActivate(int x, int y)
0285 {
0286     Q_EMIT m_statusNotifierItem->secondaryActivateRequested(QPoint(x, y));
0287 }
0288 
0289 void KStatusNotifierItemDBus::Scroll(int delta, const QString &orientation)
0290 {
0291     Qt::Orientation dir = (orientation.toLower() == QLatin1String("horizontal") ? Qt::Horizontal : Qt::Vertical);
0292     Q_EMIT m_statusNotifierItem->scrollRequested(delta, dir);
0293 }
0294 
0295 void KStatusNotifierItemDBus::ProvideXdgActivationToken(const QString &token)
0296 {
0297     m_xdgActivationToken = token;
0298     KWindowSystem::setCurrentXdgActivationToken(token);
0299 }
0300 
0301 #include "moc_kstatusnotifieritemdbus_p.cpp"