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