From 85ea8b8aa86dee14b40b4ef3e1a311871da339a1 Mon Sep 17 00:00:00 2001 From: Nikita Zlobin Date: Wed, 20 May 2020 21:10:45 +0500 Subject: [PATCH] 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);