Minimize to tray with GTK






2.39/5 (8 votes)
How to place an icon in tray and interact with it.
Introduction
This article explains the use of the GtkStatusIcon widget which is used to place an icon in system tray. A tooltip and a pop-up menu can be added to this icon for interaction. This icon can be made to blink.
How to place a icon in System tray
The following functions can be used to create a new status icon:
GtkStatusIcon* gtk_status_icon_new (); GtkStatusIcon* gtk_status_icon_new_from_pixbuf (GdkPixbuf *pixbuf); GtkStatusIcon* gtk_status_icon_new_from_file (const gchar *filename); GtkStatusIcon* gtk_status_icon_new_from_stock (const gchar *stock_id); GtkStatusIcon* gtk_status_icon_new_from_icon_name (const gchar *icon_name);
To set a tooltip text use the following function:
void gtk_status_icon_set_tooltip (GtkStatusIcon *icon, const gchar *tooltip_text);
To blink the icon use the following function:
void gtk_status_icon_set_blinking (GtkStatusIcon *icon, gboolean blinking);
The tray icon emits "activate" signal when user activates the tray icon and emits "popup-menu" signal when the user has indicated that a menu should be shown.
Sample program
The follwing program creates a trayicon and hides application window when minimize button is pressed. The application window becomes visible with pop-up menu associated with the tray icon. These signals can be handled to interact with the icon.
//trayicon.c #include <gtk/gtk.h> static void trayView(GtkMenuItem *item, gpointer user_data); static void trayExit(GtkMenuItem *item, gpointer user_data); static void trayIconActivated(GObject *trayIcon, gpointer data); static void trayIconPopup(GtkStatusIcon *status_icon, guint button, guint32 activate_time, gpointer popUpMenu); static void destroy (GtkWidget*, gpointer); static gboolean delete_event (GtkWidget*, GdkEvent*, gpointer); static gboolean window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer user_data); int main(int argc, char *argv[]) { gtk_init (&argc, &argv); GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_title (GTK_WINDOW (window), "GtkStatusIcon Example"); gtk_widget_set_size_request (window, 200, -1); //set try icon file GtkStatusIcon *trayIcon = gtk_status_icon_new_from_file ("/root/Desktop/icon.png"); //set popup menu for tray icon GtkWidget *menu, *menuItemView, *menuItemExit; menu = gtk_menu_new(); menuItemView = gtk_menu_item_new_with_label ("View"); menuItemExit = gtk_menu_item_new_with_label ("Exit"); g_signal_connect (G_OBJECT (menuItemView), "activate", G_CALLBACK (trayView), window); g_signal_connect (G_OBJECT (menuItemExit), "activate", G_CALLBACK (trayExit), NULL); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuItemView); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuItemExit); gtk_widget_show_all (menu); //set tooltip gtk_status_icon_set_tooltip (trayIcon, "MsgWatcherGTK"); //connect handlers for mouse events g_signal_connect(GTK_STATUS_ICON (trayIcon), "activate", GTK_SIGNAL_FUNC (trayIconActivated), window); g_signal_connect(GTK_STATUS_ICON (trayIcon), "popup-menu", GTK_SIGNAL_FUNC (trayIconPopup), menu); gtk_status_icon_set_visible(trayIcon, FALSE); //set icon initially invisible GtkWidget *menuBar, *menuItemTopLvl, *mainMenu, *mainMenuItemExit; menuBar = gtk_menu_bar_new (); menuItemTopLvl = gtk_menu_item_new_with_label ("Menu"); gtk_menu_shell_append (GTK_MENU_SHELL (menuBar), menuItemTopLvl); mainMenu = gtk_menu_new (); gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuItemTopLvl), mainMenu); mainMenuItemExit = gtk_menu_item_new_with_label ("Quit"); g_signal_connect (G_OBJECT (mainMenuItemExit), "activate", G_CALLBACK (trayExit), NULL); gtk_menu_shell_append (GTK_MENU_SHELL (mainMenu), mainMenuItemExit); g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (destroy), NULL); g_signal_connect (G_OBJECT (window), "delete_event", G_CALLBACK (delete_event), trayIcon); g_signal_connect (G_OBJECT (window), "window-state-event", G_CALLBACK (window_state_event), trayIcon); gtk_container_add (GTK_CONTAINER (window), menuBar); gtk_widget_show_all (window); gtk_main (); return 0; } static void trayView(GtkMenuItem *item, gpointer window) { gtk_widget_show(GTK_WIDGET(window)); gtk_window_deiconify(GTK_WINDOW(window)); } static void trayExit(GtkMenuItem *item, gpointer user_data) { printf("exit"); gtk_main_quit(); } static void trayIconActivated(GObject *trayIcon, gpointer window) { gtk_widget_show(GTK_WIDGET(window)); gtk_window_deiconify(GTK_WINDOW(window)); } static void trayIconPopup(GtkStatusIcon *status_icon, guint button, guint32 activate_time, gpointer popUpMenu) { gtk_menu_popup(GTK_MENU(popUpMenu), NULL, NULL, gtk_status_icon_position_menu, status_icon, button, activate_time); } static void destroy (GtkWidget *window, gpointer data) { gtk_main_quit (); } static gboolean delete_event (GtkWidget *window, GdkEvent *event, gpointer data) { return FALSE; } static gboolean window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer trayIcon) { if(event->changed_mask == GDK_WINDOW_STATE_ICONIFIED && (event->new_window_state == GDK_WINDOW_STATE_ICONIFIED || event->new_window_state == (GDK_WINDOW_STATE_ICONIFIED | GDK_WINDOW_STATE_MAXIMIZED))) { gtk_widget_hide (GTK_WIDGET(widget)); gtk_status_icon_set_visible(GTK_STATUS_ICON(trayIcon), TRUE); } else if(event->changed_mask == GDK_WINDOW_STATE_WITHDRAWN && (event->new_window_state == GDK_WINDOW_STATE_ICONIFIED || event->new_window_state == (GDK_WINDOW_STATE_ICONIFIED | GDK_WINDOW_STATE_MAXIMIZED))) { gtk_status_icon_set_visible(GTK_STATUS_ICON(trayIcon), FALSE); } return TRUE; }
The above code can be build with the following command:
gcc trayicon.c -o trayicon `pkg-config --cflags --libs gtk+-2.0`.