Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add foreground blurring (Privacy and Focus modes) #765

Open
wants to merge 12 commits into
base: next
Choose a base branch
from
12 changes: 10 additions & 2 deletions src/backend/backend.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
auto real_win_mode = w->mode;
coord_t window_coord = {.x = w->g.x, .y = w->g.y};

if (w->blur_background &&
if (w->blur_background && !w->blur_foreground &&
(ps->o.force_win_blend || real_win_mode == WMODE_TRANS ||
(ps->o.blur_background_frame && real_win_mode == WMODE_FRAME_TRANS))) {
// Minimize the region we try to blur, if the window
Expand Down Expand Up @@ -433,7 +433,7 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
}

// Draw window on target
if (w->frame_opacity == 1) {
if (!w->blur_foreground && w->frame_opacity == 1) {
ps->backend_data->ops->compose(ps->backend_data, w->win_image,
window_coord, NULL, window_coord,
&reg_paint_in_bound, &reg_visible);
Expand Down Expand Up @@ -480,6 +480,14 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
ps->backend_data->ops->release_image(ps->backend_data, new_img);
pixman_region32_fini(&reg_visible_local);
pixman_region32_fini(&reg_bound_local);

// Blur window
if (w->blur_foreground) {
ps->backend_data->ops->blur(
ps->backend_data, ps->o.inactive_blur_opacity,
ps->backend_blur_fgcontext, w->mask_image, window_coord,
&reg_paint_in_bound, &reg_visible);
}
}
skip:
pixman_region32_fini(&reg_bound);
Expand Down
1 change: 1 addition & 0 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ typedef struct session {
backend_t *backend_data;
/// backend blur context
void *backend_blur_context;
void *backend_blur_fgcontext;
/// graphic drivers used
enum driver drivers;
/// file watch handle
Expand Down
7 changes: 5 additions & 2 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,11 @@ char *parse_config(options_t *opt, const char *config_file, bool *shadow_enable,
.no_fading_destroyed_argb = false,
.fade_blacklist = NULL,

.inactive_blur = false,
.inactive_blur_list = NULL,
.inactive_blur_opacity = 1.0,
.inactive_dim = 0.0,
.inactive_dim_fixed = false,
.inactive_opacity = 1.0,
.inactive_opacity_override = false,
.active_opacity = 1.0,
Expand All @@ -781,8 +786,6 @@ char *parse_config(options_t *opt, const char *config_file, bool *shadow_enable,
.blur_kernel_count = 0,
.window_shader_fg = NULL,
.window_shader_fg_rules = NULL,
.inactive_dim = 0.0,
.inactive_dim_fixed = false,
.invert_color_list = NULL,
.opacity_rules = NULL,
.max_brightness = 1.0,
Expand Down
6 changes: 6 additions & 0 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,12 @@ typedef struct options {
char *window_shader_fg;
/// Rules to change custom fragment shader for painting windows.
c2_lptr_t *window_shader_fg_rules;
/// Whether to blur inactive window foregrounds
bool inactive_blur;
// Opacity of inactive foreground blurs
double inactive_blur_opacity;
/// List of windows that should be blurred out when inactive.
c2_lptr_t *inactive_blur_list;
/// How much to dim an inactive window. 0.0 - 1.0, 0 to disable.
double inactive_dim;
/// Whether to use fixed inactive dim opacity, instead of deciding
Expand Down
5 changes: 5 additions & 0 deletions src/config_libconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,11 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad
goto err;
}
}
// --inactive-blur
if (lcfg_lookup_bool(&cfg, "inactive-blur", &opt->inactive_blur)) {
parse_cfg_condlst(&cfg, &opt->inactive_blur_list, "inactive-blur-include");
config_lookup_float(&cfg, "inactive-blur-opacity", &opt->inactive_blur_opacity);
}
// --resize-damage
config_lookup_int(&cfg, "resize-damage", &opt->resize_damage);
// --glx-no-stencil
Expand Down
17 changes: 17 additions & 0 deletions src/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ static const struct picom_option picom_options[] = {
{"shadow-blue" , required_argument, 259, NULL , "Blue color value of shadow (0.0 - 1.0, defaults to 0)."},
{"inactive-opacity-override" , no_argument , 260, NULL , "Inactive opacity set by -i overrides value of _NET_WM_WINDOW_OPACITY."},
{"inactive-dim" , required_argument, 261, NULL , "Dim inactive windows. (0.0 - 1.0, defaults to 0)"},
{"inactive-blur" , no_argument , 341, NULL , "Blur the foreground of inactive windows."},
{"inactive-blur-include" , required_argument, 342, NULL , "Conditions for windows that should be fully blurred when inactive."
"When --inactive-blur is enabled without an --inactive-blur-include"
"condition, the foreground of ALL inactive windows will be blurred."},
{"inactive-blur-opacity" , required_argument, 343, NULL , "Set the opacity of inactive foreground blurs"},
{"mark-wmwin-focused" , no_argument , 262, NULL , "Try to detect WM windows and mark them as active."},
{"shadow-exclude" , required_argument, 263, NULL , "Exclude conditions for shadows."},
{"mark-ovredir-focused" , no_argument , 264, NULL , "Mark windows that have no WM frame as active."},
Expand Down Expand Up @@ -738,6 +743,18 @@ bool get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
// --dithered-present
opt->dithered_present = true;
break;
case 341:
// --inactive-blur
opt->inactive_blur = true;
break;
case 342:
// --inactive-blur-include
condlst_add(&opt->inactive_blur_list, optarg);
break;
case 343:
// --inactive-blur-opacity
opt->inactive_blur_opacity = normalize_d(atof(optarg));
break;
P_CASEBOOL(733, legacy_backends);
P_CASEBOOL(800, monitor_repaint);
case 801:
Expand Down
13 changes: 13 additions & 0 deletions src/picom.c
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,17 @@ static bool initialize_backend(session_t *ps) {
goto err;
}

if (ps->o.inactive_blur && ps->o.blur_method == BLUR_METHOD_NONE) {
log_info("No blur method set, defaulting to box for inactive blur");
struct box_blur_args bargs;
bargs.size = 3;
void *args = (void *)&bargs;
ps->backend_blur_fgcontext = ps->backend_data->ops->create_blur_context(
ps->backend_data, BLUR_METHOD_BOX, args);
} else if (ps->o.inactive_blur) {
ps->backend_blur_fgcontext = ps->backend_blur_context;
}

// Create shaders
HASH_ITER2(ps->shaders, shader) {
assert(shader->backend_shader == NULL);
Expand Down Expand Up @@ -1940,6 +1951,7 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
c2_list_postprocess(ps, ps->o.shadow_clip_list) &&
c2_list_postprocess(ps, ps->o.fade_blacklist) &&
c2_list_postprocess(ps, ps->o.blur_background_blacklist) &&
c2_list_postprocess(ps, ps->o.inactive_blur_list) &&
c2_list_postprocess(ps, ps->o.invert_color_list) &&
c2_list_postprocess(ps, ps->o.window_shader_fg_rules) &&
c2_list_postprocess(ps, ps->o.opacity_rules) &&
Expand Down Expand Up @@ -2319,6 +2331,7 @@ static void session_destroy(session_t *ps) {
c2_list_free(&ps->o.shadow_clip_list, NULL);
c2_list_free(&ps->o.fade_blacklist, NULL);
c2_list_free(&ps->o.focus_blacklist, NULL);
c2_list_free(&ps->o.inactive_blur_list, free);
c2_list_free(&ps->o.invert_color_list, NULL);
c2_list_free(&ps->o.blur_background_blacklist, NULL);
c2_list_free(&ps->o.opacity_rules, NULL);
Expand Down
4 changes: 3 additions & 1 deletion src/render.c
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,8 @@ xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int16_t x, int16_t y
static inline void
win_blur_background(session_t *ps, struct managed_win *w, xcb_render_picture_t tgt_buffer,
const region_t *reg_paint) {
assert(w->blur_foreground == false);

const int16_t x = w->g.x;
const int16_t y = w->g.y;
const auto wid = to_u16_checked(w->widthb);
Expand Down Expand Up @@ -1157,7 +1159,7 @@ void paint_all(session_t *ps, struct managed_win *t, bool ignore_damage) {
#endif

// Blur window background
if (w->blur_background &&
if (w->blur_background && !w->blur_foreground &&
(w->mode == WMODE_TRANS ||
(ps->o.blur_background_frame && w->mode == WMODE_FRAME_TRANS) ||
ps->o.force_win_blend)) {
Expand Down
32 changes: 31 additions & 1 deletion src/win.c
Original file line number Diff line number Diff line change
Expand Up @@ -1080,6 +1080,16 @@ void win_set_shadow_force(session_t *ps, struct managed_win *w, switch_t val) {
}
}

static void
win_set_blur_foreground(session_t *ps, struct managed_win *w, bool blur_foreground_new) {
if (w->blur_foreground == blur_foreground_new)
return;

w->blur_foreground = blur_foreground_new;

add_damage_from_win(ps, w);
}

static void
win_set_blur_background(session_t *ps, struct managed_win *w, bool blur_background_new) {
if (w->blur_background == blur_background_new)
Expand All @@ -1106,6 +1116,22 @@ win_set_fg_shader(session_t *ps, struct managed_win *w, struct shader_info *shad
add_damage_from_win(ps, w);
}

/**
* Determine whether a window's foreground should be blurred
*/
static void win_determine_blur_foreground(session_t *ps, struct managed_win *w) {
log_debug("Determining blur-foreground of window %#010x (%s)", w->base.id, w->name);
if (w->a.map_state != XCB_MAP_STATE_VIEWABLE) {
return;
}

bool blur_foreground_new =
ps->o.inactive_blur && !w->focused &&
(!ps->o.inactive_blur_list || c2_match(ps, w, ps->o.inactive_blur_list, NULL));

win_set_blur_foreground(ps, w, blur_foreground_new);
}

/**
* Determine if a window should have background blurred.
*/
Expand All @@ -1115,7 +1141,10 @@ static void win_determine_blur_background(session_t *ps, struct managed_win *w)
return;
}

bool blur_background_new = ps->o.blur_method != BLUR_METHOD_NONE;
bool blur_background_new = false;
if (!w->blur_foreground) {
blur_background_new = ps->o.blur_method != BLUR_METHOD_NONE;
}
if (blur_background_new) {
if (!ps->o.wintype_option[w->window_type].blur_background) {
log_debug("Blur background disabled by wintypes");
Expand Down Expand Up @@ -1220,6 +1249,7 @@ void win_on_factor_change(session_t *ps, struct managed_win *w) {
win_determine_shadow(ps, w);
win_determine_clip_shadow_above(ps, w);
win_determine_invert_color(ps, w);
win_determine_blur_foreground(ps, w);
win_determine_blur_background(ps, w);
win_determine_rounded_corners(ps, w);
win_determine_fg_shader(ps, w);
Expand Down
3 changes: 3 additions & 0 deletions src/win.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,9 @@ struct managed_win {
/// Whether to blur window background.
bool blur_background;

/// Whether to blur window foreground.
bool blur_foreground;

/// The custom window shader to use when rendering.
struct shader_info *fg_shader;

Expand Down