From 36fb2b942a08d58290b1d6ea1aec6d01f8e096b7 Mon Sep 17 00:00:00 2001 From: Federico Angelilli Date: Mon, 13 Nov 2023 22:50:39 +0100 Subject: Render correctly 'circular' corners with `xcb-shape` --- x11.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) (limited to 'x11.c') diff --git a/x11.c b/x11.c index 551e7d7..9a13bd9 100644 --- a/x11.c +++ b/x11.c @@ -9,8 +9,9 @@ #include #include #include -#include #include +#include +#include #include "x11.h" #include "log.h" @@ -473,6 +474,53 @@ void window_resize(Window *win, int width, int height) wm_set_size(win); } +static void window_paint_corners(Window *win) +{ + // TODO: Actually make this a parameter + int radius = win->height / 2; + double degree = M_PI / 180.0; + + // TODO: Check this value + int depth = 1; + + xcb_pixmap_t bitmap = xcb_generate_id(win->connection); + xcb_create_pixmap(win->connection, depth, bitmap, win->window, win->width, win->height); + log_debug("Xcb pixmap created [id=%u]", bitmap); + + cairo_surface_t *surface = cairo_xcb_surface_create_for_bitmap(win->connection, + win->screen, + bitmap, + win->width, + win->height); + + cairo_t *cr = cairo_create(surface); + + 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); + + // TODO: Decouple somewhat drawing and X11 + cairo_set_source_rgba(cr, 1, 1, 1, 1); + cairo_arc(cr, radius, radius, radius, 90.0 * degree, 270 * degree); + cairo_arc(cr, win->width - radius, radius, radius, 270 * degree, 450 * degree); + cairo_fill(cr); + + log_debug("Xcb shape painted"); + + cairo_show_page(cr); + cairo_destroy(cr); + cairo_surface_flush(surface); + cairo_surface_destroy(surface); + + xcb_shape_mask(win->connection, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, win->window, 0, 0, bitmap); + xcb_shape_select_input(win->connection, win->window, XCB_SHAPE_NOTIFY); + log_debug("Xcb shape mask configured"); + + xcb_free_pixmap(win->connection, bitmap); +} + void window_paint_surface(Window *win, cairo_surface_t *surface, int width, int height) { cairo_xcb_surface_set_size(win->surface, width, height); @@ -482,6 +530,8 @@ void window_paint_surface(Window *win, cairo_surface_t *surface, int width, int cairo_paint(win->cr); cairo_show_page(win->cr); + window_paint_corners(win); + xcb_circulate_window(win->connection, XCB_CIRCULATE_RAISE_LOWEST, win->window); xcb_flush(win->connection); } -- cgit v1.2.3