1 ///////////////////////////////////////////////////////////////////////// 
   2 // File:        src/gtk/taskbar.cpp 
   3 // Purpose:     wxTaskBarIcon 
   4 // Author:      Vaclav Slavik 
   5 // Modified by: Paul Cornett 
   8 // Copyright:   (c) Vaclav Slavik, 2004 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h". 
  13 #include "wx/wxprec.h" 
  17 #include "wx/taskbar.h" 
  20     #include "wx/toplevel.h" 
  25 #include "eggtrayicon.h" 
  28 #if !GTK_CHECK_VERSION(2,10,0) 
  29     typedef struct _GtkStatusIcon GtkStatusIcon
; 
  32 class wxTaskBarIcon::Private
 
  35     Private(wxTaskBarIcon
* taskBarIcon
); 
  38     void size_allocate(int width
, int height
); 
  40     // owning wxTaskBarIcon 
  41     wxTaskBarIcon
* m_taskBarIcon
; 
  42     // used when GTK+ >= 2.10 
  43     GtkStatusIcon
* m_statusIcon
; 
  44     // used when GTK+ < 2.10 
  45     GtkWidget
* m_eggTrayIcon
; 
  48     // for tooltip when GTK+ < 2.10 
  49     GtkTooltips
* m_tooltips
; 
  52     // width and height of available space, only used when GTK+ < 2.10 
  55 //----------------------------------------------------------------------------- 
  59 icon_size_allocate(GtkWidget
*, GtkAllocation
* alloc
, wxTaskBarIcon::Private
* priv
) 
  61     priv
->size_allocate(alloc
->width
, alloc
->height
); 
  65 icon_destroy(GtkWidget
*, wxTaskBarIcon::Private
* priv
) 
  67     // Icon window destroyed, probably because tray program has died. 
  68     // Recreate icon so it will appear if tray program is restarted. 
  69     priv
->m_eggTrayIcon 
= NULL
; 
  74 icon_activate(void*, wxTaskBarIcon
* taskBarIcon
) 
  76     // activate occurs from single click with GTK+ 
  77     wxTaskBarIconEvent 
event(wxEVT_TASKBAR_LEFT_DOWN
, taskBarIcon
); 
  78     if (!taskBarIcon
->SafelyProcessEvent(event
)) 
  80         // if single click not handled, send double click for compatibility 
  81         event
.SetEventType(wxEVT_TASKBAR_LEFT_DCLICK
); 
  82         taskBarIcon
->SafelyProcessEvent(event
); 
  87 icon_popup_menu(GtkWidget
*, wxTaskBarIcon
* taskBarIcon
) 
  89     wxTaskBarIconEvent 
event(wxEVT_TASKBAR_CLICK
, taskBarIcon
); 
  90     taskBarIcon
->SafelyProcessEvent(event
); 
  95 icon_button_press_event(GtkWidget
*, GdkEventButton
* event
, wxTaskBarIcon
* taskBarIcon
) 
  97     if (event
->type 
== GDK_BUTTON_PRESS
) 
  99         if (event
->button 
== 1) 
 100             icon_activate(NULL
, taskBarIcon
); 
 101         else if (event
->button 
== 3) 
 102             icon_popup_menu(NULL
, taskBarIcon
); 
 107 #if GTK_CHECK_VERSION(2,10,0) 
 109 status_icon_popup_menu(GtkStatusIcon
*, guint
, guint
, wxTaskBarIcon
* taskBarIcon
) 
 111     icon_popup_menu(NULL
, taskBarIcon
); 
 115 //----------------------------------------------------------------------------- 
 117 bool wxTaskBarIconBase::IsAvailable() 
 120     g_snprintf(name
, sizeof(name
), "_NET_SYSTEM_TRAY_S%d", 
 121         gdk_x11_get_default_screen()); 
 122     Atom atom 
= gdk_x11_get_xatom_by_name(name
); 
 124     Window manager 
= XGetSelectionOwner(gdk_x11_get_default_xdisplay(), atom
); 
 126     return manager 
!= None
; 
 128 //----------------------------------------------------------------------------- 
 130 wxTaskBarIcon::Private::Private(wxTaskBarIcon
* taskBarIcon
) 
 132     m_taskBarIcon 
= taskBarIcon
; 
 134     m_eggTrayIcon 
= NULL
; 
 140 wxTaskBarIcon::Private::~Private() 
 143         g_object_unref(m_statusIcon
); 
 144     else if (m_eggTrayIcon
) 
 146         g_signal_handlers_disconnect_by_func(m_eggTrayIcon
, (void*)icon_destroy
, this); 
 147         gtk_widget_destroy(m_eggTrayIcon
); 
 151         m_win
->PopEventHandler(); 
 156         gtk_object_destroy(GTK_OBJECT(m_tooltips
)); 
 157         g_object_unref(m_tooltips
); 
 161 void wxTaskBarIcon::Private::SetIcon() 
 163 #if GTK_CHECK_VERSION(2,10,0) 
 164     if (gtk_check_version(2,10,0) == NULL
) 
 167             gtk_status_icon_set_from_pixbuf(m_statusIcon
, m_bitmap
.GetPixbuf()); 
 170             m_statusIcon 
= gtk_status_icon_new_from_pixbuf(m_bitmap
.GetPixbuf()); 
 171             g_signal_connect(m_statusIcon
, "activate", 
 172                 G_CALLBACK(icon_activate
), m_taskBarIcon
); 
 173             g_signal_connect(m_statusIcon
, "popup_menu", 
 174                 G_CALLBACK(status_icon_popup_menu
), m_taskBarIcon
); 
 183             GtkWidget
* image 
= GTK_BIN(m_eggTrayIcon
)->child
; 
 184             gtk_image_set_from_pixbuf(GTK_IMAGE(image
), m_bitmap
.GetPixbuf()); 
 188             m_eggTrayIcon 
= GTK_WIDGET(egg_tray_icon_new("wxTaskBarIcon")); 
 189             gtk_widget_add_events(m_eggTrayIcon
, GDK_BUTTON_PRESS_MASK
); 
 190             g_signal_connect(m_eggTrayIcon
, "size_allocate", 
 191                 G_CALLBACK(icon_size_allocate
), this); 
 192             g_signal_connect(m_eggTrayIcon
, "destroy", 
 193                 G_CALLBACK(icon_destroy
), this); 
 194             g_signal_connect(m_eggTrayIcon
, "button_press_event", 
 195                 G_CALLBACK(icon_button_press_event
), m_taskBarIcon
); 
 196             g_signal_connect(m_eggTrayIcon
, "popup_menu", 
 197                 G_CALLBACK(icon_popup_menu
), m_taskBarIcon
); 
 198             GtkWidget
* image 
= gtk_image_new_from_pixbuf(m_bitmap
.GetPixbuf()); 
 199             gtk_container_add(GTK_CONTAINER(m_eggTrayIcon
), image
); 
 200             gtk_widget_show_all(m_eggTrayIcon
); 
 204     const char *tip_text 
= NULL
; 
 205     if (!m_tipText
.empty()) 
 206         tip_text 
= m_tipText
.c_str(); 
 208 #if GTK_CHECK_VERSION(2,10,0) 
 210         gtk_status_icon_set_tooltip(m_statusIcon
, tip_text
); 
 214         if (tip_text 
&& m_tooltips 
== NULL
) 
 216             m_tooltips 
= gtk_tooltips_new(); 
 217             g_object_ref(m_tooltips
); 
 218             gtk_object_sink(GTK_OBJECT(m_tooltips
)); 
 221             gtk_tooltips_set_tip(m_tooltips
, m_eggTrayIcon
, tip_text
, ""); 
 223 #endif // wxUSE_TOOLTIPS 
 226 void wxTaskBarIcon::Private::size_allocate(int width
, int height
) 
 229     EggTrayIcon
* icon 
= EGG_TRAY_ICON(m_eggTrayIcon
); 
 230     if (egg_tray_icon_get_orientation(icon
) == GTK_ORIENTATION_VERTICAL
) 
 235     int w 
= m_bitmap
.GetWidth(); 
 236     int h 
= m_bitmap
.GetHeight(); 
 237     if (w 
> size 
|| h 
> size
) 
 239         if (w 
> size
) w 
= size
; 
 240         if (h 
> size
) h 
= size
; 
 242             gdk_pixbuf_scale_simple(m_bitmap
.GetPixbuf(), w
, h
, GDK_INTERP_BILINEAR
); 
 243         GtkImage
* image 
= GTK_IMAGE(GTK_BIN(m_eggTrayIcon
)->child
); 
 244         gtk_image_set_from_pixbuf(image
, pixbuf
); 
 245         g_object_unref(pixbuf
); 
 248 //----------------------------------------------------------------------------- 
 250 IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon
, wxEvtHandler
) 
 252 wxTaskBarIcon::wxTaskBarIcon() 
 254     m_priv 
= new Private(this); 
 257 wxTaskBarIcon::~wxTaskBarIcon() 
 262 bool wxTaskBarIcon::SetIcon(const wxIcon
& icon
, const wxString
& tooltip
) 
 264     m_priv
->m_bitmap 
= icon
; 
 265     m_priv
->m_tipText 
= tooltip
; 
 270 bool wxTaskBarIcon::RemoveIcon() 
 273     m_priv 
= new Private(this); 
 277 bool wxTaskBarIcon::IsIconInstalled() const 
 279     return m_priv
->m_statusIcon 
|| m_priv
->m_eggTrayIcon
; 
 282 bool wxTaskBarIcon::PopupMenu(wxMenu
* menu
) 
 285     if (m_priv
->m_win 
== NULL
) 
 287         m_priv
->m_win 
= new wxTopLevelWindow( 
 288             NULL
, wxID_ANY
, wxString(), wxDefaultPosition
, wxDefaultSize
, 0); 
 289         m_priv
->m_win
->PushEventHandler(this); 
 291     wxPoint 
point(-1, -1); 
 292 #ifdef __WXUNIVERSAL__ 
 293     point 
= wxGetMousePosition(); 
 295     m_priv
->m_win
->PopupMenu(menu
, point
); 
 296 #endif // wxUSE_MENUS 
 300 #endif // wxUSE_TASKBARICON