* Copyright (C) 2003 Sun Microsystems, Inc.
* Copyright (C) 2005 Hans Breuer <hans@breuer.org>
* Copyright (C) 2005 Novell, Inc.
+ * Copyright (C) 2006 Imendio AB
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* Mark McLoughlin <mark@skynet.ie>
* Hans Breuer <hans@breuer.org>
* Tor Lillqvist <tml@novell.com>
+ * Mikael Hallendal <micke@imendio.com>
*/
#include <config.h>
#include "gtkintl.h"
#include "gtkiconfactory.h"
+#include "gtkmain.h"
#include "gtkmarshalers.h"
-#include "gtktooltips.h"
#include "gtktrayicon.h"
#include "gtkprivate.h"
#include "gtkwidget.h"
-#include "gtkalias.h"
+#ifdef GDK_WINDOWING_X11
+#include "gdk/x11/gdkx.h"
+#endif
#ifdef GDK_WINDOWING_WIN32
#include "gtkicontheme.h"
#define WM_GTK_TRAY_NOTIFICATION (WM_USER+1)
#endif
+#ifdef GDK_WINDOWING_QUARTZ
+#include "gtkicontheme.h"
+#include "gtklabel.h"
+#endif
+
+#include "gdkkeysyms.h"
+
+#include "gtkalias.h"
+
#define BLINK_TIMEOUT 500
enum
PROP_ICON_NAME,
PROP_STORAGE_TYPE,
PROP_SIZE,
+ PROP_SCREEN,
PROP_VISIBLE,
+ PROP_ORIENTATION,
+ PROP_EMBEDDED,
PROP_BLINKING
};
LAST_SIGNAL
};
+static guint status_icon_signals [LAST_SIGNAL] = { 0 };
+
+#ifdef GDK_WINDOWING_QUARTZ
+#include "gtkstatusicon-quartz.c"
+#endif
+
struct _GtkStatusIconPrivate
{
#ifdef GDK_WINDOWING_X11
GtkWidget *tray_icon;
GtkWidget *image;
- GtkTooltips *tooltips;
#endif
#ifdef GDK_WINDOWING_WIN32
GtkWidget *dummy_widget;
NOTIFYICONDATAW nid;
+ gint last_click_x, last_click_y;
+ GtkOrientation orientation;
+#endif
+
+#ifdef GDK_WINDOWING_QUARTZ
+ GtkWidget *dummy_widget;
+ GtkQuartzStatusIcon *status_item;
#endif
gint size;
guint visible : 1;
};
+static GObject* gtk_status_icon_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params);
static void gtk_status_icon_finalize (GObject *object);
static void gtk_status_icon_set_property (GObject *object,
guint prop_id,
#ifdef GDK_WINDOWING_X11
static void gtk_status_icon_size_allocate (GtkStatusIcon *status_icon,
GtkAllocation *allocation);
+static void gtk_status_icon_screen_changed (GtkStatusIcon *status_icon,
+ GdkScreen *old_screen);
+static void gtk_status_icon_embedded_changed (GtkStatusIcon *status_icon);
+static void gtk_status_icon_orientation_changed (GtkStatusIcon *status_icon);
+
+static gboolean gtk_status_icon_key_press (GtkStatusIcon *status_icon,
+ GdkEventKey *event);
+static void gtk_status_icon_popup_menu (GtkStatusIcon *status_icon);
#endif
static gboolean gtk_status_icon_button_press (GtkStatusIcon *status_icon,
GdkEventButton *event);
static void gtk_status_icon_disable_blinking (GtkStatusIcon *status_icon);
static void gtk_status_icon_reset_image_data (GtkStatusIcon *status_icon);
-
-
-static guint status_icon_signals [LAST_SIGNAL] = { 0 };
+static void gtk_status_icon_update_image (GtkStatusIcon *status_icon);
G_DEFINE_TYPE (GtkStatusIcon, gtk_status_icon, G_TYPE_OBJECT)
{
GObjectClass *gobject_class = (GObjectClass *) class;
+ gobject_class->constructor = gtk_status_icon_constructor;
gobject_class->finalize = gtk_status_icon_finalize;
gobject_class->set_property = gtk_status_icon_set_property;
gobject_class->get_property = gtk_status_icon_get_property;
0,
GTK_PARAM_READABLE));
+ g_object_class_install_property (gobject_class,
+ PROP_SCREEN,
+ g_param_spec_object ("screen",
+ P_("Screen"),
+ P_("The screen where this status icon will be displayed"),
+ GDK_TYPE_SCREEN,
+ GTK_PARAM_READWRITE));
+
g_object_class_install_property (gobject_class,
PROP_BLINKING,
g_param_spec_boolean ("blinking",
GTK_PARAM_READWRITE));
+ /**
+ * GtkStatusIcon:embedded:
+ *
+ * %TRUE if the statusicon is embedded in a notification area.
+ *
+ * Since: 2.12
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_EMBEDDED,
+ g_param_spec_boolean ("embedded",
+ P_("Embedded"),
+ P_("Whether or not the status icon is embedded"),
+ FALSE,
+ GTK_PARAM_READABLE));
+
+ /**
+ * GtkStatusIcon:orientation:
+ *
+ * The orientation of the tray in which the statusicon
+ * is embedded.
+ *
+ * Since: 2.12
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_ORIENTATION,
+ g_param_spec_enum ("orientation",
+ P_("Orientation"),
+ P_("The orientation of the tray"),
+ GTK_TYPE_ORIENTATION,
+ GTK_ORIENTATION_HORIZONTAL,
+ GTK_PARAM_READABLE));
+
+
/**
* GtkStatusIcon::activate:
* @status_icon: the object which received the signal
* Since: 2.10
*/
status_icon_signals [POPUP_MENU_SIGNAL] =
- g_signal_new (I_("popup-menu"),
+ g_signal_new (I_("popup_menu"),
G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GtkStatusIconClass, popup_menu),
* Since: 2.10
*/
status_icon_signals [SIZE_CHANGED_SIGNAL] =
- g_signal_new (I_("size-changed"),
+ g_signal_new (I_("size_changed"),
G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkStatusIconClass, size_changed),
#ifdef GDK_WINDOWING_WIN32
static void
-build_button_event (GdkEventButton *e,
- GdkEventType type,
- guint button)
+build_button_event (GtkStatusIconPrivate *priv,
+ GdkEventButton *e,
+ guint button)
{
POINT pos;
GdkRectangle monitor0;
/* We know that gdk/win32 puts the primary monitor at index 0 */
gdk_screen_get_monitor_geometry (gdk_screen_get_default (), 0, &monitor0);
- e->type = type;
- e->window = gdk_get_default_root_window ();
+ e->window = g_object_ref (gdk_get_default_root_window ());
e->send_event = TRUE;
e->time = GetTickCount ();
GetCursorPos (&pos);
- e->x = pos.x + monitor0.x;
- e->y = pos.y + monitor0.y;
+ priv->last_click_x = e->x = pos.x + monitor0.x;
+ priv->last_click_y = e->y = pos.y + monitor0.y;
e->axes = NULL;
e->state = 0;
e->button = button;
e->y_root = e->y;
}
+typedef struct
+{
+ GtkStatusIcon *status_icon;
+ GdkEventButton *event;
+} ButtonCallbackData;
+
+static gboolean
+button_callback (gpointer data)
+{
+ ButtonCallbackData *bc = (ButtonCallbackData *) data;
+
+ gtk_status_icon_button_press (bc->status_icon, bc->event);
+
+ gdk_event_free ((GdkEvent *) bc->event);
+ g_free (data);
+
+ return FALSE;
+}
+
+static UINT taskbar_created_msg = 0;
+static GSList *status_icons = NULL;
+
static LRESULT CALLBACK
wndproc (HWND hwnd,
UINT message,
WPARAM wparam,
LPARAM lparam)
{
+ if (message == taskbar_created_msg)
+ {
+ GSList *rover;
+
+ for (rover = status_icons; rover != NULL; rover = rover->next)
+ {
+ GtkStatusIcon *status_icon = GTK_STATUS_ICON (rover->data);
+ GtkStatusIconPrivate *priv = status_icon->priv;
+
+ priv->nid.hWnd = hwnd;
+ priv->nid.uID = GPOINTER_TO_UINT (status_icon);
+ priv->nid.uCallbackMessage = WM_GTK_TRAY_NOTIFICATION;
+ priv->nid.uFlags = NIF_MESSAGE;
+
+ if (!Shell_NotifyIconW (NIM_ADD, &priv->nid))
+ {
+ g_warning ("%s:%d:Shell_NotifyIcon(NIM_ADD) failed", __FILE__, __LINE__-2);
+ priv->nid.hWnd = NULL;
+ continue;
+ }
+
+ gtk_status_icon_update_image (status_icon);
+ }
+ return 0;
+ }
+
if (message == WM_GTK_TRAY_NOTIFICATION)
{
- GdkEventButton e;
- GtkStatusIcon *status_icon = GTK_STATUS_ICON (wparam);
+ ButtonCallbackData *bc;
switch (lparam)
{
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
- build_button_event (&e, GDK_BUTTON_PRESS,
- (lparam == WM_LBUTTONDOWN) ? 1 : 3);
- gtk_status_icon_button_press (status_icon, &e);
+ bc = g_new (ButtonCallbackData, 1);
+ bc->event = (GdkEventButton *) gdk_event_new (GDK_BUTTON_PRESS);
+ bc->status_icon = GTK_STATUS_ICON (wparam);
+ build_button_event (bc->status_icon->priv, bc->event, (lparam == WM_LBUTTONDOWN) ? 1 : 3);
+ g_idle_add (button_callback, bc);
break;
default :
break;
if (hwnd)
return hwnd;
+ taskbar_created_msg = RegisterWindowMessage("TaskbarCreated");
+
memset (&wclass, 0, sizeof(WNDCLASS));
wclass.lpszClassName = "gtkstatusicon-observer";
wclass.lpfnWndProc = wndproc;
if (!klass)
return NULL;
- hwnd = CreateWindow (MAKEINTRESOURCE(klass),
+ hwnd = CreateWindow (MAKEINTRESOURCE (klass),
NULL, WS_POPUP,
0, 0, 1, 1, NULL, NULL,
hmodule, NULL);
gtk_widget_add_events (GTK_WIDGET (priv->tray_icon),
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
+ g_signal_connect_swapped (priv->tray_icon, "key-press-event",
+ G_CALLBACK (gtk_status_icon_key_press), status_icon);
+ g_signal_connect_swapped (priv->tray_icon, "popup-menu",
+ G_CALLBACK (gtk_status_icon_popup_menu), status_icon);
+ g_signal_connect_swapped (priv->tray_icon, "notify::embedded",
+ G_CALLBACK (gtk_status_icon_embedded_changed), status_icon);
+ g_signal_connect_swapped (priv->tray_icon, "notify::orientation",
+ G_CALLBACK (gtk_status_icon_orientation_changed), status_icon);
g_signal_connect_swapped (priv->tray_icon, "button-press-event",
G_CALLBACK (gtk_status_icon_button_press), status_icon);
+ g_signal_connect_swapped (priv->tray_icon, "screen-changed",
+ G_CALLBACK (gtk_status_icon_screen_changed), status_icon);
priv->image = gtk_image_new ();
+ GTK_WIDGET_SET_FLAGS (priv->image, GTK_CAN_FOCUS);
gtk_container_add (GTK_CONTAINER (priv->tray_icon), priv->image);
+ gtk_widget_show (priv->image);
g_signal_connect_swapped (priv->image, "size-allocate",
G_CALLBACK (gtk_status_icon_size_allocate), status_icon);
- gtk_widget_show (priv->image);
- gtk_widget_show (priv->tray_icon);
-
- status_icon->priv->tooltips = gtk_tooltips_new ();
- g_object_ref_sink (priv->tooltips);
#endif
#ifdef GDK_WINDOWING_WIN32
- /* Code to get position and orientation of Windows taskbar. Not needed
- * currently, kept for reference.
- */
-#if 0
+ /* Get position and orientation of Windows taskbar. */
{
APPBARDATA abd;
abd.cbSize = sizeof (abd);
SHAppBarMessage (ABM_GETTASKBARPOS, &abd);
if (abd.rc.bottom - abd.rc.top > abd.rc.right - abd.rc.left)
- orientation = GTK_ORIENTATION_VERTICAL;
+ priv->orientation = GTK_ORIENTATION_VERTICAL;
else
- orientation = GTK_ORIENTATION_HORIZONTAL;
+ priv->orientation = GTK_ORIENTATION_HORIZONTAL;
}
-#endif
+
+ priv->last_click_x = priv->last_click_y = 0;
/* Are the system tray icons always 16 pixels square? */
priv->size = 16;
g_warning ("%s:%d:Shell_NotifyIcon(NIM_ADD) failed", __FILE__, __LINE__-2);
priv->nid.hWnd = NULL;
}
+
+ status_icons = g_slist_append (status_icons, status_icon);
+
#endif
+
+#ifdef GDK_WINDOWING_QUARTZ
+ priv->dummy_widget = gtk_label_new ("");
+
+ QUARTZ_POOL_ALLOC;
+
+ priv->status_item = [[GtkQuartzStatusIcon alloc] initWithStatusIcon:status_icon];
+
+ priv->image_width = priv->image_height = [priv->status_item getHeight];
+ priv->size = priv->image_height;
+
+ QUARTZ_POOL_RELEASE;
+
+#endif
+}
+
+static GObject*
+gtk_status_icon_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params)
+{
+ GObject *object;
+#ifdef GDK_WINDOWING_X11
+ GtkStatusIcon *status_icon;
+ GtkStatusIconPrivate *priv;
+#endif
+
+ object = G_OBJECT_CLASS (gtk_status_icon_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_params);
+
+#ifdef GDK_WINDOWING_X11
+ status_icon = GTK_STATUS_ICON (object);
+ priv = status_icon->priv;
+
+ if (priv->visible)
+ gtk_widget_show (priv->tray_icon);
+#endif
+
+ return object;
}
static void
priv->blank_icon = NULL;
#ifdef GDK_WINDOWING_X11
- if (priv->tooltips)
- g_object_unref (priv->tooltips);
- priv->tooltips = NULL;
-
gtk_widget_destroy (priv->tray_icon);
#endif
#ifdef GDK_WINDOWING_WIN32
if (priv->nid.hWnd != NULL && priv->visible)
Shell_NotifyIconW (NIM_DELETE, &priv->nid);
+ if (priv->nid.hIcon)
+ DestroyIcon (priv->nid.hIcon);
gtk_widget_destroy (priv->dummy_widget);
+
+ status_icons = g_slist_remove (status_icons, status_icon);
+#endif
+
+#ifdef GDK_WINDOWING_QUARTZ
+ QUARTZ_POOL_ALLOC;
+ [priv->status_item release];
+ QUARTZ_POOL_RELEASE;
#endif
G_OBJECT_CLASS (gtk_status_icon_parent_class)->finalize (object);
case PROP_ICON_NAME:
gtk_status_icon_set_from_icon_name (status_icon, g_value_get_string (value));
break;
+ case PROP_SCREEN:
+ gtk_status_icon_set_screen (status_icon, g_value_get_object (value));
+ break;
case PROP_BLINKING:
gtk_status_icon_set_blinking (status_icon, g_value_get_boolean (value));
break;
case PROP_SIZE:
g_value_set_int (value, gtk_status_icon_get_size (status_icon));
break;
+ case PROP_SCREEN:
+ g_value_set_object (value, gtk_status_icon_get_screen (status_icon));
+ break;
case PROP_BLINKING:
g_value_set_boolean (value, gtk_status_icon_get_blinking (status_icon));
break;
case PROP_VISIBLE:
g_value_set_boolean (value, gtk_status_icon_get_visible (status_icon));
break;
+ case PROP_EMBEDDED:
+ g_value_set_boolean (value, gtk_status_icon_is_embedded (status_icon));
+ break;
+ case PROP_ORIENTATION:
+#ifdef GDK_WINDOWING_X11
+ g_value_set_enum (value, _gtk_tray_icon_get_orientation (GTK_TRAY_ICON (status_icon->priv->tray_icon)));
+#endif
+#ifdef GDK_WINDOWING_WIN32
+ g_value_set_enum (value, status_icon->priv->orientation);
+#endif
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
gtk_status_icon_update_image (GtkStatusIcon *status_icon)
{
GtkStatusIconPrivate *priv = status_icon->priv;
+#ifdef GDK_WINDOWING_WIN32
+ HICON prev_hicon;
+#endif
if (priv->blink_off)
{
gtk_status_icon_blank_icon (status_icon));
#endif
#ifdef GDK_WINDOWING_WIN32
+ prev_hicon = priv->nid.hIcon;
priv->nid.hIcon = gdk_win32_pixbuf_to_hicon_libgtk_only (gtk_status_icon_blank_icon (status_icon));
priv->nid.uFlags |= NIF_ICON;
if (priv->nid.hWnd != NULL && priv->visible)
if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
+ if (prev_hicon)
+ DestroyIcon (prev_hicon);
+#endif
+#ifdef GDK_WINDOWING_QUARTZ
+ QUARTZ_POOL_ALLOC;
+ [priv->status_item setImage:gtk_status_icon_blank_icon (status_icon)];
+ QUARTZ_POOL_RELEASE;
#endif
return;
}
gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), scaled);
#endif
#ifdef GDK_WINDOWING_WIN32
+ prev_hicon = priv->nid.hIcon;
priv->nid.hIcon = gdk_win32_pixbuf_to_hicon_libgtk_only (scaled);
priv->nid.uFlags |= NIF_ICON;
if (priv->nid.hWnd != NULL && priv->visible)
if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
+ if (prev_hicon)
+ DestroyIcon (prev_hicon);
#endif
+#ifdef GDK_WINDOWING_QUARTZ
+ QUARTZ_POOL_ALLOC;
+ [priv->status_item setImage:scaled];
+ QUARTZ_POOL_RELEASE;
+#endif
+
g_object_unref (scaled);
}
else
if (priv->nid.hWnd != NULL && priv->visible)
if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
+#endif
+#ifdef GDK_WINDOWING_QUARTZ
+ [priv->status_item setImage:NULL];
#endif
}
}
priv->image_data.stock_id,
GTK_ICON_SIZE_SMALL_TOOLBAR,
NULL);
+
+ prev_hicon = priv->nid.hIcon;
priv->nid.hIcon = gdk_win32_pixbuf_to_hicon_libgtk_only (pixbuf);
priv->nid.uFlags |= NIF_ICON;
if (priv->nid.hWnd != NULL && priv->visible)
if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
+ if (prev_hicon)
+ DestroyIcon (prev_hicon);
g_object_unref (pixbuf);
}
+#endif
+#ifdef GDK_WINDOWING_QUARTZ
+ {
+ GdkPixbuf *pixbuf;
+
+ pixbuf = gtk_widget_render_icon (priv->dummy_widget,
+ priv->image_data.stock_id,
+ GTK_ICON_SIZE_SMALL_TOOLBAR,
+ NULL);
+ QUARTZ_POOL_ALLOC;
+ [priv->status_item setImage:pixbuf];
+ QUARTZ_POOL_RELEASE;
+ g_object_unref (pixbuf);
+ }
#endif
}
break;
priv->size,
0, NULL);
+ prev_hicon = priv->nid.hIcon;
priv->nid.hIcon = gdk_win32_pixbuf_to_hicon_libgtk_only (pixbuf);
priv->nid.uFlags |= NIF_ICON;
if (priv->nid.hWnd != NULL && priv->visible)
if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
+ if (prev_hicon)
+ DestroyIcon (prev_hicon);
g_object_unref (pixbuf);
}
#endif
+#ifdef GDK_WINDOWING_QUARTZ
+ {
+ GdkPixbuf *pixbuf;
+
+ pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+ priv->image_data.icon_name,
+ priv->size,
+ 0, NULL);
+
+ QUARTZ_POOL_ALLOC;
+ [priv->status_item setImage:pixbuf];
+ QUARTZ_POOL_RELEASE;
+ g_object_unref (pixbuf);
+ }
+#endif
+
}
break;
if (priv->nid.hWnd != NULL && priv->visible)
if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1);
+#endif
+#ifdef GDK_WINDOWING_QUARTZ
+ {
+ QUARTZ_POOL_ALLOC;
+ [priv->status_item setImage:NULL];
+ QUARTZ_POOL_RELEASE;
+ }
#endif
break;
default:
}
}
+static void
+gtk_status_icon_screen_changed (GtkStatusIcon *status_icon,
+ GdkScreen *old_screen)
+{
+ GtkStatusIconPrivate *priv = status_icon->priv;
+
+ if (gtk_widget_get_screen (priv->tray_icon) != old_screen)
+ {
+ g_object_notify (G_OBJECT (status_icon), "screen");
+ }
+}
+
+#endif
+
+#ifdef GDK_WINDOWING_X11
+
+static void
+gtk_status_icon_embedded_changed (GtkStatusIcon *status_icon)
+{
+ g_object_notify (G_OBJECT (status_icon), "embedded");
+}
+
+static void
+gtk_status_icon_orientation_changed (GtkStatusIcon *status_icon)
+{
+ g_object_notify (G_OBJECT (status_icon), "orientation");
+}
+
+static gboolean
+gtk_status_icon_key_press (GtkStatusIcon *status_icon,
+ GdkEventKey *event)
+{
+ guint state, keyval;
+
+ state = event->state & gtk_accelerator_get_default_mod_mask ();
+ keyval = event->keyval;
+ if (state == 0 &&
+ (keyval == GDK_Return ||
+ keyval == GDK_KP_Enter ||
+ keyval == GDK_ISO_Enter ||
+ keyval == GDK_space ||
+ keyval == GDK_KP_Space))
+ {
+ emit_activate_signal (status_icon);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_status_icon_popup_menu (GtkStatusIcon *status_icon)
+{
+ emit_popup_menu_signal (status_icon, 0, gtk_get_current_event_time ());
+}
+
#endif
static gboolean
{
GtkStatusIconPrivate *priv = status_icon->priv;
- priv->storage_type = GTK_IMAGE_EMPTY;
- g_object_notify (G_OBJECT (status_icon), "storage-type");
-
switch (priv->storage_type)
{
case GTK_IMAGE_PIXBUF:
g_assert_not_reached ();
break;
}
+
+ priv->storage_type = GTK_IMAGE_EMPTY;
+ g_object_notify (G_OBJECT (status_icon), "storage-type");
}
static void
g_object_notify (G_OBJECT (status_icon), "icon-name");
break;
default:
- g_warning ("Image type %d not handled by GtkStatusIcon", storage_type);
+ g_warning ("Image type %u not handled by GtkStatusIcon", storage_type);
}
g_object_thaw_notify (G_OBJECT (status_icon));
* if the size of the notification area changes. For other
* storage types, the size-changed signal can be used to
* react to size changes.
+ *
+ * Note that the returned size is only meaningful while the
+ * status icon is embedded (see gtk_status_icon_is_embedded()).
*
* Return value: the size that is available for the image
*
return status_icon->priv->size;
}
+/**
+ * gtk_status_icon_set_screen:
+ * @status_icon: a #GtkStatusIcon
+ * @screen: a #GdkScreen
+ *
+ * Sets the #GdkScreen where @status_icon is displayed; if
+ * the icon is already mapped, it will be unmapped, and
+ * then remapped on the new screen.
+ *
+ * Since: 2.12
+ */
+void
+gtk_status_icon_set_screen (GtkStatusIcon *status_icon,
+ GdkScreen *screen)
+{
+ g_return_if_fail (GDK_IS_SCREEN (screen));
+
+#ifdef GDK_WINDOWING_X11
+ gtk_window_set_screen (GTK_WINDOW (status_icon->priv->tray_icon), screen);
+#endif
+}
+
+/**
+ * gtk_status_icon_get_screen:
+ * @status_icon: a #GtkStatusIcon
+ *
+ * Returns the #GdkScreen associated with @status_icon.
+ *
+ * Return value: a #GdkScreen.
+ *
+ * Since: 2.12
+ */
+GdkScreen *
+gtk_status_icon_get_screen (GtkStatusIcon *status_icon)
+{
+ g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), NULL);
+
+#ifdef GDK_WINDOWING_X11
+ return gtk_window_get_screen (GTK_WINDOW (status_icon->priv->tray_icon));
+#else
+ return gdk_screen_get_default ();
+#endif
+}
+
/**
* gtk_status_icon_set_tooltip:
* @status_icon: a #GtkStatusIcon
priv = status_icon->priv;
#ifdef GDK_WINDOWING_X11
- gtk_tooltips_set_tip (priv->tooltips, priv->tray_icon,
- tooltip_text, NULL);
+
+ gtk_widget_set_tooltip_text (priv->tray_icon, tooltip_text);
+
#endif
#ifdef GDK_WINDOWING_WIN32
if (tooltip_text == NULL)
if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid))
g_warning ("%s:%d:Shell_NotifyIconW(NIM_MODIFY) failed", __FILE__, __LINE__-1);
#endif
+#ifdef GDK_WINDOWING_QUARTZ
+ QUARTZ_POOL_ALLOC;
+ [priv->status_item setToolTip:tooltip_text];
+ QUARTZ_POOL_RELEASE;
+#endif
}
static gboolean
gtk_status_icon_blinker (status_icon);
priv->blinking_timeout =
- g_timeout_add (BLINK_TIMEOUT,
+ gdk_threads_add_timeout (BLINK_TIMEOUT,
(GSourceFunc) gtk_status_icon_blinker,
status_icon);
}
#ifdef GDK_WINDOWING_X11
if (visible)
gtk_widget_show (priv->tray_icon);
- else
- gtk_widget_hide (priv->tray_icon);
+ else if (GTK_WIDGET_REALIZED (priv->tray_icon))
+ {
+ gtk_widget_hide (priv->tray_icon);
+ gtk_widget_unrealize (priv->tray_icon);
+ }
#endif
#ifdef GDK_WINDOWING_WIN32
if (priv->nid.hWnd != NULL)
else
Shell_NotifyIconW (NIM_DELETE, &priv->nid);
}
+#endif
+#ifdef GDK_WINDOWING_QUARTZ
+ QUARTZ_POOL_ALLOC;
+ [priv->status_item setVisible:visible];
+ QUARTZ_POOL_RELEASE;
#endif
g_object_notify (G_OBJECT (status_icon), "visible");
}
#ifdef GDK_WINDOWING_WIN32
return TRUE;
#endif
+#ifdef GDK_WINDOWING_QUARTZ
+ return TRUE;
+#endif
}
/**
* @menu: the #GtkMenu
* @x: return location for the x position
* @y: return location for the y position
- * @push_in: return location for whether the menu should be pushed in
- * to be completely inside the screen instead of just clamped to the
- * size to the screen.
+ * @push_in: whether the first menu item should be offset (pushed in) to be
+ * aligned with the menu popup position (only useful for GtkOptionMenu).
* @user_data: the status icon to position the menu on
*
* Menu positioning function to use with gtk_menu_popup()
*push_in = FALSE;
#endif /* GDK_WINDOWING_X11 */
+
+#ifdef GDK_WINDOWING_WIN32
+ GtkStatusIcon *status_icon;
+ GtkStatusIconPrivate *priv;
+
+ g_return_if_fail (GTK_IS_MENU (menu));
+ g_return_if_fail (GTK_IS_STATUS_ICON (user_data));
+
+ status_icon = GTK_STATUS_ICON (user_data);
+ priv = status_icon->priv;
+
+ *x = priv->last_click_x;
+ *y = priv->last_click_y;
+ *push_in = TRUE;
+#endif
}
/**
* gtk_status_icon_get_geometry:
* @status_icon: a #GtkStatusIcon
- * @screen: return location for the screen
- * @area: return location for the area occupied by the status icon
+ * @screen: return location for the screen, or %NULL if the
+ * information is not needed
+ * @area: return location for the area occupied by the status
+ * icon, or %NULL
* @orientation: return location for the orientation of the panel
- * in which the status icon is embedded. A panel at the top or
- * bottom of the screen is horizontal, a panel at the left or
- * right is vertical.
+ * in which the status icon is embedded, or %NULL. A panel
+ * at the top or bottom of the screen is horizontal, a panel
+ * at the left or right is vertical.
*
* Obtains information about the location of the status icon
* on screen. This information can be used to e.g. position
* popups like notification bubbles.
+ *
* See gtk_status_icon_position_menu() for a more convenient
* alternative for positioning menus.
*
* Note that some platforms do not allow GTK+ to provide
- * this information.
+ * this information, and even on platforms that do allow it,
+ * the information is not reliable unless the status icon
+ * is embedded in a notification area, see
+ * gtk_status_icon_is_embedded().
*
* Return value: %TRUE if the location information has
* been filled in
GtkStatusIconPrivate *priv;
gint x, y;
- g_return_if_fail (GTK_IS_STATUS_ICON (status_icon));
+ g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), FALSE);
priv = status_icon->priv;
widget = priv->tray_icon;
- *screen = gtk_widget_get_screen (widget);
- gdk_window_get_origin (widget->window, &x, &y);
- area->x = x;
- area->y = y;
- area->width = widget->allocation.width;
- area->height = widget->allocation.height;
- *orientation = _gtk_tray_icon_get_orientation (GTK_TRAY_ICON (widget));
+ if (screen)
+ *screen = gtk_widget_get_screen (widget);
+
+ if (area)
+ {
+ gdk_window_get_origin (widget->window, &x, &y);
+ area->x = x;
+ area->y = y;
+ area->width = widget->allocation.width;
+ area->height = widget->allocation.height;
+ }
+
+ if (orientation)
+ *orientation = _gtk_tray_icon_get_orientation (GTK_TRAY_ICON (widget));
return TRUE;
#else
#endif /* GDK_WINDOWING_X11 */
}
+/**
+ * gtk_status_icon_get_x11_window_id:
+ * @status_icon: a #GtkStatusIcon
+ *
+ * This function is only useful on the X11/freedesktop.org platform.
+ * It returns a window ID for the widget in the underlying
+ * status icon implementation. This is useful for the Galago
+ * notification service, which can send a window ID in the protocol
+ * in order for the server to position notification windows
+ * pointing to a status icon reliably.
+ *
+ * This function is not intended for other use cases which are
+ * more likely to be met by one of the non-X11 specific methods, such
+ * as gtk_status_icon_position_menu().
+ *
+ * Return value: An 32 bit unsigned integer identifier for the
+ * underlying X11 Window
+ *
+ * Since: 2.14
+ */
+guint32
+gtk_status_icon_get_x11_window_id (GtkStatusIcon *status_icon)
+{
+#ifdef GDK_WINDOWING_X11
+ gtk_widget_realize (GTK_WIDGET (status_icon->priv->tray_icon));
+ return GDK_WINDOW_XID (GTK_WIDGET (status_icon->priv->tray_icon)->window);
+#else
+ return 0;
+#endif
+}
#define __GTK_STATUS_ICON_C__
#include "gtkaliasdef.c"