]> git.lizzy.rs Git - bspwm.git/commitdiff
bspwm: port rounded corners patch to latest version master
authorDylan Araps <dylan.araps@gmail.com>
Mon, 23 Sep 2019 15:24:25 +0000 (18:24 +0300)
committerElias Fleckenstein <eliasfleckenstein@web.de>
Sat, 30 Jul 2022 18:14:16 +0000 (20:14 +0200)
src/messages.c
src/query.c
src/settings.c
src/settings.h
src/tree.c
src/types.h
src/window.c
src/window.h

index c3a42014db6e2f25bd7fd42cdf03ddd25de4f802..66e78c7754e721e122a9c29755403bed4364d026 100644 (file)
@@ -1494,6 +1494,13 @@ void set_setting(coordinates_t loc, char *name, char *value, FILE *rsp)
                        return;
                }
                SET_DEF_DEFMON_DEFDESK_WIN(border_width, bw)
+       } else if (streq("border_radius", name)) {
+               unsigned int br;
+               if (sscanf(value, "%u", &br) != 1) {
+                       fail(rsp, "config: %s: Invalid value: '%s'.\n", name, value);
+                       return;
+               }
+               SET_DEF_DEFMON_DEFDESK_WIN(border_radius, br)
 #undef SET_DEF_DEFMON_DEFDESK_WIN
 #define SET_DEF_DEFMON_DESK(k, v) \
                if (loc.desktop != NULL) { \
@@ -1512,6 +1519,21 @@ void set_setting(coordinates_t loc, char *name, char *value, FILE *rsp)
                                } \
                        } \
                }
+       } else if (streq("border_radius", name)) {
+               if (loc.node != NULL) {
+                       for (node_t *n = first_extrema(loc.node); n != NULL; n = next_leaf(n, loc.node)) {
+                               if (n->client != NULL) {
+                                       fprintf(rsp, "%u", n->client->border_radius);
+                                       break;
+                               }
+                       }
+               } else if (loc.desktop != NULL) {
+                       fprintf(rsp, "%u", loc.desktop->border_radius);
+               } else if (loc.monitor != NULL) {
+                       fprintf(rsp, "%u", loc.monitor->border_radius);
+               } else {
+                       fprintf(rsp, "%u", border_radius);
+               }
        } else if (streq("window_gap", name)) {
                int wg;
                if (sscanf(value, "%i", &wg) != 1) {
index aaaf3eec94ec90d0997866e0d23a30135df0f92b..a3f906ebaef8e9731f379f52a49de0382dd5035d 100644 (file)
@@ -76,6 +76,7 @@ void query_monitor(monitor_t *m, FILE *rsp)
        fprintf(rsp, "\"stickyCount\":%i,", m->sticky_count);
        fprintf(rsp, "\"windowGap\":%i,", m->window_gap);
        fprintf(rsp, "\"borderWidth\":%u,", m->border_width);
+       fprintf(rsp, "\"borderRadius\":%u,", m->border_radius);
        fprintf(rsp, "\"focusedDesktopId\":%u,", m->desk->id);
        fprintf(rsp, "\"padding\":");
        query_padding(m->padding, rsp);
@@ -104,6 +105,7 @@ void query_desktop(desktop_t *d, FILE *rsp)
        fprintf(rsp, "\"userLayout\":\"%s\",", LAYOUT_STR(d->user_layout));
        fprintf(rsp, "\"windowGap\":%i,", d->window_gap);
        fprintf(rsp, "\"borderWidth\":%u,", d->border_width);
+       fprintf(rsp, "\"borderRadius\":%u,", d->border_radius);
        fprintf(rsp, "\"focusedNodeId\":%u,", d->focus != NULL ? d->focus->id : 0);
        fprintf(rsp, "\"padding\":");
        query_padding(d->padding, rsp);
@@ -167,6 +169,7 @@ void query_client(client_t *c, FILE *rsp)
                fprintf(rsp, "\"className\":\"%s\",", c->class_name);
                fprintf(rsp, "\"instanceName\":\"%s\",", c->instance_name);
                fprintf(rsp, "\"borderWidth\":%u,", c->border_width);
+               fprintf(rsp, "\"borderRadius\":%u,", c->border_radius);
                fprintf(rsp, "\"state\":\"%s\",", STATE_STR(c->state));
                fprintf(rsp, "\"lastState\":\"%s\",", STATE_STR(c->last_state));
                fprintf(rsp, "\"layer\":\"%s\",", LAYER_STR(c->layer));
index 52358f7a29c52025b1fdcc25a27c4a847b0148f3..f18465149a2b682bd3e7e48ba6e02df12e2ba343 100644 (file)
@@ -40,6 +40,7 @@ padding_t padding;
 padding_t monocle_padding;
 int window_gap;
 unsigned int border_width;
+unsigned int border_radius;
 double split_ratio;
 child_polarity_t initial_polarity;
 automatic_scheme_t automatic_scheme;
@@ -101,6 +102,7 @@ void load_settings(void)
        monocle_padding = (padding_t) MONOCLE_PADDING;
        window_gap = WINDOW_GAP;
        border_width = BORDER_WIDTH;
+       border_radius = BORDER_RADIUS;
        split_ratio = SPLIT_RATIO;
        initial_polarity = SECOND_CHILD;
        automatic_scheme = AUTOMATIC_SCHEME;
index 248860d08f827c277c68ae958d7b6cf2479f1cb6..04c4b4b72e9239625d487fb8c72d809be5a4ce1c 100644 (file)
@@ -41,6 +41,7 @@
 #define MONOCLE_PADDING      {0, 0, 0, 0}
 #define WINDOW_GAP           6
 #define BORDER_WIDTH         1
+#define BORDER_RADIUS        0
 #define SPLIT_RATIO          0.5
 #define AUTOMATIC_SCHEME     SCHEME_LONGEST_SIDE
 #define REMOVAL_ADJUSTMENT   true
@@ -80,6 +81,7 @@ extern padding_t padding;
 extern padding_t monocle_padding;
 extern int window_gap;
 extern unsigned int border_width;
+extern unsigned int border_radius;
 extern double split_ratio;
 extern child_polarity_t initial_polarity;
 extern automatic_scheme_t automatic_scheme;
index db8208d86860680314c5f7338a8c3a3fa777407d..c3f84703b0e27db35656d3f1b80123a67d8f77ab 100644 (file)
@@ -83,6 +83,7 @@ void apply_layout(monitor_t *m, desktop_t *d, node_t *n, xcb_rectangle_t rect, x
        }
 
        if (is_leaf(n)) {
+        unsigned int br = 0;
 
                if (n->client == NULL) {
                        return;
@@ -119,9 +120,12 @@ void apply_layout(monitor_t *m, desktop_t *d, node_t *n, xcb_rectangle_t rect, x
                                }
                        }
                        n->client->tiled_rectangle = r;
+            if (!gapless_monocle || 1 != LAYOUT_MONOCLE)
+                br = n->client->border_radius;
                /* floating clients */
                } else if (s == STATE_FLOATING) {
                        r = n->client->floating_rectangle;
+            br = n->client->border_radius;
                /* fullscreen clients */
                } else {
                        r = m->rectangle;
@@ -132,12 +136,15 @@ void apply_layout(monitor_t *m, desktop_t *d, node_t *n, xcb_rectangle_t rect, x
 
                if (!rect_eq(r, cr)) {
                        window_move_resize(n->id, r.x, r.y, r.width, r.height);
+            window_rounded_border(n);
                        if (!grabbing) {
                                put_status(SBSC_MASK_NODE_GEOMETRY, "node_geometry 0x%08X 0x%08X 0x%08X %ux%u+%i+%i\n", m->id, d->id, n->id, r.width, r.height, r.x, r.y);
                        }
                }
 
                window_border_width(n->id, bw);
+        window_border_radius(n->client, br);
+        window_rounded_border(n);
 
        } else {
                xcb_rectangle_t first_rect;
@@ -743,8 +750,10 @@ client_t *make_client(void)
        snprintf(c->class_name, sizeof(c->class_name), "%s", MISSING_VALUE);
        snprintf(c->instance_name, sizeof(c->instance_name), "%s", MISSING_VALUE);
        c->border_width = border_width;
+       c->border_radius = border_radius;
        c->urgent = false;
        c->shown = false;
+    c->sets_own_shape = false;
        c->wm_flags = 0;
        c->icccm_props.input_hint = true;
        c->icccm_props.take_focus = false;
index c11b591c7eb4d33ba147a0d0bc621deadeca0779..8fc8eb6afc20cf877295b770799be6cf64f86793 100644 (file)
@@ -216,8 +216,11 @@ typedef struct {
        char instance_name[MAXLEN];
        char name[MAXLEN];
        unsigned int border_width;
+    unsigned int border_radius;
+    unsigned int drawn_border_radius;
        bool urgent;
        bool shown;
+    bool sets_own_shape;
        client_state_t state;
        client_state_t last_state;
        stack_layer_t layer;
@@ -283,6 +286,7 @@ struct desktop_t {
        padding_t padding;
        int window_gap;
        unsigned int border_width;
+       unsigned int border_radius;
 };
 
 typedef struct monitor_t monitor_t;
@@ -296,6 +300,7 @@ struct monitor_t {
        unsigned int sticky_count;
        int window_gap;
        unsigned int border_width;
+       unsigned int border_radius;
        xcb_rectangle_t rectangle;
        desktop_t *desk;
        desktop_t *desk_head;
index cd2340dfd19bf6024f37abd1e1678b8a20cfe1ea..1b9aa368414787b5b0a1e0777f420c96c07bbb13 100644 (file)
@@ -41,6 +41,8 @@
 #include "parse.h"
 #include "window.h"
 
+#include <xcb/shape.h>
+
 void schedule_window(xcb_window_t win)
 {
        coordinates_t loc;
@@ -137,10 +139,21 @@ bool manage_window(xcb_window_t win, rule_consequence_t *csq, int fd)
        node_t *n = make_node(win);
        client_t *c = make_client();
        c->border_width = csq->border ? d->border_width : 0;
+    c->border_radius = d->border_radius;
        n->client = c;
        initialize_client(n);
        initialize_floating_rectangle(n);
 
+       xcb_shape_query_extents_reply_t* ext = xcb_shape_query_extents_reply(dpy, xcb_shape_query_extents(dpy, n->id), NULL);
+
+       n->client->sets_own_shape = false;
+       if (ext != NULL) {
+         n->client->sets_own_shape = ext->bounding_shaped || ext->clip_shaped;
+
+         free(ext);
+       }
+       fprintf(stderr, "sets shape: %d\n", n->client->sets_own_shape);
+
        if (csq->rect != NULL) {
                c->floating_rectangle = *csq->rect;
                free(csq->rect);
@@ -204,6 +217,8 @@ bool manage_window(xcb_window_t win, rule_consequence_t *csq, int fd)
                hide_node(d, n);
        }
 
+    window_rounded_border(n);
+
        ewmh_update_client_list(false);
        ewmh_set_wm_desktop(n, d);
 
@@ -324,6 +339,8 @@ void draw_presel_feedback(monitor_t *m, desktop_t *d, node_t *n)
        window_move_resize(p->feedback, n->rectangle.x + presel_rect.x, n->rectangle.y + presel_rect.y,
                           presel_rect.width, presel_rect.height);
 
+    window_rounded_border(n);
+
        if (!exists && m->desk == d) {
                window_show(p->feedback);
        }
@@ -416,6 +433,101 @@ void draw_border(node_t *n, bool focused_node, bool focused_monitor)
        }
 }
 
+void window_rounded_border(node_t *n)
+{
+    xcb_window_t win = n->id;
+    unsigned int radius = n->client->drawn_border_radius;
+
+    // Check for compatibility
+    const xcb_query_extension_reply_t *shape_query;
+
+    shape_query = xcb_get_extension_data (dpy, &xcb_shape_id);
+    if (!shape_query->present) return;
+
+    if (n->client->sets_own_shape) return;
+
+    // get geometry
+       xcb_get_geometry_reply_t *geo = xcb_get_geometry_reply(dpy, xcb_get_geometry(dpy, win), NULL);
+    if (geo == NULL) return;
+
+    uint16_t x  = geo->x;
+    uint16_t y  = geo->y;
+       uint16_t w  = geo->width;
+    uint16_t h  = geo->height;
+    uint16_t bw = geo->border_width;
+       uint16_t ow  = w+2*bw;
+       uint16_t oh  = h+2*bw;
+
+       free(geo);
+
+    xcb_pixmap_t bpid = xcb_generate_id(dpy);
+    xcb_pixmap_t cpid = xcb_generate_id(dpy);
+
+    xcb_create_pixmap(dpy, 1, bpid, win, ow, oh);
+    xcb_create_pixmap(dpy, 1, cpid, win, w, h);
+
+    xcb_gcontext_t black = xcb_generate_id(dpy);
+    xcb_gcontext_t white = xcb_generate_id(dpy);
+
+    xcb_create_gc(dpy, black, bpid, XCB_GC_FOREGROUND, (uint32_t[]){0, 0});
+    xcb_create_gc(dpy, white, bpid, XCB_GC_FOREGROUND, (uint32_t[]){1, 0});
+
+    int32_t rad, dia;
+    rad = radius;
+
+    rad += bw; dia = rad*2-1;
+
+    xcb_arc_t barcs[] = {
+        { -1,     -1,     dia, dia, 0, 360 << 6 },
+        { -1,     oh-dia, dia, dia, 0, 360 << 6 },
+        { ow-dia, -1,     dia, dia, 0, 360 << 6 },
+        { ow-dia, oh-dia, dia, dia, 0, 360 << 6 },
+    };
+    xcb_rectangle_t brects[] = {
+        { rad, 0, ow-dia, oh },
+        { 0, rad, ow, oh-dia },
+    };
+
+    rad -= bw; dia = rad*2-1;
+
+    xcb_arc_t carcs[] = {
+        { -1,    -1,    dia, dia, 0, 360 << 6 },
+        { -1,    h-dia, dia, dia, 0, 360 << 6 },
+        { w-dia, -1,    dia, dia, 0, 360 << 6 },
+        { w-dia, h-dia, dia, dia, 0, 360 << 6 },
+    };
+    xcb_rectangle_t crects[] = {
+        { rad, 0, w-dia, h },
+        { 0, rad, w, h-dia },
+    };
+
+    xcb_rectangle_t bounding = {0, 0, w+2*bw, h+2*bw};
+    xcb_poly_fill_rectangle(dpy, bpid, black, 1, &bounding);
+    xcb_poly_fill_rectangle(dpy, bpid, white, 2, brects);
+    xcb_poly_fill_arc(dpy, bpid, white, 4, barcs);
+
+    xcb_rectangle_t clipping = {0, 0, w, h};
+    xcb_poly_fill_rectangle(dpy, cpid, black, 1, &clipping);
+    xcb_poly_fill_rectangle(dpy, cpid, white, 2, crects);
+    xcb_poly_fill_arc(dpy, cpid, white, 4, carcs);
+
+    xcb_shape_mask(dpy, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING,  win, -bw, -bw, bpid);
+    xcb_shape_mask(dpy, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_CLIP, win, 0, 0, cpid);
+
+    if (n->presel != NULL && n->presel != XCB_NONE) {
+        xcb_window_t fb = n->presel->feedback;
+        xcb_get_geometry_reply_t *fb_geo = xcb_get_geometry_reply(dpy, xcb_get_geometry(dpy, fb), NULL);
+
+        if (fb_geo != NULL) {
+            xcb_shape_mask(dpy, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, fb, x-fb_geo->x, y-fb_geo->y, bpid);
+            free(fb_geo);
+        }
+    }
+
+    xcb_free_pixmap(dpy, bpid);
+    xcb_free_pixmap(dpy, cpid);
+}
+
 void window_draw_border(xcb_window_t win, uint32_t border_color_pxl)
 {
        xcb_change_window_attributes(dpy, win, XCB_CW_BORDER_PIXEL, &border_color_pxl);
@@ -618,6 +730,7 @@ bool resize_client(coordinates_t *loc, resize_handle_t rh, int dx, int dy, bool
                n->client->floating_rectangle = (xcb_rectangle_t) {x, y, width, height};
                if (n->client->state == STATE_FLOATING) {
                        window_move_resize(n->id, x, y, width, height);
+            window_rounded_border(n);
 
                        if (!grabbing) {
                                put_status(SBSC_MASK_NODE_GEOMETRY, "node_geometry 0x%08X 0x%08X 0x%08X %ux%u+%i+%i\n", loc->monitor->id, loc->desktop->id, loc->node->id, width, height, x, y);
@@ -828,6 +941,11 @@ void window_border_width(xcb_window_t win, uint32_t bw)
        xcb_configure_window(dpy, win, XCB_CONFIG_WINDOW_BORDER_WIDTH, values);
 }
 
+void window_border_radius(client_t *cli, uint32_t br)
+{
+       cli->drawn_border_radius = br;
+}
+
 void window_move(xcb_window_t win, int16_t x, int16_t y)
 {
        uint32_t values[] = {x, y};
index 414ebea0100a343d2e8911453ed69b420df49fb4..79805cb42ae8ed238dcf5c88ad46fd0cb79b0b6d 100644 (file)
@@ -44,6 +44,7 @@ void hide_presel_feedbacks(monitor_t *m, desktop_t *d, node_t *n);
 void update_colors(void);
 void update_colors_in(node_t *n, desktop_t *d, monitor_t *m);
 void draw_border(node_t *n, bool focused_node, bool focused_monitor);
+void window_rounded_border(node_t *n);
 void window_draw_border(xcb_window_t win, uint32_t border_color_pxl);
 void adopt_orphans(void);
 uint32_t get_border_color(bool focused_node, bool focused_monitor);