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 rounded corners #229

Closed
wants to merge 39 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
43b8b1d
Add rounded corners
sdhand Aug 29, 2019
370afc3
Don't round fullscreen windows
sdhand Aug 30, 2019
826ab25
Use a mask for rounded corners
sdhand Aug 30, 2019
24fae5e
Fix bug where the wrong standard was used
Aug 30, 2019
43acc20
Fix bug where the wrong standard was being used - again
Aug 30, 2019
8b9c097
Add rounded-corners-exclude configuration option
Dec 17, 2019
e3c47be
Fix rounded corners when using transparent frames, and blurred backgr…
sdhand Jan 23, 2020
00a6c09
rebased rounded_corners to experimental-backends
ibhagwan Mar 26, 2020
c540c44
fixed leftover bug from testing
ibhagwan Mar 26, 2020
4ce5d64
WIP: added fragment shader skeleton for rounded corners on glx
ibhagwan Mar 27, 2020
1b78411
WIP: skeleton shader for rounded corners working (green mask)
ibhagwan Mar 27, 2020
fcb5c43
wip: rounded corners shader test code semi-worikng?
ibhagwan Mar 28, 2020
dced0d7
wip: rounded corners frag shader works with green corners
ibhagwan Mar 28, 2020
7deb0a5
merged with yshui/picom commit 3ba7a2a [2020-03-28]
ibhagwan Mar 28, 2020
6cc2974
changed some variable names in rounded corners shader
ibhagwan Mar 28, 2020
eb40993
moved round_corners function to the right place
ibhagwan Mar 29, 2020
b9cdd42
round_corners function moved again
ibhagwan Mar 30, 2020
6c0b19f
merged with yshui/compton up to commit 4c22d56
ibhagwan Mar 30, 2020
f48a7c6
rounded corners with glx: almost there...
ibhagwan Mar 30, 2020
3f0286f
rounded corners progress...
ibhagwan Mar 31, 2020
8e62405
merged with yshui/picom up to commit b109526
ibhagwan Mar 31, 2020
addfdde
temp commit before changing lots of code
ibhagwan Mar 31, 2020
491639b
need cleanup now, but rounded corners are working with glx
ibhagwan Mar 31, 2020
9879d7f
rounded corners code cleanup
ibhagwan Mar 31, 2020
7aa5f0d
init rounded corners shader only if glx backend is used
ibhagwan Apr 1, 2020
510cd99
rewrote shader code for better rounded corner rendering
ibhagwan Apr 2, 2020
27486e4
wip: rounded borders almost working, need to add source alpha to pixel
ibhagwan Apr 2, 2020
e4392af
wip: removed old shader, rounded borders almost perfect
ibhagwan Apr 2, 2020
2d13d16
Smooth glx corners
sdhand Apr 3, 2020
c732c9f
Fix memory leak?
sdhand Apr 3, 2020
e370ec2
Don't render shadows behind rounded corner windows with the xrender b…
sdhand Apr 4, 2020
32d6678
Fix frame opacity
sdhand Apr 4, 2020
6770a8c
Merge remote-tracking branch 'upstream/next' into next
sdhand Apr 4, 2020
e1b5570
Fix (another) memory leak
sdhand Apr 4, 2020
bae5bf0
rounded borders working with one-colored borders
ibhagwan Apr 4, 2020
1f8eb20
Fix a type error in the rounded corners shader
sdhand Apr 5, 2020
f6fa3c4
merge with ibhagwan's fork commit 68c8f1b
ibhagwan May 5, 2020
c5abd7e
minor modifications for tests and no-opengl build
ibhagwan May 5, 2020
a99772b
last warning fix for tests to pass
ibhagwan May 5, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions man/picom.1.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,18 @@ OPTIONS
*--inactive-dim* 'VALUE'::
Dim inactive windows. (0.0 - 1.0, defaults to 0.0)

*--corner-radius* 'VALUE'::
Round the corners of windows. (defaults to 0).

*--rounded-corners-exclude* 'CONDITION'::
Exclude conditions for rounded corners.

*--round-borders* 'VALUE'::
When rounding corners, Round the borders of windows. (defaults to 1).

*--round-borders-exclude* 'CONDITION'::
Exclude conditions for rounding borders.

*--mark-wmwin-focused*::
Try to detect WM windows (a non-override-redirect window with no child that has 'WM_STATE') and mark them as active.

Expand Down
35 changes: 27 additions & 8 deletions src/backend/backend.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
}

if (ps->root_image) {
ps->backend_data->ops->compose(ps->backend_data, ps->root_image, 0, 0,
ps->backend_data->ops->compose(ps->backend_data, t, ps->root_image, 0, 0,
&reg_paint, &reg_visible);
} else {
ps->backend_data->ops->fill(ps->backend_data, (struct color){0, 0, 0, 1},
Expand All @@ -171,7 +171,7 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {

// The bounding shape of the window, in global/target coordinates
// reminder: bounding shape contains the WM frame
auto reg_bound = win_get_bounding_shape_global_by_val(w);
auto reg_bound = win_get_bounding_shape_global_by_val(w, true);

// The clip region for the current window, in global/target coordinates
// reg_paint_in_bound \in reg_paint
Expand All @@ -190,6 +190,17 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
&reg_paint_in_bound, &reg_visible);
}

// Store the window background for rounded corners
// If rounded corners backup the region first
if (w->corner_radius > 0) {
const int16_t x = w->g.x;
const int16_t y = w->g.y;
const auto wid = to_u16_checked(w->widthb);
const auto hei = to_u16_checked(w->heightb);
ps->backend_data->ops->store_back_texture(ps->backend_data, w,
ps->backend_round_context, &reg_bound, x, y, wid, hei);
}

// Blur window background
// TODO since the background might change the content of the window (e.g.
// with shaders), we should consult the background whether the window
Expand Down Expand Up @@ -230,7 +241,7 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
assert(ps->o.blur_background_frame);
assert(real_win_mode == WMODE_FRAME_TRANS);

auto reg_blur = win_get_region_frame_local_by_val(w);
auto reg_blur = win_get_region_frame_local_by_val(w, true);
pixman_region32_translate(&reg_blur, w->g.x, w->g.y);
// make sure reg_blur \in reg_paint
pixman_region32_intersect(&reg_blur, &reg_blur, &reg_paint);
Expand Down Expand Up @@ -286,7 +297,7 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
assert(w->shadow_image);
if (w->opacity == 1) {
ps->backend_data->ops->compose(
ps->backend_data, w->shadow_image, w->g.x + w->shadow_dx,
ps->backend_data, w, w->shadow_image, w->g.x + w->shadow_dx,
w->g.y + w->shadow_dy, &reg_shadow, &reg_visible);
} else {
auto new_img = ps->backend_data->ops->copy(
Expand All @@ -295,7 +306,7 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
ps->backend_data, IMAGE_OP_APPLY_ALPHA_ALL, new_img,
NULL, &reg_visible, (double[]){w->opacity});
ps->backend_data->ops->compose(
ps->backend_data, new_img, w->g.x + w->shadow_dx,
ps->backend_data, w, new_img, w->g.x + w->shadow_dx,
w->g.y + w->shadow_dy, &reg_shadow, &reg_visible);
ps->backend_data->ops->release_image(ps->backend_data, new_img);
}
Expand All @@ -311,7 +322,7 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {

// Draw window on target
if (!w->invert_color && !w->dim && w->frame_opacity == 1 && w->opacity == 1) {
ps->backend_data->ops->compose(ps->backend_data, w->win_image,
ps->backend_data->ops->compose(ps->backend_data, w, w->win_image,
w->g.x, w->g.y,
&reg_paint_in_bound, &reg_visible);
} else if (w->opacity * MAX_ALPHA >= 1) {
Expand Down Expand Up @@ -360,7 +371,7 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
&reg_visible_local, (double[]){dim_opacity});
}
if (w->frame_opacity != 1) {
auto reg_frame = win_get_region_frame_local_by_val(w);
auto reg_frame = win_get_region_frame_local_by_val(w, true);
ps->backend_data->ops->image_op(
ps->backend_data, IMAGE_OP_APPLY_ALPHA, new_img, &reg_frame,
&reg_visible_local, (double[]){w->frame_opacity});
Expand All @@ -371,13 +382,21 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
ps->backend_data, IMAGE_OP_APPLY_ALPHA_ALL, new_img,
NULL, &reg_visible_local, (double[]){w->opacity});
}
ps->backend_data->ops->compose(ps->backend_data, new_img, w->g.x,
ps->backend_data->ops->compose(ps->backend_data, w, new_img, w->g.x,
w->g.y, &reg_paint_in_bound,
&reg_visible);
ps->backend_data->ops->release_image(ps->backend_data, new_img);
pixman_region32_fini(&reg_visible_local);
pixman_region32_fini(&reg_bound_local);
}

// Round the corners as last step after blur/shadow/dim/etc
if (w->corner_radius > 0.0) {
ps->backend_data->ops->round(ps->backend_data, w,
ps->backend_round_context, w->win_image,
&reg_bound, &reg_visible);
}

pixman_region32_fini(&reg_bound);
pixman_region32_fini(&reg_paint_in_bound);
}
Expand Down
24 changes: 23 additions & 1 deletion src/backend/backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ typedef struct backend_base {
/// Whether the backend can accept new render request at the moment
bool busy;
// ...

// Session data
session_t *ps;
} backend_t;

typedef void (*backend_ready_callback_t)(void *);
Expand Down Expand Up @@ -65,6 +68,11 @@ struct kernel_blur_args {
int kernel_count;
};

struct round_corners_args {
int corner_radius;
bool round_borders;
};

struct backend_operations {
// =========== Initialization ===========

Expand Down Expand Up @@ -126,7 +134,7 @@ struct backend_operations {
* @param reg_paint the clip region, in target coordinates
* @param reg_visible the visible region, in target coordinates
*/
void (*compose)(backend_t *backend_data, void *image_data, int dst_x, int dst_y,
void (*compose)(backend_t *backend_data, struct managed_win *const w, void *image_data, int dst_x, int dst_y,
const region_t *reg_paint, const region_t *reg_visible);

/// Fill rectangle of the rendering buffer, mostly for debug purposes, optional.
Expand All @@ -137,6 +145,11 @@ struct backend_operations {
const region_t *reg_blur, const region_t *reg_visible)
attr_nonnull(1, 3, 4, 5);

/// Round a given region of the rendering buffer.
bool (*round)(backend_t *backend_data, struct managed_win *w, void *round_ctx,
void *image_data, const region_t *reg_round, const region_t *reg_visible)
attr_nonnull(1, 2, 3, 5, 6);

/// Update part of the back buffer with the rendering buffer, then present the
/// back buffer onto the target window (if not back buffered, update part of the
/// target window directly).
Expand Down Expand Up @@ -218,6 +231,15 @@ struct backend_operations {
/// Get how many pixels outside of the blur area is needed for blur
void (*get_blur_size)(void *blur_context, int *width, int *height);

/// Backup our current window background so we can use it for "erasing" corners
bool (*store_back_texture)(backend_t *base, struct managed_win *w, void *ctx_,
const region_t *reg_tgt, int x, int y, int width, int height);

/// Create a rounded corners context
void *(*create_round_context)(backend_t *base, void *args);
/// Destroy a rounded corners context
void (*destroy_round_context)(backend_t *base, void *ctx);

// =========== Hooks ============
/// Let the backend hook into the event handling queue
/// Not implemented yet
Expand Down
1 change: 1 addition & 0 deletions src/backend/backend_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -368,4 +368,5 @@ void init_backend_base(struct backend_base *base, session_t *ps) {
base->root = ps->root;
base->busy = false;
base->ops = NULL;
base->ps = ps;
}
25 changes: 24 additions & 1 deletion src/backend/dummy/dummy.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ static void dummy_check_image(struct backend_base *base, const struct dummy_imag
assert(*tmp->refcount > 0);
}

void dummy_compose(struct backend_base *base, void *image, int dst_x attr_unused,
void dummy_compose(struct backend_base *base, struct managed_win *w attr_unused, void *image, int dst_x attr_unused,
int dst_y attr_unused, const region_t *reg_paint attr_unused,
const region_t *reg_visible attr_unused) {
dummy_check_image(base, image);
Expand All @@ -72,6 +72,12 @@ bool dummy_blur(struct backend_base *backend_data attr_unused, double opacity at
return true;
}

bool dummy_round(struct backend_base *backend_data attr_unused, struct managed_win *w attr_unused,
void *ctx_ attr_unused, void *image_data attr_unused, const region_t *reg_round attr_unused,
const region_t *reg_visible attr_unused) {
return true;
}

void *dummy_bind_pixmap(struct backend_base *base, xcb_pixmap_t pixmap,
struct xvisual_info fmt, bool owned attr_unused) {
auto dummy = (struct dummy_data *)base;
Expand Down Expand Up @@ -138,19 +144,33 @@ void *dummy_create_blur_context(struct backend_base *base attr_unused,
void dummy_destroy_blur_context(struct backend_base *base attr_unused, void *ctx attr_unused) {
}

void *dummy_create_round_context(struct backend_base *base attr_unused, void *args attr_unused) {
static int dummy_context;
return &dummy_context;
}

void dummy_destroy_round_context(struct backend_base *base attr_unused, void *ctx attr_unused) {
}

void dummy_get_blur_size(void *ctx attr_unused, int *width, int *height) {
// These numbers are arbitrary, to make sure the reisze_region code path is
// covered.
*width = 5;
*height = 5;
}

bool dummy_store_back_texture(backend_t *backend_data attr_unused, struct managed_win *w attr_unused, void *ctx_ attr_unused,
const region_t *reg_tgt attr_unused, int x attr_unused, int y attr_unused, int width attr_unused, int height attr_unused) {
return true;
}

struct backend_operations dummy_ops = {
.init = dummy_init,
.deinit = dummy_deinit,
.compose = dummy_compose,
.fill = dummy_fill,
.blur = dummy_blur,
.round = dummy_round,
.bind_pixmap = dummy_bind_pixmap,
.render_shadow = default_backend_render_shadow,
.release_image = dummy_release_image,
Expand All @@ -162,6 +182,9 @@ struct backend_operations dummy_ops = {
.copy = dummy_image_copy,
.create_blur_context = dummy_create_blur_context,
.destroy_blur_context = dummy_destroy_blur_context,
.create_round_context = dummy_create_round_context,
.destroy_round_context = dummy_destroy_round_context,
.get_blur_size = dummy_get_blur_size,
.store_back_texture = dummy_store_back_texture

};
Loading