Enabling multithreaded compilation.
[debian/lxpanel.git] / src / plugins / deskno / deskno.c
CommitLineData
1ea75322
DB
1/**
2 * Desktop number plugin to lxpanel
3 *
4 * Copyright (c) 2008 LxDE Developers, see the file AUTHORS for details.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
6cc5e1a6
DB
22// reused dclock.c and variables from pager.c
23// 11/23/04 by cmeury
24
25#include <sys/types.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <glib/gi18n.h>
29
30#include "panel.h"
31#include "misc.h"
32#include "plugin.h"
33
34#include "dbg.h"
35
1ea75322 36/* Private context for desktop number plugin. */
6cc5e1a6 37typedef struct {
1ea75322
DB
38 Panel * panel; /* Back pointer to Panel */
39 GtkWidget * label; /* The label */
40 int number_of_desktops; /* Number of desktops */
41 char * * desktop_labels; /* Vector of desktop labels */
42 gboolean bold; /* User preference: True if bold font */
43 gboolean wm_labels; /* User preference: True to display window manager labels */
44} DesknoPlugin;
45
46static gboolean deskno_name_update(GtkWidget * widget, DesknoPlugin * dc);
47static void deskno_redraw(GtkWidget * widget, DesknoPlugin * dc);
48static gboolean deskno_button_press_event(GtkWidget * widget, GdkEventButton * event, Plugin * p);
49static int deskno_constructor(Plugin * p, char ** fp);
50static void deskno_destructor(Plugin * p);
51static void deskno_apply_configuration(Plugin * p);
52static void deskno_configure(Plugin * p, GtkWindow * parent);
53static void deskno_save_configuration(Plugin * p, FILE * fp);
54static void deskno_panel_configuration_changed(Plugin * p);
55
56/* Handler for current_desktop event from window manager. */
57static gboolean deskno_name_update(GtkWidget * widget, DesknoPlugin * dc)
58{
59 /* Compute and redraw the desktop number. */
60 int desktop_number = get_net_current_desktop();
61 if (desktop_number < dc->number_of_desktops)
62 panel_draw_label_text(dc->panel, dc->label, dc->desktop_labels[desktop_number], dc->bold, TRUE);
63 return TRUE;
64}
6cc5e1a6 65
1ea75322
DB
66/* Handler for desktop_name and number_of_desktops events from window manager.
67 * Also used on a configuration change to get a full redraw. */
68static void deskno_redraw(GtkWidget * widget, DesknoPlugin * dc)
6cc5e1a6 69{
1ea75322
DB
70 /* Get the NET_DESKTOP_NAMES property. */
71 dc->number_of_desktops = get_net_number_of_desktops();
72 int number_of_desktop_names;
73 char * * desktop_names;
74 desktop_names = get_utf8_property_list(GDK_ROOT_WINDOW(), a_NET_DESKTOP_NAMES, &number_of_desktop_names);
75
76 /* Reallocate the vector of labels. */
77 if (dc->desktop_labels != NULL)
78 g_strfreev(dc->desktop_labels);
79 dc->desktop_labels = g_new0(gchar *, dc->number_of_desktops + 1);
80
81 /* Loop to copy the desktop names to the vector of labels.
82 * If there are more desktops than labels, label the extras with a decimal number. */
83 int i = 0;
84 if (dc->wm_labels)
85 for ( ; ((desktop_names != NULL) && (i < MIN(dc->number_of_desktops, number_of_desktop_names))); i++)
86 dc->desktop_labels[i] = g_strdup(desktop_names[i]);
87 for ( ; i < dc->number_of_desktops; i++)
88 dc->desktop_labels[i] = g_strdup_printf("%d", i + 1);
89
90 /* Free the property. */
91 if (desktop_names != NULL)
92 g_strfreev(desktop_names);
93
94 /* Redraw the label. */
95 deskno_name_update(widget, dc);
96}
97
98/* Handler for button-press-event on top level widget. */
99static gboolean deskno_button_press_event(GtkWidget * widget, GdkEventButton * event, Plugin * p)
100{
101 /* Standard left-click handling. */
102 if (plugin_button_press_event(widget, event, p))
103 return TRUE;
104
105 /* Right-click goes to next desktop, wrapping around to first. */
6cc5e1a6
DB
106 int desknum = get_net_current_desktop();
107 int desks = get_net_number_of_desktops();
1ea75322
DB
108 int newdesk = desknum + 1;
109 if (newdesk >= desks)
110 newdesk = 0;
111
112 /* Ask the window manager to make the new desktop current. */
6cc5e1a6 113 Xclimsg(GDK_ROOT_WINDOW(), a_NET_CURRENT_DESKTOP, newdesk, 0, 0, 0, 0);
1ea75322 114 return TRUE;
6cc5e1a6
DB
115}
116
1ea75322
DB
117/* Plugin constructor. */
118static int deskno_constructor(Plugin * p, char ** fp)
6cc5e1a6 119{
1ea75322
DB
120 /* Allocate plugin context and set into Plugin private data pointer. */
121 DesknoPlugin * dc = g_new0(DesknoPlugin, 1);
122 g_return_val_if_fail(dc != NULL, 0);
123 p->priv = dc;
124 dc->panel = p->panel;
125
126 /* Default parameters. */
127 dc->wm_labels = TRUE;
128
129 /* Load parameters from the configuration file. */
130 line s;
131 s.len = 256;
132 if (fp != NULL)
133 {
134 while (lxpanel_get_line(fp, &s) != LINE_BLOCK_END)
135 {
136 if (s.type == LINE_NONE)
137 {
138 ERR( "deskno: illegal token %s\n", s.str);
139 return 0;
140 }
141 if (s.type == LINE_VAR)
142 {
143 if (g_ascii_strcasecmp(s.t[0], "BoldFont") == 0)
144 dc->bold = str2num(bool_pair, s.t[1], 0);
145 else if (g_ascii_strcasecmp(s.t[0], "WMLabels") == 0)
146 dc->wm_labels = str2num(bool_pair, s.t[1], 0);
147 else
148 ERR( "deskno: unknown var %s\n", s.t[0]);
149 }
150 else
151 {
152 ERR( "deskno: illegal in this context %s\n", s.str);
153 return 0;
154 }
155 }
156 }
157
158 /* Allocate top level widget and set into Plugin widget pointer. */
159 p->pwid = gtk_event_box_new();
160 gtk_container_set_border_width(GTK_CONTAINER (p->pwid), 1);
161
162 /* Allocate label widget and add to top level. */
163 dc->label = gtk_label_new(NULL);
164 gtk_container_add(GTK_CONTAINER(p->pwid), dc->label);
165
166 /* Connect signals. Note use of window manager event object. */
167 g_signal_connect(p->pwid, "button_press_event", G_CALLBACK(deskno_button_press_event), p);
168 g_signal_connect(G_OBJECT(fbev), "current_desktop", G_CALLBACK(deskno_name_update), (gpointer) dc);
169 g_signal_connect(G_OBJECT(fbev), "desktop_names", G_CALLBACK(deskno_redraw), (gpointer) dc);
170 g_signal_connect(G_OBJECT(fbev), "number_of_desktops", G_CALLBACK(deskno_redraw), (gpointer) dc);
171
172 /* Initialize value and show the widget. */
173 deskno_redraw(NULL, dc);
174 gtk_widget_show_all(p->pwid);
175 return 1;
6cc5e1a6
DB
176}
177
1ea75322
DB
178/* Plugin destructor. */
179static void deskno_destructor(Plugin * p)
6cc5e1a6 180{
1ea75322 181 DesknoPlugin * dc = (DesknoPlugin *) p->priv;
6cc5e1a6 182
1ea75322
DB
183 /* Disconnect signal from window manager event object. */
184 g_signal_handlers_disconnect_by_func(G_OBJECT(fbev), deskno_name_update, dc);
6cc5e1a6 185
1ea75322
DB
186 /* Deallocate all memory. */
187 if (dc->desktop_labels != NULL)
188 g_strfreev(dc->desktop_labels);
189 g_free(dc);
190}
6cc5e1a6 191
1ea75322
DB
192/* Callback when the configuration dialog has recorded a configuration change. */
193static void deskno_apply_configuration(Plugin * p)
194{
195 DesknoPlugin * dc = (DesknoPlugin *) p->priv;
196 deskno_redraw(NULL, dc);
6cc5e1a6
DB
197}
198
1ea75322
DB
199/* Callback when the configuration dialog is to be shown. */
200static void deskno_configure(Plugin * p, GtkWindow * parent)
201{
202 DesknoPlugin * dc = (DesknoPlugin *) p->priv;
203 GtkWidget * dlg = create_generic_config_dlg(
204 _(p->class->name),
205 GTK_WIDGET(parent),
206 (GSourceFunc) deskno_apply_configuration, (gpointer) p,
207 _("Bold font"), &dc->bold, CONF_TYPE_BOOL,
208 _("Display desktop names"), &dc->wm_labels, CONF_TYPE_BOOL,
209 NULL);
210 gtk_widget_set_size_request(GTK_WIDGET(dlg), 400, -1); /* Improve geometry */
211 gtk_window_present(GTK_WINDOW(dlg));
212}
6cc5e1a6 213
1ea75322
DB
214/* Callback when the configuration is to be saved. */
215static void deskno_save_configuration(Plugin * p, FILE * fp)
6cc5e1a6 216{
1ea75322
DB
217 DesknoPlugin * dc = (DesknoPlugin *) p->priv;
218 lxpanel_put_int(fp, "BoldFont", dc->bold);
219 lxpanel_put_int(fp, "WMLabels", dc->wm_labels);
220}
6cc5e1a6 221
1ea75322
DB
222/* Callback when panel configuration changes. */
223static void deskno_panel_configuration_changed(Plugin * p)
224{
225 DesknoPlugin * dc = (DesknoPlugin *) p->priv;
226 deskno_name_update(NULL, dc);
6cc5e1a6
DB
227}
228
1ea75322 229/* Plugin descriptor. */
6cc5e1a6 230PluginClass deskno_plugin_class = {
1ea75322
DB
231
232 PLUGINCLASS_VERSIONING,
6cc5e1a6
DB
233
234 type : "deskno",
1ea75322 235 name : N_("Desktop Number / Workspace Name"),
6cc5e1a6
DB
236 version: "0.6",
237 description : N_("Display workspace number, by cmeury@users.sf.net"),
238
239 constructor : deskno_constructor,
240 destructor : deskno_destructor,
1ea75322
DB
241 config : deskno_configure,
242 save : deskno_save_configuration,
243 panel_configuration_changed : deskno_panel_configuration_changed
244
6cc5e1a6 245};