Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C

Minimize to tray with GTK

2.39/5 (10 votes)
20 Jun 2008CPOL 2  
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`.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)