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" 
  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 // ---------------------------------------------------------------------------- 
  52     #if GTK_CHECK_VERSION(2,1,0) 
  53         #include "wx/gtk/taskbarpriv.h" 
  54         #define TASKBAR_ICON_AREA_BASE_INCLUDED 
  58 #ifndef TASKBAR_ICON_AREA_BASE_INCLUDED 
  59     class WXDLLIMPEXP_ADV wxTaskBarIconAreaBase 
: public wxFrame
 
  62         wxTaskBarIconAreaBase() 
  63             : wxFrame(NULL
, wxID_ANY
, _T("systray icon"), 
  64                       wxDefaultPosition
, wxDefaultSize
, 
  65                       wxDEFAULT_FRAME_STYLE 
| wxFRAME_NO_TASKBAR 
| 
  66                       wxSIMPLE_BORDER 
| wxFRAME_SHAPED
) {} 
  68         bool IsProtocolSupported() const { return false; } 
  73 // ---------------------------------------------------------------------------- 
  74 // toolkit dependent methods to set properties on helper window: 
  75 // ---------------------------------------------------------------------------- 
  77 #if defined(__WXGTK__) 
  81     #define GetDisplay()        GDK_DISPLAY() 
  82     #define GetXWindow(wxwin)   GDK_WINDOW_XWINDOW((wxwin)->m_widget->window) 
  83 #elif defined(__WXX11__) || defined(__WXMOTIF__) 
  84     #include "wx/x11/privx.h" 
  85     #define GetDisplay()        ((Display*)wxGlobalDisplay()) 
  86     #define GetXWindow(wxwin)   ((Window)(wxwin)->GetHandle()) 
  88     #error "You must define X11 accessors for this port!" 
  92 // ---------------------------------------------------------------------------- 
  93 // wxTaskBarIconArea is the real window that shows the icon: 
  94 // ---------------------------------------------------------------------------- 
  96 class WXDLLIMPEXP_ADV wxTaskBarIconArea 
: public wxTaskBarIconAreaBase
 
  99     wxTaskBarIconArea(wxTaskBarIcon 
*icon
, const wxBitmap 
&bmp
); 
 100     void SetTrayIcon(const wxBitmap
& bmp
); 
 101     bool IsOk() { return true; } 
 104     void SetLegacyWMProperties(); 
 106     void OnSizeChange(wxSizeEvent
& event
); 
 107     void OnPaint(wxPaintEvent
& evt
); 
 108     void OnMouseEvent(wxMouseEvent
& event
); 
 109     void OnMenuEvent(wxCommandEvent
& event
); 
 111     wxTaskBarIcon 
*m_icon
; 
 115     DECLARE_EVENT_TABLE() 
 118 BEGIN_EVENT_TABLE(wxTaskBarIconArea
, wxTaskBarIconAreaBase
) 
 119     EVT_SIZE(wxTaskBarIconArea::OnSizeChange
) 
 120     EVT_MOUSE_EVENTS(wxTaskBarIconArea::OnMouseEvent
) 
 121     EVT_MENU(-1, wxTaskBarIconArea::OnMenuEvent
) 
 122     EVT_PAINT(wxTaskBarIconArea::OnPaint
) 
 125 wxTaskBarIconArea::wxTaskBarIconArea(wxTaskBarIcon 
*icon
, const wxBitmap 
&bmp
) 
 126     : wxTaskBarIconAreaBase(), m_icon(icon
), m_pos(0,0) 
 128     if (!IsProtocolSupported()) 
 130         wxLogTrace(_T("systray"), 
 131                    _T("using legacy KDE1,2 and GNOME 1.2 methods")); 
 132         SetLegacyWMProperties(); 
 135 #if defined(__WXGTK20__) && defined(TASKBAR_ICON_AREA_BASE_INCLUDED) 
 136     m_invokingWindow 
= icon
; 
 139     // Set initial size to bitmap size (tray manager may and often will 
 141     SetSize(wxSize(bmp
.GetWidth(), bmp
.GetHeight())); 
 146 void wxTaskBarIconArea::SetTrayIcon(const wxBitmap
& bmp
) 
 150     // determine suitable bitmap size: 
 151     wxSize 
winsize(GetSize()); 
 152     wxSize 
bmpsize(m_bmp
.GetWidth(), m_bmp
.GetHeight()); 
 153     wxSize 
iconsize(wxMin(winsize
.x
, bmpsize
.x
), wxMin(winsize
.y
, bmpsize
.y
)); 
 155     // rescale the bitmap to fit into the tray icon window: 
 156     if (bmpsize 
!= iconsize
) 
 158         wxImage img 
= m_bmp
.ConvertToImage(); 
 159         img
.Rescale(iconsize
.x
, iconsize
.y
); 
 160         m_bmp 
= wxBitmap(img
); 
 166     // if the bitmap is smaller than the window, offset it: 
 167     if (winsize 
!= iconsize
) 
 169         m_pos
.x 
= (winsize
.x 
- iconsize
.x
) / 2; 
 170         m_pos
.y 
= (winsize
.y 
- iconsize
.y
) / 2; 
 171         region
.Offset(m_pos
.x
, m_pos
.y
); 
 174     // set frame's shape to correct value and redraw: 
 179 void wxTaskBarIconArea::SetLegacyWMProperties() 
 182     gtk_widget_realize(m_widget
); 
 188     Atom _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR 
= 
 189         XInternAtom(GetDisplay(), "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False
); 
 191     XChangeProperty(GetDisplay(), GetXWindow(this), 
 192                     _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR
, 
 194                     PropModeReplace
, (unsigned char*)data
, 1); 
 196     // GNOME 1.2 & KDE 1: 
 197     Atom KWM_DOCKWINDOW 
= 
 198         XInternAtom(GetDisplay(), "KWM_DOCKWINDOW", False
); 
 200     XChangeProperty(GetDisplay(), GetXWindow(this), 
 203                     PropModeReplace
, (unsigned char*)data
, 1); 
 206 void wxTaskBarIconArea::OnSizeChange(wxSizeEvent
& event
) 
 208     wxLogTrace(_T("systray"), _T("icon size changed to %i x %i"), 
 209                GetSize().x
, GetSize().y
); 
 210     // rescale or reposition the icon as needed: 
 215 void wxTaskBarIconArea::OnPaint(wxPaintEvent
& WXUNUSED(event
)) 
 218     dc
.DrawBitmap(m_bmp
, m_pos
.x
, m_pos
.y
, true); 
 221 void wxTaskBarIconArea::OnMouseEvent(wxMouseEvent
& event
) 
 223     wxEventType type 
= 0; 
 224     wxEventType mtype 
= event
.GetEventType(); 
 226     if (mtype 
== wxEVT_LEFT_DOWN
) 
 227         type 
= wxEVT_TASKBAR_LEFT_DOWN
; 
 228     else if (mtype 
== wxEVT_LEFT_UP
) 
 229         type 
= wxEVT_TASKBAR_LEFT_UP
; 
 230     else if (mtype 
== wxEVT_LEFT_DCLICK
) 
 231         type 
= wxEVT_TASKBAR_LEFT_DCLICK
; 
 232     else if (mtype 
== wxEVT_RIGHT_DOWN
) 
 233         type 
= wxEVT_TASKBAR_RIGHT_DOWN
; 
 234     else if (mtype 
== wxEVT_RIGHT_UP
) 
 235         type 
= wxEVT_TASKBAR_RIGHT_UP
; 
 236     else if (mtype 
== wxEVT_RIGHT_DCLICK
) 
 237         type 
= wxEVT_TASKBAR_RIGHT_DCLICK
; 
 238     else if (mtype 
== wxEVT_MOTION
) 
 239         type 
= wxEVT_TASKBAR_MOVE
; 
 243    wxTaskBarIconEvent 
e(type
, m_icon
); 
 244    m_icon
->ProcessEvent(e
); 
 247 void wxTaskBarIconArea::OnMenuEvent(wxCommandEvent
& event
) 
 249     m_icon
->ProcessEvent(event
); 
 252 // ---------------------------------------------------------------------------- 
 253 // wxTaskBarIcon class: 
 254 // ---------------------------------------------------------------------------- 
 256 IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon
, wxEvtHandler
) 
 258 wxTaskBarIcon::wxTaskBarIcon() : m_iconWnd(NULL
) 
 262 wxTaskBarIcon::~wxTaskBarIcon() 
 268 bool wxTaskBarIcon::IsOk() const 
 273 bool wxTaskBarIcon::IsIconInstalled() const 
 275     return m_iconWnd 
!= NULL
; 
 278 bool wxTaskBarIcon::SetIcon(const wxIcon
& icon
, const wxString
& tooltip
) 
 281     bmp
.CopyFromIcon(icon
); 
 285         m_iconWnd 
= new wxTaskBarIconArea(this, bmp
); 
 286         if (m_iconWnd
->IsOk()) 
 292             m_iconWnd
->Destroy(); 
 299         m_iconWnd
->SetTrayIcon(bmp
); 
 303     if (!tooltip
.empty()) 
 304         m_iconWnd
->SetToolTip(tooltip
); 
 306         m_iconWnd
->SetToolTip(NULL
); 
 311 bool wxTaskBarIcon::RemoveIcon() 
 315     m_iconWnd
->Destroy(); 
 320 bool wxTaskBarIcon::PopupMenu(wxMenu 
*menu
) 
 324     m_iconWnd
->PopupMenu(menu
);