Here is a comprehensive GtkStatusIcon demo program (i.e. notification area icon), in C.
I had been using the egg_try_icon before deciding to upgrade to GtkStatusIcon. The issue I had was it appeared that the GtkStatusIcon lacked serious function in terms of feedback to the programmer, using signals.
I wanted to know:
* When it was embedded in a notification area, and when it disconnected
* When it was visbile and invisible
* When it was clicked
* When to repose with a popup menu.
* And it had to support a changeable ToolTip message
In a round about way, GtkStatusIcon supports all these features or requirements. I used the magic of GObject's notify() signal to get most of the features inplemented.
Attached is a focused and small demo program that is advanced but should be easy to follow.
James, 8)
Code:
/*
Gtk2 SystemTray NotificationIcon starter example
Copyright (C) 2006 James Scott, Jr. <skoona@users.sourceforge.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Name of package */
#define PACKAGE "gtkstatusicon-starter-program"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "James Scott Jr. skoona@users.sourceforge.net"
/* Define to the full name of this package. */
#define PACKAGE_NAME "GtkStatusIcon Starter Program"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "GtkStatusIcon Starter Program 0.1.0"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "gtkstatusicon-starter-program"
/* Define to the version of this package. */
#define PACKAGE_VERSION "0.1.0"
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Version number of package */
#define VERSION "0.1.0"
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE 1
#endif
#include <glib.h>
#include <gtk/gtk.h>
#include <stdlib.h> /* EXIT_SUCCESS EXIT_FAILURE */
#define GSI_WINDOW_TITLE "gsi: GtkStatusIcon Example"
#define GSI_MONITOR_MAX 8
#define GSI_MAX_ARRAY 512
#define GSI_REG_STRING 256
#define GSI_ICON_SIZE 24
/*
* Command line params
*/
static gint gd_b_debug = 0;
static gint gd_b_version = 0;
/*
* For Logging info messages
* GtkTextView widget
*/
GtkWidget *g_text_view = NULL;
typedef enum _State_Icons_IDs {
GSI_DEFAULT,
GSI_SKOONADEVEL,
GSI_N_ICONS
} GSI_IconType;
typedef struct _System_Control_Data {
guint cb_id;
GtkWindow *window; /* Main Window */
GtkWidget *evbox; /* used to share popups on main window */
gboolean b_visible; /* is the info window visible */
gboolean b_use_systray; /* should we use the tray icon */
GtkStatusIcon *tray_icon; /* the status icon */
gboolean tray_visible_flag; /* is the icon is visible */
gboolean tray_embedded_flag; /* is the icon viewable by user ? */
GtkWidget *tray_menu; /* Popup Menu */
gint tray_icon_size; /* pixel size of icon (normally 24) */
GdkPixbuf *my_icons[GSI_N_ICONS];
guint i_icon_index[GSI_MONITOR_MAX];
gint i_old_icon_index[GSI_MONITOR_MAX];
} GSI_CONFIG, *PGSI_CONFIG;
/*
* Start Local Functions
*/
static void cb_systray_popup_menu_response_exit (GtkWidget * widget, gpointer gp);
static void cb_systray_popup_menu_response_about (GtkWidget * widget, gpointer gp);
static void cb_systray_popup_menu_response_change (GtkWidget * widget, gpointer gp);
static gboolean gsi_systray_popup_menu_create (PGSI_CONFIG pgsi);
static void cb_systray_icon_handle_activate (GtkStatusIcon *status_icon, gpointer gp);
static void cb_systray_icon_handle_popup (GtkStatusIcon *status_icon, guint button, guint activate_time, gpointer gp);
static void cb_systray_icon_handle_notify (GObject *gobject, GParamSpec *arg1, gpointer gp);
static gboolean gsi_systray_icon_create (gpointer gp);
static gboolean gsi_systray_icon_remove (gpointer gp);
static void cb_main_interface_controls_clicked (GtkButton *button, PGSI_CONFIG pgsi);
static void cb_main_interface_show (GtkWidget * widget, PGSI_CONFIG pgsi);
static void cb_main_interface_hide (GtkWidget * widget, PGSI_CONFIG pgsi);
static gboolean cb_main_interface_clicked (GtkWidget * widget, GdkEventButton * event, gpointer gp);
static gboolean cb_main_interface_delete_event (GtkWidget * w, GdkEvent * event, gpointer gp);
static void cb_main_interface_destroy (GtkWidget * widget, PGSI_CONFIG pgsi);
static gint gsi_main_interface_parse_args (gint argc, gchar ** argv,GOptionContext **context);
static GtkWindow *gsi_main_interface_create (PGSI_CONFIG pgsi);
static GtkWidget *utils_scrolled_textview(GtkWidget *box, GtkPolicyType h_policy, GtkPolicyType v_policy);
static void utils_textview_append(GtkWidget *view, gchar *log_message);
static void utils_log_msg (gchar * pch_func, gchar * pch_topic, gchar * pch_emsg);
static gboolean utils_icons_load (PGSI_CONFIG pgsi);
extern int main (int argc, char *argv[]);
/*
* End local Functions
*/
static void cb_main_interface_controls_clicked (GtkButton *button, PGSI_CONFIG pgsi)
{
GtkWidget *widget = NULL;
gchar *pch = NULL;
g_return_if_fail (pgsi != NULL);
widget = GTK_WIDGET(g_object_get_data(G_OBJECT(button), "B-PEER"));
pch = (gchar *)g_object_get_data(G_OBJECT(button), "B-ACTION");
/*
* Manage the Icons Visibility
*/
if ( pgsi->tray_visible_flag ) {
gsi_systray_icon_remove (pgsi);
if ( g_str_equal(pch, "Remove")) {
gtk_widget_set_sensitive(widget, TRUE);
gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE);
} else {
gtk_widget_set_sensitive(widget, FALSE);
gtk_widget_set_sensitive(GTK_WIDGET(button), TRUE);
}
} else {
gsi_systray_icon_create (pgsi);
if ( g_str_equal(pch, "Add")) {
gtk_widget_set_sensitive(widget, TRUE);
gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE);
} else {
gtk_widget_set_sensitive(widget, FALSE);
gtk_widget_set_sensitive(GTK_WIDGET(button), TRUE);
}
}
utils_log_msg ((gchar *)__func__, "Button Clicked", (gchar *)g_object_get_data(G_OBJECT(button), "B-ACTION") );
return;
}
/*
* Menu Callback : Process PopUp menu commands
*/
static void cb_systray_popup_menu_response_change (GtkWidget * widget, gpointer gp)
{
PGSI_CONFIG pgsi = gp;
g_return_if_fail (gp != NULL);
pgsi->b_use_systray = !pgsi->b_use_systray;
if ( pgsi->b_use_systray ) {
gsi_systray_icon_remove (pgsi);
} else {
gsi_systray_icon_create (pgsi);
}
utils_log_msg ("cb_systray_popup_menu_response_change", "Changed Host Value", pgsi->b_use_systray ? "Destroyed" : "Created" );
return;
}
static void cb_systray_popup_menu_response_exit (GtkWidget * widget, gpointer gp)
{
PGSI_CONFIG pgsi = gp;
g_return_if_fail (gp != NULL);
utils_log_msg ("cb_systray_popup_menu_response_exit", "Enter", "top");
gtk_widget_destroy (GTK_WIDGET (pgsi->window)); /* this will cause everything to shutdown */
return;
}
static void cb_systray_popup_menu_response_about (GtkWidget * widget, gpointer gp)
{
gchar *website = "http://mysite.verizon.net/ressgdw8/";
gchar *website_label = "Skoona's Development Resources";
gchar *authors[] = {
"James Scott, Jr. <skoona@users.sourceforge.net>",
NULL
};
g_return_if_fail (gp != NULL);
utils_log_msg ("cb_systray_popup_menu_response_about", "Enter", "top");
gtk_show_about_dialog (NULL,
"name", "About",
"program-name", GSI_WINDOW_TITLE,
"version", PACKAGE_VERSION,
"copyright", "\xC2\xA9 2006 James Scott,Jr. (GPL)",
"comments", "System Tray Notification Icons Example",
"authors", authors,
"website", website,
"website-label", website_label,
"logo", ((PGSI_CONFIG)gp)->my_icons[GSI_SKOONADEVEL],
NULL);
return;
}
static gboolean gsi_systray_popup_menu_create (PGSI_CONFIG pgsi)
{
GtkWidget *menu = NULL, *menu_item = NULL;
g_return_val_if_fail (pgsi != NULL, FALSE);
utils_log_msg ("gsi_systray_popup_menu_create", "Enter", "top");
if (pgsi->tray_menu) {
return TRUE;
}
pgsi->tray_menu = menu = gtk_menu_new ();
menu_item = gtk_image_menu_item_new_from_stock (GTK_STOCK_ABOUT, NULL);
g_signal_connect (G_OBJECT (menu_item), "activate",
G_CALLBACK (cb_systray_popup_menu_response_about), pgsi);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
gtk_widget_show (menu_item);
menu_item = gtk_image_menu_item_new_from_stock (GTK_STOCK_APPLY, NULL);
g_signal_connect (G_OBJECT (menu_item), "activate",
G_CALLBACK (cb_systray_popup_menu_response_change), pgsi);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
gtk_widget_show (menu_item);
menu_item = gtk_separator_menu_item_new ();
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
gtk_widget_show (menu_item);
menu_item = gtk_image_menu_item_new_from_stock (GTK_STOCK_QUIT, NULL);
g_signal_connect (G_OBJECT (menu_item), "activate",
G_CALLBACK (cb_systray_popup_menu_response_exit), pgsi);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
gtk_widget_show (menu_item);
gtk_widget_show (menu);
return TRUE;
}
/*
* GtkStatusIcon Callbacks
*/
/*
* activate
*/
static void cb_systray_icon_handle_activate (GtkStatusIcon *status_icon, gpointer gp)
{
PGSI_CONFIG pgsi = gp;
gchar ch_buf[256];
g_return_if_fail (pgsi != NULL);
g_snprintf(ch_buf, sizeof(ch_buf), "gobject => %p", (gpointer)status_icon);
utils_log_msg ("cb_systray_icon_handle_activate", "Enter", ch_buf);
if (pgsi->window == NULL)
{
return;
}
if (pgsi->b_visible)
{
gtk_widget_hide (GTK_WIDGET(pgsi->window));
}
else
{
gtk_widget_show_all (GTK_WIDGET(pgsi->window));
gtk_window_present (pgsi->window);
}
return;
}
/*
* popup-menu
*/
static void cb_systray_icon_handle_popup (GtkStatusIcon *status_icon, guint button, guint activate_time, gpointer gp)
{
PGSI_CONFIG pgsi = gp;
gchar ch_buf[256];
g_return_if_fail (pgsi != NULL);
g_snprintf(ch_buf, sizeof(ch_buf), "gobject => %p", (gpointer)status_icon);
utils_log_msg ("cb_systray_icon_handle_popup", "Enter", ch_buf);
if (pgsi->window == NULL)
{
return;
}
if (pgsi->tray_menu != NULL)
{
gtk_menu_popup (GTK_MENU (pgsi->tray_menu), NULL, NULL, NULL, gp, button, activate_time);
}
return;
}
/*
* notify
* ::size
* ::embedded
* ::visible
*/
static void cb_systray_icon_handle_notify (GObject *gobject, GParamSpec *arg1, gpointer gp)
{
PGSI_CONFIG pgsi = gp;
gboolean b_value = FALSE;
gchar ch_buf[256];
g_return_if_fail (pgsi != NULL);
utils_log_msg ("cb_systray_icon_handle_notify", "Notify", arg1->name );
if ( g_str_equal(arg1->name,"size") )
{
pgsi->tray_icon_size = gtk_status_icon_get_size(pgsi->tray_icon);
g_snprintf(ch_buf, sizeof(ch_buf), "%p=>%d", (gpointer)gobject, pgsi->tray_icon_size );
}
if ( g_str_equal(arg1->name,"embedded") )
{
pgsi->tray_embedded_flag = b_value = gtk_status_icon_is_embedded(pgsi->tray_icon);
if (b_value)
pgsi->tray_visible_flag = TRUE;
g_snprintf(ch_buf, sizeof(ch_buf), "%p=>%s", (gpointer)gobject, b_value ? "True" : "False");
}
if ( g_str_equal(arg1->name,"visible") )
{
pgsi->tray_visible_flag = b_value = gtk_status_icon_get_visible(pgsi->tray_icon);
g_snprintf(ch_buf, sizeof(ch_buf), "%p=>%s", (gpointer)gobject, b_value ? "True" : "False");
}
utils_log_msg ("cb_systray_icon_handle_notify", arg1->name, ch_buf );
return;
}
static gboolean gsi_systray_icon_create (gpointer gp)
{
PGSI_CONFIG pgsi = gp;
gchar *pch_title = NULL;
g_return_val_if_fail (pgsi != NULL, FALSE);
utils_log_msg ("gsi_systray_icon_create", "Enter", "top");
/* Don't create it if it should not be on
*/
if (!pgsi->b_use_systray)
{
return FALSE;
}
/* If it exist just make it visible
*/
if (pgsi->tray_icon != NULL)
{
gtk_status_icon_set_visible(pgsi->tray_icon, TRUE);
return TRUE;
}
/* Else finally create a new one
*/
pgsi->tray_icon = gtk_status_icon_new_from_pixbuf(pgsi->my_icons[GSI_SKOONADEVEL]);
g_return_val_if_fail (pgsi->tray_icon != NULL, FALSE);
/* sink its ref so we can delete it later
*/
g_object_ref_sink (G_OBJECT(pgsi->tray_icon));
/* setup the signals to track it
*/
g_signal_connect (pgsi->tray_icon, "activate",
G_CALLBACK (cb_systray_icon_handle_activate), gp);
g_signal_connect (pgsi->tray_icon, "popup-menu",
G_CALLBACK (cb_systray_icon_handle_popup), gp);
g_signal_connect (pgsi->tray_icon, "notify::embedded",
G_CALLBACK (cb_systray_icon_handle_notify), gp);
g_signal_connect (pgsi->tray_icon, "notify::visible",
G_CALLBACK (cb_systray_icon_handle_notify), gp);
g_signal_connect (pgsi->tray_icon, "notify::size",
G_CALLBACK (cb_systray_icon_handle_notify), gp);
/* Attach a popup menu
*/
gsi_systray_popup_menu_create (pgsi);
/* Attach a new ToolTip message
*/
pch_title = g_strdup_printf ("I am SystemTray GtkStatusIcon Instance[%d]", pgsi->cb_id);
gtk_status_icon_set_tooltip(pgsi->tray_icon, pch_title);
g_free (pch_title);
return TRUE;
}
static gboolean gsi_systray_icon_remove (gpointer gp)
{
PGSI_CONFIG pgsi = gp;
g_return_val_if_fail (pgsi != NULL, FALSE);
utils_log_msg ("gsi_systray_icon_remove", "Enter", "top");
if (pgsi->tray_icon == NULL)
return FALSE;
/* Make it invisible anref it to destroy it
*/
gtk_status_icon_set_visible(pgsi->tray_icon, FALSE);
g_object_unref ( G_OBJECT(pgsi->tray_icon) );
pgsi->tray_icon = NULL;
return TRUE;
}
/*
* Manage Main window visibilty
*/
static void cb_main_interface_show (GtkWidget * widget, PGSI_CONFIG pgsi)
{
g_return_if_fail (pgsi != NULL);
utils_log_msg ("cb_main_interface_show", "Enter", "top");
pgsi->b_visible = TRUE;
}
static void cb_main_interface_hide (GtkWidget * widget, PGSI_CONFIG pgsi)
{
g_return_if_fail (pgsi != NULL);
utils_log_msg ("cb_main_interface_hide", "Enter", "top");
pgsi->b_visible = FALSE;
}
/*
* Prevent the normal window exit, just hide the window
*/
static gboolean cb_main_interface_delete_event (GtkWidget * w, GdkEvent * event,
gpointer gp)
{
PGSI_CONFIG pgsi = gp;
g_return_val_if_fail (pgsi, FALSE); /* error exit */
utils_log_msg ("cb_main_interface_delete_event", "Enter", "top");
if (pgsi->tray_visible_flag)
return gtk_widget_hide_on_delete (w);
return FALSE;
}
/*
* Handles cleanup for main window
*/
static void cb_main_interface_destroy (GtkWidget * widget, PGSI_CONFIG pgsi)
{
gint x = 0;
g_return_if_fail (pgsi != NULL);
utils_log_msg ("cb_main_interface_destroy", "Enter", "top");
gsi_systray_icon_remove (pgsi);
for (x = 0; x < GSI_N_ICONS; x++)
{
g_object_unref (pgsi->my_icons[x]);
}
gtk_main_quit ();
return;
}
/* Some of the main window core logic
*/
static gboolean cb_main_interface_clicked (GtkWidget * widget, GdkEventButton * event, gpointer gp)
{
PGSI_CONFIG pgsi = gp;
gchar *pch = NULL;
g_return_val_if_fail (pgsi != NULL, FALSE);
g_return_val_if_fail (widget != NULL, FALSE);
pch = g_strdup_printf ("button: %d", event->button);
utils_log_msg ("cb_main_interface_clicked", "Enter", pch);
g_free (pch);
if (pgsi->window == NULL)
{
return FALSE;
}
if (event->type != GDK_BUTTON_PRESS)
{
return FALSE;
}
switch (event->button)
{
case 1:
if ( widget != pgsi->evbox) {
if (pgsi->b_visible)
{
gtk_widget_hide (GTK_WIDGET(pgsi->window));
}
else
{
gtk_widget_show_all (GTK_WIDGET(pgsi->window));
gtk_window_present (pgsi->window);
}
}
return TRUE;
break;
case 2:
case 3:
if (pgsi->tray_menu != NULL)
{
gtk_menu_popup (GTK_MENU (pgsi->tray_menu), NULL, NULL, NULL, NULL,
event->button, event->time);
}
return TRUE;
break;
default:
return FALSE;
}
return FALSE;
}
/*
* Create a logging view
*/
static GtkWidget *utils_scrolled_textview(GtkWidget *box, GtkPolicyType h_policy, GtkPolicyType v_policy)
{
GtkWidget *scrolled = NULL,
*view = NULL;
scrolled = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), h_policy, v_policy);
gtk_container_add(GTK_CONTAINER(box), scrolled );
gtk_widget_show (scrolled);
view = gtk_text_view_new();
gtk_text_view_set_editable(GTK_TEXT_VIEW(view), TRUE);
gtk_container_add(GTK_CONTAINER(scrolled), view);
gtk_widget_show (view);
return view;
}
static void utils_textview_append(GtkWidget *view, gchar *log_message)
{
GtkTextIter iter;
GtkTextBuffer *buffer;
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
gtk_text_buffer_get_end_iter(buffer, &iter);
gtk_text_buffer_insert(buffer, &iter, log_message, -1);
}
/*
* Creates the main application window
*/
static GtkWindow *gsi_main_interface_create (PGSI_CONFIG pgsi)
{
GtkWidget *widget = NULL, *box = NULL, *button = NULL, *frame = NULL, *vbox =NULL;
GtkWindow *window = NULL;
GdkScreen *screen = NULL;
gchar *pch = NULL;
gint i_x = 0;
gint i_y = 0;
g_return_val_if_fail (pgsi != NULL, NULL);
pgsi->b_visible = FALSE;
pgsi->b_use_systray = TRUE;
pch = g_strdup_printf ("use_systray=%d", pgsi->b_use_systray);
utils_log_msg ("gsi_main_interface_create", "Enter", pch);
g_free (pch);
pch = NULL;
/* *********************************************************
* Create main window and display
*/
pgsi->window = window = GTK_WINDOW (gtk_window_new (GTK_WINDOW_TOPLEVEL));
gtk_container_set_border_width (GTK_CONTAINER (window), 0);
gtk_window_set_title (GTK_WINDOW (window), GSI_WINDOW_TITLE);
/* gtk_widget_add_events(window, GDK_BUTTON_PRESS_MASK); */
gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_NONE);
gtk_window_set_destroy_with_parent (GTK_WINDOW (window), TRUE);
g_signal_connect (window, "destroy", G_CALLBACK (cb_main_interface_destroy), pgsi);
g_signal_connect (window, "delete-event", G_CALLBACK (cb_main_interface_delete_event), pgsi);
g_signal_connect (window, "show", G_CALLBACK (cb_main_interface_show), pgsi);
g_signal_connect (window, "hide", G_CALLBACK (cb_main_interface_hide), pgsi);
g_signal_connect (window, "button-press-event", G_CALLBACK (cb_main_interface_clicked), pgsi);
/* *********************************************************
* Calculate window size based on current desktop sizes
*/
screen = gtk_window_get_screen (window);
i_x = gdk_screen_get_width (screen);
if (i_x > 3000) i_x /= 2; /* protect against wide double wide screens */
i_x = (gint) ((gfloat) i_x * 0.52);
i_y = gdk_screen_get_height (screen);
i_y = (gint) ((gfloat) i_y * 0.40);
gtk_widget_set_size_request (GTK_WIDGET (window), i_x / 2, i_y);
gtk_window_set_default_size (window, i_x, i_y);
gtk_window_set_default_icon (pgsi->my_icons[GSI_SKOONADEVEL]);
frame = gtk_frame_new ("GtkStatusIcon Controls");
gtk_frame_set_label_align (GTK_FRAME (frame), 0.1, 0.8);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
gtk_container_add (GTK_CONTAINER (window), frame);
gtk_widget_show (frame);
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add (GTK_CONTAINER (frame), vbox);
g_text_view = utils_scrolled_textview (vbox, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
widget = gtk_vbox_new(FALSE, 4);
gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, TRUE, 4);
/* some buttons */
box = gtk_hbutton_box_new ();
gtk_container_set_border_width (GTK_CONTAINER (box), 4);
gtk_button_box_set_layout (GTK_BUTTON_BOX (box), GTK_BUTTONBOX_END);
gtk_box_set_spacing (GTK_BOX (box), 6);
gtk_container_add (GTK_CONTAINER (widget), box);
widget = button = gtk_button_new_from_stock (GTK_STOCK_ADD);
g_object_set_data (G_OBJECT (button), "B-ACTION", (gpointer)"Add");
g_signal_connect (button, "clicked", G_CALLBACK (cb_main_interface_controls_clicked), pgsi);
gtk_box_pack_end (GTK_BOX (box), button, FALSE, FALSE, 4);
button = gtk_button_new_from_stock (GTK_STOCK_REMOVE);
g_object_set_data (G_OBJECT (button), "B-ACTION", (gpointer)"Remove");
g_signal_connect (button, "clicked", G_CALLBACK (cb_main_interface_controls_clicked), pgsi);
gtk_box_pack_end (GTK_BOX (box), button, FALSE, FALSE, 4);
g_object_set_data (G_OBJECT (button), "B-PEER", (gpointer)widget); /* to enable and disable each other */
g_object_set_data (G_OBJECT (widget), "B-PEER", (gpointer)button);
return GTK_WINDOW (window);
}
/*
* Load ICONs and set default icon
* return TRUE if ok, FALSE otherwise
*/
static gboolean utils_icons_load (PGSI_CONFIG pgsi)
{
guint i_x = 0, x = 0;
GError *gerror = NULL;
GdkPixbuf *pixbuf = NULL;
gboolean b_rc = TRUE;
gchar pch_file[GSI_MAX_ARRAY];
gchar *pch_2 = "./";
gchar *pch_3 = "../pixmaps/";
gchar *pch_4 = "/usr/share/pixmaps/";
gchar *pch_image_names[] = {
"gapc_prefs.png",
"skoona-devel-icon.png",
NULL
};
g_return_val_if_fail (pgsi != NULL, FALSE);
utils_log_msg ("utils_icons_load", "Enter", "top");
i_x = 0;
while (i_x == 0)
{
if (g_file_test (pch_image_names[0], G_FILE_TEST_EXISTS))
{
i_x = 1;
break;
}
g_snprintf (pch_file, GSI_MAX_ARRAY, "%s%s", pch_2, pch_image_names[0]);
if (g_file_test (pch_file, G_FILE_TEST_EXISTS))
{
i_x = 2;
break;
}
g_snprintf (pch_file, GSI_MAX_ARRAY, "%s%s", pch_3, pch_image_names[0]);
if (g_file_test (pch_file, G_FILE_TEST_EXISTS))
{
i_x = 3;
break;
}
g_snprintf (pch_file, GSI_MAX_ARRAY, "%s%s", pch_4, pch_image_names[0]);
if (g_file_test (pch_file, G_FILE_TEST_EXISTS))
{
i_x = 4;
break;
}
break;
}
if (i_x == 0)
{
utils_log_msg ("utils_icons_load", "Unable to find icons",
"--load failed!\n");
return FALSE;
}
for (x = 0; (pch_image_names[x] != NULL) && (x < GSI_N_ICONS); x++)
{
switch (i_x)
{
case 1:
g_snprintf (pch_file, GSI_MAX_ARRAY, "%s", pch_image_names[x]);
break;
case 2:
g_snprintf (pch_file, GSI_MAX_ARRAY, "%s%s", pch_2, pch_image_names[x]);
break;
case 3:
g_snprintf (pch_file, GSI_MAX_ARRAY, "%s%s", pch_3, pch_image_names[x]);
break;
case 4:
g_snprintf (pch_file, GSI_MAX_ARRAY, "%s%s", pch_4, pch_image_names[x]);
break;
default:
g_return_val_if_reached (FALSE);
break;
}
pixbuf = gdk_pixbuf_new_from_file (pch_file, &gerror);
if (gerror != NULL)
{
gchar *pch = NULL;
pch = g_strdup_printf ("Get Icon=%s Failed", pch_file);
utils_log_msg ("utils_icons_load", pch, gerror->message);
g_error_free (gerror);
g_free (pch);
gerror = NULL;
b_rc = FALSE;
pgsi->my_icons[x] = NULL;
}
else
{
pgsi->my_icons[x] =
gdk_pixbuf_scale_simple (pixbuf, GSI_ICON_SIZE, GSI_ICON_SIZE,
GDK_INTERP_BILINEAR);
g_object_unref (pixbuf);
}
}
return b_rc;
}
/*
* capture the current application related error values
* setup a one-shot timer to handle output of message on
* the main thread (i.e. this may be a background thread)
*/
static void utils_log_msg (gchar * pch_func, gchar * pch_topic, gchar * pch_emsg)
{
gchar *pch = NULL;
g_return_if_fail (pch_func != NULL);
pch = g_strdup_printf ("%s(%s) msg=%s\n", pch_func, pch_topic, pch_emsg);
if (gd_b_debug)
g_print (pch);
if (g_text_view != NULL)
utils_textview_append(g_text_view, pch);
g_free (pch);
return;
}
/*
* gsi_main_interface_parse_args()
*
* Parse out the command line options from argc,argv
* gstatusicon [-d |--debug] [-v|--version] [-h|--help]
*
* Returns: EXIT_SUCCESS if all params where handled
* EXIT_FAILURE if any error occurs or an option required shutdown
*/
static gint gsi_main_interface_parse_args (gint argc, gchar ** argv, GOptionContext **context)
{
GError *gerror = NULL;
GOptionEntry entries[] = {
{"debug", 'd', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &gd_b_debug,
"Turn on debug messages", "increase to debug verbosity"},
{"version", 'v', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &gd_b_version,
"Program version info", NULL},
{NULL}
};
/* Get command line parms */
*context = g_option_context_new (" => GTK+ GtkStatusIcon Example [2008] <skoona@users.sourceforge.net>");
g_option_context_add_main_entries(*context, entries, NULL);
g_option_context_set_ignore_unknown_options(*context, FALSE);
if (!(g_option_context_parse(*context, &argc, &argv, &gerror))) {
g_warning ("gsi: Parse command line failed: %s", gerror->message);
g_option_context_free(*context);
g_error_free(gerror);
return (EXIT_FAILURE);
}
if ( gd_b_version ) {
g_print ("GTK+ GtkStatusIcon Example\n%s Version %s\n%s\n\n",
PACKAGE_NAME, PACKAGE_VERSION,
"GPL2 (2008) <Skoona@users.sourceforge.net>"
);
g_option_context_free(*context);
return (EXIT_FAILURE);
}
return EXIT_SUCCESS;
}
/*
* Main entry point
*/
extern int main (int argc, char *argv[])
{
PGSI_CONFIG pgsi = NULL;
GtkWidget *window = NULL;
GOptionContext *context = NULL;
/*
* Initialize GLib thread support and GTK
*/
g_type_init ();
g_thread_init (NULL);
gdk_threads_init ();
gtk_init (&argc, &argv);
/*
* Setup to create app instance
*/
pgsi = g_new0 (GSI_CONFIG, 1);
pgsi->cb_id = 1;
utils_icons_load (pgsi);
if (gsi_main_interface_parse_args (argc, argv, &context))
{
return 1; /* exit if user only wanted help */
}
/*
* Create the main interface
*/
window = GTK_WIDGET( gsi_main_interface_create (pgsi) );
gtk_widget_show_all (window);
/* Try to force system tray icon on */
gsi_systray_icon_create ( pgsi);
/*
* enter the GTK main loop
*/
gdk_threads_enter ();
gtk_main ();
gdk_flush ();
gdk_threads_leave ();
g_free (pgsi);
return (0);
}