synced WindowID with KDE/kdelibs/kdeui/notifications/kstatusnotifieritemdbus_p.cpp...
[quassel.git] / src / qtui / statusnotifieritemdbus.cpp
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 General Public License as published by  *
8  *   the Free Software Foundation; either version 2 of the License, or     *
9  *   (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  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, 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 #else
49 __inline int toInt(WId wid) 
50 {
51         return (int)wid;
52 }
53 #endif        
54
55 // Marshall the ImageStruct data into a D-BUS argument
56 const QDBusArgument &operator<<(QDBusArgument &argument, const DBusImageStruct &icon)
57 {
58     argument.beginStructure();
59     argument << icon.width;
60     argument << icon.height;
61     argument << icon.data;
62     argument.endStructure();
63     return argument;
64 }
65
66 // Retrieve the ImageStruct data from the D-BUS argument
67 const QDBusArgument &operator>>(const QDBusArgument &argument, DBusImageStruct &icon)
68 {
69     qint32 width;
70     qint32 height;
71     QByteArray data;
72
73     argument.beginStructure();
74     argument >> width;
75     argument >> height;
76     argument >> data;
77     argument.endStructure();
78
79     icon.width = width;
80     icon.height = height;
81     icon.data = data;
82
83     return argument;
84 }
85
86
87 // Marshall the ImageVector data into a D-BUS argument
88 const QDBusArgument &operator<<(QDBusArgument &argument, const DBusImageVector &iconVector)
89 {
90     argument.beginArray(qMetaTypeId<DBusImageStruct>());
91     for (int i=0; i<iconVector.size(); ++i) {
92         argument << iconVector[i];
93     }
94     argument.endArray();
95     return argument;
96 }
97
98 // Retrieve the ImageVector data from the D-BUS argument
99 const QDBusArgument &operator>>(const QDBusArgument &argument, DBusImageVector &iconVector)
100 {
101     argument.beginArray();
102     iconVector.clear();
103
104     while ( !argument.atEnd() ) {
105        DBusImageStruct element;
106        argument >> element;
107        iconVector.append(element);
108     }
109
110     argument.endArray();
111
112
113     return argument;
114 }
115
116 // Marshall the ToolTipStruct data into a D-BUS argument
117 const QDBusArgument &operator<<(QDBusArgument &argument, const DBusToolTipStruct &toolTip)
118 {
119     argument.beginStructure();
120     argument << toolTip.icon;
121     argument << toolTip.image;
122     argument << toolTip.title;
123     argument << toolTip.subTitle;
124     argument.endStructure();
125     return argument;
126 }
127
128 // Retrieve the ToolTipStruct data from the D-BUS argument
129 const QDBusArgument &operator>>(const QDBusArgument &argument, DBusToolTipStruct &toolTip)
130 {
131     QString icon;
132     DBusImageVector image;
133     QString title;
134     QString subTitle;
135
136     argument.beginStructure();
137     argument >> icon;
138     argument >> image;
139     argument >> title;
140     argument >> subTitle;
141     argument.endStructure();
142
143     toolTip.icon = icon;
144     toolTip.image = image;
145     toolTip.title = title;
146     toolTip.subTitle = subTitle;
147
148     return argument;
149 }
150
151
152 int StatusNotifierItemDBus::s_serviceCount = 0;
153
154 StatusNotifierItemDBus::StatusNotifierItemDBus(StatusNotifierItem *parent)
155   : QObject(parent),
156     m_statusNotifierItem(parent),
157     m_service(QString("org.kde.StatusNotifierItem-%1-%2")
158                       .arg(QCoreApplication::applicationPid())
159                       .arg(++s_serviceCount)),
160     m_dbus(QDBusConnection::connectToBus(QDBusConnection::SessionBus, m_service))
161 {
162    new StatusNotifierItemAdaptor(this);
163    //qDebug() << "service is" << m_service;
164    registerService();
165    m_dbus.registerObject("/StatusNotifierItem", this);
166 }
167
168 StatusNotifierItemDBus::~StatusNotifierItemDBus()
169 {
170     unregisterService();
171 }
172
173 // FIXME: prevent double registrations, also test this on platforms != KDE
174 //
175 void StatusNotifierItemDBus::registerService()
176 {
177     //qDebug() << "registering to" << m_service;
178     m_dbus.registerService(m_service);
179 }
180
181 // FIXME: see above
182 void StatusNotifierItemDBus::unregisterService()
183 {
184     //qDebug() << "unregistering from" << m_service;
185     if(m_dbus.isConnected()) {
186         m_dbus.unregisterService(m_service);
187     }
188 }
189
190 QString StatusNotifierItemDBus::service() const
191 {
192     return m_service;
193 }
194
195 //DBUS slots
196 //Values and calls have been adapted to Quassel
197
198 QString StatusNotifierItemDBus::Category() const
199 {
200     return QString("Communications"); // no need to make this configurable for Quassel
201 }
202
203 QString StatusNotifierItemDBus::Title() const
204 {
205     return m_statusNotifierItem->title();
206 }
207
208 QString StatusNotifierItemDBus::Id() const
209 {
210     return QString("QuasselIRC");
211 }
212
213 QString StatusNotifierItemDBus::Status() const
214 {
215     return m_statusNotifierItem->metaObject()->enumerator(m_statusNotifierItem->metaObject()->indexOfEnumerator("State")).valueToKey(m_statusNotifierItem->state());
216 }
217
218 int StatusNotifierItemDBus::WindowId() const
219 {
220     return toInt(QtUi::mainWindow()->winId());
221 }
222
223
224 //Icon
225 //We don't need to support serialized icon data in Quassel
226
227 QString StatusNotifierItemDBus::IconName() const
228 {
229     return m_statusNotifierItem->iconName();
230 }
231
232 DBusImageVector StatusNotifierItemDBus::IconPixmap() const
233 {
234     return DBusImageVector();
235 }
236
237 QString StatusNotifierItemDBus::OverlayIconName() const
238 {
239     return QString();
240 }
241
242 DBusImageVector StatusNotifierItemDBus::OverlayIconPixmap() const
243 {
244     return DBusImageVector();
245 }
246
247 //Requesting attention icon and movie
248
249 QString StatusNotifierItemDBus::AttentionIconName() const
250 {
251     return m_statusNotifierItem->attentionIconName();
252 }
253
254 DBusImageVector StatusNotifierItemDBus::AttentionIconPixmap() const
255 {
256     return DBusImageVector();
257 }
258
259 QString StatusNotifierItemDBus::AttentionMovieName() const
260 {
261     return QString();
262 }
263
264
265 //ToolTip
266
267 DBusToolTipStruct StatusNotifierItemDBus::ToolTip() const
268 {
269     DBusToolTipStruct toolTip;
270     toolTip.icon = m_statusNotifierItem->toolTipIconName();
271     toolTip.image = DBusImageVector();
272     toolTip.title = m_statusNotifierItem->toolTipTitle();
273     toolTip.subTitle = m_statusNotifierItem->toolTipSubTitle();
274
275     return toolTip;
276 }
277
278 //Interaction
279
280 void StatusNotifierItemDBus::ContextMenu(int x, int y)
281 {
282     if (!m_statusNotifierItem->trayMenu()) {
283         return;
284     }
285
286     //TODO: nicer placement, possible?
287     if (!m_statusNotifierItem->trayMenu()->isVisible()) {
288 #ifdef HAVE_KDE
289         m_statusNotifierItem->trayMenu()->setWindowFlags(Qt::Window|Qt::FramelessWindowHint);
290 #endif
291         m_statusNotifierItem->trayMenu()->popup(QPoint(x,y));
292 #ifdef HAVE_KDE
293         KWindowSystem::setState(m_statusNotifierItem->trayMenu()->winId(), NET::SkipTaskbar|NET::SkipPager|NET::KeepAbove);
294         KWindowSystem::setType(m_statusNotifierItem->trayMenu()->winId(), NET::PopupMenu);
295         KWindowSystem::forceActiveWindow(m_statusNotifierItem->trayMenu()->winId());
296 #endif
297     } else {
298         m_statusNotifierItem->trayMenu()->hide();
299     }
300 }
301
302 void StatusNotifierItemDBus::Activate(int x, int y)
303 {
304     m_statusNotifierItem->activated(QPoint(x,y));
305 }
306
307 void StatusNotifierItemDBus::SecondaryActivate(int x, int y)
308 {
309     Q_UNUSED(x)
310     Q_UNUSED(y)
311     // emit m_statusNotifierItem->secondaryActivateRequested(QPoint(x,y));
312 }
313
314 void StatusNotifierItemDBus::Scroll(int delta, const QString &orientation)
315 {
316     Q_UNUSED(delta)
317     Q_UNUSED(orientation)
318     // Qt::Orientation dir = (orientation.toLower() == "horizontal" ? Qt::Horizontal : Qt::Vertical);
319     // emit m_statusNotifierItem->scrollRequested(delta, dir);
320 }