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