]> git.saurik.com Git - wxWidgets.git/blob - src/unix/taskbarx11.cpp
Fix of memory leak with generic file dialog (Patch #1017938)
[wxWidgets.git] / src / unix / taskbarx11.cpp
1 /////////////////////////////////////////////////////////////////////////
2 // File: taskbar.cpp
3 // Purpose: wxTaskBarIcon class for common Unix desktops
4 // Author: Vaclav Slavik
5 // Modified by:
6 // Created: 04/04/2003
7 // RCS-ID: $Id$
8 // Copyright: (c) Vaclav Slavik, 2003
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////
11
12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation "taskbarx11.h"
14 #endif
15
16 // NB: This implementation does *not* work with every X11 window manager.
17 // Currently only GNOME 1.2 and KDE 1,2,3 methods are implemented here.
18 // Freedesktop.org's System Tray specification is implemented in
19 // src/gtk/taskbar.cpp and used from here under wxGTK.
20 //
21 // Thanks to Ian Campbell, author of XMMS Status Docklet, for publishing
22 // KDE and GNOME 1.2 methods.
23
24
25 // For compilers that support precompilation, includes "wx.h".
26 #include "wx/wxprec.h"
27
28 #include "wx/taskbar.h"
29 #include "wx/frame.h"
30 #include "wx/bitmap.h"
31 #include "wx/statbmp.h"
32 #include "wx/sizer.h"
33 #include "wx/dcclient.h"
34 #include "wx/log.h"
35 #include "wx/image.h"
36
37 #ifdef __VMS
38 #pragma message disable nosimpint
39 #endif
40 #include <X11/Xlib.h>
41 #include <X11/Xatom.h>
42 #ifdef __VMS
43 #pragma message enable nosimpint
44 #endif
45
46 // ----------------------------------------------------------------------------
47 // base class that implements toolkit-specific method:
48 // ----------------------------------------------------------------------------
49
50 #ifdef __WXGTK20__
51 #include "wx/gtk/taskbarpriv.h"
52 #else
53 class WXDLLIMPEXP_ADV wxTaskBarIconAreaBase : public wxFrame
54 {
55 public:
56 wxTaskBarIconAreaBase()
57 : wxFrame(NULL, wxID_ANY, _T("systray icon"),
58 wxDefaultPosition, wxDefaultSize,
59 wxDEFAULT_FRAME_STYLE | wxFRAME_NO_TASKBAR |
60 wxSIMPLE_BORDER | wxFRAME_SHAPED) {}
61
62 bool IsProtocolSupported() const { return false; }
63 };
64 #endif
65
66
67 // ----------------------------------------------------------------------------
68 // toolkit dependent methods to set properties on helper window:
69 // ----------------------------------------------------------------------------
70
71 #if defined(__WXGTK__)
72 #include <gdk/gdk.h>
73 #include <gdk/gdkx.h>
74 #include <gtk/gtk.h>
75 #define GetDisplay() GDK_DISPLAY()
76 #define GetXWindow(wxwin) GDK_WINDOW_XWINDOW((wxwin)->m_widget->window)
77 #elif defined(__WXX11__) || defined(__WXMOTIF__)
78 #include "wx/x11/privx.h"
79 #define GetDisplay() ((Display*)wxGlobalDisplay())
80 #define GetXWindow(wxwin) ((Window)(wxwin)->GetHandle())
81 #else
82 #error "You must define X11 accessors for this port!"
83 #endif
84
85
86 // ----------------------------------------------------------------------------
87 // wxTaskBarIconArea is the real window that shows the icon:
88 // ----------------------------------------------------------------------------
89
90 class WXDLLIMPEXP_ADV wxTaskBarIconArea : public wxTaskBarIconAreaBase
91 {
92 public:
93 wxTaskBarIconArea(wxTaskBarIcon *icon, const wxBitmap &bmp);
94 void SetTrayIcon(const wxBitmap& bmp);
95 bool IsOk() { return true; }
96
97 protected:
98 void SetLegacyWMProperties();
99
100 void OnSizeChange(wxSizeEvent& event);
101 void OnPaint(wxPaintEvent& evt);
102 void OnMouseEvent(wxMouseEvent& event);
103 void OnMenuEvent(wxCommandEvent& event);
104
105 wxTaskBarIcon *m_icon;
106 wxPoint m_pos;
107 wxBitmap m_bmp;
108
109 DECLARE_EVENT_TABLE()
110 };
111
112 BEGIN_EVENT_TABLE(wxTaskBarIconArea, wxTaskBarIconAreaBase)
113 EVT_SIZE(wxTaskBarIconArea::OnSizeChange)
114 EVT_MOUSE_EVENTS(wxTaskBarIconArea::OnMouseEvent)
115 EVT_MENU(-1, wxTaskBarIconArea::OnMenuEvent)
116 EVT_PAINT(wxTaskBarIconArea::OnPaint)
117 END_EVENT_TABLE()
118
119 wxTaskBarIconArea::wxTaskBarIconArea(wxTaskBarIcon *icon, const wxBitmap &bmp)
120 : wxTaskBarIconAreaBase(), m_icon(icon), m_pos(0,0)
121 {
122 if (!IsProtocolSupported())
123 {
124 wxLogTrace(_T("systray"),
125 _T("using legacy KDE1,2 and GNOME 1.2 methods"));
126 SetLegacyWMProperties();
127 }
128
129 // Set initial size to bitmap size (tray manager may and often will
130 // change it):
131 SetSize(wxSize(bmp.GetWidth(), bmp.GetHeight()));
132
133 SetTrayIcon(bmp);
134 }
135
136 void wxTaskBarIconArea::SetTrayIcon(const wxBitmap& bmp)
137 {
138 m_bmp = bmp;
139
140 // determine suitable bitmap size:
141 wxSize winsize(GetSize());
142 wxSize bmpsize(m_bmp.GetWidth(), m_bmp.GetHeight());
143 wxSize iconsize(wxMin(winsize.x, bmpsize.x), wxMin(winsize.y, bmpsize.y));
144
145 // rescale the bitmap to fit into the tray icon window:
146 if (bmpsize != iconsize)
147 {
148 wxImage img = m_bmp.ConvertToImage();
149 img.Rescale(iconsize.x, iconsize.y);
150 m_bmp = wxBitmap(img);
151 }
152
153 wxRegion region;
154 region.Union(m_bmp);
155
156 // if the bitmap is smaller than the window, offset it:
157 if (winsize != iconsize)
158 {
159 m_pos.x = (winsize.x - iconsize.x) / 2;
160 m_pos.y = (winsize.y - iconsize.y) / 2;
161 region.Offset(m_pos.x, m_pos.y);
162 }
163
164 // set frame's shape to correct value and redraw:
165 SetShape(region);
166 Refresh();
167 }
168
169 void wxTaskBarIconArea::SetLegacyWMProperties()
170 {
171 #ifdef __WXGTK__
172 gtk_widget_realize(m_widget);
173 #endif
174
175 long data[1];
176
177 // KDE 2 & KDE 3:
178 Atom _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR =
179 XInternAtom(GetDisplay(), "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False);
180 data[0] = 0;
181 XChangeProperty(GetDisplay(), GetXWindow(this),
182 _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR,
183 XA_WINDOW, 32,
184 PropModeReplace, (unsigned char*)data, 1);
185
186 // GNOME 1.2 & KDE 1:
187 Atom KWM_DOCKWINDOW =
188 XInternAtom(GetDisplay(), "KWM_DOCKWINDOW", False);
189 data[0] = 1;
190 XChangeProperty(GetDisplay(), GetXWindow(this),
191 KWM_DOCKWINDOW,
192 KWM_DOCKWINDOW, 32,
193 PropModeReplace, (unsigned char*)data, 1);
194 }
195
196 void wxTaskBarIconArea::OnSizeChange(wxSizeEvent& event)
197 {
198 wxLogTrace(_T("systray"), _T("icon size changed to %i x %i"),
199 GetSize().x, GetSize().y);
200 // rescale or reposition the icon as needed:
201 wxBitmap bmp(m_bmp);
202 SetTrayIcon(bmp);
203 }
204
205 void wxTaskBarIconArea::OnPaint(wxPaintEvent& WXUNUSED(event))
206 {
207 wxPaintDC dc(this);
208 dc.DrawBitmap(m_bmp, m_pos.x, m_pos.y, true);
209 }
210
211 void wxTaskBarIconArea::OnMouseEvent(wxMouseEvent& event)
212 {
213 wxEventType type = 0;
214 wxEventType mtype = event.GetEventType();
215
216 if (mtype == wxEVT_LEFT_DOWN)
217 type = wxEVT_TASKBAR_LEFT_DOWN;
218 else if (mtype == wxEVT_LEFT_UP)
219 type = wxEVT_TASKBAR_LEFT_UP;
220 else if (mtype == wxEVT_LEFT_DCLICK)
221 type = wxEVT_TASKBAR_LEFT_DCLICK;
222 else if (mtype == wxEVT_RIGHT_DOWN)
223 type = wxEVT_TASKBAR_RIGHT_DOWN;
224 else if (mtype == wxEVT_RIGHT_UP)
225 type = wxEVT_TASKBAR_RIGHT_UP;
226 else if (mtype == wxEVT_RIGHT_DCLICK)
227 type = wxEVT_TASKBAR_RIGHT_DCLICK;
228 else if (mtype == wxEVT_MOTION)
229 type = wxEVT_TASKBAR_MOVE;
230 else
231 return;
232
233 wxTaskBarIconEvent e(type, m_icon);
234 m_icon->ProcessEvent(e);
235 }
236
237 void wxTaskBarIconArea::OnMenuEvent(wxCommandEvent& event)
238 {
239 m_icon->ProcessEvent(event);
240 }
241
242 // ----------------------------------------------------------------------------
243 // wxTaskBarIcon class:
244 // ----------------------------------------------------------------------------
245
246 IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon, wxEvtHandler)
247
248 wxTaskBarIcon::wxTaskBarIcon() : m_iconWnd(NULL)
249 {
250 }
251
252 wxTaskBarIcon::~wxTaskBarIcon()
253 {
254 if (m_iconWnd)
255 RemoveIcon();
256 }
257
258 bool wxTaskBarIcon::IsOk() const
259 {
260 return true;
261 }
262
263 bool wxTaskBarIcon::IsIconInstalled() const
264 {
265 return m_iconWnd != NULL;
266 }
267
268 bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip)
269 {
270 wxBitmap bmp;
271 bmp.CopyFromIcon(icon);
272
273 if (!m_iconWnd)
274 {
275 m_iconWnd = new wxTaskBarIconArea(this, bmp);
276 if (m_iconWnd->IsOk())
277 {
278 m_iconWnd->Show();
279 }
280 else
281 {
282 m_iconWnd->Destroy();
283 m_iconWnd = NULL;
284 return false;
285 }
286 }
287 else
288 {
289 m_iconWnd->SetTrayIcon(bmp);
290 }
291
292 #if wxUSE_TOOLTIPS
293 if (!tooltip.empty())
294 m_iconWnd->SetToolTip(tooltip);
295 else
296 m_iconWnd->SetToolTip(NULL);
297 #endif
298 return true;
299 }
300
301 bool wxTaskBarIcon::RemoveIcon()
302 {
303 if (!m_iconWnd)
304 return false;
305 m_iconWnd->Destroy();
306 m_iconWnd = NULL;
307 return true;
308 }
309
310 bool wxTaskBarIcon::PopupMenu(wxMenu *menu)
311 {
312 if (!m_iconWnd)
313 return false;
314 m_iconWnd->PopupMenu(menu);
315 return true;
316 }