1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        src/gtk/notifmsg.cpp
3 // Purpose:     wxNotificationMessage for wxGTK using libnotify.
4 // Author:      Vadim Zeitlin
5 // Created:     2012-07-25
6 // Copyright:   (c) 2012 Vadim Zeitlin <vadim@wxwidgets.org>
7 // Licence:     wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
9 
10 // ============================================================================
11 // declarations
12 // ============================================================================
13 
14 // ----------------------------------------------------------------------------
15 // headers
16 // ----------------------------------------------------------------------------
17 
18 // for compilers that support precompilation, includes "wx.h".
19 #include "wx/wxprec.h"
20 
21 #ifdef __BORLANDC__
22     #pragma hdrstop
23 #endif
24 
25 #if wxUSE_NOTIFICATION_MESSAGE && wxUSE_LIBNOTIFY
26 
27 #include "wx/notifmsg.h"
28 
29 #ifndef WX_PRECOMP
30     #include "wx/app.h"
31 #endif // WX_PRECOMP
32 
33 #include <libnotify/notify.h>
34 
35 #include "wx/module.h"
36 
37 // General note about error handling: as notifications are meant to be
38 // non-intrusive, we use wxLogDebug() and not wxLogError() if anything goes
39 // wrong here to avoid spamming the user with message boxes. As all methods
40 // return boolean indicating success or failure, the caller could show the
41 // notification in some other way or notify about the error itself if needed.
42 #include "wx/gtk/private/error.h"
43 
44 // ----------------------------------------------------------------------------
45 // A module for cleaning up libnotify on exit.
46 // ----------------------------------------------------------------------------
47 
48 class wxLibnotifyModule : public wxModule
49 {
50 public:
OnInit()51     virtual bool OnInit()
52     {
53         // We're initialized on demand.
54         return true;
55     }
56 
OnExit()57     virtual void OnExit()
58     {
59         if ( notify_is_initted() )
60             notify_uninit();
61     }
62 
63     // Do initialize the library.
Initialize()64     static bool Initialize()
65     {
66         if ( !notify_is_initted() )
67         {
68             if ( !notify_init(wxTheApp->GetAppName().utf8_str()) )
69                 return false;
70         }
71 
72         return true;
73     }
74 
75 private:
76     wxDECLARE_DYNAMIC_CLASS(wxLibnotifyModule);
77 };
78 
79 wxIMPLEMENT_DYNAMIC_CLASS(wxLibnotifyModule, wxModule);
80 
81 // ============================================================================
82 // wxNotificationMessage implementation
83 // ============================================================================
84 
GTKSetIconName(const wxString & name)85 bool wxNotificationMessage::GTKSetIconName(const wxString& name)
86 {
87     m_iconName = name;
88 
89     return true;
90 }
91 
Show(int timeout)92 bool wxNotificationMessage::Show(int timeout)
93 {
94     if ( !wxLibnotifyModule::Initialize() )
95         return false;
96 
97     // Determine the GTK+ icon to use from flags and also set the urgency
98     // appropriately.
99     const char* icon;
100     NotifyUrgency urgency;
101     switch ( GetFlags() )
102     {
103         case wxICON_INFORMATION:
104             icon = "dialog-information";
105             urgency = NOTIFY_URGENCY_LOW;
106             break;
107 
108         case wxICON_WARNING:
109             icon = "dialog-warning";
110             urgency = NOTIFY_URGENCY_NORMAL;
111             break;
112 
113         case wxICON_ERROR:
114             icon = "dialog-error";
115             urgency = NOTIFY_URGENCY_CRITICAL;
116             break;
117 
118         default:
119             wxFAIL_MSG( "Unknown notification message flags." );
120             return false;
121     }
122 
123     // Explicitly specified icon name overrides the implicit one determined by
124     // the flags.
125     wxScopedCharBuffer buf;
126     if ( !m_iconName.empty() )
127     {
128         buf = m_iconName.utf8_str();
129         icon = buf;
130     }
131 
132     // Create the notification or update an existing one if we had already been
133     // shown before.
134     if ( !m_notification )
135     {
136         m_notification = notify_notification_new
137                          (
138                             GetTitle().utf8_str(),
139                             GetMessage().utf8_str(),
140                             icon
141 #if !wxUSE_LIBNOTIFY_0_7
142                             // There used to be an "associated window"
143                             // parameter in this function but it has
144                             // disappeared by 0.7, so use it for previous
145                             // versions only.
146                             , 0
147 #endif // libnotify < 0.7
148                          );
149         if ( !m_notification )
150         {
151             wxLogDebug("Failed to creation notification.");
152 
153             return false;
154         }
155     }
156     else
157     {
158         if ( !notify_notification_update
159               (
160                 m_notification,
161                 GetTitle().utf8_str(),
162                 GetMessage().utf8_str(),
163                 icon
164               ) )
165         {
166             wxLogDebug(wxS("notify_notification_update() unexpectedly failed."));
167         }
168     }
169 
170 
171     // Set the notification parameters not specified during creation.
172     notify_notification_set_timeout
173     (
174         m_notification,
175         timeout == Timeout_Auto ? NOTIFY_EXPIRES_DEFAULT
176                                 : timeout == Timeout_Never ? NOTIFY_EXPIRES_NEVER
177                                                            : 1000*timeout
178     );
179 
180     notify_notification_set_urgency(m_notification, urgency);
181 
182 
183     // Finally do show the notification.
184     wxGtkError error;
185     if ( !notify_notification_show(m_notification, error.Out()) )
186     {
187         wxLogDebug("Failed to shown notification: %s", error.GetMessage());
188 
189         return false;
190     }
191 
192     return true;
193 }
194 
Close()195 bool wxNotificationMessage::Close()
196 {
197     wxCHECK_MSG( m_notification, false,
198                  wxS("Can't close not shown notification.") );
199 
200     wxGtkError error;
201     if ( !notify_notification_close(m_notification, error.Out()) )
202     {
203         wxLogDebug("Failed to hide notification: %s", error.GetMessage());
204 
205         return false;
206     }
207 
208     return true;
209 }
210 
~wxNotificationMessage()211 wxNotificationMessage::~wxNotificationMessage()
212 {
213     if ( m_notification )
214         g_object_unref(m_notification);
215 }
216 
217 #endif // wxUSE_NOTIFICATION_MESSAGE && wxUSE_LIBNOTIFY
218