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"
38 #include "gtkmarshalers.h"
39 #include "gtktrayicon.h"
41 #include "gtkprivate.h"
42 #include "gtkwidget.h"
44 #ifdef GDK_WINDOWING_X11
45 #include "gdk/x11/gdkx.h"
48 #ifdef GDK_WINDOWING_WIN32
49 #include "gtkicontheme.h"
52 #include "win32/gdkwin32.h"
53 #define WM_GTK_TRAY_NOTIFICATION (WM_USER+1)
56 #ifdef GDK_WINDOWING_QUARTZ
57 #include "gtkicontheme.h"
61 #include "gdkkeysyms.h"
65 #define BLINK_TIMEOUT 500
91 static guint status_icon_signals [LAST_SIGNAL] = { 0 };
93 #ifdef GDK_WINDOWING_QUARTZ
94 #include "gtkstatusicon-quartz.c"
97 struct _GtkStatusIconPrivate
99 #ifdef GDK_WINDOWING_X11
100 GtkWidget *tray_icon;
104 #ifdef GDK_WINDOWING_WIN32
105 GtkWidget *dummy_widget;
107 gint last_click_x, last_click_y;
108 GtkOrientation orientation;
111 #ifdef GDK_WINDOWING_QUARTZ
112 GtkWidget *dummy_widget;
113 GtkQuartzStatusIcon *status_item;
121 GtkImageType storage_type;
130 GdkPixbuf *blank_icon;
131 guint blinking_timeout;
138 static GObject* gtk_status_icon_constructor (GType type,
139 guint n_construct_properties,
140 GObjectConstructParam *construct_params);
141 static void gtk_status_icon_finalize (GObject *object);
142 static void gtk_status_icon_set_property (GObject *object,
146 static void gtk_status_icon_get_property (GObject *object,
151 #ifdef GDK_WINDOWING_X11
152 static void gtk_status_icon_size_allocate (GtkStatusIcon *status_icon,
153 GtkAllocation *allocation);
154 static void gtk_status_icon_screen_changed (GtkStatusIcon *status_icon,
155 GdkScreen *old_screen);
156 static void gtk_status_icon_embedded_changed (GtkStatusIcon *status_icon);
157 static void gtk_status_icon_orientation_changed (GtkStatusIcon *status_icon);
159 static gboolean gtk_status_icon_key_press (GtkStatusIcon *status_icon,
161 static void gtk_status_icon_popup_menu (GtkStatusIcon *status_icon);
163 static gboolean gtk_status_icon_button_press (GtkStatusIcon *status_icon,
164 GdkEventButton *event);
165 static void gtk_status_icon_disable_blinking (GtkStatusIcon *status_icon);
166 static void gtk_status_icon_reset_image_data (GtkStatusIcon *status_icon);
167 static void gtk_status_icon_update_image (GtkStatusIcon *status_icon);
169 G_DEFINE_TYPE (GtkStatusIcon, gtk_status_icon, G_TYPE_OBJECT)
172 gtk_status_icon_class_init (GtkStatusIconClass *class)
174 GObjectClass *gobject_class = (GObjectClass *) class;
176 gobject_class->constructor = gtk_status_icon_constructor;
177 gobject_class->finalize = gtk_status_icon_finalize;
178 gobject_class->set_property = gtk_status_icon_set_property;
179 gobject_class->get_property = gtk_status_icon_get_property;
181 g_object_class_install_property (gobject_class,
183 g_param_spec_object ("pixbuf",
185 P_("A GdkPixbuf to display"),
187 GTK_PARAM_READWRITE));
189 g_object_class_install_property (gobject_class,
191 g_param_spec_string ("file",
193 P_("Filename to load and display"),
195 GTK_PARAM_WRITABLE));
197 g_object_class_install_property (gobject_class,
199 g_param_spec_string ("stock",
201 P_("Stock ID for a stock image to display"),
203 GTK_PARAM_READWRITE));
205 g_object_class_install_property (gobject_class,
207 g_param_spec_string ("icon-name",
209 P_("The name of the icon from the icon theme"),
211 GTK_PARAM_READWRITE));
213 g_object_class_install_property (gobject_class,
215 g_param_spec_enum ("storage-type",
217 P_("The representation being used for image data"),
220 GTK_PARAM_READABLE));
222 g_object_class_install_property (gobject_class,
224 g_param_spec_int ("size",
226 P_("The size of the icon"),
230 GTK_PARAM_READABLE));
232 g_object_class_install_property (gobject_class,
234 g_param_spec_object ("screen",
236 P_("The screen where this status icon will be displayed"),
238 GTK_PARAM_READWRITE));
240 g_object_class_install_property (gobject_class,
242 g_param_spec_boolean ("blinking",
244 P_("Whether or not the status icon is blinking"),
246 GTK_PARAM_READWRITE));
248 g_object_class_install_property (gobject_class,
250 g_param_spec_boolean ("visible",
252 P_("Whether or not the status icon is visible"),
254 GTK_PARAM_READWRITE));
258 * GtkStatusIcon:embedded:
260 * %TRUE if the statusicon is embedded in a notification area.
264 g_object_class_install_property (gobject_class,
266 g_param_spec_boolean ("embedded",
268 P_("Whether or not the status icon is embedded"),
270 GTK_PARAM_READABLE));
273 * GtkStatusIcon:orientation:
275 * The orientation of the tray in which the statusicon
280 g_object_class_install_property (gobject_class,
282 g_param_spec_enum ("orientation",
284 P_("The orientation of the tray"),
285 GTK_TYPE_ORIENTATION,
286 GTK_ORIENTATION_HORIZONTAL,
287 GTK_PARAM_READABLE));
291 * GtkStatusIcon::activate:
292 * @status_icon: the object which received the signal
294 * Gets emitted when the user activates the status icon.
295 * If and how status icons can activated is platform-dependent.
299 status_icon_signals [ACTIVATE_SIGNAL] =
300 g_signal_new (I_("activate"),
301 G_TYPE_FROM_CLASS (gobject_class),
302 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
303 G_STRUCT_OFFSET (GtkStatusIconClass, activate),
306 g_cclosure_marshal_VOID__VOID,
311 * GtkStatusIcon::popup-menu:
312 * @status_icon: the object which received the signal
313 * @button: the button that was pressed, or 0 if the
314 * signal is not emitted in response to a button press event
315 * @activate_time: the timestamp of the event that
316 * triggered the signal emission
318 * Gets emitted when the user brings up the context menu
319 * of the status icon. Whether status icons can have context
320 * menus and how these are activated is platform-dependent.
322 * The @button and @activate_timeout parameters should be
323 * passed as the last to arguments to gtk_menu_popup().
327 status_icon_signals [POPUP_MENU_SIGNAL] =
328 g_signal_new (I_("popup_menu"),
329 G_TYPE_FROM_CLASS (gobject_class),
330 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
331 G_STRUCT_OFFSET (GtkStatusIconClass, popup_menu),
334 _gtk_marshal_VOID__UINT_UINT,
341 * GtkStatusIcon::size-changed:
342 * @status_icon: the object which received the signal
343 * @size: the new size
345 * Gets emitted when the size available for the image
346 * changes, e.g. because the notification area got resized.
348 * Return value: %TRUE if the icon was updated for the new
349 * size. Otherwise, GTK+ will scale the icon as necessary.
353 status_icon_signals [SIZE_CHANGED_SIGNAL] =
354 g_signal_new (I_("size_changed"),
355 G_TYPE_FROM_CLASS (gobject_class),
357 G_STRUCT_OFFSET (GtkStatusIconClass, size_changed),
358 g_signal_accumulator_true_handled,
360 _gtk_marshal_BOOLEAN__INT,
365 g_type_class_add_private (class, sizeof (GtkStatusIconPrivate));
368 #ifdef GDK_WINDOWING_WIN32
371 build_button_event (GtkStatusIconPrivate *priv,
376 GdkRectangle monitor0;
378 /* We know that gdk/win32 puts the primary monitor at index 0 */
379 gdk_screen_get_monitor_geometry (gdk_screen_get_default (), 0, &monitor0);
380 e->window = g_object_ref (gdk_get_default_root_window ());
381 e->send_event = TRUE;
382 e->time = GetTickCount ();
384 priv->last_click_x = e->x = pos.x + monitor0.x;
385 priv->last_click_y = e->y = pos.y + monitor0.y;
389 e->device = gdk_display_get_default ()->core_pointer;
396 GtkStatusIcon *status_icon;
397 GdkEventButton *event;
398 } ButtonCallbackData;
401 button_callback (gpointer data)
403 ButtonCallbackData *bc = (ButtonCallbackData *) data;
405 gtk_status_icon_button_press (bc->status_icon, bc->event);
407 gdk_event_free ((GdkEvent *) bc->event);
413 static UINT taskbar_created_msg = 0;
414 static GSList *status_icons = NULL;
416 static LRESULT CALLBACK
422 if (message == taskbar_created_msg)
426 for (rover = status_icons; rover != NULL; rover = rover->next)
428 GtkStatusIcon *status_icon = GTK_STATUS_ICON (rover->data);
429 GtkStatusIconPrivate *priv = status_icon->priv;
431 priv->nid.hWnd = hwnd;
432 priv->nid.uID = GPOINTER_TO_UINT (status_icon);
433 priv->nid.uCallbackMessage = WM_GTK_TRAY_NOTIFICATION;
434 priv->nid.uFlags = NIF_MESSAGE;
436 if (!Shell_NotifyIconW (NIM_ADD, &priv->nid))
438 g_warning ("%s:%d:Shell_NotifyIcon(NIM_ADD) failed", __FILE__, __LINE__-2);
439 priv->nid.hWnd = NULL;
443 gtk_status_icon_update_image (status_icon);
448 if (message == WM_GTK_TRAY_NOTIFICATION)
450 ButtonCallbackData *bc;
456 bc = g_new (ButtonCallbackData, 1);
457 bc->event = (GdkEventButton *) gdk_event_new (GDK_BUTTON_PRESS);
458 bc->status_icon = GTK_STATUS_ICON (wparam);
459 build_button_event (bc->status_icon->priv, bc->event, (lparam == WM_LBUTTONDOWN) ? 1 : 3);
460 g_idle_add (button_callback, bc);
469 return DefWindowProc (hwnd, message, wparam, lparam);
474 create_tray_observer (void)
477 static HWND hwnd = NULL;
479 HINSTANCE hmodule = GetModuleHandle (NULL);
484 taskbar_created_msg = RegisterWindowMessage("TaskbarCreated");
486 memset (&wclass, 0, sizeof(WNDCLASS));
487 wclass.lpszClassName = "gtkstatusicon-observer";
488 wclass.lpfnWndProc = wndproc;
489 wclass.hInstance = hmodule;
491 klass = RegisterClass (&wclass);
495 hwnd = CreateWindow (MAKEINTRESOURCE (klass),
497 0, 0, 1, 1, NULL, NULL,
501 UnregisterClass (MAKEINTRESOURCE(klass), hmodule);
511 gtk_status_icon_init (GtkStatusIcon *status_icon)
513 GtkStatusIconPrivate *priv;
515 priv = G_TYPE_INSTANCE_GET_PRIVATE (status_icon, GTK_TYPE_STATUS_ICON,
516 GtkStatusIconPrivate);
517 status_icon->priv = priv;
519 priv->storage_type = GTK_IMAGE_EMPTY;
520 priv->visible = TRUE;
522 #ifdef GDK_WINDOWING_X11
524 priv->image_width = 0;
525 priv->image_height = 0;
527 priv->tray_icon = GTK_WIDGET (_gtk_tray_icon_new (NULL));
529 gtk_widget_add_events (GTK_WIDGET (priv->tray_icon),
530 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
532 g_signal_connect_swapped (priv->tray_icon, "key-press-event",
533 G_CALLBACK (gtk_status_icon_key_press), status_icon);
534 g_signal_connect_swapped (priv->tray_icon, "popup-menu",
535 G_CALLBACK (gtk_status_icon_popup_menu), status_icon);
536 g_signal_connect_swapped (priv->tray_icon, "notify::embedded",
537 G_CALLBACK (gtk_status_icon_embedded_changed), status_icon);
538 g_signal_connect_swapped (priv->tray_icon, "notify::orientation",
539 G_CALLBACK (gtk_status_icon_orientation_changed), status_icon);
540 g_signal_connect_swapped (priv->tray_icon, "button-press-event",
541 G_CALLBACK (gtk_status_icon_button_press), status_icon);
542 g_signal_connect_swapped (priv->tray_icon, "screen-changed",
543 G_CALLBACK (gtk_status_icon_screen_changed), status_icon);
544 priv->image = gtk_image_new ();
545 GTK_WIDGET_SET_FLAGS (priv->image, GTK_CAN_FOCUS);
546 gtk_container_add (GTK_CONTAINER (priv->tray_icon), priv->image);
547 gtk_widget_show (priv->image);
549 g_signal_connect_swapped (priv->image, "size-allocate",
550 G_CALLBACK (gtk_status_icon_size_allocate), status_icon);
554 #ifdef GDK_WINDOWING_WIN32
556 /* Get position and orientation of Windows taskbar. */
560 abd.cbSize = sizeof (abd);
561 SHAppBarMessage (ABM_GETTASKBARPOS, &abd);
562 if (abd.rc.bottom - abd.rc.top > abd.rc.right - abd.rc.left)
563 priv->orientation = GTK_ORIENTATION_VERTICAL;
565 priv->orientation = GTK_ORIENTATION_HORIZONTAL;
568 priv->last_click_x = priv->last_click_y = 0;
570 /* Are the system tray icons always 16 pixels square? */
572 priv->image_width = 16;
573 priv->image_height = 16;
575 priv->dummy_widget = gtk_label_new ("");
577 memset (&priv->nid, 0, sizeof (priv->nid));
579 priv->nid.hWnd = create_tray_observer ();
580 priv->nid.uID = GPOINTER_TO_UINT (status_icon);
581 priv->nid.uCallbackMessage = WM_GTK_TRAY_NOTIFICATION;
582 priv->nid.uFlags = NIF_MESSAGE;
584 if (!Shell_NotifyIconW (NIM_ADD, &priv->nid))
586 g_warning ("%s:%d:Shell_NotifyIcon(NIM_ADD) failed", __FILE__, __LINE__-2);
587 priv->nid.hWnd = NULL;
590 status_icons = g_slist_append (status_icons, status_icon);
594 #ifdef GDK_WINDOWING_QUARTZ
595 priv->dummy_widget = gtk_label_new ("");
599 priv->status_item = [[GtkQuartzStatusIcon alloc] initWithStatusIcon:status_icon];
601 priv->image_width = priv->image_height = [priv->status_item getHeight];
602 priv->size = priv->image_height;
610 gtk_status_icon_constructor (GType type,
611 guint n_construct_properties,
612 GObjectConstructParam *construct_params)
615 #ifdef GDK_WINDOWING_X11
616 GtkStatusIcon *status_icon;
617 GtkStatusIconPrivate *priv;
620 object = G_OBJECT_CLASS (gtk_status_icon_parent_class)->constructor (type,
621 n_construct_properties,
624 #ifdef GDK_WINDOWING_X11
625 status_icon = GTK_STATUS_ICON (object);
626 priv = status_icon->priv;
629 gtk_widget_show (priv->tray_icon);
636 gtk_status_icon_finalize (GObject *object)
638 GtkStatusIcon *status_icon = GTK_STATUS_ICON (object);
639 GtkStatusIconPrivate *priv = status_icon->priv;
641 gtk_status_icon_disable_blinking (status_icon);
643 gtk_status_icon_reset_image_data (status_icon);
645 if (priv->blank_icon)
646 g_object_unref (priv->blank_icon);
647 priv->blank_icon = NULL;
649 #ifdef GDK_WINDOWING_X11
650 gtk_widget_destroy (priv->tray_icon);
653 #ifdef GDK_WINDOWING_WIN32
654 if (priv->nid.hWnd != NULL && priv->visible)
655 Shell_NotifyIconW (NIM_DELETE, &priv->nid);
657 DestroyIcon (priv->nid.hIcon);
659 gtk_widget_destroy (priv->dummy_widget);
661 status_icons = g_slist_remove (status_icons, status_icon);
664 #ifdef GDK_WINDOWING_QUARTZ
666 [priv->status_item release];
670 G_OBJECT_CLASS (gtk_status_icon_parent_class)->finalize (object);
674 gtk_status_icon_set_property (GObject *object,
679 GtkStatusIcon *status_icon = GTK_STATUS_ICON (object);
684 gtk_status_icon_set_from_pixbuf (status_icon, g_value_get_object (value));
687 gtk_status_icon_set_from_file (status_icon, g_value_get_string (value));
690 gtk_status_icon_set_from_stock (status_icon, g_value_get_string (value));
693 gtk_status_icon_set_from_icon_name (status_icon, g_value_get_string (value));
696 gtk_status_icon_set_screen (status_icon, g_value_get_object (value));
699 gtk_status_icon_set_blinking (status_icon, g_value_get_boolean (value));
702 gtk_status_icon_set_visible (status_icon, g_value_get_boolean (value));
705 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
711 gtk_status_icon_get_property (GObject *object,
716 GtkStatusIcon *status_icon = GTK_STATUS_ICON (object);
717 GtkStatusIconPrivate *priv = status_icon->priv;
719 /* The "getter" functions whine if you try to get the wrong
720 * storage type. This function is instead robust against that,
721 * so that GUI builders don't have to jump through hoops
728 if (priv->storage_type != GTK_IMAGE_PIXBUF)
729 g_value_set_object (value, NULL);
731 g_value_set_object (value, gtk_status_icon_get_pixbuf (status_icon));
734 if (priv->storage_type != GTK_IMAGE_STOCK)
735 g_value_set_string (value, NULL);
737 g_value_set_string (value, gtk_status_icon_get_stock (status_icon));
740 if (priv->storage_type != GTK_IMAGE_ICON_NAME)
741 g_value_set_string (value, NULL);
743 g_value_set_string (value, gtk_status_icon_get_icon_name (status_icon));
745 case PROP_STORAGE_TYPE:
746 g_value_set_enum (value, gtk_status_icon_get_storage_type (status_icon));
749 g_value_set_int (value, gtk_status_icon_get_size (status_icon));
752 g_value_set_object (value, gtk_status_icon_get_screen (status_icon));
755 g_value_set_boolean (value, gtk_status_icon_get_blinking (status_icon));
758 g_value_set_boolean (value, gtk_status_icon_get_visible (status_icon));
761 g_value_set_boolean (value, gtk_status_icon_is_embedded (status_icon));
763 case PROP_ORIENTATION:
764 #ifdef GDK_WINDOWING_X11
765 g_value_set_enum (value, _gtk_tray_icon_get_orientation (GTK_TRAY_ICON (status_icon->priv->tray_icon)));
767 #ifdef GDK_WINDOWING_WIN32
768 g_value_set_enum (value, status_icon->priv->orientation);
772 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
778 * gtk_status_icon_new:
780 * Creates an empty status icon object.
782 * Return value: a new #GtkStatusIcon
787 gtk_status_icon_new (void)
789 return g_object_new (GTK_TYPE_STATUS_ICON, NULL);
793 * gtk_status_icon_new_from_pixbuf:
794 * @pixbuf: a #GdkPixbuf
796 * Creates a status icon displaying @pixbuf.
798 * The image will be scaled down to fit in the available
799 * space in the notification area, if necessary.
801 * Return value: a new #GtkStatusIcon
806 gtk_status_icon_new_from_pixbuf (GdkPixbuf *pixbuf)
808 return g_object_new (GTK_TYPE_STATUS_ICON,
814 * gtk_status_icon_new_from_file:
815 * @filename: a filename
817 * Creates a status icon displaying the file @filename.
819 * The image will be scaled down to fit in the available
820 * space in the notification area, if necessary.
822 * Return value: a new #GtkStatusIcon
827 gtk_status_icon_new_from_file (const gchar *filename)
829 return g_object_new (GTK_TYPE_STATUS_ICON,
835 * gtk_status_icon_new_from_stock:
836 * @stock_id: a stock icon id
838 * Creates a status icon displaying a stock icon. Sample stock icon
839 * names are #GTK_STOCK_OPEN, #GTK_STOCK_QUIT. You can register your
840 * own stock icon names, see gtk_icon_factory_add_default() and
841 * gtk_icon_factory_add().
843 * Return value: a new #GtkStatusIcon
848 gtk_status_icon_new_from_stock (const gchar *stock_id)
850 return g_object_new (GTK_TYPE_STATUS_ICON,
856 * gtk_status_icon_new_from_icon_name:
857 * @icon_name: an icon name
859 * Creates a status icon displaying an icon from the current icon theme.
860 * If the current icon theme is changed, the icon will be updated
863 * Return value: a new #GtkStatusIcon
868 gtk_status_icon_new_from_icon_name (const gchar *icon_name)
870 return g_object_new (GTK_TYPE_STATUS_ICON,
871 "icon-name", icon_name,
876 emit_activate_signal (GtkStatusIcon *status_icon)
878 g_signal_emit (status_icon,
879 status_icon_signals [ACTIVATE_SIGNAL], 0);
883 emit_popup_menu_signal (GtkStatusIcon *status_icon,
885 guint32 activate_time)
887 g_signal_emit (status_icon,
888 status_icon_signals [POPUP_MENU_SIGNAL], 0,
893 #ifdef GDK_WINDOWING_X11
896 emit_size_changed_signal (GtkStatusIcon *status_icon,
899 gboolean handled = FALSE;
901 g_signal_emit (status_icon,
902 status_icon_signals [SIZE_CHANGED_SIGNAL], 0,
912 gtk_status_icon_blank_icon (GtkStatusIcon *status_icon)
914 GtkStatusIconPrivate *priv = status_icon->priv;
916 if (priv->blank_icon)
920 width = gdk_pixbuf_get_width (priv->blank_icon);
921 height = gdk_pixbuf_get_height (priv->blank_icon);
924 if (width == priv->image_width && height == priv->image_height)
925 return priv->blank_icon;
928 g_object_unref (priv->blank_icon);
929 priv->blank_icon = NULL;
933 priv->blank_icon = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
936 if (priv->blank_icon)
937 gdk_pixbuf_fill (priv->blank_icon, 0);
939 return priv->blank_icon;
942 #ifdef GDK_WINDOWING_X11
945 find_icon_size (GtkWidget *widget,
949 GtkSettings *settings;
953 screen = gtk_widget_get_screen (widget);
956 return GTK_ICON_SIZE_MENU;
958 settings = gtk_settings_get_for_screen (screen);
961 size = GTK_ICON_SIZE_MENU;
963 for (s = GTK_ICON_SIZE_MENU; s < GTK_ICON_SIZE_DIALOG; s++)
965 if (gtk_icon_size_lookup_for_settings (settings, s, &w, &h) &&
966 w <= pixel_size && h <= pixel_size)
968 d = MAX (pixel_size - w, pixel_size - h);
983 gtk_status_icon_update_image (GtkStatusIcon *status_icon)
985 GtkStatusIconPrivate *priv = status_icon->priv;
986 #ifdef GDK_WINDOWING_WIN32
992 #ifdef GDK_WINDOWING_X11
993 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image),
994 gtk_status_icon_blank_icon (status_icon));
996 #ifdef GDK_WINDOWING_WIN32
997 prev_hicon = priv->nid.hIcon;
998 priv->nid.hIcon = gdk_win32_pixbuf_to_hicon_libgtk_only (gtk_status_icon_blank_icon (status_icon));
999 priv->nid.uFlags |= NIF_ICON;
1000 if (priv->nid.hWnd != NULL && priv->visible)
1001 if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
1002 g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
1004 DestroyIcon (prev_hicon);
1006 #ifdef GDK_WINDOWING_QUARTZ
1008 [priv->status_item setImage:gtk_status_icon_blank_icon (status_icon)];
1009 QUARTZ_POOL_RELEASE;
1014 switch (priv->storage_type)
1016 case GTK_IMAGE_PIXBUF:
1020 pixbuf = priv->image_data.pixbuf;
1031 width = gdk_pixbuf_get_width (pixbuf);
1032 height = gdk_pixbuf_get_height (pixbuf);
1034 if (width > size || height > size)
1035 scaled = gdk_pixbuf_scale_simple (pixbuf,
1038 GDK_INTERP_BILINEAR);
1040 scaled = g_object_ref (pixbuf);
1042 #ifdef GDK_WINDOWING_X11
1043 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), scaled);
1045 #ifdef GDK_WINDOWING_WIN32
1046 prev_hicon = priv->nid.hIcon;
1047 priv->nid.hIcon = gdk_win32_pixbuf_to_hicon_libgtk_only (scaled);
1048 priv->nid.uFlags |= NIF_ICON;
1049 if (priv->nid.hWnd != NULL && priv->visible)
1050 if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
1051 g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
1053 DestroyIcon (prev_hicon);
1055 #ifdef GDK_WINDOWING_QUARTZ
1057 [priv->status_item setImage:scaled];
1058 QUARTZ_POOL_RELEASE;
1061 g_object_unref (scaled);
1065 #ifdef GDK_WINDOWING_X11
1066 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), NULL);
1068 #ifdef GDK_WINDOWING_WIN32
1069 priv->nid.uFlags &= ~NIF_ICON;
1070 if (priv->nid.hWnd != NULL && priv->visible)
1071 if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
1072 g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
1074 #ifdef GDK_WINDOWING_QUARTZ
1075 [priv->status_item setImage:NULL];
1081 case GTK_IMAGE_STOCK:
1083 #ifdef GDK_WINDOWING_X11
1084 GtkIconSize size = find_icon_size (priv->image, priv->size);
1085 gtk_image_set_from_stock (GTK_IMAGE (priv->image),
1086 priv->image_data.stock_id,
1089 #ifdef GDK_WINDOWING_WIN32
1092 gtk_widget_render_icon (priv->dummy_widget,
1093 priv->image_data.stock_id,
1094 GTK_ICON_SIZE_SMALL_TOOLBAR,
1097 prev_hicon = priv->nid.hIcon;
1098 priv->nid.hIcon = gdk_win32_pixbuf_to_hicon_libgtk_only (pixbuf);
1099 priv->nid.uFlags |= NIF_ICON;
1100 if (priv->nid.hWnd != NULL && priv->visible)
1101 if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
1102 g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
1104 DestroyIcon (prev_hicon);
1105 g_object_unref (pixbuf);
1108 #ifdef GDK_WINDOWING_QUARTZ
1112 pixbuf = gtk_widget_render_icon (priv->dummy_widget,
1113 priv->image_data.stock_id,
1114 GTK_ICON_SIZE_SMALL_TOOLBAR,
1117 [priv->status_item setImage:pixbuf];
1118 QUARTZ_POOL_RELEASE;
1119 g_object_unref (pixbuf);
1125 case GTK_IMAGE_ICON_NAME:
1127 #ifdef GDK_WINDOWING_X11
1128 GtkIconSize size = find_icon_size (priv->image, priv->size);
1129 gtk_image_set_from_icon_name (GTK_IMAGE (priv->image),
1130 priv->image_data.icon_name,
1133 #ifdef GDK_WINDOWING_WIN32
1136 gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
1137 priv->image_data.icon_name,
1141 prev_hicon = priv->nid.hIcon;
1142 priv->nid.hIcon = gdk_win32_pixbuf_to_hicon_libgtk_only (pixbuf);
1143 priv->nid.uFlags |= NIF_ICON;
1144 if (priv->nid.hWnd != NULL && priv->visible)
1145 if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
1146 g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
1148 DestroyIcon (prev_hicon);
1149 g_object_unref (pixbuf);
1152 #ifdef GDK_WINDOWING_QUARTZ
1156 pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
1157 priv->image_data.icon_name,
1162 [priv->status_item setImage:pixbuf];
1163 QUARTZ_POOL_RELEASE;
1164 g_object_unref (pixbuf);
1171 case GTK_IMAGE_EMPTY:
1172 #ifdef GDK_WINDOWING_X11
1173 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), NULL);
1175 #ifdef GDK_WINDOWING_WIN32
1176 priv->nid.uFlags &= ~NIF_ICON;
1177 if (priv->nid.hWnd != NULL && priv->visible)
1178 if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
1179 g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
1181 #ifdef GDK_WINDOWING_QUARTZ
1184 [priv->status_item setImage:NULL];
1185 QUARTZ_POOL_RELEASE;
1190 g_assert_not_reached ();
1195 #ifdef GDK_WINDOWING_X11
1198 gtk_status_icon_size_allocate (GtkStatusIcon *status_icon,
1199 GtkAllocation *allocation)
1201 GtkStatusIconPrivate *priv = status_icon->priv;
1202 GtkOrientation orientation;
1205 orientation = _gtk_tray_icon_get_orientation (GTK_TRAY_ICON (priv->tray_icon));
1207 if (orientation == GTK_ORIENTATION_HORIZONTAL)
1208 size = allocation->height;
1210 size = allocation->width;
1212 priv->image_width = allocation->width - GTK_MISC (priv->image)->xpad * 2;
1213 priv->image_height = allocation->height - GTK_MISC (priv->image)->ypad * 2;
1215 if (priv->size != size)
1219 g_object_notify (G_OBJECT (status_icon), "size");
1221 if (!emit_size_changed_signal (status_icon, size))
1222 gtk_status_icon_update_image (status_icon);
1227 gtk_status_icon_screen_changed (GtkStatusIcon *status_icon,
1228 GdkScreen *old_screen)
1230 GtkStatusIconPrivate *priv = status_icon->priv;
1232 if (gtk_widget_get_screen (priv->tray_icon) != old_screen)
1234 g_object_notify (G_OBJECT (status_icon), "screen");
1240 #ifdef GDK_WINDOWING_X11
1243 gtk_status_icon_embedded_changed (GtkStatusIcon *status_icon)
1245 g_object_notify (G_OBJECT (status_icon), "embedded");
1249 gtk_status_icon_orientation_changed (GtkStatusIcon *status_icon)
1251 g_object_notify (G_OBJECT (status_icon), "orientation");
1255 gtk_status_icon_key_press (GtkStatusIcon *status_icon,
1258 guint state, keyval;
1260 state = event->state & gtk_accelerator_get_default_mod_mask ();
1261 keyval = event->keyval;
1263 (keyval == GDK_Return ||
1264 keyval == GDK_KP_Enter ||
1265 keyval == GDK_ISO_Enter ||
1266 keyval == GDK_space ||
1267 keyval == GDK_KP_Space))
1269 emit_activate_signal (status_icon);
1277 gtk_status_icon_popup_menu (GtkStatusIcon *status_icon)
1279 emit_popup_menu_signal (status_icon, 0, gtk_get_current_event_time ());
1285 gtk_status_icon_button_press (GtkStatusIcon *status_icon,
1286 GdkEventButton *event)
1288 if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
1290 emit_activate_signal (status_icon);
1293 else if (event->button == 3 && event->type == GDK_BUTTON_PRESS)
1295 emit_popup_menu_signal (status_icon, event->button, event->time);
1303 gtk_status_icon_reset_image_data (GtkStatusIcon *status_icon)
1305 GtkStatusIconPrivate *priv = status_icon->priv;
1307 switch (priv->storage_type)
1309 case GTK_IMAGE_PIXBUF:
1310 if (priv->image_data.pixbuf)
1311 g_object_unref (priv->image_data.pixbuf);
1312 priv->image_data.pixbuf = NULL;
1313 g_object_notify (G_OBJECT (status_icon), "pixbuf");
1316 case GTK_IMAGE_STOCK:
1317 g_free (priv->image_data.stock_id);
1318 priv->image_data.stock_id = NULL;
1320 g_object_notify (G_OBJECT (status_icon), "stock");
1323 case GTK_IMAGE_ICON_NAME:
1324 g_free (priv->image_data.icon_name);
1325 priv->image_data.icon_name = NULL;
1327 g_object_notify (G_OBJECT (status_icon), "icon-name");
1330 case GTK_IMAGE_EMPTY:
1333 g_assert_not_reached ();
1337 priv->storage_type = GTK_IMAGE_EMPTY;
1338 g_object_notify (G_OBJECT (status_icon), "storage-type");
1342 gtk_status_icon_set_image (GtkStatusIcon *status_icon,
1343 GtkImageType storage_type,
1346 GtkStatusIconPrivate *priv = status_icon->priv;
1348 g_object_freeze_notify (G_OBJECT (status_icon));
1350 gtk_status_icon_reset_image_data (status_icon);
1352 priv->storage_type = storage_type;
1353 g_object_notify (G_OBJECT (status_icon), "storage-type");
1355 switch (storage_type)
1357 case GTK_IMAGE_PIXBUF:
1358 priv->image_data.pixbuf = (GdkPixbuf *)data;
1359 g_object_notify (G_OBJECT (status_icon), "pixbuf");
1361 case GTK_IMAGE_STOCK:
1362 priv->image_data.stock_id = g_strdup ((const gchar *)data);
1363 g_object_notify (G_OBJECT (status_icon), "stock");
1365 case GTK_IMAGE_ICON_NAME:
1366 priv->image_data.icon_name = g_strdup ((const gchar *)data);
1367 g_object_notify (G_OBJECT (status_icon), "icon-name");
1370 g_warning ("Image type %u not handled by GtkStatusIcon", storage_type);
1373 g_object_thaw_notify (G_OBJECT (status_icon));
1375 gtk_status_icon_update_image (status_icon);
1379 * gtk_status_icon_set_from_pixbuf:
1380 * @status_icon: a #GtkStatusIcon
1381 * @pixbuf: a #GdkPixbuf or %NULL
1383 * Makes @status_icon display @pixbuf.
1384 * See gtk_status_icon_new_from_pixbuf() for details.
1389 gtk_status_icon_set_from_pixbuf (GtkStatusIcon *status_icon,
1392 g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1393 g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));
1396 g_object_ref (pixbuf);
1398 gtk_status_icon_set_image (status_icon, GTK_IMAGE_PIXBUF,
1403 * gtk_status_icon_set_from_file:
1404 * @status_icon: a #GtkStatusIcon
1405 * @filename: a filename
1407 * Makes @status_icon display the file @filename.
1408 * See gtk_status_icon_new_from_file() for details.
1413 gtk_status_icon_set_from_file (GtkStatusIcon *status_icon,
1414 const gchar *filename)
1418 g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1419 g_return_if_fail (filename != NULL);
1421 pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
1423 gtk_status_icon_set_from_pixbuf (status_icon, pixbuf);
1426 g_object_unref (pixbuf);
1430 * gtk_status_icon_set_from_stock:
1431 * @status_icon: a #GtkStatusIcon
1432 * @stock_id: a stock icon id
1434 * Makes @status_icon display the stock icon with the id @stock_id.
1435 * See gtk_status_icon_new_from_stock() for details.
1440 gtk_status_icon_set_from_stock (GtkStatusIcon *status_icon,
1441 const gchar *stock_id)
1443 g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1444 g_return_if_fail (stock_id != NULL);
1446 gtk_status_icon_set_image (status_icon, GTK_IMAGE_STOCK,
1447 (gpointer) stock_id);
1451 * gtk_status_icon_set_from_icon_name:
1452 * @status_icon: a #GtkStatusIcon
1453 * @icon_name: an icon name
1455 * Makes @status_icon display the icon named @icon_name from the
1456 * current icon theme.
1457 * See gtk_status_icon_new_from_icon_name() for details.
1462 gtk_status_icon_set_from_icon_name (GtkStatusIcon *status_icon,
1463 const gchar *icon_name)
1465 g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1466 g_return_if_fail (icon_name != NULL);
1468 gtk_status_icon_set_image (status_icon, GTK_IMAGE_ICON_NAME,
1469 (gpointer) icon_name);
1473 * gtk_status_icon_get_storage_type:
1474 * @status_icon: a #GtkStatusIcon
1476 * Gets the type of representation being used by the #GtkStatusIcon
1477 * to store image data. If the #GtkStatusIcon has no image data,
1478 * the return value will be %GTK_IMAGE_EMPTY.
1480 * Return value: the image representation being used
1485 gtk_status_icon_get_storage_type (GtkStatusIcon *status_icon)
1487 g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), GTK_IMAGE_EMPTY);
1489 return status_icon->priv->storage_type;
1492 * gtk_status_icon_get_pixbuf:
1493 * @status_icon: a #GtkStatusIcon
1495 * Gets the #GdkPixbuf being displayed by the #GtkStatusIcon.
1496 * The storage type of the status icon must be %GTK_IMAGE_EMPTY or
1497 * %GTK_IMAGE_PIXBUF (see gtk_status_icon_get_storage_type()).
1498 * The caller of this function does not own a reference to the
1501 * Return value: the displayed pixbuf, or %NULL if the image is empty.
1506 gtk_status_icon_get_pixbuf (GtkStatusIcon *status_icon)
1508 GtkStatusIconPrivate *priv;
1510 g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), NULL);
1512 priv = status_icon->priv;
1514 g_return_val_if_fail (priv->storage_type == GTK_IMAGE_PIXBUF ||
1515 priv->storage_type == GTK_IMAGE_EMPTY, NULL);
1517 if (priv->storage_type == GTK_IMAGE_EMPTY)
1518 priv->image_data.pixbuf = NULL;
1520 return priv->image_data.pixbuf;
1524 * gtk_status_icon_get_stock:
1525 * @status_icon: a #GtkStatusIcon
1527 * Gets the id of the stock icon being displayed by the #GtkStatusIcon.
1528 * The storage type of the status icon must be %GTK_IMAGE_EMPTY or
1529 * %GTK_IMAGE_STOCK (see gtk_status_icon_get_storage_type()).
1530 * The returned string is owned by the #GtkStatusIcon and should not
1531 * be freed or modified.
1533 * Return value: stock id of the displayed stock icon,
1534 * or %NULL if the image is empty.
1538 G_CONST_RETURN gchar *
1539 gtk_status_icon_get_stock (GtkStatusIcon *status_icon)
1541 GtkStatusIconPrivate *priv;
1543 g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), NULL);
1545 priv = status_icon->priv;
1547 g_return_val_if_fail (priv->storage_type == GTK_IMAGE_STOCK ||
1548 priv->storage_type == GTK_IMAGE_EMPTY, NULL);
1550 if (priv->storage_type == GTK_IMAGE_EMPTY)
1551 priv->image_data.stock_id = NULL;
1553 return priv->image_data.stock_id;
1557 * gtk_status_icon_get_icon_name:
1558 * @status_icon: a #GtkStatusIcon
1560 * Gets the name of the icon being displayed by the #GtkStatusIcon.
1561 * The storage type of the status icon must be %GTK_IMAGE_EMPTY or
1562 * %GTK_IMAGE_ICON_NAME (see gtk_status_icon_get_storage_type()).
1563 * The returned string is owned by the #GtkStatusIcon and should not
1564 * be freed or modified.
1566 * Return value: name of the displayed icon, or %NULL if the image is empty.
1570 G_CONST_RETURN gchar *
1571 gtk_status_icon_get_icon_name (GtkStatusIcon *status_icon)
1573 GtkStatusIconPrivate *priv;
1575 g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), NULL);
1577 priv = status_icon->priv;
1579 g_return_val_if_fail (priv->storage_type == GTK_IMAGE_ICON_NAME ||
1580 priv->storage_type == GTK_IMAGE_EMPTY, NULL);
1582 if (priv->storage_type == GTK_IMAGE_EMPTY)
1583 priv->image_data.icon_name = NULL;
1585 return priv->image_data.icon_name;
1589 * gtk_status_icon_get_size:
1590 * @status_icon: a #GtkStatusIcon
1592 * Gets the size in pixels that is available for the image.
1593 * Stock icons and named icons adapt their size automatically
1594 * if the size of the notification area changes. For other
1595 * storage types, the size-changed signal can be used to
1596 * react to size changes.
1598 * Note that the returned size is only meaningful while the
1599 * status icon is embedded (see gtk_status_icon_is_embedded()).
1601 * Return value: the size that is available for the image
1606 gtk_status_icon_get_size (GtkStatusIcon *status_icon)
1608 g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), 0);
1610 return status_icon->priv->size;
1614 * gtk_status_icon_set_screen:
1615 * @status_icon: a #GtkStatusIcon
1616 * @screen: a #GdkScreen
1618 * Sets the #GdkScreen where @status_icon is displayed; if
1619 * the icon is already mapped, it will be unmapped, and
1620 * then remapped on the new screen.
1625 gtk_status_icon_set_screen (GtkStatusIcon *status_icon,
1628 g_return_if_fail (GDK_IS_SCREEN (screen));
1630 #ifdef GDK_WINDOWING_X11
1631 gtk_window_set_screen (GTK_WINDOW (status_icon->priv->tray_icon), screen);
1636 * gtk_status_icon_get_screen:
1637 * @status_icon: a #GtkStatusIcon
1639 * Returns the #GdkScreen associated with @status_icon.
1641 * Return value: a #GdkScreen.
1646 gtk_status_icon_get_screen (GtkStatusIcon *status_icon)
1648 g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), NULL);
1650 #ifdef GDK_WINDOWING_X11
1651 return gtk_window_get_screen (GTK_WINDOW (status_icon->priv->tray_icon));
1653 return gdk_screen_get_default ();
1658 * gtk_status_icon_set_tooltip:
1659 * @status_icon: a #GtkStatusIcon
1660 * @tooltip_text: the tooltip text, or %NULL
1662 * Sets the tooltip of the status icon.
1667 gtk_status_icon_set_tooltip (GtkStatusIcon *status_icon,
1668 const gchar *tooltip_text)
1670 GtkStatusIconPrivate *priv;
1672 g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1674 priv = status_icon->priv;
1676 #ifdef GDK_WINDOWING_X11
1678 gtk_widget_set_tooltip_text (priv->tray_icon, tooltip_text);
1681 #ifdef GDK_WINDOWING_WIN32
1682 if (tooltip_text == NULL)
1683 priv->nid.uFlags &= ~NIF_TIP;
1686 WCHAR *wcs = g_utf8_to_utf16 (tooltip_text, -1, NULL, NULL, NULL);
1688 priv->nid.uFlags |= NIF_TIP;
1689 wcsncpy (priv->nid.szTip, wcs, G_N_ELEMENTS (priv->nid.szTip) - 1);
1690 priv->nid.szTip[G_N_ELEMENTS (priv->nid.szTip) - 1] = 0;
1693 if (priv->nid.hWnd != NULL && priv->visible)
1694 if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
1695 g_warning ("%s:%d:Shell_NotifyIconW(NIM_MODIFY) failed", __FILE__, __LINE__-1);
1697 #ifdef GDK_WINDOWING_QUARTZ
1699 [priv->status_item setToolTip:tooltip_text];
1700 QUARTZ_POOL_RELEASE;
1705 gtk_status_icon_blinker (GtkStatusIcon *status_icon)
1707 GtkStatusIconPrivate *priv = status_icon->priv;
1709 priv->blink_off = !priv->blink_off;
1711 gtk_status_icon_update_image (status_icon);
1717 gtk_status_icon_enable_blinking (GtkStatusIcon *status_icon)
1719 GtkStatusIconPrivate *priv = status_icon->priv;
1721 if (!priv->blinking_timeout)
1723 gtk_status_icon_blinker (status_icon);
1725 priv->blinking_timeout =
1726 gdk_threads_add_timeout (BLINK_TIMEOUT,
1727 (GSourceFunc) gtk_status_icon_blinker,
1733 gtk_status_icon_disable_blinking (GtkStatusIcon *status_icon)
1735 GtkStatusIconPrivate *priv = status_icon->priv;
1737 if (priv->blinking_timeout)
1739 g_source_remove (priv->blinking_timeout);
1740 priv->blinking_timeout = 0;
1741 priv->blink_off = FALSE;
1743 gtk_status_icon_update_image (status_icon);
1748 * gtk_status_icon_set_visible:
1749 * @status_icon: a #GtkStatusIcon
1750 * @visible: %TRUE to show the status icon, %FALSE to hide it
1752 * Shows or hides a status icon.
1757 gtk_status_icon_set_visible (GtkStatusIcon *status_icon,
1760 GtkStatusIconPrivate *priv;
1762 g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1764 priv = status_icon->priv;
1766 visible = visible != FALSE;
1768 if (priv->visible != visible)
1770 priv->visible = visible;
1772 #ifdef GDK_WINDOWING_X11
1774 gtk_widget_show (priv->tray_icon);
1775 else if (GTK_WIDGET_REALIZED (priv->tray_icon))
1777 gtk_widget_hide (priv->tray_icon);
1778 gtk_widget_unrealize (priv->tray_icon);
1781 #ifdef GDK_WINDOWING_WIN32
1782 if (priv->nid.hWnd != NULL)
1785 Shell_NotifyIconW (NIM_ADD, &priv->nid);
1787 Shell_NotifyIconW (NIM_DELETE, &priv->nid);
1790 #ifdef GDK_WINDOWING_QUARTZ
1792 [priv->status_item setVisible:visible];
1793 QUARTZ_POOL_RELEASE;
1795 g_object_notify (G_OBJECT (status_icon), "visible");
1800 * gtk_status_icon_get_visible:
1801 * @status_icon: a #GtkStatusIcon
1803 * Returns whether the status icon is visible or not.
1804 * Note that being visible does not guarantee that
1805 * the user can actually see the icon, see also
1806 * gtk_status_icon_is_embedded().
1808 * Return value: %TRUE if the status icon is visible
1813 gtk_status_icon_get_visible (GtkStatusIcon *status_icon)
1815 g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), FALSE);
1817 return status_icon->priv->visible;
1821 * gtk_status_icon_set_blinking:
1822 * @status_icon: a #GtkStatusIcon
1823 * @blinking: %TRUE to turn blinking on, %FALSE to turn it off
1825 * Makes the status icon start or stop blinking.
1826 * Note that blinking user interface elements may be problematic
1827 * for some users, and thus may be turned off, in which case
1828 * this setting has no effect.
1833 gtk_status_icon_set_blinking (GtkStatusIcon *status_icon,
1836 GtkStatusIconPrivate *priv;
1838 g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
1840 priv = status_icon->priv;
1842 blinking = blinking != FALSE;
1844 if (priv->blinking != blinking)
1846 priv->blinking = blinking;
1849 gtk_status_icon_enable_blinking (status_icon);
1851 gtk_status_icon_disable_blinking (status_icon);
1853 g_object_notify (G_OBJECT (status_icon), "blinking");
1858 * gtk_status_icon_get_blinking:
1859 * @status_icon: a #GtkStatusIcon
1861 * Returns whether the icon is blinking, see
1862 * gtk_status_icon_set_blinking().
1864 * Return value: %TRUE if the icon is blinking
1869 gtk_status_icon_get_blinking (GtkStatusIcon *status_icon)
1871 g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), FALSE);
1873 return status_icon->priv->blinking;
1877 * gtk_status_icon_is_embedded:
1878 * @status_icon: a #GtkStatusIcon
1880 * Returns whether the status icon is embedded in a notification
1883 * Return value: %TRUE if the status icon is embedded in
1884 * a notification area.
1889 gtk_status_icon_is_embedded (GtkStatusIcon *status_icon)
1891 #ifdef GDK_WINDOWING_X11
1895 g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), FALSE);
1897 #ifdef GDK_WINDOWING_X11
1898 plug = GTK_PLUG (status_icon->priv->tray_icon);
1900 if (plug->socket_window)
1905 #ifdef GDK_WINDOWING_WIN32
1908 #ifdef GDK_WINDOWING_QUARTZ
1914 * gtk_status_icon_position_menu:
1915 * @menu: the #GtkMenu
1916 * @x: return location for the x position
1917 * @y: return location for the y position
1918 * @push_in: whether the first menu item should be offset (pushed in) to be
1919 * aligned with the menu popup position (only useful for GtkOptionMenu).
1920 * @user_data: the status icon to position the menu on
1922 * Menu positioning function to use with gtk_menu_popup()
1923 * to position @menu aligned to the status icon @user_data.
1928 gtk_status_icon_position_menu (GtkMenu *menu,
1934 #ifdef GDK_WINDOWING_X11
1935 GtkStatusIcon *status_icon;
1936 GtkStatusIconPrivate *priv;
1937 GtkTrayIcon *tray_icon;
1940 GtkTextDirection direction;
1941 GtkRequisition menu_req;
1942 GdkRectangle monitor;
1943 gint monitor_num, height, width, xoffset, yoffset;
1945 g_return_if_fail (GTK_IS_MENU (menu));
1946 g_return_if_fail (GTK_IS_STATUS_ICON (user_data));
1948 status_icon = GTK_STATUS_ICON (user_data);
1949 priv = status_icon->priv;
1950 tray_icon = GTK_TRAY_ICON (priv->tray_icon);
1951 widget = priv->tray_icon;
1953 direction = gtk_widget_get_direction (widget);
1955 screen = gtk_widget_get_screen (widget);
1956 gtk_menu_set_screen (menu, screen);
1958 monitor_num = gdk_screen_get_monitor_at_window (screen, widget->window);
1959 if (monitor_num < 0)
1961 gtk_menu_set_monitor (menu, monitor_num);
1963 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
1965 gdk_window_get_origin (widget->window, x, y);
1967 gtk_widget_size_request (GTK_WIDGET (menu), &menu_req);
1969 if (_gtk_tray_icon_get_orientation (tray_icon) == GTK_ORIENTATION_VERTICAL)
1972 height = widget->allocation.height;
1973 xoffset = widget->allocation.width;
1978 width = widget->allocation.width;
1981 yoffset = widget->allocation.height;
1984 if (direction == GTK_TEXT_DIR_RTL)
1986 if ((*x - (menu_req.width - width)) >= monitor.x)
1987 *x -= menu_req.width - width;
1988 else if ((*x + xoffset + menu_req.width) < (monitor.x + monitor.width))
1990 else if ((monitor.x + monitor.width - (*x + xoffset)) < *x)
1991 *x -= menu_req.width - width;
1997 if ((*x + xoffset + menu_req.width) < (monitor.x + monitor.width))
1999 else if ((*x - (menu_req.width - width)) >= monitor.x)
2000 *x -= menu_req.width - width;
2001 else if ((monitor.x + monitor.width - (*x + xoffset)) > *x)
2004 *x -= menu_req.width - width;
2007 if ((*y + yoffset + menu_req.height) < (monitor.y + monitor.height))
2009 else if ((*y - (menu_req.height - height)) >= monitor.y)
2010 *y -= menu_req.height - height;
2011 else if (monitor.y + monitor.height - (*y + yoffset) > *y)
2014 *y -= menu_req.height - height;
2017 #endif /* GDK_WINDOWING_X11 */
2019 #ifdef GDK_WINDOWING_WIN32
2020 GtkStatusIcon *status_icon;
2021 GtkStatusIconPrivate *priv;
2023 g_return_if_fail (GTK_IS_MENU (menu));
2024 g_return_if_fail (GTK_IS_STATUS_ICON (user_data));
2026 status_icon = GTK_STATUS_ICON (user_data);
2027 priv = status_icon->priv;
2029 *x = priv->last_click_x;
2030 *y = priv->last_click_y;
2036 * gtk_status_icon_get_geometry:
2037 * @status_icon: a #GtkStatusIcon
2038 * @screen: return location for the screen, or %NULL if the
2039 * information is not needed
2040 * @area: return location for the area occupied by the status
2042 * @orientation: return location for the orientation of the panel
2043 * in which the status icon is embedded, or %NULL. A panel
2044 * at the top or bottom of the screen is horizontal, a panel
2045 * at the left or right is vertical.
2047 * Obtains information about the location of the status icon
2048 * on screen. This information can be used to e.g. position
2049 * popups like notification bubbles.
2051 * See gtk_status_icon_position_menu() for a more convenient
2052 * alternative for positioning menus.
2054 * Note that some platforms do not allow GTK+ to provide
2055 * this information, and even on platforms that do allow it,
2056 * the information is not reliable unless the status icon
2057 * is embedded in a notification area, see
2058 * gtk_status_icon_is_embedded().
2060 * Return value: %TRUE if the location information has
2066 gtk_status_icon_get_geometry (GtkStatusIcon *status_icon,
2069 GtkOrientation *orientation)
2071 #ifdef GDK_WINDOWING_X11
2073 GtkStatusIconPrivate *priv;
2076 g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), FALSE);
2078 priv = status_icon->priv;
2079 widget = priv->tray_icon;
2082 *screen = gtk_widget_get_screen (widget);
2086 gdk_window_get_origin (widget->window, &x, &y);
2089 area->width = widget->allocation.width;
2090 area->height = widget->allocation.height;
2094 *orientation = _gtk_tray_icon_get_orientation (GTK_TRAY_ICON (widget));
2099 #endif /* GDK_WINDOWING_X11 */
2103 * gtk_status_icon_get_x11_window_id:
2104 * @status_icon: a #GtkStatusIcon
2106 * This function is only useful on the X11/freedesktop.org platform.
2107 * It returns a window ID for the widget in the underlying
2108 * status icon implementation. This is useful for the Galago
2109 * notification service, which can send a window ID in the protocol
2110 * in order for the server to position notification windows
2111 * pointing to a status icon reliably.
2113 * This function is not intended for other use cases which are
2114 * more likely to be met by one of the non-X11 specific methods, such
2115 * as gtk_status_icon_position_menu().
2117 * Return value: An 32 bit unsigned integer identifier for the
2118 * underlying X11 Window
2123 gtk_status_icon_get_x11_window_id (GtkStatusIcon *status_icon)
2125 #ifdef GDK_WINDOWING_X11
2126 gtk_widget_realize (GTK_WIDGET (status_icon->priv->tray_icon));
2127 return GDK_WINDOW_XID (GTK_WIDGET (status_icon->priv->tray_icon)->window);
2133 #define __GTK_STATUS_ICON_C__
2134 #include "gtkaliasdef.c"