From eb063627dc6d9f3fbc2cba31b46a8741b2261106 Mon Sep 17 00:00:00 2001 From: sewn Date: Tue, 20 Feb 2024 21:27:06 +0300 Subject: [PATCH] introduce bar patch --- bar/bar.patch | 880 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 880 insertions(+) create mode 100644 bar/bar.patch diff --git a/bar/bar.patch b/bar/bar.patch new file mode 100644 index 0000000..ba851e3 --- /dev/null +++ b/bar/bar.patch @@ -0,0 +1,880 @@ +From c57875c8ba5753f5ee43e0ee4b5d60e10cd329b2 Mon Sep 17 00:00:00 2001 +From: sewn +Date: Tue, 20 Feb 2024 19:08:03 +0300 +Subject: [PATCH] Implement dwm bar clone + +--- + Makefile | 2 +- + config.def.h | 26 +++- + dwl.c | 416 +++++++++++++++++++++++++++++++++++++++++++-------- + utf8.h | 55 +++++++ + 4 files changed, 427 insertions(+), 72 deletions(-) + create mode 100644 utf8.h + +diff --git a/Makefile b/Makefile +index 0822ddc..7cf7289 100644 +--- a/Makefile ++++ b/Makefile +@@ -9,7 +9,7 @@ DWLDEVCFLAGS = -g -pedantic -Wall -Wextra -Wdeclaration-after-statement -Wno-unu + -Werror=strict-prototypes -Werror=implicit -Werror=return-type -Werror=incompatible-pointer-types -Wfloat-conversion + + # CFLAGS / LDFLAGS +-PKGS = wlroots wayland-server xkbcommon libinput $(XLIBS) ++PKGS = wlroots wayland-server xkbcommon libinput pixman-1 fcft $(XLIBS) + DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) + LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(LIBS) + +diff --git a/config.def.h b/config.def.h +index 9009517..5fe6f9d 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -7,15 +7,23 @@ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ + static const unsigned int borderpx = 1; /* border pixel of windows */ +-static const float rootcolor[] = COLOR(0x222222ff); ++static const float rootcolor[] = COLOR(0x000000ff); + static const float bordercolor[] = COLOR(0x444444ff); + static const float focuscolor[] = COLOR(0x005577ff); + static const float urgentcolor[] = COLOR(0xff0000ff); + /* To conform the xdg-protocol, set the alpha to zero to restore the old behavior */ + static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ + ++/* bar */ ++static const char *fonts[] = {"monospace:size=10"}; ++static const char *fontattrs = "dpi=96"; ++static pixman_color_t normbarfg = { 0xbbbb, 0xbbbb, 0xbbbb, 0xffff }; ++static pixman_color_t normbarbg = { 0x2222, 0x2222, 0x2222, 0xffff }; ++static pixman_color_t selbarfg = { 0xeeee, 0xeeee, 0xeeee, 0xffff }; ++static pixman_color_t selbarbg = { 0x0000, 0x5555, 0x7777, 0xffff }; ++ + /* tagging - TAGCOUNT must be no greater than 31 */ +-#define TAGCOUNT (9) ++static char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + + /* logging */ + static int log_level = WLR_ERROR; +@@ -165,7 +173,15 @@ static const Key keys[] = { + }; + + static const Button buttons[] = { +- { MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} }, +- { MODKEY, BTN_MIDDLE, togglefloating, {0} }, +- { MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} }, ++ { ClkLtSymbol, 0, BTN_LEFT, setlayout, {.v = &layouts[0]} }, ++ { ClkLtSymbol, 0, BTN_RIGHT, setlayout, {.v = &layouts[2]} }, ++ { ClkTitle, 0, BTN_MIDDLE, zoom, {0} }, ++ { ClkStatus, 0, BTN_MIDDLE, spawn, {.v = termcmd} }, ++ { ClkClient, MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} }, ++ { ClkClient, MODKEY, BTN_MIDDLE, togglefloating, {0} }, ++ { ClkClient, MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} }, ++ { ClkTagBar, 0, BTN_LEFT, view, {0} }, ++ { ClkTagBar, 0, BTN_RIGHT, toggleview, {0} }, ++ { ClkTagBar, MODKEY, BTN_LEFT, tag, {0} }, ++ { ClkTagBar, MODKEY, BTN_RIGHT, toggletag, {0} }, + }; +diff --git a/dwl.c b/dwl.c +index fa76db2..4b5ab49 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -53,7 +54,10 @@ + #include + #include + #include ++#include + #include ++#include ++#include + #include + #ifdef XWAYLAND + #include +@@ -62,6 +66,7 @@ + #endif + + #include "util.h" ++#include "utf8.h" + + /* macros */ + #define MAX(A, B) ((A) > (B) ? (A) : (B)) +@@ -71,14 +76,16 @@ + #define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags])) + #define LENGTH(X) (sizeof X / sizeof X[0]) + #define END(A) ((A) + LENGTH(A)) +-#define TAGMASK ((1u << TAGCOUNT) - 1) ++#define TAGMASK ((1u << LENGTH(tags)) - 1) + #define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L))) + #define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0) ++#define TEXTW(text) (draw_text(NULL, 0, 0, 0, 0, 0, text, NULL) + lrpad) + + /* enums */ + enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ + enum { XDGShell, LayerShell, X11 }; /* client types */ + enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrFS, LyrTop, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */ ++enum { ClkTagBar, ClkLtSymbol, ClkStatus, ClkTitle, ClkClient, ClkRoot }; /* clicks */ + #ifdef XWAYLAND + enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar, + NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */ +@@ -92,6 +99,7 @@ typedef union { + } Arg; + + typedef struct { ++ unsigned int click; + unsigned int mod; + unsigned int button; + void (*func)(const Arg *); +@@ -185,6 +193,7 @@ struct Monitor { + struct wl_list link; + struct wlr_output *wlr_output; + struct wlr_scene_output *scene_output; ++ struct wlr_scene_buffer *scene_buffer; /* bar buffer */ + struct wlr_scene_rect *fullscreen_bg; /* See createmon() for info */ + struct wl_listener frame; + struct wl_listener destroy; +@@ -192,6 +201,7 @@ struct Monitor { + struct wl_listener destroy_lock_surface; + struct wlr_session_lock_surface_v1 *lock_surface; + struct wlr_box m; /* monitor area, layout-relative */ ++ struct wlr_box b; /* bar area */ + struct wlr_box w; /* window area, layout-relative */ + struct wl_list layers[4]; /* LayerSurface.link */ + const Layout *lt[2]; +@@ -202,8 +212,15 @@ struct Monitor { + int gamma_lut_changed; + int nmaster; + char ltsymbol[16]; ++ + }; + ++typedef struct { ++ struct wlr_buffer base; ++ size_t stride; ++ uint32_t data[]; ++} Buffer; ++ + typedef struct { + const char *name; + float mfact; +@@ -239,6 +256,10 @@ static void arrangelayer(Monitor *m, struct wl_list *list, + struct wlr_box *usable_area, int exclusive); + static void arrangelayers(Monitor *m); + static void axisnotify(struct wl_listener *listener, void *data); ++static bool bar_accepts_input(struct wlr_scene_buffer *buffer, double *sx, double *sy); ++static void buffer_destroy(struct wlr_buffer *buffer); ++static bool buffer_begin_data_ptr_access(struct wlr_buffer *buffer, uint32_t flags, void **data, uint32_t *format, size_t *stride); ++static void buffer_end_data_ptr_access(struct wlr_buffer *buffer); + static void buttonpress(struct wl_listener *listener, void *data); + static void chvt(const Arg *arg); + static void checkidleinhibitor(struct wlr_surface *exclude); +@@ -266,6 +287,10 @@ static void destroynotify(struct wl_listener *listener, void *data); + static void destroysessionlock(struct wl_listener *listener, void *data); + static void destroysessionmgr(struct wl_listener *listener, void *data); + static Monitor *dirtomon(enum wlr_direction dir); ++static void drawbar(Monitor *m); ++static void drawbars(void); ++static uint32_t draw_text(pixman_image_t *pix, int x, int y, unsigned int w, unsigned int h, ++ unsigned int lpad, const char *text, pixman_color_t *clr); + static void focusclient(Client *c, int lift); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); +@@ -293,7 +318,6 @@ static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int + static void outputmgrtest(struct wl_listener *listener, void *data); + static void pointerfocus(Client *c, struct wlr_surface *surface, + double sx, double sy, uint32_t time); +-static void printstatus(void); + static void quit(const Arg *arg); + static void rendermon(struct wl_listener *listener, void *data); + static void requestdecorationmode(struct wl_listener *listener, void *data); +@@ -314,6 +338,7 @@ static void setsel(struct wl_listener *listener, void *data); + static void setup(void); + static void spawn(const Arg *arg); + static void startdrag(struct wl_listener *listener, void *data); ++static int status_in(int fd, unsigned int mask, void *data); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *m); +@@ -388,6 +413,17 @@ static struct wlr_box sgeom; + static struct wl_list mons; + static Monitor *selmon; + ++static struct fcft_font *font; ++static int bh; ++static int lrpad; ++static char stext[256]; ++ ++static const struct wlr_buffer_impl buffer_impl = { ++ .destroy = buffer_destroy, ++ .begin_data_ptr_access = buffer_begin_data_ptr_access, ++ .end_data_ptr_access = buffer_end_data_ptr_access ++}; ++ + #ifdef XWAYLAND + static void activatex11(struct wl_listener *listener, void *data); + static void associatex11(struct wl_listener *listener, void *data); +@@ -514,6 +550,9 @@ arrangelayers(Monitor *m) + if (!m->wlr_output->enabled) + return; + ++ usable_area.height -= m->b.height; ++ usable_area.y += m->b.height; ++ + /* Arrange exclusive surfaces from top->bottom */ + for (i = 3; i >= 0; i--) + arrangelayer(m, &m->layers[i], &usable_area, 1); +@@ -556,17 +595,76 @@ axisnotify(struct wl_listener *listener, void *data) + event->delta_discrete, event->source); + } + ++bool ++bar_accepts_input(struct wlr_scene_buffer *buffer, double *sx, double *sy) ++{ ++ return true; ++} ++ ++void ++buffer_destroy(struct wlr_buffer *wlr_buffer) ++{ ++ Buffer *buf; ++ buf = wl_container_of(wlr_buffer, buf, base); ++ free(buf); ++} ++ ++bool ++buffer_begin_data_ptr_access(struct wlr_buffer *wlr_buffer, uint32_t flags, ++ void **data, uint32_t *format, size_t *stride) ++{ ++ Buffer *buf; ++ buf = wl_container_of(wlr_buffer, buf, base); ++ ++ if (flags & WLR_BUFFER_DATA_PTR_ACCESS_WRITE) return false; ++ ++ *data = buf->data; ++ *stride = buf->stride; ++ *format = DRM_FORMAT_ARGB8888; ++ ++ return true; ++} ++ ++void buffer_end_data_ptr_access(struct wlr_buffer *buffer) { ++} ++ + void + buttonpress(struct wl_listener *listener, void *data) + { ++ unsigned int i = 0, x = 0; ++ unsigned int click; + struct wlr_pointer_button_event *event = data; + struct wlr_keyboard *keyboard; ++ struct wlr_scene_node *node; ++ struct wlr_scene_buffer *buffer; + uint32_t mods; ++ Arg arg = {0}; + Client *c; + const Button *b; + + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); + ++ click = ClkRoot; ++ xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL); ++ if (c) ++ click = ClkClient; ++ ++ if ((node = wlr_scene_node_at(&layers[LyrBottom]->node, cursor->x, cursor->y, NULL, NULL)) && ++ ((buffer = wlr_scene_buffer_from_node(node)) && buffer == selmon->scene_buffer)) { ++ do ++ x += TEXTW(tags[i]); ++ while (cursor->x >= x && ++i < LENGTH(tags)); ++ if (i < LENGTH(tags)) { ++ click = ClkTagBar; ++ arg.ui = 1 << i; ++ } else if (cursor->x < x + TEXTW(selmon->ltsymbol)) ++ click = ClkLtSymbol; ++ else if (cursor->x > selmon->w.width - (int)TEXTW(stext)) ++ click = ClkStatus; ++ else ++ click = ClkTitle; ++ } ++ + switch (event->state) { + case WLR_BUTTON_PRESSED: + cursor_mode = CurPressed; +@@ -575,16 +673,14 @@ buttonpress(struct wl_listener *listener, void *data) + break; + + /* Change focus if the button was _pressed_ over a client */ +- xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL); +- if (c && (!client_is_unmanaged(c) || client_wants_focus(c))) ++ if (click == ClkClient && (!client_is_unmanaged(c) || client_wants_focus(c))) + focusclient(c, 1); + + keyboard = wlr_seat_get_keyboard(seat); + mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; + for (b = buttons; b < END(buttons); b++) { +- if (CLEANMASK(mods) == CLEANMASK(b->mod) && +- event->button == b->button && b->func) { +- b->func(&b->arg); ++ if (CLEANMASK(mods) == CLEANMASK(b->mod) && event->button == b->button && click == b->click && b->func) { ++ b->func(click == ClkTagBar && b->arg.i == 0 ? &arg : &b->arg); + return; + } + } +@@ -658,6 +754,9 @@ cleanup(void) + /* Destroy after the wayland display (when the monitors are already destroyed) + to avoid destroying them with an invalid scene output. */ + wlr_scene_node_destroy(&scene->tree.node); ++ ++ fcft_destroy(font); ++ fcft_fini(); + } + + void +@@ -709,7 +808,7 @@ closemon(Monitor *m) + setmon(c, selmon, c->tags); + } + focusclient(focustop(selmon), 1); +- printstatus(); ++ drawbars(); + } + + void +@@ -895,8 +994,13 @@ createmon(struct wl_listener *listener, void *data) + wlr_output_commit_state(wlr_output, &state); + wlr_output_state_finish(&state); + ++ m->scene_buffer = wlr_scene_buffer_create(layers[LyrBottom], NULL); ++ m->scene_buffer->point_accepts_input = bar_accepts_input; ++ m->b.width = m->wlr_output->width; ++ m->b.height = bh; ++ + wl_list_insert(&mons, &m->link); +- printstatus(); ++ drawbars(); + + /* The xdg-protocol specifies: + * +@@ -1165,6 +1269,178 @@ dirtomon(enum wlr_direction dir) + return selmon; + } + ++static uint32_t ++draw_text(pixman_image_t *pix, int x, int y, unsigned int w, unsigned int h, ++ unsigned int lpad, const char *text, pixman_color_t *clr) ++{ ++ int ty; ++ int render = x || y || w || h; ++ long x_kern; ++ uint32_t cp, last_cp = 0; ++ uint32_t state = UTF8_ACCEPT; ++ pixman_image_t *clr_pix = NULL; ++ const struct fcft_glyph *glyph; ++ ++ if ((render && (!clr || !w)) || !text || !font) ++ return 0; ++ ++ if (!render) { ++ w = -1; ++ } else { ++ clr_pix = pixman_image_create_solid_fill(clr); ++ ++ x += lpad; ++ w -= lpad; ++ } ++ ++ for (const char *p = text; *p; p++) { ++ if (utf8decode(&state, &cp, *p)) ++ continue; ++ ++ glyph = fcft_rasterize_char_utf32(font, cp, FCFT_SUBPIXEL_NONE); ++ if (!glyph) ++ continue; ++ ++ x_kern = 0; ++ if (last_cp) ++ fcft_kerning(font, last_cp, cp, &x_kern, NULL); ++ last_cp = cp; ++ ++ if ((x_kern + glyph->advance.x) > w) ++ break; ++ ++ x += x_kern; ++ ++ if (render) { ++ ty = y + (h - font->height) / 2 + font->ascent; ++ pixman_image_composite32( ++ PIXMAN_OP_OVER, clr_pix, glyph->pix, pix, 0, 0, 0, 0, ++ x + glyph->x, ty - glyph->y, glyph->width, glyph->height); ++ } ++ ++ x += glyph->advance.x; ++ w -= glyph->advance.x; ++ } ++ ++ if (render) ++ pixman_image_unref(clr_pix); ++ ++ return x + (render ? w : 0); ++} ++ ++static void ++draw_rect(pixman_image_t *pix, ++ int16_t x, int16_t y, uint16_t w, uint16_t h, ++ int filled, pixman_color_t *bg) ++{ ++ /* ++ * originally, i was using PIXMAN_OP_CLEAR and drawing ++ * a clear rectangle, however that was transparent beyond ++ * the bar, so a manually drawn bordered rectangle, made ++ * out of lines (thin recthangles) had to be used. ++ */ ++ if (filled) ++ pixman_image_fill_rectangles(PIXMAN_OP_SRC, pix, bg, 1, ++ &(pixman_rectangle16_t){x, y, w, h}); ++ else ++ pixman_image_fill_rectangles(PIXMAN_OP_SRC, pix, bg, 4, ++ (pixman_rectangle16_t[4]){ ++ { x, y, w, 1 }, ++ { x, y + h - 1, w, 1 }, ++ { x, y, 1, h }, ++ { x + w - 1, y, 1, h }}); ++} ++ ++void ++drawbar(Monitor *mon) ++{ ++ int x, w, tw = 0; ++ int sel; ++ int boxs = font->height / 9; ++ int boxw = font->height / 6 + 2; ++ uint32_t i, occ = 0, urg = 0; ++ uint32_t stride, size; ++ const char *title; ++ pixman_image_t *pix; ++ Client *c; ++ Buffer *buf; ++ ++ if (!mon) ++ return; ++ ++ stride = mon->b.width * 4; ++ size = stride * mon->b.height; ++ ++ buf = ecalloc(1, sizeof(Buffer) + size); ++ buf->stride = stride; ++ wlr_buffer_init(&buf->base, &buffer_impl, mon->b.width, mon->b.height); ++ ++ pix = pixman_image_create_bits( ++ PIXMAN_a8r8g8b8, mon->b.width, mon->b.height, buf->data, stride); ++ ++ /* draw status first so it can be overdrawn by tags later */ ++ if (mon == selmon) { ++ if (stext[0] == '\0') ++ strncpy(stext, "dwl-"VERSION, sizeof(stext)); ++ draw_rect(pix, 0, 0, mon->b.width, mon->b.height, 1, &normbarbg); ++ tw = TEXTW(stext) - lrpad + 2; ++ draw_text(pix, mon->b.width - tw, 0, tw, mon->b.height, 0, stext, &normbarfg); ++ } ++ ++ wl_list_for_each(c, &clients, link) { ++ if (c->mon != mon) ++ continue; ++ occ |= c->tags; ++ if (c->isurgent) ++ urg |= c->tags; ++ } ++ c = focustop(mon); ++ x = 0; ++ for (i = 0; i < LENGTH(tags); i++) { ++ w = TEXTW(tags[i]); ++ sel = mon->tagset[mon->seltags] & 1 << i; ++ ++ draw_rect(pix, x, 0, w, mon->b.height, 1, ++ urg ? &selbarfg : (sel ? &selbarbg : &normbarbg)); ++ draw_text(pix, x, 0, w, mon->b.height, lrpad / 2, tags[i], ++ urg ? &selbarfg : (sel ? &selbarfg : &normbarfg)); ++ ++ if (occ & 1 << i) ++ draw_rect(pix, x + boxs, boxs, boxw, boxw, ++ sel, sel ? &selbarfg : &normbarfg); ++ ++ x += w; ++ } ++ w = TEXTW(mon->ltsymbol); ++ draw_rect(pix, x, 0, w, mon->b.height, 1, &normbarbg); ++ x = draw_text(pix, x, 0, w, mon->b.height, lrpad / 2, mon->ltsymbol, &normbarfg); ++ ++ if ((w = mon->b.width - tw - x) > mon->b.height) { ++ title = c ? client_get_title(c) : NULL; ++ draw_rect(pix, x, 0, w, mon->b.height, 1, ++ (mon == selmon && title) ? &selbarbg : &normbarbg); ++ draw_text(pix, x, 0, w, mon->b.height, lrpad / 2, title, ++ mon == selmon ? &selbarfg : &normbarfg); ++ if (c && c->isfloating) ++ draw_rect(pix, x + boxs, boxs, boxw, boxw, 0, ++ mon == selmon ? &selbarfg : &normbarfg); ++ } ++ ++ pixman_image_unref(pix); ++ wlr_scene_node_set_position(&mon->scene_buffer->node, mon->m.x, mon->m.y); ++ wlr_scene_buffer_set_buffer(mon->scene_buffer, &buf->base); ++ wlr_buffer_drop(&buf->base); ++} ++ ++void ++drawbars(void) ++{ ++ Monitor *m = NULL; ++ ++ wl_list_for_each(m, &mons, link) ++ drawbar(m); ++} ++ + void + focusclient(Client *c, int lift) + { +@@ -1222,7 +1498,7 @@ focusclient(Client *c, int lift) + client_activate_surface(old, 0); + } + } +- printstatus(); ++ drawbars(); + + if (!c) { + /* With no client, all we have left is to clear focus */ +@@ -1233,6 +1509,8 @@ focusclient(Client *c, int lift) + /* Change cursor surface */ + motionnotify(0); + ++ ++ + /* Have a client, so focus its top-level wlr_surface */ + client_notify_enter(client_surface(c), wlr_seat_get_keyboard(seat)); + +@@ -1550,7 +1828,7 @@ mapnotify(struct wl_listener *listener, void *data) + } else { + applyrules(c); + } +- printstatus(); ++ drawbars(); + + unset_fullscreen: + m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y); +@@ -1803,46 +2081,6 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, + + } + +-void +-printstatus(void) +-{ +- Monitor *m = NULL; +- Client *c; +- uint32_t occ, urg, sel; +- const char *appid, *title; +- +- wl_list_for_each(m, &mons, link) { +- occ = urg = 0; +- wl_list_for_each(c, &clients, link) { +- if (c->mon != m) +- continue; +- occ |= c->tags; +- if (c->isurgent) +- urg |= c->tags; +- } +- if ((c = focustop(m))) { +- title = client_get_title(c); +- appid = client_get_appid(c); +- printf("%s title %s\n", m->wlr_output->name, title ? title : broken); +- printf("%s appid %s\n", m->wlr_output->name, appid ? appid : broken); +- printf("%s fullscreen %d\n", m->wlr_output->name, c->isfullscreen); +- printf("%s floating %d\n", m->wlr_output->name, c->isfloating); +- sel = c->tags; +- } else { +- printf("%s title \n", m->wlr_output->name); +- printf("%s appid \n", m->wlr_output->name); +- printf("%s fullscreen \n", m->wlr_output->name); +- printf("%s floating \n", m->wlr_output->name); +- sel = 0; +- } +- +- printf("%s selmon %u\n", m->wlr_output->name, m == selmon); +- printf("%s tags %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32"\n", +- m->wlr_output->name, occ, m->tagset[m->seltags], sel, urg); +- printf("%s layout %s\n", m->wlr_output->name, m->ltsymbol); +- } +- fflush(stdout); +-} + + void + quit(const Arg *arg) +@@ -1989,7 +2227,8 @@ run(char *startup_cmd) + close(piperw[1]); + close(piperw[0]); + } +- printstatus(); ++ ++ drawbars(); + + /* At this point the outputs are initialized, choose initial selmon based on + * cursor position, and set default cursor image */ +@@ -2054,7 +2293,7 @@ setfloating(Client *c, int floating) + (p && p->isfullscreen) ? LyrFS + : c->isfloating ? LyrFloat : LyrTile]); + arrange(c->mon); +- printstatus(); ++ drawbars(); + } + + void +@@ -2077,7 +2316,7 @@ setfullscreen(Client *c, int fullscreen) + resize(c, c->prev, 0); + } + arrange(c->mon); +- printstatus(); ++ drawbars(); + } + + void +@@ -2102,7 +2341,7 @@ setlayout(const Arg *arg) + selmon->lt[selmon->sellt] = (Layout *)arg->v; + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, LENGTH(selmon->ltsymbol)); + arrange(selmon); +- printstatus(); ++ drawbars(); + } + + /* arg > 1.0 will set mfact absolutely */ +@@ -2400,6 +2639,17 @@ setup(void) + + wlr_scene_set_presentation(scene, wlr_presentation_create(dpy, backend)); + ++ fcft_init(FCFT_LOG_COLORIZE_AUTO, 0, FCFT_LOG_CLASS_DEBUG); ++ fcft_set_scaling_filter(FCFT_SCALING_FILTER_LANCZOS3); ++ if (!(font = fcft_from_name(LENGTH(fonts), fonts, fontattrs))) ++ die("Could not load font"); ++ ++ lrpad = font->height; ++ bh = font->height + 2; ++ ++ wl_event_loop_add_fd(wl_display_get_event_loop(dpy), ++ STDIN_FILENO, WL_EVENT_READABLE, status_in, NULL); ++ + /* Make sure XWayland clients don't connect to the parent X server, + * e.g when running in the x11 backend or the wayland backend and the + * compositor has Xwayland support */ +@@ -2442,6 +2692,28 @@ startdrag(struct wl_listener *listener, void *data) + LISTEN_STATIC(&drag->icon->events.destroy, destroydragicon); + } + ++int ++status_in(int fd, unsigned int mask, void *data) ++{ ++ char status[1024]; ++ ssize_t n; ++ ++ if (mask & WL_EVENT_ERROR) ++ die("status in event error"); ++ ++ n = read(fd, status, sizeof(status) - 1); ++ if (n < 0 && errno != EWOULDBLOCK) ++ die("read:"); ++ ++ status[n] = '\0'; ++ status[strcspn(status, "\n")] = '\0'; ++ ++ strncpy(stext, status, sizeof(stext)); ++ drawbars(); ++ ++ return 0; ++} ++ + void + tag(const Arg *arg) + { +@@ -2452,7 +2724,7 @@ tag(const Arg *arg) + sel->tags = arg->ui & TAGMASK; + focusclient(focustop(selmon), 1); + arrange(selmon); +- printstatus(); ++ drawbars(); + } + + void +@@ -2525,7 +2797,7 @@ toggletag(const Arg *arg) + sel->tags = newtags; + focusclient(focustop(selmon), 1); + arrange(selmon); +- printstatus(); ++ drawbars(); + } + + void +@@ -2538,7 +2810,7 @@ toggleview(const Arg *arg) + selmon->tagset[selmon->seltags] = newtagset; + focusclient(focustop(selmon), 1); + arrange(selmon); +- printstatus(); ++ drawbars(); + } + + void +@@ -2586,7 +2858,7 @@ unmapnotify(struct wl_listener *listener, void *data) + } + + wlr_scene_node_destroy(&c->scene->node); +- printstatus(); ++ drawbars(); + motionnotify(0); + } + +@@ -2622,6 +2894,7 @@ updatemons(struct wl_listener *listener, void *data) + if (m->wlr_output->enabled + && !wlr_output_layout_get(output_layout, m->wlr_output)) + wlr_output_layout_add_auto(output_layout, m->wlr_output); ++ + } + + /* Now that we update the output layout we can get its box */ +@@ -2682,6 +2955,13 @@ updatemons(struct wl_listener *listener, void *data) + } + } + ++ /* Update bar */ ++ wl_list_for_each(m, &mons, link) { ++ m->b.width = m->wlr_output->width; ++ m->b.height = bh; ++ drawbar(m); ++ } ++ + /* FIXME: figure out why the cursor image is at 0,0 after turning all + * the monitors on. + * Move the cursor image where it used to be. It does not generate a +@@ -2697,7 +2977,7 @@ updatetitle(struct wl_listener *listener, void *data) + { + Client *c = wl_container_of(listener, c, set_title); + if (c == focustop(c->mon)) +- printstatus(); ++ drawbars(); + } + + void +@@ -2710,7 +2990,7 @@ urgent(struct wl_listener *listener, void *data) + return; + + c->isurgent = 1; +- printstatus(); ++ drawbars(); + + if (client_surface(c)->mapped) + client_set_border_color(c, urgentcolor); +@@ -2726,7 +3006,7 @@ view(const Arg *arg) + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; + focusclient(focustop(selmon), 1); + arrange(selmon); +- printstatus(); ++ drawbars(); + } + + void +@@ -2765,6 +3045,7 @@ xytonode(double x, double y, struct wlr_surface **psurface, + { + struct wlr_scene_node *node, *pnode; + struct wlr_surface *surface = NULL; ++ struct wlr_scene_surface *scene_surface = NULL; + Client *c = NULL; + LayerSurface *l = NULL; + int layer; +@@ -2773,9 +3054,12 @@ xytonode(double x, double y, struct wlr_surface **psurface, + if (!(node = wlr_scene_node_at(&layers[layer]->node, x, y, nx, ny))) + continue; + +- if (node->type == WLR_SCENE_NODE_BUFFER) +- surface = wlr_scene_surface_try_from_buffer( +- wlr_scene_buffer_from_node(node))->surface; ++ if (node->type == WLR_SCENE_NODE_BUFFER) { ++ scene_surface = wlr_scene_surface_try_from_buffer( ++ wlr_scene_buffer_from_node(node)); ++ if (!scene_surface) continue; ++ surface = scene_surface->surface; ++ } + /* Walk the tree to find a node that knows the client */ + for (pnode = node; pnode && !c; pnode = &pnode->parent->node) + c = pnode->data; +@@ -2914,7 +3198,7 @@ sethints(struct wl_listener *listener, void *data) + return; + + c->isurgent = xcb_icccm_wm_hints_get_urgency(c->surface.xwayland->hints); +- printstatus(); ++ drawbars(); + + if (c->isurgent && surface && surface->mapped) + client_set_border_color(c, urgentcolor); +diff --git a/utf8.h b/utf8.h +new file mode 100644 +index 0000000..c7db188 +--- /dev/null ++++ b/utf8.h +@@ -0,0 +1,55 @@ ++// Copyright (c) 2008-2009 Bjoern Hoehrmann ++// See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. ++ ++// Permission is hereby granted, free of charge, to any person obtaining a copy ++// of this software and associated documentation files (the "Software"), to deal ++// in the Software without restriction, including without limitation the rights ++// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++// copies of the Software, and to permit persons to whom the Software is ++// furnished to do so, subject to the following conditions: ++ ++// The above copyright notice and this permission notice shall be included in ++// all copies or substantial portions of the Software. ++ ++// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++// SOFTWARE. ++ ++#include ++ ++#define UTF8_ACCEPT 0 ++#define UTF8_REJECT 1 ++ ++static const uint8_t utf8d[] = { ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f ++ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f ++ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f ++ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf ++ 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df ++ 0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, // e0..ef ++ 0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, // f0..ff ++ 0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, // s0..s0 ++ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, // s1..s2 ++ 1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, // s3..s4 ++ 1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, // s5..s6 ++ 1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8 ++}; ++ ++static inline uint32_t ++utf8decode(uint32_t *state, uint32_t *codep, uint8_t byte) ++{ ++ uint32_t type = utf8d[byte]; ++ ++ *codep = (*state != UTF8_ACCEPT) ? ++ (byte & 0x3fu) | (*codep << 6) : ++ (0xff >> type) & (byte); ++ ++ *state = utf8d[256 + *state*16 + type]; ++ return *state; ++} +-- +2.43.2 +