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 #if wxUSE_TASKBARICON && !defined(__WXGTK20__) 
  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 // ---------------------------------------------------------------------------- 
  51     class WXDLLIMPEXP_ADV wxTaskBarIconAreaBase 
: public wxFrame
 
  54         wxTaskBarIconAreaBase() 
  55             : wxFrame(NULL
, wxID_ANY
, wxT("systray icon"), 
  56                       wxDefaultPosition
, wxDefaultSize
, 
  57                       wxDEFAULT_FRAME_STYLE 
| wxFRAME_NO_TASKBAR 
| 
  58                       wxSIMPLE_BORDER 
| wxFRAME_SHAPED
) {} 
  60         static bool IsProtocolSupported() { return false; } 
  63 // ---------------------------------------------------------------------------- 
  64 // toolkit dependent methods to set properties on helper window: 
  65 // ---------------------------------------------------------------------------- 
  67 #if defined(__WXGTK__) 
  70     #define GetDisplay()        GDK_DISPLAY() 
  71     #define GetXWindow(wxwin)   GDK_WINDOW_XWINDOW((wxwin)->m_widget->window) 
  72 #elif defined(__WXX11__) || defined(__WXMOTIF__) 
  73     #include "wx/x11/privx.h" 
  74     #define GetDisplay()        ((Display*)wxGlobalDisplay()) 
  75     #define GetXWindow(wxwin)   ((Window)(wxwin)->GetHandle()) 
  77     #error "You must define X11 accessors for this port!" 
  81 // ---------------------------------------------------------------------------- 
  82 // wxTaskBarIconArea is the real window that shows the icon: 
  83 // ---------------------------------------------------------------------------- 
  85 class WXDLLIMPEXP_ADV wxTaskBarIconArea 
: public wxTaskBarIconAreaBase
 
  88     wxTaskBarIconArea(wxTaskBarIcon 
*icon
, const wxBitmap 
&bmp
); 
  89     void SetTrayIcon(const wxBitmap
& bmp
); 
  90     bool IsOk() { return true; } 
  93     void SetLegacyWMProperties(); 
  95     void OnSizeChange(wxSizeEvent
& event
); 
  96     void OnPaint(wxPaintEvent
& evt
); 
  97     void OnMouseEvent(wxMouseEvent
& event
); 
  98     void OnMenuEvent(wxCommandEvent
& event
); 
 100     wxTaskBarIcon 
*m_icon
; 
 104     DECLARE_EVENT_TABLE() 
 107 BEGIN_EVENT_TABLE(wxTaskBarIconArea
, wxTaskBarIconAreaBase
) 
 108     EVT_SIZE(wxTaskBarIconArea::OnSizeChange
) 
 109     EVT_MOUSE_EVENTS(wxTaskBarIconArea::OnMouseEvent
) 
 110     EVT_MENU(wxID_ANY
, wxTaskBarIconArea::OnMenuEvent
) 
 111     EVT_PAINT(wxTaskBarIconArea::OnPaint
) 
 114 wxTaskBarIconArea::wxTaskBarIconArea(wxTaskBarIcon 
*icon
, const wxBitmap 
&bmp
) 
 115     : wxTaskBarIconAreaBase(), m_icon(icon
), m_bmp(bmp
) 
 117     // Set initial size to bitmap size (tray manager may and often will 
 119     SetClientSize(wxSize(bmp
.GetWidth(), bmp
.GetHeight())); 
 123     if (!IsProtocolSupported()) 
 125         wxLogTrace(wxT("systray"), 
 126                    wxT("using legacy KDE1,2 and GNOME 1.2 methods")); 
 127         SetLegacyWMProperties(); 
 131 void wxTaskBarIconArea::SetTrayIcon(const wxBitmap
& bmp
) 
 135     // determine suitable bitmap size: 
 136     wxSize 
winsize(GetClientSize()); 
 137     wxSize 
bmpsize(m_bmp
.GetWidth(), m_bmp
.GetHeight()); 
 138     wxSize 
iconsize(wxMin(winsize
.x
, bmpsize
.x
), wxMin(winsize
.y
, bmpsize
.y
)); 
 140     // rescale the bitmap to fit into the tray icon window: 
 141     if (bmpsize 
!= iconsize
) 
 143         wxImage img 
= m_bmp
.ConvertToImage(); 
 144         img
.Rescale(iconsize
.x
, iconsize
.y
); 
 145         m_bmp 
= wxBitmap(img
); 
 151     // if the bitmap is smaller than the window, offset it: 
 152     if (winsize 
!= iconsize
) 
 154         m_pos
.x 
= (winsize
.x 
- iconsize
.x
) / 2; 
 155         m_pos
.y 
= (winsize
.y 
- iconsize
.y
) / 2; 
 156         region
.Offset(m_pos
.x
, m_pos
.y
); 
 159     // set frame's shape to correct value and redraw: 
 164 void wxTaskBarIconArea::SetLegacyWMProperties() 
 167     gtk_widget_realize(m_widget
); 
 173     Atom _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR 
= 
 174         XInternAtom(GetDisplay(), "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False
); 
 176     XChangeProperty(GetDisplay(), GetXWindow(this), 
 177                     _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR
, 
 179                     PropModeReplace
, (unsigned char*)data
, 1); 
 181     // GNOME 1.2 & KDE 1: 
 182     Atom KWM_DOCKWINDOW 
= 
 183         XInternAtom(GetDisplay(), "KWM_DOCKWINDOW", False
); 
 185     XChangeProperty(GetDisplay(), GetXWindow(this), 
 188                     PropModeReplace
, (unsigned char*)data
, 1); 
 191 void wxTaskBarIconArea::OnSizeChange(wxSizeEvent
& WXUNUSED(event
)) 
 193     wxLogTrace(wxT("systray"), wxT("icon size changed to %i x %i"), 
 194                GetSize().x
, GetSize().y
); 
 195     // rescale or reposition the icon as needed: 
 200 void wxTaskBarIconArea::OnPaint(wxPaintEvent
& WXUNUSED(event
)) 
 203     dc
.DrawBitmap(m_bmp
, m_pos
.x
, m_pos
.y
, true); 
 206 void wxTaskBarIconArea::OnMouseEvent(wxMouseEvent
& event
) 
 208     wxEventType type 
= 0; 
 209     wxEventType mtype 
= event
.GetEventType(); 
 211     if (mtype 
== wxEVT_LEFT_DOWN
) 
 212         type 
= wxEVT_TASKBAR_LEFT_DOWN
; 
 213     else if (mtype 
== wxEVT_LEFT_UP
) 
 214         type 
= wxEVT_TASKBAR_LEFT_UP
; 
 215     else if (mtype 
== wxEVT_LEFT_DCLICK
) 
 216         type 
= wxEVT_TASKBAR_LEFT_DCLICK
; 
 217     else if (mtype 
== wxEVT_RIGHT_DOWN
) 
 218         type 
= wxEVT_TASKBAR_RIGHT_DOWN
; 
 219     else if (mtype 
== wxEVT_RIGHT_UP
) 
 220         type 
= wxEVT_TASKBAR_RIGHT_UP
; 
 221     else if (mtype 
== wxEVT_RIGHT_DCLICK
) 
 222         type 
= wxEVT_TASKBAR_RIGHT_DCLICK
; 
 223     else if (mtype 
== wxEVT_MOTION
) 
 224         type 
= wxEVT_TASKBAR_MOVE
; 
 228    wxTaskBarIconEvent 
e(type
, m_icon
); 
 229    m_icon
->ProcessEvent(e
); 
 232 void wxTaskBarIconArea::OnMenuEvent(wxCommandEvent
& event
) 
 234     m_icon
->ProcessEvent(event
); 
 237 // ---------------------------------------------------------------------------- 
 238 // wxTaskBarIconBase class: 
 239 // ---------------------------------------------------------------------------- 
 241 bool wxTaskBarIconBase::IsAvailable() 
 243     return wxTaskBarIconArea::IsProtocolSupported(); 
 246 // ---------------------------------------------------------------------------- 
 247 // wxTaskBarIcon class: 
 248 // ---------------------------------------------------------------------------- 
 250 IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon
, wxEvtHandler
) 
 252 wxTaskBarIcon::wxTaskBarIcon() : m_iconWnd(NULL
) 
 256 wxTaskBarIcon::~wxTaskBarIcon() 
 260         m_iconWnd
->Disconnect(wxEVT_DESTROY
, 
 261             wxWindowDestroyEventHandler(wxTaskBarIcon::OnDestroy
), NULL
, this); 
 266 bool wxTaskBarIcon::IsOk() const 
 271 bool wxTaskBarIcon::IsIconInstalled() const 
 273     return m_iconWnd 
!= NULL
; 
 276 // Destroy event from wxTaskBarIconArea 
 277 void wxTaskBarIcon::OnDestroy(wxWindowDestroyEvent
&) 
 279     // prevent crash if wxTaskBarIconArea is destroyed by something else, 
 280     // for example if panel/kicker is killed 
 284 bool wxTaskBarIcon::SetIcon(const wxIcon
& icon
, const wxString
& tooltip
) 
 287     bmp
.CopyFromIcon(icon
); 
 291         m_iconWnd 
= new wxTaskBarIconArea(this, bmp
); 
 292         if (m_iconWnd
->IsOk()) 
 294             m_iconWnd
->Connect(wxEVT_DESTROY
, 
 295                 wxWindowDestroyEventHandler(wxTaskBarIcon::OnDestroy
), 
 301             m_iconWnd
->Destroy(); 
 308         m_iconWnd
->SetTrayIcon(bmp
); 
 312     if (!tooltip
.empty()) 
 313         m_iconWnd
->SetToolTip(tooltip
); 
 315         m_iconWnd
->SetToolTip(NULL
); 
 317     wxUnusedVar(tooltip
); 
 322 bool wxTaskBarIcon::RemoveIcon() 
 326     m_iconWnd
->Destroy(); 
 331 bool wxTaskBarIcon::PopupMenu(wxMenu 
*menu
) 
 335     m_iconWnd
->PopupMenu(menu
); 
 339 #endif // wxUSE_TASKBARICON