Unify indentation (spaces vs tabs) in src/plugins/batt/batt.c
[lxde/lxpanel.git] / src / plugins / batt / batt.c
CommitLineData
8f11d5f8
HJYP
1/*
2 * ACPI battery monitor plugin for LXPanel
3 *
4 * Copyright (C) 2007 by Greg McNew <gmcnew@gmail.com>
802d5540 5 * Copyright (C) 2008 by Hong Jen Yee <pcman.tw@gmail.com>
c887dfa0 6 * Copyright (C) 2009 by Juergen Hoetzel <juergen@archlinux.org>
8f11d5f8
HJYP
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 *
23 * This plugin monitors battery usage on ACPI-enabled systems by reading the
c887dfa0
JH
24 * battery information found in /sys/class/power_supply. The update interval is
25 * user-configurable and defaults to 3 second.
8f11d5f8
HJYP
26 *
27 * The battery's remaining life is estimated from its current charge and current
28 * rate of discharge. The user may configure an alarm command to be run when
29 * their estimated remaining battery life reaches a certain level.
30 */
31
e751fe05
HJYP
32/* FIXME:
33 * Here are somethings need to be improvec:
34 * 1. Replace pthread stuff with gthread counterparts for portability.
e751fe05
HJYP
35 * 3. Add an option to hide the plugin when AC power is used or there is no battery.
36 * 4. Handle failure gracefully under systems other than Linux.
37*/
38
39#include <glib.h>
8f11d5f8 40#include <glib/gi18n.h>
c0ed75bf 41#include <pthread.h> /* used by pthread_create() and alarmThread */
8f11d5f8
HJYP
42#include <semaphore.h> /* used by update() and alarmProcess() for alarms */
43#include <stdlib.h>
802d5540 44#include <string.h>
9c9d3a00 45#include <stdarg.h>
8f11d5f8 46
811afd8f 47#include "dbg.h" /* for ENTER and RET macros */
c887dfa0 48#include "batt_sys.h"
813c2d44
AG
49#include "misc.h" /* used for lxpanel_generic_config_dlg() */
50#include "plugin.h" /* all other APIs including panel configuration */
8f11d5f8 51
8f11d5f8
HJYP
52/* The last MAX_SAMPLES samples are averaged when charge rates are evaluated.
53 This helps prevent spikes in the "time left" values the user sees. */
54#define MAX_SAMPLES 10
55
802d5540 56typedef struct {
8f11d5f8
HJYP
57 char *alarmCommand,
58 *backgroundColor,
59 *chargingColor1,
60 *chargingColor2,
61 *dischargingColor1,
802d5540
HJYP
62 *dischargingColor2;
63 GdkColor background,
64 charging1,
65 charging2,
66 discharging1,
67 discharging2;
f176735a 68 cairo_surface_t *pixmap;
802d5540 69 GtkWidget *drawingArea;
8f11d5f8
HJYP
70 int orientation;
71 unsigned int alarmTime,
72 border,
73 height,
74 length,
75 numSamples,
76 requestedBorder,
77 *rateSamples,
78 rateSamplesSum,
79 thickness,
80 timer,
802d5540
HJYP
81 state_elapsed_time,
82 info_elapsed_time,
8f11d5f8 83 wasCharging,
04a2f050
HJYP
84 width,
85 hide_if_no_battery;
8f11d5f8 86 sem_t alarmProcessLock;
c887dfa0 87 battery* b;
3051b49c 88 gboolean has_ac_adapter;
5c0c599d 89 gboolean show_extended_information;
813c2d44
AG
90 Panel *panel;
91 config_setting_t *settings;
c887dfa0 92} lx_battery;
8f11d5f8
HJYP
93
94
95typedef struct {
96 char *command;
97 sem_t *lock;
4a974f26 98} Alarm;
8f11d5f8 99
813c2d44 100static void destructor(gpointer data);
c887dfa0 101static void update_display(lx_battery *lx_b, gboolean repaint);
3051b49c 102
8f11d5f8
HJYP
103/* alarmProcess takes the address of a dynamically allocated alarm struct (which
104 it must free). It ensures that alarm commands do not run concurrently. */
c0ed75bf 105static void * alarmProcess(void *arg) {
4a974f26 106 Alarm *a = (Alarm *) arg;
8f11d5f8
HJYP
107
108 sem_wait(a->lock);
c0ed75bf 109 system(a->command);
8f11d5f8
HJYP
110 sem_post(a->lock);
111
112 g_free(a);
c0ed75bf 113 return NULL;
8f11d5f8
HJYP
114}
115
9c9d3a00
HG
116
117static void append(gchar **tooltip, gchar *fmt, ...)
118{
119 gchar *old = *tooltip;
120 gchar *new;
121 va_list va;
122
123 va_start(va, fmt);
124 new = g_strdup_vprintf(fmt, va);
125 va_end(va);
126
127 *tooltip = g_strconcat(old, new, NULL);
128
129 g_free(old);
130 g_free(new);
131}
132
133
f855ac58
HG
134/* Make a tooltip string, and display remaining charge time if the battery
135 is charging or remaining life if it's discharging */
136static gchar* make_tooltip(lx_battery* lx_b, gboolean isCharging)
137{
138 gchar * tooltip;
9c9d3a00
HG
139 gchar * indent = " ";
140 battery *b = lx_b->b;
f855ac58 141
029d9f0c 142 if (b == NULL)
811afd8f 143 return NULL;
029d9f0c 144
f855ac58 145 if (isCharging) {
811afd8f
AG
146 int hours = lx_b->b->seconds / 3600;
147 int left_seconds = lx_b->b->seconds - 3600 * hours;
148 int minutes = left_seconds / 60;
149 tooltip = g_strdup_printf(
150 _("Battery: %d%% charged, %d:%02d until full"),
151 lx_b->b->percentage,
152 hours,
153 minutes );
f855ac58 154 } else {
811afd8f
AG
155 /* if we have enough rate information for battery */
156 if (lx_b->b->percentage != 100) {
157 int hours = lx_b->b->seconds / 3600;
158 int left_seconds = lx_b->b->seconds - 3600 * hours;
159 int minutes = left_seconds / 60;
160 tooltip = g_strdup_printf(
161 _("Battery: %d%% charged, %d:%02d left"),
162 lx_b->b->percentage,
163 hours,
164 minutes );
165 } else {
166 tooltip = g_strdup_printf(
167 _("Battery: %d%% charged"),
168 100 );
169 }
f855ac58
HG
170 }
171
5c0c599d 172 if (!lx_b->show_extended_information) {
811afd8f 173 return tooltip;
5c0c599d
HG
174 }
175
9c9d3a00 176 if (b->energy_full_design != -1)
811afd8f 177 append(&tooltip, _("\n%sEnergy full design:\t\t%5d mWh"), indent, b->energy_full_design);
9c9d3a00 178 if (b->energy_full != -1)
811afd8f 179 append(&tooltip, _("\n%sEnergy full:\t\t\t%5d mWh"), indent, b->energy_full);
9c9d3a00 180 if (b->energy_now != -1)
811afd8f 181 append(&tooltip, _("\n%sEnergy now:\t\t\t%5d mWh"), indent, b->energy_now);
9c9d3a00 182 if (b->power_now != -1)
811afd8f 183 append(&tooltip, _("\n%sPower now:\t\t\t%5d mW"), indent, b->power_now);
9c9d3a00
HG
184
185 if (b->charge_full_design != -1)
811afd8f 186 append(&tooltip, _("\n%sCharge full design:\t%5d mAh"), indent, b->charge_full_design);
9c9d3a00 187 if (b->charge_full != -1)
811afd8f 188 append(&tooltip, _("\n%sCharge full:\t\t\t%5d mAh"), indent, b->charge_full);
9c9d3a00 189 if (b->charge_now != -1)
811afd8f 190 append(&tooltip, _("\n%sCharge now:\t\t\t%5d mAh"), indent, b->charge_now);
9c9d3a00 191 if (b->current_now != -1)
811afd8f 192 append(&tooltip, _("\n%sCurrent now:\t\t\t%5d mA"), indent, b->current_now);
9c9d3a00
HG
193
194 if (b->voltage_now != -1)
811afd8f 195 append(&tooltip, _("\n%sCurrent Voltage:\t\t%.3lf V"), indent, b->voltage_now / 1000.0);
9c9d3a00 196
f855ac58
HG
197 return tooltip;
198}
199
5c0c599d
HG
200static void set_tooltip_text(lx_battery* lx_b)
201{
029d9f0c 202 if (lx_b->b == NULL)
811afd8f 203 return;
5c0c599d
HG
204 gboolean isCharging = battery_is_charging(lx_b->b);
205 gchar *tooltip = make_tooltip(lx_b, isCharging);
206 gtk_widget_set_tooltip_text(lx_b->drawingArea, tooltip);
207 g_free(tooltip);
208}
8f11d5f8 209
802d5540
HJYP
210/* FIXME:
211 Don't repaint if percentage of remaining charge and remaining time aren't changed. */
c887dfa0 212void update_display(lx_battery *lx_b, gboolean repaint) {
f176735a 213 cairo_t *cr;
c887dfa0
JH
214 battery *b = lx_b->b;
215 /* unit: mW */
7f9ba86b 216 int rate;
eef7d6f6 217 gboolean isCharging;
8f11d5f8 218
c887dfa0 219 if (! lx_b->pixmap )
802d5540 220 return;
8f11d5f8 221
f176735a
RM
222 cr = cairo_create(lx_b->pixmap);
223 cairo_set_line_width (cr, 1.0);
224
dc9d3b94
HG
225 /* draw background */
226 gdk_cairo_set_source_color(cr, &lx_b->background);
227 cairo_rectangle(cr, 0, 0, lx_b->width, lx_b->height);
228 cairo_fill(cr);
229
c887dfa0 230 /* no battery is found */
811afd8f 231 if( b == NULL )
802d5540 232 {
811afd8f
AG
233 gtk_widget_set_tooltip_text( lx_b->drawingArea, _("No batteries found") );
234 goto update_done;
c887dfa0 235 }
811afd8f 236
c887dfa0 237 /* fixme: only one battery supported */
8f11d5f8 238
7f9ba86b 239 rate = lx_b->b->current_now;
c887dfa0 240 isCharging = battery_is_charging ( b );
811afd8f 241
c887dfa0 242 /* Consider running the alarm command */
b37f46a0 243 if ( !isCharging && rate > 0 &&
811afd8f 244 ( ( battery_get_remaining( b ) / 60 ) < lx_b->alarmTime ) )
c887dfa0 245 {
811afd8f
AG
246 /* Shrug this should be done using glibs process functions */
247 /* Alarms should not run concurrently; determine whether an alarm is
248 already running */
249 int alarmCanRun;
250 sem_getvalue(&(lx_b->alarmProcessLock), &alarmCanRun);
251
252 /* Run the alarm command if it isn't already running */
253 if (alarmCanRun) {
254
255 Alarm *a = (Alarm *) malloc(sizeof(Alarm));
256 a->command = lx_b->alarmCommand;
257 a->lock = &(lx_b->alarmProcessLock);
258
259 /* Manage the alarm process in a new thread, which which will be
260 responsible for freeing the alarm struct it's given */
261 pthread_t alarmThread;
262 pthread_create(&alarmThread, NULL, alarmProcess, a);
263 }
c887dfa0 264 }
8f11d5f8 265
5c0c599d 266 set_tooltip_text(lx_b);
eef7d6f6
HG
267
268 int chargeLevel = lx_b->b->percentage * (lx_b->length - 2 * lx_b->border) / 100;
269
cfde283a 270 if (lx_b->orientation == GTK_ORIENTATION_HORIZONTAL) {
eef7d6f6 271
811afd8f
AG
272 /* Draw the battery bar vertically, using color 1 for the left half and
273 color 2 for the right half */
f176735a
RM
274 gdk_cairo_set_source_color(cr,
275 isCharging ? &lx_b->charging1 : &lx_b->discharging1);
276 cairo_rectangle(cr, lx_b->border,
277 lx_b->height - lx_b->border - chargeLevel, lx_b->width / 2
278 - lx_b->border, chargeLevel);
279 cairo_fill(cr);
280 gdk_cairo_set_source_color(cr,
281 isCharging ? &lx_b->charging2 : &lx_b->discharging2);
282 cairo_rectangle(cr, lx_b->width / 2,
283 lx_b->height - lx_b->border - chargeLevel, (lx_b->width + 1) / 2
284 - lx_b->border, chargeLevel);
285 cairo_fill(cr);
eef7d6f6
HG
286
287 }
288 else {
289
811afd8f
AG
290 /* Draw the battery bar horizontally, using color 1 for the top half and
291 color 2 for the bottom half */
f176735a
RM
292 gdk_cairo_set_source_color(cr,
293 isCharging ? &lx_b->charging1 : &lx_b->discharging1);
294 cairo_rectangle(cr, lx_b->border,
295 lx_b->border, chargeLevel, lx_b->height / 2 - lx_b->border);
296 cairo_fill(cr);
297 gdk_cairo_set_source_color(cr,
298 isCharging ? &lx_b->charging2 : &lx_b->discharging2);
299 cairo_rectangle(cr, lx_b->border, (lx_b->height + 1)
300 / 2, chargeLevel, lx_b->height / 2 - lx_b->border);
301 cairo_fill(cr);
eef7d6f6
HG
302
303 }
dc9d3b94
HG
304
305update_done:
eef7d6f6 306 if( repaint )
811afd8f 307 gtk_widget_queue_draw( lx_b->drawingArea );
e4f8b15f
HG
308
309 check_cairo_status(cr);
310 cairo_destroy(cr);
8f11d5f8
HJYP
311}
312
71671bf6 313/* This callback is called every 3 seconds */
c887dfa0 314static int update_timout(lx_battery *lx_b) {
dc9d3b94 315 battery *bat;
251cfd3e
AG
316 if (g_source_is_destroyed(g_main_current_source()))
317 return FALSE;
52cb5b58 318 GDK_THREADS_ENTER();
c887dfa0
JH
319 lx_b->state_elapsed_time++;
320 lx_b->info_elapsed_time++;
71671bf6 321
dc9d3b94
HG
322 bat = battery_update( lx_b->b );
323 if (bat == NULL)
324 {
811afd8f 325 battery_free(lx_b->b);
dc9d3b94 326
811afd8f
AG
327 /* maybe in the mean time a battery has been inserted. */
328 lx_b->b = battery_get();
dc9d3b94 329 }
802d5540 330
c887dfa0 331 update_display( lx_b, TRUE );
802d5540 332
52cb5b58 333 GDK_THREADS_LEAVE();
7c2a8701 334 return TRUE;
52cb5b58 335}
8f11d5f8
HJYP
336
337/* An update will be performed whenever the user clicks on the charge bar */
813c2d44
AG
338static gboolean buttonPressEvent(GtkWidget *p, GdkEventButton *event,
339 Panel *panel)
340{
341 lx_battery *lx_b = lxpanel_plugin_get_data(p);
8f11d5f8 342
c887dfa0 343 update_display(lx_b, TRUE);
8f11d5f8 344
813c2d44 345 return lxpanel_plugin_button_press_event(p, event, panel);
8f11d5f8
HJYP
346}
347
348
349static gint configureEvent(GtkWidget *widget, GdkEventConfigure *event,
c887dfa0 350 lx_battery *lx_b) {
8f11d5f8
HJYP
351
352 ENTER;
353
c887dfa0 354 if (lx_b->pixmap)
f176735a 355 cairo_surface_destroy(lx_b->pixmap);
8f11d5f8
HJYP
356
357 /* Update the plugin's dimensions */
c887dfa0
JH
358 lx_b->width = widget->allocation.width;
359 lx_b->height = widget->allocation.height;
cfde283a 360 if (lx_b->orientation == GTK_ORIENTATION_HORIZONTAL) {
c887dfa0
JH
361 lx_b->length = lx_b->height;
362 lx_b->thickness = lx_b->width;
8f11d5f8
HJYP
363 }
364 else {
c887dfa0
JH
365 lx_b->length = lx_b->width;
366 lx_b->thickness = lx_b->height;
8f11d5f8
HJYP
367 }
368
f176735a
RM
369 lx_b->pixmap = cairo_image_surface_create (CAIRO_FORMAT_RGB24, widget->allocation.width,
370 widget->allocation.height);
e4f8b15f 371 check_cairo_surface_status(&lx_b->pixmap);
8f11d5f8
HJYP
372
373 /* Perform an update so the bar will look right in its new orientation */
c887dfa0 374 update_display(lx_b, FALSE);
8f11d5f8
HJYP
375
376 RET(TRUE);
377
378}
379
380
c887dfa0 381static gint exposeEvent(GtkWidget *widget, GdkEventExpose *event, lx_battery *lx_b) {
8f11d5f8 382
e4f8b15f 383 ENTER;
f176735a
RM
384 cairo_t *cr = gdk_cairo_create(widget->window);
385 gdk_cairo_region(cr, event->region);
386 cairo_clip(cr);
8f11d5f8 387
f176735a
RM
388 gdk_cairo_set_source_color(cr, &lx_b->drawingArea->style->black);
389 cairo_set_source_surface(cr, lx_b->pixmap, 0, 0);
390 cairo_paint(cr);
e4f8b15f
HG
391
392 check_cairo_status(cr);
f176735a 393 cairo_destroy(cr);
e751fe05 394
8f11d5f8 395 RET(FALSE);
8f11d5f8
HJYP
396}
397
398
813c2d44 399static GtkWidget * constructor(Panel *panel, config_setting_t *settings)
8f11d5f8 400{
8f11d5f8
HJYP
401 ENTER;
402
c887dfa0 403 lx_battery *lx_b;
813c2d44
AG
404 GtkWidget *p;
405 const char *str;
406 int tmp_int;
407
408 lx_b = g_new0(lx_battery, 1);
c887dfa0
JH
409
410 /* get available battery */
411 lx_b->b = battery_get ();
813c2d44
AG
412
413 p = gtk_event_box_new();
414 lxpanel_plugin_set_data(p, lx_b, destructor);
415 GTK_WIDGET_SET_FLAGS( p, GTK_NO_WINDOW );
416 gtk_container_set_border_width( GTK_CONTAINER(p), 1 );
4542c20d 417
c887dfa0
JH
418 lx_b->drawingArea = gtk_drawing_area_new();
419 gtk_widget_add_events( lx_b->drawingArea, GDK_BUTTON_PRESS_MASK );
8f11d5f8 420
813c2d44 421 gtk_container_add( (GtkContainer*)p, lx_b->drawingArea );
4542c20d 422
813c2d44
AG
423 lx_b->orientation = panel_get_orientation(panel);
424 if (lx_b->orientation == GTK_ORIENTATION_HORIZONTAL) {
c887dfa0
JH
425 lx_b->height = lx_b->length = 20;
426 lx_b->thickness = lx_b->width = 8;
8f11d5f8
HJYP
427 }
428 else {
c887dfa0
JH
429 lx_b->height = lx_b->thickness = 8;
430 lx_b->length = lx_b->width = 20;
8f11d5f8 431 }
c887dfa0 432 gtk_widget_set_size_request(lx_b->drawingArea, lx_b->width, lx_b->height);
8f11d5f8 433
c887dfa0 434 gtk_widget_show(lx_b->drawingArea);
8f11d5f8 435
8e05828e 436 g_signal_connect (G_OBJECT (lx_b->drawingArea),"configure-event",
c887dfa0 437 G_CALLBACK (configureEvent), (gpointer) lx_b);
8e05828e 438 g_signal_connect (G_OBJECT (lx_b->drawingArea), "expose-event",
c887dfa0 439 G_CALLBACK (exposeEvent), (gpointer) lx_b);
8f11d5f8 440
c887dfa0 441 sem_init(&(lx_b->alarmProcessLock), 0, 1);
8f11d5f8 442
c887dfa0
JH
443 lx_b->alarmCommand = lx_b->backgroundColor = lx_b->chargingColor1 = lx_b->chargingColor2
444 = lx_b->dischargingColor1 = lx_b->dischargingColor2 = NULL;
8f11d5f8
HJYP
445
446 /* Set default values for integers */
c887dfa0
JH
447 lx_b->alarmTime = 5;
448 lx_b->requestedBorder = 1;
8f11d5f8 449
813c2d44
AG
450 /* remember instance data */
451 lx_b->panel = panel;
452 lx_b->settings = settings;
8f11d5f8 453
5c0c599d
HG
454 lx_b->show_extended_information = false;
455
813c2d44
AG
456 config_setting_lookup_int(settings, "HideIfNoBattery", &lx_b->hide_if_no_battery);
457 if (config_setting_lookup_string(settings, "AlarmCommand", &str))
458 lx_b->alarmCommand = g_strdup(str);
459 if (config_setting_lookup_string(settings, "BackgroundColor", &str))
460 lx_b->backgroundColor = g_strdup(str);
461 if (config_setting_lookup_string(settings, "ChargingColor1", &str))
462 lx_b->chargingColor1 = g_strdup(str);
463 if (config_setting_lookup_string(settings, "ChargingColor2", &str))
464 lx_b->chargingColor2 = g_strdup(str);
465 if (config_setting_lookup_string(settings, "DischargingColor1", &str))
466 lx_b->dischargingColor1 = g_strdup(str);
467 if (config_setting_lookup_string(settings, "DischargingColor2", &str))
468 lx_b->dischargingColor2 = g_strdup(str);
469 config_setting_lookup_int(settings, "AlarmTime", &lx_b->alarmTime);
470 config_setting_lookup_int(settings, "BorderWidth", &lx_b->requestedBorder);
471 if (config_setting_lookup_int(settings, "Size", &tmp_int)) {
472 lx_b->thickness = MAX(1, tmp_int);
473 if (lx_b->orientation == GTK_ORIENTATION_HORIZONTAL)
474 lx_b->width = lx_b->thickness;
475 else
476 lx_b->height = lx_b->thickness;
477 gtk_widget_set_size_request(lx_b->drawingArea, lx_b->width,
478 lx_b->height);
8f11d5f8 479 }
813c2d44
AG
480 if (config_setting_lookup_int(settings, "ShowExtendedInformation", &tmp_int))
481 lx_b->show_extended_information = (tmp_int != 0);
8f11d5f8
HJYP
482
483 /* Make sure the border value is acceptable */
c887dfa0
JH
484 lx_b->border = MIN(MAX(0, lx_b->requestedBorder),
485 (MIN(lx_b->length, lx_b->thickness) - 1) / 2);
8f11d5f8
HJYP
486
487 /* Apply more default options */
c887dfa0
JH
488 if (! lx_b->alarmCommand)
489 lx_b->alarmCommand = g_strdup("xmessage Battery low");
490 if (! lx_b->backgroundColor)
491 lx_b->backgroundColor = g_strdup("black");
492 if (! lx_b->chargingColor1)
493 lx_b->chargingColor1 = g_strdup("#28f200");
494 if (! lx_b->chargingColor2)
495 lx_b->chargingColor2 = g_strdup("#22cc00");
496 if (! lx_b->dischargingColor1)
497 lx_b->dischargingColor1 = g_strdup("#ffee00");
498 if (! lx_b->dischargingColor2)
499 lx_b->dischargingColor2 = g_strdup("#d9ca00");
500
501 gdk_color_parse(lx_b->backgroundColor, &lx_b->background);
502 gdk_color_parse(lx_b->chargingColor1, &lx_b->charging1);
503 gdk_color_parse(lx_b->chargingColor2, &lx_b->charging2);
504 gdk_color_parse(lx_b->dischargingColor1, &lx_b->discharging1);
505 gdk_color_parse(lx_b->dischargingColor2, &lx_b->discharging2);
8f11d5f8
HJYP
506
507 /* Start the update loop */
13d82f29 508 lx_b->timer = g_timeout_add_seconds( 9, (GSourceFunc) update_timout, (gpointer) lx_b);
c887dfa0 509
813c2d44 510 RET(p);
8f11d5f8
HJYP
511}
512
513
514static void
813c2d44 515destructor(gpointer data)
8f11d5f8 516{
8f11d5f8
HJYP
517 ENTER;
518
813c2d44 519 lx_battery *b = (lx_battery *)data;
52cb5b58 520
029d9f0c 521 if (b->b != NULL)
811afd8f 522 battery_free(b->b);
029d9f0c 523
52cb5b58 524 if (b->pixmap)
f176735a 525 cairo_surface_destroy(b->pixmap);
8f11d5f8 526
8f11d5f8
HJYP
527 g_free(b->alarmCommand);
528 g_free(b->backgroundColor);
529 g_free(b->chargingColor1);
530 g_free(b->chargingColor2);
531 g_free(b->dischargingColor1);
532 g_free(b->dischargingColor2);
802d5540 533
8f11d5f8 534 g_free(b->rateSamples);
8f11d5f8 535 sem_destroy(&(b->alarmProcessLock));
3396dfea 536 if (b->timer)
537 g_source_remove(b->timer);
8f11d5f8
HJYP
538 g_free(b);
539
540 RET();
541
542}
543
544
813c2d44 545static void orientation(Panel *panel, GtkWidget *p) {
8f11d5f8
HJYP
546
547 ENTER;
548
813c2d44 549 lx_battery *b = lxpanel_plugin_get_data(p);
8f11d5f8 550
813c2d44
AG
551 if (b->orientation != panel_get_orientation(panel)) {
552 b->orientation = panel_get_orientation(panel);
8f11d5f8
HJYP
553 unsigned int swap = b->height;
554 b->height = b->width;
555 b->width = swap;
556 gtk_widget_set_size_request(b->drawingArea, b->width, b->height);
557 }
558
559 RET();
560}
561
562
813c2d44 563static gboolean applyConfig(gpointer user_data)
8f11d5f8 564{
8f11d5f8
HJYP
565 ENTER;
566
813c2d44 567 lx_battery *b = lxpanel_plugin_get_data(user_data);
8f11d5f8
HJYP
568
569 /* Update colors */
570 if (b->backgroundColor &&
813c2d44
AG
571 gdk_color_parse(b->backgroundColor, &b->background))
572 config_group_set_string(b->settings, "BackgroundColor", b->backgroundColor);
573 if (b->chargingColor1 && gdk_color_parse(b->chargingColor1, &b->charging1))
574 config_group_set_string(b->settings, "ChargingColor1", b->chargingColor1);
575 if (b->chargingColor2 && gdk_color_parse(b->chargingColor2, &b->charging2))
576 config_group_set_string(b->settings, "ChargingColor2", b->chargingColor2);
8f11d5f8 577 if (b->dischargingColor1 &&
813c2d44
AG
578 gdk_color_parse(b->dischargingColor1, &b->discharging1))
579 config_group_set_string(b->settings, "DischargingColor1", b->dischargingColor1);
8f11d5f8 580 if (b->dischargingColor2 &&
813c2d44
AG
581 gdk_color_parse(b->dischargingColor2, &b->discharging2))
582 config_group_set_string(b->settings, "DischargingColor2", b->dischargingColor2);
8f11d5f8 583
e751fe05 584 /* Make sure the border value is acceptable */
8f11d5f8
HJYP
585 b->border = MIN(MAX(0, b->requestedBorder),
586 (MIN(b->length, b->thickness) - 1) / 2);
587
8f11d5f8 588 /* Resize the widget */
cfde283a 589 if (b->orientation == GTK_ORIENTATION_HORIZONTAL)
8f11d5f8
HJYP
590 b->width = b->thickness;
591 else
592 b->height = b->thickness;
593 gtk_widget_set_size_request(b->drawingArea, b->width, b->height);
594
5c0c599d
HG
595 /* update tooltip */
596 set_tooltip_text(b);
597
813c2d44
AG
598 /* update settings */
599#if 0
600 config_group_set_int(b->settings, "HideIfNoBattery", b->hide_if_no_battery);
601#endif
602 config_group_set_string(b->settings, "AlarmCommand", b->alarmCommand);
603 config_group_set_int(b->settings, "AlarmTime", b->alarmTime);
604 config_group_set_int(b->settings, "BorderWidth", b->requestedBorder);
605 config_group_set_int(b->settings, "Size", b->thickness);
606 config_group_set_int(b->settings, "ShowExtendedInformation",
607 b->show_extended_information);
608
8f11d5f8 609 RET();
8f11d5f8
HJYP
610}
611
612
813c2d44 613static void config(Panel *panel, GtkWidget *p, GtkWindow *parent) {
8f11d5f8
HJYP
614 ENTER;
615
616 GtkWidget *dialog;
813c2d44
AG
617 lx_battery *b = lxpanel_plugin_get_data(p);
618 dialog = lxpanel_generic_config_dlg(_("Battery Monitor"),
619 panel, applyConfig, p,
04a2f050 620#if 0
e2957bd2 621 _("Hide if there is no battery"), &b->hide_if_no_battery, CONF_TYPE_BOOL,
04a2f050 622#endif
e2957bd2
HJYP
623 _("Alarm command"), &b->alarmCommand, CONF_TYPE_STR,
624 _("Alarm time (minutes left)"), &b->alarmTime, CONF_TYPE_INT,
625 _("Background color"), &b->backgroundColor, CONF_TYPE_STR,
626 _("Charging color 1"), &b->chargingColor1, CONF_TYPE_STR,
627 _("Charging color 2"), &b->chargingColor2, CONF_TYPE_STR,
628 _("Discharging color 1"), &b->dischargingColor1, CONF_TYPE_STR,
629 _("Discharging color 2"), &b->dischargingColor2, CONF_TYPE_STR,
630 _("Border width"), &b->requestedBorder, CONF_TYPE_INT,
631 _("Size"), &b->thickness, CONF_TYPE_INT,
5c0c599d 632 _("Show Extended Information"), &b->show_extended_information, CONF_TYPE_BOOL,
8f11d5f8
HJYP
633 NULL);
634 gtk_window_present(GTK_WINDOW(dialog));
635
636 RET();
8f11d5f8
HJYP
637}
638
639
813c2d44 640FM_DEFINE_MODULE(lxpanel_gtk, batt)
8f11d5f8 641
813c2d44
AG
642/* Plugin descriptor. */
643LXPanelPluginInit fm_module_init_lxpanel_gtk = {
3c3e9c9e 644 .name = N_("Battery Monitor"),
3c3e9c9e
HG
645 .description = N_("Display battery status using ACPI"),
646
813c2d44 647 .new_instance = constructor,
3c3e9c9e 648 .config = config,
813c2d44
AG
649 .reconfigure = orientation,
650 .button_press_event = buttonPressEvent
8f11d5f8 651};
f855ac58
HG
652
653
654/* vim: set sw=4 sts=4 : */