]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/gtk/taskbar.cpp
new file added
[wxWidgets.git] / src / gtk / taskbar.cpp
... / ...
CommitLineData
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 <gtk/gtk.h>
26#ifdef GDK_WINDOWING_X11
27 #include <gdk/gdkx.h>
28#endif
29#ifndef __WXGTK3__
30 #include "eggtrayicon.h"
31#endif
32
33#if !GTK_CHECK_VERSION(2,10,0)
34 typedef struct _GtkStatusIcon GtkStatusIcon;
35#endif
36
37class wxTaskBarIcon::Private
38{
39public:
40 Private(wxTaskBarIcon* taskBarIcon);
41 ~Private();
42 void SetIcon();
43 void size_allocate(int width, int height);
44
45 // owning wxTaskBarIcon
46 wxTaskBarIcon* m_taskBarIcon;
47 // used when GTK+ >= 2.10
48 GtkStatusIcon* m_statusIcon;
49 // for PopupMenu
50 wxWindow* m_win;
51 wxBitmap m_bitmap;
52 wxString m_tipText;
53#ifndef __WXGTK3__
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
59 int m_size;
60#endif
61};
62//-----------------------------------------------------------------------------
63
64extern "C" {
65#ifndef __WXGTK3__
66static void
67icon_size_allocate(GtkWidget*, GtkAllocation* alloc, wxTaskBarIcon::Private* priv)
68{
69 priv->size_allocate(alloc->width, alloc->height);
70}
71
72static void
73icon_destroy(GtkWidget*, wxTaskBarIcon::Private* priv)
74{
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;
78 priv->SetIcon();
79}
80#endif
81
82static void
83icon_activate(void*, wxTaskBarIcon* taskBarIcon)
84{
85 // activate occurs from single click with GTK+
86 wxTaskBarIconEvent event(wxEVT_TASKBAR_LEFT_DOWN, taskBarIcon);
87 if (!taskBarIcon->SafelyProcessEvent(event))
88 {
89 // if single click not handled, send double click for compatibility
90 event.SetEventType(wxEVT_TASKBAR_LEFT_DCLICK);
91 taskBarIcon->SafelyProcessEvent(event);
92 }
93}
94
95static gboolean
96icon_popup_menu(GtkWidget*, wxTaskBarIcon* taskBarIcon)
97{
98 wxTaskBarIconEvent event(wxEVT_TASKBAR_CLICK, taskBarIcon);
99 taskBarIcon->SafelyProcessEvent(event);
100 return true;
101}
102
103#ifndef __WXGTK3__
104static gboolean
105icon_button_press_event(GtkWidget*, GdkEventButton* event, wxTaskBarIcon* taskBarIcon)
106{
107 if (event->type == GDK_BUTTON_PRESS)
108 {
109 if (event->button == 1)
110 icon_activate(NULL, taskBarIcon);
111 else if (event->button == 3)
112 icon_popup_menu(NULL, taskBarIcon);
113 }
114 return false;
115}
116#endif
117
118#if GTK_CHECK_VERSION(2,10,0)
119static void
120status_icon_popup_menu(GtkStatusIcon*, guint, guint, wxTaskBarIcon* taskBarIcon)
121{
122 icon_popup_menu(NULL, taskBarIcon);
123}
124#endif
125} // extern "C"
126//-----------------------------------------------------------------------------
127
128bool wxTaskBarIconBase::IsAvailable()
129{
130#ifdef GDK_WINDOWING_X11
131 char name[32];
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);
135
136 Window manager = XGetSelectionOwner(gdk_x11_get_default_xdisplay(), atom);
137
138 return manager != None;
139#else
140 return true;
141#endif
142}
143//-----------------------------------------------------------------------------
144
145wxTaskBarIcon::Private::Private(wxTaskBarIcon* taskBarIcon)
146{
147 m_taskBarIcon = taskBarIcon;
148 m_statusIcon = NULL;
149 m_win = NULL;
150#ifndef __WXGTK3__
151 m_eggTrayIcon = NULL;
152 m_tooltips = NULL;
153 m_size = 0;
154#endif
155}
156
157wxTaskBarIcon::Private::~Private()
158{
159 if (m_statusIcon)
160 g_object_unref(m_statusIcon);
161#ifndef __WXGTK3__
162 else if (m_eggTrayIcon)
163 {
164 g_signal_handlers_disconnect_by_func(m_eggTrayIcon, (void*)icon_destroy, this);
165 gtk_widget_destroy(m_eggTrayIcon);
166 }
167#endif
168 if (m_win)
169 {
170 m_win->PopEventHandler();
171 m_win->Destroy();
172 }
173#ifndef __WXGTK3__
174 if (m_tooltips)
175 {
176 gtk_object_destroy(GTK_OBJECT(m_tooltips));
177 g_object_unref(m_tooltips);
178 }
179#endif
180}
181
182void wxTaskBarIcon::Private::SetIcon()
183{
184#if GTK_CHECK_VERSION(2,10,0)
185 if (GTK_CHECK_VERSION(3,0,0) || gtk_check_version(2,10,0) == NULL)
186 {
187 if (m_statusIcon)
188 gtk_status_icon_set_from_pixbuf(m_statusIcon, m_bitmap.GetPixbuf());
189 else
190 {
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);
196 }
197 }
198 else
199#endif
200 {
201#ifndef __WXGTK3__
202 m_size = 0;
203 if (m_eggTrayIcon)
204 {
205 GtkWidget* image = gtk_bin_get_child(GTK_BIN(m_eggTrayIcon));
206 gtk_image_set_from_pixbuf(GTK_IMAGE(image), m_bitmap.GetPixbuf());
207 }
208 else
209 {
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);
223 }
224#endif
225 }
226#if wxUSE_TOOLTIPS
227 const char *tip_text = NULL;
228 if (!m_tipText.empty())
229 tip_text = m_tipText.utf8_str();
230
231#if GTK_CHECK_VERSION(2,10,0)
232 if (m_statusIcon)
233 {
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);
237 else
238#endif
239 {
240#ifndef __WXGTK3__
241 gtk_status_icon_set_tooltip(m_statusIcon, tip_text);
242#endif
243 }
244 }
245 else
246#endif // GTK_CHECK_VERSION(2,10,0)
247 {
248#ifndef __WXGTK3__
249 if (tip_text && m_tooltips == NULL)
250 {
251 m_tooltips = gtk_tooltips_new();
252 g_object_ref(m_tooltips);
253 gtk_object_sink(GTK_OBJECT(m_tooltips));
254 }
255 if (m_tooltips)
256 gtk_tooltips_set_tip(m_tooltips, m_eggTrayIcon, tip_text, "");
257#endif
258 }
259#endif // wxUSE_TOOLTIPS
260}
261
262#ifndef __WXGTK3__
263void wxTaskBarIcon::Private::size_allocate(int width, int height)
264{
265 int size = height;
266 EggTrayIcon* icon = EGG_TRAY_ICON(m_eggTrayIcon);
267 if (egg_tray_icon_get_orientation(icon) == GTK_ORIENTATION_VERTICAL)
268 size = width;
269 if (m_size == size)
270 return;
271 m_size = size;
272 int w = m_bitmap.GetWidth();
273 int h = m_bitmap.GetHeight();
274 if (w > size || h > size)
275 {
276 if (w > size) w = size;
277 if (h > size) h = size;
278 GdkPixbuf* pixbuf =
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);
283 }
284}
285#endif
286//-----------------------------------------------------------------------------
287
288IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon, wxEvtHandler)
289
290wxTaskBarIcon::wxTaskBarIcon(wxTaskBarIconType WXUNUSED(iconType))
291{
292 m_priv = new Private(this);
293}
294
295wxTaskBarIcon::~wxTaskBarIcon()
296{
297 delete m_priv;
298}
299
300bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip)
301{
302 m_priv->m_bitmap = icon;
303 m_priv->m_tipText = tooltip;
304 m_priv->SetIcon();
305 return true;
306}
307
308bool wxTaskBarIcon::RemoveIcon()
309{
310 delete m_priv;
311 m_priv = new Private(this);
312 return true;
313}
314
315bool wxTaskBarIcon::IsIconInstalled() const
316{
317#ifdef __WXGTK3__
318 return m_priv->m_statusIcon != NULL;
319#else
320 return m_priv->m_statusIcon || m_priv->m_eggTrayIcon;
321#endif
322}
323
324bool wxTaskBarIcon::PopupMenu(wxMenu* menu)
325{
326#if wxUSE_MENUS
327 if (m_priv->m_win == NULL)
328 {
329 m_priv->m_win = new wxTopLevelWindow(
330 NULL, wxID_ANY, wxString(), wxDefaultPosition, wxDefaultSize, 0);
331 m_priv->m_win->PushEventHandler(this);
332 }
333 wxPoint point(-1, -1);
334#ifdef __WXUNIVERSAL__
335 point = wxGetMousePosition();
336#endif
337 m_priv->m_win->PopupMenu(menu, point);
338#endif // wxUSE_MENUS
339 return true;
340}
341
342#endif // wxUSE_TASKBARICON