1 /////////////////////////////////////////////////////////////////////////
3 // Purpose: wxTaskBarIcon class for common Unix desktops
4 // Author: Vaclav Slavik
8 // Copyright: (c) Vaclav Slavik, 2003
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////
12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation "taskbarx11.h"
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 here.
18 // Freedesktop.org's System Tray specification is implemented in
19 // src/gtk/taskbar.cpp and used from here under wxGTK.
21 // Thanks to Ian Campbell, author of XMMS Status Docklet, for publishing
22 // KDE and GNOME 1.2 methods.
25 // For compilers that support precompilation, includes "wx.h".
26 #include "wx/wxprec.h"
28 #include "wx/taskbar.h"
30 #include "wx/bitmap.h"
31 #include "wx/statbmp.h"
33 #include "wx/dcclient.h"
37 #pragma message disable nosimpint
40 #include <X11/Xatom.h>
42 #pragma message enable nosimpint
45 // ----------------------------------------------------------------------------
46 // base class that implements toolkit-specific method:
47 // ----------------------------------------------------------------------------
50 #include "wx/gtk/taskbarpriv.h"
52 class WXDLLIMPEXP_ADV wxTaskBarIconAreaBase
: public wxFrame
55 wxTaskBarIconAreaBase()
56 : wxFrame(NULL
, wxID_ANY
, _T("systray icon"),
57 wxDefaultPosition
, wxDefaultSize
,
58 wxDEFAULT_FRAME_STYLE
| wxFRAME_NO_TASKBAR
|
59 wxSIMPLE_BORDER
| wxFRAME_SHAPED
) {}
61 bool IsProtocolSupported() const { return false; }
66 // ----------------------------------------------------------------------------
67 // toolkit dependent methods to set properties on helper window:
68 // ----------------------------------------------------------------------------
70 #if defined(__WXGTK__)
74 #define GetDisplay() GDK_DISPLAY()
75 #define GetXWindow(wxwin) GDK_WINDOW_XWINDOW((wxwin)->m_widget->window)
76 #elif defined(__WXX11__) || defined(__WXMOTIF__)
77 #include "wx/x11/privx.h"
78 #define GetDisplay() ((Display*)wxGlobalDisplay())
79 #define GetXWindow(wxwin) ((Window)(wxwin)->GetHandle())
81 #error "You must define X11 accessors for this port!"
85 // ----------------------------------------------------------------------------
86 // wxTaskBarIconArea is the real window that shows the icon:
87 // ----------------------------------------------------------------------------
89 class WXDLLIMPEXP_ADV wxTaskBarIconArea
: public wxTaskBarIconAreaBase
92 wxTaskBarIconArea(wxTaskBarIcon
*icon
, const wxBitmap
&bmp
);
93 void SetTrayIcon(const wxBitmap
& bmp
);
94 bool IsOk() { return true; }
97 void SetLegacyWMProperties();
99 void OnSizeChange(wxSizeEvent
& event
);
100 void OnPaint(wxPaintEvent
& evt
);
101 void OnMouseEvent(wxMouseEvent
& event
);
102 void OnMenuEvent(wxCommandEvent
& event
);
104 wxTaskBarIcon
*m_icon
;
108 DECLARE_EVENT_TABLE()
111 BEGIN_EVENT_TABLE(wxTaskBarIconArea
, wxTaskBarIconAreaBase
)
112 EVT_SIZE(wxTaskBarIconArea::OnSizeChange
)
113 EVT_MOUSE_EVENTS(wxTaskBarIconArea::OnMouseEvent
)
114 EVT_MENU(-1, wxTaskBarIconArea::OnMenuEvent
)
115 EVT_PAINT(wxTaskBarIconArea::OnPaint
)
118 wxTaskBarIconArea::wxTaskBarIconArea(wxTaskBarIcon
*icon
, const wxBitmap
&bmp
)
119 : wxTaskBarIconAreaBase(), m_icon(icon
), m_pos(0,0)
121 if (!IsProtocolSupported())
123 wxLogTrace(_T("systray"),
124 _T("using legacy KDE1,2 and GNOME 1.2 methods"));
125 SetLegacyWMProperties();
128 // Set initial size to bitmap size (tray manager may and often will
130 SetSize(wxSize(bmp
.GetWidth(), bmp
.GetHeight()));
135 void wxTaskBarIconArea::SetTrayIcon(const wxBitmap
& bmp
)
139 // determine suitable bitmap size:
140 wxSize
winsize(GetSize());
141 wxSize
bmpsize(m_bmp
.GetWidth(), m_bmp
.GetHeight());
142 wxSize
iconsize(wxMin(winsize
.x
, bmpsize
.x
), wxMin(winsize
.y
, bmpsize
.y
));
144 // rescale the bitmap to fit into the tray icon window:
145 if (bmpsize
!= iconsize
)
147 wxImage img
= m_bmp
.ConvertToImage();
148 img
.Rescale(iconsize
.x
, iconsize
.y
);
149 m_bmp
= wxBitmap(img
);
152 wxRegion
region(m_bmp
);
154 // if the bitmap is smaller than the window, offset it:
155 if (winsize
!= iconsize
)
157 m_pos
.x
= (winsize
.x
- iconsize
.x
) / 2;
158 m_pos
.y
= (winsize
.y
- iconsize
.y
) / 2;
159 region
.Offset(m_pos
.x
, m_pos
.y
);
162 // set frame's shape to correct value and redraw:
167 void wxTaskBarIconArea::SetLegacyWMProperties()
170 gtk_widget_realize(m_widget
);
176 Atom _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR
=
177 XInternAtom(GetDisplay(), "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False
);
179 XChangeProperty(GetDisplay(), GetXWindow(this),
180 _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR
,
182 PropModeReplace
, (unsigned char*)data
, 1);
184 // GNOME 1.2 & KDE 1:
185 Atom KWM_DOCKWINDOW
=
186 XInternAtom(GetDisplay(), "KWM_DOCKWINDOW", False
);
188 XChangeProperty(GetDisplay(), GetXWindow(this),
191 PropModeReplace
, (unsigned char*)data
, 1);
194 void wxTaskBarIconArea::OnSizeChange(wxSizeEvent
& event
)
196 wxLogTrace(_T("systray"), _T("icon size changed to %i x %i"),
197 GetSize().x
, GetSize().y
);
198 // rescale or reposition the icon as needed:
203 void wxTaskBarIconArea::OnPaint(wxPaintEvent
& WXUNUSED(event
))
206 dc
.DrawBitmap(m_bmp
, m_pos
.x
, m_pos
.y
, true);
209 void wxTaskBarIconArea::OnMouseEvent(wxMouseEvent
& event
)
211 wxEventType type
= 0;
212 wxEventType mtype
= event
.GetEventType();
214 if (mtype
== wxEVT_LEFT_DOWN
)
215 type
= wxEVT_TASKBAR_LEFT_DOWN
;
216 else if (mtype
== wxEVT_LEFT_UP
)
217 type
= wxEVT_TASKBAR_LEFT_UP
;
218 else if (mtype
== wxEVT_LEFT_DCLICK
)
219 type
= wxEVT_TASKBAR_LEFT_DCLICK
;
220 else if (mtype
== wxEVT_RIGHT_DOWN
)
221 type
= wxEVT_TASKBAR_RIGHT_DOWN
;
222 else if (mtype
== wxEVT_RIGHT_UP
)
223 type
= wxEVT_TASKBAR_RIGHT_UP
;
224 else if (mtype
== wxEVT_RIGHT_DCLICK
)
225 type
= wxEVT_TASKBAR_RIGHT_DCLICK
;
226 else if (mtype
== wxEVT_MOTION
)
227 type
= wxEVT_TASKBAR_MOVE
;
231 wxTaskBarIconEvent
e(type
, m_icon
);
232 m_icon
->ProcessEvent(e
);
235 void wxTaskBarIconArea::OnMenuEvent(wxCommandEvent
& event
)
237 m_icon
->ProcessEvent(event
);
240 // ----------------------------------------------------------------------------
241 // wxTaskBarIcon class:
242 // ----------------------------------------------------------------------------
244 IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon
, wxEvtHandler
)
246 wxTaskBarIcon::wxTaskBarIcon() : m_iconWnd(NULL
)
250 wxTaskBarIcon::~wxTaskBarIcon()
256 bool wxTaskBarIcon::IsOk() const
261 bool wxTaskBarIcon::IsIconInstalled() const
263 return m_iconWnd
!= NULL
;
266 bool wxTaskBarIcon::SetIcon(const wxIcon
& icon
, const wxString
& tooltip
)
269 bmp
.CopyFromIcon(icon
);
273 m_iconWnd
= new wxTaskBarIconArea(this, bmp
);
274 if (m_iconWnd
->IsOk())
280 m_iconWnd
->Destroy();
287 m_iconWnd
->SetTrayIcon(bmp
);
291 if (!tooltip
.empty())
292 m_iconWnd
->SetToolTip(tooltip
);
294 m_iconWnd
->SetToolTip(NULL
);
299 bool wxTaskBarIcon::RemoveIcon()
303 m_iconWnd
->Destroy();
308 bool wxTaskBarIcon::PopupMenu(wxMenu
*menu
)
312 wxSize
size(m_iconWnd
->GetClientSize());
313 m_iconWnd
->PopupMenu(menu
, size
.x
/2, size
.y
/2);