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"
26 #ifdef GDK_WINDOWING_X11
30 #include "eggtrayicon.h"
33 #if !GTK_CHECK_VERSION(2,10,0)
34 typedef struct _GtkStatusIcon GtkStatusIcon
;
37 class wxTaskBarIcon::Private
40 Private(wxTaskBarIcon
* taskBarIcon
);
43 void size_allocate(int width
, int height
);
45 // owning wxTaskBarIcon
46 wxTaskBarIcon
* m_taskBarIcon
;
47 // used when GTK+ >= 2.10
48 GtkStatusIcon
* m_statusIcon
;
54 // used when GTK+ < 2.10
55 GtkWidget
* m_eggTrayIcon
;
56 // for tooltip when GTK+ < 2.10
57 GtkTooltips
* m_tooltips
;
58 // width and height of available space, only used when GTK+ < 2.10
62 //-----------------------------------------------------------------------------
67 icon_size_allocate(GtkWidget
*, GtkAllocation
* alloc
, wxTaskBarIcon::Private
* priv
)
69 priv
->size_allocate(alloc
->width
, alloc
->height
);
73 icon_destroy(GtkWidget
*, wxTaskBarIcon::Private
* priv
)
75 // Icon window destroyed, probably because tray program has died.
76 // Recreate icon so it will appear if tray program is restarted.
77 priv
->m_eggTrayIcon
= NULL
;
83 icon_activate(void*, wxTaskBarIcon
* taskBarIcon
)
85 // activate occurs from single click with GTK+
86 wxTaskBarIconEvent
event(wxEVT_TASKBAR_LEFT_DOWN
, taskBarIcon
);
87 if (!taskBarIcon
->SafelyProcessEvent(event
))
89 // if single click not handled, send double click for compatibility
90 event
.SetEventType(wxEVT_TASKBAR_LEFT_DCLICK
);
91 taskBarIcon
->SafelyProcessEvent(event
);
96 icon_popup_menu(GtkWidget
*, wxTaskBarIcon
* taskBarIcon
)
98 wxTaskBarIconEvent
event(wxEVT_TASKBAR_CLICK
, taskBarIcon
);
99 taskBarIcon
->SafelyProcessEvent(event
);
105 icon_button_press_event(GtkWidget
*, GdkEventButton
* event
, wxTaskBarIcon
* taskBarIcon
)
107 if (event
->type
== GDK_BUTTON_PRESS
)
109 if (event
->button
== 1)
110 icon_activate(NULL
, taskBarIcon
);
111 else if (event
->button
== 3)
112 icon_popup_menu(NULL
, taskBarIcon
);
118 #if GTK_CHECK_VERSION(2,10,0)
120 status_icon_popup_menu(GtkStatusIcon
*, guint
, guint
, wxTaskBarIcon
* taskBarIcon
)
122 icon_popup_menu(NULL
, taskBarIcon
);
126 //-----------------------------------------------------------------------------
128 bool wxTaskBarIconBase::IsAvailable()
130 #ifdef GDK_WINDOWING_X11
132 g_snprintf(name
, sizeof(name
), "_NET_SYSTEM_TRAY_S%d",
133 gdk_x11_get_default_screen());
134 Atom atom
= gdk_x11_get_xatom_by_name(name
);
136 Window manager
= XGetSelectionOwner(gdk_x11_get_default_xdisplay(), atom
);
138 return manager
!= None
;
143 //-----------------------------------------------------------------------------
145 wxTaskBarIcon::Private::Private(wxTaskBarIcon
* taskBarIcon
)
147 m_taskBarIcon
= taskBarIcon
;
151 m_eggTrayIcon
= NULL
;
157 wxTaskBarIcon::Private::~Private()
160 g_object_unref(m_statusIcon
);
162 else if (m_eggTrayIcon
)
164 g_signal_handlers_disconnect_by_func(m_eggTrayIcon
, (void*)icon_destroy
, this);
165 gtk_widget_destroy(m_eggTrayIcon
);
170 m_win
->PopEventHandler();
176 gtk_object_destroy(GTK_OBJECT(m_tooltips
));
177 g_object_unref(m_tooltips
);
182 void wxTaskBarIcon::Private::SetIcon()
184 #if GTK_CHECK_VERSION(2,10,0)
185 if (GTK_CHECK_VERSION(3,0,0) || gtk_check_version(2,10,0) == NULL
)
188 gtk_status_icon_set_from_pixbuf(m_statusIcon
, m_bitmap
.GetPixbuf());
191 m_statusIcon
= gtk_status_icon_new_from_pixbuf(m_bitmap
.GetPixbuf());
192 g_signal_connect(m_statusIcon
, "activate",
193 G_CALLBACK(icon_activate
), m_taskBarIcon
);
194 g_signal_connect(m_statusIcon
, "popup_menu",
195 G_CALLBACK(status_icon_popup_menu
), m_taskBarIcon
);
205 GtkWidget
* image
= gtk_bin_get_child(GTK_BIN(m_eggTrayIcon
));
206 gtk_image_set_from_pixbuf(GTK_IMAGE(image
), m_bitmap
.GetPixbuf());
210 m_eggTrayIcon
= GTK_WIDGET(egg_tray_icon_new("wxTaskBarIcon"));
211 gtk_widget_add_events(m_eggTrayIcon
, GDK_BUTTON_PRESS_MASK
);
212 g_signal_connect(m_eggTrayIcon
, "size_allocate",
213 G_CALLBACK(icon_size_allocate
), this);
214 g_signal_connect(m_eggTrayIcon
, "destroy",
215 G_CALLBACK(icon_destroy
), this);
216 g_signal_connect(m_eggTrayIcon
, "button_press_event",
217 G_CALLBACK(icon_button_press_event
), m_taskBarIcon
);
218 g_signal_connect(m_eggTrayIcon
, "popup_menu",
219 G_CALLBACK(icon_popup_menu
), m_taskBarIcon
);
220 GtkWidget
* image
= gtk_image_new_from_pixbuf(m_bitmap
.GetPixbuf());
221 gtk_container_add(GTK_CONTAINER(m_eggTrayIcon
), image
);
222 gtk_widget_show_all(m_eggTrayIcon
);
227 const char *tip_text
= NULL
;
228 if (!m_tipText
.empty())
229 tip_text
= m_tipText
.utf8_str();
231 #if GTK_CHECK_VERSION(2,10,0)
234 #if GTK_CHECK_VERSION(2,16,0)
235 if (GTK_CHECK_VERSION(3,0,0) || gtk_check_version(2,16,0) == NULL
)
236 gtk_status_icon_set_tooltip_text(m_statusIcon
, tip_text
);
241 gtk_status_icon_set_tooltip(m_statusIcon
, tip_text
);
246 #endif // GTK_CHECK_VERSION(2,10,0)
249 if (tip_text
&& m_tooltips
== NULL
)
251 m_tooltips
= gtk_tooltips_new();
252 g_object_ref(m_tooltips
);
253 gtk_object_sink(GTK_OBJECT(m_tooltips
));
256 gtk_tooltips_set_tip(m_tooltips
, m_eggTrayIcon
, tip_text
, "");
259 #endif // wxUSE_TOOLTIPS
263 void wxTaskBarIcon::Private::size_allocate(int width
, int height
)
266 EggTrayIcon
* icon
= EGG_TRAY_ICON(m_eggTrayIcon
);
267 if (egg_tray_icon_get_orientation(icon
) == GTK_ORIENTATION_VERTICAL
)
272 int w
= m_bitmap
.GetWidth();
273 int h
= m_bitmap
.GetHeight();
274 if (w
> size
|| h
> size
)
276 if (w
> size
) w
= size
;
277 if (h
> size
) h
= size
;
279 gdk_pixbuf_scale_simple(m_bitmap
.GetPixbuf(), w
, h
, GDK_INTERP_BILINEAR
);
280 GtkImage
* image
= GTK_IMAGE(gtk_bin_get_child(GTK_BIN(m_eggTrayIcon
)));
281 gtk_image_set_from_pixbuf(image
, pixbuf
);
282 g_object_unref(pixbuf
);
286 //-----------------------------------------------------------------------------
288 IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon
, wxEvtHandler
)
290 wxTaskBarIcon::wxTaskBarIcon(wxTaskBarIconType
WXUNUSED(iconType
))
292 m_priv
= new Private(this);
295 wxTaskBarIcon::~wxTaskBarIcon()
300 bool wxTaskBarIcon::SetIcon(const wxIcon
& icon
, const wxString
& tooltip
)
302 m_priv
->m_bitmap
= icon
;
303 m_priv
->m_tipText
= tooltip
;
308 bool wxTaskBarIcon::RemoveIcon()
311 m_priv
= new Private(this);
315 bool wxTaskBarIcon::IsIconInstalled() const
318 return m_priv
->m_statusIcon
!= NULL
;
320 return m_priv
->m_statusIcon
|| m_priv
->m_eggTrayIcon
;
324 bool wxTaskBarIcon::PopupMenu(wxMenu
* menu
)
327 if (m_priv
->m_win
== NULL
)
329 m_priv
->m_win
= new wxTopLevelWindow(
330 NULL
, wxID_ANY
, wxString(), wxDefaultPosition
, wxDefaultSize
, 0);
331 m_priv
->m_win
->PushEventHandler(this);
333 wxPoint
point(-1, -1);
334 #ifdef __WXUNIVERSAL__
335 point
= wxGetMousePosition();
337 m_priv
->m_win
->PopupMenu(menu
, point
);
338 #endif // wxUSE_MENUS
342 #endif // wxUSE_TASKBARICON