Merge battery format from https://gitlab.com/berkley4/tint2 (issue #229)
@@ -29,6 +29,7 @@ Justin Jacobs : tint2conf fixes
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:
@@ -456,6 +456,7 @@ <li><p><code>taskbar_background_id = integer</code> : Which background to use</p></li>
<li><p><code>taskbar_active_background_id = integer</code> : Which background to use for the taskbar of the current virtual desktop.</p></li> <li><p><code>taskbar_hide_inactive_tasks = boolean (0 or 1)</code> : If enabled, the taskbar shows only the active task. <em>(since 0.12)</em></p></li> <li><p><code>taskbar_hide_different_monitor = boolean (0 or 1)</code> : 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. <em>(since 0.12)</em></p></li> +<li><p><code>taskbar_hide_different_desktop = boolean (0 or 1)</code> : 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. <em>(since 0.15)</em></p></li> <li><p><code>taskbar_always_show_all_desktop_tasks = boolean (0 or 1)</code> : Has effect only if <code>taskbar_mode = multi_desktop</code>. 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. <em>(since 0.12.4)</em></p></li> <li><p><code>taskbar_sort_order = none/title/center</code> : Specifies the sort order of the tasks on the taskbar. <em>(since 0.12)</em></p> <ul>@@ -569,6 +570,15 @@ <li><p><code>battery_low_cmd = notify-send "battery low"</code> : Command to execute when the battery is low.</p></li>
<li><p><code>bat1_font = [FAMILY-LIST] [STYLE-OPTIONS] [SIZE]</code></p></li> <li><p><code>bat2_font = [FAMILY-LIST] [STYLE-OPTIONS] [SIZE]</code></p></li> <li><p><code>battery_font_color = color opacity (0 to 100)</code></p></li> +<li><p><code>bat1_format = FORMAT_STRING</code> : Format for battery line 1. Default: %p. <em>(since 0.15)</em> Format specification:</p> +<ul> +<li>%s: State (charging, discharging, full, unknown).</li> +<li>%m: Minutes left until completely charged/discharged (estimated).</li> +<li>%h: Hours left until completely charged/discharged (estimated).</li> +<li>%t: Time left. Shows "hrs:mins" when charging/discharging, or "Ful\" when full.</li> +<li>%p: Percentage. Includes the % sign.</li> +</ul></li> +<li><p><code>bat2_format = FORMAT_STRING</code> : Format for battery line 2. Default: %t. <em>(since 0.15)</em></p></li> <li><p><code>battery_padding = horizontal_padding vertical_padding</code></p></li> <li><p><code>battery_background_id = integer</code> : Which background to use for the battery.</p></li> <li><p><code>battery_tooltip_enabled = boolean (0 or 1)</code> : Enable/disable battery tooltips. <em>(since 0.12.3)</em></p></li>
@@ -461,6 +461,8 @@ \fB\fCtaskbar_hide_inactive_tasks = boolean (0 or 1)\fR : If enabled, the taskbar shows only the active task. \fI(since 0.12)\fP
.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@@ -656,6 +658,22 @@ .IP \(bu 2
\fB\fCbat2_font = [FAMILY\-LIST] [STYLE\-OPTIONS] [SIZE]\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
@@ -542,6 +542,15 @@ * `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.
@@ -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 @@ battery_low_cmd_sent = FALSE;
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 @@ pango_font_description_free(bat2_font_desc);
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 @@
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 @@ if (battery_state.percentage > 100) {
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 @@ {
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 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)
@@ -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;
@@ -565,6 +565,21 @@ #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 extract_values(value, &value1, &value2, &value3);
@@ -83,7 +83,7 @@ // battery
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,@@ -5747,6 +5747,46 @@ col++;
gtk_tooltips_set_tip(tooltips, battery_font_color, _("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);
@@ -91,7 +91,7 @@ // battery
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,
@@ -765,6 +765,8 @@ config_write_color(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 @@ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(battery_font_line1_set), TRUE);
} 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;