Skip to content

Commit 968112a

Browse files
authored
Add possibility for frame opacity to include menubar/toolbar and so on
This adds the possibility to define the frame opacity but also include all colors in the window that match the frame color and make those also transparent. It even supports the possibility to define the tolerance for color difference between the frame and other parts of the window and make those or gradually more opaque or also transparent just like the frame. NOTE: tested with flat window frame so not sure how it will work with gradient frames and also only added for GLX atm, lets see if it's interesting enough to be included in the core or otherwise will just keep it for myself. It adds the following config options: # Enable frame opacity for colors that match the frame frame-opacity-for-same-colors = true; # Tolerance for similar colors (0 exact match, 1 all colors, default 0.5) frame-opacity-for-same-colors-constraint = 0.5; # Make different colors opaque by a factor of x (default 5) frame-opacity-for-same-colors-multiplier = 5; and for them to work you will have to active frame opacity for e.g. frame-opacity = 0.7; With these options you can now have blurred transparent frame + menubar + toolbar or on popup like File Open have transparent window background but list of files be opaque and so on.
1 parent 2b8a753 commit 968112a

12 files changed

+86
-7
lines changed

picom.sample.conf

+11-1
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,15 @@ inactive-opacity = 0.8;
9999
# frame-opacity = 1.0
100100
frame-opacity = 0.7;
101101

102+
# Enable frame opacity for colors that match the frame
103+
# frame-opacity-for-same-colors = true;
104+
105+
# Tolerance for similar colors (0 exact match, 1 all colors, default 0.5)
106+
# frame-opacity-for-same-colors-constraint = 0.5;
107+
108+
# Make different colors opaque by a factor of x (default 5)
109+
# frame-opacity-for-same-colors-multiplier = 5;
110+
102111
# Let inactive opacity set by -i override the '_NET_WM_WINDOW_OPACITY' values of windows.
103112
# inactive-opacity-override = true
104113
inactive-opacity-override = false;
@@ -148,7 +157,8 @@ rounded-corners-exclude = [
148157

149158

150159
# Parameters for background blurring, see the *BLUR* section for more information.
151-
# blur-method =
160+
# Possible values are: box, dual_kawase, gaussian, kernel, none
161+
# blur-method = dual_kawase
152162
# blur-size = 12
153163
#
154164
# blur-deviation = false

src/backend/gl/gl_common.c

+4
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,10 @@ gl_lower_blit_args(struct gl_data *gd, ivec2 origin, const struct backend_blit_a
582582
[UNIFORM_MASK_OFFSET_LOC] = {.type = GL_FLOAT_VEC2, .f2 = {0.0F, 0.0F}},
583583
[UNIFORM_MASK_INVERTED_LOC] = {.type = GL_INT, .i = 0},
584584
[UNIFORM_MASK_CORNER_RADIUS_LOC] = {.type = GL_FLOAT, .f = 0.0F},
585+
[UNIFORM_FRAME_OPACITY_LOC] = {.type = GL_FLOAT, .f = (float)args->frame_opacity},
586+
[UNIFORM_FRAME_OPACITY_FSC_LOC] = {.type = GL_INT, .i = args->frame_opacity_for_same_colors},
587+
[UNIFORM_FRAME_OPACITY_FSCT_LOC] = {.type = GL_FLOAT, .f = (float)args->frame_opacity_for_same_colors_tolerance},
588+
[UNIFORM_FRAME_OPACITY_FSCM_LOC] = {.type = GL_INT, .i = (int)args->frame_opacity_for_same_colors_multiplier},
585589
};
586590
// clang-format on
587591

src/backend/gl/gl_common.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,11 @@ struct gl_blur_context;
3838
#define UNIFORM_SCALE_LOC 18
3939
#define UNIFORM_PROJECTION_LOC 19
4040
#define UNIFORM_TEXSIZE_LOC 21
41-
#define NUMBER_OF_UNIFORMS (UNIFORM_TEXSIZE_LOC + 1)
41+
#define UNIFORM_FRAME_OPACITY_LOC 22
42+
#define UNIFORM_FRAME_OPACITY_FSC_LOC 23
43+
#define UNIFORM_FRAME_OPACITY_FSCT_LOC 24
44+
#define UNIFORM_FRAME_OPACITY_FSCM_LOC 25
45+
#define NUMBER_OF_UNIFORMS (UNIFORM_FRAME_OPACITY_FSCM_LOC + 1)
4246

4347
struct gl_shader {
4448
GLuint prog;

src/backend/gl/shaders.c

+23-2
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,14 @@ const char blit_shader_glsl[] = GLSL(330,
128128
uniform float max_brightness;
129129
layout(location = UNIFORM_TIME_LOC)
130130
uniform float time;
131+
layout(location = UNIFORM_FRAME_OPACITY_LOC)
132+
uniform float frame_opacity;
133+
layout(location = UNIFORM_FRAME_OPACITY_FSC_LOC)
134+
uniform bool frame_opacity_fsc;
135+
layout(location = UNIFORM_FRAME_OPACITY_FSCT_LOC)
136+
uniform float frame_opacity_fsct;
137+
layout(location = UNIFORM_FRAME_OPACITY_FSCM_LOC)
138+
uniform int frame_opacity_fscm;
131139
// Signed distance field for rectangle center at (0, 0), with size of
132140
// half_size * 2
133141
float rectangle_sdf(vec2 point, vec2 half_size) {
@@ -136,13 +144,26 @@ const char blit_shader_glsl[] = GLSL(330,
136144
}
137145

138146
vec4 default_post_processing(vec4 c) {
147+
float additional_opacity = 1;
148+
if (frame_opacity_fsc && frame_opacity > 0 && frame_opacity < 1) {
149+
vec4 frame_color = texture(tex, vec2(0.0, 0.01));
150+
float color_diff = max(max(c.r - frame_color.r, c.g - frame_color.g), c.b - frame_color.b);
151+
if (color_diff < 0)
152+
color_diff *= -1;
153+
if (color_diff <= frame_opacity_fsct) {
154+
additional_opacity = frame_opacity * (1 + color_diff * frame_opacity_fscm);
155+
156+
if (additional_opacity > 1)
157+
additional_opacity = 1;
158+
}
159+
}
139160
vec4 border_color = texture(tex, vec2(0.0, 0.5));
140161
if (invert_color) {
141162
c = vec4(c.aaa - c.rgb, c.a);
142163
border_color = vec4(border_color.aaa - border_color.rgb, border_color.a);
143164
}
144-
c = vec4(c.rgb * (1.0 - dim), c.a) * opacity;
145-
border_color = vec4(border_color.rgb * (1.0 - dim), border_color.a) * opacity;
165+
c = vec4(c.rgb * (1.0 - dim), c.a) * opacity * additional_opacity;
166+
border_color = vec4(border_color.rgb * (1.0 - dim), border_color.a) * opacity * additional_opacity;
146167

147168
vec3 rgb_brightness = texelFetch(brightness, ivec2(0, 0), 0).rgb;
148169
// Ref: https://en.wikipedia.org/wiki/Relative_luminance

src/config.c

+3
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,9 @@ bool parse_config(options_t *opt, const char *config_file) {
686686
.inactive_opacity_override = false,
687687
.active_opacity = 1.0,
688688
.frame_opacity = 1.0,
689+
.frame_opacity_for_same_colors = false,
690+
.frame_opacity_for_same_colors_tolerance = 0.5,
691+
.frame_opacity_for_same_colors_multiplier = 5,
689692
.detect_client_opacity = false,
690693

691694
.blur_method = BLUR_METHOD_NONE,

src/config.h

+6
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,12 @@ typedef struct options {
268268
/// Frame opacity. Relative to window opacity, also affects shadow
269269
/// opacity.
270270
double frame_opacity;
271+
// Enable frame opacity for colors that match the frame
272+
bool frame_opacity_for_same_colors;
273+
// Tolerance for similar colors (0 exact match, 1 all colors, default 0.5)
274+
double frame_opacity_for_same_colors_tolerance;
275+
// Make different colors opaque by a factor of x (default 5)
276+
int frame_opacity_for_same_colors_multiplier;
271277
/// Whether to detect _NET_WM_WINDOW_OPACITY on client windows. Used on window
272278
/// managers that don't pass _NET_WM_WINDOW_OPACITY to frame windows.
273279
bool detect_client_opacity;

src/config_libconfig.c

+6
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,12 @@ bool parse_config_libconfig(options_t *opt, const char *config_file) {
700700

701701
// -e (frame_opacity)
702702
config_lookup_float(&cfg, "frame-opacity", &opt->frame_opacity);
703+
// --frame-opacity-for-same-colors
704+
lcfg_lookup_bool(&cfg, "frame-opacity-for-same-colors", &opt->frame_opacity_for_same_colors);
705+
// --frame-opacity-for-same-colors-tolerance
706+
config_lookup_float(&cfg, "frame-opacity-for-same-colors-tolerance", &opt->frame_opacity_for_same_colors_tolerance);
707+
// --frame-opacity-for-same-colors-multiplier
708+
config_lookup_int(&cfg, "frame-opacity-for-same-colors-multiplier", &opt->frame_opacity_for_same_colors_multiplier);
703709
// -c (shadow_enable)
704710
lcfg_lookup_bool(&cfg, "shadow", &opt->shadow_enable);
705711
// -m (menu_opacity)

src/options.c

+3
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,9 @@ static const struct picom_option picom_options[] = {
413413
['D'] = {"fade-delta" , INTEGER(fade_delta, 1, INT_MAX) , "The time between steps in a fade in milliseconds. (default 10)"},
414414
['i'] = {"inactive-opacity" , FLOAT(inactive_opacity, 0, 1) , "Opacity of inactive windows. (0.0 - 1.0)"},
415415
['e'] = {"frame-opacity" , FLOAT(frame_opacity, 0, 1) , "Opacity of window titlebars and borders. (0.0 - 1.0)"},
416+
[342] = {"frame-opacity-for-same-colors", ENABLE(frame_opacity_for_same_colors) , "Enable frame opacity for colors that match the frame"},
417+
[343] = {"frame-opacity-for-same-colors-tolerance", FLOAT(frame_opacity_for_same_colors_tolerance, 0, 1), "Tolerance for similar colors (0 exact match, 1 all colors, default 0.5)"},
418+
[344] = {"frame-opacity-for-same-colors-multiplier", INTEGER(frame_opacity_for_same_colors_multiplier, 0, INT_MAX), "Make different colors opaque by a factor of x (default 5)"},
416419
[257] = {"shadow-red" , FLOAT(shadow_red, 0, 1) , "Red color value of shadow (0.0 - 1.0, defaults to 0)."},
417420
[258] = {"shadow-green" , FLOAT(shadow_green, 0, 1) , "Green color value of shadow (0.0 - 1.0, defaults to 0)."},
418421
[259] = {"shadow-blue" , FLOAT(shadow_blue, 0, 1) , "Blue color value of shadow (0.0 - 1.0, defaults to 0)."},

src/picom.c

+3
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,9 @@ static bool paint_preprocess(session_t *ps, bool *animation, struct managed_win
866866

867867
if (win_has_frame(w)) {
868868
w->frame_opacity = ps->o.frame_opacity;
869+
w->frame_opacity_for_same_colors = ps->o.frame_opacity_for_same_colors;
870+
w->frame_opacity_for_same_colors_tolerance = ps->o.frame_opacity_for_same_colors_tolerance;
871+
w->frame_opacity_for_same_colors_multiplier = ps->o.frame_opacity_for_same_colors_multiplier;
869872
} else {
870873
w->frame_opacity = 1.0;
871874
}

src/renderer/command_builder.c

+7-3
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ commands_for_window_body(struct layer *layer, struct backend_command *cmd,
3636
pixman_region32_copy(&cmd->target_mask, &w->bounding_shape);
3737
pixman_region32_translate(&cmd->target_mask, layer->window.origin.x,
3838
layer->window.origin.y);
39-
if (w->frame_opacity < 1) {
39+
if (w->frame_opacity < 1 && !w->frame_opacity_for_same_colors) {
4040
pixman_region32_subtract(&cmd->target_mask, &cmd->target_mask, frame_region);
4141
}
4242
pixman_region32_init(&cmd->opaque_region);
@@ -62,6 +62,10 @@ commands_for_window_body(struct layer *layer, struct backend_command *cmd,
6262
.target_mask = &cmd->target_mask,
6363
.corner_radius = w->corner_radius,
6464
.opacity = layer->opacity,
65+
.frame_opacity = w->frame_opacity,
66+
.frame_opacity_for_same_colors = w->frame_opacity_for_same_colors,
67+
.frame_opacity_for_same_colors_tolerance = w->frame_opacity_for_same_colors_tolerance,
68+
.frame_opacity_for_same_colors_multiplier = w->frame_opacity_for_same_colors_multiplier,
6569
.dim = dim,
6670
.scale = layer->scale,
6771
.effective_size = layer->window.size,
@@ -70,7 +74,7 @@ commands_for_window_body(struct layer *layer, struct backend_command *cmd,
7074
.source_mask = NULL,
7175
.max_brightness = max_brightness};
7276

73-
if (w->frame_opacity == 1 || w->frame_opacity == 0) {
77+
if (w->frame_opacity == 1 || w->frame_opacity == 0 || w->frame_opacity_for_same_colors) {
7478
return 1;
7579
}
7680
cmd -= 1;
@@ -376,7 +380,7 @@ void command_builder_build(struct command_builder *cb, struct layout *layout, bo
376380
if (layer->win->shadow) {
377381
ncmds += 1;
378382
}
379-
if (layer->win->frame_opacity < 1 && layer->win->frame_opacity > 0) {
383+
if (layer->win->frame_opacity < 1 && layer->win->frame_opacity > 0 && !layer->win->frame_opacity_for_same_colors) {
380384
// Needs to draw the frame separately
381385
ncmds += 1;
382386
}

src/win.c

+9
Original file line numberDiff line numberDiff line change
@@ -803,13 +803,19 @@ winmode_t win_calc_mode_raw(const struct managed_win *w) {
803803
if (win_has_frame(w)) {
804804
// The client window doesn't have alpha, but we have a WM
805805
// frame window, which has alpha.
806+
if (w->frame_opacity_for_same_colors)
807+
return WMODE_TRANS;
808+
806809
return WMODE_FRAME_TRANS;
807810
}
808811
// Although the WM window has alpha, the frame window has 0 size,
809812
// so consider the window solid
810813
}
811814

812815
if (w->frame_opacity != 1.0 && win_has_frame(w)) {
816+
if (w->frame_opacity_for_same_colors)
817+
return WMODE_TRANS;
818+
813819
return WMODE_FRAME_TRANS;
814820
}
815821

@@ -1503,6 +1509,9 @@ struct win *attr_ret_nonnull maybe_allocate_managed_win(session_t *ps, struct wi
15031509
// The following ones are updated during paint or paint preprocess
15041510
.to_paint = false,
15051511
.frame_opacity = 1.0,
1512+
.frame_opacity_for_same_colors = false,
1513+
.frame_opacity_for_same_colors_tolerance = 0.5,
1514+
.frame_opacity_for_same_colors_multiplier = 5,
15061515
.dim = false,
15071516
.invert_color = false,
15081517
.blur_background = false,

src/win.h

+6
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,12 @@ struct managed_win {
245245
// Frame-opacity-related members
246246
/// Current window frame opacity. Affected by window opacity.
247247
double frame_opacity;
248+
// Makes colors matching the frame transparent too
249+
bool frame_opacity_for_same_colors;
250+
// Tolerance for similar colors (0 exact match, 1 all colors, default 0.5)
251+
double frame_opacity_for_same_colors_tolerance;
252+
// Make different colors opaque by a factor of x (default 5)
253+
int frame_opacity_for_same_colors_multiplier;
248254
/// Frame extents. Acquired from _NET_FRAME_EXTENTS.
249255
margin_t frame_extents;
250256

0 commit comments

Comments
 (0)