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()
119 #ifdef GDK_WINDOWING_X11
121 g_snprintf(name
, sizeof(name
), "_NET_SYSTEM_TRAY_S%d",
122 gdk_x11_get_default_screen());
123 Atom atom
= gdk_x11_get_xatom_by_name(name
);
125 Window manager
= XGetSelectionOwner(gdk_x11_get_default_xdisplay(), atom
);
127 return manager
!= None
;
132 //-----------------------------------------------------------------------------
134 wxTaskBarIcon::Private::Private(wxTaskBarIcon
* taskBarIcon
)
136 m_taskBarIcon
= taskBarIcon
;
138 m_eggTrayIcon
= NULL
;
144 wxTaskBarIcon::Private::~Private()
147 g_object_unref(m_statusIcon
);
148 else if (m_eggTrayIcon
)
150 g_signal_handlers_disconnect_by_func(m_eggTrayIcon
, (void*)icon_destroy
, this);
151 gtk_widget_destroy(m_eggTrayIcon
);
155 m_win
->PopEventHandler();
160 gtk_object_destroy(GTK_OBJECT(m_tooltips
));
161 g_object_unref(m_tooltips
);
165 void wxTaskBarIcon::Private::SetIcon()
167 #if GTK_CHECK_VERSION(2,10,0)
168 if (gtk_check_version(2,10,0) == NULL
)
171 gtk_status_icon_set_from_pixbuf(m_statusIcon
, m_bitmap
.GetPixbuf());
174 m_statusIcon
= gtk_status_icon_new_from_pixbuf(m_bitmap
.GetPixbuf());
175 g_signal_connect(m_statusIcon
, "activate",
176 G_CALLBACK(icon_activate
), m_taskBarIcon
);
177 g_signal_connect(m_statusIcon
, "popup_menu",
178 G_CALLBACK(status_icon_popup_menu
), m_taskBarIcon
);
187 GtkWidget
* image
= gtk_bin_get_child(GTK_BIN(m_eggTrayIcon
));
188 gtk_image_set_from_pixbuf(GTK_IMAGE(image
), m_bitmap
.GetPixbuf());
192 m_eggTrayIcon
= GTK_WIDGET(egg_tray_icon_new("wxTaskBarIcon"));
193 gtk_widget_add_events(m_eggTrayIcon
, GDK_BUTTON_PRESS_MASK
);
194 g_signal_connect(m_eggTrayIcon
, "size_allocate",
195 G_CALLBACK(icon_size_allocate
), this);
196 g_signal_connect(m_eggTrayIcon
, "destroy",
197 G_CALLBACK(icon_destroy
), this);
198 g_signal_connect(m_eggTrayIcon
, "button_press_event",
199 G_CALLBACK(icon_button_press_event
), m_taskBarIcon
);
200 g_signal_connect(m_eggTrayIcon
, "popup_menu",
201 G_CALLBACK(icon_popup_menu
), m_taskBarIcon
);
202 GtkWidget
* image
= gtk_image_new_from_pixbuf(m_bitmap
.GetPixbuf());
203 gtk_container_add(GTK_CONTAINER(m_eggTrayIcon
), image
);
204 gtk_widget_show_all(m_eggTrayIcon
);
208 const char *tip_text
= NULL
;
209 if (!m_tipText
.empty())
210 tip_text
= m_tipText
.utf8_str();
212 #if GTK_CHECK_VERSION(2,10,0)
215 #if GTK_CHECK_VERSION(2,16,0)
216 if (GTK_CHECK_VERSION(3,0,0) || gtk_check_version(2,16,0) == NULL
)
217 gtk_status_icon_set_tooltip_text(m_statusIcon
, tip_text
);
221 #if !GTK_CHECK_VERSION(3,0,0) && !defined(GTK_DISABLE_DEPRECATED)
222 gtk_status_icon_set_tooltip(m_statusIcon
, tip_text
);
227 #endif // GTK_CHECK_VERSION(2,10,0)
229 #if !GTK_CHECK_VERSION(3,0,0) && !defined(GTK_DISABLE_DEPRECATED)
230 if (tip_text
&& m_tooltips
== NULL
)
232 m_tooltips
= gtk_tooltips_new();
233 g_object_ref(m_tooltips
);
234 gtk_object_sink(GTK_OBJECT(m_tooltips
));
237 gtk_tooltips_set_tip(m_tooltips
, m_eggTrayIcon
, tip_text
, "");
240 #endif // wxUSE_TOOLTIPS
243 void wxTaskBarIcon::Private::size_allocate(int width
, int height
)
246 EggTrayIcon
* icon
= EGG_TRAY_ICON(m_eggTrayIcon
);
247 if (egg_tray_icon_get_orientation(icon
) == GTK_ORIENTATION_VERTICAL
)
252 int w
= m_bitmap
.GetWidth();
253 int h
= m_bitmap
.GetHeight();
254 if (w
> size
|| h
> size
)
256 if (w
> size
) w
= size
;
257 if (h
> size
) h
= size
;
259 gdk_pixbuf_scale_simple(m_bitmap
.GetPixbuf(), w
, h
, GDK_INTERP_BILINEAR
);
260 GtkImage
* image
= GTK_IMAGE(gtk_bin_get_child(GTK_BIN(m_eggTrayIcon
)));
261 gtk_image_set_from_pixbuf(image
, pixbuf
);
262 g_object_unref(pixbuf
);
265 //-----------------------------------------------------------------------------
267 IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon
, wxEvtHandler
)
269 wxTaskBarIcon::wxTaskBarIcon(wxTaskBarIconType
WXUNUSED(iconType
))
271 m_priv
= new Private(this);
274 wxTaskBarIcon::~wxTaskBarIcon()
279 bool wxTaskBarIcon::SetIcon(const wxIcon
& icon
, const wxString
& tooltip
)
281 m_priv
->m_bitmap
= icon
;
282 m_priv
->m_tipText
= tooltip
;
287 bool wxTaskBarIcon::RemoveIcon()
290 m_priv
= new Private(this);
294 bool wxTaskBarIcon::IsIconInstalled() const
296 return m_priv
->m_statusIcon
|| m_priv
->m_eggTrayIcon
;
299 bool wxTaskBarIcon::PopupMenu(wxMenu
* menu
)
302 if (m_priv
->m_win
== NULL
)
304 m_priv
->m_win
= new wxTopLevelWindow(
305 NULL
, wxID_ANY
, wxString(), wxDefaultPosition
, wxDefaultSize
, 0);
306 m_priv
->m_win
->PushEventHandler(this);
308 wxPoint
point(-1, -1);
309 #ifdef __WXUNIVERSAL__
310 point
= wxGetMousePosition();
312 m_priv
->m_win
->PopupMenu(menu
, point
);
313 #endif // wxUSE_MENUS
317 #endif // wxUSE_TASKBARICON