compilation fix for wxUSE_STL build after latest changes
[wxWidgets.git] / src / gtk / taskbar.cpp
1 /////////////////////////////////////////////////////////////////////////
2 // File: src/gtk/taskbar.cpp
3 // Purpose: wxTaskBarIcon
4 // Author: Vaclav Slavik
5 // Modified by: Paul Cornett
6 // Created: 2004/05/29
7 // RCS-ID: $Id$
8 // Copyright: (c) Vaclav Slavik, 2004
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #if wxUSE_TASKBARICON
16
17 #include "wx/taskbar.h"
18
19 #ifndef WX_PRECOMP
20 #include "wx/toplevel.h"
21 #include "wx/menu.h"
22 #include "wx/icon.h"
23 #endif
24
25 #include "eggtrayicon.h"
26 #include <gtk/gtk.h>
27
28 class wxTaskBarIcon::Private
29 {
30 public:
31 Private(wxTaskBarIcon* taskBarIcon);
32 ~Private();
33 void SetIcon();
34 void size_allocate(int width, int height);
35
36 // owning wxTaskBarIcon
37 wxTaskBarIcon* m_taskBarIcon;
38 // used when GTK+ >= 2.10
39 GtkStatusIcon* m_statusIcon;
40 // used when GTK+ < 2.10
41 GtkWidget* m_eggTrayIcon;
42 // for PopupMenu
43 wxWindow* m_win;
44 // for tooltip when GTK+ < 2.10
45 GtkTooltips* m_tooltips;
46 wxBitmap m_bitmap;
47 wxString m_tipText;
48 // width and height of available space, only used when GTK+ < 2.10
49 int m_size;
50 };
51 //-----------------------------------------------------------------------------
52
53 extern "C" {
54 static void
55 icon_size_allocate(GtkWidget*, GtkAllocation* alloc, wxTaskBarIcon::Private* priv)
56 {
57 priv->size_allocate(alloc->width, alloc->height);
58 }
59
60 static void
61 icon_destroy(GtkWidget*, wxTaskBarIcon::Private* priv)
62 {
63 // Icon window destroyed, probably because tray program has died.
64 // Recreate icon so it will appear if tray program is restarted.
65 priv->m_eggTrayIcon = NULL;
66 priv->SetIcon();
67 }
68
69 static void
70 icon_activate(void*, wxTaskBarIcon* taskBarIcon)
71 {
72 // activate occurs from single click with GTK+
73 wxTaskBarIconEvent event(wxEVT_TASKBAR_LEFT_DOWN, taskBarIcon);
74 if (!taskBarIcon->SafelyProcessEvent(event))
75 {
76 // if single click not handled, send double click for compatibility
77 event.SetEventType(wxEVT_TASKBAR_LEFT_DCLICK);
78 taskBarIcon->SafelyProcessEvent(event);
79 }
80 }
81
82 static gboolean
83 icon_popup_menu(GtkWidget*, wxTaskBarIcon* taskBarIcon)
84 {
85 wxTaskBarIconEvent event(wxEVT_TASKBAR_CLICK, taskBarIcon);
86 taskBarIcon->SafelyProcessEvent(event);
87 return true;
88 }
89
90 static gboolean
91 icon_button_press_event(GtkWidget*, GdkEventButton* event, wxTaskBarIcon* taskBarIcon)
92 {
93 if (event->type == GDK_BUTTON_PRESS)
94 {
95 if (event->button == 1)
96 icon_activate(NULL, taskBarIcon);
97 else if (event->button == 3)
98 icon_popup_menu(NULL, taskBarIcon);
99 }
100 return false;
101 }
102
103 #if GTK_CHECK_VERSION(2,10,0)
104 static void
105 status_icon_popup_menu(GtkStatusIcon*, guint, guint, wxTaskBarIcon* taskBarIcon)
106 {
107 icon_popup_menu(NULL, taskBarIcon);
108 }
109 #endif
110 } // extern "C"
111 //-----------------------------------------------------------------------------
112
113 bool wxTaskBarIconBase::IsAvailable()
114 {
115 char name[32];
116 g_snprintf(name, sizeof(name), "_NET_SYSTEM_TRAY_S%d",
117 gdk_x11_get_default_screen());
118 Atom atom = gdk_x11_get_xatom_by_name(name);
119
120 Window manager = XGetSelectionOwner(gdk_x11_get_default_xdisplay(), atom);
121
122 return manager != None;
123 }
124 //-----------------------------------------------------------------------------
125
126 wxTaskBarIcon::Private::Private(wxTaskBarIcon* taskBarIcon)
127 {
128 m_taskBarIcon = taskBarIcon;
129 m_statusIcon = NULL;
130 m_eggTrayIcon = NULL;
131 m_win = NULL;
132 m_tooltips = NULL;
133 m_size = 0;
134 }
135
136 wxTaskBarIcon::Private::~Private()
137 {
138 if (m_statusIcon)
139 g_object_unref(m_statusIcon);
140 else if (m_eggTrayIcon)
141 {
142 g_signal_handlers_disconnect_by_func(m_eggTrayIcon, (void*)icon_destroy, this);
143 gtk_widget_destroy(m_eggTrayIcon);
144 }
145 if (m_win)
146 {
147 m_win->PopEventHandler();
148 m_win->Destroy();
149 }
150 if (m_tooltips)
151 {
152 gtk_object_destroy(GTK_OBJECT(m_tooltips));
153 g_object_unref(m_tooltips);
154 }
155 }
156
157 void wxTaskBarIcon::Private::SetIcon()
158 {
159 #if GTK_CHECK_VERSION(2,10,0)
160 if (gtk_check_version(2,10,0) == NULL)
161 {
162 if (m_statusIcon)
163 gtk_status_icon_set_from_pixbuf(m_statusIcon, m_bitmap.GetPixbuf());
164 else
165 {
166 m_statusIcon = gtk_status_icon_new_from_pixbuf(m_bitmap.GetPixbuf());
167 g_signal_connect(m_statusIcon, "activate",
168 G_CALLBACK(icon_activate), m_taskBarIcon);
169 g_signal_connect(m_statusIcon, "popup_menu",
170 G_CALLBACK(status_icon_popup_menu), m_taskBarIcon);
171 }
172 }
173 else
174 #endif
175 {
176 m_size = 0;
177 if (m_eggTrayIcon)
178 {
179 GtkWidget* image = GTK_BIN(m_eggTrayIcon)->child;
180 gtk_image_set_from_pixbuf(GTK_IMAGE(image), m_bitmap.GetPixbuf());
181 }
182 else
183 {
184 m_eggTrayIcon = GTK_WIDGET(egg_tray_icon_new("wxTaskBarIcon"));
185 gtk_widget_add_events(m_eggTrayIcon, GDK_BUTTON_PRESS_MASK);
186 g_signal_connect(m_eggTrayIcon, "size_allocate",
187 G_CALLBACK(icon_size_allocate), this);
188 g_signal_connect(m_eggTrayIcon, "destroy",
189 G_CALLBACK(icon_destroy), this);
190 g_signal_connect(m_eggTrayIcon, "button_press_event",
191 G_CALLBACK(icon_button_press_event), m_taskBarIcon);
192 g_signal_connect(m_eggTrayIcon, "popup_menu",
193 G_CALLBACK(icon_popup_menu), m_taskBarIcon);
194 GtkWidget* image = gtk_image_new_from_pixbuf(m_bitmap.GetPixbuf());
195 gtk_container_add(GTK_CONTAINER(m_eggTrayIcon), image);
196 gtk_widget_show_all(m_eggTrayIcon);
197 }
198 }
199 #if wxUSE_TOOLTIPS
200 const char *tip_text = NULL;
201 if (!m_tipText.empty())
202 tip_text = m_tipText.c_str();
203
204 #if GTK_CHECK_VERSION(2,10,0)
205 if (m_statusIcon)
206 gtk_status_icon_set_tooltip(m_statusIcon, tip_text);
207 else
208 #endif
209 {
210 if (tip_text && m_tooltips == NULL)
211 {
212 m_tooltips = gtk_tooltips_new();
213 g_object_ref(m_tooltips);
214 gtk_object_sink(GTK_OBJECT(m_tooltips));
215 }
216 if (m_tooltips)
217 gtk_tooltips_set_tip(m_tooltips, m_eggTrayIcon, tip_text, "");
218 }
219 #endif // wxUSE_TOOLTIPS
220 }
221
222 void wxTaskBarIcon::Private::size_allocate(int width, int height)
223 {
224 int size = height;
225 EggTrayIcon* icon = EGG_TRAY_ICON(m_eggTrayIcon);
226 if (egg_tray_icon_get_orientation(icon) == GTK_ORIENTATION_VERTICAL)
227 size = width;
228 if (m_size == size)
229 return;
230 m_size = size;
231 int w = m_bitmap.GetWidth();
232 int h = m_bitmap.GetHeight();
233 if (w > size || h > size)
234 {
235 if (w > size) w = size;
236 if (h > size) h = size;
237 GdkPixbuf* pixbuf =
238 gdk_pixbuf_scale_simple(m_bitmap.GetPixbuf(), w, h, GDK_INTERP_BILINEAR);
239 GtkImage* image = GTK_IMAGE(GTK_BIN(m_eggTrayIcon)->child);
240 gtk_image_set_from_pixbuf(image, pixbuf);
241 g_object_unref(pixbuf);
242 }
243 }
244 //-----------------------------------------------------------------------------
245
246 IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon, wxEvtHandler)
247
248 wxTaskBarIcon::wxTaskBarIcon()
249 {
250 m_priv = new Private(this);
251 }
252
253 wxTaskBarIcon::~wxTaskBarIcon()
254 {
255 delete m_priv;
256 }
257
258 bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip)
259 {
260 m_priv->m_bitmap = icon;
261 m_priv->m_tipText = tooltip;
262 m_priv->SetIcon();
263 return true;
264 }
265
266 bool wxTaskBarIcon::RemoveIcon()
267 {
268 delete m_priv;
269 m_priv = new Private(this);
270 return true;
271 }
272
273 bool wxTaskBarIcon::IsIconInstalled() const
274 {
275 return m_priv->m_statusIcon || m_priv->m_eggTrayIcon;
276 }
277
278 bool wxTaskBarIcon::PopupMenu(wxMenu* menu)
279 {
280 #if wxUSE_MENUS
281 if (m_priv->m_win == NULL)
282 {
283 m_priv->m_win = new wxTopLevelWindow(
284 NULL, wxID_ANY, wxString(), wxDefaultPosition, wxDefaultSize, 0);
285 m_priv->m_win->PushEventHandler(this);
286 }
287 wxPoint point(-1, -1);
288 #ifdef __WXUNIVERSAL__
289 point = wxGetMousePosition();
290 #endif
291 m_priv->m_win->PopupMenu(menu, point);
292 #endif // wxUSE_MENUS
293 return true;
294 }
295
296 #endif // wxUSE_TASKBARICON