1 /**************************************************************************
5 * Copyright (C) 2009 Sebastian Reichel <elektranox@gmail.com>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License version 2
9 * or any later version as published by the Free Software Foundation.
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
14 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **************************************************************************/
24 #include <cairo-xlib.h>
25 #include <pango/pangocairo.h>
35 PangoFontDescription
*bat1_font_desc
;
36 PangoFontDescription
*bat2_font_desc
;
37 struct batstate battery_state
;
39 static char buf_bat_percentage
[10];
40 static char buf_bat_time
[20];
42 int8_t battery_low_status
;
43 char* battery_low_cmd
;
45 void update_battery(struct batstate
*data
) {
48 int64_t energy_now
= 0, energy_full
= 0, current_now
= 0;
50 int8_t new_percentage
= 0;
52 fp
= fopen("/sys/class/power_supply/BAT0/energy_now", "r");
54 fgets(tmp
, sizeof tmp
, fp
);
55 energy_now
= atoi(tmp
);
59 fp
= fopen("/sys/class/power_supply/BAT0/energy_full", "r");
61 fgets(tmp
, sizeof tmp
, fp
);
62 energy_full
= atoi(tmp
);
66 fp
= fopen("/sys/class/power_supply/BAT0/current_now", "r");
68 fgets(tmp
, sizeof tmp
, fp
);
69 current_now
= atoi(tmp
);
73 fp
= fopen("/sys/class/power_supply/BAT0/status", "r");
75 fgets(tmp
, sizeof tmp
, fp
);
79 data
->state
= BATTERY_UNKNOWN
;
80 if(strcasecmp(tmp
, "Charging\n")==0) data
->state
= BATTERY_CHARGING
;
81 if(strcasecmp(tmp
, "Discharging\n")==0) data
->state
= BATTERY_DISCHARGING
;
85 case BATTERY_CHARGING
:
86 seconds
= 3600 * (energy_full
- energy_now
) / current_now
;
88 case BATTERY_DISCHARGING
:
89 seconds
= 3600 * energy_now
/ current_now
;
97 data
->time
.hours
= seconds
/ 3600;
98 seconds
-= 3600 * data
->time
.hours
;
99 data
->time
.minutes
= seconds
/ 60;
100 seconds
-= 60 * data
->time
.minutes
;
101 data
->time
.seconds
= seconds
;
104 new_percentage
= (energy_now
*100)/energy_full
;
106 if(battery_low_status
!= 0 && battery_low_status
== new_percentage
&& data
->percentage
> new_percentage
) {
107 printf("battery low, executing: %s\n", battery_low_cmd
);
108 if(battery_low_cmd
) system(battery_low_cmd
);
111 data
->percentage
= new_percentage
;
120 int i
, bat_percentage_height
, bat_percentage_height_ink
, bat_time_height
, bat_time_height_ink
;
122 for (i
=0 ; i
< nb_panel
; i
++) {
124 battery
= &panel
->battery
;
126 battery
->area
.parent
= panel
;
127 battery
->area
.panel
= panel
;
128 battery
->area
._draw_foreground
= draw_battery
;
129 battery
->area
._resize
= resize_battery
;
131 if (!battery
->area
.on_screen
) continue;
132 if((fp
= fopen("/sys/class/power_supply/BAT0/energy_now", "r")) == NULL
) {
133 fprintf(stderr
, "ERROR: battery applet can't open energy_now\n");
134 panel
->battery
.area
.on_screen
= 0;
138 if((fp
= fopen("/sys/class/power_supply/BAT0/energy_full", "r")) == NULL
) {
139 fprintf(stderr
, "ERROR: battery applet can't open energy_full\n");
140 panel
->battery
.area
.on_screen
= 0;
144 if((fp
= fopen("/sys/class/power_supply/BAT0/current_now", "r")) == NULL
) {
145 fprintf(stderr
, "ERROR: battery applet can't open current_now\n");
146 panel
->battery
.area
.on_screen
= 0;
150 if((fp
= fopen("/sys/class/power_supply/BAT0/status", "r")) == NULL
) {
151 fprintf(stderr
, "ERROR: battery applet can't open status");
152 panel
->battery
.area
.on_screen
= 0;
157 battery
->area
.posy
= panel
->area
.pix
.border
.width
+ panel
->area
.paddingy
;
158 battery
->area
.height
= panel
->area
.height
- (2 * battery
->area
.posy
);
159 battery
->area
.resize
= 1;
160 battery
->area
.redraw
= 1;
162 update_battery(&battery_state
);
163 snprintf(buf_bat_percentage
, sizeof(buf_bat_percentage
), "%d%%", battery_state
.percentage
);
164 snprintf(buf_bat_time
, sizeof(buf_bat_time
), "%02d:%02d", battery_state
.time
.hours
, battery_state
.time
.minutes
);
166 get_text_size(bat1_font_desc
, &bat_percentage_height_ink
, &bat_percentage_height
, panel
->area
.height
, buf_bat_percentage
, strlen(buf_bat_percentage
));
167 battery
->bat1_posy
= (battery
->area
.height
- bat_percentage_height
) / 2;
169 get_text_size(bat2_font_desc
, &bat_time_height_ink
, &bat_time_height
, panel
->area
.height
, buf_bat_time
, strlen(buf_bat_time
));
171 battery
->bat1_posy
-= ((bat_time_height_ink
+ 2) / 2);
172 battery
->bat2_posy
= battery
->bat1_posy
+ bat_percentage_height
+ 2 - (bat_percentage_height
- bat_percentage_height_ink
)/2 - (bat_time_height
- bat_time_height_ink
)/2;
177 void draw_battery (void *obj
, cairo_t
*c
, int active
)
179 Battery
*battery
= obj
;
182 layout
= pango_cairo_create_layout (c
);
185 pango_layout_set_font_description(layout
, bat1_font_desc
);
186 pango_layout_set_width(layout
, battery
->area
.width
* PANGO_SCALE
);
187 pango_layout_set_alignment(layout
, PANGO_ALIGN_CENTER
);
188 pango_layout_set_text(layout
, buf_bat_percentage
, strlen(buf_bat_percentage
));
190 cairo_set_source_rgba(c
, battery
->font
.color
[0], battery
->font
.color
[1], battery
->font
.color
[2], battery
->font
.alpha
);
192 pango_cairo_update_layout(c
, layout
);
193 cairo_move_to(c
, 0, battery
->bat1_posy
);
194 pango_cairo_show_layout(c
, layout
);
196 pango_layout_set_font_description(layout
, bat2_font_desc
);
197 pango_layout_set_indent(layout
, 0);
198 pango_layout_set_text(layout
, buf_bat_time
, strlen(buf_bat_time
));
199 pango_layout_set_width(layout
, battery
->area
.width
* PANGO_SCALE
);
201 pango_cairo_update_layout(c
, layout
);
202 cairo_move_to(c
, 0, battery
->bat2_posy
);
203 pango_cairo_show_layout(c
, layout
);
205 g_object_unref(layout
);
208 void resize_battery(void *obj
)
210 Battery
*battery
= obj
;
212 int percentage_width
, time_width
, new_width
;
214 percentage_width
= time_width
= 0;
215 battery
->area
.redraw
= 1;
217 snprintf(buf_bat_percentage
, sizeof(buf_bat_percentage
), "%d%%", battery_state
.percentage
);
218 snprintf(buf_bat_time
, sizeof(buf_bat_time
), "%02d:%02d", battery_state
.time
.hours
, battery_state
.time
.minutes
);
223 pmap
= XCreatePixmap(server
.dsp
, server
.root_win
, battery
->area
.width
, battery
->area
.height
, server
.depth
);
225 cs
= cairo_xlib_surface_create(server
.dsp
, pmap
, server
.visual
, battery
->area
.width
, battery
->area
.height
);
226 c
= cairo_create(cs
);
227 layout
= pango_cairo_create_layout(c
);
230 pango_layout_set_font_description(layout
, bat1_font_desc
);
231 pango_layout_set_indent(layout
, 0);
232 pango_layout_set_text(layout
, buf_bat_percentage
, strlen(buf_bat_percentage
));
233 pango_layout_get_pixel_size(layout
, &percentage_width
, NULL
);
235 pango_layout_set_font_description(layout
, bat2_font_desc
);
236 pango_layout_set_indent(layout
, 0);
237 pango_layout_set_text(layout
, buf_bat_time
, strlen(buf_bat_time
));
238 pango_layout_get_pixel_size(layout
, &time_width
, NULL
);
240 if(percentage_width
> time_width
) new_width
= percentage_width
;
241 else new_width
= time_width
;
243 new_width
+= (2*battery
->area
.paddingxlr
) + (2*battery
->area
.pix
.border
.width
);
245 if(new_width
> battery
->area
.width
|| new_width
< (battery
->area
.width
-6)) {
247 Panel
*panel
= ((Area
*)obj
)->panel
;
249 printf("battery_width %d, new_width %d\n", battery
->area
.width
, new_width
);
252 // we try to limit the number of resize
253 battery
->area
.width
= new_width
+ 1;
254 battery
->area
.posx
= panel
->area
.width
- battery
->area
.width
- panel
->area
.paddingxlr
- panel
->area
.pix
.border
.width
;
255 if (panel
->clock
.area
.on_screen
)
256 battery
->area
.posx
-= (panel
->clock
.area
.width
+ panel
->area
.paddingx
);
258 // resize other objects on panel
259 for (i
=0 ; i
< nb_panel
; i
++)
260 panel1
[i
].area
.resize
= 1;
262 systray
.area
.resize
= 1;
266 g_object_unref (layout
);
268 cairo_surface_destroy (cs
);
269 XFreePixmap (server
.dsp
, pmap
);