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" 
  24 #include "wx/taskbar.h" 
  29     #include "wx/dcclient.h" 
  30     #include "wx/statbmp.h" 
  32     #include "wx/bitmap.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 // ---------------------------------------------------------------------------- 
  51     #if GTK_CHECK_VERSION(2,1,0) 
  52         #include "wx/gtk/taskbarpriv.h" 
  53         #define TASKBAR_ICON_AREA_BASE_INCLUDED 
  57 #ifndef TASKBAR_ICON_AREA_BASE_INCLUDED 
  58     class WXDLLIMPEXP_ADV wxTaskBarIconAreaBase 
: public wxFrame
 
  61         wxTaskBarIconAreaBase() 
  62             : wxFrame(NULL
, wxID_ANY
, _T("systray icon"), 
  63                       wxDefaultPosition
, wxDefaultSize
, 
  64                       wxDEFAULT_FRAME_STYLE 
| wxFRAME_NO_TASKBAR 
| 
  65                       wxSIMPLE_BORDER 
| wxFRAME_SHAPED
) {} 
  67         bool IsProtocolSupported() const { return false; } 
  72 // ---------------------------------------------------------------------------- 
  73 // toolkit dependent methods to set properties on helper window: 
  74 // ---------------------------------------------------------------------------- 
  76 #if defined(__WXGTK__) 
  80     #define GetDisplay()        GDK_DISPLAY() 
  81     #define GetXWindow(wxwin)   GDK_WINDOW_XWINDOW((wxwin)->m_widget->window) 
  82 #elif defined(__WXX11__) || defined(__WXMOTIF__) 
  83     #include "wx/x11/privx.h" 
  84     #define GetDisplay()        ((Display*)wxGlobalDisplay()) 
  85     #define GetXWindow(wxwin)   ((Window)(wxwin)->GetHandle()) 
  87     #error "You must define X11 accessors for this port!" 
  91 // ---------------------------------------------------------------------------- 
  92 // wxTaskBarIconArea is the real window that shows the icon: 
  93 // ---------------------------------------------------------------------------- 
  95 class WXDLLIMPEXP_ADV wxTaskBarIconArea 
: public wxTaskBarIconAreaBase
 
  98     wxTaskBarIconArea(wxTaskBarIcon 
*icon
, const wxBitmap 
&bmp
); 
  99     void SetTrayIcon(const wxBitmap
& bmp
); 
 100     bool IsOk() { return true; } 
 103     void SetLegacyWMProperties(); 
 105     void OnSizeChange(wxSizeEvent
& event
); 
 106     void OnPaint(wxPaintEvent
& evt
); 
 107     void OnMouseEvent(wxMouseEvent
& event
); 
 108     void OnMenuEvent(wxCommandEvent
& event
); 
 110     wxTaskBarIcon 
*m_icon
; 
 114     DECLARE_EVENT_TABLE() 
 117 BEGIN_EVENT_TABLE(wxTaskBarIconArea
, wxTaskBarIconAreaBase
) 
 118     EVT_SIZE(wxTaskBarIconArea::OnSizeChange
) 
 119     EVT_MOUSE_EVENTS(wxTaskBarIconArea::OnMouseEvent
) 
 120     EVT_MENU(wxID_ANY
, wxTaskBarIconArea::OnMenuEvent
) 
 121     EVT_PAINT(wxTaskBarIconArea::OnPaint
) 
 124 wxTaskBarIconArea::wxTaskBarIconArea(wxTaskBarIcon 
*icon
, const wxBitmap 
&bmp
) 
 125     : wxTaskBarIconAreaBase(), m_icon(icon
), m_pos(0,0) 
 127     if (!IsProtocolSupported()) 
 129         wxLogTrace(_T("systray"), 
 130                    _T("using legacy KDE1,2 and GNOME 1.2 methods")); 
 131         SetLegacyWMProperties(); 
 134 #if defined(__WXGTK20__) && defined(TASKBAR_ICON_AREA_BASE_INCLUDED) 
 135     m_invokingWindow 
= icon
; 
 138     // Set initial size to bitmap size (tray manager may and often will 
 140     SetSize(wxSize(bmp
.GetWidth(), bmp
.GetHeight())); 
 145 void wxTaskBarIconArea::SetTrayIcon(const wxBitmap
& bmp
) 
 149     // determine suitable bitmap size: 
 150     wxSize 
winsize(GetSize()); 
 151     wxSize 
bmpsize(m_bmp
.GetWidth(), m_bmp
.GetHeight()); 
 152     wxSize 
iconsize(wxMin(winsize
.x
, bmpsize
.x
), wxMin(winsize
.y
, bmpsize
.y
)); 
 154     // rescale the bitmap to fit into the tray icon window: 
 155     if (bmpsize 
!= iconsize
) 
 157         wxImage img 
= m_bmp
.ConvertToImage(); 
 158         img
.Rescale(iconsize
.x
, iconsize
.y
); 
 159         m_bmp 
= wxBitmap(img
); 
 165     // if the bitmap is smaller than the window, offset it: 
 166     if (winsize 
!= iconsize
) 
 168         m_pos
.x 
= (winsize
.x 
- iconsize
.x
) / 2; 
 169         m_pos
.y 
= (winsize
.y 
- iconsize
.y
) / 2; 
 170         region
.Offset(m_pos
.x
, m_pos
.y
); 
 173     // set frame's shape to correct value and redraw: 
 178 void wxTaskBarIconArea::SetLegacyWMProperties() 
 181     gtk_widget_realize(m_widget
); 
 187     Atom _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR 
= 
 188         XInternAtom(GetDisplay(), "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False
); 
 190     XChangeProperty(GetDisplay(), GetXWindow(this), 
 191                     _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR
, 
 193                     PropModeReplace
, (unsigned char*)data
, 1); 
 195     // GNOME 1.2 & KDE 1: 
 196     Atom KWM_DOCKWINDOW 
= 
 197         XInternAtom(GetDisplay(), "KWM_DOCKWINDOW", False
); 
 199     XChangeProperty(GetDisplay(), GetXWindow(this), 
 202                     PropModeReplace
, (unsigned char*)data
, 1); 
 205 void wxTaskBarIconArea::OnSizeChange(wxSizeEvent
& WXUNUSED(event
)) 
 207     wxLogTrace(_T("systray"), _T("icon size changed to %i x %i"), 
 208                GetSize().x
, GetSize().y
); 
 209     // rescale or reposition the icon as needed: 
 214 void wxTaskBarIconArea::OnPaint(wxPaintEvent
& WXUNUSED(event
)) 
 217     dc
.DrawBitmap(m_bmp
, m_pos
.x
, m_pos
.y
, true); 
 220 void wxTaskBarIconArea::OnMouseEvent(wxMouseEvent
& event
) 
 222     wxEventType type 
= 0; 
 223     wxEventType mtype 
= event
.GetEventType(); 
 225     if (mtype 
== wxEVT_LEFT_DOWN
) 
 226         type 
= wxEVT_TASKBAR_LEFT_DOWN
; 
 227     else if (mtype 
== wxEVT_LEFT_UP
) 
 228         type 
= wxEVT_TASKBAR_LEFT_UP
; 
 229     else if (mtype 
== wxEVT_LEFT_DCLICK
) 
 230         type 
= wxEVT_TASKBAR_LEFT_DCLICK
; 
 231     else if (mtype 
== wxEVT_RIGHT_DOWN
) 
 232         type 
= wxEVT_TASKBAR_RIGHT_DOWN
; 
 233     else if (mtype 
== wxEVT_RIGHT_UP
) 
 234         type 
= wxEVT_TASKBAR_RIGHT_UP
; 
 235     else if (mtype 
== wxEVT_RIGHT_DCLICK
) 
 236         type 
= wxEVT_TASKBAR_RIGHT_DCLICK
; 
 237     else if (mtype 
== wxEVT_MOTION
) 
 238         type 
= wxEVT_TASKBAR_MOVE
; 
 242    wxTaskBarIconEvent 
e(type
, m_icon
); 
 243    m_icon
->ProcessEvent(e
); 
 246 void wxTaskBarIconArea::OnMenuEvent(wxCommandEvent
& event
) 
 248     m_icon
->ProcessEvent(event
); 
 251 // ---------------------------------------------------------------------------- 
 252 // wxTaskBarIcon class: 
 253 // ---------------------------------------------------------------------------- 
 255 IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon
, wxEvtHandler
) 
 257 wxTaskBarIcon::wxTaskBarIcon() : m_iconWnd(NULL
) 
 261 wxTaskBarIcon::~wxTaskBarIcon() 
 267 bool wxTaskBarIcon::IsOk() const 
 272 bool wxTaskBarIcon::IsIconInstalled() const 
 274     return m_iconWnd 
!= NULL
; 
 277 bool wxTaskBarIcon::SetIcon(const wxIcon
& icon
, const wxString
& tooltip
) 
 280     bmp
.CopyFromIcon(icon
); 
 284         m_iconWnd 
= new wxTaskBarIconArea(this, bmp
); 
 285         if (m_iconWnd
->IsOk()) 
 291             m_iconWnd
->Destroy(); 
 298         m_iconWnd
->SetTrayIcon(bmp
); 
 302     if (!tooltip
.empty()) 
 303         m_iconWnd
->SetToolTip(tooltip
); 
 305         m_iconWnd
->SetToolTip(NULL
); 
 307     wxUnusedVar(tooltip
); 
 312 bool wxTaskBarIcon::RemoveIcon() 
 316     m_iconWnd
->Destroy(); 
 321 bool wxTaskBarIcon::PopupMenu(wxMenu 
*menu
) 
 325     m_iconWnd
->PopupMenu(menu
);