]> Pileus Git - ~andy/gtk/blob - gtk/gtkstatusicon.c
#include "gtkmain.h" for gtk_get_current_event_time().
[~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  * Copyright (C) 2006 Imendio AB
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  *
23  * Authors:
24  *      Mark McLoughlin <mark@skynet.ie>
25  *      Hans Breuer <hans@breuer.org>
26  *      Tor Lillqvist <tml@novell.com>
27  *      Mikael Hallendal <micke@imendio.com>
28  */
29
30 #include <config.h>
31 #include <string.h>
32
33 #include "gtkstatusicon.h"
34
35 #include "gtkintl.h"
36 #include "gtkiconfactory.h"
37 #include "gtkmain.h"
38 #include "gtkmarshalers.h"
39 #include "gtktrayicon.h"
40
41 #include "gtkprivate.h"
42 #include "gtkwidget.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 #ifdef GDK_WINDOWING_QUARTZ
53 #include "gtkicontheme.h"
54 #include "gtklabel.h"
55 #endif  
56
57 #include "gdkkeysyms.h"
58
59 #include "gtkalias.h"
60
61 #define BLINK_TIMEOUT 500
62
63 enum
64 {
65   PROP_0,
66   PROP_PIXBUF,
67   PROP_FILE,
68   PROP_STOCK,
69   PROP_ICON_NAME,
70   PROP_STORAGE_TYPE,
71   PROP_SIZE,
72   PROP_SCREEN,
73   PROP_VISIBLE,
74   PROP_ORIENTATION,
75   PROP_EMBEDDED,
76   PROP_BLINKING
77 };
78
79 enum 
80 {
81   ACTIVATE_SIGNAL,
82   POPUP_MENU_SIGNAL,
83   SIZE_CHANGED_SIGNAL,
84   LAST_SIGNAL
85 };
86
87 static guint status_icon_signals [LAST_SIGNAL] = { 0 };
88
89 #ifdef GDK_WINDOWING_QUARTZ
90 #include "gtkstatusicon-quartz.c"
91 #endif
92
93 struct _GtkStatusIconPrivate
94 {
95 #ifdef GDK_WINDOWING_X11
96   GtkWidget    *tray_icon;
97   GtkWidget    *image;
98 #endif
99
100 #ifdef GDK_WINDOWING_WIN32
101   GtkWidget     *dummy_widget;
102   NOTIFYICONDATAW nid;
103   gint          last_click_x, last_click_y;
104   GtkOrientation orientation;
105 #endif
106         
107 #ifdef GDK_WINDOWING_QUARTZ
108   GtkWidget     *dummy_widget;
109   GtkQuartzStatusIcon *status_item;
110 #endif
111
112   gint          size;
113
114   gint          image_width;
115   gint          image_height;
116
117   GtkImageType  storage_type;
118
119   union
120     {
121       GdkPixbuf *pixbuf;
122       gchar     *stock_id;
123       gchar     *icon_name;
124     } image_data;
125
126   GdkPixbuf    *blank_icon;
127   guint         blinking_timeout;
128
129   guint         blinking : 1;
130   guint         blink_off : 1;
131   guint         visible : 1;
132 };
133
134 static GObject* gtk_status_icon_constructor      (GType                  type,
135                                                   guint                  n_construct_properties,
136                                                   GObjectConstructParam *construct_params);
137 static void     gtk_status_icon_finalize         (GObject        *object);
138 static void     gtk_status_icon_set_property     (GObject        *object,
139                                                   guint           prop_id,
140                                                   const GValue   *value,
141                                                   GParamSpec     *pspec);
142 static void     gtk_status_icon_get_property     (GObject        *object,
143                                                   guint           prop_id,
144                                                   GValue         *value,
145                                                   GParamSpec     *pspec);
146
147 #ifdef GDK_WINDOWING_X11
148 static void     gtk_status_icon_size_allocate    (GtkStatusIcon  *status_icon,
149                                                   GtkAllocation  *allocation);
150 static void     gtk_status_icon_screen_changed   (GtkStatusIcon  *status_icon,
151                                                   GdkScreen      *old_screen);
152 static void     gtk_status_icon_embedded_changed (GtkStatusIcon *status_icon);
153 static void     gtk_status_icon_orientation_changed (GtkStatusIcon *status_icon);
154
155 #endif
156 static gboolean gtk_status_icon_key_press        (GtkStatusIcon  *status_icon,
157                                                   GdkEventKey    *event);
158 static void     gtk_status_icon_popup_menu       (GtkStatusIcon  *status_icon);
159 static gboolean gtk_status_icon_button_press     (GtkStatusIcon  *status_icon,
160                                                   GdkEventButton *event);
161 static void     gtk_status_icon_disable_blinking (GtkStatusIcon  *status_icon);
162 static void     gtk_status_icon_reset_image_data (GtkStatusIcon  *status_icon);
163                                            
164
165 G_DEFINE_TYPE (GtkStatusIcon, gtk_status_icon, G_TYPE_OBJECT)
166
167 static void
168 gtk_status_icon_class_init (GtkStatusIconClass *class)
169 {
170   GObjectClass *gobject_class = (GObjectClass *) class;
171
172   gobject_class->constructor  = gtk_status_icon_constructor;
173   gobject_class->finalize     = gtk_status_icon_finalize;
174   gobject_class->set_property = gtk_status_icon_set_property;
175   gobject_class->get_property = gtk_status_icon_get_property;
176
177   g_object_class_install_property (gobject_class,
178                                    PROP_PIXBUF,
179                                    g_param_spec_object ("pixbuf",
180                                                         P_("Pixbuf"),
181                                                         P_("A GdkPixbuf to display"),
182                                                         GDK_TYPE_PIXBUF,
183                                                         GTK_PARAM_READWRITE));
184
185   g_object_class_install_property (gobject_class,
186                                    PROP_FILE,
187                                    g_param_spec_string ("file",
188                                                         P_("Filename"),
189                                                         P_("Filename to load and display"),
190                                                         NULL,
191                                                         GTK_PARAM_WRITABLE));
192
193   g_object_class_install_property (gobject_class,
194                                    PROP_STOCK,
195                                    g_param_spec_string ("stock",
196                                                         P_("Stock ID"),
197                                                         P_("Stock ID for a stock image to display"),
198                                                         NULL,
199                                                         GTK_PARAM_READWRITE));
200   
201   g_object_class_install_property (gobject_class,
202                                    PROP_ICON_NAME,
203                                    g_param_spec_string ("icon-name",
204                                                         P_("Icon Name"),
205                                                         P_("The name of the icon from the icon theme"),
206                                                         NULL,
207                                                         GTK_PARAM_READWRITE));
208   
209   g_object_class_install_property (gobject_class,
210                                    PROP_STORAGE_TYPE,
211                                    g_param_spec_enum ("storage-type",
212                                                       P_("Storage type"),
213                                                       P_("The representation being used for image data"),
214                                                       GTK_TYPE_IMAGE_TYPE,
215                                                       GTK_IMAGE_EMPTY,
216                                                       GTK_PARAM_READABLE));
217
218   g_object_class_install_property (gobject_class,
219                                    PROP_SIZE,
220                                    g_param_spec_int ("size",
221                                                      P_("Size"),
222                                                      P_("The size of the icon"),
223                                                      0,
224                                                      G_MAXINT,
225                                                      0,
226                                                      GTK_PARAM_READABLE));
227
228   g_object_class_install_property (gobject_class,
229                                    PROP_SCREEN,
230                                    g_param_spec_object ("screen",
231                                                         P_("Screen"),
232                                                         P_("The screen where this status icon will be displayed"),
233                                                         GDK_TYPE_SCREEN,
234                                                         GTK_PARAM_READWRITE));
235
236   g_object_class_install_property (gobject_class,
237                                    PROP_BLINKING,
238                                    g_param_spec_boolean ("blinking",
239                                                          P_("Blinking"),
240                                                          P_("Whether or not the status icon is blinking"),
241                                                          FALSE,
242                                                          GTK_PARAM_READWRITE));
243
244   g_object_class_install_property (gobject_class,
245                                    PROP_VISIBLE,
246                                    g_param_spec_boolean ("visible",
247                                                          P_("Visible"),
248                                                          P_("Whether or not the status icon is visible"),
249                                                          TRUE,
250                                                          GTK_PARAM_READWRITE));
251
252
253   /**
254    * GtkStatusIcon:embedded: 
255    *
256    * %TRUE if the statusicon is embedded in a notification area.
257    *
258    * Since: 2.12
259    */
260   g_object_class_install_property (gobject_class,
261                                    PROP_EMBEDDED,
262                                    g_param_spec_boolean ("embedded",
263                                                          P_("Embedded"),
264                                                          P_("Whether or not the status icon is embedded"),
265                                                          FALSE,
266                                                          GTK_PARAM_READABLE));
267
268   /**
269    * GtkStatusIcon:orientation:
270    *
271    * The orientation of the tray in which the statusicon 
272    * is embedded. 
273    *
274    * Since: 2.12
275    */
276   g_object_class_install_property (gobject_class,
277                                    PROP_ORIENTATION,
278                                    g_param_spec_enum ("orientation",
279                                                       P_("Orientation"),
280                                                       P_("The orientation of the tray"),
281                                                       GTK_TYPE_ORIENTATION,
282                                                       GTK_ORIENTATION_HORIZONTAL,
283                                                       GTK_PARAM_READABLE));
284
285
286   /**
287    * GtkStatusIcon::activate:
288    * @status_icon: the object which received the signal
289    *
290    * Gets emitted when the user activates the status icon. 
291    * If and how status icons can activated is platform-dependent.
292    *
293    * Since: 2.10
294    */
295   status_icon_signals [ACTIVATE_SIGNAL] =
296     g_signal_new (I_("activate"),
297                   G_TYPE_FROM_CLASS (gobject_class),
298                   G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
299                   G_STRUCT_OFFSET (GtkStatusIconClass, activate),
300                   NULL,
301                   NULL,
302                   g_cclosure_marshal_VOID__VOID,
303                   G_TYPE_NONE,
304                   0);
305
306   /**
307    * GtkStatusIcon::popup-menu:
308    * @status_icon: the object which received the signal
309    * @button: the button that was pressed, or 0 if the 
310    *   signal is not emitted in response to a button press event
311    * @activate_time: the timestamp of the event that
312    *   triggered the signal emission
313    *
314    * Gets emitted when the user brings up the context menu
315    * of the status icon. Whether status icons can have context 
316    * menus and how these are activated is platform-dependent.
317    *
318    * The @button and @activate_timeout parameters should be 
319    * passed as the last to arguments to gtk_menu_popup().
320    *
321    * Since: 2.10
322    */
323   status_icon_signals [POPUP_MENU_SIGNAL] =
324     g_signal_new (I_("popup_menu"),
325                   G_TYPE_FROM_CLASS (gobject_class),
326                   G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
327                   G_STRUCT_OFFSET (GtkStatusIconClass, popup_menu),
328                   NULL,
329                   NULL,
330                   _gtk_marshal_VOID__UINT_UINT,
331                   G_TYPE_NONE,
332                   2,
333                   G_TYPE_UINT,
334                   G_TYPE_UINT);
335
336   /**
337    * GtkStatusIcon::size-changed:
338    * @status_icon: the object which received the signal
339    * @size: the new size
340    *
341    * Gets emitted when the size available for the image
342    * changes, e.g. because the notification area got resized.
343    *
344    * Return value: %TRUE if the icon was updated for the new
345    * size. Otherwise, GTK+ will scale the icon as necessary.
346    *
347    * Since: 2.10
348    */
349   status_icon_signals [SIZE_CHANGED_SIGNAL] =
350     g_signal_new (I_("size_changed"),
351                   G_TYPE_FROM_CLASS (gobject_class),
352                   G_SIGNAL_RUN_LAST,
353                   G_STRUCT_OFFSET (GtkStatusIconClass, size_changed),
354                   g_signal_accumulator_true_handled,
355                   NULL,
356                   _gtk_marshal_BOOLEAN__INT,
357                   G_TYPE_BOOLEAN,
358                   1,
359                   G_TYPE_INT);
360
361   g_type_class_add_private (class, sizeof (GtkStatusIconPrivate));
362 }
363
364 #ifdef GDK_WINDOWING_WIN32
365
366 static void
367 build_button_event (GtkStatusIconPrivate *priv,
368                     GdkEventButton       *e,
369                     guint                 button)
370 {
371   POINT pos;
372   GdkRectangle monitor0;
373
374   /* We know that gdk/win32 puts the primary monitor at index 0 */
375   gdk_screen_get_monitor_geometry (gdk_screen_get_default (), 0, &monitor0);
376   e->window = g_object_ref (gdk_get_default_root_window ());
377   e->send_event = TRUE;
378   e->time = GetTickCount ();
379   GetCursorPos (&pos);
380   priv->last_click_x = e->x = pos.x + monitor0.x;
381   priv->last_click_y = e->y = pos.y + monitor0.y;
382   e->axes = NULL;
383   e->state = 0;
384   e->button = button;
385   e->device = gdk_display_get_default ()->core_pointer;
386   e->x_root = e->x;
387   e->y_root = e->y;
388 }
389
390 typedef struct
391 {
392   GtkStatusIcon *status_icon;
393   GdkEventButton *event;
394 } ButtonCallbackData;
395
396 static gboolean
397 button_callback (gpointer data)
398 {
399   ButtonCallbackData *bc = (ButtonCallbackData *) data;
400
401   gtk_status_icon_button_press (bc->status_icon, bc->event);
402
403   gdk_event_free ((GdkEvent *) bc->event);
404   g_free (data);
405
406   return FALSE;
407 }
408
409 static LRESULT CALLBACK
410 wndproc (HWND   hwnd,
411          UINT   message,
412          WPARAM wparam,
413          LPARAM lparam)
414 {
415   if (message == WM_GTK_TRAY_NOTIFICATION)
416     {
417       ButtonCallbackData *bc;
418       
419       switch (lparam)
420         {
421         case WM_LBUTTONDOWN:
422         case WM_RBUTTONDOWN:
423           bc = g_new (ButtonCallbackData, 1);
424           bc->event = (GdkEventButton *) gdk_event_new (GDK_BUTTON_PRESS);
425           bc->status_icon = GTK_STATUS_ICON (wparam);
426           build_button_event (bc->status_icon->priv, bc->event, (lparam == WM_LBUTTONDOWN) ? 1 : 3);
427           g_idle_add (button_callback, bc);
428           break;
429         default :
430           break;
431         }
432         return 0;
433     }
434   else
435     {
436       return DefWindowProc (hwnd, message, wparam, lparam);
437     }
438 }
439
440 static HWND
441 create_tray_observer (void)
442 {
443   WNDCLASS    wclass;
444   static HWND hwnd = NULL;
445   ATOM        klass;
446   HINSTANCE   hmodule = GetModuleHandle (NULL);
447
448   if (hwnd)
449     return hwnd;
450
451   memset (&wclass, 0, sizeof(WNDCLASS));
452   wclass.lpszClassName = "gtkstatusicon-observer";
453   wclass.lpfnWndProc   = wndproc;
454   wclass.hInstance     = hmodule;
455
456   klass = RegisterClass (&wclass);
457   if (!klass)
458     return NULL;
459
460   hwnd = CreateWindow (MAKEINTRESOURCE(klass),
461                        NULL, WS_POPUP,
462                        0, 0, 1, 1, NULL, NULL,
463                        hmodule, NULL);
464   if (!hwnd)
465     {
466       UnregisterClass (MAKEINTRESOURCE(klass), hmodule);
467       return NULL;
468     }
469
470   return hwnd;
471 }
472
473 #endif
474
475 static void
476 gtk_status_icon_init (GtkStatusIcon *status_icon)
477 {
478   GtkStatusIconPrivate *priv;
479
480   priv = G_TYPE_INSTANCE_GET_PRIVATE (status_icon, GTK_TYPE_STATUS_ICON,
481                                       GtkStatusIconPrivate);
482   status_icon->priv = priv;
483   
484   priv->storage_type = GTK_IMAGE_EMPTY;
485   priv->visible      = TRUE;
486
487 #ifdef GDK_WINDOWING_X11
488   priv->size         = 0;
489   priv->image_width  = 0;
490   priv->image_height = 0;
491
492   priv->tray_icon = GTK_WIDGET (_gtk_tray_icon_new (NULL));
493
494   gtk_widget_add_events (GTK_WIDGET (priv->tray_icon),
495                          GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
496
497   g_signal_connect_swapped (priv->tray_icon, "key-press-event",
498                             G_CALLBACK (gtk_status_icon_key_press), status_icon);
499   g_signal_connect_swapped (priv->tray_icon, "popup-menu",
500                             G_CALLBACK (gtk_status_icon_popup_menu), status_icon);
501   g_signal_connect_swapped (priv->tray_icon, "notify::embedded",
502                             G_CALLBACK (gtk_status_icon_embedded_changed), status_icon);
503   g_signal_connect_swapped (priv->tray_icon, "notify::orientation",
504                             G_CALLBACK (gtk_status_icon_orientation_changed), status_icon);
505   g_signal_connect_swapped (priv->tray_icon, "button-press-event",
506                             G_CALLBACK (gtk_status_icon_button_press), status_icon);
507   g_signal_connect_swapped (priv->tray_icon, "screen-changed",
508                             G_CALLBACK (gtk_status_icon_screen_changed), status_icon);
509   priv->image = gtk_image_new ();
510   GTK_WIDGET_SET_FLAGS (priv->image, GTK_CAN_FOCUS);
511   gtk_container_add (GTK_CONTAINER (priv->tray_icon), priv->image);
512   gtk_widget_show (priv->image);
513
514   g_signal_connect_swapped (priv->image, "size-allocate",
515                             G_CALLBACK (gtk_status_icon_size_allocate), status_icon);
516
517 #endif
518
519 #ifdef GDK_WINDOWING_WIN32
520
521   /* Get position and orientation of Windows taskbar. */
522   {
523     APPBARDATA abd;
524     
525     abd.cbSize = sizeof (abd);
526     SHAppBarMessage (ABM_GETTASKBARPOS, &abd);
527     if (abd.rc.bottom - abd.rc.top > abd.rc.right - abd.rc.left)
528       priv->orientation = GTK_ORIENTATION_VERTICAL;
529     else
530       priv->orientation = GTK_ORIENTATION_HORIZONTAL;
531   }
532
533   priv->last_click_x = priv->last_click_y = 0;
534
535   /* Are the system tray icons always 16 pixels square? */
536   priv->size         = 16;
537   priv->image_width  = 16;
538   priv->image_height = 16;
539
540   priv->dummy_widget = gtk_label_new ("");
541
542   memset (&priv->nid, 0, sizeof (priv->nid));
543
544   priv->nid.hWnd = create_tray_observer ();
545   priv->nid.uID = GPOINTER_TO_UINT (status_icon);
546   priv->nid.uCallbackMessage = WM_GTK_TRAY_NOTIFICATION;
547   priv->nid.uFlags = NIF_MESSAGE;
548
549   if (!Shell_NotifyIconW (NIM_ADD, &priv->nid))
550     {
551       g_warning ("%s:%d:Shell_NotifyIcon(NIM_ADD) failed", __FILE__, __LINE__-2);
552       priv->nid.hWnd = NULL;
553     }
554 #endif
555         
556 #ifdef GDK_WINDOWING_QUARTZ
557   priv->dummy_widget = gtk_label_new ("");
558
559   QUARTZ_POOL_ALLOC;
560
561   priv->status_item = [[GtkQuartzStatusIcon alloc] initWithStatusIcon:status_icon];
562
563   priv->image_width = priv->image_height = [priv->status_item getHeight];
564   priv->size = priv->image_height;
565
566   QUARTZ_POOL_RELEASE;
567
568 #endif 
569 }
570
571 static GObject*
572 gtk_status_icon_constructor (GType                  type,
573                              guint                  n_construct_properties,
574                              GObjectConstructParam *construct_params)
575 {
576   GObject *object;
577   GtkStatusIcon *status_icon;
578   GtkStatusIconPrivate *priv;
579   
580   object = G_OBJECT_CLASS (gtk_status_icon_parent_class)->constructor (type,
581                                                                        n_construct_properties,
582                                                                        construct_params);
583
584 #ifdef GDK_WINDOWING_X11
585   status_icon = GTK_STATUS_ICON (object);
586   priv = status_icon->priv;
587   
588   if (priv->visible)
589     gtk_widget_show (priv->tray_icon);
590 #endif
591
592   return object;
593 }
594
595 static void
596 gtk_status_icon_finalize (GObject *object)
597 {
598   GtkStatusIcon *status_icon = GTK_STATUS_ICON (object);
599   GtkStatusIconPrivate *priv = status_icon->priv;
600
601   gtk_status_icon_disable_blinking (status_icon);
602   
603   gtk_status_icon_reset_image_data (status_icon);
604
605   if (priv->blank_icon)
606     g_object_unref (priv->blank_icon);
607   priv->blank_icon = NULL;
608
609 #ifdef GDK_WINDOWING_X11
610   gtk_widget_destroy (priv->tray_icon);
611 #endif
612
613 #ifdef GDK_WINDOWING_WIN32
614   if (priv->nid.hWnd != NULL && priv->visible)
615     Shell_NotifyIconW (NIM_DELETE, &priv->nid);
616   if (priv->nid.hIcon)
617     DestroyIcon (priv->nid.hIcon);
618
619   gtk_widget_destroy (priv->dummy_widget);
620 #endif
621         
622 #ifdef GDK_WINDOWING_QUARTZ
623   QUARTZ_POOL_ALLOC;
624   [priv->status_item release];
625   QUARTZ_POOL_RELEASE;
626 #endif
627
628   G_OBJECT_CLASS (gtk_status_icon_parent_class)->finalize (object);
629 }
630
631 static void
632 gtk_status_icon_set_property (GObject      *object,
633                               guint         prop_id,
634                               const GValue *value,
635                               GParamSpec   *pspec)
636 {
637   GtkStatusIcon *status_icon = GTK_STATUS_ICON (object);
638
639   switch (prop_id)
640     {
641     case PROP_PIXBUF:
642       gtk_status_icon_set_from_pixbuf (status_icon, g_value_get_object (value));
643       break;
644     case PROP_FILE:
645       gtk_status_icon_set_from_file (status_icon, g_value_get_string (value));
646       break;
647     case PROP_STOCK:
648       gtk_status_icon_set_from_stock (status_icon, g_value_get_string (value));
649       break;
650     case PROP_ICON_NAME:
651       gtk_status_icon_set_from_icon_name (status_icon, g_value_get_string (value));
652       break;
653     case PROP_SCREEN:
654       gtk_status_icon_set_screen (status_icon, g_value_get_object (value));
655       break;
656     case PROP_BLINKING:
657       gtk_status_icon_set_blinking (status_icon, g_value_get_boolean (value));
658       break;
659     case PROP_VISIBLE:
660       gtk_status_icon_set_visible (status_icon, g_value_get_boolean (value));
661       break;
662     default:
663       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
664       break;
665     }
666 }
667
668 static void
669 gtk_status_icon_get_property (GObject    *object,
670                               guint       prop_id,
671                               GValue     *value,
672                               GParamSpec *pspec)
673 {
674   GtkStatusIcon *status_icon = GTK_STATUS_ICON (object);
675   GtkStatusIconPrivate *priv = status_icon->priv;
676
677   /* The "getter" functions whine if you try to get the wrong
678    * storage type. This function is instead robust against that,
679    * so that GUI builders don't have to jump through hoops
680    * to avoid g_warning
681    */
682
683   switch (prop_id)
684     {
685     case PROP_PIXBUF:
686       if (priv->storage_type != GTK_IMAGE_PIXBUF)
687         g_value_set_object (value, NULL);
688       else
689         g_value_set_object (value, gtk_status_icon_get_pixbuf (status_icon));
690       break;
691     case PROP_STOCK:
692       if (priv->storage_type != GTK_IMAGE_STOCK)
693         g_value_set_string (value, NULL);
694       else
695         g_value_set_string (value, gtk_status_icon_get_stock (status_icon));
696       break;
697     case PROP_ICON_NAME:
698       if (priv->storage_type != GTK_IMAGE_ICON_NAME)
699         g_value_set_string (value, NULL);
700       else
701         g_value_set_string (value, gtk_status_icon_get_icon_name (status_icon));
702       break;
703     case PROP_STORAGE_TYPE:
704       g_value_set_enum (value, gtk_status_icon_get_storage_type (status_icon));
705       break;
706     case PROP_SIZE:
707       g_value_set_int (value, gtk_status_icon_get_size (status_icon));
708       break;
709     case PROP_SCREEN:
710       g_value_set_object (value, gtk_status_icon_get_screen (status_icon));
711       break;
712     case PROP_BLINKING:
713       g_value_set_boolean (value, gtk_status_icon_get_blinking (status_icon));
714       break;
715     case PROP_VISIBLE:
716       g_value_set_boolean (value, gtk_status_icon_get_visible (status_icon));
717       break;
718     case PROP_EMBEDDED:
719       g_value_set_boolean (value, gtk_status_icon_is_embedded (status_icon));
720       break;
721     case PROP_ORIENTATION:
722 #ifdef GDK_WINDOWING_X11
723       g_value_set_enum (value, _gtk_tray_icon_get_orientation (GTK_TRAY_ICON (status_icon->priv->tray_icon)));
724 #endif
725 #ifdef GDK_WINDOWING_WIN32
726       g_value_set_enum (value, status_icon->priv->orientation);
727 #endif
728       break;
729     default:
730       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
731       break;
732     }
733 }
734
735 /**
736  * gtk_status_icon_new:
737  * 
738  * Creates an empty status icon object.
739  * 
740  * Return value: a new #GtkStatusIcon
741  *
742  * Since: 2.10
743  **/
744 GtkStatusIcon *
745 gtk_status_icon_new (void)
746 {
747   return g_object_new (GTK_TYPE_STATUS_ICON, NULL);
748 }
749
750 /**
751  * gtk_status_icon_new_from_pixbuf:
752  * @pixbuf: a #GdkPixbuf
753  * 
754  * Creates a status icon displaying @pixbuf. 
755  *
756  * The image will be scaled down to fit in the available 
757  * space in the notification area, if necessary.
758  * 
759  * Return value: a new #GtkStatusIcon
760  *
761  * Since: 2.10
762  **/
763 GtkStatusIcon *
764 gtk_status_icon_new_from_pixbuf (GdkPixbuf *pixbuf)
765 {
766   return g_object_new (GTK_TYPE_STATUS_ICON,
767                        "pixbuf", pixbuf,
768                        NULL);
769 }
770
771 /**
772  * gtk_status_icon_new_from_file:
773  * @filename: a filename
774  * 
775  * Creates a status icon displaying the file @filename. 
776  *
777  * The image will be scaled down to fit in the available 
778  * space in the notification area, if necessary.
779  * 
780  * Return value: a new #GtkStatusIcon
781  *
782  * Since: 2.10
783  **/
784 GtkStatusIcon *
785 gtk_status_icon_new_from_file (const gchar *filename)
786 {
787   return g_object_new (GTK_TYPE_STATUS_ICON,
788                        "file", filename,
789                        NULL);
790 }
791
792 /**
793  * gtk_status_icon_new_from_stock:
794  * @stock_id: a stock icon id
795  * 
796  * Creates a status icon displaying a stock icon. Sample stock icon
797  * names are #GTK_STOCK_OPEN, #GTK_STOCK_QUIT. You can register your 
798  * own stock icon names, see gtk_icon_factory_add_default() and 
799  * gtk_icon_factory_add(). 
800  *
801  * Return value: a new #GtkStatusIcon
802  *
803  * Since: 2.10
804  **/
805 GtkStatusIcon *
806 gtk_status_icon_new_from_stock (const gchar *stock_id)
807 {
808   return g_object_new (GTK_TYPE_STATUS_ICON,
809                        "stock", stock_id,
810                        NULL);
811 }
812
813 /**
814  * gtk_status_icon_new_from_icon_name:
815  * @icon_name: an icon name
816  * 
817  * Creates a status icon displaying an icon from the current icon theme.
818  * If the current icon theme is changed, the icon will be updated 
819  * appropriately.
820  * 
821  * Return value: a new #GtkStatusIcon
822  *
823  * Since: 2.10
824  **/
825 GtkStatusIcon *
826 gtk_status_icon_new_from_icon_name (const gchar *icon_name)
827 {
828   return g_object_new (GTK_TYPE_STATUS_ICON,
829                        "icon-name", icon_name,
830                        NULL);
831 }
832
833 static void
834 emit_activate_signal (GtkStatusIcon *status_icon)
835 {
836   g_signal_emit (status_icon,
837                  status_icon_signals [ACTIVATE_SIGNAL], 0);
838 }
839
840 static void
841 emit_popup_menu_signal (GtkStatusIcon *status_icon,
842                         guint          button,
843                         guint32        activate_time)
844 {
845   g_signal_emit (status_icon,
846                  status_icon_signals [POPUP_MENU_SIGNAL], 0,
847                  button,
848                  activate_time);
849 }
850
851 #ifdef GDK_WINDOWING_X11
852
853 static gboolean
854 emit_size_changed_signal (GtkStatusIcon *status_icon,
855                           gint           size)
856 {
857   gboolean handled = FALSE;
858   
859   g_signal_emit (status_icon,
860                  status_icon_signals [SIZE_CHANGED_SIGNAL], 0,
861                  size,
862                  &handled);
863
864   return handled;
865 }
866
867 #endif
868
869 static GdkPixbuf *
870 gtk_status_icon_blank_icon (GtkStatusIcon *status_icon)
871 {
872   GtkStatusIconPrivate *priv = status_icon->priv;
873
874   if (priv->blank_icon)
875     {
876       gint width, height;
877
878       width  = gdk_pixbuf_get_width (priv->blank_icon);
879       height = gdk_pixbuf_get_height (priv->blank_icon);
880
881
882       if (width == priv->image_width && height == priv->image_height)
883         return priv->blank_icon;
884       else
885         {
886           g_object_unref (priv->blank_icon);
887           priv->blank_icon = NULL;
888         }
889     }
890
891   priv->blank_icon = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
892                                      priv->image_width, 
893                                      priv->image_height);
894   if (priv->blank_icon)
895     gdk_pixbuf_fill (priv->blank_icon, 0);
896
897   return priv->blank_icon;
898 }
899
900 #ifdef GDK_WINDOWING_X11
901
902 static GtkIconSize
903 find_icon_size (GtkWidget *widget, 
904                 gint       pixel_size)
905 {
906   GdkScreen *screen;
907   GtkSettings *settings;
908   GtkIconSize s, size;
909   gint w, h, d, dist;
910
911   screen = gtk_widget_get_screen (widget);
912
913   if (!screen)
914     return GTK_ICON_SIZE_MENU;
915
916   settings = gtk_settings_get_for_screen (screen);
917   
918   dist = G_MAXINT;
919   size = GTK_ICON_SIZE_MENU;
920
921   for (s = GTK_ICON_SIZE_MENU; s < GTK_ICON_SIZE_DIALOG; s++)
922     {
923       if (gtk_icon_size_lookup_for_settings (settings, s, &w, &h) &&
924           w <= pixel_size && h <= pixel_size)
925         {
926           d = MAX (pixel_size - w, pixel_size - h);
927           if (d < dist)
928             {
929               dist = d;
930               size = s;
931             }
932         }
933     }
934   
935   return size;
936 }
937
938 #endif
939
940 static void
941 gtk_status_icon_update_image (GtkStatusIcon *status_icon)
942 {
943   GtkStatusIconPrivate *priv = status_icon->priv;
944 #ifdef GDK_WINDOWING_WIN32
945   HICON prev_hicon;
946 #endif
947
948   if (priv->blink_off)
949     {
950 #ifdef GDK_WINDOWING_X11
951       gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image),
952                                  gtk_status_icon_blank_icon (status_icon));
953 #endif
954 #ifdef GDK_WINDOWING_WIN32
955       prev_hicon = priv->nid.hIcon;
956       priv->nid.hIcon = gdk_win32_pixbuf_to_hicon_libgtk_only (gtk_status_icon_blank_icon (status_icon));
957       priv->nid.uFlags |= NIF_ICON;
958       if (priv->nid.hWnd != NULL && priv->visible)
959         if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
960           g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
961       if (prev_hicon)
962         DestroyIcon (prev_hicon);
963 #endif
964 #ifdef GDK_WINDOWING_QUARTZ
965       QUARTZ_POOL_ALLOC;
966       [priv->status_item setImage:gtk_status_icon_blank_icon (status_icon)];
967       QUARTZ_POOL_RELEASE;
968 #endif
969       return;
970     }
971
972   switch (priv->storage_type)
973     {
974     case GTK_IMAGE_PIXBUF:
975       {
976         GdkPixbuf *pixbuf;
977
978         pixbuf = priv->image_data.pixbuf;
979
980         if (pixbuf)
981           {
982             GdkPixbuf *scaled;
983             gint size;
984             gint width;
985             gint height;
986
987             size = priv->size;
988
989             width  = gdk_pixbuf_get_width  (pixbuf);
990             height = gdk_pixbuf_get_height (pixbuf);
991
992             if (width > size || height > size)
993               scaled = gdk_pixbuf_scale_simple (pixbuf,
994                                                 MIN (size, width),
995                                                 MIN (size, height),
996                                                 GDK_INTERP_BILINEAR);
997             else
998               scaled = g_object_ref (pixbuf);
999
1000 #ifdef GDK_WINDOWING_X11
1001             gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), scaled);
1002 #endif
1003 #ifdef GDK_WINDOWING_WIN32
1004             prev_hicon = priv->nid.hIcon;
1005             priv->nid.hIcon = gdk_win32_pixbuf_to_hicon_libgtk_only (scaled);
1006             priv->nid.uFlags |= NIF_ICON;
1007             if (priv->nid.hWnd != NULL && priv->visible)
1008               if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
1009                   g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
1010             if (prev_hicon)
1011               DestroyIcon (prev_hicon);
1012 #endif
1013 #ifdef GDK_WINDOWING_QUARTZ
1014       QUARTZ_POOL_ALLOC;
1015       [priv->status_item setImage:scaled];
1016       QUARTZ_POOL_RELEASE;
1017 #endif
1018                         
1019             g_object_unref (scaled);
1020           }
1021         else
1022           {
1023 #ifdef GDK_WINDOWING_X11
1024             gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), NULL);
1025 #endif
1026 #ifdef GDK_WINDOWING_WIN32
1027             priv->nid.uFlags &= ~NIF_ICON;
1028             if (priv->nid.hWnd != NULL && priv->visible)
1029               if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
1030                 g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
1031 #endif
1032 #ifdef GDK_WINDOWING_QUARTZ
1033       [priv->status_item setImage:NULL];
1034 #endif
1035           }
1036       }
1037       break;
1038
1039     case GTK_IMAGE_STOCK:
1040       {
1041 #ifdef GDK_WINDOWING_X11
1042         GtkIconSize size = find_icon_size (priv->image, priv->size);
1043         gtk_image_set_from_stock (GTK_IMAGE (priv->image),
1044                                   priv->image_data.stock_id,
1045                                   size);
1046 #endif
1047 #ifdef GDK_WINDOWING_WIN32
1048         {
1049           GdkPixbuf *pixbuf =
1050             gtk_widget_render_icon (priv->dummy_widget,
1051                                     priv->image_data.stock_id,
1052                                     GTK_ICON_SIZE_SMALL_TOOLBAR,
1053                                     NULL);
1054
1055           prev_hicon = priv->nid.hIcon;
1056           priv->nid.hIcon = gdk_win32_pixbuf_to_hicon_libgtk_only (pixbuf);
1057           priv->nid.uFlags |= NIF_ICON;
1058           if (priv->nid.hWnd != NULL && priv->visible)
1059             if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
1060               g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
1061           if (prev_hicon)
1062             DestroyIcon (prev_hicon);
1063           g_object_unref (pixbuf);
1064         }
1065 #endif
1066 #ifdef GDK_WINDOWING_QUARTZ
1067         {
1068           GdkPixbuf *pixbuf;
1069
1070           pixbuf = gtk_widget_render_icon (priv->dummy_widget,
1071                                            priv->image_data.stock_id,
1072                                            GTK_ICON_SIZE_SMALL_TOOLBAR,
1073                                            NULL);
1074           QUARTZ_POOL_ALLOC;
1075           [priv->status_item setImage:pixbuf];
1076           QUARTZ_POOL_RELEASE;
1077           g_object_unref (pixbuf);
1078         }       
1079 #endif
1080       }
1081       break;
1082       
1083     case GTK_IMAGE_ICON_NAME:
1084       {
1085 #ifdef GDK_WINDOWING_X11
1086         GtkIconSize size = find_icon_size (priv->image, priv->size);
1087         gtk_image_set_from_icon_name (GTK_IMAGE (priv->image),
1088                                       priv->image_data.icon_name,
1089                                       size);
1090 #endif
1091 #ifdef GDK_WINDOWING_WIN32
1092         {
1093           GdkPixbuf *pixbuf =
1094             gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
1095                                       priv->image_data.icon_name,
1096                                       priv->size,
1097                                       0, NULL);
1098           
1099           prev_hicon = priv->nid.hIcon;
1100           priv->nid.hIcon = gdk_win32_pixbuf_to_hicon_libgtk_only (pixbuf);
1101           priv->nid.uFlags |= NIF_ICON;
1102           if (priv->nid.hWnd != NULL && priv->visible)
1103             if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
1104               g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
1105           if (prev_hicon)
1106             DestroyIcon (prev_hicon);
1107           g_object_unref (pixbuf);
1108         }
1109 #endif
1110 #ifdef GDK_WINDOWING_QUARTZ
1111         {
1112           GdkPixbuf *pixbuf;
1113
1114           pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
1115                                              priv->image_data.icon_name,
1116                                              priv->size,
1117                                              0, NULL);
1118
1119           QUARTZ_POOL_ALLOC;
1120           [priv->status_item setImage:pixbuf];
1121           QUARTZ_POOL_RELEASE;
1122           g_object_unref (pixbuf);
1123         }
1124 #endif
1125         
1126       }
1127       break;
1128       
1129     case GTK_IMAGE_EMPTY:
1130 #ifdef GDK_WINDOWING_X11
1131       gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), NULL);
1132 #endif
1133 #ifdef GDK_WINDOWING_WIN32
1134       priv->nid.uFlags &= ~NIF_ICON;
1135       if (priv->nid.hWnd != NULL && priv->visible)
1136         if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
1137           g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
1138 #endif
1139 #ifdef GDK_WINDOWING_QUARTZ
1140         {
1141           QUARTZ_POOL_ALLOC;
1142           [priv->status_item setImage:NULL];
1143           QUARTZ_POOL_RELEASE;
1144         }
1145 #endif
1146       break;
1147     default:
1148       g_assert_not_reached ();
1149       break;
1150     }
1151 }
1152
1153 #ifdef GDK_WINDOWING_X11
1154
1155 static void
1156 gtk_status_icon_size_allocate (GtkStatusIcon *status_icon,
1157                                GtkAllocation *allocation)
1158 {
1159   GtkStatusIconPrivate *priv = status_icon->priv;
1160   GtkOrientation orientation;
1161   gint size;
1162
1163   orientation = _gtk_tray_icon_get_orientation (GTK_TRAY_ICON (priv->tray_icon));
1164
1165   if (orientation == GTK_ORIENTATION_HORIZONTAL)
1166     size = allocation->height;
1167   else
1168     size = allocation->width;
1169
1170   priv->image_width = allocation->width - GTK_MISC (priv->image)->xpad * 2;
1171   priv->image_height = allocation->height - GTK_MISC (priv->image)->ypad * 2;
1172
1173   if (priv->size != size)
1174     {
1175       priv->size = size;
1176
1177       g_object_notify (G_OBJECT (status_icon), "size");
1178
1179       if (!emit_size_changed_signal (status_icon, size))
1180         gtk_status_icon_update_image (status_icon);
1181     }
1182 }
1183
1184 static void
1185 gtk_status_icon_screen_changed (GtkStatusIcon *status_icon,
1186                                 GdkScreen *old_screen)
1187 {
1188   GtkStatusIconPrivate *priv = status_icon->priv;
1189
1190   if (gtk_widget_get_screen (priv->tray_icon) != old_screen)
1191     {
1192       g_object_notify (G_OBJECT (status_icon), "screen");
1193     }
1194 }
1195
1196 #endif
1197
1198 #ifdef GDK_WINDOWING_X11
1199
1200 static void
1201 gtk_status_icon_embedded_changed (GtkStatusIcon *status_icon)
1202 {
1203   g_object_notify (G_OBJECT (status_icon), "embedded");
1204 }
1205
1206 static void
1207 gtk_status_icon_orientation_changed (GtkStatusIcon *status_icon)
1208 {
1209   g_object_notify (G_OBJECT (status_icon), "orientation");
1210 }
1211
1212 #endif
1213
1214 static gboolean
1215 gtk_status_icon_key_press (GtkStatusIcon  *status_icon,
1216                            GdkEventKey    *event)
1217 {
1218   guint state, keyval;
1219
1220   state = event->state & gtk_accelerator_get_default_mod_mask ();
1221   keyval = event->keyval;
1222   if (state == 0 &&
1223       (keyval == GDK_Return ||
1224        keyval == GDK_KP_Enter ||
1225        keyval == GDK_ISO_Enter ||
1226        keyval == GDK_space ||
1227        keyval == GDK_KP_Space))
1228     {
1229       emit_activate_signal (status_icon);
1230       return TRUE;
1231     }
1232
1233   return FALSE;
1234 }
1235
1236 static void
1237 gtk_status_icon_popup_menu (GtkStatusIcon  *status_icon)
1238 {
1239   emit_popup_menu_signal (status_icon, 0, gtk_get_current_event_time ());
1240 }
1241
1242 static gboolean
1243 gtk_status_icon_button_press (GtkStatusIcon  *status_icon,
1244                               GdkEventButton *event)
1245 {
1246   if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
1247     {
1248       emit_activate_signal (status_icon);
1249       return TRUE;
1250     }
1251   else if (event->button == 3 && event->type == GDK_BUTTON_PRESS)
1252     {
1253       emit_popup_menu_signal (status_icon, event->button, event->time);
1254       return TRUE;
1255     }
1256
1257   return FALSE;
1258 }
1259
1260 static void
1261 gtk_status_icon_reset_image_data (GtkStatusIcon *status_icon)
1262 {
1263   GtkStatusIconPrivate *priv = status_icon->priv;
1264
1265   switch (priv->storage_type)
1266   {
1267     case GTK_IMAGE_PIXBUF:
1268       if (priv->image_data.pixbuf)
1269         g_object_unref (priv->image_data.pixbuf);
1270       priv->image_data.pixbuf = NULL;
1271       g_object_notify (G_OBJECT (status_icon), "pixbuf");
1272       break;
1273
1274     case GTK_IMAGE_STOCK:
1275       g_free (priv->image_data.stock_id);
1276       priv->image_data.stock_id = NULL;
1277
1278       g_object_notify (G_OBJECT (status_icon), "stock");
1279       break;
1280       
1281     case GTK_IMAGE_ICON_NAME:
1282       g_free (priv->image_data.icon_name);
1283       priv->image_data.icon_name = NULL;
1284
1285       g_object_notify (G_OBJECT (status_icon), "icon-name");
1286       break;
1287       
1288     case GTK_IMAGE_EMPTY:
1289       break;
1290     default:
1291       g_assert_not_reached ();
1292       break;
1293   }
1294
1295   priv->storage_type = GTK_IMAGE_EMPTY;
1296   g_object_notify (G_OBJECT (status_icon), "storage-type");
1297 }
1298
1299 static void
1300 gtk_status_icon_set_image (GtkStatusIcon *status_icon,
1301                            GtkImageType   storage_type,
1302                            gpointer       data)
1303 {
1304   GtkStatusIconPrivate *priv = status_icon->priv;
1305
1306   g_object_freeze_notify (G_OBJECT (status_icon));
1307
1308   gtk_status_icon_reset_image_data (status_icon);
1309
1310   priv->storage_type = storage_type;
1311   g_object_notify (G_OBJECT (status_icon), "storage-type");
1312
1313   switch (storage_type) 
1314     {
1315     case GTK_IMAGE_PIXBUF:
1316       priv->image_data.pixbuf = (GdkPixbuf *)data;
1317       g_object_notify (G_OBJECT (status_icon), "pixbuf");
1318       break;
1319     case GTK_IMAGE_STOCK:
1320       priv->image_data.stock_id = g_strdup ((const gchar *)data);
1321       g_object_notify (G_OBJECT (status_icon), "stock");
1322       break;
1323     case GTK_IMAGE_ICON_NAME:
1324       priv->image_data.icon_name = g_strdup ((const gchar *)data);
1325       g_object_notify (G_OBJECT (status_icon), "icon-name");
1326       break;
1327     default:
1328       g_warning ("Image type %u not handled by GtkStatusIcon", storage_type);
1329     }
1330
1331   g_object_thaw_notify (G_OBJECT (status_icon));
1332
1333   gtk_status_icon_update_image (status_icon);
1334 }
1335
1336 /**
1337  * gtk_status_icon_set_from_pixbuf:
1338  * @status_icon: a #GtkStatusIcon
1339  * @pixbuf: a #GdkPixbuf or %NULL
1340  * 
1341  * Makes @status_icon display @pixbuf. 
1342  * See gtk_status_icon_new_from_pixbuf() for details.
1343  *
1344  * Since: 2.10
1345  **/
1346 void
1347 gtk_status_icon_set_from_pixbuf (GtkStatusIcon *status_icon,
1348                                  GdkPixbuf     *pixbuf)
1349 {
1350   g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1351   g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));
1352
1353   if (pixbuf)
1354     g_object_ref (pixbuf);
1355
1356   gtk_status_icon_set_image (status_icon, GTK_IMAGE_PIXBUF,
1357                              (gpointer) pixbuf);
1358 }
1359
1360 /**
1361  * gtk_status_icon_set_from_file:
1362  * @status_icon: a #GtkStatusIcon
1363  * @filename: a filename
1364  * 
1365  * Makes @status_icon display the file @filename.
1366  * See gtk_status_icon_new_from_file() for details.
1367  *
1368  * Since: 2.10 
1369  **/
1370 void
1371 gtk_status_icon_set_from_file (GtkStatusIcon *status_icon,
1372                                const gchar   *filename)
1373 {
1374   GdkPixbuf *pixbuf;
1375   
1376   g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1377   g_return_if_fail (filename != NULL);
1378   
1379   pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
1380   
1381   gtk_status_icon_set_from_pixbuf (status_icon, pixbuf);
1382   
1383   if (pixbuf)
1384     g_object_unref (pixbuf);
1385 }
1386
1387 /**
1388  * gtk_status_icon_set_from_stock:
1389  * @status_icon: a #GtkStatusIcon
1390  * @stock_id: a stock icon id
1391  * 
1392  * Makes @status_icon display the stock icon with the id @stock_id.
1393  * See gtk_status_icon_new_from_stock() for details.
1394  *
1395  * Since: 2.10 
1396  **/
1397 void
1398 gtk_status_icon_set_from_stock (GtkStatusIcon *status_icon,
1399                                 const gchar   *stock_id)
1400 {
1401   g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1402   g_return_if_fail (stock_id != NULL);
1403
1404   gtk_status_icon_set_image (status_icon, GTK_IMAGE_STOCK,
1405                              (gpointer) stock_id);
1406 }
1407
1408 /**
1409  * gtk_status_icon_set_from_icon_name:
1410  * @status_icon: a #GtkStatusIcon
1411  * @icon_name: an icon name
1412  * 
1413  * Makes @status_icon display the icon named @icon_name from the 
1414  * current icon theme.
1415  * See gtk_status_icon_new_from_icon_name() for details.
1416  *
1417  * Since: 2.10 
1418  **/
1419 void
1420 gtk_status_icon_set_from_icon_name (GtkStatusIcon *status_icon,
1421                                     const gchar   *icon_name)
1422 {
1423   g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1424   g_return_if_fail (icon_name != NULL);
1425
1426   gtk_status_icon_set_image (status_icon, GTK_IMAGE_ICON_NAME,
1427                              (gpointer) icon_name);
1428 }
1429
1430 /**
1431  * gtk_status_icon_get_storage_type:
1432  * @status_icon: a #GtkStatusIcon
1433  * 
1434  * Gets the type of representation being used by the #GtkStatusIcon
1435  * to store image data. If the #GtkStatusIcon has no image data,
1436  * the return value will be %GTK_IMAGE_EMPTY. 
1437  * 
1438  * Return value: the image representation being used
1439  *
1440  * Since: 2.10
1441  **/
1442 GtkImageType
1443 gtk_status_icon_get_storage_type (GtkStatusIcon *status_icon)
1444 {
1445   g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), GTK_IMAGE_EMPTY);
1446
1447   return status_icon->priv->storage_type;
1448 }
1449 /**
1450  * gtk_status_icon_get_pixbuf:
1451  * @status_icon: a #GtkStatusIcon
1452  * 
1453  * Gets the #GdkPixbuf being displayed by the #GtkStatusIcon.
1454  * The storage type of the status icon must be %GTK_IMAGE_EMPTY or
1455  * %GTK_IMAGE_PIXBUF (see gtk_status_icon_get_storage_type()).
1456  * The caller of this function does not own a reference to the
1457  * returned pixbuf.
1458  * 
1459  * Return value: the displayed pixbuf, or %NULL if the image is empty.
1460  *
1461  * Since: 2.10
1462  **/
1463 GdkPixbuf *
1464 gtk_status_icon_get_pixbuf (GtkStatusIcon *status_icon)
1465 {
1466   GtkStatusIconPrivate *priv;
1467
1468   g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), NULL);
1469
1470   priv = status_icon->priv;
1471
1472   g_return_val_if_fail (priv->storage_type == GTK_IMAGE_PIXBUF ||
1473                         priv->storage_type == GTK_IMAGE_EMPTY, NULL);
1474
1475   if (priv->storage_type == GTK_IMAGE_EMPTY)
1476     priv->image_data.pixbuf = NULL;
1477
1478   return priv->image_data.pixbuf;
1479 }
1480
1481 /**
1482  * gtk_status_icon_get_stock:
1483  * @status_icon: a #GtkStatusIcon
1484  * 
1485  * Gets the id of the stock icon being displayed by the #GtkStatusIcon.
1486  * The storage type of the status icon must be %GTK_IMAGE_EMPTY or
1487  * %GTK_IMAGE_STOCK (see gtk_status_icon_get_storage_type()).
1488  * The returned string is owned by the #GtkStatusIcon and should not
1489  * be freed or modified.
1490  * 
1491  * Return value: stock id of the displayed stock icon,
1492  *   or %NULL if the image is empty.
1493  *
1494  * Since: 2.10
1495  **/
1496 G_CONST_RETURN gchar *
1497 gtk_status_icon_get_stock (GtkStatusIcon *status_icon)
1498 {
1499   GtkStatusIconPrivate *priv;
1500
1501   g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), NULL);
1502
1503   priv = status_icon->priv;
1504
1505   g_return_val_if_fail (priv->storage_type == GTK_IMAGE_STOCK ||
1506                         priv->storage_type == GTK_IMAGE_EMPTY, NULL);
1507   
1508   if (priv->storage_type == GTK_IMAGE_EMPTY)
1509     priv->image_data.stock_id = NULL;
1510
1511   return priv->image_data.stock_id;
1512 }
1513
1514 /**
1515  * gtk_status_icon_get_icon_name:
1516  * @status_icon: a #GtkStatusIcon
1517  * 
1518  * Gets the name of the icon being displayed by the #GtkStatusIcon.
1519  * The storage type of the status icon must be %GTK_IMAGE_EMPTY or
1520  * %GTK_IMAGE_ICON_NAME (see gtk_status_icon_get_storage_type()).
1521  * The returned string is owned by the #GtkStatusIcon and should not
1522  * be freed or modified.
1523  * 
1524  * Return value: name of the displayed icon, or %NULL if the image is empty.
1525  *
1526  * Since: 2.10
1527  **/
1528 G_CONST_RETURN gchar *
1529 gtk_status_icon_get_icon_name (GtkStatusIcon *status_icon)
1530 {
1531   GtkStatusIconPrivate *priv;
1532   
1533   g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), NULL);
1534
1535   priv = status_icon->priv;
1536
1537   g_return_val_if_fail (priv->storage_type == GTK_IMAGE_ICON_NAME ||
1538                         priv->storage_type == GTK_IMAGE_EMPTY, NULL);
1539
1540   if (priv->storage_type == GTK_IMAGE_EMPTY)
1541     priv->image_data.icon_name = NULL;
1542
1543   return priv->image_data.icon_name;
1544 }
1545
1546 /**
1547  * gtk_status_icon_get_size:
1548  * @status_icon: a #GtkStatusIcon
1549  * 
1550  * Gets the size in pixels that is available for the image. 
1551  * Stock icons and named icons adapt their size automatically
1552  * if the size of the notification area changes. For other
1553  * storage types, the size-changed signal can be used to
1554  * react to size changes.
1555  *
1556  * Note that the returned size is only meaningful while the 
1557  * status icon is embedded (see gtk_status_icon_is_embedded()).
1558  * 
1559  * Return value: the size that is available for the image
1560  *
1561  * Since: 2.10
1562  **/
1563 gint
1564 gtk_status_icon_get_size (GtkStatusIcon *status_icon)
1565 {
1566   g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), 0);
1567
1568   return status_icon->priv->size;
1569 }
1570
1571 /**
1572  * gtk_status_icon_set_screen:
1573  * @status_icon: a #GtkStatusIcon
1574  * @screen: a #GdkScreen
1575  *
1576  * Sets the #GdkScreen where @status_icon is displayed; if
1577  * the icon is already mapped, it will be unmapped, and
1578  * then remapped on the new screen.
1579  *
1580  * Since: 2.12
1581  */
1582 void
1583 gtk_status_icon_set_screen (GtkStatusIcon *status_icon,
1584                             GdkScreen     *screen)
1585 {
1586   g_return_if_fail (GDK_IS_SCREEN (screen));
1587
1588 #ifdef GDK_WINDOWING_X11
1589   gtk_window_set_screen (GTK_WINDOW (status_icon->priv->tray_icon), screen);
1590 #endif
1591 }
1592
1593 /** 
1594  * gtk_status_icon_get_screen:
1595  * @status_icon: a #GtkStatusIcon
1596  *
1597  * Returns the #GdkScreen associated with @status_icon.
1598  *
1599  * Return value: a #GdkScreen.
1600  *
1601  * Since: 2.12
1602  */
1603 GdkScreen *
1604 gtk_status_icon_get_screen (GtkStatusIcon *status_icon)
1605 {
1606   g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), NULL);
1607
1608 #ifdef GDK_WINDOWING_X11   
1609   return gtk_window_get_screen (GTK_WINDOW (status_icon->priv->tray_icon));
1610 #else
1611   return gdk_screen_get_default ();
1612 #endif
1613 }
1614
1615 /**
1616  * gtk_status_icon_set_tooltip:
1617  * @status_icon: a #GtkStatusIcon
1618  * @tooltip_text: the tooltip text, or %NULL
1619  * 
1620  * Sets the tooltip of the status icon.
1621  * 
1622  * Since: 2.10
1623  **/ 
1624 void
1625 gtk_status_icon_set_tooltip (GtkStatusIcon *status_icon,
1626                              const gchar   *tooltip_text)
1627 {
1628   GtkStatusIconPrivate *priv;
1629
1630   g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1631
1632   priv = status_icon->priv;
1633
1634 #ifdef GDK_WINDOWING_X11
1635
1636   gtk_widget_set_tooltip_text (priv->tray_icon, tooltip_text);
1637
1638 #endif
1639 #ifdef GDK_WINDOWING_WIN32
1640   if (tooltip_text == NULL)
1641     priv->nid.uFlags &= ~NIF_TIP;
1642   else
1643     {
1644       WCHAR *wcs = g_utf8_to_utf16 (tooltip_text, -1, NULL, NULL, NULL);
1645
1646       priv->nid.uFlags |= NIF_TIP;
1647       wcsncpy (priv->nid.szTip, wcs, G_N_ELEMENTS (priv->nid.szTip) - 1);
1648       priv->nid.szTip[G_N_ELEMENTS (priv->nid.szTip) - 1] = 0;
1649       g_free (wcs);
1650     }
1651   if (priv->nid.hWnd != NULL && priv->visible)
1652     if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
1653       g_warning ("%s:%d:Shell_NotifyIconW(NIM_MODIFY) failed", __FILE__, __LINE__-1);
1654 #endif
1655 #ifdef GDK_WINDOWING_QUARTZ
1656   QUARTZ_POOL_ALLOC;
1657   [priv->status_item setToolTip:tooltip_text];
1658   QUARTZ_POOL_RELEASE;
1659 #endif
1660 }
1661
1662 static gboolean
1663 gtk_status_icon_blinker (GtkStatusIcon *status_icon)
1664 {
1665   GtkStatusIconPrivate *priv = status_icon->priv;
1666   
1667   priv->blink_off = !priv->blink_off;
1668
1669   gtk_status_icon_update_image (status_icon);
1670
1671   return TRUE;
1672 }
1673
1674 static void
1675 gtk_status_icon_enable_blinking (GtkStatusIcon *status_icon)
1676 {
1677   GtkStatusIconPrivate *priv = status_icon->priv;
1678   
1679   if (!priv->blinking_timeout)
1680     {
1681       gtk_status_icon_blinker (status_icon);
1682
1683       priv->blinking_timeout =
1684         gdk_threads_add_timeout (BLINK_TIMEOUT, 
1685                        (GSourceFunc) gtk_status_icon_blinker, 
1686                        status_icon);
1687     }
1688 }
1689
1690 static void
1691 gtk_status_icon_disable_blinking (GtkStatusIcon *status_icon)
1692 {
1693   GtkStatusIconPrivate *priv = status_icon->priv;
1694   
1695   if (priv->blinking_timeout)
1696     {
1697       g_source_remove (priv->blinking_timeout);
1698       priv->blinking_timeout = 0;
1699       priv->blink_off = FALSE;
1700
1701       gtk_status_icon_update_image (status_icon);
1702     }
1703 }
1704
1705 /**
1706  * gtk_status_icon_set_visible:
1707  * @status_icon: a #GtkStatusIcon
1708  * @visible: %TRUE to show the status icon, %FALSE to hide it
1709  * 
1710  * Shows or hides a status icon.
1711  *
1712  * Since: 2.10
1713  **/
1714 void
1715 gtk_status_icon_set_visible (GtkStatusIcon *status_icon,
1716                              gboolean       visible)
1717 {
1718   GtkStatusIconPrivate *priv;
1719
1720   g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1721
1722   priv = status_icon->priv;
1723
1724   visible = visible != FALSE;
1725
1726   if (priv->visible != visible)
1727     {
1728       priv->visible = visible;
1729
1730 #ifdef GDK_WINDOWING_X11
1731       if (visible)
1732         gtk_widget_show (priv->tray_icon);
1733       else if (GTK_WIDGET_REALIZED (priv->tray_icon)) 
1734         {
1735           gtk_widget_hide (priv->tray_icon);
1736           gtk_widget_unrealize (priv->tray_icon);
1737         }
1738 #endif
1739 #ifdef GDK_WINDOWING_WIN32
1740       if (priv->nid.hWnd != NULL)
1741         {
1742           if (visible)
1743             Shell_NotifyIconW (NIM_ADD, &priv->nid);
1744           else
1745             Shell_NotifyIconW (NIM_DELETE, &priv->nid);
1746         }
1747 #endif
1748 #ifdef GDK_WINDOWING_QUARTZ
1749       QUARTZ_POOL_ALLOC;
1750       [priv->status_item setVisible:visible];
1751       QUARTZ_POOL_RELEASE;
1752 #endif
1753       g_object_notify (G_OBJECT (status_icon), "visible");
1754     }
1755 }
1756
1757 /**
1758  * gtk_status_icon_get_visible:
1759  * @status_icon: a #GtkStatusIcon
1760  * 
1761  * Returns whether the status icon is visible or not. 
1762  * Note that being visible does not guarantee that 
1763  * the user can actually see the icon, see also 
1764  * gtk_status_icon_is_embedded().
1765  * 
1766  * Return value: %TRUE if the status icon is visible
1767  *
1768  * Since: 2.10
1769  **/
1770 gboolean
1771 gtk_status_icon_get_visible (GtkStatusIcon *status_icon)
1772 {
1773   g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), FALSE);
1774
1775   return status_icon->priv->visible;
1776 }
1777
1778 /**
1779  * gtk_status_icon_set_blinking:
1780  * @status_icon: a #GtkStatusIcon
1781  * @blinking: %TRUE to turn blinking on, %FALSE to turn it off
1782  * 
1783  * Makes the status icon start or stop blinking. 
1784  * Note that blinking user interface elements may be problematic
1785  * for some users, and thus may be turned off, in which case
1786  * this setting has no effect.
1787  *
1788  * Since: 2.10
1789  **/
1790 void
1791 gtk_status_icon_set_blinking (GtkStatusIcon *status_icon,
1792                               gboolean       blinking)
1793 {
1794   GtkStatusIconPrivate *priv;
1795
1796   g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1797
1798   priv = status_icon->priv;
1799
1800   blinking = blinking != FALSE;
1801
1802   if (priv->blinking != blinking)
1803     {
1804       priv->blinking = blinking;
1805
1806       if (blinking)
1807         gtk_status_icon_enable_blinking (status_icon);
1808       else
1809         gtk_status_icon_disable_blinking (status_icon);
1810
1811       g_object_notify (G_OBJECT (status_icon), "blinking");
1812     }
1813 }
1814
1815 /**
1816  * gtk_status_icon_get_blinking:
1817  * @status_icon: a #GtkStatusIcon
1818  * 
1819  * Returns whether the icon is blinking, see 
1820  * gtk_status_icon_set_blinking().
1821  * 
1822  * Return value: %TRUE if the icon is blinking
1823  *
1824  * Since: 2.10
1825  **/
1826 gboolean
1827 gtk_status_icon_get_blinking (GtkStatusIcon *status_icon)
1828 {
1829   g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), FALSE);
1830
1831   return status_icon->priv->blinking;
1832 }
1833
1834 /**
1835  * gtk_status_icon_is_embedded:
1836  * @status_icon: a #GtkStatusIcon
1837  * 
1838  * Returns whether the status icon is embedded in a notification
1839  * area. 
1840  * 
1841  * Return value: %TRUE if the status icon is embedded in
1842  *   a notification area.
1843  *
1844  * Since: 2.10
1845  **/
1846 gboolean
1847 gtk_status_icon_is_embedded (GtkStatusIcon *status_icon)
1848 {
1849 #ifdef GDK_WINDOWING_X11
1850   GtkPlug *plug;
1851 #endif
1852
1853   g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), FALSE);
1854
1855 #ifdef GDK_WINDOWING_X11
1856   plug = GTK_PLUG (status_icon->priv->tray_icon);
1857
1858   if (plug->socket_window)
1859     return TRUE;
1860   else
1861     return FALSE;
1862 #endif
1863 #ifdef GDK_WINDOWING_WIN32
1864   return TRUE;
1865 #endif
1866 #ifdef GDK_WINDOWING_QUARTZ
1867   return TRUE;
1868 #endif
1869 }
1870
1871 /**
1872  * gtk_status_icon_position_menu:
1873  * @menu: the #GtkMenu
1874  * @x: return location for the x position
1875  * @y: return location for the y position
1876  * @push_in: whether the first menu item should be offset (pushed in) to be
1877  *           aligned with the menu popup position (only useful for GtkOptionMenu).
1878  * @user_data: the status icon to position the menu on
1879  *
1880  * Menu positioning function to use with gtk_menu_popup()
1881  * to position @menu aligned to the status icon @user_data.
1882  * 
1883  * Since: 2.10
1884  **/
1885 void
1886 gtk_status_icon_position_menu (GtkMenu  *menu,
1887                                gint     *x,
1888                                gint     *y,
1889                                gboolean *push_in,
1890                                gpointer  user_data)
1891 {
1892 #ifdef GDK_WINDOWING_X11
1893   GtkStatusIcon *status_icon;
1894   GtkStatusIconPrivate *priv;
1895   GtkTrayIcon *tray_icon;
1896   GtkWidget *widget;
1897   GdkScreen *screen;
1898   GtkTextDirection direction;
1899   GtkRequisition menu_req;
1900   GdkRectangle monitor;
1901   gint monitor_num, height, width, xoffset, yoffset;
1902   
1903   g_return_if_fail (GTK_IS_MENU (menu));
1904   g_return_if_fail (GTK_IS_STATUS_ICON (user_data));
1905
1906   status_icon = GTK_STATUS_ICON (user_data);
1907   priv = status_icon->priv;
1908   tray_icon = GTK_TRAY_ICON (priv->tray_icon);
1909   widget = priv->tray_icon;
1910
1911   direction = gtk_widget_get_direction (widget);
1912
1913   screen = gtk_widget_get_screen (widget);
1914   gtk_menu_set_screen (menu, screen);
1915
1916   monitor_num = gdk_screen_get_monitor_at_window (screen, widget->window);
1917   if (monitor_num < 0)
1918     monitor_num = 0;
1919   gtk_menu_set_monitor (menu, monitor_num);
1920
1921   gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
1922
1923   gdk_window_get_origin (widget->window, x, y);
1924   
1925   gtk_widget_size_request (GTK_WIDGET (menu), &menu_req);
1926
1927   if (_gtk_tray_icon_get_orientation (tray_icon) == GTK_ORIENTATION_VERTICAL)
1928     {
1929       width = 0;
1930       height = widget->allocation.height;
1931       xoffset = widget->allocation.width;
1932       yoffset = 0;
1933     }
1934   else
1935     {
1936       width = widget->allocation.width;
1937       height = 0;
1938       xoffset = 0;
1939       yoffset = widget->allocation.height;
1940     }
1941
1942   if (direction == GTK_TEXT_DIR_RTL)
1943     {
1944       if ((*x - (menu_req.width - width)) >= monitor.x)
1945         *x -= menu_req.width - width;
1946       else if ((*x + xoffset + menu_req.width) < (monitor.x + monitor.width))
1947         *x += xoffset;
1948       else if ((monitor.x + monitor.width - (*x + xoffset)) < *x)
1949         *x -= menu_req.width - width;
1950       else
1951         *x += xoffset;
1952     }
1953   else
1954     {
1955       if ((*x + xoffset + menu_req.width) < (monitor.x + monitor.width))
1956         *x += xoffset;
1957       else if ((*x - (menu_req.width - width)) >= monitor.x)
1958         *x -= menu_req.width - width;
1959       else if ((monitor.x + monitor.width - (*x + xoffset)) > *x)
1960         *x += xoffset;
1961       else 
1962         *x -= menu_req.width - width;
1963     }
1964
1965   if ((*y + yoffset + menu_req.height) < (monitor.y + monitor.height))
1966     *y += yoffset;
1967   else if ((*y - (menu_req.height - height)) >= monitor.y)
1968     *y -= menu_req.height - height;
1969   else if (monitor.y + monitor.height - (*y + yoffset) > *y)
1970     *y += yoffset;
1971   else 
1972     *y -= menu_req.height - height;
1973
1974   *push_in = FALSE;
1975 #endif /* GDK_WINDOWING_X11 */
1976
1977 #ifdef GDK_WINDOWING_WIN32
1978   GtkStatusIcon *status_icon;
1979   GtkStatusIconPrivate *priv;
1980   
1981   g_return_if_fail (GTK_IS_MENU (menu));
1982   g_return_if_fail (GTK_IS_STATUS_ICON (user_data));
1983
1984   status_icon = GTK_STATUS_ICON (user_data);
1985   priv = status_icon->priv;
1986
1987   *x = priv->last_click_x;
1988   *y = priv->last_click_y;
1989   *push_in = TRUE;
1990 #endif
1991 }
1992
1993 /**
1994  * gtk_status_icon_get_geometry:
1995  * @status_icon: a #GtkStatusIcon
1996  * @screen: return location for the screen, or %NULL if the
1997  *          information is not needed 
1998  * @area: return location for the area occupied by the status 
1999  *        icon, or %NULL
2000  * @orientation: return location for the orientation of the panel 
2001  *    in which the status icon is embedded, or %NULL. A panel 
2002  *    at the top or bottom of the screen is horizontal, a panel 
2003  *    at the left or right is vertical.
2004  *
2005  * Obtains information about the location of the status icon
2006  * on screen. This information can be used to e.g. position 
2007  * popups like notification bubbles. 
2008  *
2009  * See gtk_status_icon_position_menu() for a more convenient 
2010  * alternative for positioning menus.
2011  *
2012  * Note that some platforms do not allow GTK+ to provide 
2013  * this information, and even on platforms that do allow it,
2014  * the information is not reliable unless the status icon
2015  * is embedded in a notification area, see
2016  * gtk_status_icon_is_embedded().
2017  *
2018  * Return value: %TRUE if the location information has 
2019  *               been filled in
2020  *
2021  * Since: 2.10
2022  */
2023 gboolean  
2024 gtk_status_icon_get_geometry (GtkStatusIcon    *status_icon,
2025                               GdkScreen       **screen,
2026                               GdkRectangle     *area,
2027                               GtkOrientation   *orientation)
2028 {
2029 #ifdef GDK_WINDOWING_X11   
2030   GtkWidget *widget;
2031   GtkStatusIconPrivate *priv;
2032   gint x, y;
2033
2034   g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), FALSE);
2035
2036   priv = status_icon->priv;
2037   widget = priv->tray_icon;
2038
2039   if (screen)
2040     *screen = gtk_widget_get_screen (widget);
2041
2042   if (area)
2043     {
2044       gdk_window_get_origin (widget->window, &x, &y);
2045       area->x = x;
2046       area->y = y;
2047       area->width = widget->allocation.width;
2048       area->height = widget->allocation.height;
2049     }
2050
2051   if (orientation)
2052     *orientation = _gtk_tray_icon_get_orientation (GTK_TRAY_ICON (widget));
2053
2054   return TRUE;
2055 #else
2056   return FALSE;
2057 #endif /* GDK_WINDOWING_X11 */
2058 }
2059
2060
2061 #define __GTK_STATUS_ICON_C__
2062 #include "gtkaliasdef.c"