]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/taskbar.cpp
Make BOM-detection code in wxConvAuto public.
[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 #if !GTK_CHECK_VERSION(2,10,0)
29 typedef struct _GtkStatusIcon GtkStatusIcon;
30 #endif
31
32 class wxTaskBarIcon::Private
33 {
34 public:
35 Private(wxTaskBarIcon* taskBarIcon);
36 ~Private();
37 void SetIcon();
38 void size_allocate(int width, int height);
39
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;
46 // for PopupMenu
47 wxWindow* m_win;
48 // for tooltip when GTK+ < 2.10
49 GtkTooltips* m_tooltips;
50 wxBitmap m_bitmap;
51 wxString m_tipText;
52 // width and height of available space, only used when GTK+ < 2.10
53 int m_size;
54 };
55 //-----------------------------------------------------------------------------
56
57 extern "C" {
58 static void
59 icon_size_allocate(GtkWidget*, GtkAllocation* alloc, wxTaskBarIcon::Private* priv)
60 {
61 priv->size_allocate(alloc->width, alloc->height);
62 }
63
64 static void
65 icon_destroy(GtkWidget*, wxTaskBarIcon::Private* priv)
66 {
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;
70 priv->SetIcon();
71 }
72
73 static void
74 icon_activate(void*, wxTaskBarIcon* taskBarIcon)
75 {
76 // activate occurs from single click with GTK+
77 wxTaskBarIconEvent event(wxEVT_TASKBAR_LEFT_DOWN, taskBarIcon);
78 if (!taskBarIcon->SafelyProcessEvent(event))
79 {
80 // if single click not handled, send double click for compatibility
81 event.SetEventType(wxEVT_TASKBAR_LEFT_DCLICK);
82 taskBarIcon->SafelyProcessEvent(event);
83 }
84 }
85
86 static gboolean
87 icon_popup_menu(GtkWidget*, wxTaskBarIcon* taskBarIcon)
88 {
89 wxTaskBarIconEvent event(wxEVT_TASKBAR_CLICK, taskBarIcon);
90 taskBarIcon->SafelyProcessEvent(event);
91 return true;
92 }
93
94 static gboolean
95 icon_button_press_event(GtkWidget*, GdkEventButton* event, wxTaskBarIcon* taskBarIcon)
96 {
97 if (event->type == GDK_BUTTON_PRESS)
98 {
99 if (event->button == 1)
100 icon_activate(NULL, taskBarIcon);
101 else if (event->button == 3)
102 icon_popup_menu(NULL, taskBarIcon);
103 }
104 return false;
105 }
106
107 #if GTK_CHECK_VERSION(2,10,0)
108 static void
109 status_icon_popup_menu(GtkStatusIcon*, guint, guint, wxTaskBarIcon* taskBarIcon)
110 {
111 icon_popup_menu(NULL, taskBarIcon);
112 }
113 #endif
114 } // extern "C"
115 //-----------------------------------------------------------------------------
116
117 bool wxTaskBarIconBase::IsAvailable()
118 {
119 char name[32];
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);
123
124 Window manager = XGetSelectionOwner(gdk_x11_get_default_xdisplay(), atom);
125
126 return manager != None;
127 }
128 //-----------------------------------------------------------------------------
129
130 wxTaskBarIcon::Private::Private(wxTaskBarIcon* taskBarIcon)
131 {
132 m_taskBarIcon = taskBarIcon;
133 m_statusIcon = NULL;
134 m_eggTrayIcon = NULL;
135 m_win = NULL;
136 m_tooltips = NULL;
137 m_size = 0;
138 }
139
140 wxTaskBarIcon::Private::~Private()
141 {
142 if (m_statusIcon)
143 g_object_unref(m_statusIcon);
144 else if (m_eggTrayIcon)
145 {
146 g_signal_handlers_disconnect_by_func(m_eggTrayIcon, (void*)icon_destroy, this);
147 gtk_widget_destroy(m_eggTrayIcon);
148 }
149 if (m_win)
150 {
151 m_win->PopEventHandler();
152 m_win->Destroy();
153 }
154 if (m_tooltips)
155 {
156 gtk_object_destroy(GTK_OBJECT(m_tooltips));
157 g_object_unref(m_tooltips);
158 }
159 }
160
161 void wxTaskBarIcon::Private::SetIcon()
162 {
163 #if GTK_CHECK_VERSION(2,10,0)
164 if (gtk_check_version(2,10,0) == NULL)
165 {
166 if (m_statusIcon)
167 gtk_status_icon_set_from_pixbuf(m_statusIcon, m_bitmap.GetPixbuf());
168 else
169 {
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);
175 }
176 }
177 else
178 #endif
179 {
180 m_size = 0;
181 if (m_eggTrayIcon)
182 {
183 GtkWidget* image = gtk_bin_get_child(GTK_BIN(m_eggTrayIcon));
184 gtk_image_set_from_pixbuf(GTK_IMAGE(image), m_bitmap.GetPixbuf());
185 }
186 else
187 {
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);
201 }
202 }
203 #if wxUSE_TOOLTIPS
204 const char *tip_text = NULL;
205 if (!m_tipText.empty())
206 tip_text = m_tipText.c_str();
207
208 #if GTK_CHECK_VERSION(2,10,0)
209 if (m_statusIcon)
210 {
211 #if GTK_CHECK_VERSION(2,16,0)
212 if (GTK_CHECK_VERSION(3,0,0) || gtk_check_version(2,16,0) == NULL)
213 gtk_status_icon_set_tooltip_text(m_statusIcon, tip_text);
214 else
215 #endif
216 {
217 #if !GTK_CHECK_VERSION(3,0,0) && !defined(GTK_DISABLE_DEPRECATED)
218 gtk_status_icon_set_tooltip(m_statusIcon, tip_text);
219 #endif
220 }
221 }
222 else
223 #endif // GTK_CHECK_VERSION(2,10,0)
224 {
225 #if !GTK_CHECK_VERSION(3,0,0) && !defined(GTK_DISABLE_DEPRECATED)
226 if (tip_text && m_tooltips == NULL)
227 {
228 m_tooltips = gtk_tooltips_new();
229 g_object_ref(m_tooltips);
230 gtk_object_sink(GTK_OBJECT(m_tooltips));
231 }
232 if (m_tooltips)
233 gtk_tooltips_set_tip(m_tooltips, m_eggTrayIcon, tip_text, "");
234 #endif
235 }
236 #endif // wxUSE_TOOLTIPS
237 }
238
239 void wxTaskBarIcon::Private::size_allocate(int width, int height)
240 {
241 int size = height;
242 EggTrayIcon* icon = EGG_TRAY_ICON(m_eggTrayIcon);
243 if (egg_tray_icon_get_orientation(icon) == GTK_ORIENTATION_VERTICAL)
244 size = width;
245 if (m_size == size)
246 return;
247 m_size = size;
248 int w = m_bitmap.GetWidth();
249 int h = m_bitmap.GetHeight();
250 if (w > size || h > size)
251 {
252 if (w > size) w = size;
253 if (h > size) h = size;
254 GdkPixbuf* pixbuf =
255 gdk_pixbuf_scale_simple(m_bitmap.GetPixbuf(), w, h, GDK_INTERP_BILINEAR);
256 GtkImage* image = GTK_IMAGE(gtk_bin_get_child(GTK_BIN(m_eggTrayIcon)));
257 gtk_image_set_from_pixbuf(image, pixbuf);
258 g_object_unref(pixbuf);
259 }
260 }
261 //-----------------------------------------------------------------------------
262
263 IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon, wxEvtHandler)
264
265 wxTaskBarIcon::wxTaskBarIcon()
266 {
267 m_priv = new Private(this);
268 }
269
270 wxTaskBarIcon::~wxTaskBarIcon()
271 {
272 delete m_priv;
273 }
274
275 bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip)
276 {
277 m_priv->m_bitmap = icon;
278 m_priv->m_tipText = tooltip;
279 m_priv->SetIcon();
280 return true;
281 }
282
283 bool wxTaskBarIcon::RemoveIcon()
284 {
285 delete m_priv;
286 m_priv = new Private(this);
287 return true;
288 }
289
290 bool wxTaskBarIcon::IsIconInstalled() const
291 {
292 return m_priv->m_statusIcon || m_priv->m_eggTrayIcon;
293 }
294
295 bool wxTaskBarIcon::PopupMenu(wxMenu* menu)
296 {
297 #if wxUSE_MENUS
298 if (m_priv->m_win == NULL)
299 {
300 m_priv->m_win = new wxTopLevelWindow(
301 NULL, wxID_ANY, wxString(), wxDefaultPosition, wxDefaultSize, 0);
302 m_priv->m_win->PushEventHandler(this);
303 }
304 wxPoint point(-1, -1);
305 #ifdef __WXUNIVERSAL__
306 point = wxGetMousePosition();
307 #endif
308 m_priv->m_win->PopupMenu(menu, point);
309 #endif // wxUSE_MENUS
310 return true;
311 }
312
313 #endif // wxUSE_TASKBARICON