1 /////////////////////////////////////////////////////////////////////////
2 // File: src/unix/taskbarx11.cpp
3 // Purpose: wxTaskBarIcon class for common Unix desktops
4 // Author: Vaclav Slavik
8 // Copyright: (c) Vaclav Slavik, 2003
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////
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.
17 // Thanks to Ian Campbell, author of XMMS Status Docklet, for publishing
18 // KDE and GNOME 1.2 methods.
21 // For compilers that support precompilation, includes "wx.h".
22 #include "wx/wxprec.h"
26 #include "wx/taskbar.h"
31 #include "wx/dcclient.h"
32 #include "wx/statbmp.h"
34 #include "wx/bitmap.h"
39 #pragma message disable nosimpint
42 #include <X11/Xatom.h>
44 #pragma message enable nosimpint
47 // ----------------------------------------------------------------------------
48 // base class that implements toolkit-specific method:
49 // ----------------------------------------------------------------------------
53 #if GTK_CHECK_VERSION(2,1,0)
54 #include "wx/gtk/taskbarpriv.h"
55 #define TASKBAR_ICON_AREA_BASE_INCLUDED
59 #ifndef TASKBAR_ICON_AREA_BASE_INCLUDED
60 class WXDLLIMPEXP_ADV wxTaskBarIconAreaBase
: public wxFrame
63 wxTaskBarIconAreaBase()
64 : wxFrame(NULL
, wxID_ANY
, _T("systray icon"),
65 wxDefaultPosition
, wxDefaultSize
,
66 wxDEFAULT_FRAME_STYLE
| wxFRAME_NO_TASKBAR
|
67 wxSIMPLE_BORDER
| wxFRAME_SHAPED
) {}
69 static bool IsProtocolSupported() { return false; }
74 // ----------------------------------------------------------------------------
75 // toolkit dependent methods to set properties on helper window:
76 // ----------------------------------------------------------------------------
78 #if defined(__WXGTK__)
82 #define GetDisplay() GDK_DISPLAY()
83 #define GetXWindow(wxwin) GDK_WINDOW_XWINDOW((wxwin)->m_widget->window)
84 #elif defined(__WXX11__) || defined(__WXMOTIF__)
85 #include "wx/x11/privx.h"
86 #define GetDisplay() ((Display*)wxGlobalDisplay())
87 #define GetXWindow(wxwin) ((Window)(wxwin)->GetHandle())
89 #error "You must define X11 accessors for this port!"
93 // ----------------------------------------------------------------------------
94 // wxTaskBarIconArea is the real window that shows the icon:
95 // ----------------------------------------------------------------------------
97 class WXDLLIMPEXP_ADV wxTaskBarIconArea
: public wxTaskBarIconAreaBase
100 wxTaskBarIconArea(wxTaskBarIcon
*icon
, const wxBitmap
&bmp
);
101 void SetTrayIcon(const wxBitmap
& bmp
);
102 bool IsOk() { return true; }
105 void SetLegacyWMProperties();
107 void OnSizeChange(wxSizeEvent
& event
);
108 void OnPaint(wxPaintEvent
& evt
);
109 void OnMouseEvent(wxMouseEvent
& event
);
110 void OnMenuEvent(wxCommandEvent
& event
);
112 wxTaskBarIcon
*m_icon
;
116 DECLARE_EVENT_TABLE()
119 BEGIN_EVENT_TABLE(wxTaskBarIconArea
, wxTaskBarIconAreaBase
)
120 EVT_SIZE(wxTaskBarIconArea::OnSizeChange
)
121 EVT_MOUSE_EVENTS(wxTaskBarIconArea::OnMouseEvent
)
122 EVT_MENU(wxID_ANY
, wxTaskBarIconArea::OnMenuEvent
)
123 EVT_PAINT(wxTaskBarIconArea::OnPaint
)
126 wxTaskBarIconArea::wxTaskBarIconArea(wxTaskBarIcon
*icon
, const wxBitmap
&bmp
)
127 : wxTaskBarIconAreaBase(), m_icon(icon
), m_bmp(bmp
)
129 #if defined(__WXGTK20__) && defined(TASKBAR_ICON_AREA_BASE_INCLUDED)
130 m_invokingWindow
= icon
;
133 // Set initial size to bitmap size (tray manager may and often will
135 SetClientSize(wxSize(bmp
.GetWidth(), bmp
.GetHeight()));
139 if (!IsProtocolSupported())
141 wxLogTrace(_T("systray"),
142 _T("using legacy KDE1,2 and GNOME 1.2 methods"));
143 SetLegacyWMProperties();
147 void wxTaskBarIconArea::SetTrayIcon(const wxBitmap
& bmp
)
151 // determine suitable bitmap size:
152 wxSize
winsize(GetClientSize());
153 wxSize
bmpsize(m_bmp
.GetWidth(), m_bmp
.GetHeight());
154 wxSize
iconsize(wxMin(winsize
.x
, bmpsize
.x
), wxMin(winsize
.y
, bmpsize
.y
));
156 // rescale the bitmap to fit into the tray icon window:
157 if (bmpsize
!= iconsize
)
159 wxImage img
= m_bmp
.ConvertToImage();
160 img
.Rescale(iconsize
.x
, iconsize
.y
);
161 m_bmp
= wxBitmap(img
);
167 // if the bitmap is smaller than the window, offset it:
168 if (winsize
!= iconsize
)
170 m_pos
.x
= (winsize
.x
- iconsize
.x
) / 2;
171 m_pos
.y
= (winsize
.y
- iconsize
.y
) / 2;
172 region
.Offset(m_pos
.x
, m_pos
.y
);
175 // set frame's shape to correct value and redraw:
180 void wxTaskBarIconArea::SetLegacyWMProperties()
183 gtk_widget_realize(m_widget
);
189 Atom _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR
=
190 XInternAtom(GetDisplay(), "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False
);
192 XChangeProperty(GetDisplay(), GetXWindow(this),
193 _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR
,
195 PropModeReplace
, (unsigned char*)data
, 1);
197 // GNOME 1.2 & KDE 1:
198 Atom KWM_DOCKWINDOW
=
199 XInternAtom(GetDisplay(), "KWM_DOCKWINDOW", False
);
201 XChangeProperty(GetDisplay(), GetXWindow(this),
204 PropModeReplace
, (unsigned char*)data
, 1);
207 void wxTaskBarIconArea::OnSizeChange(wxSizeEvent
& WXUNUSED(event
))
209 wxLogTrace(_T("systray"), _T("icon size changed to %i x %i"),
210 GetSize().x
, GetSize().y
);
211 // rescale or reposition the icon as needed:
216 void wxTaskBarIconArea::OnPaint(wxPaintEvent
& WXUNUSED(event
))
219 dc
.DrawBitmap(m_bmp
, m_pos
.x
, m_pos
.y
, true);
222 void wxTaskBarIconArea::OnMouseEvent(wxMouseEvent
& event
)
224 wxEventType type
= 0;
225 wxEventType mtype
= event
.GetEventType();
227 if (mtype
== wxEVT_LEFT_DOWN
)
228 type
= wxEVT_TASKBAR_LEFT_DOWN
;
229 else if (mtype
== wxEVT_LEFT_UP
)
230 type
= wxEVT_TASKBAR_LEFT_UP
;
231 else if (mtype
== wxEVT_LEFT_DCLICK
)
232 type
= wxEVT_TASKBAR_LEFT_DCLICK
;
233 else if (mtype
== wxEVT_RIGHT_DOWN
)
234 type
= wxEVT_TASKBAR_RIGHT_DOWN
;
235 else if (mtype
== wxEVT_RIGHT_UP
)
236 type
= wxEVT_TASKBAR_RIGHT_UP
;
237 else if (mtype
== wxEVT_RIGHT_DCLICK
)
238 type
= wxEVT_TASKBAR_RIGHT_DCLICK
;
239 else if (mtype
== wxEVT_MOTION
)
240 type
= wxEVT_TASKBAR_MOVE
;
244 wxTaskBarIconEvent
e(type
, m_icon
);
245 m_icon
->ProcessEvent(e
);
248 void wxTaskBarIconArea::OnMenuEvent(wxCommandEvent
& event
)
250 m_icon
->ProcessEvent(event
);
253 // ----------------------------------------------------------------------------
254 // wxTaskBarIconBase class:
255 // ----------------------------------------------------------------------------
257 bool wxTaskBarIconBase::IsAvailable()
259 return wxTaskBarIconArea::IsProtocolSupported();
262 // ----------------------------------------------------------------------------
263 // wxTaskBarIcon class:
264 // ----------------------------------------------------------------------------
266 IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon
, wxEvtHandler
)
268 wxTaskBarIcon::wxTaskBarIcon() : m_iconWnd(NULL
)
272 wxTaskBarIcon::~wxTaskBarIcon()
276 m_iconWnd
->Disconnect(
277 wxEVT_DESTROY
, wxObjectEventFunction(NULL
), NULL
, this);
282 bool wxTaskBarIcon::IsOk() const
287 bool wxTaskBarIcon::IsIconInstalled() const
289 return m_iconWnd
!= NULL
;
292 // Destroy event from wxTaskBarIconArea
293 void wxTaskBarIcon::OnDestroy(wxWindowDestroyEvent
&)
295 // prevent crash if wxTaskBarIconArea is destroyed by something else,
296 // for example if panel/kicker is killed
300 bool wxTaskBarIcon::SetIcon(const wxIcon
& icon
, const wxString
& tooltip
)
303 bmp
.CopyFromIcon(icon
);
307 m_iconWnd
= new wxTaskBarIconArea(this, bmp
);
308 if (m_iconWnd
->IsOk())
310 m_iconWnd
->Connect(wxEVT_DESTROY
,
311 wxWindowDestroyEventHandler(wxTaskBarIcon::OnDestroy
),
317 m_iconWnd
->Destroy();
324 m_iconWnd
->SetTrayIcon(bmp
);
328 if (!tooltip
.empty())
329 m_iconWnd
->SetToolTip(tooltip
);
331 m_iconWnd
->SetToolTip(NULL
);
333 wxUnusedVar(tooltip
);
338 bool wxTaskBarIcon::RemoveIcon()
342 m_iconWnd
->Destroy();
347 bool wxTaskBarIcon::PopupMenu(wxMenu
*menu
)
351 m_iconWnd
->PopupMenu(menu
);
355 #endif // wxUSE_TASKBARICON