diff options
| author | Federico Angelilli <code@fedang.net> | 2023-11-13 22:50:39 +0100 |
|---|---|---|
| committer | Federico Angelilli <code@fedang.net> | 2023-11-13 22:50:39 +0100 |
| commit | 36fb2b942a08d58290b1d6ea1aec6d01f8e096b7 (patch) | |
| tree | e1120c66a83611fe5a4735fd1a04b0f9fb14959d | |
| parent | 0581b5d5a3f892586e78f61f1398b811d589c501 (diff) | |
Render correctly 'circular' corners with `xcb-shape`
| -rw-r--r-- | Makefile | 3 | ||||
| -rw-r--r-- | x11.c | 52 |
2 files changed, 53 insertions, 2 deletions
@@ -6,8 +6,9 @@ DEPS = \ cairo \ xcb \ xcb-icccm \ - xcb-xrm \ xcb-ewmh \ + xcb-xrm \ + xcb-shape \ xcb-errors \ "xcb-randr >= 1.5" \ "glib-2.0 >= 2.44" \ @@ -9,8 +9,9 @@ #include <xcb/xcb_icccm.h> #include <xcb/xcb_ewmh.h> #include <xcb/xcb_xrm.h> -#include <xcb/randr.h> #include <xcb/xcb_errors.h> +#include <xcb/randr.h> +#include <xcb/shape.h> #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); } |
