1 /////////////////////////////////////////////////////////////////////////
2 // File: src/unix/taskbarx11.cpp
3 // Purpose: wxTaskBarIcon class for common Unix desktops
4 // Author: Vaclav Slavik
7 // Copyright: (c) Vaclav Slavik, 2003
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////
11 // NB: This implementation does *not* work with every X11 window manager.
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.
16 // Thanks to Ian Campbell, author of XMMS Status Docklet, for publishing
17 // KDE and GNOME 1.2 methods.
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
23 #if wxUSE_TASKBARICON && !defined(__WXGTK20__)
25 #include "wx/taskbar.h"
30 #include "wx/dcclient.h"
31 #include "wx/statbmp.h"
33 #include "wx/bitmap.h"
38 #pragma message disable nosimpint
41 #include <X11/Xatom.h>
43 #pragma message enable nosimpint
46 // ----------------------------------------------------------------------------
47 // base class that implements toolkit-specific method:
48 // ----------------------------------------------------------------------------
50 class WXDLLIMPEXP_ADV wxTaskBarIconAreaBase
: public wxFrame
53 wxTaskBarIconAreaBase()
54 : wxFrame(NULL
, wxID_ANY
, wxT("systray icon"),
55 wxDefaultPosition
, wxDefaultSize
,
56 wxDEFAULT_FRAME_STYLE
| wxFRAME_NO_TASKBAR
|
57 wxSIMPLE_BORDER
| wxFRAME_SHAPED
) {}
59 static bool IsProtocolSupported() { return false; }
62 // ----------------------------------------------------------------------------
63 // toolkit dependent methods to set properties on helper window:
64 // ----------------------------------------------------------------------------
66 #if defined(__WXGTK__)
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())
76 #error "You must define X11 accessors for this port!"
80 // ----------------------------------------------------------------------------
81 // wxTaskBarIconArea is the real window that shows the icon:
82 // ----------------------------------------------------------------------------
84 class WXDLLIMPEXP_ADV wxTaskBarIconArea
: public wxTaskBarIconAreaBase
87 wxTaskBarIconArea(wxTaskBarIcon
*icon
, const wxBitmap
&bmp
);
88 void SetTrayIcon(const wxBitmap
& bmp
);
89 bool IsOk() { return true; }
92 void SetLegacyWMProperties();
94 void OnSizeChange(wxSizeEvent
& event
);
95 void OnPaint(wxPaintEvent
& evt
);
96 void OnMouseEvent(wxMouseEvent
& event
);
97 void OnMenuEvent(wxCommandEvent
& event
);
99 wxTaskBarIcon
*m_icon
;
103 DECLARE_EVENT_TABLE()
106 BEGIN_EVENT_TABLE(wxTaskBarIconArea
, wxTaskBarIconAreaBase
)
107 EVT_SIZE(wxTaskBarIconArea::OnSizeChange
)
108 EVT_MOUSE_EVENTS(wxTaskBarIconArea::OnMouseEvent
)
109 EVT_MENU(wxID_ANY
, wxTaskBarIconArea::OnMenuEvent
)
110 EVT_PAINT(wxTaskBarIconArea::OnPaint
)
113 wxTaskBarIconArea::wxTaskBarIconArea(wxTaskBarIcon
*icon
, const wxBitmap
&bmp
)
114 : wxTaskBarIconAreaBase(), m_icon(icon
), m_bmp(bmp
)
116 // Set initial size to bitmap size (tray manager may and often will
118 SetClientSize(wxSize(bmp
.GetWidth(), bmp
.GetHeight()));
122 if (!IsProtocolSupported())
124 wxLogTrace(wxT("systray"),
125 wxT("using legacy KDE1,2 and GNOME 1.2 methods"));
126 SetLegacyWMProperties();
130 void wxTaskBarIconArea::SetTrayIcon(const wxBitmap
& bmp
)
134 // determine suitable bitmap size:
135 wxSize
winsize(GetClientSize());
136 wxSize
bmpsize(m_bmp
.GetWidth(), m_bmp
.GetHeight());
137 wxSize
iconsize(wxMin(winsize
.x
, bmpsize
.x
), wxMin(winsize
.y
, bmpsize
.y
));
139 // rescale the bitmap to fit into the tray icon window:
140 if (bmpsize
!= iconsize
)
142 wxImage img
= m_bmp
.ConvertToImage();
143 img
.Rescale(iconsize
.x
, iconsize
.y
);
144 m_bmp
= wxBitmap(img
);
150 // if the bitmap is smaller than the window, offset it:
151 if (winsize
!= iconsize
)
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
);
158 // set frame's shape to correct value and redraw:
163 void wxTaskBarIconArea::SetLegacyWMProperties()
166 gtk_widget_realize(m_widget
);
172 Atom _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR
=
173 XInternAtom(GetDisplay(), "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False
);
175 XChangeProperty(GetDisplay(), GetXWindow(this),
176 _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR
,
178 PropModeReplace
, (unsigned char*)data
, 1);
180 // GNOME 1.2 & KDE 1:
181 Atom KWM_DOCKWINDOW
=
182 XInternAtom(GetDisplay(), "KWM_DOCKWINDOW", False
);
184 XChangeProperty(GetDisplay(), GetXWindow(this),
187 PropModeReplace
, (unsigned char*)data
, 1);
190 void wxTaskBarIconArea::OnSizeChange(wxSizeEvent
& WXUNUSED(event
))
192 wxLogTrace(wxT("systray"), wxT("icon size changed to %i x %i"),
193 GetSize().x
, GetSize().y
);
194 // rescale or reposition the icon as needed:
199 void wxTaskBarIconArea::OnPaint(wxPaintEvent
& WXUNUSED(event
))
202 dc
.DrawBitmap(m_bmp
, m_pos
.x
, m_pos
.y
, true);
205 void wxTaskBarIconArea::OnMouseEvent(wxMouseEvent
& event
)
207 wxEventType type
= 0;
208 wxEventType mtype
= event
.GetEventType();
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
;
227 wxTaskBarIconEvent
e(type
, m_icon
);
228 m_icon
->ProcessEvent(e
);
231 void wxTaskBarIconArea::OnMenuEvent(wxCommandEvent
& event
)
233 m_icon
->ProcessEvent(event
);
236 // ----------------------------------------------------------------------------
237 // wxTaskBarIconBase class:
238 // ----------------------------------------------------------------------------
240 bool wxTaskBarIconBase::IsAvailable()
242 return wxTaskBarIconArea::IsProtocolSupported();
245 // ----------------------------------------------------------------------------
246 // wxTaskBarIcon class:
247 // ----------------------------------------------------------------------------
249 IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon
, wxEvtHandler
)
251 wxTaskBarIcon::wxTaskBarIcon() : m_iconWnd(NULL
)
255 wxTaskBarIcon::~wxTaskBarIcon()
259 m_iconWnd
->Disconnect(wxEVT_DESTROY
,
260 wxWindowDestroyEventHandler(wxTaskBarIcon::OnDestroy
), NULL
, this);
265 bool wxTaskBarIcon::IsOk() const
270 bool wxTaskBarIcon::IsIconInstalled() const
272 return m_iconWnd
!= NULL
;
275 // Destroy event from wxTaskBarIconArea
276 void wxTaskBarIcon::OnDestroy(wxWindowDestroyEvent
&)
278 // prevent crash if wxTaskBarIconArea is destroyed by something else,
279 // for example if panel/kicker is killed
283 bool wxTaskBarIcon::SetIcon(const wxIcon
& icon
, const wxString
& tooltip
)
286 bmp
.CopyFromIcon(icon
);
290 m_iconWnd
= new wxTaskBarIconArea(this, bmp
);
291 if (m_iconWnd
->IsOk())
293 m_iconWnd
->Connect(wxEVT_DESTROY
,
294 wxWindowDestroyEventHandler(wxTaskBarIcon::OnDestroy
),
300 m_iconWnd
->Destroy();
307 m_iconWnd
->SetTrayIcon(bmp
);
311 if (!tooltip
.empty())
312 m_iconWnd
->SetToolTip(tooltip
);
314 m_iconWnd
->SetToolTip(NULL
);
316 wxUnusedVar(tooltip
);
321 bool wxTaskBarIcon::RemoveIcon()
325 m_iconWnd
->Destroy();
330 bool wxTaskBarIcon::PopupMenu(wxMenu
*menu
)
334 m_iconWnd
->PopupMenu(menu
);
338 #endif // wxUSE_TASKBARICON