diff --git a/.gitignore b/.gitignore index a745c34..d4e98fe 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ dwl *.orig *.rej .ccls-cache +compile_commands.json diff --git a/README.md b/README.md index bc3c299..924c668 100644 --- a/README.md +++ b/README.md @@ -17,12 +17,17 @@ philosophy. Like dwm, dwl is: - [attachtop](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/attachtop) - [autostart](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/autostart) - [bar](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/bar) +- [barcolors](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/barcolors) - [barheight](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/barheight) +- [barpadding](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/barpadding) +- [column](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/column) - [cursortheme](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/cursortheme) +- [disable-keybindings-on-fullscreen](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/disable-keybindings-on-fullscreen) - [en-keycodes](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/en-keycodes) - [genericgaps](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/genericgaps) - [hide_vacant_tags](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/hide_vacant_tags) - [inputdevicerules](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/inputdevicerules) +- [movestack](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/movestack) - [nextlayout](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/nextlayout) - [pertag](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/pertag) - [rotatetags](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/rotatetags) diff --git a/config.def.h b/config.def.h index f8bd97e..7c959ed 100644 --- a/config.def.h +++ b/config.def.h @@ -17,6 +17,8 @@ static const unsigned int gappov = 10; /* vert outer gap between windo static const int user_bh = 30; /* 0 means that dwl will calculate barheight, >= 1 means dwl will use user_bh as the bar height. */ static const int showbar = 1; /* 0 means no bar */ static const int topbar = 1; /* 0 means bottom bar */ +static const int vertpad = 10; /* vertical padding of bar */ +static const int sidepad = 10; /* horizontal padding of bar */ static const char *fonts[] = {"monospace:size=10"}; static const float rootcolor[] = COLOR(0x000000ff); /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ @@ -72,6 +74,8 @@ static const Layout layouts[] = { { "[]=", tile }, { "><>", NULL }, /* no layout function means floating behavior */ { "[M]", monocle }, + { "|M|", centeredmaster }, + { "||", col }, { NULL, NULL }, /* terminate */ }; @@ -91,12 +95,16 @@ static const MonitorRule monrules[] = { }; /* keyboard */ -static const struct xkb_rule_names xkb_rules = { - /* can specify fields: rules, model, layout, variant, options */ - /* example: - .options = "ctrl:nocaps", - */ - .options = NULL, +static const struct xkb_rule_names xkb_rules[] = { + { + /* can specify fields: rules, model, layout, variant, options */ + .layout = "us", + .options = NULL, + }, + { + .layout = "us", + .options = "compose:ralt", + }, }; /* input devices */ @@ -181,6 +189,8 @@ static const Key keys[] = { { MODKEY, XKB_KEY_b, togglebar, {0} }, { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_J, movestack, {.i = +1} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_K, movestack, {.i = -1} }, { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_i, incnmaster, {.i = -1} }, { MODKEY, XKB_KEY_a, rotatetags, {.i = VIEW_L} }, @@ -211,6 +221,8 @@ static const Key keys[] = { { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XKB_KEY_c, setlayout, {.v = &layouts[3]} }, + { MODKEY, XKB_KEY_v, setlayout, {.v = &layouts[4]} }, { MODKEY, XKB_KEY_space, setlayout, {0} }, { MODKEY, XKB_KEY_n, nextlayout, {0} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, @@ -224,6 +236,7 @@ static const Key keys[] = { { MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} }, + { MODKEY, XKB_KEY_w, switchxkbrule, {0} }, TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0), TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1), TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2), diff --git a/config.h b/config.h index 4415bcb..eed82b0 100644 --- a/config.h +++ b/config.h @@ -12,16 +12,18 @@ static const int monoclegaps = 0; /* 1 means outer gaps in monocl static const unsigned int borderpx = 2; /* border pixel of windows */ static const unsigned int gappih = 4; /* horiz inner gap between windows */ static const unsigned int gappiv = 4; /* vert inner gap between windows */ -static const unsigned int gappoh = 1; /* horiz outer gap between windows and screen edge */ -static const unsigned int gappov = 1; /* vert outer gap between windows and screen edge */ +static const unsigned int gappoh = 2; /* horiz outer gap between windows and screen edge */ +static const unsigned int gappov = 2; /* vert outer gap between windows and screen edge */ static const int user_bh = 30; /* 0 means that dwl will calculate barheight, >= 1 means dwl will use user_bh as the bar height. */ static const int showbar = 1; /* 0 means no bar */ static const int topbar = 1; /* 0 means bottom bar */ -static const char *fonts[] = {"Inconsolata:size=12"}; +static const int vertpad = 4; /* vertical padding of bar */ +static const int sidepad = 6; /* horizontal padding of bar */ +static const char *fonts[] = {"CommitMono:size=12", "Arimo Nerd Font:size=12"}; /* This conforms to 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 */ static int enableautoswallow = 1; /* enables autoswallowing newly spawned clients */ -static float swallowborder = 1.0f; /* add this multiplied by borderpx to border when a client is swallowed */ +static float swallowborder = 0.0f; /* add this multiplied by borderpx to border when a client is swallowed */ static const char *cursor_theme = "macOS"; static const char cursor_size[] = "28"; /* Make sure it's a valid integer, otherwise things will break */ #include "/home/amolinae/.cache/hellwal/dwl-colors-bar.h" @@ -54,6 +56,7 @@ static const char *const autostart[] = { "foot", "--server", NULL, "swayidle", NULL, "mako", NULL, + "kanshi", NULL, NULL /* terminate */ }; @@ -71,9 +74,11 @@ static const Rule rules[] = { /* layout(s) */ static const Layout layouts[] = { /* symbol arrange function */ - { "[]=", tile }, - { "><>", NULL }, /* no layout function means floating behavior */ - { "[M]", monocle }, + { "", tile }, + { "", NULL }, /* no layout function means floating behavior */ + { "", monocle }, + { "", centeredmaster }, + { "", col }, { NULL, NULL }, /* terminate */ }; @@ -93,13 +98,16 @@ static const MonitorRule monrules[] = { }; /* keyboard */ -static const struct xkb_rule_names xkb_rules = { - /* can specify fields: rules, model, layout, variant, options */ - /* example: - .options = "ctrl:nocaps", - */ - .layout = "latam", - .options = NULL, +static const struct xkb_rule_names xkb_rules[] = { + { + /* can specify fields: rules, model, layout, variant, options */ + .layout = "latam", + .options = NULL, + }, + { + .layout = "us", + .options = NULL, + }, }; /* input devices */ @@ -176,10 +184,12 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA static const char *termcmd[] = { "footclient", NULL }; static const char *menucmd[] = { "fuzzel", NULL }; static const char *filecmd[] = { "footclient", "--title", "lf", "lf", NULL }; +static const char *brwscmd[] = { "librewolf", NULL }; static const char *volmcmd[] = { "footclient", "--title", "ncpamixer", "ncpamixer", NULL }; static const char *sptpcmd[] = { "footclient", "--title", "Spotify", "spotify_player", NULL }; -static const char *editcmd[] = { "footclient", "nvim", NULL }; +static const char *editcmd[] = { "footclient", "-e", "nvim", NULL }; static const char *lockcmd[] = { "swaylock", NULL }; +static const char *blthcmd[] = { "abman", NULL }; static const char *wcamcmd[] = { "camera", NULL }; static const char *awsfcmd[] = { "aws", "-f", NULL }; static const char *awsrcmd[] = { "aws", "-r", NULL }; @@ -188,20 +198,22 @@ static const char *sysucmd[] = { "sysutils", NULL }; static const char *emomcmd[] = { "emojimenu", NULL }; static const Key keys[] = { - /* modifier key function argument */ { MODKEY, XKB_KEY_r, spawn, {.v = menucmd} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_R, spawn, {.v = brwscmd} }, { MODKEY, XKB_KEY_e, spawn, {.v = filecmd} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Q, spawn, {.v = sysucmd} }, { MODKEY, XKB_KEY_v, spawn, {.v = volmcmd} }, + { MODKEY, XKB_KEY_b, spawn, {.v = blthcmd} }, { MODKEY, XKB_KEY_s, spawn, {.v = sptpcmd} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_E, spawn, {.v = editcmd} }, { MODKEY, XKB_KEY_l, spawn, {.v = lockcmd} }, - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_c, spawn, {.v = wcamcmd} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, spawn, {.v = wcamcmd} }, { WLR_MODIFIER_SHIFT, XKB_KEY_Print, spawn, {.v = awsfcmd} }, { 0, XKB_KEY_Print, spawn, {.v = awsrcmd} }, { MODKEY, XKB_KEY_Print, spawn, {.v = artrcmd} }, + { MODKEY, XKB_KEY_space, spawn, {.v = emomcmd} }, { MODKEY, XKB_KEY_q, killclient, {0} }, { 0, XKB_KEY_XF86AudioMicMute, spawn,SHCMD("setvol -m mute") }, { WLR_MODIFIER_SHIFT, XKB_KEY_XF86AudioRaiseVolume, spawn,SHCMD("setvol -m up") }, @@ -211,11 +223,13 @@ static const Key keys[] = { { 0, XKB_KEY_XF86AudioLowerVolume, spawn,SHCMD("setvol down") }, { 0, XKB_KEY_XF86MonBrightnessUp, spawn,SHCMD("setbr increase")}, { 0, XKB_KEY_XF86MonBrightnessDown,spawn,SHCMD("setbr decrease")}, - /* - { MODKEY, XKB_KEY_b, togglebar, {0} }, - */ + { MODKEY, XKB_KEY_w, switchxkbrule, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_B, togglebar, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_S, togglesticky, {0} }, { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_J, movestack, {.i = +1} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_K, movestack, {.i = -1} }, { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_i, incnmaster, {.i = -1} }, { MODKEY, XKB_KEY_a, rotatetags, {.i = VIEW_L} }, @@ -249,10 +263,11 @@ static const Key keys[] = { { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XKB_KEY_c, setlayout, {.v = &layouts[3]} }, + { MODKEY, XKB_KEY_v, setlayout, {.v = &layouts[4]} }, { MODKEY, XKB_KEY_space, setlayout, {0} }, */ { MODKEY, XKB_KEY_n, nextlayout, {0} }, - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_F, togglefullscreen,{0} }, /* diff --git a/config.mk b/config.mk index e22aac7..78b6498 100644 --- a/config.mk +++ b/config.mk @@ -8,10 +8,10 @@ PREFIX = /usr/local MANDIR = $(PREFIX)/share/man DATADIR = $(PREFIX)/share -XWAYLAND = -XLIBS = +#XWAYLAND = +#XLIBS = # Uncomment to build XWayland support -#XWAYLAND = -DXWAYLAND -#XLIBS = xcb xcb-icccm +XWAYLAND = -DXWAYLAND +XLIBS = xcb xcb-icccm CC = tcc diff --git a/dwl.c b/dwl.c index e161ab1..4f765e9 100644 --- a/dwl.c +++ b/dwl.c @@ -84,6 +84,7 @@ #define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0) #define BORDERPX(C) (borderpx + ((C)->swallowing ? (int)ceilf(swallowborder * (C)->swallowing->bw) : 0)) #define TEXTW(mon, text) (drwl_font_getwidth(mon->drw, text) + mon->lrpad) +#define PREFIX(str, prefix) !strncmp(str, prefix, strlen(prefix)) /* enums */ enum { SchemeNorm, SchemeSel, SchemeUrg }; /* color schemes */ @@ -310,11 +311,13 @@ static void bufdataend(struct wlr_buffer *buffer); static Buffer *bufmon(Monitor *m); static void bufrelease(struct wl_listener *listener, void *data); static void buttonpress(struct wl_listener *listener, void *data); +static void centeredmaster(Monitor *m); static void chvt(const Arg *arg); static void checkidleinhibitor(struct wlr_surface *exclude); static void cleanup(void); static void cleanupmon(struct wl_listener *listener, void *data); static void closemon(Monitor *m); +static void col(Monitor *m); static void commitlayersurfacenotify(struct wl_listener *listener, void *data); static void commitnotify(struct wl_listener *listener, void *data); static void commitpopup(struct wl_listener *listener, void *data); @@ -349,6 +352,8 @@ static void destroykeyboardgroup(struct wl_listener *listener, void *data); static Monitor *dirtomon(enum wlr_direction dir); static void drawbar(Monitor *m); static void drawbars(void); +static int drawstatus(Monitor *m); +static Client *firstfocused(void); static void focusclient(Client *c, int lift); static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); @@ -374,6 +379,7 @@ static void locksession(struct wl_listener *listener, void *data); static void mapnotify(struct wl_listener *listener, void *data); static void maximizenotify(struct wl_listener *listener, void *data); static void monocle(Monitor *m); +static void movestack(const Arg *arg); static void motionabsolute(struct wl_listener *listener, void *data); static void motionnotify(uint32_t time, struct wlr_input_device *device, double sx, double sy, double sx_unaccel, double sy_unaccel); @@ -410,6 +416,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 void switchxkbrule(const Arg *arg); static void swallow(Client *c, Client *toswallow); static int statusin(int fd, unsigned int mask, void *data); static void tag(const Arg *arg); @@ -491,6 +498,7 @@ static struct wl_listener lock_listener = {.notify = locksession}; static struct wlr_seat *seat; static KeyboardGroup *kb_group; static unsigned int cursor_mode; +static unsigned int xkb_rule_index = 0; static Client *grabc; static int grabcx, grabcy; /* client-relative */ @@ -499,7 +507,7 @@ static struct wlr_box sgeom; static struct wl_list mons; static Monitor *selmon; -static char stext[256]; +static char stext[512]; static struct wl_event_source *status_event_source; static const struct wlr_buffer_impl buffer_impl = { @@ -723,8 +731,8 @@ arrangelayers(Monitor *m) return; if (m->scene_buffer->node.enabled) { - usable_area.height -= m->b.real_height; - usable_area.y += topbar ? m->b.real_height : 0; + usable_area.height -= m->b.real_height + vertpad; + usable_area.y += topbar ? m->b.real_height + vertpad : 0; } /* Arrange exclusive surfaces from top->bottom */ @@ -876,7 +884,7 @@ buttonpress(struct wl_listener *listener, void *data) struct wlr_scene_buffer *buffer; uint32_t mods; Arg arg = {0}; - Client *c; + Client *c, *focused; const Button *b; wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); @@ -886,6 +894,10 @@ buttonpress(struct wl_listener *listener, void *data) if (c) click = ClkClient; + focused = firstfocused(); + if (focused && focused->isfullscreen) + goto skip_click; + switch (event->state) { case WL_POINTER_BUTTON_STATE_PRESSED: cursor_mode = CurPressed; @@ -896,7 +908,7 @@ buttonpress(struct wl_listener *listener, void *data) if (!c && !exclusive_focus && (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) { - cx = (cursor->x - selmon->m.x) * selmon->wlr_output->scale; + cx = (cursor->x - selmon->m.x - sidepad) * selmon->wlr_output->scale; wl_list_for_each(c, &clients, link) { if (c->mon != selmon) continue; @@ -949,10 +961,73 @@ buttonpress(struct wl_listener *listener, void *data) } /* If the event wasn't handled by the compositor, notify the client with * pointer focus that a button press has occurred */ +skip_click: wlr_seat_pointer_notify_button(seat, event->time_msec, event->button, event->state); } +void +centeredmaster(Monitor *m) +{ + int i, n, h, mw, mx, my, oty, ety, tw; + Client *c; + + n = 0; + wl_list_for_each(c, &clients, link) + if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) + n++; + if (n == 0) + return; + + /* initialize areas */ + mw = m->w.width; + mx = 0; + my = 0; + tw = mw; + + if (n > m->nmaster) { + /* go mfact box in the center if more than nmaster clients */ + mw = m->nmaster ? (int)roundf(m->w.width * m->mfact) : 0; + tw = m->w.width - mw; + + if (n - m->nmaster > 1) { + /* only one client */ + mx = (m->w.width - mw) / 2; + tw = (m->w.width - mw) / 2; + } + } + + i = 0; + oty = 0; + ety = 0; + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; + if (i < m->nmaster) { + /* nmaster clients are stacked vertically, in the center + * of the screen */ + h = (m->w.height - my) / (MIN(n, m->nmaster) - i); + resize(c, (struct wlr_box){.x = m->w.x + mx, .y = m->w.y + my, .width = mw, + .height = h}, 0); + my += c->geom.height; + } else { + /* stack clients are stacked vertically */ + if ((i - m->nmaster) % 2) { + h = (m->w.height - ety) / ( (1 + n - i) / 2); + resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + ety, .width = tw, + .height = h}, 0); + ety += c->geom.height; + } else { + h = (m->w.height - oty) / ((1 + n - i) / 2); + resize(c, (struct wlr_box){.x = m->w.x + mx + mw, .y = m->w.y + oty, .width = tw, + .height = h}, 0); + oty += c->geom.height; + } + } + i++; + } +} + void chvt(const Arg *arg) { @@ -1081,6 +1156,33 @@ closemon(Monitor *m) drawbars(); } +void +col(Monitor *m) +{ + Client *c; + unsigned int n = 0, i = 0; + + wl_list_for_each(c, &clients, link) + if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen) + n++; + + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen) + continue; + resize( + c, + (struct wlr_box){ + .x = m->w.x + i * m->w.width / n, + .y = m->w.y, + .width = m->w.width / n, + .height = m->w.height + }, + 0 + ); + i++; + } +} + void commitlayersurfacenotify(struct wl_listener *listener, void *data) { @@ -1222,7 +1324,7 @@ createkeyboardgroup(void) /* Prepare an XKB keymap and assign it to the keyboard group. */ context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - if (!(keymap = xkb_keymap_new_from_names(context, &xkb_rules, + if (!(keymap = xkb_keymap_new_from_names(context, &xkb_rules[xkb_rule_index], XKB_KEYMAP_COMPILE_NO_FLAGS))) die("failed to compile keymap"); @@ -1738,11 +1840,8 @@ drawbar(Monitor *m) return; /* draw status first so it can be overdrawn by tags later */ - if (m == selmon) { /* status is only drawn on selected monitor */ - drwl_setscheme(m->drw, colors[SchemeNorm]); - tw = TEXTW(m, stext) - m->lrpad + 2; /* 2px right padding */ - drwl_text(m->drw, m->b.width - tw, 0, tw, m->b.height, 0, stext, 0); - } + if (m == selmon) /* status is only drawn on selected monitor */ + tw = drawstatus(m); wl_list_for_each(c, &clients, link) { if (c->mon != m) @@ -1779,8 +1878,8 @@ drawbar(Monitor *m) wlr_scene_buffer_set_dest_size(m->scene_buffer, m->b.real_width, m->b.real_height); - wlr_scene_node_set_position(&m->scene_buffer->node, m->m.x, - m->m.y + (topbar ? 0 : m->m.height - m->b.real_height)); + wlr_scene_node_set_position(&m->scene_buffer->node, m->m.x + sidepad, + m->m.y + (topbar ? vertpad : m->m.height - m->b.real_height - vertpad)); wlr_scene_buffer_set_buffer(m->scene_buffer, &buf->base); wlr_buffer_unlock(&buf->base); } @@ -1794,6 +1893,95 @@ drawbars(void) drawbar(m); } +int +drawstatus(Monitor *m) +{ + int x, tw, iw; + char rstext[512] = ""; + char *p, *argstart, *argend, *itext; + uint32_t scheme[3], *color; + + /* calculate real width of stext */ + for (p = stext; *p; p++) { + if (PREFIX(p, "^^")) { + strncat(rstext, p, 2); + p++; + } else if (PREFIX(p, "^fg(") || PREFIX(p, "^bg(")) { + argend = strchr(p, ')'); + if (!argend) { /* ignore this command */ + argstart = strchr(p, '(') + 1; + strncat(rstext, p, argstart - p); + p = argstart - 1; + } else { + p = argend; + } + } else { + strncat(rstext, p, 1); + } + } + tw = TEXTW(m, rstext) - m->lrpad; + + x = m->b.width - tw; + itext = stext; + scheme[0] = colors[SchemeNorm][0]; + scheme[1] = colors[SchemeNorm][1]; + drwl_setscheme(m->drw, scheme); + for (p = stext; *p; p++) { + if (PREFIX(p, "^^")) { + p++; + } else if (PREFIX(p, "^fg(") || PREFIX(p, "^bg(")) { + argstart = strchr(p, '(') + 1; + argend = strchr(argstart, ')'); + if (!argend) { /* ignore this command */ + p = argstart - 1; + continue; + } + + *p = '\0'; + iw = TEXTW(m, itext) - m->lrpad; + if (*itext) /* only draw text if there is something to draw */ + x = drwl_text(m->drw, x, 0, iw, m->b.height, 0, itext, 0); + *p = '^'; + + if (PREFIX(p, "^fg(")) + color = &scheme[0]; + else + color = &scheme[1]; + + if (argend != argstart) { + *argend = '\0'; + *color = strtoul(argstart, NULL, 16); + *color = *color << 8 | 0xff; /* add alpha channel */ + *argend = ')'; + } else { + *color = 0; /* reset */ + } + + /* reset color back to normal if none was provided */ + if (!scheme[0]) + scheme[0] = colors[SchemeNorm][0]; + if (!scheme[1]) + scheme[1] = colors[SchemeNorm][1]; + + itext = argend + 1; + drwl_setscheme(m->drw, scheme); + p = argend; + } + } + iw = TEXTW(m, itext) - m->lrpad; + if (*itext) + drwl_text(m->drw, x, 0, iw, m->b.height, 0, itext, 0); + + return tw; +} + +Client * +firstfocused(void) +{ + Client *c = wl_container_of(fstack.next, c, flink); + return c; +} + void focusclient(Client *c, int lift) { @@ -2123,10 +2311,18 @@ keybinding(uint32_t mods, xkb_keysym_t sym) * processing keys, rather than passing them on to the client for its own * processing. */ + Client *c = firstfocused(); const Key *k; for (k = keys; k < END(keys); k++) { if (CLEANMASK(mods) == CLEANMASK(k->mod) && sym == k->keysym && k->func) { + if (c && c->isfullscreen) { + if (k->func == togglefullscreen) { + k->func(&k->arg); + return 1; + } + return 0; + } k->func(&k->arg); return 1; } @@ -2363,6 +2559,48 @@ monocle(Monitor *m) wlr_scene_node_raise_to_top(&c->scene->node); } +void +movestack(const Arg *arg) +{ + Client *c, *sel = focustop(selmon); + + if (!sel) { + return; + } + + if (wl_list_length(&clients) <= 1) { + return; + } + + if (arg->i > 0) { + wl_list_for_each(c, &sel->link, link) { + if (&c->link == &clients) { + c = wl_container_of(&clients, c, link); + break; /* wrap past the sentinel node */ + } + if (VISIBLEON(c, selmon) || &c->link == &clients) { + break; /* found it */ + } + } + } else { + wl_list_for_each_reverse(c, &sel->link, link) { + if (&c->link == &clients) { + c = wl_container_of(&clients, c, link); + break; /* wrap past the sentinel node */ + } + if (VISIBLEON(c, selmon) || &c->link == &clients) { + break; /* found it */ + } + } + /* backup one client */ + c = wl_container_of(c->link.prev, c, link); + } + + wl_list_remove(&sel->link); + wl_list_insert(&c->link, &sel->link); + arrange(selmon); +} + void motionabsolute(struct wl_listener *listener, void *data) { @@ -3352,6 +3590,21 @@ swallow(Client *c, Client *toswallow) } } +void +switchxkbrule(const Arg *arg) +{ + struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + struct xkb_keymap *keymap; + + xkb_rule_index = (xkb_rule_index + 1) % LENGTH(xkb_rules); + if (!(keymap = xkb_keymap_new_from_names(context, &xkb_rules[xkb_rule_index], + XKB_KEYMAP_COMPILE_NO_FLAGS))) + die("failed to compile keymap"); + wlr_keyboard_set_keymap(&kb_group->wlr_group->keyboard, keymap); + xkb_keymap_unref(keymap); + xkb_context_unref(context); +} + void tag(const Arg *arg) { @@ -3746,8 +3999,8 @@ updatebar(Monitor *m) char fontattrs[12]; wlr_output_transformed_resolution(m->wlr_output, &rw, &rh); - m->b.width = rw; - m->b.real_width = (int)((float)m->b.width / m->wlr_output->scale); + m->b.width = rw - (2 * sidepad); + m->b.real_width = (int)((float)rw / m->wlr_output->scale) - (2 * sidepad); wlr_scene_node_set_enabled(&m->scene_buffer->node, m->wlr_output->enabled ? showbar : 0);