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
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.
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.
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.
24 * Mark McLoughlin <mark@skynet.ie>
25 * Hans Breuer <hans@breuer.org>
26 * Tor Lillqvist <tml@novell.com>
27 * Mikael Hallendal <micke@imendio.com>
33 #include "gtkstatusicon.h"
36 #include "gtkiconfactory.h"
37 #include "gtkmarshalers.h"
38 #include "gtktrayicon.h"
40 #include "gtkprivate.h"
41 #include "gtkwidget.h"
43 #ifdef GDK_WINDOWING_WIN32
44 #include "gtkicontheme.h"
47 #include "win32/gdkwin32.h"
48 #define WM_GTK_TRAY_NOTIFICATION (WM_USER+1)
51 #ifdef GDK_WINDOWING_QUARTZ
52 #include "gtkicontheme.h"
56 #include "gdkkeysyms.h"
60 #define BLINK_TIMEOUT 500
86 static guint status_icon_signals [LAST_SIGNAL] = { 0 };
88 #ifdef GDK_WINDOWING_QUARTZ
89 #include "gtkstatusicon-quartz.c"
92 struct _GtkStatusIconPrivate
94 #ifdef GDK_WINDOWING_X11
99 #ifdef GDK_WINDOWING_WIN32
100 GtkWidget *dummy_widget;
102 gint last_click_x, last_click_y;
103 GtkOrientation orientation;
106 #ifdef GDK_WINDOWING_QUARTZ
107 GtkWidget *dummy_widget;
108 GtkQuartzStatusIcon *status_item;
116 GtkImageType storage_type;
125 GdkPixbuf *blank_icon;
126 guint blinking_timeout;
133 static GObject* gtk_status_icon_constructor (GType type,
134 guint n_construct_properties,
135 GObjectConstructParam *construct_params);
136 static void gtk_status_icon_finalize (GObject *object);
137 static void gtk_status_icon_set_property (GObject *object,
141 static void gtk_status_icon_get_property (GObject *object,
146 #ifdef GDK_WINDOWING_X11
147 static void gtk_status_icon_size_allocate (GtkStatusIcon *status_icon,
148 GtkAllocation *allocation);
149 static void gtk_status_icon_screen_changed (GtkStatusIcon *status_icon,
150 GdkScreen *old_screen);
151 static void gtk_status_icon_embedded_changed (GtkStatusIcon *status_icon);
152 static void gtk_status_icon_orientation_changed (GtkStatusIcon *status_icon);
155 static gboolean gtk_status_icon_key_press (GtkStatusIcon *status_icon,
157 static void gtk_status_icon_popup_menu (GtkStatusIcon *status_icon);
158 static gboolean gtk_status_icon_button_press (GtkStatusIcon *status_icon,
159 GdkEventButton *event);
160 static void gtk_status_icon_disable_blinking (GtkStatusIcon *status_icon);
161 static void gtk_status_icon_reset_image_data (GtkStatusIcon *status_icon);
164 G_DEFINE_TYPE (GtkStatusIcon, gtk_status_icon, G_TYPE_OBJECT)
167 gtk_status_icon_class_init (GtkStatusIconClass *class)
169 GObjectClass *gobject_class = (GObjectClass *) class;
171 gobject_class->constructor = gtk_status_icon_constructor;
172 gobject_class->finalize = gtk_status_icon_finalize;
173 gobject_class->set_property = gtk_status_icon_set_property;
174 gobject_class->get_property = gtk_status_icon_get_property;
176 g_object_class_install_property (gobject_class,
178 g_param_spec_object ("pixbuf",
180 P_("A GdkPixbuf to display"),
182 GTK_PARAM_READWRITE));
184 g_object_class_install_property (gobject_class,
186 g_param_spec_string ("file",
188 P_("Filename to load and display"),
190 GTK_PARAM_WRITABLE));
192 g_object_class_install_property (gobject_class,
194 g_param_spec_string ("stock",
196 P_("Stock ID for a stock image to display"),
198 GTK_PARAM_READWRITE));
200 g_object_class_install_property (gobject_class,
202 g_param_spec_string ("icon-name",
204 P_("The name of the icon from the icon theme"),
206 GTK_PARAM_READWRITE));
208 g_object_class_install_property (gobject_class,
210 g_param_spec_enum ("storage-type",
212 P_("The representation being used for image data"),
215 GTK_PARAM_READABLE));
217 g_object_class_install_property (gobject_class,
219 g_param_spec_int ("size",
221 P_("The size of the icon"),
225 GTK_PARAM_READABLE));
227 g_object_class_install_property (gobject_class,
229 g_param_spec_object ("screen",
231 P_("The screen where this status icon will be displayed"),
233 GTK_PARAM_READWRITE));
235 g_object_class_install_property (gobject_class,
237 g_param_spec_boolean ("blinking",
239 P_("Whether or not the status icon is blinking"),
241 GTK_PARAM_READWRITE));
243 g_object_class_install_property (gobject_class,
245 g_param_spec_boolean ("visible",
247 P_("Whether or not the status icon is visible"),
249 GTK_PARAM_READWRITE));
253 * GtkStatusIcon:embedded:
255 * %TRUE if the statusicon is embedded in a notification area.
259 g_object_class_install_property (gobject_class,
261 g_param_spec_boolean ("embedded",
263 P_("Whether or not the status icon is embedded"),
265 GTK_PARAM_READABLE));
268 * GtkStatusIcon:orientation:
270 * The orientation of the tray in which the statusicon
275 g_object_class_install_property (gobject_class,
277 g_param_spec_enum ("orientation",
279 P_("The orientation of the tray"),
280 GTK_TYPE_ORIENTATION,
281 GTK_ORIENTATION_HORIZONTAL,
282 GTK_PARAM_READABLE));
286 * GtkStatusIcon::activate:
287 * @status_icon: the object which received the signal
289 * Gets emitted when the user activates the status icon.
290 * If and how status icons can activated is platform-dependent.
294 status_icon_signals [ACTIVATE_SIGNAL] =
295 g_signal_new (I_("activate"),
296 G_TYPE_FROM_CLASS (gobject_class),
297 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
298 G_STRUCT_OFFSET (GtkStatusIconClass, activate),
301 g_cclosure_marshal_VOID__VOID,
306 * GtkStatusIcon::popup-menu:
307 * @status_icon: the object which received the signal
308 * @button: the button that was pressed, or 0 if the
309 * signal is not emitted in response to a button press event
310 * @activate_time: the timestamp of the event that
311 * triggered the signal emission
313 * Gets emitted when the user brings up the context menu
314 * of the status icon. Whether status icons can have context
315 * menus and how these are activated is platform-dependent.
317 * The @button and @activate_timeout parameters should be
318 * passed as the last to arguments to gtk_menu_popup().
322 status_icon_signals [POPUP_MENU_SIGNAL] =
323 g_signal_new (I_("popup_menu"),
324 G_TYPE_FROM_CLASS (gobject_class),
325 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
326 G_STRUCT_OFFSET (GtkStatusIconClass, popup_menu),
329 _gtk_marshal_VOID__UINT_UINT,
336 * GtkStatusIcon::size-changed:
337 * @status_icon: the object which received the signal
338 * @size: the new size
340 * Gets emitted when the size available for the image
341 * changes, e.g. because the notification area got resized.
343 * Return value: %TRUE if the icon was updated for the new
344 * size. Otherwise, GTK+ will scale the icon as necessary.
348 status_icon_signals [SIZE_CHANGED_SIGNAL] =
349 g_signal_new (I_("size_changed"),
350 G_TYPE_FROM_CLASS (gobject_class),
352 G_STRUCT_OFFSET (GtkStatusIconClass, size_changed),
353 g_signal_accumulator_true_handled,
355 _gtk_marshal_BOOLEAN__INT,
360 g_type_class_add_private (class, sizeof (GtkStatusIconPrivate));
363 #ifdef GDK_WINDOWING_WIN32
366 build_button_event (GtkStatusIconPrivate *priv,
371 GdkRectangle monitor0;
373 /* We know that gdk/win32 puts the primary monitor at index 0 */
374 gdk_screen_get_monitor_geometry (gdk_screen_get_default (), 0, &monitor0);
375 e->window = g_object_ref (gdk_get_default_root_window ());
376 e->send_event = TRUE;
377 e->time = GetTickCount ();
379 priv->last_click_x = e->x = pos.x + monitor0.x;
380 priv->last_click_y = e->y = pos.y + monitor0.y;
384 e->device = gdk_display_get_default ()->core_pointer;
391 GtkStatusIcon *status_icon;
392 GdkEventButton *event;
393 } ButtonCallbackData;
396 button_callback (gpointer data)
398 ButtonCallbackData *bc = (ButtonCallbackData *) data;
400 gtk_status_icon_button_press (bc->status_icon, bc->event);
402 gdk_event_free ((GdkEvent *) bc->event);
408 static LRESULT CALLBACK
414 if (message == WM_GTK_TRAY_NOTIFICATION)
416 ButtonCallbackData *bc;
422 bc = g_new (ButtonCallbackData, 1);
423 bc->event = (GdkEventButton *) gdk_event_new (GDK_BUTTON_PRESS);
424 bc->status_icon = GTK_STATUS_ICON (wparam);
425 build_button_event (bc->status_icon->priv, bc->event, (lparam == WM_LBUTTONDOWN) ? 1 : 3);
426 g_idle_add (button_callback, bc);
435 return DefWindowProc (hwnd, message, wparam, lparam);
440 create_tray_observer (void)
443 static HWND hwnd = NULL;
445 HINSTANCE hmodule = GetModuleHandle (NULL);
450 memset (&wclass, 0, sizeof(WNDCLASS));
451 wclass.lpszClassName = "gtkstatusicon-observer";
452 wclass.lpfnWndProc = wndproc;
453 wclass.hInstance = hmodule;
455 klass = RegisterClass (&wclass);
459 hwnd = CreateWindow (MAKEINTRESOURCE(klass),
461 0, 0, 1, 1, NULL, NULL,
465 UnregisterClass (MAKEINTRESOURCE(klass), hmodule);
475 gtk_status_icon_init (GtkStatusIcon *status_icon)
477 GtkStatusIconPrivate *priv;
479 priv = G_TYPE_INSTANCE_GET_PRIVATE (status_icon, GTK_TYPE_STATUS_ICON,
480 GtkStatusIconPrivate);
481 status_icon->priv = priv;
483 priv->storage_type = GTK_IMAGE_EMPTY;
484 priv->visible = TRUE;
486 #ifdef GDK_WINDOWING_X11
488 priv->image_width = 0;
489 priv->image_height = 0;
491 priv->tray_icon = GTK_WIDGET (_gtk_tray_icon_new (NULL));
493 gtk_widget_add_events (GTK_WIDGET (priv->tray_icon),
494 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
496 g_signal_connect_swapped (priv->tray_icon, "key-press-event",
497 G_CALLBACK (gtk_status_icon_key_press), status_icon);
498 g_signal_connect_swapped (priv->tray_icon, "popup-menu",
499 G_CALLBACK (gtk_status_icon_popup_menu), status_icon);
500 g_signal_connect_swapped (priv->tray_icon, "notify::embedded",
501 G_CALLBACK (gtk_status_icon_embedded_changed), status_icon);
502 g_signal_connect_swapped (priv->tray_icon, "notify::orientation",
503 G_CALLBACK (gtk_status_icon_orientation_changed), status_icon);
504 g_signal_connect_swapped (priv->tray_icon, "button-press-event",
505 G_CALLBACK (gtk_status_icon_button_press), status_icon);
506 g_signal_connect_swapped (priv->tray_icon, "screen-changed",
507 G_CALLBACK (gtk_status_icon_screen_changed), status_icon);
508 priv->image = gtk_image_new ();
509 GTK_WIDGET_SET_FLAGS (priv->image, GTK_CAN_FOCUS);
510 gtk_container_add (GTK_CONTAINER (priv->tray_icon), priv->image);
511 gtk_widget_show (priv->image);
513 g_signal_connect_swapped (priv->image, "size-allocate",
514 G_CALLBACK (gtk_status_icon_size_allocate), status_icon);
518 #ifdef GDK_WINDOWING_WIN32
520 /* Get position and orientation of Windows taskbar. */
524 abd.cbSize = sizeof (abd);
525 SHAppBarMessage (ABM_GETTASKBARPOS, &abd);
526 if (abd.rc.bottom - abd.rc.top > abd.rc.right - abd.rc.left)
527 priv->orientation = GTK_ORIENTATION_VERTICAL;
529 priv->orientation = GTK_ORIENTATION_HORIZONTAL;
532 priv->last_click_x = priv->last_click_y = 0;
534 /* Are the system tray icons always 16 pixels square? */
536 priv->image_width = 16;
537 priv->image_height = 16;
539 priv->dummy_widget = gtk_label_new ("");
541 memset (&priv->nid, 0, sizeof (priv->nid));
543 priv->nid.hWnd = create_tray_observer ();
544 priv->nid.uID = GPOINTER_TO_UINT (status_icon);
545 priv->nid.uCallbackMessage = WM_GTK_TRAY_NOTIFICATION;
546 priv->nid.uFlags = NIF_MESSAGE;
548 if (!Shell_NotifyIconW (NIM_ADD, &priv->nid))
550 g_warning ("%s:%d:Shell_NotifyIcon(NIM_ADD) failed", __FILE__, __LINE__-2);
551 priv->nid.hWnd = NULL;
555 #ifdef GDK_WINDOWING_QUARTZ
556 priv->dummy_widget = gtk_label_new ("");
560 priv->status_item = [[GtkQuartzStatusIcon alloc] initWithStatusIcon:status_icon];
562 priv->image_width = priv->image_height = [priv->status_item getHeight];
563 priv->size = priv->image_height;
571 gtk_status_icon_constructor (GType type,
572 guint n_construct_properties,
573 GObjectConstructParam *construct_params)
576 GtkStatusIcon *status_icon;
577 GtkStatusIconPrivate *priv;
579 object = G_OBJECT_CLASS (gtk_status_icon_parent_class)->constructor (type,
580 n_construct_properties,
583 #ifdef GDK_WINDOWING_X11
584 status_icon = GTK_STATUS_ICON (object);
585 priv = status_icon->priv;
588 gtk_widget_show (priv->tray_icon);
595 gtk_status_icon_finalize (GObject *object)
597 GtkStatusIcon *status_icon = GTK_STATUS_ICON (object);
598 GtkStatusIconPrivate *priv = status_icon->priv;
600 gtk_status_icon_disable_blinking (status_icon);
602 gtk_status_icon_reset_image_data (status_icon);
604 if (priv->blank_icon)
605 g_object_unref (priv->blank_icon);
606 priv->blank_icon = NULL;
608 #ifdef GDK_WINDOWING_X11
609 gtk_widget_destroy (priv->tray_icon);
612 #ifdef GDK_WINDOWING_WIN32
613 if (priv->nid.hWnd != NULL && priv->visible)
614 Shell_NotifyIconW (NIM_DELETE, &priv->nid);
616 DestroyIcon (priv->nid.hIcon);
618 gtk_widget_destroy (priv->dummy_widget);
621 #ifdef GDK_WINDOWING_QUARTZ
623 [priv->status_item release];
627 G_OBJECT_CLASS (gtk_status_icon_parent_class)->finalize (object);
631 gtk_status_icon_set_property (GObject *object,
636 GtkStatusIcon *status_icon = GTK_STATUS_ICON (object);
641 gtk_status_icon_set_from_pixbuf (status_icon, g_value_get_object (value));
644 gtk_status_icon_set_from_file (status_icon, g_value_get_string (value));
647 gtk_status_icon_set_from_stock (status_icon, g_value_get_string (value));
650 gtk_status_icon_set_from_icon_name (status_icon, g_value_get_string (value));
653 gtk_status_icon_set_screen (status_icon, g_value_get_object (value));
656 gtk_status_icon_set_blinking (status_icon, g_value_get_boolean (value));
659 gtk_status_icon_set_visible (status_icon, g_value_get_boolean (value));
662 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
668 gtk_status_icon_get_property (GObject *object,
673 GtkStatusIcon *status_icon = GTK_STATUS_ICON (object);
674 GtkStatusIconPrivate *priv = status_icon->priv;
676 /* The "getter" functions whine if you try to get the wrong
677 * storage type. This function is instead robust against that,
678 * so that GUI builders don't have to jump through hoops
685 if (priv->storage_type != GTK_IMAGE_PIXBUF)
686 g_value_set_object (value, NULL);
688 g_value_set_object (value, gtk_status_icon_get_pixbuf (status_icon));
691 if (priv->storage_type != GTK_IMAGE_STOCK)
692 g_value_set_string (value, NULL);
694 g_value_set_string (value, gtk_status_icon_get_stock (status_icon));
697 if (priv->storage_type != GTK_IMAGE_ICON_NAME)
698 g_value_set_string (value, NULL);
700 g_value_set_string (value, gtk_status_icon_get_icon_name (status_icon));
702 case PROP_STORAGE_TYPE:
703 g_value_set_enum (value, gtk_status_icon_get_storage_type (status_icon));
706 g_value_set_int (value, gtk_status_icon_get_size (status_icon));
709 g_value_set_object (value, gtk_status_icon_get_screen (status_icon));
712 g_value_set_boolean (value, gtk_status_icon_get_blinking (status_icon));
715 g_value_set_boolean (value, gtk_status_icon_get_visible (status_icon));
718 g_value_set_boolean (value, gtk_status_icon_is_embedded (status_icon));
720 case PROP_ORIENTATION:
721 #ifdef GDK_WINDOWING_X11
722 g_value_set_enum (value, _gtk_tray_icon_get_orientation (GTK_TRAY_ICON (status_icon->priv->tray_icon)));
724 #ifdef GDK_WINDOWING_WIN32
725 g_value_set_enum (value, status_icon->priv->orientation);
729 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
735 * gtk_status_icon_new:
737 * Creates an empty status icon object.
739 * Return value: a new #GtkStatusIcon
744 gtk_status_icon_new (void)
746 return g_object_new (GTK_TYPE_STATUS_ICON, NULL);
750 * gtk_status_icon_new_from_pixbuf:
751 * @pixbuf: a #GdkPixbuf
753 * Creates a status icon displaying @pixbuf.
755 * The image will be scaled down to fit in the available
756 * space in the notification area, if necessary.
758 * Return value: a new #GtkStatusIcon
763 gtk_status_icon_new_from_pixbuf (GdkPixbuf *pixbuf)
765 return g_object_new (GTK_TYPE_STATUS_ICON,
771 * gtk_status_icon_new_from_file:
772 * @filename: a filename
774 * Creates a status icon displaying the file @filename.
776 * The image will be scaled down to fit in the available
777 * space in the notification area, if necessary.
779 * Return value: a new #GtkStatusIcon
784 gtk_status_icon_new_from_file (const gchar *filename)
786 return g_object_new (GTK_TYPE_STATUS_ICON,
792 * gtk_status_icon_new_from_stock:
793 * @stock_id: a stock icon id
795 * Creates a status icon displaying a stock icon. Sample stock icon
796 * names are #GTK_STOCK_OPEN, #GTK_STOCK_QUIT. You can register your
797 * own stock icon names, see gtk_icon_factory_add_default() and
798 * gtk_icon_factory_add().
800 * Return value: a new #GtkStatusIcon
805 gtk_status_icon_new_from_stock (const gchar *stock_id)
807 return g_object_new (GTK_TYPE_STATUS_ICON,
813 * gtk_status_icon_new_from_icon_name:
814 * @icon_name: an icon name
816 * Creates a status icon displaying an icon from the current icon theme.
817 * If the current icon theme is changed, the icon will be updated
820 * Return value: a new #GtkStatusIcon
825 gtk_status_icon_new_from_icon_name (const gchar *icon_name)
827 return g_object_new (GTK_TYPE_STATUS_ICON,
828 "icon-name", icon_name,
833 emit_activate_signal (GtkStatusIcon *status_icon)
835 g_signal_emit (status_icon,
836 status_icon_signals [ACTIVATE_SIGNAL], 0);
840 emit_popup_menu_signal (GtkStatusIcon *status_icon,
842 guint32 activate_time)
844 g_signal_emit (status_icon,
845 status_icon_signals [POPUP_MENU_SIGNAL], 0,
850 #ifdef GDK_WINDOWING_X11
853 emit_size_changed_signal (GtkStatusIcon *status_icon,
856 gboolean handled = FALSE;
858 g_signal_emit (status_icon,
859 status_icon_signals [SIZE_CHANGED_SIGNAL], 0,
869 gtk_status_icon_blank_icon (GtkStatusIcon *status_icon)
871 GtkStatusIconPrivate *priv = status_icon->priv;
873 if (priv->blank_icon)
877 width = gdk_pixbuf_get_width (priv->blank_icon);
878 height = gdk_pixbuf_get_height (priv->blank_icon);
881 if (width == priv->image_width && height == priv->image_height)
882 return priv->blank_icon;
885 g_object_unref (priv->blank_icon);
886 priv->blank_icon = NULL;
890 priv->blank_icon = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
893 if (priv->blank_icon)
894 gdk_pixbuf_fill (priv->blank_icon, 0);
896 return priv->blank_icon;
899 #ifdef GDK_WINDOWING_X11
902 find_icon_size (GtkWidget *widget,
906 GtkSettings *settings;
910 screen = gtk_widget_get_screen (widget);
913 return GTK_ICON_SIZE_MENU;
915 settings = gtk_settings_get_for_screen (screen);
918 size = GTK_ICON_SIZE_MENU;
920 for (s = GTK_ICON_SIZE_MENU; s < GTK_ICON_SIZE_DIALOG; s++)
922 if (gtk_icon_size_lookup_for_settings (settings, s, &w, &h) &&
923 w <= pixel_size && h <= pixel_size)
925 d = MAX (pixel_size - w, pixel_size - h);
940 gtk_status_icon_update_image (GtkStatusIcon *status_icon)
942 GtkStatusIconPrivate *priv = status_icon->priv;
943 #ifdef GDK_WINDOWING_WIN32
949 #ifdef GDK_WINDOWING_X11
950 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image),
951 gtk_status_icon_blank_icon (status_icon));
953 #ifdef GDK_WINDOWING_WIN32
954 prev_hicon = priv->nid.hIcon;
955 priv->nid.hIcon = gdk_win32_pixbuf_to_hicon_libgtk_only (gtk_status_icon_blank_icon (status_icon));
956 priv->nid.uFlags |= NIF_ICON;
957 if (priv->nid.hWnd != NULL && priv->visible)
958 if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
959 g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
961 DestroyIcon (prev_hicon);
963 #ifdef GDK_WINDOWING_QUARTZ
965 [priv->status_item setImage:gtk_status_icon_blank_icon (status_icon)];
971 switch (priv->storage_type)
973 case GTK_IMAGE_PIXBUF:
977 pixbuf = priv->image_data.pixbuf;
988 width = gdk_pixbuf_get_width (pixbuf);
989 height = gdk_pixbuf_get_height (pixbuf);
991 if (width > size || height > size)
992 scaled = gdk_pixbuf_scale_simple (pixbuf,
995 GDK_INTERP_BILINEAR);
997 scaled = g_object_ref (pixbuf);
999 #ifdef GDK_WINDOWING_X11
1000 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), scaled);
1002 #ifdef GDK_WINDOWING_WIN32
1003 prev_hicon = priv->nid.hIcon;
1004 priv->nid.hIcon = gdk_win32_pixbuf_to_hicon_libgtk_only (scaled);
1005 priv->nid.uFlags |= NIF_ICON;
1006 if (priv->nid.hWnd != NULL && priv->visible)
1007 if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
1008 g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
1010 DestroyIcon (prev_hicon);
1012 #ifdef GDK_WINDOWING_QUARTZ
1014 [priv->status_item setImage:scaled];
1015 QUARTZ_POOL_RELEASE;
1018 g_object_unref (scaled);
1022 #ifdef GDK_WINDOWING_X11
1023 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), NULL);
1025 #ifdef GDK_WINDOWING_WIN32
1026 priv->nid.uFlags &= ~NIF_ICON;
1027 if (priv->nid.hWnd != NULL && priv->visible)
1028 if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
1029 g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
1031 #ifdef GDK_WINDOWING_QUARTZ
1032 [priv->status_item setImage:NULL];
1038 case GTK_IMAGE_STOCK:
1040 #ifdef GDK_WINDOWING_X11
1041 GtkIconSize size = find_icon_size (priv->image, priv->size);
1042 gtk_image_set_from_stock (GTK_IMAGE (priv->image),
1043 priv->image_data.stock_id,
1046 #ifdef GDK_WINDOWING_WIN32
1049 gtk_widget_render_icon (priv->dummy_widget,
1050 priv->image_data.stock_id,
1051 GTK_ICON_SIZE_SMALL_TOOLBAR,
1054 prev_hicon = priv->nid.hIcon;
1055 priv->nid.hIcon = gdk_win32_pixbuf_to_hicon_libgtk_only (pixbuf);
1056 priv->nid.uFlags |= NIF_ICON;
1057 if (priv->nid.hWnd != NULL && priv->visible)
1058 if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
1059 g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
1061 DestroyIcon (prev_hicon);
1062 g_object_unref (pixbuf);
1065 #ifdef GDK_WINDOWING_QUARTZ
1069 pixbuf = gtk_widget_render_icon (priv->dummy_widget,
1070 priv->image_data.stock_id,
1071 GTK_ICON_SIZE_SMALL_TOOLBAR,
1074 [priv->status_item setImage:pixbuf];
1075 QUARTZ_POOL_RELEASE;
1076 g_object_unref (pixbuf);
1082 case GTK_IMAGE_ICON_NAME:
1084 #ifdef GDK_WINDOWING_X11
1085 GtkIconSize size = find_icon_size (priv->image, priv->size);
1086 gtk_image_set_from_icon_name (GTK_IMAGE (priv->image),
1087 priv->image_data.icon_name,
1090 #ifdef GDK_WINDOWING_WIN32
1093 gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
1094 priv->image_data.icon_name,
1098 prev_hicon = priv->nid.hIcon;
1099 priv->nid.hIcon = gdk_win32_pixbuf_to_hicon_libgtk_only (pixbuf);
1100 priv->nid.uFlags |= NIF_ICON;
1101 if (priv->nid.hWnd != NULL && priv->visible)
1102 if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
1103 g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
1105 DestroyIcon (prev_hicon);
1106 g_object_unref (pixbuf);
1109 #ifdef GDK_WINDOWING_QUARTZ
1113 pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
1114 priv->image_data.icon_name,
1119 [priv->status_item setImage:pixbuf];
1120 QUARTZ_POOL_RELEASE;
1121 g_object_unref (pixbuf);
1128 case GTK_IMAGE_EMPTY:
1129 #ifdef GDK_WINDOWING_X11
1130 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), NULL);
1132 #ifdef GDK_WINDOWING_WIN32
1133 priv->nid.uFlags &= ~NIF_ICON;
1134 if (priv->nid.hWnd != NULL && priv->visible)
1135 if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
1136 g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
1138 #ifdef GDK_WINDOWING_QUARTZ
1141 [priv->status_item setImage:NULL];
1142 QUARTZ_POOL_RELEASE;
1147 g_assert_not_reached ();
1152 #ifdef GDK_WINDOWING_X11
1155 gtk_status_icon_size_allocate (GtkStatusIcon *status_icon,
1156 GtkAllocation *allocation)
1158 GtkStatusIconPrivate *priv = status_icon->priv;
1159 GtkOrientation orientation;
1162 orientation = _gtk_tray_icon_get_orientation (GTK_TRAY_ICON (priv->tray_icon));
1164 if (orientation == GTK_ORIENTATION_HORIZONTAL)
1165 size = allocation->height;
1167 size = allocation->width;
1169 priv->image_width = allocation->width - GTK_MISC (priv->image)->xpad * 2;
1170 priv->image_height = allocation->height - GTK_MISC (priv->image)->ypad * 2;
1172 if (priv->size != size)
1176 g_object_notify (G_OBJECT (status_icon), "size");
1178 if (!emit_size_changed_signal (status_icon, size))
1179 gtk_status_icon_update_image (status_icon);
1184 gtk_status_icon_screen_changed (GtkStatusIcon *status_icon,
1185 GdkScreen *old_screen)
1187 GtkStatusIconPrivate *priv = status_icon->priv;
1189 if (gtk_widget_get_screen (priv->tray_icon) != old_screen)
1191 g_object_notify (G_OBJECT (status_icon), "screen");
1197 #ifdef GDK_WINDOWING_X11
1200 gtk_status_icon_embedded_changed (GtkStatusIcon *status_icon)
1202 g_object_notify (G_OBJECT (status_icon), "embedded");
1206 gtk_status_icon_orientation_changed (GtkStatusIcon *status_icon)
1208 g_object_notify (G_OBJECT (status_icon), "orientation");
1214 gtk_status_icon_key_press (GtkStatusIcon *status_icon,
1217 guint state, keyval;
1219 state = event->state & gtk_accelerator_get_default_mod_mask ();
1220 keyval = event->keyval;
1222 (keyval == GDK_Return ||
1223 keyval == GDK_KP_Enter ||
1224 keyval == GDK_ISO_Enter ||
1225 keyval == GDK_space ||
1226 keyval == GDK_KP_Space))
1228 emit_activate_signal (status_icon);
1236 gtk_status_icon_popup_menu (GtkStatusIcon *status_icon)
1238 emit_popup_menu_signal (status_icon, 0, gtk_get_current_event_time ());
1242 gtk_status_icon_button_press (GtkStatusIcon *status_icon,
1243 GdkEventButton *event)
1245 if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
1247 emit_activate_signal (status_icon);
1250 else if (event->button == 3 && event->type == GDK_BUTTON_PRESS)
1252 emit_popup_menu_signal (status_icon, event->button, event->time);
1260 gtk_status_icon_reset_image_data (GtkStatusIcon *status_icon)
1262 GtkStatusIconPrivate *priv = status_icon->priv;
1264 switch (priv->storage_type)
1266 case GTK_IMAGE_PIXBUF:
1267 if (priv->image_data.pixbuf)
1268 g_object_unref (priv->image_data.pixbuf);
1269 priv->image_data.pixbuf = NULL;
1270 g_object_notify (G_OBJECT (status_icon), "pixbuf");
1273 case GTK_IMAGE_STOCK:
1274 g_free (priv->image_data.stock_id);
1275 priv->image_data.stock_id = NULL;
1277 g_object_notify (G_OBJECT (status_icon), "stock");
1280 case GTK_IMAGE_ICON_NAME:
1281 g_free (priv->image_data.icon_name);
1282 priv->image_data.icon_name = NULL;
1284 g_object_notify (G_OBJECT (status_icon), "icon-name");
1287 case GTK_IMAGE_EMPTY:
1290 g_assert_not_reached ();
1294 priv->storage_type = GTK_IMAGE_EMPTY;
1295 g_object_notify (G_OBJECT (status_icon), "storage-type");
1299 gtk_status_icon_set_image (GtkStatusIcon *status_icon,
1300 GtkImageType storage_type,
1303 GtkStatusIconPrivate *priv = status_icon->priv;
1305 g_object_freeze_notify (G_OBJECT (status_icon));
1307 gtk_status_icon_reset_image_data (status_icon);
1309 priv->storage_type = storage_type;
1310 g_object_notify (G_OBJECT (status_icon), "storage-type");
1312 switch (storage_type)
1314 case GTK_IMAGE_PIXBUF:
1315 priv->image_data.pixbuf = (GdkPixbuf *)data;
1316 g_object_notify (G_OBJECT (status_icon), "pixbuf");
1318 case GTK_IMAGE_STOCK:
1319 priv->image_data.stock_id = g_strdup ((const gchar *)data);
1320 g_object_notify (G_OBJECT (status_icon), "stock");
1322 case GTK_IMAGE_ICON_NAME:
1323 priv->image_data.icon_name = g_strdup ((const gchar *)data);
1324 g_object_notify (G_OBJECT (status_icon), "icon-name");
1327 g_warning ("Image type %u not handled by GtkStatusIcon", storage_type);
1330 g_object_thaw_notify (G_OBJECT (status_icon));
1332 gtk_status_icon_update_image (status_icon);
1336 * gtk_status_icon_set_from_pixbuf:
1337 * @status_icon: a #GtkStatusIcon
1338 * @pixbuf: a #GdkPixbuf or %NULL
1340 * Makes @status_icon display @pixbuf.
1341 * See gtk_status_icon_new_from_pixbuf() for details.
1346 gtk_status_icon_set_from_pixbuf (GtkStatusIcon *status_icon,
1349 g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1350 g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));
1353 g_object_ref (pixbuf);
1355 gtk_status_icon_set_image (status_icon, GTK_IMAGE_PIXBUF,
1360 * gtk_status_icon_set_from_file:
1361 * @status_icon: a #GtkStatusIcon
1362 * @filename: a filename
1364 * Makes @status_icon display the file @filename.
1365 * See gtk_status_icon_new_from_file() for details.
1370 gtk_status_icon_set_from_file (GtkStatusIcon *status_icon,
1371 const gchar *filename)
1375 g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1376 g_return_if_fail (filename != NULL);
1378 pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
1380 gtk_status_icon_set_from_pixbuf (status_icon, pixbuf);
1383 g_object_unref (pixbuf);
1387 * gtk_status_icon_set_from_stock:
1388 * @status_icon: a #GtkStatusIcon
1389 * @stock_id: a stock icon id
1391 * Makes @status_icon display the stock icon with the id @stock_id.
1392 * See gtk_status_icon_new_from_stock() for details.
1397 gtk_status_icon_set_from_stock (GtkStatusIcon *status_icon,
1398 const gchar *stock_id)
1400 g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1401 g_return_if_fail (stock_id != NULL);
1403 gtk_status_icon_set_image (status_icon, GTK_IMAGE_STOCK,
1404 (gpointer) stock_id);
1408 * gtk_status_icon_set_from_icon_name:
1409 * @status_icon: a #GtkStatusIcon
1410 * @icon_name: an icon name
1412 * Makes @status_icon display the icon named @icon_name from the
1413 * current icon theme.
1414 * See gtk_status_icon_new_from_icon_name() for details.
1419 gtk_status_icon_set_from_icon_name (GtkStatusIcon *status_icon,
1420 const gchar *icon_name)
1422 g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1423 g_return_if_fail (icon_name != NULL);
1425 gtk_status_icon_set_image (status_icon, GTK_IMAGE_ICON_NAME,
1426 (gpointer) icon_name);
1430 * gtk_status_icon_get_storage_type:
1431 * @status_icon: a #GtkStatusIcon
1433 * Gets the type of representation being used by the #GtkStatusIcon
1434 * to store image data. If the #GtkStatusIcon has no image data,
1435 * the return value will be %GTK_IMAGE_EMPTY.
1437 * Return value: the image representation being used
1442 gtk_status_icon_get_storage_type (GtkStatusIcon *status_icon)
1444 g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), GTK_IMAGE_EMPTY);
1446 return status_icon->priv->storage_type;
1449 * gtk_status_icon_get_pixbuf:
1450 * @status_icon: a #GtkStatusIcon
1452 * Gets the #GdkPixbuf being displayed by the #GtkStatusIcon.
1453 * The storage type of the status icon must be %GTK_IMAGE_EMPTY or
1454 * %GTK_IMAGE_PIXBUF (see gtk_status_icon_get_storage_type()).
1455 * The caller of this function does not own a reference to the
1458 * Return value: the displayed pixbuf, or %NULL if the image is empty.
1463 gtk_status_icon_get_pixbuf (GtkStatusIcon *status_icon)
1465 GtkStatusIconPrivate *priv;
1467 g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), NULL);
1469 priv = status_icon->priv;
1471 g_return_val_if_fail (priv->storage_type == GTK_IMAGE_PIXBUF ||
1472 priv->storage_type == GTK_IMAGE_EMPTY, NULL);
1474 if (priv->storage_type == GTK_IMAGE_EMPTY)
1475 priv->image_data.pixbuf = NULL;
1477 return priv->image_data.pixbuf;
1481 * gtk_status_icon_get_stock:
1482 * @status_icon: a #GtkStatusIcon
1484 * Gets the id of the stock icon being displayed by the #GtkStatusIcon.
1485 * The storage type of the status icon must be %GTK_IMAGE_EMPTY or
1486 * %GTK_IMAGE_STOCK (see gtk_status_icon_get_storage_type()).
1487 * The returned string is owned by the #GtkStatusIcon and should not
1488 * be freed or modified.
1490 * Return value: stock id of the displayed stock icon,
1491 * or %NULL if the image is empty.
1495 G_CONST_RETURN gchar *
1496 gtk_status_icon_get_stock (GtkStatusIcon *status_icon)
1498 GtkStatusIconPrivate *priv;
1500 g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), NULL);
1502 priv = status_icon->priv;
1504 g_return_val_if_fail (priv->storage_type == GTK_IMAGE_STOCK ||
1505 priv->storage_type == GTK_IMAGE_EMPTY, NULL);
1507 if (priv->storage_type == GTK_IMAGE_EMPTY)
1508 priv->image_data.stock_id = NULL;
1510 return priv->image_data.stock_id;
1514 * gtk_status_icon_get_icon_name:
1515 * @status_icon: a #GtkStatusIcon
1517 * Gets the name of the icon being displayed by the #GtkStatusIcon.
1518 * The storage type of the status icon must be %GTK_IMAGE_EMPTY or
1519 * %GTK_IMAGE_ICON_NAME (see gtk_status_icon_get_storage_type()).
1520 * The returned string is owned by the #GtkStatusIcon and should not
1521 * be freed or modified.
1523 * Return value: name of the displayed icon, or %NULL if the image is empty.
1527 G_CONST_RETURN gchar *
1528 gtk_status_icon_get_icon_name (GtkStatusIcon *status_icon)
1530 GtkStatusIconPrivate *priv;
1532 g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), NULL);
1534 priv = status_icon->priv;
1536 g_return_val_if_fail (priv->storage_type == GTK_IMAGE_ICON_NAME ||
1537 priv->storage_type == GTK_IMAGE_EMPTY, NULL);
1539 if (priv->storage_type == GTK_IMAGE_EMPTY)
1540 priv->image_data.icon_name = NULL;
1542 return priv->image_data.icon_name;
1546 * gtk_status_icon_get_size:
1547 * @status_icon: a #GtkStatusIcon
1549 * Gets the size in pixels that is available for the image.
1550 * Stock icons and named icons adapt their size automatically
1551 * if the size of the notification area changes. For other
1552 * storage types, the size-changed signal can be used to
1553 * react to size changes.
1555 * Note that the returned size is only meaningful while the
1556 * status icon is embedded (see gtk_status_icon_is_embedded()).
1558 * Return value: the size that is available for the image
1563 gtk_status_icon_get_size (GtkStatusIcon *status_icon)
1565 g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), 0);
1567 return status_icon->priv->size;
1571 * gtk_status_icon_set_screen:
1572 * @status_icon: a #GtkStatusIcon
1573 * @screen: a #GdkScreen
1575 * Sets the #GdkScreen where @status_icon is displayed; if
1576 * the icon is already mapped, it will be unmapped, and
1577 * then remapped on the new screen.
1582 gtk_status_icon_set_screen (GtkStatusIcon *status_icon,
1585 g_return_if_fail (GDK_IS_SCREEN (screen));
1587 #ifdef GDK_WINDOWING_X11
1588 gtk_window_set_screen (GTK_WINDOW (status_icon->priv->tray_icon), screen);
1593 * gtk_status_icon_get_screen:
1594 * @status_icon: a #GtkStatusIcon
1596 * Returns the #GdkScreen associated with @status_icon.
1598 * Return value: a #GdkScreen.
1603 gtk_status_icon_get_screen (GtkStatusIcon *status_icon)
1605 g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), NULL);
1607 #ifdef GDK_WINDOWING_X11
1608 return gtk_window_get_screen (GTK_WINDOW (status_icon->priv->tray_icon));
1610 return gdk_screen_get_default ();
1615 * gtk_status_icon_set_tooltip:
1616 * @status_icon: a #GtkStatusIcon
1617 * @tooltip_text: the tooltip text, or %NULL
1619 * Sets the tooltip of the status icon.
1624 gtk_status_icon_set_tooltip (GtkStatusIcon *status_icon,
1625 const gchar *tooltip_text)
1627 GtkStatusIconPrivate *priv;
1629 g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1631 priv = status_icon->priv;
1633 #ifdef GDK_WINDOWING_X11
1635 gtk_widget_set_tooltip_text (priv->tray_icon, tooltip_text);
1638 #ifdef GDK_WINDOWING_WIN32
1639 if (tooltip_text == NULL)
1640 priv->nid.uFlags &= ~NIF_TIP;
1643 WCHAR *wcs = g_utf8_to_utf16 (tooltip_text, -1, NULL, NULL, NULL);
1645 priv->nid.uFlags |= NIF_TIP;
1646 wcsncpy (priv->nid.szTip, wcs, G_N_ELEMENTS (priv->nid.szTip) - 1);
1647 priv->nid.szTip[G_N_ELEMENTS (priv->nid.szTip) - 1] = 0;
1650 if (priv->nid.hWnd != NULL && priv->visible)
1651 if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
1652 g_warning ("%s:%d:Shell_NotifyIconW(NIM_MODIFY) failed", __FILE__, __LINE__-1);
1654 #ifdef GDK_WINDOWING_QUARTZ
1656 [priv->status_item setToolTip:tooltip_text];
1657 QUARTZ_POOL_RELEASE;
1662 gtk_status_icon_blinker (GtkStatusIcon *status_icon)
1664 GtkStatusIconPrivate *priv = status_icon->priv;
1666 priv->blink_off = !priv->blink_off;
1668 gtk_status_icon_update_image (status_icon);
1674 gtk_status_icon_enable_blinking (GtkStatusIcon *status_icon)
1676 GtkStatusIconPrivate *priv = status_icon->priv;
1678 if (!priv->blinking_timeout)
1680 gtk_status_icon_blinker (status_icon);
1682 priv->blinking_timeout =
1683 gdk_threads_add_timeout (BLINK_TIMEOUT,
1684 (GSourceFunc) gtk_status_icon_blinker,
1690 gtk_status_icon_disable_blinking (GtkStatusIcon *status_icon)
1692 GtkStatusIconPrivate *priv = status_icon->priv;
1694 if (priv->blinking_timeout)
1696 g_source_remove (priv->blinking_timeout);
1697 priv->blinking_timeout = 0;
1698 priv->blink_off = FALSE;
1700 gtk_status_icon_update_image (status_icon);
1705 * gtk_status_icon_set_visible:
1706 * @status_icon: a #GtkStatusIcon
1707 * @visible: %TRUE to show the status icon, %FALSE to hide it
1709 * Shows or hides a status icon.
1714 gtk_status_icon_set_visible (GtkStatusIcon *status_icon,
1717 GtkStatusIconPrivate *priv;
1719 g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1721 priv = status_icon->priv;
1723 visible = visible != FALSE;
1725 if (priv->visible != visible)
1727 priv->visible = visible;
1729 #ifdef GDK_WINDOWING_X11
1731 gtk_widget_show (priv->tray_icon);
1732 else if (GTK_WIDGET_REALIZED (priv->tray_icon))
1734 gtk_widget_hide (priv->tray_icon);
1735 gtk_widget_unrealize (priv->tray_icon);
1738 #ifdef GDK_WINDOWING_WIN32
1739 if (priv->nid.hWnd != NULL)
1742 Shell_NotifyIconW (NIM_ADD, &priv->nid);
1744 Shell_NotifyIconW (NIM_DELETE, &priv->nid);
1747 #ifdef GDK_WINDOWING_QUARTZ
1749 [priv->status_item setVisible:visible];
1750 QUARTZ_POOL_RELEASE;
1752 g_object_notify (G_OBJECT (status_icon), "visible");
1757 * gtk_status_icon_get_visible:
1758 * @status_icon: a #GtkStatusIcon
1760 * Returns whether the status icon is visible or not.
1761 * Note that being visible does not guarantee that
1762 * the user can actually see the icon, see also
1763 * gtk_status_icon_is_embedded().
1765 * Return value: %TRUE if the status icon is visible
1770 gtk_status_icon_get_visible (GtkStatusIcon *status_icon)
1772 g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), FALSE);
1774 return status_icon->priv->visible;
1778 * gtk_status_icon_set_blinking:
1779 * @status_icon: a #GtkStatusIcon
1780 * @blinking: %TRUE to turn blinking on, %FALSE to turn it off
1782 * Makes the status icon start or stop blinking.
1783 * Note that blinking user interface elements may be problematic
1784 * for some users, and thus may be turned off, in which case
1785 * this setting has no effect.
1790 gtk_status_icon_set_blinking (GtkStatusIcon *status_icon,
1793 GtkStatusIconPrivate *priv;
1795 g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1797 priv = status_icon->priv;
1799 blinking = blinking != FALSE;
1801 if (priv->blinking != blinking)
1803 priv->blinking = blinking;
1806 gtk_status_icon_enable_blinking (status_icon);
1808 gtk_status_icon_disable_blinking (status_icon);
1810 g_object_notify (G_OBJECT (status_icon), "blinking");
1815 * gtk_status_icon_get_blinking:
1816 * @status_icon: a #GtkStatusIcon
1818 * Returns whether the icon is blinking, see
1819 * gtk_status_icon_set_blinking().
1821 * Return value: %TRUE if the icon is blinking
1826 gtk_status_icon_get_blinking (GtkStatusIcon *status_icon)
1828 g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), FALSE);
1830 return status_icon->priv->blinking;
1834 * gtk_status_icon_is_embedded:
1835 * @status_icon: a #GtkStatusIcon
1837 * Returns whether the status icon is embedded in a notification
1840 * Return value: %TRUE if the status icon is embedded in
1841 * a notification area.
1846 gtk_status_icon_is_embedded (GtkStatusIcon *status_icon)
1848 #ifdef GDK_WINDOWING_X11
1852 g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), FALSE);
1854 #ifdef GDK_WINDOWING_X11
1855 plug = GTK_PLUG (status_icon->priv->tray_icon);
1857 if (plug->socket_window)
1862 #ifdef GDK_WINDOWING_WIN32
1865 #ifdef GDK_WINDOWING_QUARTZ
1871 * gtk_status_icon_position_menu:
1872 * @menu: the #GtkMenu
1873 * @x: return location for the x position
1874 * @y: return location for the y position
1875 * @push_in: whether the first menu item should be offset (pushed in) to be
1876 * aligned with the menu popup position (only useful for GtkOptionMenu).
1877 * @user_data: the status icon to position the menu on
1879 * Menu positioning function to use with gtk_menu_popup()
1880 * to position @menu aligned to the status icon @user_data.
1885 gtk_status_icon_position_menu (GtkMenu *menu,
1891 #ifdef GDK_WINDOWING_X11
1892 GtkStatusIcon *status_icon;
1893 GtkStatusIconPrivate *priv;
1894 GtkTrayIcon *tray_icon;
1897 GtkTextDirection direction;
1898 GtkRequisition menu_req;
1899 GdkRectangle monitor;
1900 gint monitor_num, height, width, xoffset, yoffset;
1902 g_return_if_fail (GTK_IS_MENU (menu));
1903 g_return_if_fail (GTK_IS_STATUS_ICON (user_data));
1905 status_icon = GTK_STATUS_ICON (user_data);
1906 priv = status_icon->priv;
1907 tray_icon = GTK_TRAY_ICON (priv->tray_icon);
1908 widget = priv->tray_icon;
1910 direction = gtk_widget_get_direction (widget);
1912 screen = gtk_widget_get_screen (widget);
1913 gtk_menu_set_screen (menu, screen);
1915 monitor_num = gdk_screen_get_monitor_at_window (screen, widget->window);
1916 if (monitor_num < 0)
1918 gtk_menu_set_monitor (menu, monitor_num);
1920 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
1922 gdk_window_get_origin (widget->window, x, y);
1924 gtk_widget_size_request (GTK_WIDGET (menu), &menu_req);
1926 if (_gtk_tray_icon_get_orientation (tray_icon) == GTK_ORIENTATION_VERTICAL)
1929 height = widget->allocation.height;
1930 xoffset = widget->allocation.width;
1935 width = widget->allocation.width;
1938 yoffset = widget->allocation.height;
1941 if (direction == GTK_TEXT_DIR_RTL)
1943 if ((*x - (menu_req.width - width)) >= monitor.x)
1944 *x -= menu_req.width - width;
1945 else if ((*x + xoffset + menu_req.width) < (monitor.x + monitor.width))
1947 else if ((monitor.x + monitor.width - (*x + xoffset)) < *x)
1948 *x -= menu_req.width - width;
1954 if ((*x + xoffset + menu_req.width) < (monitor.x + monitor.width))
1956 else if ((*x - (menu_req.width - width)) >= monitor.x)
1957 *x -= menu_req.width - width;
1958 else if ((monitor.x + monitor.width - (*x + xoffset)) > *x)
1961 *x -= menu_req.width - width;
1964 if ((*y + yoffset + menu_req.height) < (monitor.y + monitor.height))
1966 else if ((*y - (menu_req.height - height)) >= monitor.y)
1967 *y -= menu_req.height - height;
1968 else if (monitor.y + monitor.height - (*y + yoffset) > *y)
1971 *y -= menu_req.height - height;
1974 #endif /* GDK_WINDOWING_X11 */
1976 #ifdef GDK_WINDOWING_WIN32
1977 GtkStatusIcon *status_icon;
1978 GtkStatusIconPrivate *priv;
1980 g_return_if_fail (GTK_IS_MENU (menu));
1981 g_return_if_fail (GTK_IS_STATUS_ICON (user_data));
1983 status_icon = GTK_STATUS_ICON (user_data);
1984 priv = status_icon->priv;
1986 *x = priv->last_click_x;
1987 *y = priv->last_click_y;
1993 * gtk_status_icon_get_geometry:
1994 * @status_icon: a #GtkStatusIcon
1995 * @screen: return location for the screen, or %NULL if the
1996 * information is not needed
1997 * @area: return location for the area occupied by the status
1999 * @orientation: return location for the orientation of the panel
2000 * in which the status icon is embedded, or %NULL. A panel
2001 * at the top or bottom of the screen is horizontal, a panel
2002 * at the left or right is vertical.
2004 * Obtains information about the location of the status icon
2005 * on screen. This information can be used to e.g. position
2006 * popups like notification bubbles.
2008 * See gtk_status_icon_position_menu() for a more convenient
2009 * alternative for positioning menus.
2011 * Note that some platforms do not allow GTK+ to provide
2012 * this information, and even on platforms that do allow it,
2013 * the information is not reliable unless the status icon
2014 * is embedded in a notification area, see
2015 * gtk_status_icon_is_embedded().
2017 * Return value: %TRUE if the location information has
2023 gtk_status_icon_get_geometry (GtkStatusIcon *status_icon,
2026 GtkOrientation *orientation)
2028 #ifdef GDK_WINDOWING_X11
2030 GtkStatusIconPrivate *priv;
2033 g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), FALSE);
2035 priv = status_icon->priv;
2036 widget = priv->tray_icon;
2039 *screen = gtk_widget_get_screen (widget);
2043 gdk_window_get_origin (widget->window, &x, &y);
2046 area->width = widget->allocation.width;
2047 area->height = widget->allocation.height;
2051 *orientation = _gtk_tray_icon_get_orientation (GTK_TRAY_ICON (widget));
2056 #endif /* GDK_WINDOWING_X11 */
2060 #define __GTK_STATUS_ICON_C__
2061 #include "gtkaliasdef.c"