]> git.saurik.com Git - wxWidgets.git/blob - src/unix/taskbarx11.cpp
reverted bitmap depth increases
[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 <gtk/gtk.h>
52 #if GTK_CHECK_VERSION(2,1,0)
53 #include "wx/gtk/taskbarpriv.h"
54 #define TASKBAR_ICON_AREA_BASE_INCLUDED
55 #endif
56 #endif
57
58 #ifndef TASKBAR_ICON_AREA_BASE_INCLUDED
59 class WXDLLIMPEXP_ADV wxTaskBarIconAreaBase : public wxFrame
60 {
61 public:
62 wxTaskBarIconAreaBase()
63 : wxFrame(NULL, wxID_ANY, _T("systray icon"),
64 wxDefaultPosition, wxDefaultSize,
65 wxDEFAULT_FRAME_STYLE | wxFRAME_NO_TASKBAR |
66 wxSIMPLE_BORDER | wxFRAME_SHAPED) {}
67
68 bool IsProtocolSupported() const { return false; }
69 };
70 #endif
71
72
73 // ----------------------------------------------------------------------------
74 // toolkit dependent methods to set properties on helper window:
75 // ----------------------------------------------------------------------------
76
77 #if defined(__WXGTK__)
78 #include <gdk/gdk.h>
79 #include <gdk/gdkx.h>
80 #include <gtk/gtk.h>
81 #define GetDisplay() GDK_DISPLAY()
82 #define GetXWindow(wxwin) GDK_WINDOW_XWINDOW((wxwin)->m_widget->window)
83 #elif defined(__WXX11__) || defined(__WXMOTIF__)
84 #include "wx/x11/privx.h"
85 #define GetDisplay() ((Display*)wxGlobalDisplay())
86 #define GetXWindow(wxwin) ((Window)(wxwin)->GetHandle())
87 #else
88 #error "You must define X11 accessors for this port!"
89 #endif
90
91
92 // ----------------------------------------------------------------------------
93 // wxTaskBarIconArea is the real window that shows the icon:
94 // ----------------------------------------------------------------------------
95
96 class WXDLLIMPEXP_ADV wxTaskBarIconArea : public wxTaskBarIconAreaBase
97 {
98 public:
99 wxTaskBarIconArea(wxTaskBarIcon *icon, const wxBitmap &bmp);
100 void SetTrayIcon(const wxBitmap& bmp);
101 bool IsOk() { return true; }
102
103 protected:
104 void SetLegacyWMProperties();
105
106 void OnSizeChange(wxSizeEvent& event);
107 void OnPaint(wxPaintEvent& evt);
108 void OnMouseEvent(wxMouseEvent& event);
109 void OnMenuEvent(wxCommandEvent& event);
110
111 wxTaskBarIcon *m_icon;
112 wxPoint m_pos;
113 wxBitmap m_bmp;
114
115 DECLARE_EVENT_TABLE()
116 };
117
118 BEGIN_EVENT_TABLE(wxTaskBarIconArea, wxTaskBarIconAreaBase)
119 EVT_SIZE(wxTaskBarIconArea::OnSizeChange)
120 EVT_MOUSE_EVENTS(wxTaskBarIconArea::OnMouseEvent)
121 EVT_MENU(-1, wxTaskBarIconArea::OnMenuEvent)
122 EVT_PAINT(wxTaskBarIconArea::OnPaint)
123 END_EVENT_TABLE()
124
125 wxTaskBarIconArea::wxTaskBarIconArea(wxTaskBarIcon *icon, const wxBitmap &bmp)
126 : wxTaskBarIconAreaBase(), m_icon(icon), m_pos(0,0)
127 {
128 if (!IsProtocolSupported())
129 {
130 wxLogTrace(_T("systray"),
131 _T("using legacy KDE1,2 and GNOME 1.2 methods"));
132 SetLegacyWMProperties();
133 }
134
135 // Set initial size to bitmap size (tray manager may and often will
136 // change it):
137 SetSize(wxSize(bmp.GetWidth(), bmp.GetHeight()));
138
139 SetTrayIcon(bmp);
140 }
141
142 void wxTaskBarIconArea::SetTrayIcon(const wxBitmap& bmp)
143 {
144 m_bmp = bmp;
145
146 // determine suitable bitmap size:
147 wxSize winsize(GetSize());
148 wxSize bmpsize(m_bmp.GetWidth(), m_bmp.GetHeight());
149 wxSize iconsize(wxMin(winsize.x, bmpsize.x), wxMin(winsize.y, bmpsize.y));
150
151 // rescale the bitmap to fit into the tray icon window:
152 if (bmpsize != iconsize)
153 {
154 wxImage img = m_bmp.ConvertToImage();
155 img.Rescale(iconsize.x, iconsize.y);
156 m_bmp = wxBitmap(img);
157 }
158
159 wxRegion region;
160 region.Union(m_bmp);
161
162 // if the bitmap is smaller than the window, offset it:
163 if (winsize != iconsize)
164 {
165 m_pos.x = (winsize.x - iconsize.x) / 2;
166 m_pos.y = (winsize.y - iconsize.y) / 2;
167 region.Offset(m_pos.x, m_pos.y);
168 }
169
170 // set frame's shape to correct value and redraw:
171 SetShape(region);
172 Refresh();
173 }
174
175 void wxTaskBarIconArea::SetLegacyWMProperties()
176 {
177 #ifdef __WXGTK__
178 gtk_widget_realize(m_widget);
179 #endif
180
181 long data[1];
182
183 // KDE 2 & KDE 3:
184 Atom _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR =
185 XInternAtom(GetDisplay(), "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False);
186 data[0] = 0;
187 XChangeProperty(GetDisplay(), GetXWindow(this),
188 _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR,
189 XA_WINDOW, 32,
190 PropModeReplace, (unsigned char*)data, 1);
191
192 // GNOME 1.2 & KDE 1:
193 Atom KWM_DOCKWINDOW =
194 XInternAtom(GetDisplay(), "KWM_DOCKWINDOW", False);
195 data[0] = 1;
196 XChangeProperty(GetDisplay(), GetXWindow(this),
197 KWM_DOCKWINDOW,
198 KWM_DOCKWINDOW, 32,
199 PropModeReplace, (unsigned char*)data, 1);
200 }
201
202 void wxTaskBarIconArea::OnSizeChange(wxSizeEvent& event)
203 {
204 wxLogTrace(_T("systray"), _T("icon size changed to %i x %i"),
205 GetSize().x, GetSize().y);
206 // rescale or reposition the icon as needed:
207 wxBitmap bmp(m_bmp);
208 SetTrayIcon(bmp);
209 }
210
211 void wxTaskBarIconArea::OnPaint(wxPaintEvent& WXUNUSED(event))
212 {
213 wxPaintDC dc(this);
214 dc.DrawBitmap(m_bmp, m_pos.x, m_pos.y, true);
215 }
216
217 void wxTaskBarIconArea::OnMouseEvent(wxMouseEvent& event)
218 {
219 wxEventType type = 0;
220 wxEventType mtype = event.GetEventType();
221
222 if (mtype == wxEVT_LEFT_DOWN)
223 type = wxEVT_TASKBAR_LEFT_DOWN;
224 else if (mtype == wxEVT_LEFT_UP)
225 type = wxEVT_TASKBAR_LEFT_UP;
226 else if (mtype == wxEVT_LEFT_DCLICK)
227 type = wxEVT_TASKBAR_LEFT_DCLICK;
228 else if (mtype == wxEVT_RIGHT_DOWN)
229 type = wxEVT_TASKBAR_RIGHT_DOWN;
230 else if (mtype == wxEVT_RIGHT_UP)
231 type = wxEVT_TASKBAR_RIGHT_UP;
232 else if (mtype == wxEVT_RIGHT_DCLICK)
233 type = wxEVT_TASKBAR_RIGHT_DCLICK;
234 else if (mtype == wxEVT_MOTION)
235 type = wxEVT_TASKBAR_MOVE;
236 else
237 return;
238
239 wxTaskBarIconEvent e(type, m_icon);
240 m_icon->ProcessEvent(e);
241 }
242
243 void wxTaskBarIconArea::OnMenuEvent(wxCommandEvent& event)
244 {
245 m_icon->ProcessEvent(event);
246 }
247
248 // ----------------------------------------------------------------------------
249 // wxTaskBarIcon class:
250 // ----------------------------------------------------------------------------
251
252 IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon, wxEvtHandler)
253
254 wxTaskBarIcon::wxTaskBarIcon() : m_iconWnd(NULL)
255 {
256 }
257
258 wxTaskBarIcon::~wxTaskBarIcon()
259 {
260 if (m_iconWnd)
261 RemoveIcon();
262 }
263
264 bool wxTaskBarIcon::IsOk() const
265 {
266 return true;
267 }
268
269 bool wxTaskBarIcon::IsIconInstalled() const
270 {
271 return m_iconWnd != NULL;
272 }
273
274 bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip)
275 {
276 wxBitmap bmp;
277 bmp.CopyFromIcon(icon);
278
279 if (!m_iconWnd)
280 {
281 m_iconWnd = new wxTaskBarIconArea(this, bmp);
282 if (m_iconWnd->IsOk())
283 {
284 m_iconWnd->Show();
285 }
286 else
287 {
288 m_iconWnd->Destroy();
289 m_iconWnd = NULL;
290 return false;
291 }
292 }
293 else
294 {
295 m_iconWnd->SetTrayIcon(bmp);
296 }
297
298 #if wxUSE_TOOLTIPS
299 if (!tooltip.empty())
300 m_iconWnd->SetToolTip(tooltip);
301 else
302 m_iconWnd->SetToolTip(NULL);
303 #endif
304 return true;
305 }
306
307 bool wxTaskBarIcon::RemoveIcon()
308 {
309 if (!m_iconWnd)
310 return false;
311 m_iconWnd->Destroy();
312 m_iconWnd = NULL;
313 return true;
314 }
315
316 bool wxTaskBarIcon::PopupMenu(wxMenu *menu)
317 {
318 if (!m_iconWnd)
319 return false;
320 m_iconWnd->PopupMenu(menu);
321 return true;
322 }