]> git.saurik.com Git - wxWidgets.git/blame - src/msw/notifmsg.cpp
check that the version of __sync_sub_and_fetch that returns a value is supported...
[wxWidgets.git] / src / msw / notifmsg.cpp
CommitLineData
e2d5abbf
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/msw/notifmsg.cpp
3// Purpose: implementation of wxNotificationMessage for Windows
4// Author: Vadim Zeitlin
5// Created: 2007-12-01
6// RCS-ID: $Id$
7// Copyright: (c) 2007 Vadim Zeitlin <vadim@wxwindows.org>
8// Licence: wxWindows licence
9///////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19// for compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
26#if wxUSE_NOTIFICATION_MESSAGE && wxUSE_TASKBARICON
27
11a0827d
PC
28#include "wx/notifmsg.h"
29
e2d5abbf 30#ifndef WX_PRECOMP
11a0827d
PC
31 #include "wx/toplevel.h"
32 #include "wx/app.h"
e2d5abbf
VZ
33 #include "wx/string.h"
34#endif // WX_PRECOMP
35
e2d5abbf
VZ
36#include "wx/generic/notifmsg.h"
37
38#include "wx/taskbar.h"
39
40// ----------------------------------------------------------------------------
41// different implementations used by wxNotificationMessage
42// ----------------------------------------------------------------------------
43
44// base class for all available implementations
45class wxNotifMsgImpl
46{
47public:
48 wxNotifMsgImpl() { }
49 virtual ~wxNotifMsgImpl() { }
50
51 virtual bool DoShow(const wxString& title,
52 const wxString& message,
53 int timeout,
54 int flags) = 0;
55 virtual bool DoClose() = 0;
56
57private:
58 DECLARE_NO_COPY_CLASS(wxNotifMsgImpl)
59};
60
61// implementation which is simply a bridge to wxGenericNotificationMessage
62class wxGenericNotifMsgImpl : public wxNotifMsgImpl
63{
64public:
65 wxGenericNotifMsgImpl() : m_notif(new wxGenericNotificationMessage) { }
66 virtual ~wxGenericNotifMsgImpl() { delete m_notif; }
67
68 virtual bool DoShow(const wxString& title,
69 const wxString& message,
70 int timeout,
71 int flags)
72 {
73 m_notif->SetTitle(title);
74 m_notif->SetMessage(message);
75 m_notif->SetFlags(flags);
76 return m_notif->Show(timeout);
77 }
78
79 virtual bool DoClose()
80 {
81 return m_notif->Close();
82 }
83
84private:
85 wxGenericNotificationMessage * const m_notif;
86};
87
88// common base class for implementations using a taskbar icon and balloons
89class wxBalloonNotifMsgImpl : public wxNotifMsgImpl
90{
91public:
92 // ctor sets up m_icon (using the icon of the top level parent of the given
93 // window) which can be used to show an attached balloon later by the
94 // derived classes
95 wxBalloonNotifMsgImpl(wxWindow *win) { SetUpIcon(win); }
96
97 // implementation of wxNotificationMessage method with the same name
98 static wxTaskBarIcon *UseTaskBarIcon(wxTaskBarIcon *icon);
99
100 virtual bool DoShow(const wxString& title,
101 const wxString& message,
102 int timeout,
103 int flags);
104
105protected:
106 // sets up m_icon (doesn't do anything with the old value, caller beware)
107 void SetUpIcon(wxWindow *win);
108
109
110 static wxTaskBarIcon *ms_iconToUse;
111
112 // the icon we attach our notification to, either ms_iconToUse or a
113 // temporary one which we will destroy when done
114 wxTaskBarIcon *m_icon;
115
116 // should be only used if m_icon != NULL and indicates whether we should
117 // delete it
118 bool m_ownsIcon;
119};
120
121// implementation for automatically hidden notifications
122class wxAutoNotifMsgImpl : public wxBalloonNotifMsgImpl
123{
124public:
125 wxAutoNotifMsgImpl(wxWindow *win);
126
127 virtual bool DoShow(const wxString& title,
128 const wxString& message,
129 int timeout,
130 int flags);
131
132 // can't close automatic notification [currently]
133 virtual bool DoClose() { return false; }
134
135private:
136 // custom event handler connected to m_icon which will receive the icon
137 // close event and delete it and itself when it happens
138 wxEvtHandler * const m_iconEvtHandler;
139};
140
141// implementation for manually closed notifications
142class wxManualNotifMsgImpl : public wxBalloonNotifMsgImpl
143{
144public:
145 wxManualNotifMsgImpl(wxWindow *win);
146 virtual ~wxManualNotifMsgImpl();
147
148 virtual bool DoShow(const wxString& title,
149 const wxString& message,
150 int timeout,
151 int flags);
152 virtual bool DoClose();
153
154private:
155 // store ctor parameter as we need it to recreate the icon later if we're
156 // closed and shown again
157 wxWindow * const m_win;
158};
159
160// ----------------------------------------------------------------------------
161// custom event handler for task bar icons
162// ----------------------------------------------------------------------------
163
164// normally we'd just use a custom taskbar icon class but this is impossible
165// because we can be asked to attach the notifications to an existing icon
166// which we didn't create, hence we install a special event handler allowing us
167// to get the events we need (and, crucially, to delete the icon when it's not
168// needed any more) in any case
169
170class wxNotificationIconEvtHandler : public wxEvtHandler
171{
172public:
173 wxNotificationIconEvtHandler(wxTaskBarIcon *icon);
174
175private:
176 void OnTimeout(wxTaskBarIconEvent& event);
177 void OnClick(wxTaskBarIconEvent& event);
178
179 void OnIconHidden();
180
181
182 wxTaskBarIcon * const m_icon;
183
184 DECLARE_NO_COPY_CLASS(wxNotificationIconEvtHandler)
185};
186
187// ============================================================================
188// implementation
189// ============================================================================
190
191// ----------------------------------------------------------------------------
192// wxNotificationIconEvtHandler
193// ----------------------------------------------------------------------------
194
195wxNotificationIconEvtHandler::wxNotificationIconEvtHandler(wxTaskBarIcon *icon)
196 : m_icon(icon)
197{
198 m_icon->Connect
199 (
200 wxEVT_TASKBAR_BALLOON_TIMEOUT,
201 wxTaskBarIconEventHandler(wxNotificationIconEvtHandler::OnTimeout),
202 NULL,
203 this
204 );
205
206 m_icon->Connect
207 (
208 wxEVT_TASKBAR_BALLOON_CLICK,
64336927 209 wxTaskBarIconEventHandler(wxNotificationIconEvtHandler::OnClick),
e2d5abbf
VZ
210 NULL,
211 this
212 );
213}
214
215void wxNotificationIconEvtHandler::OnIconHidden()
216{
217 delete m_icon;
218
219 delete this;
220}
221
222void
223wxNotificationIconEvtHandler::OnTimeout(wxTaskBarIconEvent& WXUNUSED(event))
224{
225 OnIconHidden();
226}
227
228void wxNotificationIconEvtHandler::OnClick(wxTaskBarIconEvent& WXUNUSED(event))
229{
230 // TODO: generate an event notifying the user code?
231
232 OnIconHidden();
233}
234
235// ----------------------------------------------------------------------------
236// wxBalloonNotifMsgImpl
237// ----------------------------------------------------------------------------
238
239wxTaskBarIcon *wxBalloonNotifMsgImpl::ms_iconToUse = NULL;
240
241/* static */
242wxTaskBarIcon *wxBalloonNotifMsgImpl::UseTaskBarIcon(wxTaskBarIcon *icon)
243{
244 wxTaskBarIcon * const iconOld = ms_iconToUse;
245 ms_iconToUse = icon;
246 return iconOld;
247}
248
249void wxBalloonNotifMsgImpl::SetUpIcon(wxWindow *win)
250{
251 if ( ms_iconToUse )
252 {
253 // use an existing icon
254 m_ownsIcon = false;
255 m_icon = ms_iconToUse;
256 }
257 else // no user-specified icon to attach to
258 {
259 // create our own one
260 m_ownsIcon = true;
261 m_icon = new wxTaskBarIcon;
262
263 // use the icon of the associated (or main, if none) frame
264 wxIcon icon;
265 if ( win )
266 win = wxGetTopLevelParent(win);
267 if ( !win )
268 win = wxTheApp->GetTopWindow();
269 if ( win )
270 {
271 const wxTopLevelWindow * const
272 tlw = wxDynamicCast(win, wxTopLevelWindow);
273 if ( tlw )
274 icon = tlw->GetIcon();
275 }
276
277 if ( !icon.IsOk() )
278 {
279 // we really must have some icon
280 icon = wxIcon(_T("wxICON_AAA"));
281 }
282
283 m_icon->SetIcon(icon);
284 }
285}
286
287bool
288wxBalloonNotifMsgImpl::DoShow(const wxString& title,
289 const wxString& message,
290 int timeout,
291 int flags)
292{
293 timeout *= 1000; // Windows expresses timeout in milliseconds
294
295 return m_icon->ShowBalloon(title, message, timeout, flags);
296}
297
298// ----------------------------------------------------------------------------
299// wxManualNotifMsgImpl
300// ----------------------------------------------------------------------------
301
302wxManualNotifMsgImpl::wxManualNotifMsgImpl(wxWindow *win)
303 : wxBalloonNotifMsgImpl(win),
304 m_win(win)
305{
306}
307
308wxManualNotifMsgImpl::~wxManualNotifMsgImpl()
309{
310 if ( m_icon )
311 DoClose();
312}
313
314bool
315wxManualNotifMsgImpl::DoShow(const wxString& title,
316 const wxString& message,
317 int timeout,
318 int flags)
319{
320 wxASSERT_MSG( timeout == wxNotificationMessage::Timeout_Never,
321 _T("shouldn't be used") );
322
323 // base class creates the icon for us initially but we could have destroyed
324 // it in DoClose(), recreate it if this was the case
325 if ( !m_icon )
326 SetUpIcon(m_win);
327
328 // use maximal (in current Windows versions) timeout (but it will still
329 // disappear on its own)
330 return wxBalloonNotifMsgImpl::DoShow(title, message, 30, flags);
331}
332
333bool wxManualNotifMsgImpl::DoClose()
334{
335 if ( m_ownsIcon )
336 {
337 // we don't need the icon any more
338 delete m_icon;
339 }
340 else // using an existing icon
341 {
342 // just hide the balloon
343 m_icon->ShowBalloon("", "");
344 }
345
346 m_icon = NULL;
347
348 return true;
349}
350
351// ----------------------------------------------------------------------------
352// wxAutoNotifMsgImpl
353// ----------------------------------------------------------------------------
354
355wxAutoNotifMsgImpl::wxAutoNotifMsgImpl(wxWindow *win)
356 : wxBalloonNotifMsgImpl(win),
357 m_iconEvtHandler(new wxNotificationIconEvtHandler(m_icon))
358{
359}
360
361bool
362wxAutoNotifMsgImpl::DoShow(const wxString& title,
363 const wxString& message,
364 int timeout,
365 int flags)
366{
367 wxASSERT_MSG( timeout != wxNotificationMessage::Timeout_Never,
368 _T("shouldn't be used") );
369
370 if ( timeout == wxNotificationMessage::Timeout_Auto )
371 {
372 // choose a value more or less in the middle of the allowed range
373 timeout = 1;
374 }
375
376 return wxBalloonNotifMsgImpl::DoShow(title, message, timeout, flags);
377}
378
379// ----------------------------------------------------------------------------
380// wxNotificationMessage
381// ----------------------------------------------------------------------------
382
5e6b39c9
VZ
383/* static */
384bool wxNotificationMessage::ms_alwaysUseGeneric = false;
385
e2d5abbf
VZ
386/* static */
387wxTaskBarIcon *wxNotificationMessage::UseTaskBarIcon(wxTaskBarIcon *icon)
388{
389 return wxBalloonNotifMsgImpl::UseTaskBarIcon(icon);
390}
391
392bool wxNotificationMessage::Show(int timeout)
393{
394 if ( !m_impl )
395 {
5e6b39c9 396 if ( !ms_alwaysUseGeneric && wxTheApp->GetShell32Version() >= 500 )
e2d5abbf
VZ
397 {
398 if ( timeout == Timeout_Never )
399 m_impl = new wxManualNotifMsgImpl(GetParent());
400 else
401 m_impl = new wxAutoNotifMsgImpl(GetParent());
402 }
403 else // no support for balloon tooltips
404 {
405 m_impl = new wxGenericNotifMsgImpl;
406 }
407 }
408 //else: reuse the same implementation for the subsequent calls, it would
409 // be too confusing if it changed
410
411 return m_impl->DoShow(GetTitle(), GetMessage(), timeout, GetFlags());
412}
413
414bool wxNotificationMessage::Close()
415{
416 wxCHECK_MSG( m_impl, false, "must show the notification first" );
417
418 return m_impl->DoClose();
419}
420
421wxNotificationMessage::~wxNotificationMessage()
422{
423 delete m_impl;
424}
425
426#endif // wxUSE_NOTIFICATION_MESSAGE && wxUSE_TASKBARICON