Skip to content

Commit

Permalink
Add possibility for frame opacity to include menubar/toolbar and so on
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
pijulius authored May 26, 2024
1 parent 2b8a753 commit 968112a
Show file tree
Hide file tree
Showing 12 changed files with 86 additions and 7 deletions.
12 changes: 11 additions & 1 deletion picom.sample.conf
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@ inactive-opacity = 0.8;
# frame-opacity = 1.0
frame-opacity = 0.7;

# 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;

# Let inactive opacity set by -i override the '_NET_WM_WINDOW_OPACITY' values of windows.
# inactive-opacity-override = true
inactive-opacity-override = false;
Expand Down Expand Up @@ -148,7 +157,8 @@ rounded-corners-exclude = [


# Parameters for background blurring, see the *BLUR* section for more information.
# blur-method =
# Possible values are: box, dual_kawase, gaussian, kernel, none
# blur-method = dual_kawase
# blur-size = 12
#
# blur-deviation = false
Expand Down
4 changes: 4 additions & 0 deletions src/backend/gl/gl_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,10 @@ gl_lower_blit_args(struct gl_data *gd, ivec2 origin, const struct backend_blit_a
[UNIFORM_MASK_OFFSET_LOC] = {.type = GL_FLOAT_VEC2, .f2 = {0.0F, 0.0F}},
[UNIFORM_MASK_INVERTED_LOC] = {.type = GL_INT, .i = 0},
[UNIFORM_MASK_CORNER_RADIUS_LOC] = {.type = GL_FLOAT, .f = 0.0F},
[UNIFORM_FRAME_OPACITY_LOC] = {.type = GL_FLOAT, .f = (float)args->frame_opacity},
[UNIFORM_FRAME_OPACITY_FSC_LOC] = {.type = GL_INT, .i = args->frame_opacity_for_same_colors},
[UNIFORM_FRAME_OPACITY_FSCT_LOC] = {.type = GL_FLOAT, .f = (float)args->frame_opacity_for_same_colors_tolerance},
[UNIFORM_FRAME_OPACITY_FSCM_LOC] = {.type = GL_INT, .i = (int)args->frame_opacity_for_same_colors_multiplier},
};
// clang-format on

Expand Down
6 changes: 5 additions & 1 deletion src/backend/gl/gl_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ struct gl_blur_context;
#define UNIFORM_SCALE_LOC 18
#define UNIFORM_PROJECTION_LOC 19
#define UNIFORM_TEXSIZE_LOC 21
#define NUMBER_OF_UNIFORMS (UNIFORM_TEXSIZE_LOC + 1)
#define UNIFORM_FRAME_OPACITY_LOC 22
#define UNIFORM_FRAME_OPACITY_FSC_LOC 23
#define UNIFORM_FRAME_OPACITY_FSCT_LOC 24
#define UNIFORM_FRAME_OPACITY_FSCM_LOC 25
#define NUMBER_OF_UNIFORMS (UNIFORM_FRAME_OPACITY_FSCM_LOC + 1)

struct gl_shader {
GLuint prog;
Expand Down
25 changes: 23 additions & 2 deletions src/backend/gl/shaders.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,14 @@ const char blit_shader_glsl[] = GLSL(330,
uniform float max_brightness;
layout(location = UNIFORM_TIME_LOC)
uniform float time;
layout(location = UNIFORM_FRAME_OPACITY_LOC)
uniform float frame_opacity;
layout(location = UNIFORM_FRAME_OPACITY_FSC_LOC)
uniform bool frame_opacity_fsc;
layout(location = UNIFORM_FRAME_OPACITY_FSCT_LOC)
uniform float frame_opacity_fsct;
layout(location = UNIFORM_FRAME_OPACITY_FSCM_LOC)
uniform int frame_opacity_fscm;
// Signed distance field for rectangle center at (0, 0), with size of
// half_size * 2
float rectangle_sdf(vec2 point, vec2 half_size) {
Expand All @@ -136,13 +144,26 @@ const char blit_shader_glsl[] = GLSL(330,
}

vec4 default_post_processing(vec4 c) {
float additional_opacity = 1;
if (frame_opacity_fsc && frame_opacity > 0 && frame_opacity < 1) {
vec4 frame_color = texture(tex, vec2(0.0, 0.01));
float color_diff = max(max(c.r - frame_color.r, c.g - frame_color.g), c.b - frame_color.b);
if (color_diff < 0)
color_diff *= -1;
if (color_diff <= frame_opacity_fsct) {
additional_opacity = frame_opacity * (1 + color_diff * frame_opacity_fscm);

if (additional_opacity > 1)
additional_opacity = 1;
}
}
vec4 border_color = texture(tex, vec2(0.0, 0.5));
if (invert_color) {
c = vec4(c.aaa - c.rgb, c.a);
border_color = vec4(border_color.aaa - border_color.rgb, border_color.a);
}
c = vec4(c.rgb * (1.0 - dim), c.a) * opacity;
border_color = vec4(border_color.rgb * (1.0 - dim), border_color.a) * opacity;
c = vec4(c.rgb * (1.0 - dim), c.a) * opacity * additional_opacity;
border_color = vec4(border_color.rgb * (1.0 - dim), border_color.a) * opacity * additional_opacity;

vec3 rgb_brightness = texelFetch(brightness, ivec2(0, 0), 0).rgb;
// Ref: https://en.wikipedia.org/wiki/Relative_luminance
Expand Down
3 changes: 3 additions & 0 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,9 @@ bool parse_config(options_t *opt, const char *config_file) {
.inactive_opacity_override = false,
.active_opacity = 1.0,
.frame_opacity = 1.0,
.frame_opacity_for_same_colors = false,
.frame_opacity_for_same_colors_tolerance = 0.5,
.frame_opacity_for_same_colors_multiplier = 5,
.detect_client_opacity = false,

.blur_method = BLUR_METHOD_NONE,
Expand Down
6 changes: 6 additions & 0 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,12 @@ typedef struct options {
/// Frame opacity. Relative to window opacity, also affects shadow
/// opacity.
double frame_opacity;
// Enable frame opacity for colors that match the frame
bool frame_opacity_for_same_colors;
// Tolerance for similar colors (0 exact match, 1 all colors, default 0.5)
double frame_opacity_for_same_colors_tolerance;
// Make different colors opaque by a factor of x (default 5)
int frame_opacity_for_same_colors_multiplier;
/// Whether to detect _NET_WM_WINDOW_OPACITY on client windows. Used on window
/// managers that don't pass _NET_WM_WINDOW_OPACITY to frame windows.
bool detect_client_opacity;
Expand Down
6 changes: 6 additions & 0 deletions src/config_libconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,12 @@ bool parse_config_libconfig(options_t *opt, const char *config_file) {

// -e (frame_opacity)
config_lookup_float(&cfg, "frame-opacity", &opt->frame_opacity);
// --frame-opacity-for-same-colors
lcfg_lookup_bool(&cfg, "frame-opacity-for-same-colors", &opt->frame_opacity_for_same_colors);
// --frame-opacity-for-same-colors-tolerance
config_lookup_float(&cfg, "frame-opacity-for-same-colors-tolerance", &opt->frame_opacity_for_same_colors_tolerance);
// --frame-opacity-for-same-colors-multiplier
config_lookup_int(&cfg, "frame-opacity-for-same-colors-multiplier", &opt->frame_opacity_for_same_colors_multiplier);
// -c (shadow_enable)
lcfg_lookup_bool(&cfg, "shadow", &opt->shadow_enable);
// -m (menu_opacity)
Expand Down
3 changes: 3 additions & 0 deletions src/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,9 @@ static const struct picom_option picom_options[] = {
['D'] = {"fade-delta" , INTEGER(fade_delta, 1, INT_MAX) , "The time between steps in a fade in milliseconds. (default 10)"},
['i'] = {"inactive-opacity" , FLOAT(inactive_opacity, 0, 1) , "Opacity of inactive windows. (0.0 - 1.0)"},
['e'] = {"frame-opacity" , FLOAT(frame_opacity, 0, 1) , "Opacity of window titlebars and borders. (0.0 - 1.0)"},
[342] = {"frame-opacity-for-same-colors", ENABLE(frame_opacity_for_same_colors) , "Enable frame opacity for colors that match the frame"},
[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)"},
[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)"},
[257] = {"shadow-red" , FLOAT(shadow_red, 0, 1) , "Red color value of shadow (0.0 - 1.0, defaults to 0)."},
[258] = {"shadow-green" , FLOAT(shadow_green, 0, 1) , "Green color value of shadow (0.0 - 1.0, defaults to 0)."},
[259] = {"shadow-blue" , FLOAT(shadow_blue, 0, 1) , "Blue color value of shadow (0.0 - 1.0, defaults to 0)."},
Expand Down
3 changes: 3 additions & 0 deletions src/picom.c
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,9 @@ static bool paint_preprocess(session_t *ps, bool *animation, struct managed_win

if (win_has_frame(w)) {
w->frame_opacity = ps->o.frame_opacity;
w->frame_opacity_for_same_colors = ps->o.frame_opacity_for_same_colors;
w->frame_opacity_for_same_colors_tolerance = ps->o.frame_opacity_for_same_colors_tolerance;
w->frame_opacity_for_same_colors_multiplier = ps->o.frame_opacity_for_same_colors_multiplier;
} else {
w->frame_opacity = 1.0;
}
Expand Down
10 changes: 7 additions & 3 deletions src/renderer/command_builder.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ commands_for_window_body(struct layer *layer, struct backend_command *cmd,
pixman_region32_copy(&cmd->target_mask, &w->bounding_shape);
pixman_region32_translate(&cmd->target_mask, layer->window.origin.x,
layer->window.origin.y);
if (w->frame_opacity < 1) {
if (w->frame_opacity < 1 && !w->frame_opacity_for_same_colors) {
pixman_region32_subtract(&cmd->target_mask, &cmd->target_mask, frame_region);
}
pixman_region32_init(&cmd->opaque_region);
Expand All @@ -62,6 +62,10 @@ commands_for_window_body(struct layer *layer, struct backend_command *cmd,
.target_mask = &cmd->target_mask,
.corner_radius = w->corner_radius,
.opacity = layer->opacity,
.frame_opacity = w->frame_opacity,
.frame_opacity_for_same_colors = w->frame_opacity_for_same_colors,
.frame_opacity_for_same_colors_tolerance = w->frame_opacity_for_same_colors_tolerance,
.frame_opacity_for_same_colors_multiplier = w->frame_opacity_for_same_colors_multiplier,
.dim = dim,
.scale = layer->scale,
.effective_size = layer->window.size,
Expand All @@ -70,7 +74,7 @@ commands_for_window_body(struct layer *layer, struct backend_command *cmd,
.source_mask = NULL,
.max_brightness = max_brightness};

if (w->frame_opacity == 1 || w->frame_opacity == 0) {
if (w->frame_opacity == 1 || w->frame_opacity == 0 || w->frame_opacity_for_same_colors) {
return 1;
}
cmd -= 1;
Expand Down Expand Up @@ -376,7 +380,7 @@ void command_builder_build(struct command_builder *cb, struct layout *layout, bo
if (layer->win->shadow) {
ncmds += 1;
}
if (layer->win->frame_opacity < 1 && layer->win->frame_opacity > 0) {
if (layer->win->frame_opacity < 1 && layer->win->frame_opacity > 0 && !layer->win->frame_opacity_for_same_colors) {
// Needs to draw the frame separately
ncmds += 1;
}
Expand Down
9 changes: 9 additions & 0 deletions src/win.c
Original file line number Diff line number Diff line change
Expand Up @@ -803,13 +803,19 @@ winmode_t win_calc_mode_raw(const struct managed_win *w) {
if (win_has_frame(w)) {
// The client window doesn't have alpha, but we have a WM
// frame window, which has alpha.
if (w->frame_opacity_for_same_colors)
return WMODE_TRANS;

return WMODE_FRAME_TRANS;
}
// Although the WM window has alpha, the frame window has 0 size,
// so consider the window solid
}

if (w->frame_opacity != 1.0 && win_has_frame(w)) {
if (w->frame_opacity_for_same_colors)
return WMODE_TRANS;

return WMODE_FRAME_TRANS;
}

Expand Down Expand Up @@ -1503,6 +1509,9 @@ struct win *attr_ret_nonnull maybe_allocate_managed_win(session_t *ps, struct wi
// The following ones are updated during paint or paint preprocess
.to_paint = false,
.frame_opacity = 1.0,
.frame_opacity_for_same_colors = false,
.frame_opacity_for_same_colors_tolerance = 0.5,
.frame_opacity_for_same_colors_multiplier = 5,
.dim = false,
.invert_color = false,
.blur_background = false,
Expand Down
6 changes: 6 additions & 0 deletions src/win.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,12 @@ struct managed_win {
// Frame-opacity-related members
/// Current window frame opacity. Affected by window opacity.
double frame_opacity;
// Makes colors matching the frame transparent too
bool frame_opacity_for_same_colors;
// Tolerance for similar colors (0 exact match, 1 all colors, default 0.5)
double frame_opacity_for_same_colors_tolerance;
// Make different colors opaque by a factor of x (default 5)
int frame_opacity_for_same_colors_multiplier;
/// Frame extents. Acquired from _NET_FRAME_EXTENTS.
margin_t frame_extents;

Expand Down

0 comments on commit 968112a

Please sign in to comment.