From 4c4dc9aa95ca86d58eb261fb19cbc62be67f92a0 Mon Sep 17 00:00:00 2001 From: Nikita Zlobin Date: Sun, 3 May 2020 14:28:14 +0500 Subject: [PATCH 01/16] Fix ugly rounded corners --- src/x11/x.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/x11/x.c b/src/x11/x.c index 6595d28..bc5daf2 100644 --- a/src/x11/x.c +++ b/src/x11/x.c @@ -110,10 +110,13 @@ static void x_win_round_corners(struct window_x11 *win, const int rad) /* To mark all pixels, which should get exposed, we * use a circle for every corner and two overlapping rectangles */ + int fw = settings.frame_width / 2 + settings.frame_width % 2; + if (fw < 1) + fw=1; unsigned const int centercoords[] = { - 0, 0, - width - dia - 1, 0, - 0, height - dia - 1, + -fw, -fw, + width - dia - 1, -fw, + -fw, height - dia - 1, width - dia - 1, height - dia - 1, }; @@ -123,8 +126,8 @@ static void x_win_round_corners(struct window_x11 *win, const int rad) shape_gc, centercoords[i], centercoords[i+1], - dia, - dia, + dia+fw, + dia+fw, degrees * 0, degrees * 360); } From 16e38a9a84c46b0cd4fd7b0f2f88e9d8054ccc0b Mon Sep 17 00:00:00 2001 From: Nikita Zlobin Date: Sun, 3 May 2020 16:24:59 +0500 Subject: [PATCH 02/16] Don't draw frame with zero line width --- src/draw.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/draw.c b/src/draw.c index bdda7f3..eb33b96 100644 --- a/src/draw.c +++ b/src/draw.c @@ -464,24 +464,27 @@ static cairo_surface_t *render_background(cairo_surface_t *srf, else height += settings.separator_height; - cairo_set_source_rgb(c, cl->frame.r, cl->frame.g, cl->frame.b); - draw_rounded_rect(c, x, y, width, height, corner_radius, first, last); - cairo_fill(c); + if (settings.frame_width > 0) + { + cairo_set_source_rgb(c, cl->frame.r, cl->frame.g, cl->frame.b); + draw_rounded_rect(c, x, y, width, height, corner_radius, first, last); + cairo_fill(c); - /* adding frame */ - x += settings.frame_width; - if (first) { - y += settings.frame_width; - height -= settings.frame_width; + /* adding frame */ + x += settings.frame_width; + if (first) { + y += settings.frame_width; + height -= settings.frame_width; + } + + width -= 2 * settings.frame_width; + + if (last) + height -= settings.frame_width; + else + height -= settings.separator_height; } - width -= 2 * settings.frame_width; - - if (last) - height -= settings.frame_width; - else - height -= settings.separator_height; - cairo_set_source_rgb(c, cl->bg.r, cl->bg.g, cl->bg.b); draw_rounded_rect(c, x, y, width, height, corner_radius, first, last); cairo_fill(c); From dbbaecfd1db3e77d2addea5d1bee4fffe6793717 Mon Sep 17 00:00:00 2001 From: Nikita Zlobin Date: Mon, 4 May 2020 02:35:34 +0500 Subject: [PATCH 03/16] Fix indentation --- src/draw.c | 30 +++++++++++++++--------------- src/x11/x.c | 6 +++--- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/draw.c b/src/draw.c index eb33b96..b7d2518 100644 --- a/src/draw.c +++ b/src/draw.c @@ -464,25 +464,25 @@ static cairo_surface_t *render_background(cairo_surface_t *srf, else height += settings.separator_height; - if (settings.frame_width > 0) + if (settings.frame_width > 0) { - cairo_set_source_rgb(c, cl->frame.r, cl->frame.g, cl->frame.b); - draw_rounded_rect(c, x, y, width, height, corner_radius, first, last); - cairo_fill(c); + cairo_set_source_rgb(c, cl->frame.r, cl->frame.g, cl->frame.b); + draw_rounded_rect(c, x, y, width, height, corner_radius, first, last); + cairo_fill(c); - /* adding frame */ - x += settings.frame_width; - if (first) { - y += settings.frame_width; - height -= settings.frame_width; - } + /* adding frame */ + x += settings.frame_width; + if (first) { + y += settings.frame_width; + height -= settings.frame_width; + } - width -= 2 * settings.frame_width; + width -= 2 * settings.frame_width; - if (last) - height -= settings.frame_width; - else - height -= settings.separator_height; + if (last) + height -= settings.frame_width; + else + height -= settings.separator_height; } cairo_set_source_rgb(c, cl->bg.r, cl->bg.g, cl->bg.b); diff --git a/src/x11/x.c b/src/x11/x.c index bc5daf2..294d110 100644 --- a/src/x11/x.c +++ b/src/x11/x.c @@ -110,9 +110,9 @@ static void x_win_round_corners(struct window_x11 *win, const int rad) /* To mark all pixels, which should get exposed, we * use a circle for every corner and two overlapping rectangles */ - int fw = settings.frame_width / 2 + settings.frame_width % 2; - if (fw < 1) - fw=1; + int fw = settings.frame_width / 2 + settings.frame_width % 2; + if (fw < 1) + fw=1; unsigned const int centercoords[] = { -fw, -fw, width - dia - 1, -fw, From c09f0f029f15494cfd05261999e69c5afdb70401 Mon Sep 17 00:00:00 2001 From: Nikita Zlobin Date: Mon, 4 May 2020 02:42:18 +0500 Subject: [PATCH 04/16] style fix --- src/x11/x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/x11/x.c b/src/x11/x.c index 294d110..4cd7e41 100644 --- a/src/x11/x.c +++ b/src/x11/x.c @@ -112,7 +112,7 @@ static void x_win_round_corners(struct window_x11 *win, const int rad) * use a circle for every corner and two overlapping rectangles */ int fw = settings.frame_width / 2 + settings.frame_width % 2; if (fw < 1) - fw=1; + fw = 1; unsigned const int centercoords[] = { -fw, -fw, width - dia - 1, -fw, From 7a094bc702149104cd4049281a7dd9ed0ab76c89 Mon Sep 17 00:00:00 2001 From: Nikita Zlobin Date: Mon, 4 May 2020 18:58:39 +0500 Subject: [PATCH 05/16] Clear window to prevent accumulations --- src/x11/x.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/x11/x.c b/src/x11/x.c index 4cd7e41..3321e99 100644 --- a/src/x11/x.c +++ b/src/x11/x.c @@ -160,6 +160,9 @@ void x_display_surface(cairo_surface_t *srf, struct window_x11 *win, const struc x_win_move(win, dim->x, dim->y, dim->w, dim->h); cairo_xlib_surface_set_size(win->root_surface, dim->w, dim->h); + XClearWindow(xctx.dpy, win->xwin); + XFlush(xctx.dpy); + cairo_set_source_surface(win->c_ctx, srf, 0, 0); cairo_paint(win->c_ctx); cairo_show_page(win->c_ctx); @@ -650,6 +653,7 @@ struct window_x11 *x_win_create(void) wa.override_redirect = true; wa.background_pixmap = ParentRelative; + wa.background_pixel = 0; wa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask | ButtonReleaseMask | FocusChangeMask| StructureNotifyMask; @@ -665,7 +669,7 @@ struct window_x11 *x_win_create(void) DefaultDepth(xctx.dpy, DefaultScreen(xctx.dpy)), CopyFromParent, DefaultVisual(xctx.dpy, DefaultScreen(xctx.dpy)), - CWOverrideRedirect | CWBackPixmap | CWEventMask, + CWOverrideRedirect | CWBackPixmap | CWBackPixel | CWEventMask, &wa); x_set_wm(win->xwin); From d3f6c055902d9723c4b46acb943fd75fd142f2ee Mon Sep 17 00:00:00 2001 From: Nikita Zlobin Date: Mon, 4 May 2020 19:45:02 +0500 Subject: [PATCH 06/16] True transparency support --- src/x11/x.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/x11/x.c b/src/x11/x.c index 3321e99..896e819 100644 --- a/src/x11/x.c +++ b/src/x11/x.c @@ -647,13 +647,19 @@ struct window_x11 *x_win_create(void) struct window_x11 *win = g_malloc0(sizeof(struct window_x11)); Window root; + int scr_n; + XVisualInfo vi; XSetWindowAttributes wa; - root = RootWindow(xctx.dpy, DefaultScreen(xctx.dpy)); + scr_n = DefaultScreen(xctx.dpy); + root = RootWindow(xctx.dpy, scr_n); + XMatchVisualInfo(xctx.dpy, scr_n, 32, TrueColor, &vi); wa.override_redirect = true; - wa.background_pixmap = ParentRelative; + wa.background_pixmap = None; wa.background_pixel = 0; + wa.border_pixel = 0; + wa.colormap = XCreateColormap(xctx.dpy, root, vi.visual, AllocNone); wa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask | ButtonReleaseMask | FocusChangeMask| StructureNotifyMask; @@ -666,10 +672,10 @@ struct window_x11 *x_win_create(void) scr->w, 1, 0, - DefaultDepth(xctx.dpy, DefaultScreen(xctx.dpy)), + vi.depth, CopyFromParent, - DefaultVisual(xctx.dpy, DefaultScreen(xctx.dpy)), - CWOverrideRedirect | CWBackPixmap | CWBackPixel | CWEventMask, + vi.visual, + CWOverrideRedirect | CWBackPixmap | CWBackPixel | CWBorderPixel | CWColormap | CWEventMask, &wa); x_set_wm(win->xwin); @@ -680,7 +686,7 @@ struct window_x11 *x_win_create(void) (0xffffffff / 100))); win->root_surface = cairo_xlib_surface_create(xctx.dpy, win->xwin, - DefaultVisual(xctx.dpy, 0), + vi.visual, WIDTH, HEIGHT); win->c_ctx = cairo_create(win->root_surface); From d964455d36b79d651faeec7f9c416dfcfde3334a Mon Sep 17 00:00:00 2001 From: Nikita Zlobin Date: Tue, 5 May 2020 00:52:07 +0500 Subject: [PATCH 07/16] oops: Keep ready for possible 32bit color lack --- src/x11/x.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/x11/x.c b/src/x11/x.c index 896e819..a5706d9 100644 --- a/src/x11/x.c +++ b/src/x11/x.c @@ -648,18 +648,29 @@ struct window_x11 *x_win_create(void) Window root; int scr_n; + int depth; + Visual * vis; XVisualInfo vi; XSetWindowAttributes wa; scr_n = DefaultScreen(xctx.dpy); root = RootWindow(xctx.dpy, scr_n); - XMatchVisualInfo(xctx.dpy, scr_n, 32, TrueColor, &vi); + if (XMatchVisualInfo(xctx.dpy, scr_n, 32, TrueColor, &vi)) + { + vis = vi.visual; + depth = vi.depth; + } + else + { + vis = DefaultVisual(xctx.dpy, scr_n); + depth = DefaultDepth(xctx.dpy, scr_n); + } wa.override_redirect = true; wa.background_pixmap = None; wa.background_pixel = 0; wa.border_pixel = 0; - wa.colormap = XCreateColormap(xctx.dpy, root, vi.visual, AllocNone); + wa.colormap = XCreateColormap(xctx.dpy, root, vis, AllocNone); wa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask | ButtonReleaseMask | FocusChangeMask| StructureNotifyMask; @@ -672,9 +683,9 @@ struct window_x11 *x_win_create(void) scr->w, 1, 0, - vi.depth, + depth, CopyFromParent, - vi.visual, + vis, CWOverrideRedirect | CWBackPixmap | CWBackPixel | CWBorderPixel | CWColormap | CWEventMask, &wa); @@ -686,7 +697,7 @@ struct window_x11 *x_win_create(void) (0xffffffff / 100))); win->root_surface = cairo_xlib_surface_create(xctx.dpy, win->xwin, - vi.visual, + vis, WIDTH, HEIGHT); win->c_ctx = cairo_create(win->root_surface); From dcf060effa91444b6032084fd9d75592557446a3 Mon Sep 17 00:00:00 2001 From: Nikita Zlobin Date: Tue, 5 May 2020 11:55:50 +0500 Subject: [PATCH 08/16] Fix xshape mask rounding --- src/x11/x.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/x11/x.c b/src/x11/x.c index a5706d9..7d1be82 100644 --- a/src/x11/x.c +++ b/src/x11/x.c @@ -110,13 +110,10 @@ static void x_win_round_corners(struct window_x11 *win, const int rad) /* To mark all pixels, which should get exposed, we * use a circle for every corner and two overlapping rectangles */ - int fw = settings.frame_width / 2 + settings.frame_width % 2; - if (fw < 1) - fw = 1; unsigned const int centercoords[] = { - -fw, -fw, - width - dia - 1, -fw, - -fw, height - dia - 1, + 0, 0, + width - dia - 1, 0, + 0, height - dia - 1, width - dia - 1, height - dia - 1, }; @@ -124,10 +121,10 @@ static void x_win_round_corners(struct window_x11 *win, const int rad) XFillArc(xctx.dpy, mask, shape_gc, - centercoords[i], - centercoords[i+1], - dia+fw, - dia+fw, + centercoords[i]-1, + centercoords[i+1]-1, + dia+2, + dia+2, degrees * 0, degrees * 360); } From 5fd090e618092c89a1497817aca482f472219e1f Mon Sep 17 00:00:00 2001 From: Nikita Zlobin Date: Wed, 6 May 2020 22:26:30 +0500 Subject: [PATCH 09/16] Frame internal radius --- src/draw.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/draw.c b/src/draw.c index b7d2518..7e11e11 100644 --- a/src/draw.c +++ b/src/draw.c @@ -454,6 +454,7 @@ static cairo_surface_t *render_background(cairo_surface_t *srf, int *ret_width) { int x = 0; + int radius_int = corner_radius; cairo_t *c = cairo_create(srf); @@ -483,10 +484,27 @@ static cairo_surface_t *render_background(cairo_surface_t *srf, height -= settings.frame_width; else height -= settings.separator_height; + + /* Attempt to make internal radius more organic. + * Simple r-w is not enough for too small r/w ratio. + * simplifications: r/2 == r - w + w*w / (r * 2) with (w == r) + **/ + { const int s = 2 << (sizeof(int) * 8 / 4); // Integer precision scaler + int h, w, r, r1, r2; + + h = s * height; + r = s * corner_radius; + w = s * settings.frame_width; + r1 = r - w + w * w / (r * 2); // w < r; + r2 = r * h / (h + (w - r) * 2); // w >= r + + radius_int = (r > w) ? r1 : (r / 2 < r2) ? r / 2 : r2; + radius_int /= s; + } } cairo_set_source_rgb(c, cl->bg.r, cl->bg.g, cl->bg.b); - draw_rounded_rect(c, x, y, width, height, corner_radius, first, last); + draw_rounded_rect(c, x, y, width, height, radius_int, first, last); cairo_fill(c); if ( settings.sep_color.type != SEP_FRAME From 0e35c6acb0c110a4ab00a560ff15f3e2c85c5f4c Mon Sep 17 00:00:00 2001 From: Nikita Zlobin Date: Thu, 7 May 2020 02:47:11 +0500 Subject: [PATCH 10/16] Use cairo to form xshape mask --- src/x11/x.c | 85 +++++++++++++++++++++-------------------------------- 1 file changed, 33 insertions(+), 52 deletions(-) diff --git a/src/x11/x.c b/src/x11/x.c index 7d1be82..672b6e2 100644 --- a/src/x11/x.c +++ b/src/x11/x.c @@ -89,63 +89,44 @@ static void x_win_round_corners(struct window_x11 *win, const int rad) { const int width = win->dim.w; const int height = win->dim.h; - const int dia = 2 * rad; - const int degrees = 64; // the factor to convert degrees to XFillArc's angle param - - Pixmap mask = XCreatePixmap(xctx.dpy, win->xwin, width, height, 1); - XGCValues xgcv; - - GC shape_gc = XCreateGC(xctx.dpy, mask, 0, &xgcv); - - XSetForeground(xctx.dpy, shape_gc, 0); - XFillRectangle(xctx.dpy, - mask, - shape_gc, - 0, - 0, - width, - height); - - XSetForeground(xctx.dpy, shape_gc, 1); - - /* To mark all pixels, which should get exposed, we - * use a circle for every corner and two overlapping rectangles */ - unsigned const int centercoords[] = { - 0, 0, - width - dia - 1, 0, - 0, height - dia - 1, - width - dia - 1, height - dia - 1, + unsigned const int coords[] = { + 0 + rad, + width - rad, + height - rad, }; - for (int i = 0; i < sizeof(centercoords)/sizeof(unsigned int); i = i+2) { - XFillArc(xctx.dpy, - mask, - shape_gc, - centercoords[i]-1, - centercoords[i+1]-1, - dia+2, - dia+2, - degrees * 0, - degrees * 360); - } - XFillRectangle(xctx.dpy, - mask, - shape_gc, - rad, - 0, - width-dia, - height); - XFillRectangle(xctx.dpy, - mask, - shape_gc, - 0, - rad, - width, - height-dia); + Pixmap mask; + cairo_surface_t * cxbm; + cairo_t * cr; + Screen * scr; + + mask = XCreatePixmap(xctx.dpy, win->xwin, width, height, 1); + scr = ScreenOfDisplay(xctx.dpy, win->cur_screen); + cxbm = cairo_xlib_surface_create_for_bitmap(xctx.dpy, mask, scr, width, height); + cr = cairo_create(cxbm); + + cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + + cairo_set_source_rgba(cr, 0, 0, 0, 0); + cairo_paint(cr); + cairo_set_source_rgba(cr, 1, 1, 1, 1); + + cairo_new_path(cr); + cairo_arc(cr, coords[0], coords[0], rad, M_PI, -M_PI_2); + cairo_arc(cr, coords[1], coords[0], rad, -M_PI_2, 0); + cairo_arc(cr, coords[1], coords[2], rad, 0, M_PI_2); + cairo_arc(cr, coords[0], coords[2], rad, M_PI_2, M_PI); + cairo_close_path(cr); + cairo_fill(cr); + + cairo_show_page(cr); + cairo_destroy(cr); + cairo_surface_flush(cxbm); + cairo_surface_destroy(cxbm); XShapeCombineMask(xctx.dpy, win->xwin, ShapeBounding, 0, 0, mask, ShapeSet); - XFreeGC(xctx.dpy, shape_gc); XFreePixmap(xctx.dpy, mask); XShapeSelectInput(xctx.dpy, From 296cea499c4b1ea09c20bf54a150987938b800d4 Mon Sep 17 00:00:00 2001 From: Nikita Zlobin Date: Fri, 8 May 2020 06:23:10 +0500 Subject: [PATCH 11/16] Compositor detection --- src/x11/x.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/x11/x.c b/src/x11/x.c index 672b6e2..468b18d 100644 --- a/src/x11/x.c +++ b/src/x11/x.c @@ -135,6 +135,8 @@ static void x_win_round_corners(struct window_x11 *win, const int rad) void x_display_surface(cairo_surface_t *srf, struct window_x11 *win, const struct dimensions *dim) { + char astr[sizeof("_NET_WM_CM_S") / sizeof(char) + 8]; + x_win_move(win, dim->x, dim->y, dim->w, dim->h); cairo_xlib_surface_set_size(win->root_surface, dim->w, dim->h); @@ -145,8 +147,21 @@ void x_display_surface(cairo_surface_t *srf, struct window_x11 *win, const struc cairo_paint(win->c_ctx); cairo_show_page(win->c_ctx); - if (settings.corner_radius != 0) + sprintf (astr, "_NET_WM_CM_S%i", win->cur_screen); + Atom cm_sel = XInternAtom (xctx.dpy, astr, true); + if (settings.corner_radius != 0 && XGetSelectionOwner(xctx.dpy, cm_sel) == None) x_win_round_corners(win, dim->corner_radius); + else + { + XRectangle rect = { + .x = 0, + .y = 0, + .width = dim->w, + .height = dim->h }; + XShapeCombineRectangles(xctx.dpy, win->xwin, ShapeBounding, 0, 0, &rect, 1, ShapeSet, 1); + XShapeSelectInput(xctx.dpy, + win->xwin, ShapeNotifyMask); + } XFlush(xctx.dpy); From 6b6b63da17a9e027ab922a6048d672789160dfa0 Mon Sep 17 00:00:00 2001 From: Nikita Zlobin Date: Sat, 9 May 2020 02:10:15 +0500 Subject: [PATCH 12/16] code style fix --- src/x11/x.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/x11/x.c b/src/x11/x.c index 468b18d..0fb95c5 100644 --- a/src/x11/x.c +++ b/src/x11/x.c @@ -136,6 +136,7 @@ static void x_win_round_corners(struct window_x11 *win, const int rad) void x_display_surface(cairo_surface_t *srf, struct window_x11 *win, const struct dimensions *dim) { char astr[sizeof("_NET_WM_CM_S") / sizeof(char) + 8]; + Atom cm_sel; x_win_move(win, dim->x, dim->y, dim->w, dim->h); cairo_xlib_surface_set_size(win->root_surface, dim->w, dim->h); @@ -147,8 +148,8 @@ void x_display_surface(cairo_surface_t *srf, struct window_x11 *win, const struc cairo_paint(win->c_ctx); cairo_show_page(win->c_ctx); - sprintf (astr, "_NET_WM_CM_S%i", win->cur_screen); - Atom cm_sel = XInternAtom (xctx.dpy, astr, true); + sprintf(astr, "_NET_WM_CM_S%i", win->cur_screen); + cm_sel = XInternAtom(xctx.dpy, astr, true); if (settings.corner_radius != 0 && XGetSelectionOwner(xctx.dpy, cm_sel) == None) x_win_round_corners(win, dim->corner_radius); else From 85ea8b8aa86dee14b40b4ef3e1a311871da339a1 Mon Sep 17 00:00:00 2001 From: Nikita Zlobin Date: Wed, 20 May 2020 21:10:45 +0500 Subject: [PATCH 13/16] Separate some functions --- src/draw.c | 40 ++++++++++++++++++++++++---------------- src/x11/x.c | 37 +++++++++++++++++++++++-------------- 2 files changed, 47 insertions(+), 30 deletions(-) diff --git a/src/draw.c b/src/draw.c index 7e11e11..ada575d 100644 --- a/src/draw.c +++ b/src/draw.c @@ -388,6 +388,29 @@ static int layout_get_height(struct colored_layout *cl) return MAX(h, h_icon); } +/* Attempt to make internal radius more organic. + * Simple r-w is not enough for too small r/w ratio. + * simplifications: r/2 == r - w + w*w / (r * 2) with (w == r) + * r, w - corner radius & frame width, + * h - box height + */ +static int frame_internal_radius (int r, int w, int h) +{ + // Integer precision scaler, using 1/4 of int size + const int s = 2 << (8 * sizeof(int) / 4); + + int r1, r2, ret; + h *= s; + r *= s; + w *= s; + r1 = r - w + w * w / (r * 2); // w < r + r2 = r * h / (h + (w - r) * 2); // w >= r + + ret = (r > w) ? r1 : (r / 2 < r2) ? r / 2 : r2; + + return ret / s; +} + /** * Create a path on the given cairo context to draw the background of a notification. * The top corners will get rounded by `corner_radius`, if `first` is set. @@ -485,22 +508,7 @@ static cairo_surface_t *render_background(cairo_surface_t *srf, else height -= settings.separator_height; - /* Attempt to make internal radius more organic. - * Simple r-w is not enough for too small r/w ratio. - * simplifications: r/2 == r - w + w*w / (r * 2) with (w == r) - **/ - { const int s = 2 << (sizeof(int) * 8 / 4); // Integer precision scaler - int h, w, r, r1, r2; - - h = s * height; - r = s * corner_radius; - w = s * settings.frame_width; - r1 = r - w + w * w / (r * 2); // w < r; - r2 = r * h / (h + (w - r) * 2); // w >= r - - radius_int = (r > w) ? r1 : (r / 2 < r2) ? r / 2 : r2; - radius_int /= s; - } + radius_int = frame_internal_radius (corner_radius, settings.frame_width, height); } cairo_set_source_rgb(c, cl->bg.r, cl->bg.g, cl->bg.b); diff --git a/src/x11/x.c b/src/x11/x.c index 0fb95c5..b6eb819 100644 --- a/src/x11/x.c +++ b/src/x11/x.c @@ -133,11 +133,31 @@ static void x_win_round_corners(struct window_x11 *win, const int rad) win->xwin, ShapeNotifyMask); } -void x_display_surface(cairo_surface_t *srf, struct window_x11 *win, const struct dimensions *dim) +static void x_win_corners_unshape(struct window_x11 *win) +{ + XRectangle rect = { + .x = 0, + .y = 0, + .width = win->dim.w, + .height = win->dim.h }; + XShapeCombineRectangles(xctx.dpy, win->xwin, ShapeBounding, 0, 0, &rect, 1, ShapeSet, 1); + XShapeSelectInput(xctx.dpy, + win->xwin, ShapeNotifyMask); +} + +static bool x_win_composited(struct window_x11 *win) { char astr[sizeof("_NET_WM_CM_S") / sizeof(char) + 8]; Atom cm_sel; + sprintf(astr, "_NET_WM_CM_S%i", win->cur_screen); + cm_sel = XInternAtom(xctx.dpy, astr, true); + + return XGetSelectionOwner(xctx.dpy, cm_sel) != None; +} + +void x_display_surface(cairo_surface_t *srf, struct window_x11 *win, const struct dimensions *dim) +{ x_win_move(win, dim->x, dim->y, dim->w, dim->h); cairo_xlib_surface_set_size(win->root_surface, dim->w, dim->h); @@ -148,21 +168,10 @@ void x_display_surface(cairo_surface_t *srf, struct window_x11 *win, const struc cairo_paint(win->c_ctx); cairo_show_page(win->c_ctx); - sprintf(astr, "_NET_WM_CM_S%i", win->cur_screen); - cm_sel = XInternAtom(xctx.dpy, astr, true); - if (settings.corner_radius != 0 && XGetSelectionOwner(xctx.dpy, cm_sel) == None) x_win_round_corners(win, dim->corner_radius); + if (settings.corner_radius != 0 && ! x_win_composited(win)) else - { - XRectangle rect = { - .x = 0, - .y = 0, - .width = dim->w, - .height = dim->h }; - XShapeCombineRectangles(xctx.dpy, win->xwin, ShapeBounding, 0, 0, &rect, 1, ShapeSet, 1); - XShapeSelectInput(xctx.dpy, - win->xwin, ShapeNotifyMask); - } + x_win_corners_unshape(win); XFlush(xctx.dpy); From 73b7176e0bb074c10f50f67d7f088041632cc153 Mon Sep 17 00:00:00 2001 From: Nikita Zlobin Date: Wed, 20 May 2020 21:15:01 +0500 Subject: [PATCH 14/16] Reuse draw_rounded_rect() for xshape drawing --- src/draw.c | 2 +- src/draw.h | 2 ++ src/x11/x.c | 15 ++++----------- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/draw.c b/src/draw.c index ada575d..14dfd8b 100644 --- a/src/draw.c +++ b/src/draw.c @@ -416,7 +416,7 @@ static int frame_internal_radius (int r, int w, int h) * The top corners will get rounded by `corner_radius`, if `first` is set. * Respectably the same for `last` with the bottom corners. */ -static void draw_rounded_rect(cairo_t *c, int x, int y, int width, int height, int corner_radius, bool first, bool last) +void draw_rounded_rect(cairo_t *c, int x, int y, int width, int height, int corner_radius, bool first, bool last) { const float degrees = M_PI / 180.0; diff --git a/src/draw.h b/src/draw.h index d646dc2..be7a467 100644 --- a/src/draw.h +++ b/src/draw.h @@ -8,6 +8,8 @@ void draw_setup(void); void draw(void); +void draw_rounded_rect(cairo_t *c, int x, int y, int width, int height, int corner_radius, bool first, bool last); + void draw_deinit(void); #endif diff --git a/src/x11/x.c b/src/x11/x.c index b6eb819..b82f481 100644 --- a/src/x11/x.c +++ b/src/x11/x.c @@ -89,11 +89,6 @@ static void x_win_round_corners(struct window_x11 *win, const int rad) { const int width = win->dim.w; const int height = win->dim.h; - unsigned const int coords[] = { - 0 + rad, - width - rad, - height - rad, - }; Pixmap mask; cairo_surface_t * cxbm; @@ -112,12 +107,10 @@ static void x_win_round_corners(struct window_x11 *win, const int rad) cairo_paint(cr); cairo_set_source_rgba(cr, 1, 1, 1, 1); - cairo_new_path(cr); - cairo_arc(cr, coords[0], coords[0], rad, M_PI, -M_PI_2); - cairo_arc(cr, coords[1], coords[0], rad, -M_PI_2, 0); - cairo_arc(cr, coords[1], coords[2], rad, 0, M_PI_2); - cairo_arc(cr, coords[0], coords[2], rad, M_PI_2, M_PI); - cairo_close_path(cr); + draw_rounded_rect(cr, 0, 0, + width, height, + rad, + true, true); cairo_fill(cr); cairo_show_page(cr); From 10c82ed7fe9be96cc79e07302b2046c0ca957f47 Mon Sep 17 00:00:00 2001 From: Nikita Zlobin Date: Wed, 20 May 2020 21:16:31 +0500 Subject: [PATCH 15/16] Rename x_win_round_corners() to x_win_corners_shape() It's all job is to feel proper X11 shape. --- src/x11/x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/x11/x.c b/src/x11/x.c index b82f481..d5b15d7 100644 --- a/src/x11/x.c +++ b/src/x11/x.c @@ -85,7 +85,7 @@ static void x_win_move(struct window_x11 *win, int x, int y, int width, int heig } } -static void x_win_round_corners(struct window_x11 *win, const int rad) +static void x_win_corners_shape(struct window_x11 *win, const int rad) { const int width = win->dim.w; const int height = win->dim.h; @@ -161,8 +161,8 @@ void x_display_surface(cairo_surface_t *srf, struct window_x11 *win, const struc cairo_paint(win->c_ctx); cairo_show_page(win->c_ctx); - x_win_round_corners(win, dim->corner_radius); if (settings.corner_radius != 0 && ! x_win_composited(win)) + x_win_corners_shape(win, dim->corner_radius); else x_win_corners_unshape(win); From 2de1603cd204793eaa82ab37dc5dea689db505be Mon Sep 17 00:00:00 2001 From: Nikita Zlobin Date: Wed, 20 May 2020 21:19:04 +0500 Subject: [PATCH 16/16] style fix --- src/x11/x.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/x11/x.c b/src/x11/x.c index d5b15d7..772ae74 100644 --- a/src/x11/x.c +++ b/src/x11/x.c @@ -651,13 +651,10 @@ struct window_x11 *x_win_create(void) scr_n = DefaultScreen(xctx.dpy); root = RootWindow(xctx.dpy, scr_n); - if (XMatchVisualInfo(xctx.dpy, scr_n, 32, TrueColor, &vi)) - { + if (XMatchVisualInfo(xctx.dpy, scr_n, 32, TrueColor, &vi)) { vis = vi.visual; depth = vi.depth; - } - else - { + } else { vis = DefaultVisual(xctx.dpy, scr_n); depth = DefaultDepth(xctx.dpy, scr_n); }