all repos — tint2 @ 9f4087b471ccaa29195d227aa6ee9418c5d5de20

fork of the tint2 desktop panel for my custom setup - only minimized windows across all desktops for the taskbar

Implement tinting by icon content (issue #638; thanks @heisenbug)
o9000 mrovi9000@gmail.com
commit

9f4087b471ccaa29195d227aa6ee9418c5d5de20

parent

247687307bedd8ed3f550ab4a17c77b51f3f6a61

M src/config.csrc/config.c

@@ -350,6 +350,12 @@ int id = atoi(value);

id = (id < gradients->len && id >= 0) ? id : -1; if (id >= 0) bg->gradients[MOUSE_DOWN] = &g_array_index(gradients, GradientClass, id); + } else if (strcmp(key, "border_content_tint_weight") == 0) { + Background *bg = &g_array_index(backgrounds, Background, backgrounds->len - 1); + bg->border_content_tint_weight = MAX(0.0, MIN(1.0, atoi(value) / 100.)); + } else if (strcmp(key, "fill_content_tint_weight") == 0) { + Background *bg = &g_array_index(backgrounds, Background, backgrounds->len - 1); + bg->fill_content_tint_weight = MAX(0.0, MIN(1.0, atoi(value) / 100.)); } /* Gradients */
M src/taskbar/task.csrc/taskbar/task.c

@@ -41,6 +41,7 @@

void task_dump_geometry(void *obj, int indent); int task_compute_desired_size(void *obj); void task_refresh_thumbnail(Task *task); +void task_get_content_color(void *obj, Color *color); char *task_get_tooltip(void *obj) {

@@ -85,6 +86,7 @@ task_template.area.has_mouse_over_effect = panel_config.mouse_effects;

task_template.area.has_mouse_press_effect = panel_config.mouse_effects; task_template.area._dump_geometry = task_dump_geometry; task_template.area._is_under_mouse = full_width_area_is_under_mouse; + task_template.area._get_content_color = task_get_content_color; task_template.win = win; task_template.desktop = get_window_desktop(win); task_template.area.panel = &panels[monitor];

@@ -118,6 +120,7 @@ task_instance->area.has_mouse_press_effect = panel_config.mouse_effects;

task_instance->area._dump_geometry = task_dump_geometry; task_instance->area._is_under_mouse = full_width_area_is_under_mouse; task_instance->area._compute_desired_size = task_compute_desired_size; + task_instance->area._get_content_color = task_get_content_color; task_instance->win = task_template.win; task_instance->desktop = task_template.desktop; task_instance->win_x = task_template.win_x;

@@ -135,8 +138,11 @@ task_instance->area._get_tooltip_image = task_get_thumbnail;

} for (int k = 0; k < TASK_STATE_COUNT; ++k) { task_instance->icon[k] = task_template.icon[k]; + task_instance->icon_color[k] = task_template.icon_color[k]; task_instance->icon_hover[k] = task_template.icon_hover[k]; + task_instance->icon_color_hover[k] = task_template.icon_color_hover[k]; task_instance->icon_press[k] = task_template.icon_press[k]; + task_instance->icon_color_press[k] = task_template.icon_color_press[k]; } task_instance->icon_width = task_template.icon_width; task_instance->icon_height = task_template.icon_height;

@@ -342,6 +348,7 @@ task->icon_height = imlib_image_get_height();

for (int k = 0; k < TASK_STATE_COUNT; ++k) { imlib_context_set_image(orig_image); task->icon[k] = imlib_clone_image(); + get_image_mean_color(task->icon[k], &task->icon_color[k]); imlib_context_set_image(task->icon[k]); DATA32 *data32; if (panel->g_task.alpha[k] != 100 || panel->g_task.saturation[k] != 0 || panel->g_task.brightness[k] != 0) {

@@ -353,16 +360,19 @@ panel->g_task.alpha[k] / 100.0,

panel->g_task.saturation[k] / 100.0, panel->g_task.brightness[k] / 100.0); imlib_image_put_back_data(data32); + get_image_mean_color(task->icon[k], &task->icon_color[k]); } if (panel_config.mouse_effects) { task->icon_hover[k] = adjust_icon(task->icon[k], panel_config.mouse_over_alpha, panel_config.mouse_over_saturation, panel_config.mouse_over_brightness); + get_image_mean_color(task->icon_hover[k], &task->icon_color_hover[k]); task->icon_press[k] = adjust_icon(task->icon[k], panel_config.mouse_pressed_alpha, panel_config.mouse_pressed_saturation, panel_config.mouse_pressed_brightness); + get_image_mean_color(task->icon_press[k], &task->icon_color_press[k]); } } imlib_context_set_image(orig_image);

@@ -371,13 +381,16 @@

GPtrArray *task_buttons = get_task_buttons(task->win); if (task_buttons) { for (int i = 0; i < task_buttons->len; ++i) { - Task *task2 = g_ptr_array_index(task_buttons, i); + Task *task2 = (Task *)g_ptr_array_index(task_buttons, i); task2->icon_width = task->icon_width; task2->icon_height = task->icon_height; for (int k = 0; k < TASK_STATE_COUNT; ++k) { task2->icon[k] = task->icon[k]; + task2->icon_color[k] = task->icon_color[k]; task2->icon_hover[k] = task->icon_hover[k]; + task2->icon_color_hover[k] = task->icon_color_hover[k]; task2->icon_press[k] = task->icon_press[k]; + task2->icon_color_press[k] = task->icon_color_press[k]; } schedule_redraw(&task2->area); }

@@ -477,6 +490,24 @@ "",

task->_icon_x, task->_icon_y, panel->g_task.icon_size1); +} + +void task_get_content_color(void *obj, Color *color) +{ + Task *task = (Task *)obj; + Color *content_color = NULL; + if (panel_config.mouse_effects) { + if (task->area.mouse_state == MOUSE_OVER) + content_color = &task->icon_color_hover[task->current_state]; + else if (task->area.mouse_state == MOUSE_DOWN) + content_color = &task->icon_color_press[task->current_state]; + else + content_color = &task->icon_color[task->current_state]; + } else { + content_color = &task->icon_color[task->current_state]; + } + if (content_color) + memcpy(color, content_color, sizeof(*content_color)); } int task_compute_desired_size(void *obj)
M src/taskbar/task.hsrc/taskbar/task.h

@@ -63,6 +63,9 @@ Imlib_Image icon_hover[TASK_STATE_COUNT];

Imlib_Image icon_press[TASK_STATE_COUNT]; unsigned int icon_width; unsigned int icon_height; + Color icon_color[TASK_STATE_COUNT]; + Color icon_color_hover[TASK_STATE_COUNT]; + Color icon_color_press[TASK_STATE_COUNT]; char *title; int urgent_tick; // These may not be up-to-date
M src/tint2conf/background_gui.csrc/tint2conf/background_gui.c

@@ -6,7 +6,7 @@ GtkWidget *current_background, *background_fill_color, *background_border_color, *background_gradient,

*background_fill_color_over, *background_border_color_over, *background_gradient_over, *background_fill_color_press, *background_border_color_press, *background_gradient_press, *background_border_width, *background_corner_radius, *background_border_sides_top, *background_border_sides_bottom, *background_border_sides_left, - *background_border_sides_right; + *background_border_sides_right, *background_border_content_tint_weight, *background_fill_content_tint_weight; GtkWidget *create_background_combo(const char *label) {

@@ -115,7 +115,9 @@ GTK_TYPE_INT,

GTK_TYPE_BOOL, GTK_TYPE_BOOL, GTK_TYPE_BOOL, - GTK_TYPE_BOOL); + GTK_TYPE_BOOL, + GTK_TYPE_DOUBLE, + GTK_TYPE_DOUBLE); GtkWidget *table, *label, *button; int row, col;

@@ -176,6 +178,19 @@ col++;

gtk_tooltips_set_tip(tooltips, background_fill_color, _("The fill color of the current background"), NULL); row++, col = 2; + label = gtk_label_new(_("Fill tint")); + 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++; + + background_fill_content_tint_weight = gtk_spin_button_new_with_range(0, 1, 0.01); + gtk_widget_show(background_fill_content_tint_weight); + gtk_table_attach(GTK_TABLE(table), background_fill_content_tint_weight, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); + col++; + gtk_tooltips_set_tip(tooltips, background_fill_content_tint_weight, _("How much the border color should be tinted with the content color"), NULL); + + row++, col = 2; label = gtk_label_new(_("Border color")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0); gtk_widget_show(label);

@@ -190,6 +205,19 @@ col++;

gtk_tooltips_set_tip(tooltips, background_border_color, _("The border color of the current background"), NULL); row++, col = 2; + label = gtk_label_new(_("Border tint")); + 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++; + + background_border_content_tint_weight = gtk_spin_button_new_with_range(0, 1, 0.01); + gtk_widget_show(background_border_content_tint_weight); + gtk_table_attach(GTK_TABLE(table), background_border_content_tint_weight, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); + col++; + gtk_tooltips_set_tip(tooltips, background_border_content_tint_weight, _("How much the border color should be tinted with the content color"), NULL); + + row++, col = 2; label = gtk_label_new(_("Gradient")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0); gtk_widget_show(label);

@@ -366,6 +394,8 @@ g_signal_connect(G_OBJECT(background_border_sides_top), "toggled", G_CALLBACK(background_update), NULL);

g_signal_connect(G_OBJECT(background_border_sides_bottom), "toggled", G_CALLBACK(background_update), NULL); g_signal_connect(G_OBJECT(background_border_sides_left), "toggled", G_CALLBACK(background_update), NULL); g_signal_connect(G_OBJECT(background_border_sides_right), "toggled", G_CALLBACK(background_update), NULL); + g_signal_connect(G_OBJECT(background_border_content_tint_weight), "value-changed", G_CALLBACK(background_update), NULL); + g_signal_connect(G_OBJECT(background_fill_content_tint_weight), "value-changed", G_CALLBACK(background_update), NULL); change_paragraph(parent); }

@@ -750,6 +780,9 @@

r = gtk_spin_button_get_value(GTK_SPIN_BUTTON(background_corner_radius)); b = gtk_spin_button_get_value(GTK_SPIN_BUTTON(background_border_width)); + double fill_weight = gtk_spin_button_get_value(GTK_SPIN_BUTTON(background_fill_content_tint_weight)); + double border_weight = gtk_spin_button_get_value(GTK_SPIN_BUTTON(background_border_content_tint_weight)); + gboolean sideTop = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(background_border_sides_top)); gboolean sideBottom = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(background_border_sides_bottom)); gboolean sideLeft = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(background_border_sides_left));

@@ -836,6 +869,10 @@ bgColBorderSidesLeft,

sideLeft, bgColBorderSidesRight, sideRight, + bgColFillWeight, + fill_weight, + bgColBorderWeight, + border_weight, -1); background_update_image(index); }

@@ -862,6 +899,8 @@ gtk_widget_set_sensitive(background_border_sides_bottom, index > 0);

gtk_widget_set_sensitive(background_border_sides_left, index > 0); gtk_widget_set_sensitive(background_border_sides_right, index > 0); gtk_widget_set_sensitive(background_corner_radius, index > 0); + gtk_widget_set_sensitive(background_border_content_tint_weight, index > 0); + gtk_widget_set_sensitive(background_fill_content_tint_weight, index > 0); background_updates_disabled = TRUE;

@@ -874,6 +913,9 @@ gtk_tree_path_free(path);

int r; int b; + + double fill_weight; + double border_weight; gboolean sideTop; gboolean sideBottom;

@@ -938,6 +980,10 @@ bgColBorderSidesLeft,

&sideLeft, bgColBorderSidesRight, &sideRight, + bgColFillWeight, + &fill_weight, + bgColBorderWeight, + &border_weight, -1); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(background_border_sides_top), sideTop);

@@ -967,6 +1013,9 @@ gtk_combo_box_set_active(GTK_COMBO_BOX(background_gradient_press), gradient_id_press);

gtk_spin_button_set_value(GTK_SPIN_BUTTON(background_border_width), b); gtk_spin_button_set_value(GTK_SPIN_BUTTON(background_corner_radius), r); + + gtk_spin_button_set_value(GTK_SPIN_BUTTON(background_fill_content_tint_weight), fill_weight); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(background_border_content_tint_weight), border_weight); g_boxed_free(GDK_TYPE_COLOR, fillColor); g_boxed_free(GDK_TYPE_COLOR, borderColor);
M src/tint2conf/properties.hsrc/tint2conf/properties.h

@@ -203,6 +203,8 @@ bgColBorderSidesTop,

bgColBorderSidesBottom, bgColBorderSidesLeft, bgColBorderSidesRight, + bgColFillWeight, + bgColBorderWeight, bgNumCols };

@@ -211,7 +213,7 @@ extern GtkWidget *current_background, *background_fill_color, *background_border_color, *background_gradient,

*background_fill_color_over, *background_border_color_over, *background_gradient_over, *background_fill_color_press, *background_border_color_press, *background_gradient_press, *background_border_width, *background_border_sides_top, *background_border_sides_bottom, *background_border_sides_left, *background_border_sides_right, - *background_corner_radius; + *background_corner_radius, *background_border_content_tint_weight, *background_fill_content_tint_weight; // gradients enum { grColPixbuf = 0, grColId, grColText, grNumCols };
M src/tint2conf/properties_rw.csrc/tint2conf/properties_rw.c

@@ -161,6 +161,8 @@ }

int r; int b; + double fill_weight; + double border_weight; gboolean sideTop; gboolean sideBottom; gboolean sideLeft;

@@ -228,6 +230,10 @@ bgColBorderSidesLeft,

&sideLeft, bgColBorderSidesRight, &sideRight, + bgColFillWeight, + &fill_weight, + bgColBorderWeight, + &border_weight, -1); fprintf(fp, "# Background %d: %s\n", index, text ? text : ""); fprintf(fp, "rounded = %d\n", r);

@@ -244,6 +250,9 @@ strcat(sides, "L");

if (sideRight) strcat(sides, "R"); fprintf(fp, "border_sides = %s\n", sides); + + fprintf(fp, "border_content_tint_weight = %d\n", (int)(100 * border_weight)); + fprintf(fp, "fill_content_tint_weight = %d\n", (int)(100 * fill_weight)); config_write_color(fp, "background_color", *fillColor, fillOpacity); config_write_color(fp, "border_color", *borderColor, borderOpacity);

@@ -1229,6 +1238,12 @@ background_force_update();

} else if (strcmp(key, "gradient_id_pressed") == 0 || strcmp(key, "pressed_gradient_id") == 0) { int id = gradient_index_safe(atoi(value)); gtk_combo_box_set_active(GTK_COMBO_BOX(background_gradient_press), id); + background_force_update(); + } else if (strcmp(key, "border_content_tint_weight") == 0) { + gtk_spin_button_set_value(GTK_SPIN_BUTTON(background_border_content_tint_weight), atoi(value) / 100.); + background_force_update(); + } else if (strcmp(key, "fill_content_tint_weight") == 0) { + gtk_spin_button_set_value(GTK_SPIN_BUTTON(background_fill_content_tint_weight), atoi(value) / 100.); background_force_update(); }
M src/util/area.csrc/util/area.c

@@ -490,28 +490,59 @@ cairo_destroy(c);

cairo_surface_destroy(cs); } +double tint_color_channel(double a, double b, double tint_weight) +{ + double gamma = 2.2; + if (tint_weight == 0.0) + return a; + double result = sqrt((1.-tint_weight)*pow(a, gamma) + tint_weight * pow(b, gamma)); + return result; +} + +void set_cairo_source_tinted(cairo_t *c, Color *color1, Color *color2, double tint_weight) +{ + cairo_set_source_rgba(c, + tint_color_channel(color1->rgb[0], color2->rgb[0], tint_weight), + tint_color_channel(color1->rgb[1], color2->rgb[1], tint_weight), + tint_color_channel(color1->rgb[2], color2->rgb[2], tint_weight), + color1->alpha); +} + +void set_cairo_source_bg_color(Area *a, cairo_t *c) +{ + Color content_color; + if (a->_get_content_color) + a->_get_content_color(a, &content_color); + else + bzero(&content_color, sizeof(content_color)); + if (a->mouse_state == MOUSE_OVER) + set_cairo_source_tinted(c, &a->bg->fill_color_hover, &content_color, a->bg->fill_content_tint_weight); + else if (a->mouse_state == MOUSE_DOWN) + set_cairo_source_tinted(c, &a->bg->fill_color_pressed, &content_color, a->bg->fill_content_tint_weight); + else + set_cairo_source_tinted(c, &a->bg->fill_color, &content_color, a->bg->fill_content_tint_weight); +} + +void set_cairo_source_border_color(Area *a, cairo_t *c) +{ + Color content_color; + if (a->_get_content_color) + a->_get_content_color(a, &content_color); + else + bzero(&content_color, sizeof(content_color)); + if (a->mouse_state == MOUSE_OVER) + set_cairo_source_tinted(c, &a->bg->border_color_hover, &content_color, a->bg->border_content_tint_weight); + else if (a->mouse_state == MOUSE_DOWN) + set_cairo_source_tinted(c, &a->bg->border_color_pressed, &content_color, a->bg->border_content_tint_weight); + else + set_cairo_source_tinted(c, &a->bg->border.color, &content_color, a->bg->border_content_tint_weight); +} + void draw_background(Area *a, cairo_t *c) { if ((a->bg->fill_color.alpha > 0.0) || (panel_config.mouse_effects && (a->has_mouse_over_effect || a->has_mouse_press_effect))) { - if (a->mouse_state == MOUSE_OVER) - cairo_set_source_rgba(c, - a->bg->fill_color_hover.rgb[0], - a->bg->fill_color_hover.rgb[1], - a->bg->fill_color_hover.rgb[2], - a->bg->fill_color_hover.alpha); - else if (a->mouse_state == MOUSE_DOWN) - cairo_set_source_rgba(c, - a->bg->fill_color_pressed.rgb[0], - a->bg->fill_color_pressed.rgb[1], - a->bg->fill_color_pressed.rgb[2], - a->bg->fill_color_pressed.alpha); - else - cairo_set_source_rgba(c, - a->bg->fill_color.rgb[0], - a->bg->fill_color.rgb[1], - a->bg->fill_color.rgb[2], - a->bg->fill_color.alpha); + // Not sure about this draw_rect(c, left_border_width(a),

@@ -519,7 +550,7 @@ top_border_width(a),

a->width - left_right_border_width(a), a->height - top_bottom_border_width(a), a->bg->border.radius - a->bg->border.width / 1.571); - + set_cairo_source_bg_color(a, c); cairo_fill(c); } for (GList *l = a->gradient_instances_by_state[a->mouse_state]; l; l = l->next) {

@@ -540,24 +571,7 @@ if (a->bg->border.width > 0) {

cairo_set_line_width(c, a->bg->border.width); // draw border inside (x, y, width, height) - if (a->mouse_state == MOUSE_OVER) - cairo_set_source_rgba(c, - a->bg->border_color_hover.rgb[0], - a->bg->border_color_hover.rgb[1], - a->bg->border_color_hover.rgb[2], - a->bg->border_color_hover.alpha); - else if (a->mouse_state == MOUSE_DOWN) - cairo_set_source_rgba(c, - a->bg->border_color_pressed.rgb[0], - a->bg->border_color_pressed.rgb[1], - a->bg->border_color_pressed.rgb[2], - a->bg->border_color_pressed.alpha); - else - cairo_set_source_rgba(c, - a->bg->border.color.rgb[0], - a->bg->border.color.rgb[1], - a->bg->border.color.rgb[2], - a->bg->border.color.alpha); + set_cairo_source_border_color(a, c); draw_rect_on_sides(c, left_border_width(a) / 2., top_border_width(a) / 2.,
M src/util/area.hsrc/util/area.h

@@ -154,6 +154,8 @@ Color fill_color_pressed;

Color border_color_pressed; // Pointer to a GradientClass or NULL, no ownership GradientClass *gradients[MOUSE_STATE_COUNT]; + double fill_content_tint_weight; + double border_content_tint_weight; } Background; typedef enum Layout {

@@ -241,6 +243,8 @@ gboolean (*_is_under_mouse)(void *obj, int x, int y);

// Prints the geometry of the object on stderr, with left indentation of indent spaces. void (*_dump_geometry)(void *obj, int indent); + + void (*_get_content_color)(void *obj, Color *color); } Area; // Initializes the Background member to default values.
M src/util/common.csrc/util/common.c

@@ -406,12 +406,14 @@ fprintf(stderr, "tint2: executing in x-terminal-emulator: %s\n", command);

wordexp_t words; words.we_offs = 2; if (wordexp(command, &words, WRDE_DOOFFS | WRDE_SHOWERR) == 0) { - words.we_wordv[0] = (char*)"x-terminal-emulator"; - words.we_wordv[1] = (char*)"-e"; + words.we_wordv[0] = (char *)"x-terminal-emulator"; + words.we_wordv[1] = (char *)"-e"; execvp("x-terminal-emulator", words.we_wordv); } #endif - fprintf(stderr, "tint2: could not execute command in x-terminal-emulator: %s, executting in shell\n", command); + fprintf(stderr, + "tint2: could not execute command in x-terminal-emulator: %s, executting in shell\n", + command); } execlp("sh", "sh", "-c", command, NULL); fprintf(stderr, "tint2: Failed to execute %s\n", command);

@@ -1057,3 +1059,36 @@ g_string_assign(s, result->str);

g_string_free(result, TRUE); return s; } + +void get_image_mean_color(const Imlib_Image image, Color *mean_color) +{ + bzero(mean_color, sizeof(*mean_color)); + + if (!image) + return; + imlib_context_set_image(image); + imlib_image_set_has_alpha(1); + size_t size = (size_t)imlib_image_get_width() * (size_t)imlib_image_get_height(); + DATA32 *data = imlib_image_get_data_for_reading_only(); + DATA32 sum_r, sum_g, sum_b, count; + sum_r = sum_g = sum_b = count = 0; + for (size_t i = 0; i < size; i++) { + DATA32 argb, a, r, g, b; + argb = data[i]; + a = (argb >> 24) & 0xff; + r = (argb >> 16) & 0xff; + g = (argb >> 8) & 0xff; + b = (argb) & 0xff; + if (a) { + sum_r += r; + sum_g += g; + sum_b += b; + count++; + } + } + + mean_color->alpha = 1.0; + mean_color->rgb[0] = sum_r / 255.0 / count; + mean_color->rgb[1] = sum_g / 255.0 / count; + mean_color->rgb[2] = sum_b / 255.0 / count; +}
M src/util/common.hsrc/util/common.h

@@ -150,6 +150,8 @@ gint cmp_ptr(gconstpointer a, gconstpointer b);

GString *tint2_g_string_replace(GString *s, const char *from, const char *to); +void get_image_mean_color(const Imlib_Image image, Color *mean_color); + #define free_and_null(p) \ { \ free(p); \