diff --git a/AUTHORS b/AUTHORS
index 58a453b..df9c8cd 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -29,6 +29,7 @@ Contributors:
Oskari Rauta : separator plugin, gradients
Michael Messmore : Support for Path in .desktop files
Matthew Otnel : config option systray_name_filter
+ Ryan Gray, Jeff Blake (https://gitlab.com/berkley4) : battery format
Translations:
Bosnian:
diff --git a/doc/manual.html b/doc/manual.html
index 72a66c4..deedfcd 100644
--- a/doc/manual.html
+++ b/doc/manual.html
@@ -456,6 +456,7 @@ panel_size = 94% 30
taskbar_active_background_id = integer
: Which background to use for the taskbar of the current virtual desktop.
taskbar_hide_inactive_tasks = boolean (0 or 1)
: If enabled, the taskbar shows only the active task. (since 0.12)
taskbar_hide_different_monitor = boolean (0 or 1)
: If enabled, the taskbar shows only the tasks from the current monitor. Useful when running different tint2 instances on different monitors, each one having its own config. (since 0.12)
+taskbar_hide_different_desktop = boolean (0 or 1)
: If enabled, the taskbar shows only the tasks from the current desktop. Useful to make multi-desktop taskbars more compact, but still allow desktop switching with mouse click. (since 0.15)
taskbar_always_show_all_desktop_tasks = boolean (0 or 1)
: Has effect only if taskbar_mode = multi_desktop
. If enabled, tasks that appear on all desktops are shown on all taskbars. Otherwise, they are shown only on the taskbar of the current desktop. (since 0.12.4)
taskbar_sort_order = none/title/center
: Specifies the sort order of the tasks on the taskbar. (since 0.12)
@@ -569,6 +570,15 @@ panel_size = 94% 30
bat1_font = [FAMILY-LIST] [STYLE-OPTIONS] [SIZE]
bat2_font = [FAMILY-LIST] [STYLE-OPTIONS] [SIZE]
battery_font_color = color opacity (0 to 100)
+bat1_format = FORMAT_STRING
: Format for battery line 1. Default: %p. (since 0.15) Format specification:
+
+- %s: State (charging, discharging, full, unknown).
+- %m: Minutes left until completely charged/discharged (estimated).
+- %h: Hours left until completely charged/discharged (estimated).
+- %t: Time left. Shows "hrs:mins" when charging/discharging, or "Ful\" when full.
+- %p: Percentage. Includes the % sign.
+
+bat2_format = FORMAT_STRING
: Format for battery line 2. Default: %t. (since 0.15)
battery_padding = horizontal_padding vertical_padding
battery_background_id = integer
: Which background to use for the battery.
battery_tooltip_enabled = boolean (0 or 1)
: Enable/disable battery tooltips. (since 0.12.3)
diff --git a/doc/tint2.1 b/doc/tint2.1
index 5a12a98..1b00f4a 100644
--- a/doc/tint2.1
+++ b/doc/tint2.1
@@ -461,6 +461,8 @@ You can switch between virtual desktops.
.IP \(bu 2
\fB\fCtaskbar_hide_different_monitor = boolean (0 or 1)\fR : If enabled, the taskbar shows only the tasks from the current monitor. Useful when running different tint2 instances on different monitors, each one having its own config. \fI(since 0.12)\fP
.IP \(bu 2
+\fB\fCtaskbar_hide_different_desktop = boolean (0 or 1)\fR : If enabled, the taskbar shows only the tasks from the current desktop. Useful to make multi\-desktop taskbars more compact, but still allow desktop switching with mouse click. \fI(since 0.15)\fP
+.IP \(bu 2
\fB\fCtaskbar_always_show_all_desktop_tasks = boolean (0 or 1)\fR : Has effect only if \fB\fCtaskbar_mode = multi_desktop\fR\&. If enabled, tasks that appear on all desktops are shown on all taskbars. Otherwise, they are shown only on the taskbar of the current desktop. \fI(since 0.12.4)\fP
.IP \(bu 2
\fB\fCtaskbar_sort_order = none/title/center\fR : Specifies the sort order of the tasks on the taskbar. \fI(since 0.12)\fP
@@ -657,6 +659,22 @@ To hide the clock, comment \fB\fCtime1_format\fR and \fB\fCtime2_format\fR\&.
.IP \(bu 2
\fB\fCbattery_font_color = color opacity (0 to 100)\fR
.IP \(bu 2
+\fB\fCbat1_format = FORMAT_STRING\fR : Format for battery line 1. Default: %p. \fI(since 0.15)\fP Format specification:
+.RS
+.IP \(bu 2
+%s: State (charging, discharging, full, unknown).
+.IP \(bu 2
+%m: Minutes left until completely charged/discharged (estimated).
+.IP \(bu 2
+%h: Hours left until completely charged/discharged (estimated).
+.IP \(bu 2
+%t: Time left. Shows "hrs:mins" when charging/discharging, or "Ful\[rs]" when full.
+.IP \(bu 2
+%p: Percentage. Includes the % sign.
+.RE
+.IP \(bu 2
+\fB\fCbat2_format = FORMAT_STRING\fR : Format for battery line 2. Default: %t. \fI(since 0.15)\fP
+.IP \(bu 2
\fB\fCbattery_padding = horizontal_padding vertical_padding\fR
.IP \(bu 2
\fB\fCbattery_background_id = integer\fR : Which background to use for the battery.
diff --git a/doc/tint2.md b/doc/tint2.md
index 2097a0e..5757726 100644
--- a/doc/tint2.md
+++ b/doc/tint2.md
@@ -542,6 +542,15 @@ The action semantics:
* `battery_font_color = color opacity (0 to 100)`
+ * `bat1_format = FORMAT_STRING` : Format for battery line 1. Default: %p. *(since 0.15)* Format specification:
+ * %s: State (charging, discharging, full, unknown).
+ * %m: Minutes left until completely charged/discharged (estimated).
+ * %h: Hours left until completely charged/discharged (estimated).
+ * %t: Time left. Shows "hrs:mins" when charging/discharging, or "Ful\" when full.
+ * %p: Percentage. Includes the % sign.
+
+ * `bat2_format = FORMAT_STRING` : Format for battery line 2. Default: %t. *(since 0.15)*
+
* `battery_padding = horizontal_padding vertical_padding`
* `battery_background_id = integer` : Which background to use for the battery.
diff --git a/src/battery/battery.c b/src/battery/battery.c
index bbe7dca..c9b1201 100644
--- a/src/battery/battery.c
+++ b/src/battery/battery.c
@@ -35,14 +35,17 @@ gboolean bat1_has_font;
PangoFontDescription *bat1_font_desc;
gboolean bat2_has_font;
PangoFontDescription *bat2_font_desc;
+char *bat1_format;
+char *bat2_format;
struct BatteryState battery_state;
gboolean battery_enabled;
gboolean battery_tooltip_enabled;
int percentage_hide;
static timeout *battery_timeout;
-static char buf_bat_percentage[10];
-static char buf_bat_time[20];
+#define BATTERY_BUF_SIZE 256
+static char buf_bat_line1[BATTERY_BUF_SIZE];
+static char buf_bat_line2[BATTERY_BUF_SIZE];
int8_t battery_low_status;
gboolean battery_low_cmd_sent;
@@ -73,8 +76,10 @@ void default_battery()
battery_timeout = NULL;
bat1_has_font = FALSE;
bat1_font_desc = NULL;
+ bat1_format = strdup("%p");
bat2_has_font = FALSE;
bat2_font_desc = NULL;
+ bat2_format = strdup("%t");
ac_connected_cmd = NULL;
ac_disconnected_cmd = NULL;
battery_low_cmd = NULL;
@@ -98,6 +103,10 @@ void cleanup_battery()
bat2_font_desc = NULL;
free(battery_low_cmd);
battery_low_cmd = NULL;
+ free(bat1_format);
+ bat1_format = NULL;
+ free(bat2_format);
+ bat2_format = NULL;
free(battery_lclick_command);
battery_lclick_command = NULL;
free(battery_mclick_command);
@@ -119,6 +128,88 @@ void cleanup_battery()
battery_os_free();
}
+char *strncat(char *dest, const char *addendum, size_t limit)
+{
+ char *tmp = strdup(dest);
+
+ // Actually concatenate them.
+ snprintf(dest, limit, "%s%s", tmp, addendum);
+
+ free(tmp);
+ return dest;
+}
+
+void battery_update_text(char *dest, char *format)
+{
+ if (!battery_enabled || !dest || !format)
+ return;
+ // We want to loop over the format specifier, replacing any known symbols with our battery data.
+ // First, erase anything already stored in the buffer.
+ // This ensures the string will always be null-terminated.
+ bzero(dest, BATTERY_BUF_SIZE);
+ char buf[BATTERY_BUF_SIZE];
+ bzero(buf, BATTERY_BUF_SIZE);
+
+ for (size_t o = 0; o < strlen(format); o++) {
+ char *c = &format[o];
+ // Format specification:
+ // %s : State (charging, discharging, full, unknown)
+ // %m : Minutes left (estimated).
+ // %h : Hours left (estimated).
+ // %t : Time left. This is equivalent to the old behaviour; i.e. "(plugged in)" or "hrs:mins" otherwise.
+ // %p : Percentage left. Includes the % sign.
+ if (*c == '%') {
+ c++;
+ o++; // Skip the format control character.
+ switch (*c) {
+ case 's':
+ // Append the appropriate status message to the string.
+ strncat(dest,
+ (battery_state.state == BATTERY_CHARGING)
+ ? "Charging"
+ : (battery_state.state == BATTERY_DISCHARGING)
+ ? "Discharging"
+ : (battery_state.state == BATTERY_FULL) ? "Full" : "Unknown",
+ BATTERY_BUF_SIZE);
+ break;
+ case 'm':
+ snprintf(buf, sizeof(buf), "%02d", battery_state.time.minutes);
+ strncat(dest, buf, BATTERY_BUF_SIZE);
+ break;
+ case 'h':
+ snprintf(buf, sizeof(buf), "%02d", battery_state.time.hours);
+ strncat(dest, buf, BATTERY_BUF_SIZE);
+ break;
+ case 'p':
+ snprintf(buf, sizeof(buf), "%d%%", battery_state.percentage);
+ strncat(dest, buf, BATTERY_BUF_SIZE);
+ break;
+ case 't':
+ if (battery_state.state == BATTERY_FULL) {
+ snprintf(buf, sizeof(buf), "Full");
+ strncat(dest, buf, BATTERY_BUF_SIZE);
+ } else {
+ snprintf(buf, sizeof(buf), "%02d:%02d", battery_state.time.hours, battery_state.time.minutes);
+ strncat(dest, buf, BATTERY_BUF_SIZE);
+ }
+ break;
+
+ case '%':
+ buf[0] = *c;
+ strncat(dest, buf, BATTERY_BUF_SIZE);
+ break;
+ default:
+ fprintf(stderr, "Battery: unrecognised format specifier '%%%c'.\n", *c);
+ buf[0] = *c;
+ strncat(dest, buf, BATTERY_BUF_SIZE);
+ }
+ } else {
+ buf[0] = *c;
+ strncat(dest, buf, BATTERY_BUF_SIZE);
+ }
+ }
+}
+
void init_battery()
{
if (!battery_enabled)
@@ -278,11 +369,9 @@ int update_battery()
battery_state.percentage = 100;
}
- snprintf(buf_bat_percentage, sizeof(buf_bat_percentage), "%d%%", battery_state.percentage);
- if (battery_state.state == BATTERY_FULL) {
- strcpy(buf_bat_time, "Full");
- } else {
- snprintf(buf_bat_time, sizeof(buf_bat_time), "%02d:%02d", battery_state.time.hours, battery_state.time.minutes);
+ battery_update_text(buf_bat_line1, bat1_format);
+ if (bat2_format != 0) {
+ battery_update_text(buf_bat_line2, bat2_format);
}
return err;
@@ -292,8 +381,8 @@ int battery_compute_desired_size(void *obj)
{
Battery *battery = (Battery *)obj;
return text_area_compute_desired_size(&battery->area,
- buf_bat_percentage,
- buf_bat_time,
+ buf_bat_line1,
+ buf_bat_line2,
bat1_font_desc,
bat2_font_desc);
}
@@ -302,8 +391,8 @@ gboolean resize_battery(void *obj)
{
Battery *battery = (Battery *)obj;
return resize_text_area(&battery->area,
- buf_bat_percentage,
- buf_bat_time,
+ buf_bat_line1,
+ buf_bat_line2,
bat1_font_desc,
bat2_font_desc,
&battery->bat1_posy,
@@ -315,8 +404,8 @@ void draw_battery(void *obj, cairo_t *c)
Battery *battery = (Battery *)obj;
draw_text_area(&battery->area,
c,
- buf_bat_percentage,
- buf_bat_time,
+ buf_bat_line1,
+ buf_bat_line2,
bat1_font_desc,
bat2_font_desc,
battery->bat1_posy,
@@ -327,8 +416,8 @@ void draw_battery(void *obj, cairo_t *c)
void battery_dump_geometry(void *obj, int indent)
{
Battery *battery = (Battery *)obj;
- fprintf(stderr, "%*sText 1: y = %d, text = %s\n", indent, "", battery->bat1_posy, buf_bat_percentage);
- fprintf(stderr, "%*sText 2: y = %d, text = %s\n", indent, "", battery->bat2_posy, buf_bat_time);
+ fprintf(stderr, "%*sText 1: y = %d, text = %s\n", indent, "", battery->bat1_posy, buf_bat_line1);
+ fprintf(stderr, "%*sText 2: y = %d, text = %s\n", indent, "", battery->bat2_posy, buf_bat_line2);
}
char *battery_get_tooltip(void *obj)
diff --git a/src/battery/battery.h b/src/battery/battery.h
index 9c02803..55f7b2e 100644
--- a/src/battery/battery.h
+++ b/src/battery/battery.h
@@ -48,6 +48,8 @@ extern gboolean bat1_has_font;
extern PangoFontDescription *bat1_font_desc;
extern gboolean bat2_has_font;
extern PangoFontDescription *bat2_font_desc;
+extern char *bat1_format;
+extern char *bat2_format;
extern gboolean battery_enabled;
extern gboolean battery_tooltip_enabled;
extern int percentage_hide;
diff --git a/src/config.c b/src/config.c
index 6f2bf85..7057e21 100644
--- a/src/config.c
+++ b/src/config.c
@@ -564,6 +564,21 @@ void add_entry(char *key, char *value)
#ifdef ENABLE_BATTERY
bat2_font_desc = pango_font_description_from_string(value);
bat2_has_font = TRUE;
+#endif
+ } else if (strcmp (key, "bat1_format") == 0) {
+#ifdef ENABLE_BATTERY
+ if (strlen(value) > 0) {
+ free(bat1_format);
+ bat1_format = strdup(value);
+ battery_enabled = 1;
+ }
+#endif
+ } else if (strcmp (key, "bat2_format") == 0) {
+#ifdef ENABLE_BATTERY
+ if (strlen(value) > 0) {
+ free(bat2_format);
+ bat2_format = strdup(value);
+ }
#endif
} else if (strcmp(key, "battery_font_color") == 0) {
#ifdef ENABLE_BATTERY
diff --git a/src/tint2conf/properties.c b/src/tint2conf/properties.c
index 8a86c5c..5caf617 100644
--- a/src/tint2conf/properties.c
+++ b/src/tint2conf/properties.c
@@ -83,7 +83,7 @@ GtkWidget *clock_background;
GtkWidget *battery_hide_if_higher, *battery_alert_if_lower, *battery_alert_cmd;
GtkWidget *battery_padding_x, *battery_padding_y;
GtkWidget *battery_font_line1, *battery_font_line1_set, *battery_font_line2, *battery_font_line2_set,
- *battery_font_color;
+ *battery_font_color, *battery_format1, *battery_format2;
GtkWidget *battery_background;
GtkWidget *battery_tooltip;
GtkWidget *battery_left_command, *battery_mclick_command, *battery_right_command, *battery_uwheel_command,
@@ -5749,6 +5749,46 @@ void create_battery(GtkWidget *parent)
_("Specifies the font clor used to display the battery text."),
NULL);
+ row++, col = 2;
+ label = gtk_label_new(_("First line format"));
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_widget_show(label);
+ gtk_table_attach(GTK_TABLE(table), label, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
+ col++;
+
+ battery_format1 = gtk_entry_new();
+ gtk_widget_show(battery_format1);
+ gtk_entry_set_width_chars(GTK_ENTRY(battery_format1), 16);
+ gtk_table_attach(GTK_TABLE(table), battery_format1, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
+ col++;
+ char *bat_format_spec = "Format specification:\n"
+ " %s: State (charging, discharging, full, unknown).\n"
+ " %m: Minutes left until completely charged/discharged (estimated).\n"
+ " %h: Hours left until completely charged/discharged (estimated).\n"
+ " %t: Time left. Shows \"hrs:mins\" when charging/discharging, or \"Full\".\n"
+ " %p: Percentage. Includes the % sign.";
+ gtk_tooltips_set_tip(tooltips,
+ battery_format1,
+ _(bat_format_spec),
+ NULL);
+
+ row++, col = 2;
+ label = gtk_label_new(_("Second line format"));
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_widget_show(label);
+ gtk_table_attach(GTK_TABLE(table), label, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
+ col++;
+
+ battery_format2 = gtk_entry_new();
+ gtk_widget_show(battery_format2);
+ gtk_entry_set_width_chars(GTK_ENTRY(battery_format2), 16);
+ gtk_table_attach(GTK_TABLE(table), battery_format2, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0);
+ col++;
+ gtk_tooltips_set_tip(tooltips,
+ battery_format2,
+ _(bat_format_spec),
+ NULL);
+
change_paragraph(parent);
}
diff --git a/src/tint2conf/properties.h b/src/tint2conf/properties.h
index d978513..2e8a602 100644
--- a/src/tint2conf/properties.h
+++ b/src/tint2conf/properties.h
@@ -91,7 +91,7 @@ extern GtkWidget *clock_background;
extern GtkWidget *battery_hide_if_higher, *battery_alert_if_lower, *battery_alert_cmd;
extern GtkWidget *battery_padding_x, *battery_padding_y;
extern GtkWidget *battery_font_line1, *battery_font_line1_set, *battery_font_line2, *battery_font_line2_set,
- *battery_font_color;
+ *battery_font_color, *battery_format1, *battery_format2;
extern GtkWidget *battery_background;
extern GtkWidget *battery_tooltip;
extern GtkWidget *battery_left_command, *battery_mclick_command, *battery_right_command, *battery_uwheel_command,
diff --git a/src/tint2conf/properties_rw.c b/src/tint2conf/properties_rw.c
index 0a5e2fd..44c4d47 100644
--- a/src/tint2conf/properties_rw.c
+++ b/src/tint2conf/properties_rw.c
@@ -765,6 +765,8 @@ void config_write_battery(FILE *fp)
"battery_font_color",
color,
gtk_color_button_get_alpha(GTK_COLOR_BUTTON(battery_font_color)) * 100 / 0xffff);
+ fprintf(fp, "bat1_format = %s\n", gtk_entry_get_text(GTK_ENTRY(battery_format1)));
+ fprintf(fp, "bat2_format = %s\n", gtk_entry_get_text(GTK_ENTRY(battery_format2)));
fprintf(fp,
"battery_padding = %d %d\n",
(int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(battery_padding_x)),
@@ -1412,6 +1414,10 @@ void add_entry(char *key, char *value)
} else if (strcmp(key, "bat2_font") == 0) {
gtk_font_button_set_font_name(GTK_FONT_BUTTON(battery_font_line2), value);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(battery_font_line2_set), TRUE);
+ } else if (strcmp(key, "bat1_format") == 0) {
+ gtk_entry_set_text(GTK_ENTRY(battery_format1), value);
+ } else if (strcmp(key, "bat2_format") == 0) {
+ gtk_entry_set_text(GTK_ENTRY(battery_format2), value);
} else if (strcmp(key, "battery_font_color") == 0) {
extract_values(value, &value1, &value2, &value3);
GdkColor col;