1 /*
2     This file is part of the KDE libraries
3     SPDX-FileCopyrightText: 2009 Marco Martin <notmart@gmail.com>
4 
5     SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7 
8 #ifndef KSTATUSNOTIFIERITEMPRIVATE_H
9 #define KSTATUSNOTIFIERITEMPRIVATE_H
10 
11 #include <QEventLoopLocker>
12 #include <QMovie>
13 #include <QObject>
14 #include <QString>
15 #include <QSystemTrayIcon>
16 #include <QWheelEvent>
17 
18 #include "kstatusnotifieritem.h"
19 
20 #ifdef QT_DBUS_LIB
21 #include "kstatusnotifieritemdbus_p.h"
22 
23 #include "notifications_interface.h"
24 #include "statusnotifierwatcher_interface.h"
25 #endif
26 
27 class KSystemTrayIcon;
28 class QMenu;
29 class QAction;
30 
31 // this class is needed because we can't just put an event filter on it:
32 // the events that are passed to QSystemTrayIcon are done so in a way that
33 // bypasses the usual event filtering mechanisms *sigh*
34 class KStatusNotifierLegacyIcon : public QSystemTrayIcon
35 {
36     Q_OBJECT
37 
38 public:
KStatusNotifierLegacyIcon(QObject * parent)39     KStatusNotifierLegacyIcon(QObject *parent)
40         : QSystemTrayIcon(parent)
41     {
42     }
43 
event(QEvent * e)44     bool event(QEvent *e) override
45     {
46         if (e->type() == QEvent::Wheel) {
47             QWheelEvent *wheelEvent = static_cast<QWheelEvent *>(e);
48             Q_EMIT wheel(wheelEvent->angleDelta().y());
49         }
50 
51         return false;
52     }
53 
setMovie(QMovie * movie)54     void setMovie(QMovie *movie)
55     {
56         if (m_movie.data() == movie) {
57             return;
58         }
59 
60         delete m_movie.data();
61         m_movie = movie;
62 
63         if (!movie) {
64             return;
65         }
66 
67         movie->setParent(this);
68         movie->setCacheMode(QMovie::CacheAll);
69         connect(movie, &QMovie::frameChanged, this, &KStatusNotifierLegacyIcon::slotNewFrame);
70     }
71 
setIconWithMask(QIcon & icon,bool isMask)72     void setIconWithMask(QIcon &icon, bool isMask)
73     {
74         icon.setIsMask(isMask);
75         QSystemTrayIcon::setIcon(icon);
76     }
77 
78 Q_SIGNALS:
79     void wheel(int);
80 
81 private Q_SLOTS:
slotNewFrame()82     void slotNewFrame()
83     {
84         if (m_movie) {
85             setIcon(QIcon(m_movie.data()->currentPixmap()));
86         }
87     }
88 
89 private:
90     QPointer<QMovie> m_movie;
91 };
92 
93 class KStatusNotifierItemPrivate
94 {
95 public:
96     KStatusNotifierItemPrivate(KStatusNotifierItem *item);
97 
98     void init(const QString &extraId);
99     void registerToDaemon();
100     void serviceChange(const QString &name, const QString &oldOwner, const QString &newOwner);
101     void setLegacySystemTrayEnabled(bool enabled);
102     void syncLegacySystemTrayIcon();
103     void contextMenuAboutToShow();
104     void maybeQuit();
105     void minimizeRestore();
106     void minimizeRestore(bool show);
107     void hideMenu();
108     void setLegacyMode(bool legacy);
109     void checkForRegisteredHosts();
110     void legacyWheelEvent(int delta);
111     void legacyActivated(QSystemTrayIcon::ActivationReason reason);
112 
113     bool checkVisibility(QPoint pos, bool perform = true);
114 
115     static const int s_protocolVersion;
116 
117     KStatusNotifierItem *q;
118 
119 #ifdef QT_DBUS_LIB
120     KDbusImageStruct imageToStruct(const QImage &image);
121     KDbusImageVector iconToVector(const QIcon &icon);
122 
123     KDbusImageVector serializedIcon;
124     KDbusImageVector serializedAttentionIcon;
125     KDbusImageVector serializedOverlayIcon;
126     KDbusImageVector serializedToolTipIcon;
127 
128     org::kde::StatusNotifierWatcher *statusNotifierWatcher = nullptr;
129     org::freedesktop::Notifications *notificationsClient = nullptr;
130 
131     KStatusNotifierItemDBus *statusNotifierItemDBus;
132 #endif
133 
134     KStatusNotifierItem::ItemCategory category;
135     QString id;
136     QString title;
137     KStatusNotifierItem::ItemStatus status;
138 
139     QString iconName;
140     QIcon icon;
141 
142     QString overlayIconName;
143     QIcon overlayIcon;
144 
145     QString attentionIconName;
146     QIcon attentionIcon;
147     QString movieName;
148     QPointer<QMovie> movie;
149 
150     QString toolTipIconName;
151     QIcon toolTipIcon;
152     QString toolTipTitle;
153     QString toolTipSubTitle;
154     QString iconThemePath;
155     QString menuObjectPath;
156     KStatusNotifierLegacyIcon *systemTrayIcon;
157 
158     QMenu *menu;
159     QHash<QString, QAction *> actionCollection;
160     QWidget *associatedWidget;
161     QPoint associatedWidgetPos;
162     QAction *titleAction;
163 
164     // Ensure that closing the last KMainWindow doesn't exit the application
165     // if a system tray icon is still present.
166     QEventLoopLocker eventLoopLocker;
167 
168     bool hasQuit : 1;
169     bool onAllDesktops : 1;
170     bool standardActionsEnabled : 1;
171 };
172 
173 #endif
174