use shaped window for taskbar icon, so that background shows correctly behind icons...
[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.
18 //
19 // FIXME: implement:
20 // - GNOME 2 support (see www.freedesktop.org for specification;
21 // KDE 3 uses this method as well, even though legacy KDE
22 // method we implement works as well)
23 // - IceWM support (?)
24 //
25 // Thanks to Ian Campbell, author of XMMS Status Docklet, for publishing
26 // KDE and GNOME 1.2 methods.
27
28
29 // For compilers that support precompilation, includes "wx.h".
30 #include "wx/wxprec.h"
31
32 #include "wx/taskbar.h"
33 #include "wx/frame.h"
34 #include "wx/bitmap.h"
35 #include "wx/statbmp.h"
36 #include "wx/sizer.h"
37 #include "wx/dcclient.h"
38
39 #ifdef __VMS
40 #pragma message disable nosimpint
41 #endif
42 #include <X11/Xlib.h>
43 #include <X11/Xatom.h>
44 #ifdef __VMS
45 #pragma message enable nosimpint
46 #endif
47
48 // ----------------------------------------------------------------------------
49 // toolkit dependent methods to set properties on helper window:
50 // ----------------------------------------------------------------------------
51
52 #if defined(__WXGTK__)
53 #include <gdk/gdk.h>
54 #include <gdk/gdkx.h>
55 #include <gtk/gtk.h>
56 #define GetDisplay() GDK_DISPLAY()
57 #define GetXWindow(wxwin) GDK_WINDOW_XWINDOW((wxwin)->m_widget->window)
58 #elif defined(__WXX11__) || defined(__WXMOTIF__)
59 #include "wx/x11/privx.h"
60 #define GetDisplay() ((Display*)wxGlobalDisplay())
61 #define GetXWindow(wxwin) ((Window)(wxwin)->GetHandle())
62 #else
63 #error "You must define X11 accessors for this port!"
64 #endif
65
66
67 // ----------------------------------------------------------------------------
68 // wxTaskBarIconArea is the real window that shows the icon:
69 // ----------------------------------------------------------------------------
70
71 class WXDLLIMPEXP_ADV wxTaskBarIconArea : public wxFrame
72 {
73 public:
74 wxTaskBarIconArea(wxTaskBarIcon *icon, const wxBitmap &bmp)
75 : wxFrame(NULL, -1, wxT("taskbar icon"),
76 wxDefaultPosition, wxDefaultSize,
77 wxDEFAULT_FRAME_STYLE | wxFRAME_NO_TASKBAR |
78 wxSIMPLE_BORDER | wxFRAME_SHAPED),
79 m_icon(icon), m_bmp(bmp)
80 {
81 SetWMProperties();
82 SetSize(wxSize(bmp.GetWidth(), bmp.GetHeight()));
83 }
84
85 bool IsOk() { return true; }
86
87 protected:
88 void SetWMProperties();
89
90 void OnPaint(wxPaintEvent& evt);
91 void OnWindowCreate(wxWindowCreateEvent& event);
92 void OnMouseEvent(wxMouseEvent& event);
93 void OnMenuEvent(wxCommandEvent& event);
94
95 wxTaskBarIcon *m_icon;
96 wxBitmap m_bmp;
97
98 DECLARE_EVENT_TABLE()
99 };
100
101 BEGIN_EVENT_TABLE(wxTaskBarIconArea, wxFrame)
102 EVT_MOUSE_EVENTS(wxTaskBarIconArea::OnMouseEvent)
103 EVT_MENU(-1, wxTaskBarIconArea::OnMenuEvent)
104 EVT_PAINT(wxTaskBarIconArea::OnPaint)
105 #ifdef __WXGTK__
106 EVT_WINDOW_CREATE(wxTaskBarIconArea::OnWindowCreate)
107 #endif
108 END_EVENT_TABLE()
109
110 void wxTaskBarIconArea::SetWMProperties()
111 {
112 #ifdef __WXGTK__
113 gtk_widget_realize(m_widget);
114 #endif
115
116 long data[1];
117
118 // KDE 2 & KDE 3:
119 Atom _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR =
120 XInternAtom(GetDisplay(), "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False);
121 data[0] = 0;
122 XChangeProperty(GetDisplay(), GetXWindow(this),
123 _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR,
124 XA_WINDOW, 32,
125 PropModeReplace, (unsigned char*)data, 1);
126
127 // GNOME 1.2 & KDE 1:
128 Atom KWM_DOCKWINDOW =
129 XInternAtom(GetDisplay(), "KWM_DOCKWINDOW", False);
130 data[0] = 1;
131 XChangeProperty(GetDisplay(), GetXWindow(this),
132 KWM_DOCKWINDOW,
133 KWM_DOCKWINDOW, 32,
134 PropModeReplace, (unsigned char*)data, 1);
135 }
136
137 void wxTaskBarIconArea::OnWindowCreate(wxWindowCreateEvent& WXUNUSED(event))
138 {
139 SetShape(wxRegion(m_bmp));
140 }
141
142 void wxTaskBarIconArea::OnPaint(wxPaintEvent& WXUNUSED(event))
143 {
144 wxPaintDC dc(this);
145 dc.DrawBitmap(m_bmp, 0, 0, true);
146 }
147
148 void wxTaskBarIconArea::OnMouseEvent(wxMouseEvent& event)
149 {
150 wxEventType type = 0;
151 wxEventType mtype = event.GetEventType();
152
153 if (mtype == wxEVT_LEFT_DOWN)
154 type = wxEVT_TASKBAR_LEFT_DOWN;
155 else if (mtype == wxEVT_LEFT_UP)
156 type = wxEVT_TASKBAR_LEFT_UP;
157 else if (mtype == wxEVT_LEFT_DCLICK)
158 type = wxEVT_TASKBAR_LEFT_DCLICK;
159 else if (mtype == wxEVT_RIGHT_DOWN)
160 type = wxEVT_TASKBAR_RIGHT_DOWN;
161 else if (mtype == wxEVT_RIGHT_UP)
162 type = wxEVT_TASKBAR_RIGHT_UP;
163 else if (mtype == wxEVT_RIGHT_DCLICK)
164 type = wxEVT_TASKBAR_RIGHT_DCLICK;
165 else if (mtype == wxEVT_MOTION)
166 type = wxEVT_TASKBAR_MOVE;
167 else
168 return;
169
170 wxTaskBarIconEvent e(type, m_icon);
171 m_icon->ProcessEvent(e);
172 }
173
174 void wxTaskBarIconArea::OnMenuEvent(wxCommandEvent& event)
175 {
176 m_icon->ProcessEvent(event);
177 }
178
179 // ----------------------------------------------------------------------------
180 // wxTaskBarIcon class:
181 // ----------------------------------------------------------------------------
182
183 IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon, wxEvtHandler)
184
185 wxTaskBarIcon::wxTaskBarIcon() : m_iconWnd(NULL)
186 {
187 }
188
189 wxTaskBarIcon::~wxTaskBarIcon()
190 {
191 if (m_iconWnd)
192 RemoveIcon();
193 }
194
195 bool wxTaskBarIcon::IsOk() const
196 {
197 return true;
198 }
199
200 bool wxTaskBarIcon::IsIconInstalled() const
201 {
202 return m_iconWnd != NULL;
203 }
204
205 bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip)
206 {
207 if (m_iconWnd)
208 RemoveIcon();
209
210 wxBitmap bmp;
211 bmp.CopyFromIcon(icon);
212
213 m_iconWnd = new wxTaskBarIconArea(this, bmp);
214
215 #if wxUSE_TOOLTIPS
216 if (!tooltip.empty())
217 m_iconWnd->SetToolTip(tooltip);
218 #endif
219 if (m_iconWnd->IsOk())
220 {
221 m_iconWnd->Show();
222 return true;
223 }
224 else
225 {
226 m_iconWnd->Destroy();
227 m_iconWnd = NULL;
228 return false;
229 }
230 }
231
232 bool wxTaskBarIcon::RemoveIcon()
233 {
234 if (!m_iconWnd)
235 return false;
236 m_iconWnd->Destroy();
237 m_iconWnd = NULL;
238 return true;
239 }
240
241 bool wxTaskBarIcon::PopupMenu(wxMenu *menu)
242 {
243 if (!m_iconWnd)
244 return false;
245 wxSize size(m_iconWnd->GetClientSize());
246 m_iconWnd->PopupMenu(menu, size.x/2, size.y/2);
247 return true;
248 }