1 | /*************************************************************************** |
2 | * The original file is part of the KDE libraries * |
3 | * Copyright (C) 2009 by Marco Martin <notmart@gmail.com> * |
4 | * Quasselfied 2010 by Manuel Nickschas <sputnick@quassel-irc.org> * |
5 | * * |
6 | * This file is free software; you can redistribute it and/or modify * |
7 | * it under the terms of the GNU Library General Public License (LGPL) * |
8 | * as published by the Free Software Foundation; either version 2 of the * |
9 | * License, or (at your option) any later version. * |
10 | * * |
11 | * This program is distributed in the hope that it will be useful, * |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
14 | * GNU General Public License for more details. * |
15 | * * |
16 | * You should have received a copy of the GNU General Public License * |
17 | * along with this program; if not, write to the * |
18 | * Free Software Foundation, Inc., * |
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * |
20 | ***************************************************************************/ |
21 | |
22 | #include "mainwin.h" |
23 | #include "qtui.h" |
24 | #include "statusnotifieritemdbus.h" |
25 | #include "statusnotifieritem.h" |
26 | |
27 | #include <QDBusConnection> |
28 | #include <QPixmap> |
29 | #include <QImage> |
30 | #include <QApplication> |
31 | #include <QMenu> |
32 | #include <QMovie> |
33 | |
34 | #ifdef HAVE_KDE |
35 | # include <KWindowInfo> |
36 | # include <KWindowSystem> |
37 | #endif |
38 | |
39 | #include "statusnotifierwatcher.h" |
40 | #include "statusnotifieritemadaptor.h" |
41 | |
42 | #ifdef Q_OS_WIN64 |
43 | __inline int toInt(WId wid) |
44 | { |
45 | return (int)((__int64)wid); |
46 | } |
47 | |
48 | |
49 | #else |
50 | __inline int toInt(WId wid) |
51 | { |
52 | return (int)wid; |
53 | } |
54 | |
55 | |
56 | #endif |
57 | |
58 | // Marshall the ImageStruct data into a D-BUS argument |
59 | const QDBusArgument &operator<<(QDBusArgument &argument, const DBusImageStruct &icon) |
60 | { |
61 | argument.beginStructure(); |
62 | argument << icon.width; |
63 | argument << icon.height; |
64 | argument << icon.data; |
65 | argument.endStructure(); |
66 | return argument; |
67 | } |
68 | |
69 | |
70 | // Retrieve the ImageStruct data from the D-BUS argument |
71 | const QDBusArgument &operator>>(const QDBusArgument &argument, DBusImageStruct &icon) |
72 | { |
73 | qint32 width; |
74 | qint32 height; |
75 | QByteArray data; |
76 | |
77 | argument.beginStructure(); |
78 | argument >> width; |
79 | argument >> height; |
80 | argument >> data; |
81 | argument.endStructure(); |
82 | |
83 | icon.width = width; |
84 | icon.height = height; |
85 | icon.data = data; |
86 | |
87 | return argument; |
88 | } |
89 | |
90 | |
91 | // Marshall the ImageVector data into a D-BUS argument |
92 | const QDBusArgument &operator<<(QDBusArgument &argument, const DBusImageVector &iconVector) |
93 | { |
94 | argument.beginArray(qMetaTypeId<DBusImageStruct>()); |
95 | for (int i = 0; i < iconVector.size(); ++i) { |
96 | argument << iconVector[i]; |
97 | } |
98 | argument.endArray(); |
99 | return argument; |
100 | } |
101 | |
102 | |
103 | // Retrieve the ImageVector data from the D-BUS argument |
104 | const QDBusArgument &operator>>(const QDBusArgument &argument, DBusImageVector &iconVector) |
105 | { |
106 | argument.beginArray(); |
107 | iconVector.clear(); |
108 | |
109 | while (!argument.atEnd()) { |
110 | DBusImageStruct element; |
111 | argument >> element; |
112 | iconVector.append(element); |
113 | } |
114 | |
115 | argument.endArray(); |
116 | |
117 | return argument; |
118 | } |
119 | |
120 | |
121 | // Marshall the ToolTipStruct data into a D-BUS argument |
122 | const QDBusArgument &operator<<(QDBusArgument &argument, const DBusToolTipStruct &toolTip) |
123 | { |
124 | argument.beginStructure(); |
125 | argument << toolTip.icon; |
126 | argument << toolTip.image; |
127 | argument << toolTip.title; |
128 | argument << toolTip.subTitle; |
129 | argument.endStructure(); |
130 | return argument; |
131 | } |
132 | |
133 | |
134 | // Retrieve the ToolTipStruct data from the D-BUS argument |
135 | const QDBusArgument &operator>>(const QDBusArgument &argument, DBusToolTipStruct &toolTip) |
136 | { |
137 | QString icon; |
138 | DBusImageVector image; |
139 | QString title; |
140 | QString subTitle; |
141 | |
142 | argument.beginStructure(); |
143 | argument >> icon; |
144 | argument >> image; |
145 | argument >> title; |
146 | argument >> subTitle; |
147 | argument.endStructure(); |
148 | |
149 | toolTip.icon = icon; |
150 | toolTip.image = image; |
151 | toolTip.title = title; |
152 | toolTip.subTitle = subTitle; |
153 | |
154 | return argument; |
155 | } |
156 | |
157 | |
158 | int StatusNotifierItemDBus::s_serviceCount = 0; |
159 | |
160 | StatusNotifierItemDBus::StatusNotifierItemDBus(StatusNotifierItem *parent) |
161 | : QObject(parent), |
162 | m_statusNotifierItem(parent), |
163 | m_service(QString("org.kde.StatusNotifierItem-%1-%2" ) |
164 | .arg(QCoreApplication::applicationPid()) |
165 | .arg(++s_serviceCount)), |
166 | m_dbus(QDBusConnection::connectToBus(QDBusConnection::SessionBus, m_service)) |
167 | { |
168 | new StatusNotifierItemAdaptor(this); |
169 | //qDebug() << "service is" << m_service; |
170 | registerService(); |
171 | } |
172 | |
173 | |
174 | StatusNotifierItemDBus::~StatusNotifierItemDBus() |
175 | { |
176 | unregisterService(); |
177 | } |
178 | |
179 | |
180 | QDBusConnection StatusNotifierItemDBus::dbusConnection() const |
181 | { |
182 | return m_dbus; |
183 | } |
184 | |
185 | |
186 | // FIXME: prevent double registrations, also test this on platforms != KDE |
187 | // |
188 | void StatusNotifierItemDBus::registerService() |
189 | { |
190 | //qDebug() << "registering to" << m_service; |
191 | m_dbus.registerService(m_service); |
192 | m_dbus.registerObject("/StatusNotifierItem" , this); |
193 | } |
194 | |
195 | |
196 | // FIXME: see above |
197 | void StatusNotifierItemDBus::unregisterService() |
198 | { |
199 | //qDebug() << "unregistering from" << m_service; |
200 | if (m_dbus.isConnected()) { |
201 | m_dbus.unregisterObject("/StatusNotifierItem" ); |
202 | m_dbus.unregisterService(m_service); |
203 | } |
204 | } |
205 | |
206 | |
207 | QString StatusNotifierItemDBus::service() const |
208 | { |
209 | return m_service; |
210 | } |
211 | |
212 | |
213 | //DBUS slots |
214 | //Values and calls have been adapted to Quassel |
215 | |
216 | QString StatusNotifierItemDBus::Category() const |
217 | { |
218 | return QString("Communications" ); // no need to make this configurable for Quassel |
219 | } |
220 | |
221 | |
222 | QString StatusNotifierItemDBus::Title() const |
223 | { |
224 | return m_statusNotifierItem->title(); |
225 | } |
226 | |
227 | |
228 | QString StatusNotifierItemDBus::Id() const |
229 | { |
230 | return QString("QuasselIRC" ); |
231 | } |
232 | |
233 | |
234 | QString StatusNotifierItemDBus::Status() const |
235 | { |
236 | return m_statusNotifierItem->metaObject()->enumerator(m_statusNotifierItem->metaObject()->indexOfEnumerator("State" )).valueToKey(m_statusNotifierItem->state()); |
237 | } |
238 | |
239 | |
240 | int StatusNotifierItemDBus::WindowId() const |
241 | { |
242 | return toInt(QtUi::mainWindow()->winId()); |
243 | } |
244 | |
245 | |
246 | //Icon |
247 | //We don't need to support serialized icon data in Quassel |
248 | |
249 | QString StatusNotifierItemDBus::IconName() const |
250 | { |
251 | return m_statusNotifierItem->iconName(); |
252 | } |
253 | |
254 | |
255 | DBusImageVector StatusNotifierItemDBus::IconPixmap() const |
256 | { |
257 | return DBusImageVector(); |
258 | } |
259 | |
260 | |
261 | QString StatusNotifierItemDBus::OverlayIconName() const |
262 | { |
263 | return QString(); |
264 | } |
265 | |
266 | |
267 | DBusImageVector StatusNotifierItemDBus::OverlayIconPixmap() const |
268 | { |
269 | return DBusImageVector(); |
270 | } |
271 | |
272 | |
273 | //Requesting attention icon and movie |
274 | |
275 | QString StatusNotifierItemDBus::AttentionIconName() const |
276 | { |
277 | return m_statusNotifierItem->attentionIconName(); |
278 | } |
279 | |
280 | |
281 | DBusImageVector StatusNotifierItemDBus::AttentionIconPixmap() const |
282 | { |
283 | return DBusImageVector(); |
284 | } |
285 | |
286 | |
287 | QString StatusNotifierItemDBus::AttentionMovieName() const |
288 | { |
289 | return QString(); |
290 | } |
291 | |
292 | |
293 | //ToolTip |
294 | |
295 | DBusToolTipStruct StatusNotifierItemDBus::ToolTip() const |
296 | { |
297 | DBusToolTipStruct toolTip; |
298 | toolTip.icon = m_statusNotifierItem->toolTipIconName(); |
299 | toolTip.image = DBusImageVector(); |
300 | toolTip.title = m_statusNotifierItem->toolTipTitle(); |
301 | toolTip.subTitle = m_statusNotifierItem->toolTipSubTitle(); |
302 | |
303 | return toolTip; |
304 | } |
305 | |
306 | |
307 | QString StatusNotifierItemDBus::IconThemePath() const |
308 | { |
309 | return m_statusNotifierItem->iconThemePath(); |
310 | } |
311 | |
312 | |
313 | //Menu |
314 | |
315 | QDBusObjectPath StatusNotifierItemDBus::() const |
316 | { |
317 | return QDBusObjectPath(m_statusNotifierItem->menuObjectPath()); |
318 | } |
319 | |
320 | |
321 | //Interaction |
322 | |
323 | void StatusNotifierItemDBus::(int x, int y) |
324 | { |
325 | if (!m_statusNotifierItem->trayMenu()) { |
326 | return; |
327 | } |
328 | |
329 | //TODO: nicer placement, possible? |
330 | if (!m_statusNotifierItem->trayMenu()->isVisible()) { |
331 | #ifdef HAVE_KDE |
332 | m_statusNotifierItem->trayMenu()->setWindowFlags(Qt::Window|Qt::FramelessWindowHint); |
333 | #endif |
334 | m_statusNotifierItem->trayMenu()->popup(QPoint(x, y)); |
335 | #ifdef HAVE_KDE |
336 | KWindowSystem::setState(m_statusNotifierItem->trayMenu()->winId(), NET::SkipTaskbar|NET::SkipPager|NET::KeepAbove); |
337 | KWindowSystem::setType(m_statusNotifierItem->trayMenu()->winId(), NET::PopupMenu); |
338 | KWindowSystem::forceActiveWindow(m_statusNotifierItem->trayMenu()->winId()); |
339 | #endif |
340 | } |
341 | else { |
342 | m_statusNotifierItem->trayMenu()->hide(); |
343 | } |
344 | } |
345 | |
346 | |
347 | void StatusNotifierItemDBus::Activate(int x, int y) |
348 | { |
349 | m_statusNotifierItem->activated(QPoint(x, y)); |
350 | } |
351 | |
352 | |
353 | void StatusNotifierItemDBus::SecondaryActivate(int x, int y) |
354 | { |
355 | Q_UNUSED(x) |
356 | Q_UNUSED(y) |
357 | // emit m_statusNotifierItem->secondaryActivateRequested(QPoint(x,y)); |
358 | } |
359 | |
360 | |
361 | void StatusNotifierItemDBus::Scroll(int delta, const QString &orientation) |
362 | { |
363 | Q_UNUSED(delta) |
364 | Q_UNUSED(orientation) |
365 | // Qt::Orientation dir = (orientation.toLower() == "horizontal" ? Qt::Horizontal : Qt::Vertical); |
366 | // emit m_statusNotifierItem->scrollRequested(delta, dir); |
367 | } |
368 | |