]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/unix/taskbarx11.cpp
Handle IN_MOVE inotify events better.
[wxWidgets.git] / src / unix / taskbarx11.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////
2// File: src/unix/taskbarx11.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// NB: This implementation does *not* work with every X11 window manager.
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.
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
24#if wxUSE_TASKBARICON && !defined(__WXGTK20__)
25
26#include "wx/taskbar.h"
27
28#ifndef WX_PRECOMP
29 #include "wx/log.h"
30 #include "wx/frame.h"
31 #include "wx/dcclient.h"
32 #include "wx/statbmp.h"
33 #include "wx/sizer.h"
34 #include "wx/bitmap.h"
35 #include "wx/image.h"
36#endif
37
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
47// ----------------------------------------------------------------------------
48// base class that implements toolkit-specific method:
49// ----------------------------------------------------------------------------
50
51 class WXDLLIMPEXP_ADV wxTaskBarIconAreaBase : public wxFrame
52 {
53 public:
54 wxTaskBarIconAreaBase()
55 : wxFrame(NULL, wxID_ANY, wxT("systray icon"),
56 wxDefaultPosition, wxDefaultSize,
57 wxDEFAULT_FRAME_STYLE | wxFRAME_NO_TASKBAR |
58 wxSIMPLE_BORDER | wxFRAME_SHAPED) {}
59
60 static bool IsProtocolSupported() { return false; }
61 };
62
63// ----------------------------------------------------------------------------
64// toolkit dependent methods to set properties on helper window:
65// ----------------------------------------------------------------------------
66
67#if defined(__WXGTK__)
68 #include <gtk/gtk.h>
69 #include <gdk/gdkx.h>
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
80
81// ----------------------------------------------------------------------------
82// wxTaskBarIconArea is the real window that shows the icon:
83// ----------------------------------------------------------------------------
84
85class WXDLLIMPEXP_ADV wxTaskBarIconArea : public wxTaskBarIconAreaBase
86{
87public:
88 wxTaskBarIconArea(wxTaskBarIcon *icon, const wxBitmap &bmp);
89 void SetTrayIcon(const wxBitmap& bmp);
90 bool IsOk() { return true; }
91
92protected:
93 void SetLegacyWMProperties();
94
95 void OnSizeChange(wxSizeEvent& event);
96 void OnPaint(wxPaintEvent& evt);
97 void OnMouseEvent(wxMouseEvent& event);
98 void OnMenuEvent(wxCommandEvent& event);
99
100 wxTaskBarIcon *m_icon;
101 wxPoint m_pos;
102 wxBitmap m_bmp;
103
104 DECLARE_EVENT_TABLE()
105};
106
107BEGIN_EVENT_TABLE(wxTaskBarIconArea, wxTaskBarIconAreaBase)
108 EVT_SIZE(wxTaskBarIconArea::OnSizeChange)
109 EVT_MOUSE_EVENTS(wxTaskBarIconArea::OnMouseEvent)
110 EVT_MENU(wxID_ANY, wxTaskBarIconArea::OnMenuEvent)
111 EVT_PAINT(wxTaskBarIconArea::OnPaint)
112END_EVENT_TABLE()
113
114wxTaskBarIconArea::wxTaskBarIconArea(wxTaskBarIcon *icon, const wxBitmap &bmp)
115 : wxTaskBarIconAreaBase(), m_icon(icon), m_bmp(bmp)
116{
117 // Set initial size to bitmap size (tray manager may and often will
118 // change it):
119 SetClientSize(wxSize(bmp.GetWidth(), bmp.GetHeight()));
120
121 SetTrayIcon(bmp);
122
123 if (!IsProtocolSupported())
124 {
125 wxLogTrace(wxT("systray"),
126 wxT("using legacy KDE1,2 and GNOME 1.2 methods"));
127 SetLegacyWMProperties();
128 }
129}
130
131void wxTaskBarIconArea::SetTrayIcon(const wxBitmap& bmp)
132{
133 m_bmp = bmp;
134
135 // determine suitable bitmap size:
136 wxSize winsize(GetClientSize());
137 wxSize bmpsize(m_bmp.GetWidth(), m_bmp.GetHeight());
138 wxSize iconsize(wxMin(winsize.x, bmpsize.x), wxMin(winsize.y, bmpsize.y));
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 }
147
148 wxRegion region;
149 region.Union(m_bmp);
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()
165{
166#ifdef __WXGTK__
167 gtk_widget_realize(m_widget);
168#endif
169
170 long data[1];
171
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;
176 XChangeProperty(GetDisplay(), GetXWindow(this),
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;
185 XChangeProperty(GetDisplay(), GetXWindow(this),
186 KWM_DOCKWINDOW,
187 KWM_DOCKWINDOW, 32,
188 PropModeReplace, (unsigned char*)data, 1);
189}
190
191void wxTaskBarIconArea::OnSizeChange(wxSizeEvent& WXUNUSED(event))
192{
193 wxLogTrace(wxT("systray"), wxT("icon size changed to %i x %i"),
194 GetSize().x, GetSize().y);
195 // rescale or reposition the icon as needed:
196 wxBitmap bmp(m_bmp);
197 SetTrayIcon(bmp);
198}
199
200void wxTaskBarIconArea::OnPaint(wxPaintEvent& WXUNUSED(event))
201{
202 wxPaintDC dc(this);
203 dc.DrawBitmap(m_bmp, m_pos.x, m_pos.y, true);
204}
205
206void wxTaskBarIconArea::OnMouseEvent(wxMouseEvent& event)
207{
208 wxEventType type = 0;
209 wxEventType mtype = event.GetEventType();
210
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)
233{
234 m_icon->ProcessEvent(event);
235}
236
237// ----------------------------------------------------------------------------
238// wxTaskBarIconBase class:
239// ----------------------------------------------------------------------------
240
241bool wxTaskBarIconBase::IsAvailable()
242{
243 return wxTaskBarIconArea::IsProtocolSupported();
244}
245
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)
259 {
260 m_iconWnd->Disconnect(wxEVT_DESTROY,
261 wxWindowDestroyEventHandler(wxTaskBarIcon::OnDestroy), NULL, this);
262 RemoveIcon();
263 }
264}
265
266bool wxTaskBarIcon::IsOk() const
267{
268 return true;
269}
270
271bool wxTaskBarIcon::IsIconInstalled() const
272{
273 return m_iconWnd != NULL;
274}
275
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
284bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip)
285{
286 wxBitmap bmp;
287 bmp.CopyFromIcon(icon);
288
289 if (!m_iconWnd)
290 {
291 m_iconWnd = new wxTaskBarIconArea(this, bmp);
292 if (m_iconWnd->IsOk())
293 {
294 m_iconWnd->Connect(wxEVT_DESTROY,
295 wxWindowDestroyEventHandler(wxTaskBarIcon::OnDestroy),
296 NULL, this);
297 m_iconWnd->Show();
298 }
299 else
300 {
301 m_iconWnd->Destroy();
302 m_iconWnd = NULL;
303 return false;
304 }
305 }
306 else
307 {
308 m_iconWnd->SetTrayIcon(bmp);
309 }
310
311#if wxUSE_TOOLTIPS
312 if (!tooltip.empty())
313 m_iconWnd->SetToolTip(tooltip);
314 else
315 m_iconWnd->SetToolTip(NULL);
316#else
317 wxUnusedVar(tooltip);
318#endif
319 return true;
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;
335 m_iconWnd->PopupMenu(menu);
336 return true;
337}
338
339#endif // wxUSE_TASKBARICON