1 /////////////////////////////////////////////////////////////////////////
2 // File: src/gtk/taskbar.cpp
3 // Purpose: wxTaskBarIcon
4 // Author: Vaclav Slavik
5 // Modified by: Paul Cornett
7 // Copyright: (c) Vaclav Slavik, 2004
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
16 #include "wx/taskbar.h"
19 #include "wx/toplevel.h"
25 #ifdef GDK_WINDOWING_X11
29 #include "eggtrayicon.h"
32 #if !GTK_CHECK_VERSION(2,10,0)
33 typedef struct _GtkStatusIcon GtkStatusIcon
;
36 class wxTaskBarIcon::Private
39 Private(wxTaskBarIcon
* taskBarIcon
);
42 void size_allocate(int width
, int height
);
44 // owning wxTaskBarIcon
45 wxTaskBarIcon
* m_taskBarIcon
;
46 // used when GTK+ >= 2.10
47 GtkStatusIcon
* m_statusIcon
;
53 // used when GTK+ < 2.10
54 GtkWidget
* m_eggTrayIcon
;
55 // for tooltip when GTK+ < 2.10
56 GtkTooltips
* m_tooltips
;
57 // width and height of available space, only used when GTK+ < 2.10
61 //-----------------------------------------------------------------------------
66 icon_size_allocate(GtkWidget
*, GtkAllocation
* alloc
, wxTaskBarIcon::Private
* priv
)
68 priv
->size_allocate(alloc
->width
, alloc
->height
);
72 icon_destroy(GtkWidget
*, wxTaskBarIcon::Private
* priv
)
74 // Icon window destroyed, probably because tray program has died.
75 // Recreate icon so it will appear if tray program is restarted.
76 priv
->m_eggTrayIcon
= NULL
;
82 icon_activate(void*, wxTaskBarIcon
* taskBarIcon
)
84 // activate occurs from single click with GTK+
85 wxTaskBarIconEvent
event(wxEVT_TASKBAR_LEFT_DOWN
, taskBarIcon
);
86 if (!taskBarIcon
->SafelyProcessEvent(event
))
88 // if single click not handled, send double click for compatibility
89 event
.SetEventType(wxEVT_TASKBAR_LEFT_DCLICK
);
90 taskBarIcon
->SafelyProcessEvent(event
);
95 icon_popup_menu(GtkWidget
*, wxTaskBarIcon
* taskBarIcon
)
97 wxTaskBarIconEvent
event(wxEVT_TASKBAR_CLICK
, taskBarIcon
);
98 taskBarIcon
->SafelyProcessEvent(event
);
104 icon_button_press_event(GtkWidget
*, GdkEventButton
* event
, wxTaskBarIcon
* taskBarIcon
)
106 if (event
->type
== GDK_BUTTON_PRESS
)
108 if (event
->button
== 1)
109 icon_activate(NULL
, taskBarIcon
);
110 else if (event
->button
== 3)
111 icon_popup_menu(NULL
, taskBarIcon
);
117 #if GTK_CHECK_VERSION(2,10,0)
119 status_icon_popup_menu(GtkStatusIcon
*, guint
, guint
, wxTaskBarIcon
* taskBarIcon
)
121 icon_popup_menu(NULL
, taskBarIcon
);
125 //-----------------------------------------------------------------------------
127 bool wxTaskBarIconBase::IsAvailable()
129 #ifdef GDK_WINDOWING_X11
131 g_snprintf(name
, sizeof(name
), "_NET_SYSTEM_TRAY_S%d",
132 gdk_x11_get_default_screen());
133 Atom atom
= gdk_x11_get_xatom_by_name(name
);
135 Window manager
= XGetSelectionOwner(gdk_x11_get_default_xdisplay(), atom
);
137 return manager
!= None
;
142 //-----------------------------------------------------------------------------
144 wxTaskBarIcon::Private::Private(wxTaskBarIcon
* taskBarIcon
)
146 m_taskBarIcon
= taskBarIcon
;
150 m_eggTrayIcon
= NULL
;
156 wxTaskBarIcon::Private::~Private()
159 g_object_unref(m_statusIcon
);
161 else if (m_eggTrayIcon
)
163 g_signal_handlers_disconnect_by_func(m_eggTrayIcon
, (void*)icon_destroy
, this);
164 gtk_widget_destroy(m_eggTrayIcon
);
169 m_win
->PopEventHandler();
175 gtk_object_destroy(GTK_OBJECT(m_tooltips
));
176 g_object_unref(m_tooltips
);
181 void wxTaskBarIcon::Private::SetIcon()
183 #if GTK_CHECK_VERSION(2,10,0)
184 if (GTK_CHECK_VERSION(3,0,0) || gtk_check_version(2,10,0) == NULL
)
187 gtk_status_icon_set_from_pixbuf(m_statusIcon
, m_bitmap
.GetPixbuf());
190 m_statusIcon
= gtk_status_icon_new_from_pixbuf(m_bitmap
.GetPixbuf());
191 g_signal_connect(m_statusIcon
, "activate",
192 G_CALLBACK(icon_activate
), m_taskBarIcon
);
193 g_signal_connect(m_statusIcon
, "popup_menu",
194 G_CALLBACK(status_icon_popup_menu
), m_taskBarIcon
);
204 GtkWidget
* image
= gtk_bin_get_child(GTK_BIN(m_eggTrayIcon
));
205 gtk_image_set_from_pixbuf(GTK_IMAGE(image
), m_bitmap
.GetPixbuf());
209 m_eggTrayIcon
= GTK_WIDGET(egg_tray_icon_new("wxTaskBarIcon"));
210 gtk_widget_add_events(m_eggTrayIcon
, GDK_BUTTON_PRESS_MASK
);
211 g_signal_connect(m_eggTrayIcon
, "size_allocate",
212 G_CALLBACK(icon_size_allocate
), this);
213 g_signal_connect(m_eggTrayIcon
, "destroy",
214 G_CALLBACK(icon_destroy
), this);
215 g_signal_connect(m_eggTrayIcon
, "button_press_event",
216 G_CALLBACK(icon_button_press_event
), m_taskBarIcon
);
217 g_signal_connect(m_eggTrayIcon
, "popup_menu",
218 G_CALLBACK(icon_popup_menu
), m_taskBarIcon
);
219 GtkWidget
* image
= gtk_image_new_from_pixbuf(m_bitmap
.GetPixbuf());
220 gtk_container_add(GTK_CONTAINER(m_eggTrayIcon
), image
);
221 gtk_widget_show_all(m_eggTrayIcon
);
226 const char *tip_text
= NULL
;
227 if (!m_tipText
.empty())
228 tip_text
= m_tipText
.utf8_str();
230 #if GTK_CHECK_VERSION(2,10,0)
233 #if GTK_CHECK_VERSION(2,16,0)
234 if (GTK_CHECK_VERSION(3,0,0) || gtk_check_version(2,16,0) == NULL
)
235 gtk_status_icon_set_tooltip_text(m_statusIcon
, tip_text
);
240 gtk_status_icon_set_tooltip(m_statusIcon
, tip_text
);
245 #endif // GTK_CHECK_VERSION(2,10,0)
248 if (tip_text
&& m_tooltips
== NULL
)
250 m_tooltips
= gtk_tooltips_new();
251 g_object_ref(m_tooltips
);
252 gtk_object_sink(GTK_OBJECT(m_tooltips
));
255 gtk_tooltips_set_tip(m_tooltips
, m_eggTrayIcon
, tip_text
, "");
258 #endif // wxUSE_TOOLTIPS
262 void wxTaskBarIcon::Private::size_allocate(int width
, int height
)
265 EggTrayIcon
* icon
= EGG_TRAY_ICON(m_eggTrayIcon
);
266 if (egg_tray_icon_get_orientation(icon
) == GTK_ORIENTATION_VERTICAL
)
271 int w
= m_bitmap
.GetWidth();
272 int h
= m_bitmap
.GetHeight();
273 if (w
> size
|| h
> size
)
275 if (w
> size
) w
= size
;
276 if (h
> size
) h
= size
;
278 gdk_pixbuf_scale_simple(m_bitmap
.GetPixbuf(), w
, h
, GDK_INTERP_BILINEAR
);
279 GtkImage
* image
= GTK_IMAGE(gtk_bin_get_child(GTK_BIN(m_eggTrayIcon
)));
280 gtk_image_set_from_pixbuf(image
, pixbuf
);
281 g_object_unref(pixbuf
);
285 //-----------------------------------------------------------------------------
287 IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon
, wxEvtHandler
)
289 wxTaskBarIcon::wxTaskBarIcon(wxTaskBarIconType
WXUNUSED(iconType
))
291 m_priv
= new Private(this);
294 wxTaskBarIcon::~wxTaskBarIcon()
299 bool wxTaskBarIcon::SetIcon(const wxIcon
& icon
, const wxString
& tooltip
)
301 m_priv
->m_bitmap
= icon
;
302 m_priv
->m_tipText
= tooltip
;
307 bool wxTaskBarIcon::RemoveIcon()
310 m_priv
= new Private(this);
314 bool wxTaskBarIcon::IsIconInstalled() const
317 return m_priv
->m_statusIcon
!= NULL
;
319 return m_priv
->m_statusIcon
|| m_priv
->m_eggTrayIcon
;
323 bool wxTaskBarIcon::PopupMenu(wxMenu
* menu
)
326 if (m_priv
->m_win
== NULL
)
328 m_priv
->m_win
= new wxTopLevelWindow(
329 NULL
, wxID_ANY
, wxString(), wxDefaultPosition
, wxDefaultSize
, 0);
330 m_priv
->m_win
->PushEventHandler(this);
332 wxPoint
point(-1, -1);
333 #ifdef __WXUNIVERSAL__
334 point
= wxGetMousePosition();
336 m_priv
->m_win
->PopupMenu(menu
, point
);
337 #endif // wxUSE_MENUS
341 #endif // wxUSE_TASKBARICON