]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/taskbar.cpp
Correct mouse event coordinates in wxMSW wxUIActionSimulator.
[wxWidgets.git] / src / gtk / taskbar.cpp
CommitLineData
33d4eef0 1/////////////////////////////////////////////////////////////////////////
e4db172a 2// File: src/gtk/taskbar.cpp
a1c6f069 3// Purpose: wxTaskBarIcon
33d4eef0 4// Author: Vaclav Slavik
a1c6f069 5// Modified by: Paul Cornett
33d4eef0
VS
6// Created: 2004/05/29
7// RCS-ID: $Id$
8// Copyright: (c) Vaclav Slavik, 2004
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////
11
33d4eef0
VS
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
7669dce5 15#if wxUSE_TASKBARICON
4f167b46 16
a1c6f069 17#include "wx/taskbar.h"
e4db172a
WS
18
19#ifndef WX_PRECOMP
a1c6f069 20 #include "wx/toplevel.h"
3b3dc801 21 #include "wx/menu.h"
a1c6f069 22 #include "wx/icon.h"
e4db172a
WS
23#endif
24
a1c6f069 25#include "eggtrayicon.h"
290cd301 26#include <gtk/gtk.h>
5dc22463 27
7669dce5
PC
28#if !GTK_CHECK_VERSION(2,10,0)
29 typedef struct _GtkStatusIcon GtkStatusIcon;
30#endif
31
a1c6f069
PC
32class wxTaskBarIcon::Private
33{
34public:
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//-----------------------------------------------------------------------------
33d4eef0 56
a1c6f069
PC
57extern "C" {
58static void
59icon_size_allocate(GtkWidget*, GtkAllocation* alloc, wxTaskBarIcon::Private* priv)
33d4eef0 60{
a1c6f069
PC
61 priv->size_allocate(alloc->width, alloc->height);
62}
3d257b8d 63
a1c6f069
PC
64static void
65icon_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}
3d257b8d 72
a1c6f069
PC
73static void
74icon_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}
3d257b8d 85
a1c6f069
PC
86static gboolean
87icon_popup_menu(GtkWidget*, wxTaskBarIcon* taskBarIcon)
88{
89 wxTaskBarIconEvent event(wxEVT_TASKBAR_CLICK, taskBarIcon);
90 taskBarIcon->SafelyProcessEvent(event);
91 return true;
92}
53e3cd04 93
a1c6f069
PC
94static gboolean
95icon_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;
33d4eef0
VS
105}
106
a1c6f069
PC
107#if GTK_CHECK_VERSION(2,10,0)
108static void
109status_icon_popup_menu(GtkStatusIcon*, guint, guint, wxTaskBarIcon* taskBarIcon)
33d4eef0 110{
a1c6f069
PC
111 icon_popup_menu(NULL, taskBarIcon);
112}
113#endif
114} // extern "C"
115//-----------------------------------------------------------------------------
3d257b8d 116
a1c6f069
PC
117bool wxTaskBarIconBase::IsAvailable()
118{
3b81515c 119#ifdef GDK_WINDOWING_X11
61f6ba07
VS
120 char name[32];
121 g_snprintf(name, sizeof(name), "_NET_SYSTEM_TRAY_S%d",
a1c6f069
PC
122 gdk_x11_get_default_screen());
123 Atom atom = gdk_x11_get_xatom_by_name(name);
3d257b8d 124
a1c6f069 125 Window manager = XGetSelectionOwner(gdk_x11_get_default_xdisplay(), atom);
3d257b8d 126
a1c6f069 127 return manager != None;
3b81515c
VZ
128#else
129 return true;
130#endif
33d4eef0 131}
0bd3b8ec 132//-----------------------------------------------------------------------------
a1c6f069
PC
133
134wxTaskBarIcon::Private::Private(wxTaskBarIcon* taskBarIcon)
135{
136 m_taskBarIcon = taskBarIcon;
137 m_statusIcon = NULL;
138 m_eggTrayIcon = NULL;
139 m_win = NULL;
140 m_tooltips = NULL;
141 m_size = 0;
142}
143
144wxTaskBarIcon::Private::~Private()
145{
146 if (m_statusIcon)
147 g_object_unref(m_statusIcon);
148 else if (m_eggTrayIcon)
149 {
150 g_signal_handlers_disconnect_by_func(m_eggTrayIcon, (void*)icon_destroy, this);
151 gtk_widget_destroy(m_eggTrayIcon);
152 }
153 if (m_win)
154 {
155 m_win->PopEventHandler();
156 m_win->Destroy();
157 }
158 if (m_tooltips)
159 {
160 gtk_object_destroy(GTK_OBJECT(m_tooltips));
161 g_object_unref(m_tooltips);
162 }
163}
164
165void wxTaskBarIcon::Private::SetIcon()
166{
167#if GTK_CHECK_VERSION(2,10,0)
168 if (gtk_check_version(2,10,0) == NULL)
169 {
170 if (m_statusIcon)
171 gtk_status_icon_set_from_pixbuf(m_statusIcon, m_bitmap.GetPixbuf());
172 else
173 {
174 m_statusIcon = gtk_status_icon_new_from_pixbuf(m_bitmap.GetPixbuf());
175 g_signal_connect(m_statusIcon, "activate",
176 G_CALLBACK(icon_activate), m_taskBarIcon);
177 g_signal_connect(m_statusIcon, "popup_menu",
178 G_CALLBACK(status_icon_popup_menu), m_taskBarIcon);
179 }
180 }
181 else
182#endif
183 {
184 m_size = 0;
185 if (m_eggTrayIcon)
186 {
385e8575 187 GtkWidget* image = gtk_bin_get_child(GTK_BIN(m_eggTrayIcon));
a1c6f069
PC
188 gtk_image_set_from_pixbuf(GTK_IMAGE(image), m_bitmap.GetPixbuf());
189 }
190 else
191 {
192 m_eggTrayIcon = GTK_WIDGET(egg_tray_icon_new("wxTaskBarIcon"));
193 gtk_widget_add_events(m_eggTrayIcon, GDK_BUTTON_PRESS_MASK);
194 g_signal_connect(m_eggTrayIcon, "size_allocate",
195 G_CALLBACK(icon_size_allocate), this);
196 g_signal_connect(m_eggTrayIcon, "destroy",
197 G_CALLBACK(icon_destroy), this);
198 g_signal_connect(m_eggTrayIcon, "button_press_event",
199 G_CALLBACK(icon_button_press_event), m_taskBarIcon);
200 g_signal_connect(m_eggTrayIcon, "popup_menu",
201 G_CALLBACK(icon_popup_menu), m_taskBarIcon);
202 GtkWidget* image = gtk_image_new_from_pixbuf(m_bitmap.GetPixbuf());
203 gtk_container_add(GTK_CONTAINER(m_eggTrayIcon), image);
204 gtk_widget_show_all(m_eggTrayIcon);
205 }
206 }
207#if wxUSE_TOOLTIPS
70ef48fe 208 const char *tip_text = NULL;
a1c6f069 209 if (!m_tipText.empty())
70ef48fe 210 tip_text = m_tipText.c_str();
a1c6f069
PC
211
212#if GTK_CHECK_VERSION(2,10,0)
213 if (m_statusIcon)
385e8575
PC
214 {
215#if GTK_CHECK_VERSION(2,16,0)
216 if (GTK_CHECK_VERSION(3,0,0) || gtk_check_version(2,16,0) == NULL)
217 gtk_status_icon_set_tooltip_text(m_statusIcon, tip_text);
218 else
219#endif
220 {
221#if !GTK_CHECK_VERSION(3,0,0) && !defined(GTK_DISABLE_DEPRECATED)
222 gtk_status_icon_set_tooltip(m_statusIcon, tip_text);
a1c6f069 223#endif
385e8575
PC
224 }
225 }
226 else
227#endif // GTK_CHECK_VERSION(2,10,0)
a1c6f069 228 {
385e8575 229#if !GTK_CHECK_VERSION(3,0,0) && !defined(GTK_DISABLE_DEPRECATED)
a1c6f069
PC
230 if (tip_text && m_tooltips == NULL)
231 {
232 m_tooltips = gtk_tooltips_new();
233 g_object_ref(m_tooltips);
234 gtk_object_sink(GTK_OBJECT(m_tooltips));
235 }
236 if (m_tooltips)
237 gtk_tooltips_set_tip(m_tooltips, m_eggTrayIcon, tip_text, "");
385e8575 238#endif
a1c6f069
PC
239 }
240#endif // wxUSE_TOOLTIPS
241}
242
243void wxTaskBarIcon::Private::size_allocate(int width, int height)
244{
245 int size = height;
246 EggTrayIcon* icon = EGG_TRAY_ICON(m_eggTrayIcon);
247 if (egg_tray_icon_get_orientation(icon) == GTK_ORIENTATION_VERTICAL)
248 size = width;
249 if (m_size == size)
250 return;
251 m_size = size;
252 int w = m_bitmap.GetWidth();
253 int h = m_bitmap.GetHeight();
254 if (w > size || h > size)
255 {
256 if (w > size) w = size;
257 if (h > size) h = size;
258 GdkPixbuf* pixbuf =
259 gdk_pixbuf_scale_simple(m_bitmap.GetPixbuf(), w, h, GDK_INTERP_BILINEAR);
385e8575 260 GtkImage* image = GTK_IMAGE(gtk_bin_get_child(GTK_BIN(m_eggTrayIcon)));
a1c6f069
PC
261 gtk_image_set_from_pixbuf(image, pixbuf);
262 g_object_unref(pixbuf);
263 }
264}
0bd3b8ec
RR
265//-----------------------------------------------------------------------------
266
a1c6f069
PC
267IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon, wxEvtHandler)
268
269wxTaskBarIcon::wxTaskBarIcon()
270{
271 m_priv = new Private(this);
272}
273
274wxTaskBarIcon::~wxTaskBarIcon()
275{
276 delete m_priv;
277}
278
279bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip)
280{
281 m_priv->m_bitmap = icon;
282 m_priv->m_tipText = tooltip;
283 m_priv->SetIcon();
284 return true;
285}
286
287bool wxTaskBarIcon::RemoveIcon()
288{
289 delete m_priv;
290 m_priv = new Private(this);
291 return true;
292}
293
294bool wxTaskBarIcon::IsIconInstalled() const
0bd3b8ec 295{
a1c6f069 296 return m_priv->m_statusIcon || m_priv->m_eggTrayIcon;
0bd3b8ec 297}
a1c6f069
PC
298
299bool wxTaskBarIcon::PopupMenu(wxMenu* menu)
300{
301#if wxUSE_MENUS
302 if (m_priv->m_win == NULL)
303 {
304 m_priv->m_win = new wxTopLevelWindow(
305 NULL, wxID_ANY, wxString(), wxDefaultPosition, wxDefaultSize, 0);
306 m_priv->m_win->PushEventHandler(this);
307 }
308 wxPoint point(-1, -1);
309#ifdef __WXUNIVERSAL__
310 point = wxGetMousePosition();
311#endif
312 m_priv->m_win->PopupMenu(menu, point);
313#endif // wxUSE_MENUS
314 return true;
315}
316
4f167b46 317#endif // wxUSE_TASKBARICON