diff --git a/src/config.c b/src/config.c index 15dfffb..8c17b4a 100644 --- a/src/config.c +++ b/src/config.c @@ -72,6 +72,8 @@ char *snapshot_path; // detect if it's an old config file (==1) static gboolean new_config_file; +static gboolean read_bg_color2; +static gboolean read_bg_gradient; static gboolean read_bg_color_hover; static gboolean read_border_color_hover; static gboolean read_bg_color_press; @@ -230,6 +232,10 @@ void add_entry(char *key, char *value) // 'rounded' is the first parameter => alloc a new background if (backgrounds->len > 0) { Background *bg = &g_array_index(backgrounds, Background, backgrounds->len - 1); + if (!read_bg_color2) + memcpy(&bg->fill_color2, &bg->fill_color, sizeof(Color)); + if (!read_bg_gradient) + bg->gradient = 0; if (!read_bg_color_hover) memcpy(&bg->fill_color_hover, &bg->fill_color, sizeof(Color)); if (!read_border_color_hover) @@ -243,6 +249,8 @@ void add_entry(char *key, char *value) init_background(&bg); bg.border.radius = atoi(value); g_array_append_val(backgrounds, bg); + read_bg_color2 = 0; + read_bg_gradient = 0; read_bg_color_hover = 0; read_border_color_hover = 0; read_bg_color_press = 0; @@ -270,6 +278,19 @@ void add_entry(char *key, char *value) bg->fill_color.alpha = (atoi(value2) / 100.0); else bg->fill_color.alpha = 0.5; + } else if (strcmp(key, "background_color2") == 0) { + Background* bg = &g_array_index(backgrounds, Background, backgrounds->len-1); + extract_values(value, &value1, &value2, &value3); + get_color (value1, bg->fill_color2.rgb); + if (value2) + bg->fill_color2.alpha = (atoi (value2) / 100.0); + else + bg->fill_color2.alpha = 0.5; + read_bg_color2 = 1; + } else if (strcmp(key, "gradient") == 0) { + Background *bg = &g_array_index(backgrounds, Background, backgrounds->len-1); + bg->gradient = atoi(value); + read_bg_gradient = 1; } else if (strcmp(key, "border_color") == 0) { Background *bg = &g_array_index(backgrounds, Background, backgrounds->len - 1); extract_values(value, &value1, &value2, &value3); @@ -1130,6 +1151,10 @@ gboolean config_read_file(const char *path) if (backgrounds->len > 0) { Background *bg = &g_array_index(backgrounds, Background, backgrounds->len - 1); + if (!read_bg_color2) + memcpy(&bg->fill_color2, &bg->fill_color, sizeof(Color)); + if (!read_bg_gradient) + bg->gradient = 0; if (!read_bg_color_hover) memcpy(&bg->fill_color_hover, &bg->fill_color, sizeof(Color)); if (!read_border_color_hover) diff --git a/src/tint2conf/properties.c b/src/tint2conf/properties.c index c922cb7..8f4ec68 100644 --- a/src/tint2conf/properties.c +++ b/src/tint2conf/properties.c @@ -144,6 +144,8 @@ GtkWidget *launcher_icon_theme_override; GtkListStore *backgrounds; GtkWidget *current_background, *background_fill_color, + *background_fill_color2, + *background_gradient, *background_border_color, *background_fill_color_over, *background_border_color_over, @@ -502,6 +504,9 @@ void create_background(GtkWidget *parent) GTK_TYPE_INT, GDK_TYPE_COLOR, GTK_TYPE_INT, + GTK_TYPE_BOOL, + GDK_TYPE_COLOR, + GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_STRING, @@ -576,6 +581,26 @@ void create_background(GtkWidget *parent) col++; gtk_tooltips_set_tip(tooltips, background_fill_color, _("The fill color of the current background"), NULL); + row++, col = 2; + label = gtk_label_new(_("Secondary fill color")); + 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_color2 = gtk_color_button_new(); + gtk_color_button_set_use_alpha(GTK_COLOR_BUTTON(background_fill_color2), TRUE); + gtk_widget_show(background_fill_color2); + gtk_table_attach(GTK_TABLE(table), background_fill_color2, col, col+1, row, row+1, GTK_FILL, 0, 0, 0); + + col++; + background_gradient = gtk_check_button_new_with_label(_("Enable gradient")); + gtk_widget_show(background_gradient); + gtk_table_attach(GTK_TABLE(table), background_gradient, col, col+1, row, row+1, GTK_FILL, 0, 0, 0); + + col++; + gtk_tooltips_set_tip(tooltips, background_fill_color2, _("Color to fade into when using gradient background."), NULL); + row++, col = 2; label = gtk_label_new(_("Border color")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0); @@ -702,6 +727,8 @@ void create_background(GtkWidget *parent) g_signal_connect(G_OBJECT(current_background), "changed", G_CALLBACK(current_background_changed), NULL); g_signal_connect(G_OBJECT(background_fill_color), "color-set", G_CALLBACK(background_update), NULL); + g_signal_connect(G_OBJECT(background_fill_color2), "color-set", G_CALLBACK(background_update), NULL); + g_signal_connect(G_OBJECT(background_gradient), "toggled", G_CALLBACK(background_update), NULL); g_signal_connect(G_OBJECT(background_border_color), "color-set", G_CALLBACK(background_update), NULL); g_signal_connect(G_OBJECT(background_fill_color_over), "color-set", G_CALLBACK(background_update), NULL); g_signal_connect(G_OBJECT(background_border_color_over), "color-set", G_CALLBACK(background_update), NULL); @@ -754,6 +781,10 @@ void background_create_new() GdkColor fillColor; cairoColor2GdkColor(0, 0, 0, &fillColor); int fillOpacity = 0; + GdkColor fillColor2; + cairoColor2GdkColor(0, 0, 0, &fillColor2); + int fillOpacity2 = 0; + gboolean gradient = FALSE; GdkColor borderColor; cairoColor2GdkColor(0, 0, 0, &borderColor); int borderOpacity = 0; @@ -780,6 +811,9 @@ void background_create_new() bgColPixbuf, NULL, bgColFillColor, &fillColor, bgColFillOpacity, fillOpacity, + bgColFillColor2, &fillColor2, + bgColFillOpacity2, fillOpacity2, + bgColGradient, gradient, bgColBorderColor, &borderColor, bgColBorderOpacity, borderOpacity, bgColBorderWidth, b, @@ -827,6 +861,9 @@ void background_duplicate(GtkWidget *widget, gpointer data) gboolean sideRight; GdkColor *fillColor; int fillOpacity; + GdkColor *fillColor2; + int fillOpacity2; + gboolean gradient; GdkColor *borderColor; int borderOpacity; GdkColor *fillColorOver; @@ -841,6 +878,9 @@ void background_duplicate(GtkWidget *widget, gpointer data) gtk_tree_model_get(GTK_TREE_MODEL(backgrounds), &iter, bgColFillColor, &fillColor, bgColFillOpacity, &fillOpacity, + bgColFillColor2, &fillColor2, + bgColFillOpacity2, &fillOpacity2, + bgColGradient, &gradient, bgColBorderColor, &borderColor, bgColBorderOpacity, &borderOpacity, bgColFillColorOver, &fillColorOver, @@ -864,6 +904,9 @@ void background_duplicate(GtkWidget *widget, gpointer data) bgColPixbuf, NULL, bgColFillColor, fillColor, bgColFillOpacity, fillOpacity, + bgColFillColor2, fillColor2, + bgColFillOpacity2, fillOpacity2, + bgColGradient, gradient, bgColBorderColor, borderColor, bgColBorderOpacity, borderOpacity, bgColText, "", @@ -883,6 +926,7 @@ void background_duplicate(GtkWidget *widget, gpointer data) bgColBorderSidesRight, sideRight, -1); g_boxed_free(GDK_TYPE_COLOR, fillColor); + g_boxed_free(GDK_TYPE_COLOR, fillColor2); g_boxed_free(GDK_TYPE_COLOR, borderColor); g_boxed_free(GDK_TYPE_COLOR, fillColorOver); g_boxed_free(GDK_TYPE_COLOR, borderColorOver); @@ -931,12 +975,18 @@ void background_update_image(int index) GdkPixbuf *pixbuf; GdkColor *fillColor; int fillOpacity = 50; + GdkColor *fillColor2; + int fillOpacity2 = 50; + gboolean gradient = FALSE; GdkColor *borderColor; int borderOpacity = 100; gtk_tree_model_get(GTK_TREE_MODEL(backgrounds), &iter, bgColFillColor, &fillColor, bgColFillOpacity, &fillOpacity, + bgColFillColor2, &fillColor2, + bgColFillOpacity2, &fillOpacity2, + bgColGradient, &gradient, bgColBorderColor, &borderColor, bgColBorderOpacity, &borderOpacity, bgColBorderWidth, &b, @@ -946,11 +996,17 @@ void background_update_image(int index) double bg_r, bg_g, bg_b, bg_a; gdkColor2CairoColor(*fillColor, &bg_r, &bg_g, &bg_b); bg_a = fillOpacity / 100.0; + + double bg_r2, bg_g2, bg_b2, bg_a2; + gdkColor2CairoColor(*fillColor2, &bg_r2, &bg_g2, &bg_b2); + bg_a2 = fillOpacity2 / 100.0; + double b_r, b_g, b_b, b_a; gdkColor2CairoColor(*borderColor, &b_r, &b_g, &b_b); b_a = borderOpacity / 100.0; g_boxed_free(GDK_TYPE_COLOR, fillColor); + g_boxed_free(GDK_TYPE_COLOR, fillColor2); g_boxed_free(GDK_TYPE_COLOR, borderColor); GdkPixmap *pixmap = gdk_pixmap_new(NULL, w, h, 24); @@ -971,8 +1027,19 @@ void background_update_image(int index) cairo_arc(cr, r + b, r + b, r, 180 * degrees, 270 * degrees); cairo_close_path(cr); - cairo_set_source_rgba(cr, bg_r, bg_g, bg_b, bg_a); - cairo_fill_preserve(cr); + if (gradient) { + cairo_pattern_t *gpat; + gpat = cairo_pattern_create_linear(0, 0, 0, h - b); + cairo_pattern_add_color_stop_rgba(gpat, 0.1, bg_r, bg_g, bg_b, bg_a); + cairo_pattern_add_color_stop_rgba(gpat, 0.9, bg_r2, bg_g2, bg_b2, bg_a2); + cairo_set_source(cr, gpat); + cairo_fill_preserve(cr); + cairo_pattern_destroy(gpat); + } else { + cairo_set_source_rgba(cr, bg_r, bg_g, bg_b, bg_a); + cairo_fill_preserve(cr); + } + cairo_set_source_rgba(cr, b_r, b_g, b_b, b_a); cairo_set_line_width(cr, b); cairo_stroke(cr); @@ -1024,10 +1091,16 @@ void background_update(GtkWidget *widget, gpointer data) GdkColor fillColor; int fillOpacity; + GdkColor fillColor2; + int fillOpacity2; + gboolean gradient; GdkColor borderColor; int borderOpacity; gtk_color_button_get_color(GTK_COLOR_BUTTON(background_fill_color), &fillColor); fillOpacity = MIN(100, 0.5 + gtk_color_button_get_alpha(GTK_COLOR_BUTTON(background_fill_color)) * 100.0 / 0xffff); + gtk_color_button_get_color(GTK_COLOR_BUTTON(background_fill_color2), &fillColor2); + fillOpacity2 = MIN(100, 0.5 + gtk_color_button_get_alpha(GTK_COLOR_BUTTON(background_fill_color2)) * 100.0 / 0xffff); + gradient = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(background_gradient)); gtk_color_button_get_color(GTK_COLOR_BUTTON(background_border_color), &borderColor); borderOpacity = MIN(100, 0.5 + gtk_color_button_get_alpha(GTK_COLOR_BUTTON(background_border_color)) * 100.0 / 0xffff); @@ -1053,6 +1126,9 @@ void background_update(GtkWidget *widget, gpointer data) bgColPixbuf, NULL, bgColFillColor, &fillColor, bgColFillOpacity, fillOpacity, + bgColFillColor2, &fillColor2, + bgColFillOpacity2, fillOpacity2, + bgColGradient, gradient, bgColBorderColor, &borderColor, bgColBorderOpacity, borderOpacity, bgColFillColorOver, &fillColorOver, @@ -1098,6 +1174,9 @@ void current_background_changed(GtkWidget *widget, gpointer data) GdkColor *fillColor; int fillOpacity; + GdkColor *fillColor2; + int fillOpacity2; + gboolean gradient; GdkColor *borderColor; int borderOpacity; GdkColor *fillColorOver; @@ -1113,6 +1192,9 @@ void current_background_changed(GtkWidget *widget, gpointer data) gtk_tree_model_get(GTK_TREE_MODEL(backgrounds), &iter, bgColFillColor, &fillColor, bgColFillOpacity, &fillOpacity, + bgColFillColor2, &fillColor2, + bgColFillOpacity2, &fillOpacity2, + bgColGradient, &gradient, bgColBorderColor, &borderColor, bgColBorderOpacity, &borderOpacity, bgColFillColorOver, &fillColorOver, @@ -1138,6 +1220,12 @@ void current_background_changed(GtkWidget *widget, gpointer data) gtk_color_button_set_color(GTK_COLOR_BUTTON(background_fill_color), fillColor); gtk_color_button_set_alpha(GTK_COLOR_BUTTON(background_fill_color), (fillOpacity*0xffff)/100); + + gtk_color_button_set_color(GTK_COLOR_BUTTON(background_fill_color2), fillColor2); + gtk_color_button_set_alpha(GTK_COLOR_BUTTON(background_fill_color2), (fillOpacity2*0xffff)/100); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(background_gradient), gradient); + gtk_color_button_set_color(GTK_COLOR_BUTTON(background_border_color), borderColor); gtk_color_button_set_alpha(GTK_COLOR_BUTTON(background_border_color), (borderOpacity*0xffff)/100); @@ -1155,6 +1243,7 @@ void current_background_changed(GtkWidget *widget, gpointer data) gtk_spin_button_set_value(GTK_SPIN_BUTTON(background_corner_radius), r); g_boxed_free(GDK_TYPE_COLOR, fillColor); + g_boxed_free(GDK_TYPE_COLOR, fillColor2); g_boxed_free(GDK_TYPE_COLOR, borderColor); g_boxed_free(GDK_TYPE_COLOR, fillColorOver); g_boxed_free(GDK_TYPE_COLOR, borderColorOver); diff --git a/src/tint2conf/properties.h b/src/tint2conf/properties.h index de3faa5..ad0286b 100644 --- a/src/tint2conf/properties.h +++ b/src/tint2conf/properties.h @@ -179,6 +179,9 @@ enum { bgColPixbuf = 0, bgColFillColor, bgColFillOpacity, + bgColFillColor2, + bgColFillOpacity2, + bgColGradient, bgColBorderColor, bgColBorderOpacity, bgColBorderWidth, @@ -202,6 +205,8 @@ enum { extern GtkListStore *backgrounds; extern GtkWidget *current_background, *background_fill_color, + *background_fill_color2, + *background_gradient, *background_border_color, *background_fill_color_over, *background_border_color_over, diff --git a/src/tint2conf/properties_rw.c b/src/tint2conf/properties_rw.c index d6748b7..f163911 100644 --- a/src/tint2conf/properties_rw.c +++ b/src/tint2conf/properties_rw.c @@ -23,6 +23,7 @@ int no_items_systray_enabled; int no_items_battery_enabled; static int num_bg; +static int read_bg_color2; static int read_bg_color_hover; static int read_border_color_hover; static int read_bg_color_press; @@ -121,6 +122,9 @@ void config_write_backgrounds(FILE *fp) gboolean sideRight; GdkColor *fillColor; int fillOpacity; + GdkColor *fillColor2; + int fillOpacity2; + gboolean gradient; GdkColor *borderColor; int borderOpacity; GdkColor *fillColorOver; @@ -136,6 +140,9 @@ void config_write_backgrounds(FILE *fp) gtk_tree_model_get(GTK_TREE_MODEL(backgrounds), &iter, bgColFillColor, &fillColor, bgColFillOpacity, &fillOpacity, + bgColFillColor2, &fillColor2, + bgColFillOpacity2, &fillOpacity2, + bgColGradient, &gradient, bgColBorderColor, &borderColor, bgColBorderOpacity, &borderOpacity, bgColFillColorOver, &fillColorOver, @@ -170,7 +177,12 @@ void config_write_backgrounds(FILE *fp) strcat(sides, "R"); fprintf(fp, "border_sides = %s\n", sides); + // This is a workaround. For some reason, there was a problem while storing fillOpacity2 + //fillOpacity2 = MIN(100, 0.5 + gtk_color_button_get_alpha(GTK_COLOR_BUTTON(background_fill_color2)) * 100.0 / 0xffff); + config_write_color(fp, "background_color", *fillColor, fillOpacity); + config_write_color(fp, "background_color2", *fillColor2, fillOpacity2); + fprintf(fp, "gradient = %d\n", gradient); config_write_color(fp, "border_color", *borderColor, borderOpacity); config_write_color(fp, "background_color_hover", *fillColorOver, fillOpacityOver); config_write_color(fp, "border_color_hover", *borderColorOver, borderOpacityOver); @@ -850,6 +862,14 @@ gboolean config_is_manual(const char *path) void finalize_bg() { if (num_bg > 0) { + if (!read_bg_color2) { + GdkColor fillColor; + gtk_color_button_get_color(GTK_COLOR_BUTTON(background_fill_color),&fillColor); + gtk_color_button_set_color(GTK_COLOR_BUTTON(background_fill_color2), &fillColor); + int fillOpacity = gtk_color_button_get_alpha(GTK_COLOR_BUTTON(background_fill_color2)); + gtk_color_button_set_alpha(GTK_COLOR_BUTTON(background_fill_color2), fillOpacity); + background_force_update(); + } if (!read_bg_color_hover) { GdkColor fillColor; gtk_color_button_get_color(GTK_COLOR_BUTTON(background_fill_color), &fillColor); @@ -895,6 +915,7 @@ void add_entry(char *key, char *value) finalize_bg(); background_create_new(); num_bg++; + read_bg_color2 = 0; read_bg_color_hover = 0; read_border_color_hover = 0; read_bg_color_press = 0; @@ -915,6 +936,19 @@ void add_entry(char *key, char *value) gtk_color_button_set_alpha(GTK_COLOR_BUTTON(background_fill_color), (alpha*65535)/100); background_force_update(); } + else if (strcmp(key, "background_color2") == 0) { + extract_values(value, &value1, &value2, &value3); + GdkColor col; + hex2gdk(value1, &col); + gtk_color_button_set_color(GTK_COLOR_BUTTON(background_fill_color2), &col); + int alpha = value2 ? atoi(value2) : 50; + gtk_color_button_set_alpha(GTK_COLOR_BUTTON(background_fill_color2), (alpha*65535)/100); + background_force_update(); + read_bg_color2 = 1; + } + else if (strcmp(key, "gradient") == 0 ) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(background_gradient), atoi(value)); + } else if (strcmp(key, "border_color") == 0) { extract_values(value, &value1, &value2, &value3); GdkColor col; diff --git a/src/util/area.c b/src/util/area.c index cf7e711..dd81d77 100644 --- a/src/util/area.c +++ b/src/util/area.c @@ -438,9 +438,18 @@ void draw(Area *a) 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) + if ((a->bg->fill_color.alpha > 0.0) || + (panel_config.mouse_effects && (a->has_mouse_over_effect || a->has_mouse_press_effect)) || + (area_has_gradient_fill(a))) { + + cairo_pattern_t *cairo_gradient_pattern; + + if (area_has_gradient_fill(a)) { + cairo_gradient_pattern = cairo_pattern_create_linear(0.0, 0.0, 0.0, a->height - top_bottom_border_width(a)); + cairo_pattern_add_color_stop_rgba(cairo_gradient_pattern, 0.1, a->bg->fill_color.rgb[0], a->bg->fill_color.rgb[1], a->bg->fill_color.rgb[2], a->bg->fill_color.alpha); + cairo_pattern_add_color_stop_rgba(cairo_gradient_pattern, 0.9, a->bg->fill_color2.rgb[0], a->bg->fill_color2.rgb[1], a->bg->fill_color2.rgb[2], a->bg->fill_color2.alpha); + cairo_set_source(c, cairo_gradient_pattern); + } else 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], @@ -467,6 +476,8 @@ void draw_background(Area *a, cairo_t *c) a->bg->border.radius - a->bg->border.width / 1.571); cairo_fill(c); + if (area_has_gradient_fill(a)) + cairo_pattern_destroy(cairo_gradient_pattern); } if (a->bg->border.width > 0) { @@ -814,3 +825,18 @@ void area_dump_geometry(Area *area, int indent) area_dump_geometry((Area *)l->data, indent); } } + +gboolean area_has_gradient_fill(Area *area) +{ + if (!area->bg->gradient) + return FALSE; + else if ((area->bg->fill_color.alpha <= 0.0 ) && (area->bg->fill_color2.alpha <= 0.0)) + return FALSE; + else if ((area->bg->fill_color.rgb[0] == area->bg->fill_color2.rgb[0]) && + (area->bg->fill_color.rgb[1] == area->bg->fill_color2.rgb[1]) && + (area->bg->fill_color.rgb[2] == area->bg->fill_color2.rgb[2]) && + (area->bg->fill_color.alpha == area->bg->fill_color2.alpha)) + return FALSE; + else return TRUE; + +} diff --git a/src/util/area.h b/src/util/area.h index 75b4528..76e66b7 100644 --- a/src/util/area.h +++ b/src/util/area.h @@ -147,6 +147,8 @@ typedef struct Border { typedef struct Background { // Normal state Color fill_color; + Color fill_color2; + gboolean gradient; Border border; // On mouse hover Color fill_color_hover; @@ -314,4 +316,6 @@ void area_dump_geometry(Area *area, int indent); void mouse_over(Area *area, int pressed); void mouse_out(); +gboolean area_has_gradient_fill(Area *area); + #endif