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