The only part of dealing with a context menu that is specific to applets is how to setup the context menu. Once it is setup, this is really just a matter of using GtkAction.
To setup the context menu of the applet, the panel_applet_setup_menu_from_file() function should be used, with a path to a menu XML file and a GtkActionGroup object containing all actions that are used in the menu XML file. The example below shows how to achieve this:
Example 3. Hello World applet, with a context menu
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <panel-applet.h>
/* This would usually be defined in config.h */
#define GETTEXT_PACKAGE "hello-world"
/* This would usually be defined in Makefile.am */
#define HELLO_WORLD_UI_DIR "/usr/share/hello-world"
static void hello_world_applet_prefs (GtkAction *action,
PanelApplet *applet);
static void hello_world_applet_say (GtkAction *action,
PanelApplet *applet);
static const GtkActionEntry hello_world_menu_actions [] = {
{ "HelloWorldPrefs", GTK_STOCK_HELP, N_("_Preferences"),
NULL, NULL,
G_CALLBACK (hello_world_applet_prefs) },
{ "HelloWorldSay", GTK_STOCK_ABOUT, N_("_Say Hello"),
NULL, NULL,
G_CALLBACK (hello_world_applet_say) }
};
static void
hello_world_applet_prefs (GtkAction *action,
PanelApplet *applet)
{
GtkWidget *dialog;
dialog = gtk_message_dialog_new (NULL, 0,
GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
"Preferences");
g_signal_connect (dialog, "response",
G_CALLBACK (gtk_widget_destroy), NULL);
gtk_widget_show (dialog);
}
static void
hello_world_applet_say (GtkAction *action,
PanelApplet *applet)
{
GtkWidget *dialog;
dialog = gtk_message_dialog_new (NULL, 0,
GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
"Hello World!");
g_signal_connect (dialog, "response",
G_CALLBACK (gtk_widget_destroy), NULL);
gtk_widget_show (dialog);
}
static gboolean
hello_world_applet_start (PanelApplet *applet)
{
GtkWidget *label;
GtkActionGroup *action_group;
gchar *ui_path;
label = gtk_label_new ("Hello World");
gtk_container_add (GTK_CONTAINER (applet), label);
action_group = gtk_action_group_new ("Hello World Applet Actions");
gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
gtk_action_group_add_actions (action_group,
hello_world_menu_actions,
G_N_ELEMENTS (hello_world_menu_actions),
applet);
ui_path = g_build_filename (HELLO_WORLD_UI_DIR, "hello-world-menu.xml", NULL);
panel_applet_setup_menu_from_file (applet, ui_path, action_group);
g_free (ui_path);
g_object_unref (action_group);
gtk_widget_show_all (GTK_WIDGET (applet));
return TRUE;
}
static gboolean
hello_world_factory_callback (PanelApplet *applet,
const gchar *iid,
gpointer data)
{
gboolean retval = FALSE;
if (g_strcmp0 (iid, "HelloWorldApplet") == 0)
retval = hello_world_applet_start (applet);
return retval;
}
PANEL_APPLET_OUT_PROCESS_FACTORY ("HelloWorldFactory",
PANEL_TYPE_APPLET,
hello_world_factory_callback,
NULL)
Here are the changes compared to the simple example with no context menu:
We define a list of GtkActionEntry entries: hello_world_menu_actions. This will be used later on to build GtkAction objects, with their label and callback. We obviously implement the callbacks.
We change hello_world_applet_start() to define a GtkActionGroup object, to which we add, with gtk_action_group_add_actions(), GtkAction objects based on the GtkActionEntry entries. Note that the the last argument to gtk_action_group_add_actions() will be passed as user data to the callbacks.
We also change hello_world_applet_start() to add this GtkActionGroup object to the context menu of the applet, by calling panel_applet_setup_menu_from_file(). This function takes as argument a path to the menu XML file that will define how to display the GtkAction objects in the context menu.