]> Pileus Git - ~andy/gtk/blob - gtk/gtkstatusicon.c
Add docs.
[~andy/gtk] / gtk / gtkstatusicon.c
1 /* gtkstatusicon.c:
2  *
3  * Copyright (C) 2003 Sun Microsystems, Inc.
4  * Copyright (C) 2005 Hans Breuer <hans@breuer.org>
5  * Copyright (C) 2005 Novell, Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  *
22  * Authors:
23  *      Mark McLoughlin <mark@skynet.ie>
24  *      Hans Breuer <hans@breuer.org>
25  *      Tor Lillqvist <tml@novell.com>
26  */
27
28 #include <config.h>
29 #include <string.h>
30
31 #include "gtkstatusicon.h"
32
33 #include "gtkintl.h"
34 #include "gtkiconfactory.h"
35 #include "gtkmarshalers.h"
36 #include "gtktooltips.h"
37 #include "gtktrayicon.h"
38
39 #include "gtkprivate.h"
40 #include "gtkwidget.h"
41
42 #include "gtkalias.h"
43
44 #ifdef GDK_WINDOWING_WIN32
45 #include "gtkicontheme.h"
46 #include "gtklabel.h"
47
48 #include "win32/gdkwin32.h"
49 #define WM_GTK_TRAY_NOTIFICATION (WM_USER+1)
50 #endif
51
52 #define BLINK_TIMEOUT 500
53
54 enum
55 {
56   PROP_0,
57   PROP_PIXBUF,
58   PROP_FILE,
59   PROP_STOCK,
60   PROP_ICON_NAME,
61   PROP_STORAGE_TYPE,
62   PROP_SIZE,
63   PROP_VISIBLE,
64   PROP_BLINKING
65 };
66
67 enum 
68 {
69   ACTIVATE_SIGNAL,
70   POPUP_MENU_SIGNAL,
71   SIZE_CHANGED_SIGNAL,
72   LAST_SIGNAL
73 };
74
75 struct _GtkStatusIconPrivate
76 {
77 #ifdef GDK_WINDOWING_X11
78   GtkWidget    *tray_icon;
79   GtkWidget    *image;
80   GtkTooltips  *tooltips;
81 #endif
82
83 #ifdef GDK_WINDOWING_WIN32
84   GtkWidget     *dummy_widget;
85   NOTIFYICONDATAW nid;
86 #endif
87
88   gint          size;
89
90   gint          image_width;
91   gint          image_height;
92
93   GtkImageType  storage_type;
94
95   union
96     {
97       GdkPixbuf *pixbuf;
98       gchar     *stock_id;
99       gchar     *icon_name;
100     } image_data;
101
102   GdkPixbuf    *blank_icon;
103   guint         blinking_timeout;
104
105   guint         blinking : 1;
106   guint         blink_off : 1;
107   guint         visible : 1;
108 };
109
110 static void     gtk_status_icon_finalize         (GObject        *object);
111 static void     gtk_status_icon_set_property     (GObject        *object,
112                                                   guint           prop_id,
113                                                   const GValue   *value,
114                                                   GParamSpec     *pspec);
115 static void     gtk_status_icon_get_property     (GObject        *object,
116                                                   guint           prop_id,
117                                                   GValue         *value,
118                                                   GParamSpec     *pspec);
119
120 #ifdef GDK_WINDOWING_X11
121 static void     gtk_status_icon_size_allocate    (GtkStatusIcon  *status_icon,
122                                                   GtkAllocation  *allocation);
123 #endif
124 static gboolean gtk_status_icon_button_press     (GtkStatusIcon  *status_icon,
125                                                   GdkEventButton *event);
126 static void     gtk_status_icon_disable_blinking (GtkStatusIcon  *status_icon);
127 static void     gtk_status_icon_reset_image_data (GtkStatusIcon  *status_icon);
128                                            
129
130 static guint status_icon_signals [LAST_SIGNAL] = { 0 };
131
132 G_DEFINE_TYPE (GtkStatusIcon, gtk_status_icon, G_TYPE_OBJECT);
133
134 static void
135 gtk_status_icon_class_init (GtkStatusIconClass *class)
136 {
137   GObjectClass *gobject_class = (GObjectClass *) class;
138
139   gobject_class->finalize     = gtk_status_icon_finalize;
140   gobject_class->set_property = gtk_status_icon_set_property;
141   gobject_class->get_property = gtk_status_icon_get_property;
142
143   g_object_class_install_property (gobject_class,
144                                    PROP_PIXBUF,
145                                    g_param_spec_object ("pixbuf",
146                                                         P_("Pixbuf"),
147                                                         P_("A GdkPixbuf to display"),
148                                                         GDK_TYPE_PIXBUF,
149                                                         GTK_PARAM_READWRITE));
150
151   g_object_class_install_property (gobject_class,
152                                    PROP_FILE,
153                                    g_param_spec_string ("file",
154                                                         P_("Filename"),
155                                                         P_("Filename to load and display"),
156                                                         NULL,
157                                                         GTK_PARAM_WRITABLE));
158
159   g_object_class_install_property (gobject_class,
160                                    PROP_STOCK,
161                                    g_param_spec_string ("stock",
162                                                         P_("Stock ID"),
163                                                         P_("Stock ID for a stock image to display"),
164                                                         NULL,
165                                                         GTK_PARAM_READWRITE));
166   
167   g_object_class_install_property (gobject_class,
168                                    PROP_ICON_NAME,
169                                    g_param_spec_string ("icon-name",
170                                                         P_("Icon Name"),
171                                                         P_("The name of the icon from the icon theme"),
172                                                         NULL,
173                                                         GTK_PARAM_READWRITE));
174   
175   g_object_class_install_property (gobject_class,
176                                    PROP_STORAGE_TYPE,
177                                    g_param_spec_enum ("storage-type",
178                                                       P_("Storage type"),
179                                                       P_("The representation being used for image data"),
180                                                       GTK_TYPE_IMAGE_TYPE,
181                                                       GTK_IMAGE_EMPTY,
182                                                       GTK_PARAM_READABLE));
183
184   g_object_class_install_property (gobject_class,
185                                    PROP_SIZE,
186                                    g_param_spec_int ("size",
187                                                      P_("Size"),
188                                                      P_("The size of the icon"),
189                                                      0,
190                                                      G_MAXINT,
191                                                      0,
192                                                      GTK_PARAM_READABLE));
193
194   g_object_class_install_property (gobject_class,
195                                    PROP_BLINKING,
196                                    g_param_spec_boolean ("blinking",
197                                                          P_("Blinking"),
198                                                          P_("Whether or not the status icon is blinking"),
199                                                          FALSE,
200                                                          GTK_PARAM_READWRITE));
201
202   g_object_class_install_property (gobject_class,
203                                    PROP_VISIBLE,
204                                    g_param_spec_boolean ("visible",
205                                                          P_("Visible"),
206                                                          P_("Whether or not the status icon is visible"),
207                                                          TRUE,
208                                                          GTK_PARAM_READWRITE));
209
210
211   /**
212    * GtkStatusIcon::activate:
213    * @status_icon: the object which received the signal
214    *
215    * Gets emitted when the user activates the status icon. 
216    * If and how status icons can activated is platform-dependent.
217    *
218    * Since: 2.10
219    */
220   status_icon_signals [ACTIVATE_SIGNAL] =
221     g_signal_new (I_("activate"),
222                   G_TYPE_FROM_CLASS (gobject_class),
223                   G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
224                   G_STRUCT_OFFSET (GtkStatusIconClass, activate),
225                   NULL,
226                   NULL,
227                   g_cclosure_marshal_VOID__VOID,
228                   G_TYPE_NONE,
229                   0);
230
231   /**
232    * GtkStatusIcon::popup-menu:
233    * @status_icon: the object which received the signal
234    * @button: the button that was pressed, or 0 if the 
235    *   signal is not emitted in response to a button press event
236    * @activate_time: the timestamp of the event that
237    *   triggered the signal emission
238    *
239    * Gets emitted when the user brings up the context menu
240    * of the status icon. Whether status icons can have context 
241    * menus and how these are activated is platform-dependent.
242    *
243    * The @button and @activate_timeout parameters should be 
244    * passed as the last to arguments to gtk_menu_popup().
245    *
246    * Since: 2.10
247    */
248   status_icon_signals [POPUP_MENU_SIGNAL] =
249     g_signal_new (I_("popup-menu"),
250                   G_TYPE_FROM_CLASS (gobject_class),
251                   G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
252                   G_STRUCT_OFFSET (GtkStatusIconClass, popup_menu),
253                   NULL,
254                   NULL,
255                   _gtk_marshal_VOID__UINT_UINT,
256                   G_TYPE_NONE,
257                   2,
258                   G_TYPE_UINT,
259                   G_TYPE_UINT);
260
261   /**
262    * GtkStatusIcon::size-changed:
263    * @status_icon: the object which received the signal
264    * @size: the new size
265    *
266    * Gets emitted when the size available for the image
267    * changes, e.g. because the notification area got resized.
268    *
269    * Since: 2.10
270    */
271   status_icon_signals [SIZE_CHANGED_SIGNAL] =
272     g_signal_new (I_("size-changed"),
273                   G_TYPE_FROM_CLASS (gobject_class),
274                   G_SIGNAL_RUN_FIRST,
275                   G_STRUCT_OFFSET (GtkStatusIconClass, size_changed),
276                   NULL,
277                   NULL,
278                   _gtk_marshal_BOOLEAN__INT,
279                   G_TYPE_NONE,
280                   1,
281                   G_TYPE_INT);
282
283   g_type_class_add_private (class, sizeof (GtkStatusIconPrivate));
284 }
285
286 #ifdef GDK_WINDOWING_WIN32
287
288 static void
289 build_button_event (GdkEventButton *e,
290                     GdkEventType    type,
291                     guint           button)
292 {
293   POINT pos;
294   GdkRectangle monitor0;
295
296   /* We know that gdk/win32 puts the primary monitor at index 0 */
297   gdk_screen_get_monitor_geometry (gdk_screen_get_default (), 0, &monitor0);
298   e->type = type;
299   e->window = gdk_get_default_root_window ();
300   e->send_event = TRUE;
301   e->time = GetTickCount ();
302   GetCursorPos (&pos);
303   e->x = pos.x + monitor0.x;
304   e->y = pos.y + monitor0.y;
305   e->axes = NULL;
306   e->state = 0;
307   e->button = button;
308   e->device = gdk_display_get_default ()->core_pointer;
309   e->x_root = e->x;
310   e->y_root = e->y;
311 }
312
313 static LRESULT CALLBACK
314 wndproc (HWND   hwnd,
315          UINT   message,
316          WPARAM wparam,
317          LPARAM lparam)
318 {
319   if (message == WM_GTK_TRAY_NOTIFICATION)
320     {
321       GdkEventButton e;
322       GtkStatusIcon *status_icon = GTK_STATUS_ICON (wparam);
323       
324       switch (lparam)
325         {
326         case WM_LBUTTONDOWN:
327         case WM_RBUTTONDOWN:
328           build_button_event (&e, GDK_BUTTON_PRESS,
329                               (lparam == WM_LBUTTONDOWN) ? 1 : 3);
330           gtk_status_icon_button_press (status_icon, &e);
331           break;
332         default :
333           break;
334         }
335         return 0;
336     }
337   else
338     {
339       return DefWindowProc (hwnd, message, wparam, lparam);
340     }
341 }
342
343 static HWND
344 create_tray_observer (void)
345 {
346   WNDCLASS    wclass;
347   static HWND hwnd = NULL;
348   ATOM        klass;
349   HINSTANCE   hmodule = GetModuleHandle (NULL);
350
351   if (hwnd)
352     return hwnd;
353
354   memset (&wclass, 0, sizeof(WNDCLASS));
355   wclass.lpszClassName = "gtkstatusicon-observer";
356   wclass.lpfnWndProc   = wndproc;
357   wclass.hInstance     = hmodule;
358
359   klass = RegisterClass (&wclass);
360   if (!klass)
361     return NULL;
362
363   hwnd = CreateWindow (MAKEINTRESOURCE(klass),
364                        NULL, WS_POPUP,
365                        0, 0, 1, 1, NULL, NULL,
366                        hmodule, NULL);
367   if (!hwnd)
368     {
369       UnregisterClass (MAKEINTRESOURCE(klass), hmodule);
370       return NULL;
371     }
372
373   return hwnd;
374 }
375
376 #endif
377
378 static void
379 gtk_status_icon_init (GtkStatusIcon *status_icon)
380 {
381   status_icon->priv = G_TYPE_INSTANCE_GET_PRIVATE (status_icon, GTK_TYPE_STATUS_ICON,
382                                                    GtkStatusIconPrivate);
383   
384   status_icon->priv->storage_type = GTK_IMAGE_EMPTY;
385   status_icon->priv->visible      = TRUE;
386
387 #ifdef GDK_WINDOWING_X11
388   status_icon->priv->size         = 0;
389   status_icon->priv->image_width  = 0;
390   status_icon->priv->image_height = 0;
391
392   status_icon->priv->tray_icon = GTK_WIDGET (_gtk_tray_icon_new (NULL));
393
394   gtk_widget_add_events (GTK_WIDGET (status_icon->priv->tray_icon),
395                          GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
396
397   g_signal_connect_swapped (status_icon->priv->tray_icon, "button-press-event",
398                             G_CALLBACK (gtk_status_icon_button_press), status_icon);
399   status_icon->priv->image = gtk_image_new ();
400   gtk_container_add (GTK_CONTAINER (status_icon->priv->tray_icon),
401                      status_icon->priv->image);
402
403   g_signal_connect_swapped (status_icon->priv->image, "size-allocate",
404                             G_CALLBACK (gtk_status_icon_size_allocate), status_icon);
405
406   gtk_widget_show (status_icon->priv->image);
407   gtk_widget_show (status_icon->priv->tray_icon);
408
409   status_icon->priv->tooltips = gtk_tooltips_new ();
410   g_object_ref_sink (status_icon->priv->tooltips);
411 #endif
412
413 #ifdef GDK_WINDOWING_WIN32
414
415   /* Code to get position and orientation of Windows taskbar. Not needed
416    * currently, kept for reference.
417    */
418 #if 0
419   {
420     APPBARDATA abd;
421     
422     abd.cbSize = sizeof (abd);
423     SHAppBarMessage (ABM_GETTASKBARPOS, &abd);
424     if (abd.rc.bottom - abd.rc.top > abd.rc.right - abd.rc.left)
425       orientation = GTK_ORIENTATION_VERTICAL;
426     else
427       orientation = GTK_ORIENTATION_HORIZONTAL;
428   }
429 #endif
430
431   /* Are the system tray icons always 16 pixels square? */
432   status_icon->priv->size         = 16;
433   status_icon->priv->image_width  = 16;
434   status_icon->priv->image_height = 16;
435
436   status_icon->priv->dummy_widget = gtk_label_new ("");
437
438   memset (&status_icon->priv->nid, 0, sizeof (status_icon->priv->nid));
439
440   status_icon->priv->nid.hWnd = create_tray_observer ();
441   status_icon->priv->nid.uID = GPOINTER_TO_UINT (status_icon);
442   status_icon->priv->nid.uCallbackMessage = WM_GTK_TRAY_NOTIFICATION;
443   status_icon->priv->nid.uFlags = NIF_MESSAGE;
444
445   if (!Shell_NotifyIconW (NIM_ADD, &status_icon->priv->nid))
446     {
447       g_warning ("%s:%d:Shell_NotifyIcon(NIM_ADD) failed", __FILE__, __LINE__-2);
448       status_icon->priv->nid.hWnd = NULL;
449     }
450 #endif
451 }
452
453 static void
454 gtk_status_icon_finalize (GObject *object)
455 {
456   GtkStatusIcon *status_icon = GTK_STATUS_ICON (object);
457
458   gtk_status_icon_disable_blinking (status_icon);
459   
460   gtk_status_icon_reset_image_data (status_icon);
461
462   if (status_icon->priv->blank_icon)
463     g_object_unref (status_icon->priv->blank_icon);
464   status_icon->priv->blank_icon = NULL;
465
466 #ifdef GDK_WINDOWING_X11
467   if (status_icon->priv->tooltips)
468     g_object_unref (status_icon->priv->tooltips);
469   status_icon->priv->tooltips = NULL;
470
471   gtk_widget_destroy (status_icon->priv->tray_icon);
472 #endif
473
474 #ifdef GDK_WINDOWING_WIN32
475   if (status_icon->priv->nid.hWnd != NULL && status_icon->priv->visible)
476     Shell_NotifyIconW (NIM_DELETE, &status_icon->priv->nid);
477
478   gtk_widget_destroy (status_icon->priv->dummy_widget);
479 #endif
480
481   G_OBJECT_CLASS (gtk_status_icon_parent_class)->finalize (object);
482 }
483
484 static void
485 gtk_status_icon_set_property (GObject      *object,
486                               guint         prop_id,
487                               const GValue *value,
488                               GParamSpec   *pspec)
489 {
490   GtkStatusIcon *status_icon = GTK_STATUS_ICON (object);
491
492   switch (prop_id)
493     {
494     case PROP_PIXBUF:
495       gtk_status_icon_set_from_pixbuf (status_icon, g_value_get_object (value));
496       break;
497     case PROP_FILE:
498       gtk_status_icon_set_from_file (status_icon, g_value_get_string (value));
499       break;
500     case PROP_STOCK:
501       gtk_status_icon_set_from_stock (status_icon, g_value_get_string (value));
502       break;
503     case PROP_ICON_NAME:
504       gtk_status_icon_set_from_icon_name (status_icon, g_value_get_string (value));
505       break;
506     case PROP_BLINKING:
507       gtk_status_icon_set_blinking (status_icon, g_value_get_boolean (value));
508       break;
509     case PROP_VISIBLE:
510       gtk_status_icon_set_visible (status_icon, g_value_get_boolean (value));
511       break;
512     default:
513       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
514       break;
515     }
516 }
517
518 static void
519 gtk_status_icon_get_property (GObject    *object,
520                               guint       prop_id,
521                               GValue     *value,
522                               GParamSpec *pspec)
523 {
524   GtkStatusIcon *status_icon = GTK_STATUS_ICON (object);
525
526   switch (prop_id)
527     {
528     case PROP_PIXBUF:
529       g_value_set_object (value, gtk_status_icon_get_pixbuf (status_icon));
530       break;
531     case PROP_STOCK:
532       g_value_set_string (value, gtk_status_icon_get_stock (status_icon));
533       break;
534     case PROP_ICON_NAME:
535       g_value_set_string (value, gtk_status_icon_get_icon_name (status_icon));
536       break;
537     case PROP_STORAGE_TYPE:
538       g_value_set_enum (value, gtk_status_icon_get_storage_type (status_icon));
539       break;
540     case PROP_SIZE:
541       g_value_set_int (value, gtk_status_icon_get_size (status_icon));
542       break;
543     case PROP_BLINKING:
544       g_value_set_boolean (value, gtk_status_icon_get_blinking (status_icon));
545       break;
546     case PROP_VISIBLE:
547       g_value_set_boolean (value, gtk_status_icon_get_visible (status_icon));
548       break;
549     default:
550       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
551       break;
552     }
553 }
554
555 /**
556  * gtk_status_icon_new:
557  * 
558  * Creates an empty status icon object.
559  * 
560  * Return value: a new #GtkStatusIcon
561  *
562  * Since: 2.10
563  **/
564 GtkStatusIcon *
565 gtk_status_icon_new (void)
566 {
567   return g_object_new (GTK_TYPE_STATUS_ICON, NULL);
568 }
569
570 /**
571  * gtk_status_icon_new_from_pixbuf:
572  * @pixbuf: a #GdkPixbuf
573  * 
574  * Creates a status icon displaying @pixbuf. 
575  *
576  * The image will be scaled down to fit in the available 
577  * space in the notification area, if necessary.
578  * 
579  * Return value: a new #GtkStatusIcon
580  *
581  * Since: 2.10
582  **/
583 GtkStatusIcon *
584 gtk_status_icon_new_from_pixbuf (GdkPixbuf *pixbuf)
585 {
586   return g_object_new (GTK_TYPE_STATUS_ICON,
587                        "pixbuf", pixbuf,
588                        NULL);
589 }
590
591 /**
592  * gtk_status_icon_new_from_file:
593  * @filename: a filename
594  * 
595  * Creates a status icon displaying the file @filename. 
596  *
597  * The image will be scaled down to fit in the available 
598  * space in the notification area, if necessary.
599  * 
600  * Return value: a new #GtkStatusIcon
601  *
602  * Since: 2.10
603  **/
604 GtkStatusIcon *
605 gtk_status_icon_new_from_file (const gchar *filename)
606 {
607   return g_object_new (GTK_TYPE_STATUS_ICON,
608                        "file", filename,
609                        NULL);
610 }
611
612 /**
613  * gtk_status_icon_new_from_stock:
614  * @stock_id: a stock icon id
615  * 
616  * Creates a status icon displaying a stock icon. Sample stock icon
617  * names are #GTK_STOCK_OPEN, #GTK_STOCK_QUIT. You can register your 
618  * own stock icon names, see gtk_icon_factory_add_default() and 
619  * gtk_icon_factory_add(). 
620  *
621  * Return value: a new #GtkStatusIcon
622  *
623  * Since: 2.10
624  **/
625 GtkStatusIcon *
626 gtk_status_icon_new_from_stock (const gchar *stock_id)
627 {
628   return g_object_new (GTK_TYPE_STATUS_ICON,
629                        "stock", stock_id,
630                        NULL);
631 }
632
633 /**
634  * gtk_status_icon_new_from_icon_name:
635  * @icon_name: an icon name
636  * 
637  * Creates a status icon displaying an icon from the current icon theme.
638  * If the current icon theme is changed, the icon will be updated 
639  * appropriately.
640  * 
641  * Return value: a new #GtkStatusIcon
642  *
643  * Since: 2.10
644  **/
645 GtkStatusIcon *
646 gtk_status_icon_new_from_icon_name (const gchar *icon_name)
647 {
648   return g_object_new (GTK_TYPE_STATUS_ICON,
649                        "icon-name", icon_name,
650                        NULL);
651 }
652
653 static void
654 emit_activate_signal (GtkStatusIcon *status_icon)
655 {
656   g_signal_emit (status_icon,
657                  status_icon_signals [ACTIVATE_SIGNAL], 0);
658 }
659
660 static void
661 emit_popup_menu_signal (GtkStatusIcon *status_icon,
662                         guint          button,
663                         guint32        activate_time)
664 {
665   g_signal_emit (status_icon,
666                  status_icon_signals [POPUP_MENU_SIGNAL], 0,
667                  button,
668                  activate_time);
669 }
670
671 #ifdef GDK_WINDOWING_X11
672
673 static gboolean
674 emit_size_changed_signal (GtkStatusIcon *status_icon,
675                           gint           size)
676 {
677   gboolean handled = FALSE;
678   
679   g_signal_emit (status_icon,
680                  status_icon_signals [SIZE_CHANGED_SIGNAL], 0,
681                  size,
682                  &handled);
683
684   return handled;
685 }
686
687 #endif
688
689 static GdkPixbuf *
690 gtk_status_icon_blank_icon (GtkStatusIcon *status_icon)
691 {
692   if (status_icon->priv->blank_icon)
693     {
694       gint width, height;
695
696       width  = gdk_pixbuf_get_width (status_icon->priv->blank_icon);
697       height = gdk_pixbuf_get_height (status_icon->priv->blank_icon);
698
699
700       if (width == status_icon->priv->image_width && 
701           height == status_icon->priv->image_height)
702         {
703           return status_icon->priv->blank_icon;
704         }
705       else
706         {
707           g_object_unref (status_icon->priv->blank_icon);
708           status_icon->priv->blank_icon = NULL;
709         }
710     }
711
712   status_icon->priv->blank_icon = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
713                                                   status_icon->priv->image_width, 
714                                                   status_icon->priv->image_height);
715   if (status_icon->priv->blank_icon)
716     gdk_pixbuf_fill (status_icon->priv->blank_icon, 0);
717
718   return status_icon->priv->blank_icon;
719 }
720
721 #ifdef GDK_WINDOWING_X11
722
723 static GtkIconSize
724 find_icon_size (GtkWidget *widget, 
725                 gint       pixel_size)
726 {
727   GdkScreen *screen;
728   GtkSettings *settings;
729   GtkIconSize s, size;
730   gint w, h, d, dist;
731
732   screen = gtk_widget_get_screen (widget);
733
734   if (!screen)
735     return GTK_ICON_SIZE_MENU;
736
737   settings = gtk_settings_get_for_screen (screen);
738   
739   dist = G_MAXINT;
740   size = GTK_ICON_SIZE_MENU;
741
742   for (s = GTK_ICON_SIZE_MENU; s < GTK_ICON_SIZE_DIALOG; s++)
743     {
744       if (gtk_icon_size_lookup_for_settings (settings, s, &w, &h) &&
745           w <= pixel_size && h <= pixel_size)
746         {
747           d = MAX (pixel_size - w, pixel_size - h);
748           if (d < dist)
749             {
750               dist = d;
751               size = s;
752             }
753         }
754     }
755   
756   return size;
757 }
758
759 #endif
760
761 static void
762 gtk_status_icon_update_image (GtkStatusIcon *status_icon)
763 {
764   if (status_icon->priv->blink_off)
765     {
766 #ifdef GDK_WINDOWING_X11
767       gtk_image_set_from_pixbuf (GTK_IMAGE (status_icon->priv->image),
768                                  gtk_status_icon_blank_icon (status_icon));
769 #endif
770 #ifdef GDK_WINDOWING_WIN32
771       status_icon->priv->nid.hIcon = gdk_win32_pixbuf_to_hicon_libgtk_only (gtk_status_icon_blank_icon (status_icon));
772       status_icon->priv->nid.uFlags |= NIF_ICON;
773       if (status_icon->priv->nid.hWnd != NULL && status_icon->priv->visible)
774         if (!Shell_NotifyIconW (NIM_MODIFY, &status_icon->priv->nid))
775           g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
776 #endif
777       return;
778     }
779
780   switch (status_icon->priv->storage_type)
781     {
782     case GTK_IMAGE_PIXBUF:
783       {
784         GdkPixbuf *pixbuf;
785
786         pixbuf = status_icon->priv->image_data.pixbuf;
787
788         if (pixbuf)
789           {
790             GdkPixbuf *scaled;
791             gint size;
792             gint width;
793             gint height;
794
795             size = status_icon->priv->size;
796
797             width  = gdk_pixbuf_get_width  (pixbuf);
798             height = gdk_pixbuf_get_height (pixbuf);
799
800             if (width > size || height > size)
801               {
802                 scaled = gdk_pixbuf_scale_simple (pixbuf,
803                                                   MIN (size, width),
804                                                   MIN (size, height),
805                                                   GDK_INTERP_BILINEAR);
806               }
807             else
808               {
809                 scaled = g_object_ref (pixbuf);
810               }
811
812 #ifdef GDK_WINDOWING_X11
813             gtk_image_set_from_pixbuf (GTK_IMAGE (status_icon->priv->image), scaled);
814 #endif
815 #ifdef GDK_WINDOWING_WIN32
816             status_icon->priv->nid.hIcon = gdk_win32_pixbuf_to_hicon_libgtk_only (scaled);
817             status_icon->priv->nid.uFlags |= NIF_ICON;
818             if (status_icon->priv->nid.hWnd != NULL && status_icon->priv->visible)
819               if (!Shell_NotifyIconW (NIM_MODIFY, &status_icon->priv->nid))
820                   g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
821 #endif
822             g_object_unref (scaled);
823           }
824         else
825           {
826 #ifdef GDK_WINDOWING_X11
827             gtk_image_set_from_pixbuf (GTK_IMAGE (status_icon->priv->image), NULL);
828 #endif
829 #ifdef GDK_WINDOWING_WIN32
830             status_icon->priv->nid.uFlags &= ~NIF_ICON;
831             if (status_icon->priv->nid.hWnd != NULL && status_icon->priv->visible)
832               if (!Shell_NotifyIconW (NIM_MODIFY, &status_icon->priv->nid))
833                 g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
834 #endif
835           }
836       }
837       break;
838
839     case GTK_IMAGE_STOCK:
840       {
841 #ifdef GDK_WINDOWING_X11
842         GtkIconSize size = find_icon_size (status_icon->priv->image, status_icon->priv->size);
843         gtk_image_set_from_stock (GTK_IMAGE (status_icon->priv->image),
844                                   status_icon->priv->image_data.stock_id,
845                                   size);
846 #endif
847 #ifdef GDK_WINDOWING_WIN32
848         {
849           GdkPixbuf *pixbuf =
850             gtk_widget_render_icon (status_icon->priv->dummy_widget,
851                                     status_icon->priv->image_data.stock_id,
852                                     GTK_ICON_SIZE_SMALL_TOOLBAR,
853                                     NULL);
854           status_icon->priv->nid.hIcon = gdk_win32_pixbuf_to_hicon_libgtk_only (pixbuf);
855           status_icon->priv->nid.uFlags |= NIF_ICON;
856           if (status_icon->priv->nid.hWnd != NULL && status_icon->priv->visible)
857             if (!Shell_NotifyIconW (NIM_MODIFY, &status_icon->priv->nid))
858               g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
859           g_object_unref (pixbuf);
860         }
861 #endif
862       }
863       break;
864       
865     case GTK_IMAGE_ICON_NAME:
866       {
867 #ifdef GDK_WINDOWING_X11
868         GtkIconSize size = find_icon_size (status_icon->priv->image, status_icon->priv->size);
869         gtk_image_set_from_icon_name (GTK_IMAGE (status_icon->priv->image),
870                                       status_icon->priv->image_data.icon_name,
871                                       size);
872 #endif
873 #ifdef GDK_WINDOWING_WIN32
874         {
875           GdkPixbuf *pixbuf =
876             gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
877                                       status_icon->priv->image_data.icon_name,
878                                       status_icon->priv->size,
879                                       0, NULL);
880           
881           status_icon->priv->nid.hIcon = gdk_win32_pixbuf_to_hicon_libgtk_only (pixbuf);
882           status_icon->priv->nid.uFlags |= NIF_ICON;
883           if (status_icon->priv->nid.hWnd != NULL && status_icon->priv->visible)
884             if (!Shell_NotifyIconW (NIM_MODIFY, &status_icon->priv->nid))
885               g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
886           g_object_unref (pixbuf);
887         }
888 #endif
889       }
890       break;
891       
892     case GTK_IMAGE_EMPTY:
893 #ifdef GDK_WINDOWING_X11
894       gtk_image_set_from_pixbuf (GTK_IMAGE (status_icon->priv->image), NULL);
895 #endif
896 #ifdef GDK_WINDOWING_WIN32
897       status_icon->priv->nid.uFlags &= ~NIF_ICON;
898       if (status_icon->priv->nid.hWnd != NULL && status_icon->priv->visible)
899         if (!Shell_NotifyIconW (NIM_MODIFY, &status_icon->priv->nid))
900           g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
901 #endif
902       break;
903     default:
904       g_assert_not_reached ();
905       break;
906     }
907 }
908
909 #ifdef GDK_WINDOWING_X11
910
911 static void
912 gtk_status_icon_size_allocate (GtkStatusIcon *status_icon,
913                                GtkAllocation *allocation)
914 {
915   GtkOrientation orientation;
916   gint size;
917
918   orientation = _gtk_tray_icon_get_orientation (GTK_TRAY_ICON (status_icon->priv->tray_icon));
919
920   if (orientation == GTK_ORIENTATION_HORIZONTAL)
921     size = allocation->height;
922   else
923     size = allocation->width;
924
925   status_icon->priv->image_width = allocation->width - GTK_MISC (status_icon->priv->image)->xpad * 2;
926   status_icon->priv->image_height = allocation->height - GTK_MISC (status_icon->priv->image)->ypad * 2;
927
928   if (status_icon->priv->size != size)
929     {
930       status_icon->priv->size = size;
931
932       g_object_notify (G_OBJECT (status_icon), "size");
933
934       if (!emit_size_changed_signal (status_icon, size))
935         {
936           gtk_status_icon_update_image (status_icon);
937         }
938     }
939 }
940
941 #endif
942
943 static gboolean
944 gtk_status_icon_button_press (GtkStatusIcon  *status_icon,
945                               GdkEventButton *event)
946 {
947   if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
948     {
949       emit_activate_signal (status_icon);
950       return TRUE;
951     }
952   else if (event->button == 3 && event->type == GDK_BUTTON_PRESS)
953     {
954       emit_popup_menu_signal (status_icon, event->button, event->time);
955       return TRUE;
956     }
957
958   return FALSE;
959 }
960
961 static void
962 gtk_status_icon_reset_image_data (GtkStatusIcon *status_icon)
963 {
964   status_icon->priv->storage_type = GTK_IMAGE_EMPTY;
965   g_object_notify (G_OBJECT (status_icon), "storage-type");
966
967   switch (status_icon->priv->storage_type)
968   {
969     case GTK_IMAGE_PIXBUF:
970       if (status_icon->priv->image_data.pixbuf)
971         g_object_unref (status_icon->priv->image_data.pixbuf);
972       status_icon->priv->image_data.pixbuf = NULL;
973       g_object_notify (G_OBJECT (status_icon), "pixbuf");
974       break;
975
976     case GTK_IMAGE_STOCK:
977       g_free (status_icon->priv->image_data.stock_id);
978       status_icon->priv->image_data.stock_id = NULL;
979
980       g_object_notify (G_OBJECT (status_icon), "stock");
981       break;
982       
983     case GTK_IMAGE_ICON_NAME:
984       g_free (status_icon->priv->image_data.icon_name);
985       status_icon->priv->image_data.icon_name = NULL;
986
987       g_object_notify (G_OBJECT (status_icon), "icon-name");
988       break;
989       
990     case GTK_IMAGE_EMPTY:
991       break;
992     default:
993       g_assert_not_reached ();
994       break;
995   }
996 }
997
998 static void
999 gtk_status_icon_set_image (GtkStatusIcon *status_icon,
1000                            GtkImageType   storage_type,
1001                            gpointer       data)
1002 {
1003   g_object_freeze_notify (G_OBJECT (status_icon));
1004
1005   gtk_status_icon_reset_image_data (status_icon);
1006
1007   status_icon->priv->storage_type = storage_type;
1008   g_object_notify (G_OBJECT (status_icon), "storage-type");
1009
1010   switch (storage_type) 
1011     {
1012     case GTK_IMAGE_PIXBUF:
1013       status_icon->priv->image_data.pixbuf = (GdkPixbuf *)data;
1014       g_object_notify (G_OBJECT (status_icon), "pixbuf");
1015       break;
1016     case GTK_IMAGE_STOCK:
1017       status_icon->priv->image_data.stock_id = g_strdup ((const gchar *)data);
1018       g_object_notify (G_OBJECT (status_icon), "stock");
1019       break;
1020     case GTK_IMAGE_ICON_NAME:
1021       status_icon->priv->image_data.icon_name = g_strdup ((const gchar *)data);
1022       g_object_notify (G_OBJECT (status_icon), "icon-name");
1023       break;
1024     default:
1025       g_warning ("Image type %d not handled by GtkStatusIcon", storage_type);
1026     }
1027
1028   g_object_thaw_notify (G_OBJECT (status_icon));
1029
1030   gtk_status_icon_update_image (status_icon);
1031 }
1032
1033 /**
1034  * gtk_status_icon_set_from_pixbuf:
1035  * @status_icon: a #GtkStatusIcon
1036  * @pixbuf: a #GdkPixbuf or %NULL
1037  * 
1038  * Makes @status_icon display @pixbuf. 
1039  * See gtk_status_icon_new_from_pixbuf() for details.
1040  *
1041  * Since: 2.10
1042  **/
1043 void
1044 gtk_status_icon_set_from_pixbuf (GtkStatusIcon *status_icon,
1045                                  GdkPixbuf     *pixbuf)
1046 {
1047   g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1048   g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));
1049
1050   if (pixbuf)
1051     g_object_ref (pixbuf);
1052
1053   gtk_status_icon_set_image (status_icon, GTK_IMAGE_PIXBUF,
1054                              (gpointer) pixbuf);
1055 }
1056
1057 /**
1058  * gtk_status_icon_set_from_file:
1059  * @status_icon: a #GtkStatusIcon
1060  * @filename: a filename
1061  * 
1062  * Makes @status_icon display the file @filename.
1063  * See gtk_status_icon_new_from_file() for details.
1064  *
1065  * Since: 2.10 
1066  **/
1067 void
1068 gtk_status_icon_set_from_file (GtkStatusIcon *status_icon,
1069                                const gchar   *filename)
1070 {
1071   GdkPixbuf *pixbuf;
1072   
1073   g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1074   g_return_if_fail (filename != NULL);
1075   
1076   pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
1077   
1078   gtk_status_icon_set_from_pixbuf (status_icon, pixbuf);
1079   
1080   if (pixbuf)
1081     g_object_unref (pixbuf);
1082 }
1083
1084 /**
1085  * gtk_status_icon_set_from_stock:
1086  * @status_icon: a #GtkStatusIcon
1087  * @stock_id: a stock icon id
1088  * 
1089  * Makes @status_icon display the stock icon with the id @stock_id.
1090  * See gtk_status_icon_new_from_stock() for details.
1091  *
1092  * Since: 2.10 
1093  **/
1094 void
1095 gtk_status_icon_set_from_stock (GtkStatusIcon *status_icon,
1096                                 const gchar   *stock_id)
1097 {
1098   g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1099   g_return_if_fail (stock_id != NULL);
1100
1101   gtk_status_icon_set_image (status_icon, GTK_IMAGE_STOCK,
1102                              (gpointer) stock_id);
1103 }
1104
1105 /**
1106  * gtk_status_icon_set_from_icon_name:
1107  * @status_icon: a #GtkStatusIcon
1108  * @icon_name: an icon name
1109  * 
1110  * Makes @status_icon display the icon named @icon_name from the 
1111  * current icon theme.
1112  * See gtk_status_icon_new_from_icon_name() for details.
1113  *
1114  * Since: 2.10 
1115  **/
1116 void
1117 gtk_status_icon_set_from_icon_name (GtkStatusIcon *status_icon,
1118                                     const gchar   *icon_name)
1119 {
1120   g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1121   g_return_if_fail (icon_name != NULL);
1122
1123   gtk_status_icon_set_image (status_icon, GTK_IMAGE_ICON_NAME,
1124                              (gpointer) icon_name);
1125 }
1126
1127 /**
1128  * gtk_status_icon_get_storage_type:
1129  * @status_icon: a #GtkStatusIcon
1130  * 
1131  * Gets the type of representation being used by the #GtkStatusIcon
1132  * to store image data. If the #GtkStatusIcon has no image data,
1133  * the return value will be %GTK_IMAGE_EMPTY. 
1134  * 
1135  * Return value: the image representation being used
1136  *
1137  * Since: 2.10
1138  **/
1139 GtkImageType
1140 gtk_status_icon_get_storage_type (GtkStatusIcon *status_icon)
1141 {
1142   g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), GTK_IMAGE_EMPTY);
1143
1144   return status_icon->priv->storage_type;
1145 }
1146 /**
1147  * gtk_status_icon_get_pixbuf:
1148  * @status_icon: a #GtkStatusIcon
1149  * 
1150  * Gets the #GdkPixbuf being displayed by the #GtkStatusIcon.
1151  * The storage type of the status icon must be %GTK_IMAGE_EMPTY or
1152  * %GTK_IMAGE_PIXBUF (see gtk_status_icon_get_storage_type()).
1153  * The caller of this function does not own a reference to the
1154  * returned pixbuf.
1155  * 
1156  * Return value: the displayed pixbuf, or %NULL if the image is empty.
1157  *
1158  * Since: 2.10
1159  **/
1160 GdkPixbuf *
1161 gtk_status_icon_get_pixbuf (GtkStatusIcon *status_icon)
1162 {
1163   g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), NULL);
1164   g_return_val_if_fail (status_icon->priv->storage_type == GTK_IMAGE_PIXBUF ||
1165                         status_icon->priv->storage_type == GTK_IMAGE_EMPTY, NULL);
1166   if (status_icon->priv->storage_type == GTK_IMAGE_EMPTY)
1167     status_icon->priv->image_data.pixbuf = NULL;
1168
1169   return status_icon->priv->image_data.pixbuf;
1170 }
1171
1172 /**
1173  * gtk_status_icon_get_stock:
1174  * @status_icon: a #GtkStatusIcon
1175  * 
1176  * Gets the id of the stock icon being displayed by the #GtkStatusIcon.
1177  * The storage type of the status icon must be %GTK_IMAGE_EMPTY or
1178  * %GTK_IMAGE_STOCK (see gtk_status_icon_get_storage_type()).
1179  * The returned string is owned by the #GtkStatusIcon and should not
1180  * be freed or modified.
1181  * 
1182  * Return value: stock id of the displayed stock icon,
1183  *   or %NULL if the image is empty.
1184  *
1185  * Since: 2.10
1186  **/
1187 G_CONST_RETURN gchar *
1188 gtk_status_icon_get_stock (GtkStatusIcon *status_icon)
1189 {
1190   g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), NULL);
1191   g_return_val_if_fail (status_icon->priv->storage_type == GTK_IMAGE_STOCK ||
1192                         status_icon->priv->storage_type == GTK_IMAGE_EMPTY, NULL);
1193   
1194   if (status_icon->priv->storage_type == GTK_IMAGE_EMPTY)
1195     status_icon->priv->image_data.stock_id = NULL;
1196
1197   return status_icon->priv->image_data.stock_id;
1198 }
1199
1200 /**
1201  * gtk_status_icon_get_icon_name:
1202  * @status_icon: a #GtkStatusIcon
1203  * 
1204  * Gets the name of the icon being displayed by the #GtkStatusIcon.
1205  * The storage type of the status icon must be %GTK_IMAGE_EMPTY or
1206  * %GTK_IMAGE_ICON_NAME (see gtk_status_icon_get_storage_type()).
1207  * The returned string is owned by the #GtkStatusIcon and should not
1208  * be freed or modified.
1209  * 
1210  * Return value: name of the displayed icon, or %NULL if the image is empty.
1211  *
1212  * Since: 2.10
1213  **/
1214 G_CONST_RETURN gchar *
1215 gtk_status_icon_get_icon_name (GtkStatusIcon *status_icon)
1216 {
1217   g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), NULL);
1218   g_return_val_if_fail (status_icon->priv->storage_type == GTK_IMAGE_ICON_NAME ||
1219                         status_icon->priv->storage_type == GTK_IMAGE_EMPTY, NULL);
1220
1221   if (status_icon->priv->storage_type == GTK_IMAGE_EMPTY)
1222     status_icon->priv->image_data.icon_name = NULL;
1223
1224   return status_icon->priv->image_data.icon_name;
1225 }
1226
1227 /**
1228  * gtk_status_icon_get_size:
1229  * @status_icon: a #GtkStatusIcon
1230  * 
1231  * Gets the size in pixels that is available for the image. 
1232  * Stock icons and named icons adapt their size automatically
1233  * if the size of the notification area changes. For other
1234  * storage types, the size-changed signal can be used to
1235  * react to size changes.
1236  * 
1237  * Return value: the size that is available for the image
1238  *
1239  * Since: 2.10
1240  **/
1241 gint
1242 gtk_status_icon_get_size (GtkStatusIcon *status_icon)
1243 {
1244   g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), 0);
1245
1246   return status_icon->priv->size;
1247 }
1248
1249 /**
1250  * gtk_status_icon_set_tooltip:
1251  * @status_icon: a #GtkStatusIcon
1252  * @tooltip_text: the tooltip text, or %NULL
1253  * 
1254  * Sets the tooltip of the status icon.
1255  * 
1256  * Since: 2.10
1257  **/ 
1258 void
1259 gtk_status_icon_set_tooltip (GtkStatusIcon *status_icon,
1260                              const gchar   *tooltip_text)
1261 {
1262   g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1263
1264 #ifdef GDK_WINDOWING_X11
1265   gtk_tooltips_set_tip (status_icon->priv->tooltips,
1266                         status_icon->priv->tray_icon,
1267                         tooltip_text, NULL);
1268 #endif
1269 #ifdef GDK_WINDOWING_WIN32
1270   if (tooltip_text == NULL)
1271     status_icon->priv->nid.uFlags &= ~NIF_TIP;
1272   else
1273     {
1274       WCHAR *wcs = g_utf8_to_utf16 (tooltip_text, -1, NULL, NULL, NULL);
1275
1276       status_icon->priv->nid.uFlags |= NIF_TIP;
1277       wcsncpy (status_icon->priv->nid.szTip, wcs,
1278                G_N_ELEMENTS (status_icon->priv->nid.szTip) - 1);
1279       status_icon->priv->nid.szTip[G_N_ELEMENTS (status_icon->priv->nid.szTip) - 1] = 0;
1280       g_free (wcs);
1281     }
1282   if (status_icon->priv->nid.hWnd != NULL && status_icon->priv->visible)
1283     if (!Shell_NotifyIconW (NIM_MODIFY, &status_icon->priv->nid))
1284       g_warning ("%s:%d:Shell_NotifyIconW(NIM_MODIFY) failed", __FILE__, __LINE__-1);
1285 #endif
1286 }
1287
1288 static gboolean
1289 gtk_status_icon_blinker (GtkStatusIcon *status_icon)
1290 {
1291   status_icon->priv->blink_off = !status_icon->priv->blink_off;
1292
1293   gtk_status_icon_update_image (status_icon);
1294
1295   return TRUE;
1296 }
1297
1298 static void
1299 gtk_status_icon_enable_blinking (GtkStatusIcon *status_icon)
1300 {
1301   if (!status_icon->priv->blinking_timeout)
1302     {
1303       gtk_status_icon_blinker (status_icon);
1304
1305       status_icon->priv->blinking_timeout =
1306         g_timeout_add (BLINK_TIMEOUT, 
1307                        (GSourceFunc) gtk_status_icon_blinker, 
1308                        status_icon);
1309     }
1310 }
1311
1312 static void
1313 gtk_status_icon_disable_blinking (GtkStatusIcon *status_icon)
1314 {
1315   if (status_icon->priv->blinking_timeout)
1316     {
1317       g_source_remove (status_icon->priv->blinking_timeout);
1318       status_icon->priv->blinking_timeout = 0;
1319       status_icon->priv->blink_off = FALSE;
1320
1321       gtk_status_icon_update_image (status_icon);
1322     }
1323 }
1324
1325 /**
1326  * gtk_status_icon_set_visible:
1327  * @status_icon: a #GtkStatusIcon
1328  * @visible: %TRUE to show the status icon, %FALSE to hide it
1329  * 
1330  * Shows or hides a status icon.
1331  *
1332  * Since: 2.10
1333  **/
1334 void
1335 gtk_status_icon_set_visible (GtkStatusIcon *status_icon,
1336                              gboolean       visible)
1337 {
1338   g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1339
1340   visible = visible != FALSE;
1341
1342   if (status_icon->priv->visible != visible)
1343     {
1344       status_icon->priv->visible = visible;
1345
1346 #ifdef GDK_WINDOWING_X11
1347       if (visible)
1348         gtk_widget_show (status_icon->priv->tray_icon);
1349       else
1350         gtk_widget_hide (status_icon->priv->tray_icon);
1351 #endif
1352 #ifdef GDK_WINDOWING_WIN32
1353       if (status_icon->priv->nid.hWnd != NULL)
1354         {
1355           if (visible)
1356             Shell_NotifyIconW (NIM_ADD, &status_icon->priv->nid);
1357           else
1358             Shell_NotifyIconW (NIM_DELETE, &status_icon->priv->nid);
1359         }
1360 #endif
1361       g_object_notify (G_OBJECT (status_icon), "visible");
1362     }
1363 }
1364
1365 /**
1366  * gtk_status_icon_get_visible:
1367  * @status_icon: a #GtkStatusIcon
1368  * 
1369  * Returns whether the status icon is visible or not. 
1370  * Note that being visible does not guarantee that 
1371  * the user can actually see the icon, see also 
1372  * gtk_status_icon_is_embedded().
1373  * 
1374  * Return value: %TRUE if the status icon is visible
1375  *
1376  * Since: 2.10
1377  **/
1378 gboolean
1379 gtk_status_icon_get_visible (GtkStatusIcon *status_icon)
1380 {
1381   g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), FALSE);
1382
1383   return status_icon->priv->visible;
1384 }
1385
1386 /**
1387  * gtk_status_icon_set_blinking:
1388  * @status_icon: a #GtkStatusIcon
1389  * @blinking: %TRUE to turn blinking on, %FALSE to turn it off
1390  * 
1391  * Makes the status icon start or stop blinking. 
1392  * Note that blinking user interface elements may be problematic
1393  * for some users, and thus may be turned off, in which case
1394  * this setting has no effect.
1395  *
1396  * Since: 2.10
1397  **/
1398 void
1399 gtk_status_icon_set_blinking (GtkStatusIcon *status_icon,
1400                               gboolean       blinking)
1401 {
1402   g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1403
1404   blinking = blinking != FALSE;
1405
1406   if (status_icon->priv->blinking != blinking)
1407     {
1408       status_icon->priv->blinking = blinking;
1409
1410       if (blinking)
1411         gtk_status_icon_enable_blinking (status_icon);
1412       else
1413         gtk_status_icon_disable_blinking (status_icon);
1414
1415       g_object_notify (G_OBJECT (status_icon), "blinking");
1416     }
1417 }
1418
1419 /**
1420  * gtk_status_icon_get_blinking:
1421  * @status_icon: a #GtkStatusIcon
1422  * 
1423  * Returns whether the icon is blinking, see 
1424  * gtk_status_icon_set_blinking().
1425  * 
1426  * Return value: %TRUE if the icon is blinking
1427  *
1428  * Since: 2.10
1429  **/
1430 gboolean
1431 gtk_status_icon_get_blinking (GtkStatusIcon *status_icon)
1432 {
1433   g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), FALSE);
1434
1435   return status_icon->priv->blinking;
1436 }
1437
1438 /**
1439  * gtk_status_icon_is_embedded:
1440  * @status_icon: a #GtkStatusIcon
1441  * 
1442  * Returns whether the status icon is embedded in a notification
1443  * area. 
1444  * 
1445  * Return value: %TRUE if the status icon is embedded in
1446  *   a notification area.
1447  *
1448  * Since: 2.10
1449  **/
1450 gboolean
1451 gtk_status_icon_is_embedded (GtkStatusIcon *status_icon)
1452 {
1453 #ifdef GDK_WINDOWING_X11
1454   GtkPlug *plug;
1455 #endif
1456
1457   g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), FALSE);
1458
1459 #ifdef GDK_WINDOWING_X11
1460   plug = GTK_PLUG (status_icon->priv->tray_icon);
1461
1462   if (plug->socket_window)
1463     return TRUE;
1464   else
1465     return FALSE;
1466 #endif
1467 #ifdef GDK_WINDOWING_WIN32
1468   return TRUE;
1469 #endif
1470 }
1471
1472 #define __GTK_STATUS_ICON_C__
1473 #include "gtkaliasdef.c"