Create GTK + applet for LXPanel
An article on how to write your applet for LXPanel. The developers have not yet written the documentation, so they have to learn from the source, which, on the contrary, is rich in comments.
I decided to clearly analyze one example and the easiest way to build into a ready-made * .so plugin.
The assembly is under Ubuntu, requires minimal knowledge of C and GTK +.
The cpufreq plugin was chosen as a victim , I'll tell you why later. And we will write a plugin for switching performance <-> ondemand processor modes.
Actually, all the code with comments:
You can add our plugin to build scripts, but this is not necessary and it is extremely dreary. So just take the cpufreq victim plugin and replace its source src / plugins / cpufreq / cpufreq.c with ours.
We collect:
The finished * .so lies in src / plugins / cpufreq / .libs / , you need to put it in the folder with the rest of the plugins, only under a different name, for example /usr/lib/lxpanel/plugins/my_plugin.so
Content / usr / local / bin / cpufreq-gov :
2 icons in / usr / share / lxpanel / images / :
For clarity, I advise you to read the files, they are rich in comments.
Good luck Example source : my_plugin.c
I decided to clearly analyze one example and the easiest way to build into a ready-made * .so plugin.
The assembly is under Ubuntu, requires minimal knowledge of C and GTK +.
Training
- Get lxpanel sources:
echo "deb-src http://mirror.yandex.ru/ubuntu maverick main restricted universe multiverse" >> /etc/apt/sources.list
apt-get update && apt-get source lxpanel
cd lxpanel-0.5.6 - Install the packages necessary for assembly:
apt-get build-dep lxpanel
- Verification:
LIBS = "- lX11" ./configure --prefix = / usr --with-plugins = cpufreq
make
ls src / plugins / cpufreq / .libs / cpufreq.so
The cpufreq plugin was chosen as a victim , I'll tell you why later. And we will write a plugin for switching performance <-> ondemand processor modes.
Spelling
vim src / plugins / cpufreq / my_plugin.c
Actually, all the code with comments:
- / **
- * My_plugin
- * Habrahabr
- * /
- #include
- #include
- #include
- #include
- #include
- #include "panel.h"
- #include "misc.h"
- #include "plugin.h"
- // For string comparison
- #define STREQV (a, b) (* (a) == * (b) && strcmp ((a), (b)) == 0)
- // Declare the structure of our plugin
- typedef struct {
- // Widget that will contain an icon and a menu
- GtkWidget * namew;
- } my_plugin;
- // Create an object
- static my_plugin * mp;
- // Plugin structure is declared in src / plugin.h
- // * mp_p - now the Plugin class
- // Which at least sets the parent container mp_p-> pwid
- // Our widget mp-> namew is "inserted" into it
- // And the icon, for example, is contained in mp-> namew
- // Death hid for a long time
- static plugin * mp_p;
- // The title speaks for itself
- static char get_governor () {
- FILE * fpipe;
- const char governor [16];
- char line [16];
- // Problem with cpufreq-info output recognition
- // The script / usr / local / bin / cpufreq-gov returns the name of the current mode
- fpipe = (FILE *) popen ("/ usr / local / bin / cpufreq-gov", "r");
- fgets (line, sizeof (line), fpipe);
- pclose (fpipe);
- return line;
- }
- // The title speaks for itself
- static char get_frequency () {
- FILE * fpipe;
- const char governor [16];
- char line [16];
- // Problem with cpufreq-info output recognition
- // The script / usr / local / bin / cpufreq-gov returns the name of the current mode
- fpipe = (FILE *) popen ("cpufreq-info -f -m", "r");
- fgets (line, sizeof (line), fpipe);
- pclose (fpipe);
- line [strlen (line) -1] = '\ 0';
- return line;
- }
- // Make the icon update function when changing the mode
- static void refresh_icon () {
- // Find out the current mode
- const char governor [16];
- char line [16] = get_governor ();
- sprintf (governor, "% s", line);
- // mp_p-> pwid - parent container of type GTKWidget, which contains mp-> namew
- // Take out the widget mp-> namew and change the icon
- gtk_container_remove (GTK_CONTAINER (mp_p-> pwid), mp-> namew);
- // If the mode is "ondemand"
- if (STREQV (governor, "ondemand"))
- {
- // One icon
- mp-> namew = gtk_image_new_from_file ("/ usr / share / lxpanel / images / cpufreq_ond.png");
- }
- else
- {
- // Otherwise, another
- mp-> namew = gtk_image_new_from_file ("/ usr / share / lxpanel / images / cpufreq_perf.png");
- }
- // Insert widget mp-> namew back into parent container mp_p-> pwid
- gtk_container_add (GTK_CONTAINER (mp_p-> pwid), mp-> namew);
- gtk_widget_show_all (mp_p-> pwid);
- }
- // Function change mode
- static void set_governor (GtkWidget * widget, char * p) {
- const char exec [32];
- sprintf (exec, "cpufreq-set -g% s", p);
- system (exec);
- refresh_icon ();
- }
- // Create a menu
- static GtkWidget * mp_menu () {
- GtkMenu * menu = gtk_menu_new ();
- GSList * group = NULL;
- GtkWidget * menuitem, * radio1, * radio2;
- FILE * fpipe;
- const char governor [16];
- const char frequency [16];
- char line [16];
- line = get_governor ();
- sprintf (governor, "% s", line);
- line = get_frequency ();
- sprintf (frequency, "% s", line);
- // 1) Add the current frequency to the menu, make the item inactive
- menuitem = gtk_menu_item_new_with_label (frequency);
- gtk_menu_append (menu, menuitem);
- gtk_widget_set_sensitive (menuitem, FALSE);
- gtk_widget_show (menuitem);
- // 2) Add a separator
- menuitem = gtk_separator_menu_item_new ();
- gtk_menu_append (menu, menuitem);
- gtk_widget_show (menuitem);
- // 3) 2 radio buttons for switching between modes
- radio1 = gtk_radio_menu_item_new_with_label (group, "Savings");
- group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (radio1));
- if (STREQV (governor, "ondemand"))
- {
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (radio1), TRUE);
- }
- gtk_menu_append (menu, radio1);
- gtk_widget_show (radio1);
- // 4) Second button
- radio2 = gtk_radio_menu_item_new_with_label (group, "Performance");
- if (STREQV (governor, "performance"))
- {
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (radio2), TRUE);
- }
- gtk_menu_append (menu, radio2);
- gtk_widget_show (radio2);
- // When you click on the radio buttons, the mode switches
- g_signal_connect (G_OBJECT (radio1), "toggled", G_CALLBACK (set_governor), "ondemand");
- g_signal_connect (G_OBJECT (radio2), "toggled", G_CALLBACK (set_governor), "performance");
- return menu;
- }
- // Handler for the click event on the plugin icon
- static gboolean clicked (GtkWidget * widget, GdkEventButton * evt, Plugin * plugin) {
- gtk_menu_popup (mp_menu (), NULL, NULL, NULL, NULL, evt-> button, evt-> time);
- return TRUE;
- }
- // Actually the constructor of the object
- static int constructor (Plugin * p) {
- // Create an object
- mechanism_mp = g_new0 (my_plugin, 1);
- p-> priv = mechanism_mp;
- // Make the parent widget sensitive (follow events)
- // And remove the window decoration from it
- p-> pwid = gtk_event_box_new ();
- GTK_WIDGET_SET_FLAGS (p-> pwid, GTK_NO_WINDOW);
- gtk_container_set_border_width (GTK_CONTAINER (p-> pwid), 0);
- // Set The Initial Icon
- refresh_icon ();
- // When clicked, the clicked () handler function fires
- g_signal_connect (G_OBJECT (p-> pwid), "button_press_event", G_CALLBACK (clicked), (gpointer) p);
- gtk_widget_show (mechanism_mp-> namew);
- }
- // Destructor
- static void destructor (Plugin * p) {
- my_plugin * mechanism_mp = (my_plugin *) p-> priv;
- g_free (mechanism_mp);
- }
- // And here we indicate information about our plugin
- PluginClass mp_plugin_class = {
- PLUGINCLASS_VERSIONING,
- type: "my_plugin",
- name: N _ ("My super plugin"),
- version: "1.0",
- description: N _ ("Habrahabr"),
- constructor: constructor,
- destructor: destructor,
- // In our plugin are not used,
- // but you can assign handlers for configuration, save configuration
- // And redraw the widget when changing the configuration
- config: NULL,
- save: NULL,
- panel_configuration_changed: NULL
- };
Compilation
You can add our plugin to build scripts, but this is not necessary and it is extremely dreary. So just take the cpufreq victim plugin and replace its source src / plugins / cpufreq / cpufreq.c with ours.
We collect:
LIBS = "- lX11" ./configure --prefix = / usr --with-plugins = cpufreq
make
The finished * .so lies in src / plugins / cpufreq / .libs / , you need to put it in the folder with the rest of the plugins, only under a different name, for example /usr/lib/lxpanel/plugins/my_plugin.so
Content / usr / local / bin / cpufreq-gov :
- #! / bin / sh
- echo `cpufreq-info -p | awk '{print $ 3}' '
2 icons in / usr / share / lxpanel / images / :
Finally
For clarity, I advise you to read the files, they are rich in comments.
- src / plugin.c
- src / plugin.h
- src / panel.c
- src / panel.h
Good luck Example source : my_plugin.c