From 57b69302f10565ddc16f9f838fcad9cb8b313b5a Mon Sep 17 00:00:00 2001 From: coast Date: Tue, 29 Jul 2025 04:42:29 +0330 Subject: [PATCH] suicide --- {suckless/dmenu => dmenu}/LICENSE | 0 {suckless/dmenu => dmenu}/Makefile | 0 {suckless/dmenu => dmenu}/README | 0 {suckless/dmenu => dmenu}/arg.h | 0 {suckless/dmenu => dmenu}/config.def.h | 0 {suckless/dmenu => dmenu}/config.def.h.orig | 0 {suckless/dmenu => dmenu}/config.h | 0 {suckless/dmenu => dmenu}/config.mk | 0 {suckless/dmenu => dmenu}/dmenu | Bin {suckless/dmenu => dmenu}/dmenu.1 | 0 {suckless/dmenu => dmenu}/dmenu.c | 0 {suckless/dmenu => dmenu}/dmenu.c.orig | 0 {suckless/dmenu => dmenu}/dmenu.c.rej | 0 {suckless/dmenu => dmenu}/dmenu.o | Bin {suckless/dmenu => dmenu}/dmenu_path | 0 {suckless/dmenu => dmenu}/dmenu_run | 0 {suckless/dmenu => dmenu}/drw.c | 0 {suckless/dmenu => dmenu}/drw.h | 0 {suckless/dmenu => dmenu}/drw.o | Bin .../patch/dmenu-bar-height-5.2.diff | 0 .../patch/dmenu-border-5.2.diff | 0 .../patch/dmenu-mousesupport-5.3.diff | 0 .../dmenu => dmenu}/patch/dmenu-xyw-5.2.diff | 0 {suckless/dmenu => dmenu}/stest | Bin {suckless/dmenu => dmenu}/stest.1 | 0 {suckless/dmenu => dmenu}/stest.c | 0 {suckless/dmenu => dmenu}/stest.o | Bin {suckless/dmenu => dmenu}/util.c | 0 {suckless/dmenu => dmenu}/util.h | 0 {suckless/dmenu => dmenu}/util.o | Bin dwm/LICENSE | 38 + dwm/Makefile | 67 + dwm/README.md | 58 + dwm/config.h | 389 +++ dwm/config.mk | 55 + dwm/configure | 40 + dwm/drw.c | 451 +++ dwm/drw.h | 72 + dwm/drw.o | Bin 0 -> 10576 bytes dwm/dwm | Bin 0 -> 98848 bytes dwm/dwm.1 | 187 ++ dwm/dwm.c | 2619 +++++++++++++++++ dwm/dwm.o | Bin 0 -> 100392 bytes dwm/dwm.png | Bin 0 -> 373 bytes dwm/mkconfig/config.mk.freebsd | 59 + dwm/mkconfig/config.mk.linux | 55 + dwm/mkconfig/config.mk.openbsd | 57 + dwm/mkconfig/config.mk.solaris | 58 + dwm/patch/attachx.c | 20 + dwm/patch/attachx.h | 2 + dwm/patch/bar.c | 39 + dwm/patch/bar.h | 2 + dwm/patch/bar_alpha.c | 43 + dwm/patch/bar_alpha.h | 4 + dwm/patch/bar_indicators.c | 104 + dwm/patch/bar_indicators.h | 21 + dwm/patch/bar_ltsymbol.c | 18 + dwm/patch/bar_ltsymbol.h | 4 + dwm/patch/bar_status.c | 20 + dwm/patch/bar_status.h | 4 + dwm/patch/bar_tagicons.c | 9 + dwm/patch/bar_tagicons.h | 8 + dwm/patch/bar_tags.c | 81 + dwm/patch/bar_tags.h | 4 + dwm/patch/bar_wintitle.c | 48 + dwm/patch/bar_wintitle.h | 4 + dwm/patch/cool_autostart.c | 29 + dwm/patch/cool_autostart.h | 2 + dwm/patch/dwmc | 130 + dwm/patch/dwmc.c | 85 + dwm/patch/dwmc.h | 14 + dwm/patch/fullscreen.c | 15 + dwm/patch/fullscreen.h | 2 + dwm/patch/include.c | 27 + dwm/patch/include.h | 26 + dwm/patch/ipc/IPCClient.h | 62 + dwm/patch/ipc/dwm-msg.c | 549 ++++ dwm/patch/ipc/yajl_dumps.h | 66 + dwm/patch/layout_facts.c | 24 + dwm/patch/layout_tile.c | 41 + dwm/patch/layout_tile.h | 2 + dwm/patch/moveresize.c | 65 + dwm/patch/moveresize.h | 2 + dwm/patch/movestack.c | 51 + dwm/patch/movestack.h | 2 + dwm/patch/scratchpad.c | 77 + dwm/patch/scratchpad.h | 9 + dwm/patch/swallow.c | 212 ++ dwm/patch/swallow.h | 8 + dwm/patch/togglefullscreen.c | 10 + dwm/patch/togglefullscreen.h | 2 + dwm/patch/vanitygaps.c | 177 ++ dwm/patch/vanitygaps.h | 16 + dwm/patch/xrdb.c | 73 + dwm/patch/xrdb.h | 22 + dwm/readme.dwm.txt | 48 + dwm/transient.c | 43 + dwm/util.c | 36 + dwm/util.h | 19 + dwm/util.o | Bin 0 -> 2272 bytes {suckless/slstatus => slstatus}/LICENSE | 0 {suckless/slstatus => slstatus}/Makefile | 0 {suckless/slstatus => slstatus}/arg.h | 0 .../components/battery.c | 0 .../components/battery.o | Bin .../slstatus => slstatus}/components/cat.c | 0 .../slstatus => slstatus}/components/cat.o | Bin .../slstatus => slstatus}/components/cpu.c | 0 .../slstatus => slstatus}/components/cpu.o | Bin .../components/datetime.c | 0 .../components/datetime.o | Bin .../slstatus => slstatus}/components/disk.c | 0 .../slstatus => slstatus}/components/disk.o | Bin .../components/entropy.c | 0 .../components/entropy.o | Bin .../components/hostname.c | 0 .../components/hostname.o | Bin .../slstatus => slstatus}/components/ip.c | 0 .../slstatus => slstatus}/components/ip.o | Bin .../components/kernel_release.c | 0 .../components/kernel_release.o | Bin .../components/keyboard_indicators.c | 0 .../components/keyboard_indicators.o | Bin .../slstatus => slstatus}/components/keymap.c | 0 .../slstatus => slstatus}/components/keymap.o | Bin .../components/load_avg.c | 0 .../components/load_avg.o | Bin .../components/netspeeds.c | 0 .../components/netspeeds.o | Bin .../components/num_files.c | 0 .../components/num_files.o | Bin .../components/pixVol.sh | 0 .../slstatus => slstatus}/components/ram.c | 0 .../slstatus => slstatus}/components/ram.o | Bin .../components/run_command.c | 0 .../components/run_command.o | Bin .../slstatus => slstatus}/components/swap.c | 0 .../slstatus => slstatus}/components/swap.o | Bin .../components/temperature.c | 0 .../components/temperature.o | Bin .../slstatus => slstatus}/components/uptime.c | 0 .../slstatus => slstatus}/components/uptime.o | Bin .../slstatus => slstatus}/components/user.c | 0 .../slstatus => slstatus}/components/user.o | Bin .../slstatus => slstatus}/components/volume.c | 0 .../slstatus => slstatus}/components/volume.o | Bin .../slstatus => slstatus}/components/wifi.c | 0 .../slstatus => slstatus}/components/wifi.o | Bin {suckless/slstatus => slstatus}/config.def.h | 0 {suckless/slstatus => slstatus}/config.h | 10 +- {suckless/slstatus => slstatus}/config.h~ | 0 {suckless/slstatus => slstatus}/config.mk | 0 {suckless/slstatus => slstatus}/slstatus | Bin 31248 -> 31248 bytes {suckless/slstatus => slstatus}/slstatus.1 | 0 {suckless/slstatus => slstatus}/slstatus.c | 0 {suckless/slstatus => slstatus}/slstatus.h | 0 {suckless/slstatus => slstatus}/slstatus.o | Bin 6336 -> 6352 bytes {suckless/slstatus => slstatus}/util.c | 0 {suckless/slstatus => slstatus}/util.h | 0 {suckless/slstatus => slstatus}/util.o | Bin {suckless/st => st}/LEGACY | 0 {suckless/st => st}/LICENSE | 0 {suckless/st => st}/Makefile | 0 {suckless/st => st}/README | 0 {suckless/st => st}/TODO | 0 {suckless/st => st}/arg.h | 0 {suckless/st => st}/boxdraw.c | 0 {suckless/st => st}/boxdraw_data.h | 0 {suckless/st => st}/config.def.h | 0 {suckless/st => st}/config.h | 127 +- {suckless/st => st}/config.h.save | 0 {suckless/st => st}/config.h.save.1 | 0 {suckless/st => st}/config.h.save.2 | 0 {suckless/st => st}/config.h.save.3 | 0 {suckless/st => st}/config.h~ | 0 {suckless/st => st}/config.mk | 0 {suckless/st => st}/graphics.c | 0 {suckless/st => st}/graphics.h | 0 {suckless/st => st}/hb.c | 0 {suckless/st => st}/hb.h | 0 {suckless/st => st}/hb.o | Bin {suckless/st => st}/icat-mini.sh | 0 {suckless/st => st}/khash.h | 0 {suckless/st => st}/kvec.h | 0 .../st => st}/rowcolumn_diacritics_helpers.c | 0 {suckless/st => st}/st | Bin 120544 -> 120544 bytes ...st-alpha-changealpha-20230519-b44f2ad.diff | 0 {suckless/st => st}/st.1 | 0 {suckless/st => st}/st.c | 0 {suckless/st => st}/st.h | 0 {suckless/st => st}/st.info | 0 {suckless/st => st}/st.o | Bin {suckless/st => st}/win.h | 0 {suckless/st => st}/x.c | 0 {suckless/st => st}/x.o | Bin 86896 -> 86904 bytes suckless/dwm | 1 - 196 files changed, 6596 insertions(+), 128 deletions(-) rename {suckless/dmenu => dmenu}/LICENSE (100%) rename {suckless/dmenu => dmenu}/Makefile (100%) rename {suckless/dmenu => dmenu}/README (100%) rename {suckless/dmenu => dmenu}/arg.h (100%) rename {suckless/dmenu => dmenu}/config.def.h (100%) rename {suckless/dmenu => dmenu}/config.def.h.orig (100%) rename {suckless/dmenu => dmenu}/config.h (100%) rename {suckless/dmenu => dmenu}/config.mk (100%) rename {suckless/dmenu => dmenu}/dmenu (100%) rename {suckless/dmenu => dmenu}/dmenu.1 (100%) rename {suckless/dmenu => dmenu}/dmenu.c (100%) rename {suckless/dmenu => dmenu}/dmenu.c.orig (100%) rename {suckless/dmenu => dmenu}/dmenu.c.rej (100%) rename {suckless/dmenu => dmenu}/dmenu.o (100%) rename {suckless/dmenu => dmenu}/dmenu_path (100%) rename {suckless/dmenu => dmenu}/dmenu_run (100%) rename {suckless/dmenu => dmenu}/drw.c (100%) rename {suckless/dmenu => dmenu}/drw.h (100%) rename {suckless/dmenu => dmenu}/drw.o (100%) rename {suckless/dmenu => dmenu}/patch/dmenu-bar-height-5.2.diff (100%) rename {suckless/dmenu => dmenu}/patch/dmenu-border-5.2.diff (100%) rename {suckless/dmenu => dmenu}/patch/dmenu-mousesupport-5.3.diff (100%) rename {suckless/dmenu => dmenu}/patch/dmenu-xyw-5.2.diff (100%) rename {suckless/dmenu => dmenu}/stest (100%) rename {suckless/dmenu => dmenu}/stest.1 (100%) rename {suckless/dmenu => dmenu}/stest.c (100%) rename {suckless/dmenu => dmenu}/stest.o (100%) rename {suckless/dmenu => dmenu}/util.c (100%) rename {suckless/dmenu => dmenu}/util.h (100%) rename {suckless/dmenu => dmenu}/util.o (100%) create mode 100644 dwm/LICENSE create mode 100644 dwm/Makefile create mode 100644 dwm/README.md create mode 100644 dwm/config.h create mode 100644 dwm/config.mk create mode 100755 dwm/configure create mode 100644 dwm/drw.c create mode 100644 dwm/drw.h create mode 100644 dwm/drw.o create mode 100755 dwm/dwm create mode 100644 dwm/dwm.1 create mode 100644 dwm/dwm.c create mode 100644 dwm/dwm.o create mode 100644 dwm/dwm.png create mode 100644 dwm/mkconfig/config.mk.freebsd create mode 100644 dwm/mkconfig/config.mk.linux create mode 100644 dwm/mkconfig/config.mk.openbsd create mode 100644 dwm/mkconfig/config.mk.solaris create mode 100644 dwm/patch/attachx.c create mode 100644 dwm/patch/attachx.h create mode 100644 dwm/patch/bar.c create mode 100644 dwm/patch/bar.h create mode 100644 dwm/patch/bar_alpha.c create mode 100644 dwm/patch/bar_alpha.h create mode 100644 dwm/patch/bar_indicators.c create mode 100644 dwm/patch/bar_indicators.h create mode 100644 dwm/patch/bar_ltsymbol.c create mode 100644 dwm/patch/bar_ltsymbol.h create mode 100644 dwm/patch/bar_status.c create mode 100644 dwm/patch/bar_status.h create mode 100644 dwm/patch/bar_tagicons.c create mode 100644 dwm/patch/bar_tagicons.h create mode 100644 dwm/patch/bar_tags.c create mode 100644 dwm/patch/bar_tags.h create mode 100644 dwm/patch/bar_wintitle.c create mode 100644 dwm/patch/bar_wintitle.h create mode 100644 dwm/patch/cool_autostart.c create mode 100644 dwm/patch/cool_autostart.h create mode 100755 dwm/patch/dwmc create mode 100644 dwm/patch/dwmc.c create mode 100644 dwm/patch/dwmc.h create mode 100644 dwm/patch/fullscreen.c create mode 100644 dwm/patch/fullscreen.h create mode 100644 dwm/patch/include.c create mode 100644 dwm/patch/include.h create mode 100644 dwm/patch/ipc/IPCClient.h create mode 100644 dwm/patch/ipc/dwm-msg.c create mode 100644 dwm/patch/ipc/yajl_dumps.h create mode 100644 dwm/patch/layout_facts.c create mode 100644 dwm/patch/layout_tile.c create mode 100644 dwm/patch/layout_tile.h create mode 100644 dwm/patch/moveresize.c create mode 100644 dwm/patch/moveresize.h create mode 100644 dwm/patch/movestack.c create mode 100644 dwm/patch/movestack.h create mode 100644 dwm/patch/scratchpad.c create mode 100644 dwm/patch/scratchpad.h create mode 100644 dwm/patch/swallow.c create mode 100644 dwm/patch/swallow.h create mode 100644 dwm/patch/togglefullscreen.c create mode 100644 dwm/patch/togglefullscreen.h create mode 100644 dwm/patch/vanitygaps.c create mode 100644 dwm/patch/vanitygaps.h create mode 100644 dwm/patch/xrdb.c create mode 100644 dwm/patch/xrdb.h create mode 100644 dwm/readme.dwm.txt create mode 100644 dwm/transient.c create mode 100644 dwm/util.c create mode 100644 dwm/util.h create mode 100644 dwm/util.o rename {suckless/slstatus => slstatus}/LICENSE (100%) rename {suckless/slstatus => slstatus}/Makefile (100%) rename {suckless/slstatus => slstatus}/arg.h (100%) rename {suckless/slstatus => slstatus}/components/battery.c (100%) rename {suckless/slstatus => slstatus}/components/battery.o (100%) rename {suckless/slstatus => slstatus}/components/cat.c (100%) rename {suckless/slstatus => slstatus}/components/cat.o (100%) rename {suckless/slstatus => slstatus}/components/cpu.c (100%) rename {suckless/slstatus => slstatus}/components/cpu.o (100%) rename {suckless/slstatus => slstatus}/components/datetime.c (100%) rename {suckless/slstatus => slstatus}/components/datetime.o (100%) rename {suckless/slstatus => slstatus}/components/disk.c (100%) rename {suckless/slstatus => slstatus}/components/disk.o (100%) rename {suckless/slstatus => slstatus}/components/entropy.c (100%) rename {suckless/slstatus => slstatus}/components/entropy.o (100%) rename {suckless/slstatus => slstatus}/components/hostname.c (100%) rename {suckless/slstatus => slstatus}/components/hostname.o (100%) rename {suckless/slstatus => slstatus}/components/ip.c (100%) rename {suckless/slstatus => slstatus}/components/ip.o (100%) rename {suckless/slstatus => slstatus}/components/kernel_release.c (100%) rename {suckless/slstatus => slstatus}/components/kernel_release.o (100%) rename {suckless/slstatus => slstatus}/components/keyboard_indicators.c (100%) rename {suckless/slstatus => slstatus}/components/keyboard_indicators.o (100%) rename {suckless/slstatus => slstatus}/components/keymap.c (100%) rename {suckless/slstatus => slstatus}/components/keymap.o (100%) rename {suckless/slstatus => slstatus}/components/load_avg.c (100%) rename {suckless/slstatus => slstatus}/components/load_avg.o (100%) rename {suckless/slstatus => slstatus}/components/netspeeds.c (100%) rename {suckless/slstatus => slstatus}/components/netspeeds.o (100%) rename {suckless/slstatus => slstatus}/components/num_files.c (100%) rename {suckless/slstatus => slstatus}/components/num_files.o (100%) rename {suckless/slstatus => slstatus}/components/pixVol.sh (100%) rename {suckless/slstatus => slstatus}/components/ram.c (100%) rename {suckless/slstatus => slstatus}/components/ram.o (100%) rename {suckless/slstatus => slstatus}/components/run_command.c (100%) rename {suckless/slstatus => slstatus}/components/run_command.o (100%) rename {suckless/slstatus => slstatus}/components/swap.c (100%) rename {suckless/slstatus => slstatus}/components/swap.o (100%) rename {suckless/slstatus => slstatus}/components/temperature.c (100%) rename {suckless/slstatus => slstatus}/components/temperature.o (100%) rename {suckless/slstatus => slstatus}/components/uptime.c (100%) rename {suckless/slstatus => slstatus}/components/uptime.o (100%) rename {suckless/slstatus => slstatus}/components/user.c (100%) rename {suckless/slstatus => slstatus}/components/user.o (100%) rename {suckless/slstatus => slstatus}/components/volume.c (100%) rename {suckless/slstatus => slstatus}/components/volume.o (100%) rename {suckless/slstatus => slstatus}/components/wifi.c (100%) rename {suckless/slstatus => slstatus}/components/wifi.o (100%) rename {suckless/slstatus => slstatus}/config.def.h (100%) rename {suckless/slstatus => slstatus}/config.h (93%) rename {suckless/slstatus => slstatus}/config.h~ (100%) rename {suckless/slstatus => slstatus}/config.mk (100%) rename {suckless/slstatus => slstatus}/slstatus (84%) rename {suckless/slstatus => slstatus}/slstatus.1 (100%) rename {suckless/slstatus => slstatus}/slstatus.c (100%) rename {suckless/slstatus => slstatus}/slstatus.h (100%) rename {suckless/slstatus => slstatus}/slstatus.o (55%) rename {suckless/slstatus => slstatus}/util.c (100%) rename {suckless/slstatus => slstatus}/util.h (100%) rename {suckless/slstatus => slstatus}/util.o (100%) rename {suckless/st => st}/LEGACY (100%) rename {suckless/st => st}/LICENSE (100%) rename {suckless/st => st}/Makefile (100%) rename {suckless/st => st}/README (100%) rename {suckless/st => st}/TODO (100%) rename {suckless/st => st}/arg.h (100%) rename {suckless/st => st}/boxdraw.c (100%) rename {suckless/st => st}/boxdraw_data.h (100%) rename {suckless/st => st}/config.def.h (100%) rename {suckless/st => st}/config.h (82%) rename {suckless/st => st}/config.h.save (100%) rename {suckless/st => st}/config.h.save.1 (100%) rename {suckless/st => st}/config.h.save.2 (100%) rename {suckless/st => st}/config.h.save.3 (100%) rename {suckless/st => st}/config.h~ (100%) rename {suckless/st => st}/config.mk (100%) rename {suckless/st => st}/graphics.c (100%) rename {suckless/st => st}/graphics.h (100%) rename {suckless/st => st}/hb.c (100%) rename {suckless/st => st}/hb.h (100%) rename {suckless/st => st}/hb.o (100%) rename {suckless/st => st}/icat-mini.sh (100%) rename {suckless/st => st}/khash.h (100%) rename {suckless/st => st}/kvec.h (100%) rename {suckless/st => st}/rowcolumn_diacritics_helpers.c (100%) rename {suckless/st => st}/st (74%) rename {suckless/st => st}/st-alpha-changealpha-20230519-b44f2ad.diff (100%) rename {suckless/st => st}/st.1 (100%) rename {suckless/st => st}/st.c (100%) rename {suckless/st => st}/st.h (100%) rename {suckless/st => st}/st.info (100%) rename {suckless/st => st}/st.o (100%) rename {suckless/st => st}/win.h (100%) rename {suckless/st => st}/x.c (100%) rename {suckless/st => st}/x.o (89%) delete mode 160000 suckless/dwm diff --git a/suckless/dmenu/LICENSE b/dmenu/LICENSE similarity index 100% rename from suckless/dmenu/LICENSE rename to dmenu/LICENSE diff --git a/suckless/dmenu/Makefile b/dmenu/Makefile similarity index 100% rename from suckless/dmenu/Makefile rename to dmenu/Makefile diff --git a/suckless/dmenu/README b/dmenu/README similarity index 100% rename from suckless/dmenu/README rename to dmenu/README diff --git a/suckless/dmenu/arg.h b/dmenu/arg.h similarity index 100% rename from suckless/dmenu/arg.h rename to dmenu/arg.h diff --git a/suckless/dmenu/config.def.h b/dmenu/config.def.h similarity index 100% rename from suckless/dmenu/config.def.h rename to dmenu/config.def.h diff --git a/suckless/dmenu/config.def.h.orig b/dmenu/config.def.h.orig similarity index 100% rename from suckless/dmenu/config.def.h.orig rename to dmenu/config.def.h.orig diff --git a/suckless/dmenu/config.h b/dmenu/config.h similarity index 100% rename from suckless/dmenu/config.h rename to dmenu/config.h diff --git a/suckless/dmenu/config.mk b/dmenu/config.mk similarity index 100% rename from suckless/dmenu/config.mk rename to dmenu/config.mk diff --git a/suckless/dmenu/dmenu b/dmenu/dmenu similarity index 100% rename from suckless/dmenu/dmenu rename to dmenu/dmenu diff --git a/suckless/dmenu/dmenu.1 b/dmenu/dmenu.1 similarity index 100% rename from suckless/dmenu/dmenu.1 rename to dmenu/dmenu.1 diff --git a/suckless/dmenu/dmenu.c b/dmenu/dmenu.c similarity index 100% rename from suckless/dmenu/dmenu.c rename to dmenu/dmenu.c diff --git a/suckless/dmenu/dmenu.c.orig b/dmenu/dmenu.c.orig similarity index 100% rename from suckless/dmenu/dmenu.c.orig rename to dmenu/dmenu.c.orig diff --git a/suckless/dmenu/dmenu.c.rej b/dmenu/dmenu.c.rej similarity index 100% rename from suckless/dmenu/dmenu.c.rej rename to dmenu/dmenu.c.rej diff --git a/suckless/dmenu/dmenu.o b/dmenu/dmenu.o similarity index 100% rename from suckless/dmenu/dmenu.o rename to dmenu/dmenu.o diff --git a/suckless/dmenu/dmenu_path b/dmenu/dmenu_path similarity index 100% rename from suckless/dmenu/dmenu_path rename to dmenu/dmenu_path diff --git a/suckless/dmenu/dmenu_run b/dmenu/dmenu_run similarity index 100% rename from suckless/dmenu/dmenu_run rename to dmenu/dmenu_run diff --git a/suckless/dmenu/drw.c b/dmenu/drw.c similarity index 100% rename from suckless/dmenu/drw.c rename to dmenu/drw.c diff --git a/suckless/dmenu/drw.h b/dmenu/drw.h similarity index 100% rename from suckless/dmenu/drw.h rename to dmenu/drw.h diff --git a/suckless/dmenu/drw.o b/dmenu/drw.o similarity index 100% rename from suckless/dmenu/drw.o rename to dmenu/drw.o diff --git a/suckless/dmenu/patch/dmenu-bar-height-5.2.diff b/dmenu/patch/dmenu-bar-height-5.2.diff similarity index 100% rename from suckless/dmenu/patch/dmenu-bar-height-5.2.diff rename to dmenu/patch/dmenu-bar-height-5.2.diff diff --git a/suckless/dmenu/patch/dmenu-border-5.2.diff b/dmenu/patch/dmenu-border-5.2.diff similarity index 100% rename from suckless/dmenu/patch/dmenu-border-5.2.diff rename to dmenu/patch/dmenu-border-5.2.diff diff --git a/suckless/dmenu/patch/dmenu-mousesupport-5.3.diff b/dmenu/patch/dmenu-mousesupport-5.3.diff similarity index 100% rename from suckless/dmenu/patch/dmenu-mousesupport-5.3.diff rename to dmenu/patch/dmenu-mousesupport-5.3.diff diff --git a/suckless/dmenu/patch/dmenu-xyw-5.2.diff b/dmenu/patch/dmenu-xyw-5.2.diff similarity index 100% rename from suckless/dmenu/patch/dmenu-xyw-5.2.diff rename to dmenu/patch/dmenu-xyw-5.2.diff diff --git a/suckless/dmenu/stest b/dmenu/stest similarity index 100% rename from suckless/dmenu/stest rename to dmenu/stest diff --git a/suckless/dmenu/stest.1 b/dmenu/stest.1 similarity index 100% rename from suckless/dmenu/stest.1 rename to dmenu/stest.1 diff --git a/suckless/dmenu/stest.c b/dmenu/stest.c similarity index 100% rename from suckless/dmenu/stest.c rename to dmenu/stest.c diff --git a/suckless/dmenu/stest.o b/dmenu/stest.o similarity index 100% rename from suckless/dmenu/stest.o rename to dmenu/stest.o diff --git a/suckless/dmenu/util.c b/dmenu/util.c similarity index 100% rename from suckless/dmenu/util.c rename to dmenu/util.c diff --git a/suckless/dmenu/util.h b/dmenu/util.h similarity index 100% rename from suckless/dmenu/util.h rename to dmenu/util.h diff --git a/suckless/dmenu/util.o b/dmenu/util.o similarity index 100% rename from suckless/dmenu/util.o rename to dmenu/util.o diff --git a/dwm/LICENSE b/dwm/LICENSE new file mode 100644 index 0000000..995172f --- /dev/null +++ b/dwm/LICENSE @@ -0,0 +1,38 @@ +MIT/X Consortium License + +© 2006-2019 Anselm R Garbe +© 2006-2009 Jukka Salmi +© 2006-2007 Sander van Dijk +© 2007-2011 Peter Hartlich +© 2007-2009 Szabolcs Nagy +© 2007-2009 Christof Musik +© 2007-2009 Premysl Hruby +© 2007-2008 Enno Gottox Boland +© 2008 Martin Hurton +© 2008 Neale Pickett +© 2009 Mate Nagy +© 2010-2016 Hiltjo Posthuma +© 2010-2012 Connor Lane Smith +© 2011 Christoph Lohmann <20h@r-36.net> +© 2015-2016 Quentin Rameau +© 2015-2016 Eric Pruitt +© 2016-2017 Markus Teich +© 2020-2022 Chris Down + +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. diff --git a/dwm/Makefile b/dwm/Makefile new file mode 100644 index 0000000..088a4b9 --- /dev/null +++ b/dwm/Makefile @@ -0,0 +1,67 @@ +# dwm - dynamic window manager +# See LICENSE file for copyright and license details. + +include config.mk + +SRC = drw.c dwm.c util.c +OBJ = ${SRC:.c=.o} + +# FreeBSD users, prefix all ifdef, else and endif statements with a . for this to work (e.g. .ifdef) + +ifdef YAJLLIBS +all: options dwm dwm-msg +else +all: options dwm +endif + +options: + @echo dwm build options: + @echo "CFLAGS = ${CFLAGS}" + @echo "LDFLAGS = ${LDFLAGS}" + @echo "CC = ${CC}" + +.c.o: + ${CC} -c ${CFLAGS} $< + +${OBJ}: config.h config.mk + +dwm: ${OBJ} + ${CC} -o $@ ${OBJ} ${LDFLAGS} + +ifdef YAJLLIBS +dwm-msg: + ${CC} -o $@ patch/ipc/dwm-msg.c ${LDFLAGS} +endif + +clean: + rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz + rm -f dwm-msg + +dist: clean + mkdir -p dwm-${VERSION} + cp -R LICENSE Makefile README config.def.h config.mk\ + dwm.1 drw.h util.h ${SRC} dwm.png transient.c dwm-${VERSION} + tar -cf dwm-${VERSION}.tar dwm-${VERSION} + gzip dwm-${VERSION}.tar + rm -rf dwm-${VERSION} + +install: all + mkdir -p ${DESTDIR}${PREFIX}/bin + cp -f dwm ${DESTDIR}${PREFIX}/bin +ifdef YAJLLIBS + cp -f dwm-msg ${DESTDIR}${PREFIX}/bin +endif + cp -f patch/dwmc ${DESTDIR}${PREFIX}/bin + chmod 755 ${DESTDIR}${PREFIX}/bin/dwm +ifdef YAJLLIBS + chmod 755 ${DESTDIR}${PREFIX}/bin/dwm-msg +endif + mkdir -p ${DESTDIR}${MANPREFIX}/man1 + sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1 + chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1 + +uninstall: + rm -f ${DESTDIR}${PREFIX}/bin/dwm\ + ${DESTDIR}${MANPREFIX}/man1/dwm.1 + +.PHONY: all options clean dist install uninstall diff --git a/dwm/README.md b/dwm/README.md new file mode 100644 index 0000000..e754d08 --- /dev/null +++ b/dwm/README.md @@ -0,0 +1,58 @@ +# DWM +DWM is my favorite window manager by far due to its simplicity, portability, and low resource usage. However, it requires a decent amount of tweaking if you want to be able to use it for standard tasks. That's what I've aimed to do here, creating a user-friendly environment and memorable keybinds. + +## Compiling +### Dependencies +X11, Xinerama, xcb, freetype +### Instructions +Run `./configure` to properly set up `config.mk`. +#### Linux +`make && sudo make install` +#### FreeBSD, OpenBSD +`gmake && doas gmake install` + +## Patches applied +``` +dwmblocks (statuscmd) +dwmblocks (SIGUSR1) +bar layout symbol -- show window layout in status bar +bar status -- show status in bar +bar tag symbols -- show tag symbols in bar +bar window title -- show window title in bar +bar alpha -- semi-transparency on bar +bar hide vacant tags -- hide tags with no windows +attach aside -- add new windows to stack instead of master +cool autostart -- execute commands on start and have processes owned by dwm +dwmc -- use dwmc program to execute dwm commands (for scriptability) +fullscreen -- applies monocle layout on active window and hides bar +moveresize -- resize dwm windows with keybinds +movestack -- allows to move windows in stack and to become master +no transparent borders -- make window borders always solid +scratchpads -- allow for scratchpad terminals +swallow -- hide terminal window when it spawns a window and freezes itself (not working on OpenBSD) +togglefullscreen -- use a keybind to make a window fullscreen or not +vanitygaps -- add gaps between all windows +``` + +## Software Made to Work With This +- [DWMBlocks](https://github.com/swindlesmccoop/dwmblocks) +- [DMenu](https://github.com/swindlesmccoop/dmenu) +- [ST](https://github.com/swindlesmccoop/st) + +## Keybinds +All keybinds can be found by running `man dwm`, but here are the important ones: +- `Super + Enter` - Spawn terminal (st) +- `Super + Shift + Enter`, `F12` - Toggle scratchpad terminal +- `Super + h/l` - Shrink/enlarge master window +- `Super + d` - dmenu\_run (program launcher) +- `Super + q` - Kill window +- `Super + b` - Toggle status bar +- `Super + f` - Toggle fullscreen +- `Super + m` - Set window as master +- `Super + o/O` - Increase/decrease number of masters +- `Super + j/k` - Move focus down/up +- `Super + J/K` - Move window in stack down/up +- `Super + E`, `Super + Q` - Kill DWM +- `Super + Space` - Set all windows to Floating mode +- `Super + [Arrow]` - Move window in direction of arrow pressed +- `Super + Shift + [Arrow]` - Expand/shrink window in direction of arrow pressed diff --git a/dwm/config.h b/dwm/config.h new file mode 100644 index 0000000..8801bfa --- /dev/null +++ b/dwm/config.h @@ -0,0 +1,389 @@ +/* See LICENSE file for copyright and license details. */ + +/* appearance */ +static const unsigned int borderpx = 3; /* border pixel of windows */ +static const unsigned int snap = 0; /* snap pixel */ +static const int swallowfloating = 1; /* 1 means swallow floating windows by default */ +static const unsigned int gappih = 10; /* horiz inner gap between windows */ +static const unsigned int gappiv = 10; /* vert inner gap between windows */ +static const unsigned int gappoh = 10; /* horiz outer gap between windows and screen edge */ +static const unsigned int gappov = 30; /* vert outer gap between windows and screen edge */ +static const int smartgaps_fact = 1; /* gap factor when there is only one client; 0 = no gaps, 3 = 3x outer gaps */ +static const int showbar = 1; /* 0 means no bar */ +static const int topbar = 1; /* 0 means bottom bar */ +/* Status is to be shown on: -1 (all monitors), 0 (a specific monitor by index), 'A' (active monitor) */ +static const int statusmon = 'A'; + +/* Indicators: see patch/bar_indicators.h for options */ +static int tagindicatortype = INDICATOR_NONE; +static int tiledindicatortype = INDICATOR_NONE; +static int floatindicatortype = INDICATOR_NONE; +static const char *fonts[] = { "monospace:size=12" }; +static const char dmenufont[] = "monospace:size=12"; + +static char c000000[] = "#000000"; + +static char normfgcolor[] = "#bbbbbb"; +static char normbgcolor[] = "#222222"; +static char normbordercolor[] = "#444444"; +static char normfloatcolor[] = "#db8fd9"; + +static char selfgcolor[] = "#eeeeee"; +static char selbgcolor[] = "#005577"; +static char selbordercolor[] = "#005577"; +static char selfloatcolor[] = "#005577"; + +static char titlenormfgcolor[] = "#bbbbbb"; +static char titlenormbgcolor[] = "#222222"; +static char titlenormbordercolor[] = "#444444"; +static char titlenormfloatcolor[] = "#db8fd9"; + +static char titleselfgcolor[] = "#eeeeee"; +static char titleselbgcolor[] = "#005577"; +static char titleselbordercolor[] = "#005577"; +static char titleselfloatcolor[] = "#005577"; + +static char tagsnormfgcolor[] = "#bbbbbb"; +static char tagsnormbgcolor[] = "#222222"; +static char tagsnormbordercolor[] = "#444444"; +static char tagsnormfloatcolor[] = "#db8fd9"; + +static char tagsselfgcolor[] = "#eeeeee"; +static char tagsselbgcolor[] = "#005577"; +static char tagsselbordercolor[] = "#005577"; +static char tagsselfloatcolor[] = "#005577"; + +static char hidnormfgcolor[] = "#005577"; +static char hidselfgcolor[] = "#227799"; +static char hidnormbgcolor[] = "#222222"; +static char hidselbgcolor[] = "#222222"; + +static char urgfgcolor[] = "#bbbbbb"; +static char urgbgcolor[] = "#222222"; +static char urgbordercolor[] = "#ff0000"; +static char urgfloatcolor[] = "#db8fd9"; + + + +static const unsigned int baralpha = 0xff; +static const unsigned int borderalpha = OPAQUE; +static const unsigned int alphas[][3] = { + /* fg bg border */ + [SchemeNorm] = { OPAQUE, baralpha, borderalpha }, + [SchemeSel] = { OPAQUE, baralpha, borderalpha }, + [SchemeTitleNorm] = { OPAQUE, baralpha, borderalpha }, + [SchemeTitleSel] = { OPAQUE, baralpha, borderalpha }, + [SchemeTagsNorm] = { OPAQUE, baralpha, borderalpha }, + [SchemeTagsSel] = { OPAQUE, baralpha, borderalpha }, + [SchemeHidNorm] = { OPAQUE, baralpha, borderalpha }, + [SchemeHidSel] = { OPAQUE, baralpha, borderalpha }, + [SchemeUrg] = { OPAQUE, baralpha, borderalpha }, +}; + +static char *colors[][ColCount] = { + /* fg bg border float */ + [SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor, normfloatcolor }, + [SchemeSel] = { selfgcolor, selbgcolor, selbordercolor, selfloatcolor }, + [SchemeTitleNorm] = { titlenormfgcolor, titlenormbgcolor, titlenormbordercolor, titlenormfloatcolor }, + [SchemeTitleSel] = { titleselfgcolor, titleselbgcolor, titleselbordercolor, titleselfloatcolor }, + [SchemeTagsNorm] = { tagsnormfgcolor, tagsnormbgcolor, tagsnormbordercolor, tagsnormfloatcolor }, + [SchemeTagsSel] = { tagsselfgcolor, tagsselbgcolor, tagsselbordercolor, tagsselfloatcolor }, + [SchemeHidNorm] = { hidnormfgcolor, hidnormbgcolor, c000000, c000000 }, + [SchemeHidSel] = { hidselfgcolor, hidselbgcolor, c000000, c000000 }, + [SchemeUrg] = { urgfgcolor, urgbgcolor, urgbordercolor, urgfloatcolor }, +}; + + + +static const char *const autostart[] = { + //"sh", "-c", "$HOME/.xprofile", NULL, + NULL /* terminate */ +}; + +const char *spcmd1[] = {"st", "-n", "spterm", "-g", "120x34", NULL }; +static Sp scratchpads[] = { + /* name cmd */ + {"spterm", spcmd1}, +}; + +/* Tags + * In a traditional dwm the number of tags in use can be changed simply by changing the number + * of strings in the tags array. This build does things a bit different which has some added + * benefits. If you need to change the number of tags here then change the NUMTAGS macro in dwm.c. + * + * Examples: + * + * 1) static char *tagicons[][NUMTAGS*2] = { + * [DEFAULT_TAGS] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I" }, + * } + * + * 2) static char *tagicons[][1] = { + * [DEFAULT_TAGS] = { "•" }, + * } + * + * The first example would result in the tags on the first monitor to be 1 through 9, while the + * tags for the second monitor would be named A through I. A third monitor would start again at + * 1 through 9 while the tags on a fourth monitor would also be named A through I. Note the tags + * count of NUMTAGS*2 in the array initialiser which defines how many tag text / icon exists in + * the array. This can be changed to *3 to add separate icons for a third monitor. + * + * For the second example each tag would be represented as a bullet point. Both cases work the + * same from a technical standpoint - the icon index is derived from the tag index and the monitor + * index. If the icon index is is greater than the number of tag icons then it will wrap around + * until it an icon matches. Similarly if there are two tag icons then it would alternate between + * them. This works seamlessly with alternative tags and alttagsdecoration patches. + */ +static char *tagicons[][NUMTAGS] = { + [DEFAULT_TAGS] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }, + [ALTERNATIVE_TAGS] = { "A", "B", "C", "D", "E", "F", "G", "H", "I" }, + [ALT_TAGS_DECORATION] = { "<1>", "<2>", "<3>", "<4>", "<5>", "<6>", "<7>", "<8>", "<9>" }, +}; + + +/* There are two options when it comes to per-client rules: + * - a typical struct table or + * - using the RULE macro + * + * A traditional struct table looks like this: + * // class instance title wintype tags mask isfloating monitor + * { "Gimp", NULL, NULL, NULL, 1 << 4, 0, -1 }, + * { "Firefox", NULL, NULL, NULL, 1 << 7, 0, -1 }, + * + * The RULE macro has the default values set for each field allowing you to only + * specify the values that are relevant for your rule, e.g. + * + * RULE(.class = "Gimp", .tags = 1 << 4) + * RULE(.class = "Firefox", .tags = 1 << 7) + * + * Refer to the Rule struct definition for the list of available fields depending on + * the patches you enable. + */ +static const Rule rules[] = { + /* xprop(1): + * WM_CLASS(STRING) = instance, class + * WM_NAME(STRING) = title + * WM_WINDOW_ROLE(STRING) = role + * _NET_WM_WINDOW_TYPE(ATOM) = wintype + */ + RULE(.wintype = WTYPE "DIALOG", .isfloating = 1) + RULE(.wintype = WTYPE "UTILITY", .isfloating = 1) + RULE(.wintype = WTYPE "TOOLBAR", .isfloating = 1) + RULE(.wintype = WTYPE "SPLASH", .isfloating = 1) + //RULE(.class = "Gimp", .tags = 1 << 4) + //RULE(.class = "Firefox", .tags = 1 << 7) + RULE(.instance = "spterm", .tags = SPTAG(0), .isfloating = 1) +}; + + + +/* Bar rules allow you to configure what is shown where on the bar, as well as + * introducing your own bar modules. + * + * monitor: + * -1 show on all monitors + * 0 show on monitor 0 + * 'A' show on active monitor (i.e. focused / selected) (or just -1 for active?) + * bar - bar index, 0 is default, 1 is extrabar + * alignment - how the module is aligned compared to other modules + * widthfunc, drawfunc, clickfunc - providing bar module width, draw and click functions + * name - does nothing, intended for visual clue and for logging / debugging + */ +static const BarRule barrules[] = { + /* monitor bar alignment widthfunc drawfunc clickfunc hoverfunc name */ + { -1, 0, BAR_ALIGN_LEFT, width_tags, draw_tags, click_tags, hover_tags, "tags" }, + { -1, 0, BAR_ALIGN_LEFT, width_ltsymbol, draw_ltsymbol, click_ltsymbol, NULL, "layout" }, + { statusmon, 0, BAR_ALIGN_RIGHT, width_status, draw_status, click_status, NULL, "status" }, + { -1, 0, BAR_ALIGN_NONE, width_wintitle, draw_wintitle, click_wintitle, NULL, "wintitle" }, +}; + +/* layout(s) */ +static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ +static const int nmaster = 1; /* number of clients in master area */ +static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */ +static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ + + + +static const Layout layouts[] = { + /* symbol arrange function */ + { " master", tile }, /* first entry is default */ + { " float", NULL }, /* no layout function means floating behavior */ +}; + +/* key definitions */ +#define MODKEY Mod4Mask +#define TAGKEYS(KEY,TAG) \ + { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ + { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, + +/* helper for spawning shell commands in the pre dwm-5.0 fashion */ +#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } + +/* commands */ +static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ +static const char *dmenucmd[] = { + "dmenu_run", + "-m", dmenumon, + "-fn", dmenufont, + "-nb", normbgcolor, + "-nf", normfgcolor, + "-sb", selbgcolor, + "-sf", selfgcolor, + NULL +}; + +static const char *termcmd[] = { "st", NULL }; + +///////////////////////////////////////////////KEYBINDS////////////////////////////////////////////// +#include +//different commands per OS +#ifdef __linux__ + #define VOL_UP "pamixer --allow-boost -i 10; kill -44 $(pidof dwmblocks)" + #define XK_UP "pamixer --allow-boost -i 5; kill -44 $(pidof dwmblocks)" + #define VOL_DOWN "pamixer --allow-boost -d 10; kill -44 $(pidof dwmblocks)" + #define XK_DOWN "pamixer --allow-boost -d 5; kill -44 $(pidof dwmblocks)" + #define VOL_MUTE "pamixer -t; kill -44 $(pidof dwmblocks)" + #define VOL_KILL "kill -44 $(pidof dwmblocks)" +#elif __OpenBSD__ + #define VOL_UP "sndioctl output.level=+0.10; pkill -SIGUSR1 dwmblocks" + #define XK_UP "sndioctl output.level=+0.05; pkill -SIGUSR1 dwmblocks" + #define VOL_DOWN "sndioctl output.level=-0.10; pkill -SIGUSR1 dwmblocks" + #define XK_DOWN "sndioctl output.level=-0.05; pkill -SIGUSR1 dwmblocks" + #define VOL_MUTE "sndioctl output.mute=!; pkill -SIGUSR1 dwmblocks" + #define VOL_KILL "pkill -SIGUSR1 dwmblocks" +#elif __FreeBSD__ + #define VOL_UP "sndioctl output.level=+0.10" + #define XK_UP "sndioctl output.level=+0.05" + #define VOL_DOWN "sndioctl output.level=-0.10" + #define XK_DOWN "sndioctl output.level=-0.05" + #define VOL_MUTE "sndioctl output.level=-1" + #define VOL_KILL "pkill -SIGUSR2 dwmblocks" +#endif + +static Key keys[] = { + /*modifierkey function argument */ + { MODKEY, XK_r, spawn, {.v = dmenucmd } }, + { MODKEY, XK_j, focusstack, {.i = +1 } }, + { MODKEY, XK_k, focusstack, {.i = -1 } }, + { MODKEY, XK_Down, moveresize, {.v = "0x 25y 0w 0h" } }, + { MODKEY, XK_Up, moveresize, {.v = "0x -25y 0w 0h" } }, + { MODKEY, XK_Right, moveresize, {.v = "25x 0y 0w 0h" } }, + { MODKEY, XK_Left, moveresize, {.v = "-25x 0y 0w 0h" } }, + { MODKEY|ShiftMask, XK_Down, moveresize, {.v = "0x 0y 0w 25h" } }, + { MODKEY|ShiftMask, XK_Up, moveresize, {.v = "0x 0y 0w -25h" } }, + { MODKEY|ShiftMask, XK_Right, moveresize, {.v = "0x 0y 25w 0h" } }, + { MODKEY|ShiftMask, XK_Left, moveresize, {.v = "0x 0y -25w 0h" } }, + { MODKEY, XK_Tab, view, {0} }, + { MODKEY|ShiftMask, XK_F5, xrdb, {.v = NULL } }, + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + { MODKEY, XK_grave, togglescratch, {.ui = 0 } }, + { MODKEY|ControlMask, XK_grave, setscratch, {.ui = 0 } }, + { MODKEY|ShiftMask, XK_grave, removescratch, {.ui = 0 } }, + { MODKEY, XK_w, togglefullscreen, {0} }, + { MODKEY, XK_0, view, {.ui = ~SPTAGMASK } }, + { MODKEY|ShiftMask, XK_0, tag, {.ui = ~SPTAGMASK } }, + + TAGKEYS( XK_1, 0) + TAGKEYS( XK_2, 1) + TAGKEYS( XK_3, 2) + TAGKEYS( XK_4, 3) + TAGKEYS( XK_5, 4) + TAGKEYS( XK_6, 5) + TAGKEYS( XK_7, 6) + TAGKEYS( XK_8, 7) + TAGKEYS( XK_9, 8) + + { MODKEY, XK_h, setmfact, {.f = -0.05} }, + { MODKEY, XK_l, setmfact, {.f = +0.05} }, + { MODKEY|ShiftMask, XK_q,quit, {0} }, + { MODKEY|ShiftMask, XK_e,quit, {0} }, + { MODKEY, XK_b, togglebar, {0} }, + { MODKEY, XK_d, spawn, {.v = dmenucmd } }, + { MODKEY, XK_w, togglefullscreen, {0} }, + { MODKEY, XK_m, zoom, {0} }, + { MODKEY, XK_o, incnmaster, {.i = +1 } }, + { MODKEY, XK_Return, spawn, {.v = termcmd } }, + { MODKEY|ShiftMask, XK_o, incnmaster, {.i = -1 } }, + { MODKEY, XK_s, killclient, {0} }, + { MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } }, + { MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } }, + { MODKEY|ShiftMask, XK_Return, togglescratch, {.ui = 0 } }, + { 0, XK_F12, togglescratch, {.ui = 0 } }, + + //volume control + { Mod1Mask, XK_equal, spawn, SHCMD(VOL_UP) }, + { Mod1Mask, XK_minus, spawn, SHCMD(VOL_DOWN) }, + { Mod1Mask, XK_m, spawn, SHCMD(VOL_MUTE) }, + { 0, XF86XK_AudioMute, spawn, SHCMD(VOL_MUTE) }, + { 0, XF86XK_AudioRaiseVolume, spawn, SHCMD(XK_UP) }, + { 0, XF86XK_AudioLowerVolume, spawn, SHCMD(XK_DOWN) }, + + { 0, XK_Print, spawn, SHCMD("screenie")}, +}; +///////////////////////////////////////////////////////////////////////////////////////////////////// + + +/* button definitions */ +/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ +static Button buttons[] = { + /* click event mask button function argument */ + { ClkLtSymbol, 0, Button1, setlayout, {0} }, + { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, + { ClkWinTitle, 0, Button2, zoom, {0} }, + { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, + { ClkClientWin, MODKEY, Button1, movemouse, {0} }, + { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, + { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, + { ClkTagBar, 0, Button1, view, {0} }, + { ClkTagBar, 0, Button3, toggleview, {0} }, + { ClkTagBar, MODKEY, Button1, tag, {0} }, + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, +}; + +/* signal definitions */ +/* signum must be greater than 0 */ +/* trigger signals using `xsetroot -name "fsignal: [ ]"` */ +static Signal signals[] = { + /* signum function */ + { "focusstack", focusstack }, + { "setmfact", setmfact }, + { "togglebar", togglebar }, + { "incnmaster", incnmaster }, + { "togglefloating", togglefloating }, + { "focusmon", focusmon }, + { "tagmon", tagmon }, + { "zoom", zoom }, + { "incrgaps", incrgaps }, + { "incrigaps", incrigaps }, + { "incrogaps", incrogaps }, + { "incrihgaps", incrihgaps }, + { "incrivgaps", incrivgaps }, + { "incrohgaps", incrohgaps }, + { "incrovgaps", incrovgaps }, + { "togglegaps", togglegaps }, + { "defaultgaps", defaultgaps }, + { "setgaps", setgapsex }, + { "view", view }, + { "viewall", viewallex }, + { "viewex", viewex }, + { "toggleview", toggleview }, + { "toggleviewex", toggleviewex }, + { "tag", tag }, + { "tagall", tagallex }, + { "tagex", tagex }, + { "toggletag", toggletag }, + { "toggletagex", toggletagex }, + { "togglefullscreen", togglefullscreen }, + { "fullscreen", fullscreen }, + { "togglescratch", togglescratch }, + { "killclient", killclient }, + { "xrdb", xrdb }, + { "quit", quit }, + { "setlayout", setlayout }, + { "setlayoutex", setlayoutex }, +}; + diff --git a/dwm/config.mk b/dwm/config.mk new file mode 100644 index 0000000..7b3b027 --- /dev/null +++ b/dwm/config.mk @@ -0,0 +1,55 @@ +# dwm version +VERSION = 6.3 + +# Customize below to fit your system + +# paths +PREFIX = /usr/local +MANPREFIX = ${PREFIX}/share/man + +X11INC = /usr/X11R6/include +X11LIB = /usr/X11R6/lib + +# Xinerama, comment if you don't want it +XINERAMALIBS = -lXinerama +XINERAMAFLAGS = -DXINERAMA + +# freetype +FREETYPELIBS = -lfontconfig -lXft +FREETYPEINC = /usr/include/freetype2 + +# Uncomment this for the alpha patch and the winicon patch (BAR_ALPHA_PATCH, BAR_WINICON_PATCH) +XRENDER = -lXrender + +# Uncomment this for the mdpcontrol patch / MDPCONTROL_PATCH +#MPDCLIENT = -lmpdclient + +# Uncomment for the pango patch / BAR_PANGO_PATCH +#PANGOINC = `pkg-config --cflags xft pango pangoxft` +#PANGOLIB = `pkg-config --libs xft pango pangoxft` + +# Uncomment for the ipc patch / IPC_PATCH +#YAJLLIBS = -lyajl +#YAJLINC = -I/usr/include/yajl + +# Uncomment this for the rounded corners patch / ROUNDED_CORNERS_PATCH +#XEXTLIB = -lXext + +# Uncomment this for the swallow patch / SWALLOW_PATCH +XCBLIBS = -lX11-xcb -lxcb -lxcb-res + +# This is needed for the winicon and tagpreview patches / BAR_WINICON_PATCH / BAR_TAGPREVIEW_PATCH +#IMLIB2LIBS = -lImlib2 + +# includes and libs +INCS = -I${X11INC} -I${FREETYPEINC} ${YAJLINC} ${PANGOINC} +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XRENDER} ${MPDCLIENT} ${XEXTLIB} ${XCBLIBS} ${KVMLIB} ${PANGOLIB} ${YAJLLIBS} ${IMLIB2LIBS} + +# flags +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} +CFLAGS = -std=c99 -pedantic -Wall -Wno-unused-function -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} +LDFLAGS = ${LIBS} + +# compiler and linker +CC = cc diff --git a/dwm/configure b/dwm/configure new file mode 100755 index 0000000..69e51e6 --- /dev/null +++ b/dwm/configure @@ -0,0 +1,40 @@ +#!/bin/sh + +#OS=$(printf 'Linux\nOpenBSD\nFreeBSD\nSolaris' | fzf --layout=reverse --height 40%) +OS=$(uname) + +case $OS in + Linux) cp -f mkconfig/config.mk.linux config.mk ;; + OpenBSD) cp -f mkconfig/config.mk.openbsd config.mk ;; + FreeBSD) cp -f mkconfig/config.mk.freebsd config.mk ;; + Solaris) cp -f mkconfig/config.mk.solaris config.mk ;; +esac + +#sed -i 's/##/#/g' config.mk +#sed -i '14 s/^/#/' config.mk +#sed -i '15 s/^/#/' config.mk +#sed -i '25 s/^/#/' config.mk +#sed -i '27 s/^/#/' config.mk +#sed -i '29 s/^/#/' config.mk +#sed -i '65 s/^/#/' config.mk +#sed -i '66 s/^/#/' config.mk +#sed -i 's/##/#/g' config.mk +# +#if [ "$OS" = "Linux" ]; then +# true +#else if [ "$OS" = "OpenBSD" ]; then +# sed -i '27 s/.//' config.mk +# sed -i '29 s/.//' config.mk +#else if [ "$OS" = "FreeBSD" ]; then +# sed -i '14 s/.//' config.mk +# sed -i '15 s/.//' config.mk +# sed -i '25 s/.//' config.mk +#else if [ "$OS" = "Solaris" ]; then +# sed -i '65 s/.//' config.mk +# sed -i '66 s/.//' config.mk +#fi +#fi +#fi +#fi +# +#sed -i 's/##/#/g' config.mk diff --git a/dwm/drw.c b/dwm/drw.c new file mode 100644 index 0000000..2297da4 --- /dev/null +++ b/dwm/drw.c @@ -0,0 +1,451 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include + +#include "drw.h" +#include "util.h" + +#define UTF_INVALID 0xFFFD +#define UTF_SIZ 4 + +static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; +static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; +static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; +static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; + + +static long +utf8decodebyte(const char c, size_t *i) +{ + for (*i = 0; *i < (UTF_SIZ + 1); ++(*i)) + if (((unsigned char)c & utfmask[*i]) == utfbyte[*i]) + return (unsigned char)c & ~utfmask[*i]; + return 0; +} + +static size_t +utf8validate(long *u, size_t i) +{ + if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) + *u = UTF_INVALID; + for (i = 1; *u > utfmax[i]; ++i) + ; + return i; +} + +static size_t +utf8decode(const char *c, long *u, size_t clen) +{ + size_t i, j, len, type; + long udecoded; + + *u = UTF_INVALID; + if (!clen) + return 0; + udecoded = utf8decodebyte(c[0], &len); + if (!BETWEEN(len, 1, UTF_SIZ)) + return 1; + for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { + udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); + if (type) + return j; + } + if (j < len) + return 0; + *u = udecoded; + utf8validate(u, len); + + return len; +} + +Drw * +drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h, Visual *visual, unsigned int depth, Colormap cmap) +{ + Drw *drw = ecalloc(1, sizeof(Drw)); + + drw->dpy = dpy; + drw->screen = screen; + drw->root = root; + drw->w = w; + drw->h = h; + + drw->visual = visual; + drw->depth = depth; + drw->cmap = cmap; + drw->drawable = XCreatePixmap(dpy, root, w, h, depth); + drw->gc = XCreateGC(dpy, drw->drawable, 0, NULL); + XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); + + return drw; +} + +void +drw_resize(Drw *drw, unsigned int w, unsigned int h) +{ + if (!drw) + return; + + drw->w = w; + drw->h = h; + if (drw->drawable) + XFreePixmap(drw->dpy, drw->drawable); + drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, drw->depth); +} + +void +drw_free(Drw *drw) +{ + XFreePixmap(drw->dpy, drw->drawable); + XFreeGC(drw->dpy, drw->gc); + drw_fontset_free(drw->fonts); + free(drw); +} + +/* This function is an implementation detail. Library users should use + * drw_fontset_create instead. + */ +static Fnt * +xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) +{ + Fnt *font; + XftFont *xfont = NULL; + FcPattern *pattern = NULL; + + if (fontname) { + /* Using the pattern found at font->xfont->pattern does not yield the + * same substitution results as using the pattern returned by + * FcNameParse; using the latter results in the desired fallback + * behaviour whereas the former just results in missing-character + * rectangles being drawn, at least with some fonts. */ + if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) { + fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname); + return NULL; + } + if (!(pattern = FcNameParse((FcChar8 *) fontname))) { + fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname); + XftFontClose(drw->dpy, xfont); + return NULL; + } + } else if (fontpattern) { + if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { + fprintf(stderr, "error, cannot load font from pattern.\n"); + return NULL; + } + } else { + die("no font specified."); + } + + /* Do not allow using color fonts. This is a workaround for a BadLength + * error from Xft with color glyphs. Modelled on the Xterm workaround. See + * https://bugzilla.redhat.com/show_bug.cgi?id=1498269 + * https://lists.suckless.org/dev/1701/30932.html + * https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=916349 + * and lots more all over the internet. + */ + FcBool iscol; + if (FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) { + XftFontClose(drw->dpy, xfont); + return NULL; + } + + font = ecalloc(1, sizeof(Fnt)); + font->xfont = xfont; + font->pattern = pattern; + font->h = xfont->ascent + xfont->descent; + font->dpy = drw->dpy; + + return font; +} + +static void +xfont_free(Fnt *font) +{ + if (!font) + return; + if (font->pattern) + FcPatternDestroy(font->pattern); + XftFontClose(font->dpy, font->xfont); + free(font); +} + +Fnt* +drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) +{ + Fnt *cur, *ret = NULL; + size_t i; + + if (!drw || !fonts) + return NULL; + + for (i = 1; i <= fontcount; i++) { + if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) { + cur->next = ret; + ret = cur; + } + } + return (drw->fonts = ret); +} + +void +drw_fontset_free(Fnt *font) +{ + if (font) { + drw_fontset_free(font->next); + xfont_free(font); + } +} + +void +drw_clr_create( + Drw *drw, + Clr *dest, + const char *clrname + , unsigned int alpha +) { + if (!drw || !dest || !clrname) + return; + + if (!XftColorAllocName(drw->dpy, drw->visual, drw->cmap, + clrname, dest)) + die("error, cannot allocate color '%s'", clrname); + + dest->pixel = (dest->pixel & 0x00ffffffU) | (alpha << 24); +} + +/* Wrapper to create color schemes. The caller has to call free(3) on the + * returned color scheme when done using it. */ +Clr * +drw_scm_create( + Drw *drw, + char *clrnames[], + const unsigned int alphas[], + size_t clrcount +) { + size_t i; + Clr *ret; + + /* need at least two colors for a scheme */ + if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor)))) + return NULL; + + for (i = 0; i < clrcount; i++) + drw_clr_create(drw, &ret[i], clrnames[i], alphas[i]); + return ret; +} + +void +drw_setfontset(Drw *drw, Fnt *set) +{ + if (drw) + drw->fonts = set; +} + +void +drw_setscheme(Drw *drw, Clr *scm) +{ + if (drw) + drw->scheme = scm; +} + + +void +drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) +{ + if (!drw || !drw->scheme) + return; + XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel); + if (filled) + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); + else + XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1); +} + +int +drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, Bool ignored) +{ + char buf[1024]; + int ty; + unsigned int ew; + XftDraw *d = NULL; + Fnt *usedfont, *curfont, *nextfont; + size_t i, len; + int utf8strlen, utf8charlen, render = x || y || w || h; + long utf8codepoint = 0; + const char *utf8str; + FcCharSet *fccharset; + FcPattern *fcpattern; + FcPattern *match; + XftResult result; + int charexists = 0; + + if (!drw || (render && !drw->scheme) || !text || !drw->fonts) + return 0; + + if (!render) { + w = ~w; + } else { + XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); + d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap); + x += lpad; + w -= lpad; + } + + usedfont = drw->fonts; + while (1) { + utf8strlen = 0; + utf8str = text; + nextfont = NULL; + while (*text) { + utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ); + for (curfont = drw->fonts; curfont; curfont = curfont->next) { + charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); + if (charexists) { + if (curfont == usedfont) { + utf8strlen += utf8charlen; + text += utf8charlen; + } else { + nextfont = curfont; + } + break; + } + } + + if (!charexists || nextfont) + break; + else + charexists = 0; + } + + if (utf8strlen) { + drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL); + /* shorten text if necessary */ + for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; drw_font_getexts(usedfont, utf8str, len, &ew, NULL)) + len--; + + if (len) { + memcpy(buf, utf8str, len); + buf[len] = '\0'; + if (len < utf8strlen) + for (i = len; i && i > len - 3; buf[--i] = '.') + ; /* NOP */ + + if (render) { + ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; + XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], + usedfont->xfont, x, ty, (XftChar8 *)buf, len); + } + x += ew; + w -= ew; + } + } + + if (!*text) { + break; + } else if (nextfont) { + charexists = 0; + usedfont = nextfont; + } else { + /* Regardless of whether or not a fallback font is found, the + * character must be drawn. */ + charexists = 1; + + fccharset = FcCharSetCreate(); + FcCharSetAddChar(fccharset, utf8codepoint); + + if (!drw->fonts->pattern) { + /* Refer to the comment in xfont_create for more information. */ + die("the first font in the cache must be loaded from a font string."); + } + + fcpattern = FcPatternDuplicate(drw->fonts->pattern); + FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); + FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); + FcPatternAddBool(fcpattern, FC_COLOR, FcFalse); + + FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); + FcDefaultSubstitute(fcpattern); + match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result); + + FcCharSetDestroy(fccharset); + FcPatternDestroy(fcpattern); + + if (match) { + usedfont = xfont_create(drw, NULL, match); + if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) { + for (curfont = drw->fonts; curfont->next; curfont = curfont->next) + ; /* NOP */ + curfont->next = usedfont; + } else { + xfont_free(usedfont); + usedfont = drw->fonts; + } + } + } + } + if (d) + XftDrawDestroy(d); + + return x + (render ? w : 0); +} + + +void +drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) +{ + if (!drw) + return; + + XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); + XSync(drw->dpy, False); +} + +unsigned int +drw_fontset_getwidth(Drw *drw, const char *text, Bool markup) +{ + if (!drw || !drw->fonts || !text) + return 0; + return drw_text(drw, 0, 0, 0, 0, 0, text, 0, markup); +} + +void +drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) +{ + XGlyphInfo ext; + + if (!font || !text) + return; + + XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); + if (w) + *w = ext.xOff; + if (h) + *h = font->h; +} + +Cur * +drw_cur_create(Drw *drw, int shape) +{ + Cur *cur; + + if (!drw || !(cur = ecalloc(1, sizeof(Cur)))) + return NULL; + + cur->cursor = XCreateFontCursor(drw->dpy, shape); + + return cur; +} + +void +drw_cur_free(Drw *drw, Cur *cursor) +{ + if (!cursor) + return; + + XFreeCursor(drw->dpy, cursor->cursor); + free(cursor); +} + diff --git a/dwm/drw.h b/dwm/drw.h new file mode 100644 index 0000000..0eff1ce --- /dev/null +++ b/dwm/drw.h @@ -0,0 +1,72 @@ +/* See LICENSE file for copyright and license details. */ + + +typedef struct { + Cursor cursor; +} Cur; + +typedef struct Fnt { + Display *dpy; + unsigned int h; + XftFont *xfont; + FcPattern *pattern; + struct Fnt *next; +} Fnt; + +enum { ColFg, ColBg, ColBorder, ColFloat, ColCount }; /* Clr scheme index */ +typedef XftColor Clr; + +typedef struct { + unsigned int w, h; + Display *dpy; + int screen; + Window root; + Visual *visual; + unsigned int depth; + Colormap cmap; + Drawable drawable; + GC gc; + Clr *scheme; + Fnt *fonts; +} Drw; + +/* Drawable abstraction */ +Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h, Visual *visual, unsigned int depth, Colormap cmap); +void drw_resize(Drw *drw, unsigned int w, unsigned int h); +void drw_free(Drw *drw); + +/* Fnt abstraction */ +Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); +void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); +void drw_fontset_free(Fnt* set); +unsigned int drw_fontset_getwidth(Drw *drw, const char *text, Bool markup); + +/* Colorscheme abstraction */ +void drw_clr_create( + Drw *drw, + Clr *dest, + const char *clrname + , unsigned int alpha +); +Clr *drw_scm_create( + Drw *drw, + char *clrnames[], + const unsigned int alphas[], + size_t clrcount +); + +/* Cursor abstraction */ +Cur *drw_cur_create(Drw *drw, int shape); +void drw_cur_free(Drw *drw, Cur *cursor); + +/* Drawing context manipulation */ +void drw_setfontset(Drw *drw, Fnt *set); +void drw_setscheme(Drw *drw, Clr *scm); + +/* Drawing functions */ +void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); +int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, Bool markup); + +/* Map functions */ +void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); + diff --git a/dwm/drw.o b/dwm/drw.o new file mode 100644 index 0000000000000000000000000000000000000000..b50018445a450ea07ab5aae41f714f537650b9b1 GIT binary patch literal 10576 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 literal 0 HcmV?d00001 diff --git a/dwm/dwm b/dwm/dwm new file mode 100755 index 0000000000000000000000000000000000000000..41e7488c541ef3f9b4c7f662f8174bf455ced041 GIT binary patch literal 98848 zcmeEve_T{m`u~hDiir&w7L_UGxIw8wNinNaj0}3Q(MCnZA0>zw7$U)pVws`?>h
    _#a&%tb@8|pV_5Ewv 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
    qI)I%5tVtmn+XU=l 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 L5>fVGavJ{!C*JRz literal 0 HcmV?d00001 diff --git a/dwm/dwm.1 b/dwm/dwm.1 new file mode 100644 index 0000000..6020871 --- /dev/null +++ b/dwm/dwm.1 @@ -0,0 +1,187 @@ +.TH DWM 1 dwm\-VERSION +.SH NAME +dwm \- dynamic window manager +.SH SYNOPSIS +.B dwm +.RB [ \-v ] +.SH DESCRIPTION +dwm is a dynamic window manager for X. It manages windows in tiled, monocle +and floating layouts. Either layout can be applied dynamically, optimising the +environment for the application in use and the task performed. +.P +In tiled layouts windows are managed in a master and stacking area. The master +area on the left contains one window by default, and the stacking area on the +right contains all other windows. The number of master area windows can be +adjusted from zero to an arbitrary number. In monocle layout all windows are +maximised to the screen size. In floating layout windows can be resized and +moved freely. Dialog windows are always managed floating, regardless of the +layout applied. +.P +Windows are grouped by tags. Each window can be tagged with one or multiple +tags. Selecting certain tags displays all windows with these tags. +.P +Each screen contains a small status bar which displays all available tags, the +layout, the title of the focused window, and the text read from the root window +name property, if the screen is focused. A floating window is indicated with an +empty square and a maximised floating window is indicated with a filled square +before the windows title. The selected tags are indicated with a different +color. The tags of the focused window are indicated with a filled square in the +top left corner. The tags which are applied to one or more windows are +indicated with an empty square in the top left corner. +.P +dwm draws a small border around windows to indicate the focus state. +.SH OPTIONS +.TP +.B \-v +prints version information to stderr, then exits. +.SH USAGE +.SS Status bar +.TP +.B X root window name +is read and displayed in the status text area. It can be set with the +.BR xsetroot (1) +command. +.TP +.B Button1 +click on a tag label to display all windows with that tag, click on the layout +label toggles between tiled and floating layout. +.TP +.B Button3 +click on a tag label adds/removes all windows with that tag to/from the view. +.TP +.B Super\-Button1 +click on a tag label applies that tag to the focused window. +.TP +.B Super\-Button3 +click on a tag label adds/removes that tag to/from the focused window. +.SS Keyboard commands +.TP +.B Super\-Return +Start +.BR st(1). +.TP +.B Super\-Shift\-Return +Start or toggle +.BR st(1) +as a floating (scratchpad) terminal. +.TP +.B Super\-d +Spawn +.BR dmenu(1) +for launching other programs. +.TP +.B Super\-f +Toggles fullscreen state of focused window. +.TP +.B Super\-, +Focus previous screen, if any. +.TP +.B Super\-. +Focus next screen, if any. +.TP +.B Super\-Shift\-, +Send focused window to previous screen, if any. +.TP +.B Super\-Shift\-. +Send focused window to next screen, if any. +.TP +.B Super\-b +Toggles bar on and off. +.TP +.B Super\-t +Sets tiled layout. +.TP +.B Super\-m +Zooms/cycles focused window to/from master area (tiled layouts only). +.TP +.B Super\-space +Toggles between floating and tiled layout. +.TP +.B Super\-j +Focus next window. +.TP +.B Super\-k +Focus previous window. +.TP +.B Super\-Shift\-j +Move focused stack window downward. +.TP +.B Super\-Shift\-k +Move focused stack window upward. +.TP +.B Super\-o +Increase number of windows in master area. +.TP +.B Super\-Shift\-o +Decrease number of windows in master area. +.TP +.B Super\-l +Increase master area size. +.TP +.B Super\-h +Decrease master area size. +.TP +.B Super\-m +Zooms/cycles focused window to/from master area (tiled layouts only). +.TP +.B Super\-q +Close focused window. +.TP +.B Super\-Shift\-space +Toggle focused window between tiled and floating state. +.TP +.B Super\-Tab +Toggles to the previously selected tags. +.TP +.B Super\-Shift\-[1..n] +Apply nth tag to focused window. +.TP +.B Super\-Shift\-0 +Apply all tags to focused window. +.TP +.B Super\-Control\-Shift\-[1..n] +Add/remove nth tag to/from focused window. +.TP +.B Super\-[1..n] +View all windows with nth tag. +.TP +.B Super\-0 +View all windows with any tag. +.TP +.B Super\-Control\-[1..n] +Add/remove all windows with nth tag to/from the view. +.TP +.B Super\-Shift\-q, Super\-Shift\-e +Quit dwm. +.SS Mouse commands +.TP +.B Super\-Button1 +Move focused window while dragging. Tiled windows will be toggled to the floating state. +.TP +.B Super\-Button2 +Toggles focused window between floating and tiled state. +.TP +.B Super\-Button3 +Resize focused window while dragging. Tiled windows will be toggled to the floating state. +.SH CUSTOMIZATION +dwm is customized by creating a custom config.h and (re)compiling the source +code. This keeps it fast, secure and simple. +.SH SEE ALSO +.BR dmenu (1), +.BR st (1) +.SH ISSUES +Java applications which use the XToolkit/XAWT backend may draw grey windows +only. The XToolkit/XAWT backend breaks ICCCM-compliance in recent JDK 1.5 and early +JDK 1.6 versions, because it assumes a reparenting window manager. Possible workarounds +are using JDK 1.4 (which doesn't contain the XToolkit/XAWT backend) or setting the +environment variable +.BR AWT_TOOLKIT=MToolkit +(to use the older Motif backend instead) or running +.B xprop -root -f _NET_WM_NAME 32a -set _NET_WM_NAME LG3D +or +.B wmname LG3D +(to pretend that a non-reparenting window manager is running that the +XToolkit/XAWT backend can recognize) or when using OpenJDK setting the environment variable +.BR _JAVA_AWT_WM_NONREPARENTING=1 . +.SH BUGS +Send all bug reports with a patch to hackers@suckless.org. diff --git a/dwm/dwm.c b/dwm/dwm.c new file mode 100644 index 0000000..7c87101 --- /dev/null +++ b/dwm/dwm.c @@ -0,0 +1,2619 @@ +/* See LICENSE file for copyright and license details. + * + * dynamic window manager is designed like any other X client as well. It is + * driven through handling X events. In contrast to other X clients, a window + * manager selects for SubstructureRedirectMask on the root window, to receive + * events about window (dis-)appearance. Only one X connection at a time is + * allowed to select for this event mask. + * + * The event handlers of dwm are organized in an array which is accessed + * whenever a new event has been fetched. This allows event dispatching + * in O(1) time. + * + * Each child of the root window is called a client, except windows which have + * set the override_redirect flag. Clients are organized in a linked client + * list on each monitor, the focus history is remembered through a stack list + * on each monitor. Each client contains a bit array to indicate the tags of a + * client. + * + * Keys and tagging rules are organized as arrays and defined in config.h. + * + * To understand everything else, start reading main(). + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef XINERAMA +#include +#endif /* XINERAMA */ +#include + +#include "drw.h" +#include "util.h" + + + + + +/* macros */ +#define Button6 6 +#define Button7 7 +#define Button8 8 +#define Button9 9 +#define NUMTAGS 9 +#define BARRULES 20 +#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) +#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) +#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ + * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) +#define ISVISIBLEONTAG(C, T) ((C->tags & T)) +#define ISVISIBLE(C) ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags]) +#define LENGTH(X) (sizeof X / sizeof X[0]) +#define MOUSEMASK (BUTTONMASK|PointerMotionMask) +#define WIDTH(X) ((X)->w + 2 * (X)->bw) +#define HEIGHT(X) ((X)->h + 2 * (X)->bw) +#define WTYPE "_NET_WM_WINDOW_TYPE_" +#define TOTALTAGS (NUMTAGS + LENGTH(scratchpads)) +#define TAGMASK ((1 << TOTALTAGS) - 1) +#define SPTAG(i) ((1 << NUMTAGS) << (i)) +#define SPTAGMASK (((1 << LENGTH(scratchpads))-1) << NUMTAGS) +#define TEXTWM(X) (drw_fontset_getwidth(drw, (X), True) + lrpad) +#define TEXTW(X) (drw_fontset_getwidth(drw, (X), False) + lrpad) +#define HIDDEN(C) ((getstate(C->win) == IconicState)) + +/* enums */ +enum { + CurNormal, + CurResize, + CurMove, + CurLast +}; /* cursor */ + +enum { + SchemeNorm, + SchemeSel, + SchemeTitleNorm, + SchemeTitleSel, + SchemeTagsNorm, + SchemeTagsSel, + SchemeHidNorm, + SchemeHidSel, + SchemeUrg, +}; /* color schemes */ + +enum { + NetSupported, NetWMName, NetWMState, NetWMCheck, + NetWMFullscreen, NetActiveWindow, NetWMWindowType, + NetClientList, + NetLast +}; /* EWMH atoms */ + +enum { + WMProtocols, + WMDelete, + WMState, + WMTakeFocus, + WMLast +}; /* default atoms */ + + +enum { + ClkTagBar, + ClkLtSymbol, + ClkStatusText, + ClkWinTitle, + ClkClientWin, + ClkRootWin, + ClkLast +}; /* clicks */ + +enum { + BAR_ALIGN_LEFT, + BAR_ALIGN_CENTER, + BAR_ALIGN_RIGHT, + BAR_ALIGN_LEFT_LEFT, + BAR_ALIGN_LEFT_RIGHT, + BAR_ALIGN_LEFT_CENTER, + BAR_ALIGN_NONE, + BAR_ALIGN_RIGHT_LEFT, + BAR_ALIGN_RIGHT_RIGHT, + BAR_ALIGN_RIGHT_CENTER, + BAR_ALIGN_LAST +}; /* bar alignment */ + + +typedef union { + int i; + unsigned int ui; + float f; + const void *v; +} Arg; + +typedef struct Monitor Monitor; +typedef struct Bar Bar; +struct Bar { + Window win; + Monitor *mon; + Bar *next; + int idx; + int showbar; + int topbar; + int external; + int borderpx; + int borderscheme; + int bx, by, bw, bh; /* bar geometry */ + int w[BARRULES]; // width, array length == barrules, then use r index for lookup purposes + int x[BARRULES]; // x position, array length == ^ +}; + +typedef struct { + int x; + int y; + int h; + int w; +} BarArg; + +typedef struct { + int monitor; + int bar; + int alignment; // see bar alignment enum + int (*widthfunc)(Bar *bar, BarArg *a); + int (*drawfunc)(Bar *bar, BarArg *a); + int (*clickfunc)(Bar *bar, Arg *arg, BarArg *a); + int (*hoverfunc)(Bar *bar, BarArg *a, XMotionEvent *ev); + char *name; // for debugging + int x, w; // position, width for internal use +} BarRule; + +typedef struct { + unsigned int click; + unsigned int mask; + unsigned int button; + void (*func)(const Arg *arg); + const Arg arg; +} Button; + + +typedef struct Client Client; +struct Client { + char name[256]; + float mina, maxa; + int x, y, w, h; + int oldx, oldy, oldw, oldh; + int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; + int bw, oldbw; + unsigned int tags; + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; + int isterminal, noswallow; + pid_t pid; + Client *next; + Client *snext; + Client *swallowing; + Monitor *mon; + Window win; +}; + +typedef struct { + unsigned int mod; + KeySym keysym; + void (*func)(const Arg *); + const Arg arg; +} Key; + + +typedef struct { + const char *symbol; + void (*arrange)(Monitor *); +} Layout; + + +struct Monitor { + char ltsymbol[16]; + float mfact; + int nmaster; + int num; + int mx, my, mw, mh; /* screen size */ + int wx, wy, ww, wh; /* window area */ + int gappih; /* horizontal gap between windows */ + int gappiv; /* vertical gap between windows */ + int gappoh; /* horizontal outer gaps */ + int gappov; /* vertical outer gaps */ + unsigned int seltags; + unsigned int sellt; + unsigned int tagset[2]; + int showbar; + Client *clients; + Client *sel; + Client *stack; + Monitor *next; + Bar *bar; + const Layout *lt[2]; +}; + +typedef struct { + const char *class; + const char *instance; + const char *title; + const char *wintype; + unsigned int tags; + int isfloating; + int isterminal; + int noswallow; + int monitor; +} Rule; + +#define RULE(...) { .monitor = -1, __VA_ARGS__ }, + +/* Cross patch compatibility rule macro helper macros */ +#define FLOATING , .isfloating = 1 +#define CENTERED +#define PERMANENT +#define FAKEFULLSCREEN +#define NOSWALLOW , .noswallow = 1 +#define TERMINAL , .isterminal = 1 +#define SWITCHTAG + + +/* function declarations */ +static void applyrules(Client *c); +static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); +static void arrange(Monitor *m); +static void arrangemon(Monitor *m); +static void attach(Client *c); +static void attachstack(Client *c); +static void buttonpress(XEvent *e); +static void checkotherwm(void); +static void cleanup(void); +static void cleanupmon(Monitor *mon); +static void clientmessage(XEvent *e); +static void configure(Client *c); +static void configurenotify(XEvent *e); +static void configurerequest(XEvent *e); +static Monitor *createmon(void); +static void destroynotify(XEvent *e); +static void detach(Client *c); +static void detachstack(Client *c); +static Monitor *dirtomon(int dir); +static void drawbar(Monitor *m); +static void drawbars(void); +static void drawbarwin(Bar *bar); +static void enternotify(XEvent *e); +static void expose(XEvent *e); +static void focus(Client *c); +static void focusin(XEvent *e); +static void focusmon(const Arg *arg); +static void focusstack(const Arg *arg); +static Atom getatomprop(Client *c, Atom prop, Atom req); +static int getrootptr(int *x, int *y); +static long getstate(Window w); +static int gettextprop(Window w, Atom atom, char *text, unsigned int size); +static void grabbuttons(Client *c, int focused); +static void grabkeys(void); +static void incnmaster(const Arg *arg); +static void keypress(XEvent *e); +static void killclient(const Arg *arg); +static void manage(Window w, XWindowAttributes *wa); +static void mappingnotify(XEvent *e); +static void maprequest(XEvent *e); +static void motionnotify(XEvent *e); +static void movemouse(const Arg *arg); +static Client *nexttiled(Client *c); +static void pop(Client *); +static void propertynotify(XEvent *e); +static void quit(const Arg *arg); +static Monitor *recttomon(int x, int y, int w, int h); +static void resize(Client *c, int x, int y, int w, int h, int interact); +static void resizeclient(Client *c, int x, int y, int w, int h); +static void resizemouse(const Arg *arg); +static void restack(Monitor *m); +static void run(void); +static void scan(void); +static int sendevent(Client *c, Atom proto); +static void sendmon(Client *c, Monitor *m); +static void setclientstate(Client *c, long state); +static void setfocus(Client *c); +static void setfullscreen(Client *c, int fullscreen); +static void setlayout(const Arg *arg); +static void setmfact(const Arg *arg); +static void setup(void); +static void seturgent(Client *c, int urg); +static void showhide(Client *c); +static void sigchld(int unused); +static void spawn(const Arg *arg); +static void tag(const Arg *arg); +static void tagmon(const Arg *arg); +static void togglebar(const Arg *arg); +static void togglefloating(const Arg *arg); +static void toggletag(const Arg *arg); +static void toggleview(const Arg *arg); +static void unfocus(Client *c, int setfocus, Client *nextfocus); +static void unmanage(Client *c, int destroyed); +static void unmapnotify(XEvent *e); +static void updatebarpos(Monitor *m); +static void updatebars(void); +static void updateclientlist(void); +static int updategeom(void); +static void updatenumlockmask(void); +static void updatesizehints(Client *c); +static void updatestatus(void); +static void updatetitle(Client *c); +static void updatewmhints(Client *c); +static void view(const Arg *arg); +static Client *wintoclient(Window w); +static Monitor *wintomon(Window w); +static int xerror(Display *dpy, XErrorEvent *ee); +static int xerrordummy(Display *dpy, XErrorEvent *ee); +static int xerrorstart(Display *dpy, XErrorEvent *ee); +static void zoom(const Arg *arg); + +/* bar functions */ + +#include "patch/include.h" + +/* variables */ +static const char broken[] = "broken"; +static char stext[512]; + +static int screen; +static int sw, sh; /* X display screen geometry width, height */ +static int bh; /* bar geometry */ +static int lrpad; /* sum of left and right padding for text */ +/* Some clients (e.g. alacritty) helpfully send configure requests with a new size or position + * when they detect that they have been moved to another monitor. This can cause visual glitches + * when moving (or resizing) client windows from one monitor to another. This variable is used + * internally to ignore such configure requests while movemouse or resizemouse are being used. */ +static int ignoreconfigurerequests = 0; +static int (*xerrorxlib)(Display *, XErrorEvent *); +static unsigned int numlockmask = 0; +static void (*handler[LASTEvent]) (XEvent *) = { + [ButtonPress] = buttonpress, + [ClientMessage] = clientmessage, + [ConfigureRequest] = configurerequest, + [ConfigureNotify] = configurenotify, + [DestroyNotify] = destroynotify, + [EnterNotify] = enternotify, + [Expose] = expose, + [FocusIn] = focusin, + [KeyPress] = keypress, + [MappingNotify] = mappingnotify, + [MapRequest] = maprequest, + [MotionNotify] = motionnotify, + [PropertyNotify] = propertynotify, + [UnmapNotify] = unmapnotify +}; +static Atom wmatom[WMLast], netatom[NetLast]; +static int running = 1; +static Cur *cursor[CurLast]; +static Clr **scheme; +static Display *dpy; +static Drw *drw; +static Monitor *mons, *selmon; +static Window root, wmcheckwin; + +/* configuration, allows nested code to access above variables */ +#include "config.h" + +#include "patch/include.c" + +/* compile-time check if all tags fit into an unsigned int bit array. */ +struct NumTags { char limitexceeded[NUMTAGS > 31 ? -1 : 1]; }; + +/* function implementations */ +void +applyrules(Client *c) +{ + const char *class, *instance; + Atom wintype; + unsigned int i; + const Rule *r; + Monitor *m; + XClassHint ch = { NULL, NULL }; + + /* rule matching */ + c->noswallow = -1; + c->isfloating = 0; + c->tags = 0; + XGetClassHint(dpy, c->win, &ch); + class = ch.res_class ? ch.res_class : broken; + instance = ch.res_name ? ch.res_name : broken; + wintype = getatomprop(c, netatom[NetWMWindowType], XA_ATOM); + + + for (i = 0; i < LENGTH(rules); i++) { + r = &rules[i]; + if ((!r->title || strstr(c->name, r->title)) + && (!r->class || strstr(class, r->class)) + && (!r->instance || strstr(instance, r->instance)) + && (!r->wintype || wintype == XInternAtom(dpy, r->wintype, False))) + { + c->isterminal = r->isterminal; + c->noswallow = r->noswallow; + c->isfloating = r->isfloating; + c->tags |= r->tags; + if ((r->tags & SPTAGMASK) && r->isfloating) { + c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2); + c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2); + } + for (m = mons; m && m->num != r->monitor; m = m->next); + if (m) + c->mon = m; + + } + } + if (ch.res_class) + XFree(ch.res_class); + if (ch.res_name) + XFree(ch.res_name); + c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : (c->mon->tagset[c->mon->seltags] & ~SPTAGMASK); +} + +int +applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) +{ + int baseismin; + Monitor *m = c->mon; + + /* set minimum possible */ + *w = MAX(1, *w); + *h = MAX(1, *h); + if (interact) { + if (*x > sw) + *x = sw - WIDTH(c); + if (*y > sh) + *y = sh - HEIGHT(c); + if (*x + *w + 2 * c->bw < 0) + *x = 0; + if (*y + *h + 2 * c->bw < 0) + *y = 0; + } else { + if (*x >= m->wx + m->ww) + *x = m->wx + m->ww - WIDTH(c); + if (*y >= m->wy + m->wh) + *y = m->wy + m->wh - HEIGHT(c); + if (*x + *w + 2 * c->bw <= m->wx) + *x = m->wx; + if (*y + *h + 2 * c->bw <= m->wy) + *y = m->wy; + } + if (*h < bh) + *h = bh; + if (*w < bh) + *w = bh; + if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) { + if (!c->hintsvalid) + updatesizehints(c); + /* see last two sentences in ICCCM 4.1.2.3 */ + baseismin = c->basew == c->minw && c->baseh == c->minh; + if (!baseismin) { /* temporarily remove base dimensions */ + *w -= c->basew; + *h -= c->baseh; + } + /* adjust for aspect limits */ + if (c->mina > 0 && c->maxa > 0) { + if (c->maxa < (float)*w / *h) + *w = *h * c->maxa + 0.5; + else if (c->mina < (float)*h / *w) + *h = *w * c->mina + 0.5; + } + if (baseismin) { /* increment calculation requires this */ + *w -= c->basew; + *h -= c->baseh; + } + /* adjust for increment value */ + if (c->incw) + *w -= *w % c->incw; + if (c->inch) + *h -= *h % c->inch; + /* restore base dimensions */ + *w = MAX(*w + c->basew, c->minw); + *h = MAX(*h + c->baseh, c->minh); + if (c->maxw) + *w = MIN(*w, c->maxw); + if (c->maxh) + *h = MIN(*h, c->maxh); + } + return *x != c->x || *y != c->y || *w != c->w || *h != c->h; +} + +void +arrange(Monitor *m) +{ + if (m) + showhide(m->stack); + else for (m = mons; m; m = m->next) + showhide(m->stack); + if (m) { + arrangemon(m); + restack(m); + } else for (m = mons; m; m = m->next) + arrangemon(m); +} + +void +arrangemon(Monitor *m) +{ + strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); + if (m->lt[m->sellt]->arrange) + m->lt[m->sellt]->arrange(m); +} + +void +attach(Client *c) +{ + c->next = c->mon->clients; + c->mon->clients = c; +} + +void +attachstack(Client *c) +{ + c->snext = c->mon->stack; + c->mon->stack = c; +} + +void +buttonpress(XEvent *e) +{ + int click, i, r; + Arg arg = {0}; + Client *c; + Monitor *m; + Bar *bar; + XButtonPressedEvent *ev = &e->xbutton; + const BarRule *br; + BarArg carg = { 0, 0, 0, 0 }; + click = ClkRootWin; + + + /* focus monitor if necessary */ + if ((m = wintomon(ev->window)) && m != selmon + ) { + unfocus(selmon->sel, 1, NULL); + selmon = m; + focus(NULL); + } + + for (bar = selmon->bar; bar; bar = bar->next) { + if (ev->window == bar->win) { + for (r = 0; r < LENGTH(barrules); r++) { + br = &barrules[r]; + if (br->bar != bar->idx || (br->monitor == 'A' && m != selmon) || br->clickfunc == NULL) + continue; + if (br->monitor != 'A' && br->monitor != -1 && br->monitor != bar->mon->num) + continue; + if (bar->x[r] <= ev->x && ev->x <= bar->x[r] + bar->w[r]) { + carg.x = ev->x - bar->x[r]; + carg.y = ev->y - bar->borderpx; + carg.w = bar->w[r]; + carg.h = bar->bh - 2 * bar->borderpx; + click = br->clickfunc(bar, &arg, &carg); + if (click < 0) + return; + break; + } + } + break; + } + } + + + if (click == ClkRootWin && (c = wintoclient(ev->window))) { + focus(c); + restack(selmon); + XAllowEvents(dpy, ReplayPointer, CurrentTime); + click = ClkClientWin; + } + + for (i = 0; i < LENGTH(buttons); i++) { + if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button + && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) { + buttons[i].func( + ( + click == ClkTagBar + ) && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg + ); + } + } +} + +void +checkotherwm(void) +{ + xerrorxlib = XSetErrorHandler(xerrorstart); + /* this causes an error if some other window manager is running */ + XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask); + XSync(dpy, False); + XSetErrorHandler(xerror); + XSync(dpy, False); +} + +void +cleanup(void) +{ + Monitor *m; + Layout foo = { "", NULL }; + size_t i; + + + /* kill child processes */ + for (i = 0; i < autostart_len; i++) { + if (0 < autostart_pids[i]) { + kill(autostart_pids[i], SIGTERM); + waitpid(autostart_pids[i], NULL, 0); + } + } + + selmon->lt[selmon->sellt] = &foo; + for (m = mons; m; m = m->next) + while (m->stack) + unmanage(m->stack, 0); + XUngrabKey(dpy, AnyKey, AnyModifier, root); + while (mons) + cleanupmon(mons); + for (i = 0; i < CurLast; i++) + drw_cur_free(drw, cursor[i]); + for (i = 0; i < LENGTH(colors); i++) + free(scheme[i]); + free(scheme); + XDestroyWindow(dpy, wmcheckwin); + drw_free(drw); + XSync(dpy, False); + XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + +} + +void +cleanupmon(Monitor *mon) +{ + Monitor *m; + Bar *bar; + + if (mon == mons) + mons = mons->next; + else { + for (m = mons; m && m->next != mon; m = m->next); + m->next = mon->next; + } + for (bar = mon->bar; bar; bar = mon->bar) { + if (!bar->external) { + XUnmapWindow(dpy, bar->win); + XDestroyWindow(dpy, bar->win); + } + mon->bar = bar->next; + free(bar); + } + free(mon); +} + +void +clientmessage(XEvent *e) +{ + XClientMessageEvent *cme = &e->xclient; + Client *c = wintoclient(cme->window); + + + if (!c) + return; + if (cme->message_type == netatom[NetWMState]) { + if (cme->data.l[1] == netatom[NetWMFullscreen] + || cme->data.l[2] == netatom[NetWMFullscreen]) { + setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ + || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ + && !c->isfullscreen + ))); + } + } else if (cme->message_type == netatom[NetActiveWindow]) { + if (c != selmon->sel && !c->isurgent) + seturgent(c, 1); + } +} + +void +configure(Client *c) +{ + XConfigureEvent ce; + + ce.type = ConfigureNotify; + ce.display = dpy; + ce.event = c->win; + ce.window = c->win; + ce.x = c->x; + ce.y = c->y; + ce.width = c->w; + ce.height = c->h; + ce.border_width = c->bw; + ce.above = None; + ce.override_redirect = False; + XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce); +} + +void +configurenotify(XEvent *e) +{ + Monitor *m; + Bar *bar; + Client *c; + XConfigureEvent *ev = &e->xconfigure; + int dirty; + /* TODO: updategeom handling sucks, needs to be simplified */ + if (ev->window == root) { + dirty = (sw != ev->width || sh != ev->height); + sw = ev->width; + sh = ev->height; + if (updategeom() || dirty) { + drw_resize(drw, sw, sh); + updatebars(); + for (m = mons; m; m = m->next) { + for (c = m->clients; c; c = c->next) + if (c->isfullscreen) + resizeclient(c, m->mx, m->my, m->mw, m->mh); + for (bar = m->bar; bar; bar = bar->next) + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + } + focus(NULL); + arrange(NULL); + } + } +} + +void +configurerequest(XEvent *e) +{ + Client *c; + Monitor *m; + XConfigureRequestEvent *ev = &e->xconfigurerequest; + XWindowChanges wc; + + if (ignoreconfigurerequests) + return; + + if ((c = wintoclient(ev->window))) { + if (ev->value_mask & CWBorderWidth) + c->bw = ev->border_width; + else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) { + m = c->mon; + if (ev->value_mask & CWX) { + c->oldx = c->x; + c->x = m->mx + ev->x; + } + if (ev->value_mask & CWY) { + c->oldy = c->y; + c->y = m->my + ev->y; + } + if (ev->value_mask & CWWidth) { + c->oldw = c->w; + c->w = ev->width; + } + if (ev->value_mask & CWHeight) { + c->oldh = c->h; + c->h = ev->height; + } + if ((c->x + c->w) > m->mx + m->mw && c->isfloating) + c->x = m->mx + (m->mw / 2 - WIDTH(c) / 2); /* center in x direction */ + if ((c->y + c->h) > m->my + m->mh && c->isfloating) + c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */ + if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight))) + configure(c); + if (ISVISIBLE(c)) + XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); + } else + configure(c); + } else { + wc.x = ev->x; + wc.y = ev->y; + wc.width = ev->width; + wc.height = ev->height; + wc.border_width = ev->border_width; + wc.sibling = ev->above; + wc.stack_mode = ev->detail; + XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); + } + XSync(dpy, False); +} + +Monitor * +createmon(void) +{ + Monitor *m, *mon; + int i, n, mi, max_bars = 2, istopbar = topbar; + + const BarRule *br; + Bar *bar; + + m = ecalloc(1, sizeof(Monitor)); + m->tagset[0] = m->tagset[1] = 1; + m->mfact = mfact; + m->nmaster = nmaster; + m->showbar = showbar; + m->gappih = gappih; + m->gappiv = gappiv; + m->gappoh = gappoh; + m->gappov = gappov; + for (mi = 0, mon = mons; mon; mon = mon->next, mi++); // monitor index + m->num = mi; + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); + + /* Derive the number of bars for this monitor based on bar rules */ + for (n = -1, i = 0; i < LENGTH(barrules); i++) { + br = &barrules[i]; + if (br->monitor == 'A' || br->monitor == -1 || br->monitor == m->num) + n = MAX(br->bar, n); + } + + m->bar = NULL; + for (i = 0; i <= n && i < max_bars; i++) { + bar = ecalloc(1, sizeof(Bar)); + bar->mon = m; + bar->idx = i; + bar->next = m->bar; + bar->topbar = istopbar; + m->bar = bar; + istopbar = !istopbar; + bar->showbar = 1; + bar->external = 0; + bar->borderpx = 0; + bar->bh = bh + bar->borderpx * 2; + bar->borderscheme = SchemeNorm; + } + + + + + return m; +} + +void +destroynotify(XEvent *e) +{ + Client *c; + XDestroyWindowEvent *ev = &e->xdestroywindow; + + if ((c = wintoclient(ev->window))) + unmanage(c, 1); + else if ((c = swallowingclient(ev->window))) + unmanage(c->swallowing, 1); +} + +void +detach(Client *c) +{ + Client **tc; + + for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); + *tc = c->next; + c->next = NULL; +} + +void +detachstack(Client *c) +{ + Client **tc, *t; + + for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext); + *tc = c->snext; + + if (c == c->mon->sel) { + for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext); + c->mon->sel = t; + } + c->snext = NULL; +} + +Monitor * +dirtomon(int dir) +{ + Monitor *m = NULL; + + if (dir > 0) { + if (!(m = selmon->next)) + m = mons; + } else if (selmon == mons) + for (m = mons; m->next; m = m->next); + else + for (m = mons; m->next != selmon; m = m->next); + return m; +} + +void +drawbar(Monitor *m) +{ + Bar *bar; + + if (m->showbar) + for (bar = m->bar; bar; bar = bar->next) + drawbarwin(bar); +} + +void +drawbars(void) +{ + Monitor *m; + for (m = mons; m; m = m->next) + drawbar(m); +} + +void +drawbarwin(Bar *bar) +{ + if (!bar || !bar->win || bar->external) + return; + int r, w, total_drawn = 0; + int rx, lx, rw, lw; // bar size, split between left and right if a center module is added + const BarRule *br; + + if (bar->borderpx) { + XSetForeground(drw->dpy, drw->gc, scheme[bar->borderscheme][ColBorder].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, 0, 0, bar->bw, bar->bh); + } + + BarArg warg = { 0 }; + BarArg darg = { 0 }; + warg.h = bar->bh - 2 * bar->borderpx; + + rw = lw = bar->bw - 2 * bar->borderpx; + rx = lx = bar->borderpx; + + drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, lx, bar->borderpx, lw, bar->bh - 2 * bar->borderpx, 1, 1); + for (r = 0; r < LENGTH(barrules); r++) { + br = &barrules[r]; + if (br->bar != bar->idx || !br->widthfunc || (br->monitor == 'A' && bar->mon != selmon)) + continue; + if (br->monitor != 'A' && br->monitor != -1 && br->monitor != bar->mon->num) + continue; + drw_setscheme(drw, scheme[SchemeNorm]); + warg.w = (br->alignment < BAR_ALIGN_RIGHT_LEFT ? lw : rw); + + w = br->widthfunc(bar, &warg); + w = MIN(warg.w, w); + + if (lw <= 0) { // if left is exhausted then switch to right side, and vice versa + lw = rw; + lx = rx; + } else if (rw <= 0) { + rw = lw; + rx = lx; + } + + switch(br->alignment) { + default: + case BAR_ALIGN_NONE: + case BAR_ALIGN_LEFT_LEFT: + case BAR_ALIGN_LEFT: + bar->x[r] = lx; + if (lx == rx) { + rx += w; + rw -= w; + } + lx += w; + lw -= w; + break; + case BAR_ALIGN_LEFT_RIGHT: + case BAR_ALIGN_RIGHT: + bar->x[r] = lx + lw - w; + if (lx == rx) + rw -= w; + lw -= w; + break; + case BAR_ALIGN_LEFT_CENTER: + case BAR_ALIGN_CENTER: + bar->x[r] = lx + lw / 2 - w / 2; + if (lx == rx) { + rw = rx + rw - bar->x[r] - w; + rx = bar->x[r] + w; + } + lw = bar->x[r] - lx; + break; + case BAR_ALIGN_RIGHT_LEFT: + bar->x[r] = rx; + if (lx == rx) { + lx += w; + lw -= w; + } + rx += w; + rw -= w; + break; + case BAR_ALIGN_RIGHT_RIGHT: + bar->x[r] = rx + rw - w; + if (lx == rx) + lw -= w; + rw -= w; + break; + case BAR_ALIGN_RIGHT_CENTER: + bar->x[r] = rx + rw / 2 - w / 2; + if (lx == rx) { + lw = lx + lw - bar->x[r] + w; + lx = bar->x[r] + w; + } + rw = bar->x[r] - rx; + break; + } + bar->w[r] = w; + darg.x = bar->x[r]; + darg.y = bar->borderpx; + darg.h = bar->bh - 2 * bar->borderpx; + darg.w = bar->w[r]; + if (br->drawfunc) + total_drawn += br->drawfunc(bar, &darg); + } + + if (total_drawn == 0 && bar->showbar) { + bar->showbar = 0; + updatebarpos(bar->mon); + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + arrange(bar->mon); + } + else if (total_drawn > 0 && !bar->showbar) { + bar->showbar = 1; + updatebarpos(bar->mon); + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + drw_map(drw, bar->win, 0, 0, bar->bw, bar->bh); + arrange(bar->mon); + } else + drw_map(drw, bar->win, 0, 0, bar->bw, bar->bh); +} + +void +enternotify(XEvent *e) +{ + Client *c; + Monitor *m; + XCrossingEvent *ev = &e->xcrossing; + + if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) + return; + c = wintoclient(ev->window); + m = c ? c->mon : wintomon(ev->window); + if (m != selmon) { + unfocus(selmon->sel, 1, c); + selmon = m; + } else if (!c || c == selmon->sel) + return; + focus(c); +} + +void +expose(XEvent *e) +{ + Monitor *m; + XExposeEvent *ev = &e->xexpose; + + if (ev->count == 0 && (m = wintomon(ev->window))) { + drawbar(m); + } +} + +void +focus(Client *c) +{ + if (!c || !ISVISIBLE(c)) + for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); + if (selmon->sel && selmon->sel != c) + unfocus(selmon->sel, 0, c); + if (c) { + if (c->mon != selmon) + selmon = c->mon; + if (c->isurgent) + seturgent(c, 0); + detachstack(c); + attachstack(c); + grabbuttons(c, 1); + if (c->isfloating) + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColFloat].pixel); + else + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); + setfocus(c); + } else { + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + } + selmon->sel = c; + drawbars(); + +} + +/* there are some broken focus acquiring clients needing extra handling */ +void +focusin(XEvent *e) +{ + XFocusChangeEvent *ev = &e->xfocus; + + if (selmon->sel && ev->window != selmon->sel->win) + setfocus(selmon->sel); +} + +void +focusmon(const Arg *arg) +{ + Monitor *m; + + if (!mons->next) + return; + if ((m = dirtomon(arg->i)) == selmon) + return; + unfocus(selmon->sel, 0, NULL); + selmon = m; + focus(NULL); +} + +void +focusstack(const Arg *arg) +{ + Client *c = NULL, *i; + + if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen)) + return; + if (arg->i > 0) { + for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); + if (!c) + for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); + } else { + for (i = selmon->clients; i != selmon->sel; i = i->next) + if (ISVISIBLE(i)) + c = i; + if (!c) + for (; i; i = i->next) + if (ISVISIBLE(i)) + c = i; + } + if (c) { + focus(c); + restack(selmon); + } +} + +Atom +getatomprop(Client *c, Atom prop, Atom req) +{ + int di; + unsigned long dl; + unsigned char *p = NULL; + Atom da, atom = None; + + + /* FIXME getatomprop should return the number of items and a pointer to + * the stored data instead of this workaround */ + if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req, + &da, &di, &dl, &dl, &p) == Success && p) { + atom = *(Atom *)p; + XFree(p); + } + return atom; +} + +int +getrootptr(int *x, int *y) +{ + int di; + unsigned int dui; + Window dummy; + + return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui); +} + +long +getstate(Window w) +{ + int format; + long result = -1; + unsigned char *p = NULL; + unsigned long n, extra; + Atom real; + + if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], + &real, &format, &n, &extra, (unsigned char **)&p) != Success) + return -1; + if (n != 0) + result = *p; + XFree(p); + return result; +} + +int +gettextprop(Window w, Atom atom, char *text, unsigned int size) +{ + char **list = NULL; + int n; + XTextProperty name; + + if (!text || size == 0) + return 0; + text[0] = '\0'; + if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems) + return 0; + if (name.encoding == XA_STRING) + strncpy(text, (char *)name.value, size - 1); + else { + if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) { + strncpy(text, *list, size - 1); + XFreeStringList(list); + } + } + text[size - 1] = '\0'; + XFree(name.value); + return 1; +} + +void +grabbuttons(Client *c, int focused) +{ + updatenumlockmask(); + { + unsigned int i, j; + unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; + XUngrabButton(dpy, AnyButton, AnyModifier, c->win); + if (!focused) + XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, + BUTTONMASK, GrabModeSync, GrabModeSync, None, None); + for (i = 0; i < LENGTH(buttons); i++) + if (buttons[i].click == ClkClientWin + ) + for (j = 0; j < LENGTH(modifiers); j++) + XGrabButton(dpy, buttons[i].button, + buttons[i].mask | modifiers[j], + c->win, False, BUTTONMASK, + GrabModeAsync, GrabModeSync, None, None); + } +} + +void +grabkeys(void) +{ + updatenumlockmask(); + { + unsigned int i, j; + unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; + KeyCode code; + + XUngrabKey(dpy, AnyKey, AnyModifier, root); + for (i = 0; i < LENGTH(keys); i++) + if ((code = XKeysymToKeycode(dpy, keys[i].keysym))) + for (j = 0; j < LENGTH(modifiers); j++) + XGrabKey(dpy, code, keys[i].mod | modifiers[j], root, + True, GrabModeAsync, GrabModeAsync); + } +} + +void +incnmaster(const Arg *arg) +{ + selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); + arrange(selmon); +} + +#ifdef XINERAMA +static int +isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) +{ + while (n--) + if (unique[n].x_org == info->x_org && unique[n].y_org == info->y_org + && unique[n].width == info->width && unique[n].height == info->height) + return 0; + return 1; +} +#endif /* XINERAMA */ + +void +keypress(XEvent *e) +{ + unsigned int i; + int keysyms_return; + KeySym* keysym; + XKeyEvent *ev; + + ev = &e->xkey; + keysym = XGetKeyboardMapping(dpy, (KeyCode)ev->keycode, 1, &keysyms_return); + for (i = 0; i < LENGTH(keys); i++) + if (*keysym == keys[i].keysym + && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) + && keys[i].func) + keys[i].func(&(keys[i].arg)); + XFree(keysym); +} + +void +killclient(const Arg *arg) +{ + if (!selmon->sel) + return; + if (!sendevent(selmon->sel, wmatom[WMDelete])) + { + XGrabServer(dpy); + XSetErrorHandler(xerrordummy); + XSetCloseDownMode(dpy, DestroyAll); + XKillClient(dpy, selmon->sel->win); + XSync(dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } +} + +void +manage(Window w, XWindowAttributes *wa) +{ + Client *c, *t = NULL; + Client *term = NULL; + Window trans = None; + XWindowChanges wc; + + c = ecalloc(1, sizeof(Client)); + c->win = w; + c->pid = winpid(w); + /* geometry */ + c->x = c->oldx = wa->x; + c->y = c->oldy = wa->y; + c->w = c->oldw = wa->width; + c->h = c->oldh = wa->height; + c->oldbw = wa->border_width; + updatetitle(c); + + + if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { + c->mon = t->mon; + c->tags = t->tags; + c->bw = borderpx; + } else { + c->mon = selmon; + c->bw = borderpx; + applyrules(c); + term = termforwin(c); + if (term) + c->mon = term->mon; + } + + if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) + c->x = c->mon->mx + c->mon->mw - WIDTH(c); + if (c->y + HEIGHT(c) > c->mon->my + c->mon->mh) + c->y = c->mon->my + c->mon->mh - HEIGHT(c); + c->x = MAX(c->x, c->mon->mx); + /* only fix client y-offset, if the client center might cover the bar */ + c->y = MAX(c->y, ((!c->mon->bar || c->mon->bar->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx) + && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); + + wc.border_width = c->bw; + XConfigureWindow(dpy, w, CWBorderWidth, &wc); + if (c->isfloating) + XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColFloat].pixel); + else + XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); + configure(c); /* propagates border_width, if size doesn't change */ + updatesizehints(c); + if (getatomprop(c, netatom[NetWMState], XA_ATOM) == netatom[NetWMFullscreen]) + setfullscreen(c, 1); + updatewmhints(c); + + + XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); + grabbuttons(c, 0); + + if (!c->isfloating) + c->isfloating = c->oldstate = trans != None || c->isfixed; + if (c->isfloating) { + XRaiseWindow(dpy, c->win); + XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColFloat].pixel); + } + attachx(c); + attachstack(c); + XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); + XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ + + setclientstate(c, NormalState); + if (c->mon == selmon) + unfocus(selmon->sel, 0, c); + c->mon->sel = c; + if (!(term && swallow(term, c))) { + arrange(c->mon); + XMapWindow(dpy, c->win); + } + focus(NULL); + +} + +void +mappingnotify(XEvent *e) +{ + XMappingEvent *ev = &e->xmapping; + + XRefreshKeyboardMapping(ev); + if (ev->request == MappingKeyboard) + grabkeys(); +} + +void +maprequest(XEvent *e) +{ + static XWindowAttributes wa; + XMapRequestEvent *ev = &e->xmaprequest; + + + if (!XGetWindowAttributes(dpy, ev->window, &wa)) + return; + if (wa.override_redirect) + return; + if (!wintoclient(ev->window)) + manage(ev->window, &wa); +} + +void +motionnotify(XEvent *e) +{ + static Monitor *mon = NULL; + Monitor *m; + Bar *bar; + XMotionEvent *ev = &e->xmotion; + + if ((bar = wintobar(ev->window))) { + barhover(e, bar); + return; + } + + + if (ev->window != root) + return; + if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { + unfocus(selmon->sel, 1, NULL); + selmon = m; + focus(NULL); + } + mon = m; +} + +void +movemouse(const Arg *arg) +{ + int x, y, ocx, ocy, nx, ny; + Client *c; + Monitor *m; + XEvent ev; + Time lasttime = 0; + + if (!(c = selmon->sel)) + return; + if (c->isfullscreen) /* no support moving fullscreen windows by mouse */ + return; + restack(selmon); + nx = ocx = c->x; + ny = ocy = c->y; + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) + return; + if (!getrootptr(&x, &y)) + return; + ignoreconfigurerequests = 1; + do { + XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); + switch(ev.type) { + case ConfigureRequest: + case Expose: + case MapRequest: + handler[ev.type](&ev); + break; + case MotionNotify: + if ((ev.xmotion.time - lasttime) <= (1000 / 60)) + continue; + lasttime = ev.xmotion.time; + + nx = ocx + (ev.xmotion.x - x); + ny = ocy + (ev.xmotion.y - y); + if (abs(selmon->wx - nx) < snap) + nx = selmon->wx; + else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) + nx = selmon->wx + selmon->ww - WIDTH(c); + if (abs(selmon->wy - ny) < snap) + ny = selmon->wy; + else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap) + ny = selmon->wy + selmon->wh - HEIGHT(c); + if (!c->isfloating && selmon->lt[selmon->sellt]->arrange + && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) { + togglefloating(NULL); + } + if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) { + resize(c, nx, ny, c->w, c->h, 1); + } + break; + } + } while (ev.type != ButtonRelease); + + XUngrabPointer(dpy, CurrentTime); + if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { + if (c->tags & SPTAGMASK) { + c->mon->tagset[c->mon->seltags] ^= (c->tags & SPTAGMASK); + m->tagset[m->seltags] |= (c->tags & SPTAGMASK); + } + sendmon(c, m); + selmon = m; + focus(NULL); + } + ignoreconfigurerequests = 0; +} + +Client * +nexttiled(Client *c) +{ + for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); + return c; +} + +void +pop(Client *c) +{ + detach(c); + attach(c); + focus(c); + arrange(c->mon); +} + +void +propertynotify(XEvent *e) +{ + Client *c; + Window trans; + XPropertyEvent *ev = &e->xproperty; + + + if ((ev->window == root) && (ev->atom == XA_WM_NAME)) { + if (!fake_signal()) + updatestatus(); + } else if (ev->state == PropertyDelete) { + return; /* ignore */ + } else if ((c = wintoclient(ev->window))) { + switch(ev->atom) { + default: break; + case XA_WM_TRANSIENT_FOR: + if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) && + (c->isfloating = (wintoclient(trans)) != NULL)) + arrange(c->mon); + break; + case XA_WM_NORMAL_HINTS: + c->hintsvalid = 0; + break; + case XA_WM_HINTS: + updatewmhints(c); + if (c->isurgent) + drawbars(); + break; + } + if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { + updatetitle(c); + if (c == c->mon->sel) + drawbar(c->mon); + } + } +} + +void +quit(const Arg *arg) +{ + running = 0; +} + +Monitor * +recttomon(int x, int y, int w, int h) +{ + Monitor *m, *r = selmon; + int a, area = 0; + + for (m = mons; m; m = m->next) + if ((a = INTERSECT(x, y, w, h, m)) > area) { + area = a; + r = m; + } + return r; +} + +void +resize(Client *c, int x, int y, int w, int h, int interact) +{ + if (applysizehints(c, &x, &y, &w, &h, interact)) + resizeclient(c, x, y, w, h); +} + +void +resizeclient(Client *c, int x, int y, int w, int h) +{ + XWindowChanges wc; + + c->oldx = c->x; c->x = wc.x = x; + c->oldy = c->y; c->y = wc.y = y; + c->oldw = c->w; c->w = wc.width = w; + c->oldh = c->h; c->h = wc.height = h; + wc.border_width = c->bw; + XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); + configure(c); + XSync(dpy, False); +} + +void +resizemouse(const Arg *arg) +{ + int ocx, ocy, nw, nh, nx, ny; + Client *c; + Monitor *m; + XEvent ev; + Time lasttime = 0; + + if (!(c = selmon->sel)) + return; + if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ + return; + restack(selmon); + nx = ocx = c->x; + ny = ocy = c->y; + nh = c->h; + nw = c->w; + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) + return; + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); + ignoreconfigurerequests = 1; + do { + XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); + switch(ev.type) { + case ConfigureRequest: + case Expose: + case MapRequest: + handler[ev.type](&ev); + break; + case MotionNotify: + if ((ev.xmotion.time - lasttime) <= (1000 / 60)) + continue; + lasttime = ev.xmotion.time; + + nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); + nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); + if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww + && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh) + { + if (!c->isfloating && selmon->lt[selmon->sellt]->arrange + && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) { + togglefloating(NULL); + } + } + if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) { + resize(c, nx, ny, nw, nh, 1); + } + break; + } + } while (ev.type != ButtonRelease); + + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); + XUngrabPointer(dpy, CurrentTime); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); + if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { + if (c->tags & SPTAGMASK) { + c->mon->tagset[c->mon->seltags] ^= (c->tags & SPTAGMASK); + m->tagset[m->seltags] |= (c->tags & SPTAGMASK); + } + sendmon(c, m); + selmon = m; + focus(NULL); + } + ignoreconfigurerequests = 0; +} + +void +restack(Monitor *m) +{ + Client *c, *f = NULL; + XEvent ev; + XWindowChanges wc; + + drawbar(m); + if (!m->sel) + return; + if (m->sel->isfloating || !m->lt[m->sellt]->arrange) + XRaiseWindow(dpy, m->sel->win); + if (m->lt[m->sellt]->arrange) { + wc.stack_mode = Below; + if (m->bar) { + wc.sibling = m->bar->win; + } else { + for (f = m->stack; f && (f->isfloating || !ISVISIBLE(f)); f = f->snext); // find first tiled stack client + if (f) + wc.sibling = f->win; + } + for (c = m->stack; c; c = c->snext) + if (!c->isfloating && ISVISIBLE(c) && c != f) { + XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); + wc.sibling = c->win; + } + } + XSync(dpy, False); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); +} + +void +run(void) +{ + XEvent ev; + /* main event loop */ + XSync(dpy, False); + while (running && !XNextEvent(dpy, &ev)) { + + + if (handler[ev.type]) + handler[ev.type](&ev); /* call handler */ + } +} + +void +scan(void) +{ + scanner = 1; + char swin[256]; + unsigned int i, num; + Window d1, d2, *wins = NULL; + XWindowAttributes wa; + + if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { + for (i = 0; i < num; i++) { + if (!XGetWindowAttributes(dpy, wins[i], &wa) + || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) + continue; + if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) + manage(wins[i], &wa); + else if (gettextprop(wins[i], netatom[NetClientList], swin, sizeof swin)) + manage(wins[i], &wa); + } + for (i = 0; i < num; i++) { /* now the transients */ + if (!XGetWindowAttributes(dpy, wins[i], &wa)) + continue; + if (XGetTransientForHint(dpy, wins[i], &d1) + && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)) + manage(wins[i], &wa); + } + XFree(wins); + } + scanner = 0; +} + +void +sendmon(Client *c, Monitor *m) +{ + if (c->mon == m) + return; + unfocus(c, 1, NULL); + detach(c); + detachstack(c); + c->mon = m; + if (!(c->tags & SPTAGMASK)) + c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ + attachx(c); + attachstack(c); + focus(NULL); + arrange(NULL); +} + +void +setclientstate(Client *c, long state) +{ + long data[] = { state, None }; + + XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, + PropModeReplace, (unsigned char *)data, 2); +} + +int +sendevent(Client *c, Atom proto) +{ + int n; + Atom *protocols; + int exists = 0; + XEvent ev; + + if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { + while (!exists && n--) + exists = protocols[n] == proto; + XFree(protocols); + } + + if (exists) { + ev.type = ClientMessage; + ev.xclient.window = c->win; + ev.xclient.message_type = wmatom[WMProtocols]; + ev.xclient.format = 32; + ev.xclient.data.l[0] = proto; + ev.xclient.data.l[1] = CurrentTime; + XSendEvent(dpy, c->win, False, NoEventMask, &ev); + } + return exists; +} + +void +setfocus(Client *c) +{ + if (!c->neverfocus) { + XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); + XChangeProperty(dpy, root, netatom[NetActiveWindow], + XA_WINDOW, 32, PropModeReplace, + (unsigned char *) &(c->win), 1); + } + sendevent(c, wmatom[WMTakeFocus]); +} + +void +setfullscreen(Client *c, int fullscreen) +{ + if (fullscreen && !c->isfullscreen) { + XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); + c->isfullscreen = 1; + c->oldbw = c->bw; + c->oldstate = c->isfloating; + c->bw = 0; + c->isfloating = 1; + resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); + XRaiseWindow(dpy, c->win); + } else if (!fullscreen && c->isfullscreen){ + XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)0, 0); + c->isfullscreen = 0; + c->bw = c->oldbw; + c->isfloating = c->oldstate; + c->x = c->oldx; + c->y = c->oldy; + c->w = c->oldw; + c->h = c->oldh; + resizeclient(c, c->x, c->y, c->w, c->h); + arrange(c->mon); + } +} + +void +setlayout(const Arg *arg) +{ + if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) { + selmon->sellt ^= 1; + } + if (arg && arg->v) + selmon->lt[selmon->sellt] = (Layout *)arg->v; + + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); + if (selmon->sel) + arrange(selmon); + else + drawbar(selmon); +} + +/* arg > 1.0 will set mfact absolutely */ +void +setmfact(const Arg *arg) +{ + float f; + + if (!arg || !selmon->lt[selmon->sellt]->arrange) + return; + f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; + if (f < 0.05 || f > 0.95) + return; + selmon->mfact = f; + arrange(selmon); +} + +void +setup(void) +{ + int i; + XSetWindowAttributes wa; + Atom utf8string; + + /* clean up any zombies immediately */ + sigchld(0); + + + /* the one line of bloat that would have saved a lot of time for a lot of people */ + putenv("_JAVA_AWT_WM_NONREPARENTING=1"); + + /* init screen */ + screen = DefaultScreen(dpy); + sw = DisplayWidth(dpy, screen); + sh = DisplayHeight(dpy, screen); + root = RootWindow(dpy, screen); + xinitvisual(); + drw = drw_create(dpy, screen, root, sw, sh, visual, depth, cmap); + if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) + die("no fonts could be loaded."); + lrpad = drw->fonts->h; + bh = drw->fonts->h + 2; + updategeom(); + /* init atoms */ + utf8string = XInternAtom(dpy, "UTF8_STRING", False); + wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); + wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); + wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); + wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); + netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); + netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); + netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); + netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); + netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); + netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); + netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); + netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); + /* init cursors */ + cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); + cursor[CurResize] = drw_cur_create(drw, XC_sizing); + cursor[CurMove] = drw_cur_create(drw, XC_fleur); + /* init appearance */ + scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); + for (i = 0; i < LENGTH(colors); i++) + scheme[i] = drw_scm_create(drw, colors[i], alphas[i], ColCount); + + updatebars(); + updatestatus(); + + /* supporting window for NetWMCheck */ + wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0); + XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32, + PropModeReplace, (unsigned char *) &wmcheckwin, 1); + XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8, + PropModeReplace, (unsigned char *) "dwm", 3); + XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32, + PropModeReplace, (unsigned char *) &wmcheckwin, 1); + /* EWMH support per view */ + XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, + PropModeReplace, (unsigned char *) netatom, NetLast); + XDeleteProperty(dpy, root, netatom[NetClientList]); + /* select events */ + wa.cursor = cursor[CurNormal]->cursor; + wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask + |ButtonPressMask|PointerMotionMask|EnterWindowMask + |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; + XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); + XSelectInput(dpy, root, wa.event_mask); + + + grabkeys(); + focus(NULL); +} + + +void +seturgent(Client *c, int urg) +{ + XWMHints *wmh; + + c->isurgent = urg; + if (!(wmh = XGetWMHints(dpy, c->win))) + return; + wmh->flags = urg ? (wmh->flags | XUrgencyHint) : (wmh->flags & ~XUrgencyHint); + XSetWMHints(dpy, c->win, wmh); + XFree(wmh); +} + +void +showhide(Client *c) +{ + if (!c) + return; + if (ISVISIBLE(c)) { + if ((c->tags & SPTAGMASK) && c->isfloating) { + c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2); + c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2); + } + /* show clients top down */ + XMoveWindow(dpy, c->win, c->x, c->y); + if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) + && !c->isfullscreen + ) + resize(c, c->x, c->y, c->w, c->h, 0); + showhide(c->snext); + } else { + /* hide clients bottom up */ + showhide(c->snext); + XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y); + } +} + +void +sigchld(int unused) +{ + pid_t pid; + if (signal(SIGCHLD, sigchld) == SIG_ERR) + die("can't install SIGCHLD handler:"); + while (0 < (pid = waitpid(-1, NULL, WNOHANG))) { + pid_t *p, *lim; + + if (!(p = autostart_pids)) + continue; + lim = &p[autostart_len]; + + for (; p < lim; p++) { + if (*p == pid) { + *p = -1; + break; + } + } + } +} + +void +spawn(const Arg *arg) +{ + if (arg->v == dmenucmd) + dmenumon[0] = '0' + selmon->num; + + if (fork() == 0) + { + if (dpy) + close(ConnectionNumber(dpy)); + + setsid(); + execvp(((char **)arg->v)[0], (char **)arg->v); + fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]); + perror(" failed"); + exit(EXIT_SUCCESS); + } +} + +void +tag(const Arg *arg) +{ + + if (selmon->sel && arg->ui & TAGMASK) { + selmon->sel->tags = arg->ui & TAGMASK; + focus(NULL); + arrange(selmon); + } +} + +void +tagmon(const Arg *arg) +{ + Client *c = selmon->sel; + Monitor *dest; + if (!c || !mons->next) + return; + dest = dirtomon(arg->i); + sendmon(c, dest); +} + +void +togglebar(const Arg *arg) +{ + Bar *bar; + selmon->showbar = !selmon->showbar; + updatebarpos(selmon); + for (bar = selmon->bar; bar; bar = bar->next) + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + arrange(selmon); +} + +void +togglefloating(const Arg *arg) +{ + Client *c = selmon->sel; + if (arg && arg->v) + c = (Client*)arg->v; + if (!c) + return; + if (c->isfullscreen) /* no support for fullscreen windows */ + return; + c->isfloating = !c->isfloating || c->isfixed; + if (c->isfloating) + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColFloat].pixel); + else + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); + if (c->isfloating) { + resize(c, c->x, c->y, c->w, c->h, 0); + } + arrange(c->mon); + +} + +void +toggletag(const Arg *arg) +{ + unsigned int newtags; + + if (!selmon->sel) + return; + newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); + if (newtags) { + selmon->sel->tags = newtags; + focus(NULL); + arrange(selmon); + } +} + +void +toggleview(const Arg *arg) +{ + unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);; + + + if (newtagset) { + selmon->tagset[selmon->seltags] = newtagset; + + focus(NULL); + arrange(selmon); + } +} + +void +unfocus(Client *c, int setfocus, Client *nextfocus) +{ + if (!c) + return; + grabbuttons(c, 0); + if (c->isfloating) + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColFloat].pixel); + else + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); + if (setfocus) { + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + } +} + +void +unmanage(Client *c, int destroyed) +{ + Monitor *m = c->mon; + XWindowChanges wc; + + if (c->swallowing) { + unswallow(c); + return; + } + + Client *s = swallowingclient(c->win); + if (s) { + free(s->swallowing); + s->swallowing = NULL; + arrange(m); + focus(NULL); + return; + } + + detach(c); + detachstack(c); + if (!destroyed) { + wc.border_width = c->oldbw; + XGrabServer(dpy); /* avoid race conditions */ + XSetErrorHandler(xerrordummy); + XSelectInput(dpy, c->win, NoEventMask); + XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ + XUngrabButton(dpy, AnyButton, AnyModifier, c->win); + setclientstate(c, WithdrawnState); + XSync(dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } + + + free(c); + if (s) + return; + focus(NULL); + updateclientlist(); + arrange(m); +} + +void +unmapnotify(XEvent *e) +{ + Client *c; + XUnmapEvent *ev = &e->xunmap; + + if ((c = wintoclient(ev->window))) { + if (ev->send_event) + setclientstate(c, WithdrawnState); + else + unmanage(c, 0); + } +} + +void +updatebars(void) +{ + Bar *bar; + Monitor *m; + XSetWindowAttributes wa = { + .override_redirect = True, + .background_pixel = 0, + .border_pixel = 0, + .colormap = cmap, + .event_mask = ButtonPressMask|ExposureMask + }; + XClassHint ch = {"dwm", "dwm"}; + for (m = mons; m; m = m->next) { + for (bar = m->bar; bar; bar = bar->next) { + if (bar->external) + continue; + if (!bar->win) { + bar->win = XCreateWindow(dpy, root, bar->bx, bar->by, bar->bw, bar->bh, 0, depth, + InputOutput, visual, + CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa); + XDefineCursor(dpy, bar->win, cursor[CurNormal]->cursor); + XMapRaised(dpy, bar->win); + XSetClassHint(dpy, bar->win, &ch); + } + } + } +} + +void +updatebarpos(Monitor *m) +{ + + m->wx = m->mx; + m->wy = m->my; + m->ww = m->mw; + m->wh = m->mh; + Bar *bar; + int y_pad = 0; + int x_pad = 0; + + + for (bar = m->bar; bar; bar = bar->next) { + bar->bx = m->wx + x_pad; + bar->bw = m->ww - 2 * x_pad; + } + + for (bar = m->bar; bar; bar = bar->next) + if (!m->showbar || !bar->showbar) + bar->by = -bar->bh - y_pad; + + + if (!m->showbar) + return; + for (bar = m->bar; bar; bar = bar->next) { + if (!bar->showbar) + continue; + if (bar->topbar) + m->wy = m->wy + bar->bh + y_pad; + m->wh -= y_pad + bar->bh; + bar->by = (bar->topbar ? m->wy - bar->bh : m->wy + m->wh); + } +} + +void +updateclientlist() +{ + Client *c; + Monitor *m; + + XDeleteProperty(dpy, root, netatom[NetClientList]); + for (m = mons; m; m = m->next) + for (c = m->clients; c; c = c->next) + XChangeProperty(dpy, root, netatom[NetClientList], + XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); + +} + +int +updategeom(void) +{ + int dirty = 0; + +#ifdef XINERAMA + if (XineramaIsActive(dpy)) { + int i, j, n, nn; + Client *c; + Monitor *m; + XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); + XineramaScreenInfo *unique = NULL; + + for (n = 0, m = mons; m; m = m->next, n++); + /* only consider unique geometries as separate screens */ + unique = ecalloc(nn, sizeof(XineramaScreenInfo)); + for (i = 0, j = 0; i < nn; i++) + if (isuniquegeom(unique, j, &info[i])) + memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); + XFree(info); + nn = j; + /* new monitors if nn > n */ + for (i = n; i < nn; i++) { + for (m = mons; m && m->next; m = m->next); + if (m) + m->next = createmon(); + else + mons = createmon(); + } + for (i = 0, m = mons; i < nn && m; m = m->next, i++) + if (i >= n + || unique[i].x_org != m->mx || unique[i].y_org != m->my + || unique[i].width != m->mw || unique[i].height != m->mh) + { + dirty = 1; + m->num = i; + m->mx = m->wx = unique[i].x_org; + m->my = m->wy = unique[i].y_org; + m->mw = m->ww = unique[i].width; + m->mh = m->wh = unique[i].height; + updatebarpos(m); + } + /* removed monitors if n > nn */ + for (i = nn; i < n; i++) { + for (m = mons; m && m->next; m = m->next); + while ((c = m->clients)) { + dirty = 1; + m->clients = c->next; + detachstack(c); + c->mon = mons; + attach(c); + attachstack(c); + } + if (m == selmon) + selmon = mons; + cleanupmon(m); + } + free(unique); + } else +#endif /* XINERAMA */ + { /* default monitor setup */ + if (!mons) + mons = createmon(); + if (mons->mw != sw || mons->mh != sh) { + dirty = 1; + mons->mw = mons->ww = sw; + mons->mh = mons->wh = sh; + updatebarpos(mons); + } + } + if (dirty) { + selmon = mons; + selmon = wintomon(root); + } + return dirty; +} + +void +updatenumlockmask(void) +{ + unsigned int i, j; + XModifierKeymap *modmap; + + numlockmask = 0; + modmap = XGetModifierMapping(dpy); + for (i = 0; i < 8; i++) + for (j = 0; j < modmap->max_keypermod; j++) + if (modmap->modifiermap[i * modmap->max_keypermod + j] + == XKeysymToKeycode(dpy, XK_Num_Lock)) + numlockmask = (1 << i); + XFreeModifiermap(modmap); +} + +void +updatesizehints(Client *c) +{ + long msize; + XSizeHints size; + + if (!XGetWMNormalHints(dpy, c->win, &size, &msize)) + /* size is uninitialized, ensure that size.flags aren't used */ + size.flags = PSize; + if (size.flags & PBaseSize) { + c->basew = size.base_width; + c->baseh = size.base_height; + } else if (size.flags & PMinSize) { + c->basew = size.min_width; + c->baseh = size.min_height; + } else + c->basew = c->baseh = 0; + if (size.flags & PResizeInc) { + c->incw = size.width_inc; + c->inch = size.height_inc; + } else + c->incw = c->inch = 0; + if (size.flags & PMaxSize) { + c->maxw = size.max_width; + c->maxh = size.max_height; + } else + c->maxw = c->maxh = 0; + if (size.flags & PMinSize) { + c->minw = size.min_width; + c->minh = size.min_height; + } else if (size.flags & PBaseSize) { + c->minw = size.base_width; + c->minh = size.base_height; + } else + c->minw = c->minh = 0; + if (size.flags & PAspect) { + c->mina = (float)size.min_aspect.y / size.min_aspect.x; + c->maxa = (float)size.max_aspect.x / size.max_aspect.y; + } else + c->maxa = c->mina = 0.0; + c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh); + c->hintsvalid = 1; +} + +void +updatestatus(void) +{ + Monitor *m; + if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) + strcpy(stext, "dwm-"VERSION); + for (m = mons; m; m = m->next) + drawbar(m); +} + +void +updatetitle(Client *c) +{ + + if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) + gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name); + if (c->name[0] == '\0') /* hack to mark broken clients */ + strcpy(c->name, broken); + +} + +void +updatewmhints(Client *c) +{ + XWMHints *wmh; + + if ((wmh = XGetWMHints(dpy, c->win))) { + if (c == selmon->sel && wmh->flags & XUrgencyHint) { + wmh->flags &= ~XUrgencyHint; + XSetWMHints(dpy, c->win, wmh); + } else + c->isurgent = (wmh->flags & XUrgencyHint) ? 1 : 0; + if (c->isurgent) { + if (c->isfloating) + XSetWindowBorder(dpy, c->win, scheme[SchemeUrg][ColFloat].pixel); + else + XSetWindowBorder(dpy, c->win, scheme[SchemeUrg][ColBorder].pixel); + } + if (wmh->flags & InputHint) + c->neverfocus = !wmh->input; + else + c->neverfocus = 0; + XFree(wmh); + } +} + +void +view(const Arg *arg) +{ + if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) + { + return; + } + selmon->seltags ^= 1; /* toggle sel tagset */ + if (arg->ui & TAGMASK) + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; + focus(NULL); + arrange(selmon); +} + +Client * +wintoclient(Window w) +{ + Client *c; + Monitor *m; + + for (m = mons; m; m = m->next) + for (c = m->clients; c; c = c->next) + if (c->win == w) + return c; + return NULL; +} + +Monitor * +wintomon(Window w) +{ + int x, y; + Client *c; + Monitor *m; + Bar *bar; + + if (w == root && getrootptr(&x, &y)) + return recttomon(x, y, 1, 1); + for (m = mons; m; m = m->next) + for (bar = m->bar; bar; bar = bar->next) + if (w == bar->win) + return m; + if ((c = wintoclient(w))) + return c->mon; + return selmon; +} + +/* There's no way to check accesses to destroyed windows, thus those cases are + * ignored (especially on UnmapNotify's). Other types of errors call Xlibs + * default error handler, which may call exit. */ +int +xerror(Display *dpy, XErrorEvent *ee) +{ + if (ee->error_code == BadWindow + || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) + || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) + || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) + || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable) + || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch) + || (ee->request_code == X_GrabButton && ee->error_code == BadAccess) + || (ee->request_code == X_GrabKey && ee->error_code == BadAccess) + || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) + return 0; + fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", + ee->request_code, ee->error_code); + return xerrorxlib(dpy, ee); /* may call exit */ +} + +int +xerrordummy(Display *dpy, XErrorEvent *ee) +{ + return 0; +} + +/* Startup Error handler to check if another window manager + * is already running. */ +int +xerrorstart(Display *dpy, XErrorEvent *ee) +{ + die("dwm: another window manager is already running"); + return -1; +} + +void +zoom(const Arg *arg) +{ + Client *c = selmon->sel; + if (arg && arg->v) + c = (Client*)arg->v; + if (!c) + return; + + + + if (!c->mon->lt[c->mon->sellt]->arrange + || (c && c->isfloating) + ) + return; + + if (c == nexttiled(c->mon->clients)) + if (!c || !(c = nexttiled(c->next))) + return; + pop(c); +} + +int +main(int argc, char *argv[]) +{ + if (argc == 2 && !strcmp("-v", argv[1])) + die("dwm-"VERSION); + else if (argc != 1) + die("usage: dwm [-v]"); + if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) + fputs("warning: no locale support\n", stderr); + if (!(dpy = XOpenDisplay(NULL))) + die("dwm: cannot open display"); + if (!(xcon = XGetXCBConnection(dpy))) + die("dwm: cannot get xcb connection\n"); + checkotherwm(); + XrmInitialize(); + loadxrdb(); + autostart_exec(); + setup(); +#ifdef __OpenBSD__ + if (pledge("stdio rpath proc exec ps", NULL) == -1) + die("pledge"); +#endif /* __OpenBSD__ */ + scan(); + run(); + cleanup(); + XCloseDisplay(dpy); + return EXIT_SUCCESS; +} + diff --git a/dwm/dwm.o b/dwm/dwm.o new file mode 100644 index 0000000000000000000000000000000000000000..387744ff2292fe0b34b8ec69832bfeaf140e3a65 GIT binary patch literal 100392 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 literal 0 HcmV?d00001 diff --git a/dwm/dwm.png b/dwm/dwm.png new file mode 100644 index 0000000000000000000000000000000000000000..b1f9ba7e5f4cc7350ee2392ebcea5fcbe00fb49b GIT binary patch literal 373 zcmeAS@N?(olHy`uVBq!ia0vp^2Y@($g9*gC@m3f}u_bxCyDx`7I;J! zGca%iWx0hJ8D`Cq01C2~c>21sUt<^MF=V?Ztt9{yk}YwKC~?lu%}vcKVQ?-=O)N=G zQ7F$W$xsN%NL6t6^bL5QqM8R(c+=CxF{I+w+q;fj4F)_6j>`Z3pZ>_($QEQ&92OXP z%lpEKGwG8$G-U1H{@Y%;mx-mNK|p|siBVAj$Z~Mt-~h6K0!}~{PyozQ07(f5fTdVi zm=-zT`NweeJ#%S&{fequZGmkDDC*%x$$Sa*fAP=$`nJkhx1Y~k<8b2;Hq)FOdV=P$ q&oWzoxz_&nv&n0)xBzV8k*jsxheTIy&cCY600f?{elF{r5}E*x)opSB literal 0 HcmV?d00001 diff --git a/dwm/mkconfig/config.mk.freebsd b/dwm/mkconfig/config.mk.freebsd new file mode 100644 index 0000000..e3fb9ab --- /dev/null +++ b/dwm/mkconfig/config.mk.freebsd @@ -0,0 +1,59 @@ +# dwm version +VERSION = 6.3 + +# Customize below to fit your system + +# paths +PREFIX = /usr/local +MANPREFIX = ${PREFIX}/share/man + +X11INC = /usr/X11R6/include +X11LIB = /usr/X11R6/lib + +X11INC = /usr/local/include +X11LIB = /usr/local/lib + +# Xinerama, comment if you don't want it +XINERAMALIBS = -lXinerama +XINERAMAFLAGS = -DXINERAMA + +# freetype +FREETYPELIBS = -lfontconfig -lXft +FREETYPEINC = /usr/include/freetype2 +FREETYPEINC = /usr/local/include/freetype2 + +# Uncomment this for the alpha patch and the winicon patch (BAR_ALPHA_PATCH, BAR_WINICON_PATCH) +XRENDER = -lXrender + +# Uncomment this for the mdpcontrol patch / MDPCONTROL_PATCH +#MPDCLIENT = -lmpdclient + +# Uncomment for the pango patch / BAR_PANGO_PATCH +#PANGOINC = `pkg-config --cflags xft pango pangoxft` +#PANGOLIB = `pkg-config --libs xft pango pangoxft` + +# Uncomment for the ipc patch / IPC_PATCH +#YAJLLIBS = -lyajl +#YAJLINC = -I/usr/include/yajl + +# Uncomment this for the rounded corners patch / ROUNDED_CORNERS_PATCH +#XEXTLIB = -lXext + +# Uncomment this for the swallow patch / SWALLOW_PATCH +XCBLIBS = -lX11-xcb -lxcb -lxcb-res + +# This is needed for the winicon and tagpreview patches / BAR_WINICON_PATCH / BAR_TAGPREVIEW_PATCH +#IMLIB2LIBS = -lImlib2 + +# includes and libs +INCS = -I${X11INC} -I${FREETYPEINC} ${YAJLINC} ${PANGOINC} +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XRENDER} ${MPDCLIENT} ${XEXTLIB} ${XCBLIBS} ${KVMLIB} ${PANGOLIB} ${YAJLLIBS} ${IMLIB2LIBS} + +# flags +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} +CFLAGS = -std=c99 -pedantic -Wall -Wno-unused-function -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} +LDFLAGS = ${LIBS} + +# compiler and linker +CC = cc diff --git a/dwm/mkconfig/config.mk.linux b/dwm/mkconfig/config.mk.linux new file mode 100644 index 0000000..7b3b027 --- /dev/null +++ b/dwm/mkconfig/config.mk.linux @@ -0,0 +1,55 @@ +# dwm version +VERSION = 6.3 + +# Customize below to fit your system + +# paths +PREFIX = /usr/local +MANPREFIX = ${PREFIX}/share/man + +X11INC = /usr/X11R6/include +X11LIB = /usr/X11R6/lib + +# Xinerama, comment if you don't want it +XINERAMALIBS = -lXinerama +XINERAMAFLAGS = -DXINERAMA + +# freetype +FREETYPELIBS = -lfontconfig -lXft +FREETYPEINC = /usr/include/freetype2 + +# Uncomment this for the alpha patch and the winicon patch (BAR_ALPHA_PATCH, BAR_WINICON_PATCH) +XRENDER = -lXrender + +# Uncomment this for the mdpcontrol patch / MDPCONTROL_PATCH +#MPDCLIENT = -lmpdclient + +# Uncomment for the pango patch / BAR_PANGO_PATCH +#PANGOINC = `pkg-config --cflags xft pango pangoxft` +#PANGOLIB = `pkg-config --libs xft pango pangoxft` + +# Uncomment for the ipc patch / IPC_PATCH +#YAJLLIBS = -lyajl +#YAJLINC = -I/usr/include/yajl + +# Uncomment this for the rounded corners patch / ROUNDED_CORNERS_PATCH +#XEXTLIB = -lXext + +# Uncomment this for the swallow patch / SWALLOW_PATCH +XCBLIBS = -lX11-xcb -lxcb -lxcb-res + +# This is needed for the winicon and tagpreview patches / BAR_WINICON_PATCH / BAR_TAGPREVIEW_PATCH +#IMLIB2LIBS = -lImlib2 + +# includes and libs +INCS = -I${X11INC} -I${FREETYPEINC} ${YAJLINC} ${PANGOINC} +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XRENDER} ${MPDCLIENT} ${XEXTLIB} ${XCBLIBS} ${KVMLIB} ${PANGOLIB} ${YAJLLIBS} ${IMLIB2LIBS} + +# flags +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} +CFLAGS = -std=c99 -pedantic -Wall -Wno-unused-function -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} +LDFLAGS = ${LIBS} + +# compiler and linker +CC = cc diff --git a/dwm/mkconfig/config.mk.openbsd b/dwm/mkconfig/config.mk.openbsd new file mode 100644 index 0000000..6651dbb --- /dev/null +++ b/dwm/mkconfig/config.mk.openbsd @@ -0,0 +1,57 @@ +# dwm version +VERSION = 6.3 + +# Customize below to fit your system + +# paths +PREFIX = /usr/local +MANPREFIX = ${PREFIX}/share/man + +X11INC = /usr/X11R6/include +X11LIB = /usr/X11R6/lib + +# Xinerama, comment if you don't want it +XINERAMALIBS = -lXinerama +XINERAMAFLAGS = -DXINERAMA + +# freetype +FREETYPELIBS = -lfontconfig -lXft +FREETYPEINC = /usr/include/freetype2 +FREETYPEINC = ${X11INC}/freetype2 +KVMLIB = -lkvm + +# Uncomment this for the alpha patch and the winicon patch (BAR_ALPHA_PATCH, BAR_WINICON_PATCH) +XRENDER = -lXrender + +# Uncomment this for the mdpcontrol patch / MDPCONTROL_PATCH +#MPDCLIENT = -lmpdclient + +# Uncomment for the pango patch / BAR_PANGO_PATCH +#PANGOINC = `pkg-config --cflags xft pango pangoxft` +#PANGOLIB = `pkg-config --libs xft pango pangoxft` + +# Uncomment for the ipc patch / IPC_PATCH +#YAJLLIBS = -lyajl +#YAJLINC = -I/usr/include/yajl + +# Uncomment this for the rounded corners patch / ROUNDED_CORNERS_PATCH +#XEXTLIB = -lXext + +# Uncomment this for the swallow patch / SWALLOW_PATCH +XCBLIBS = -lX11-xcb -lxcb -lxcb-res + +# This is needed for the winicon and tagpreview patches / BAR_WINICON_PATCH / BAR_TAGPREVIEW_PATCH +#IMLIB2LIBS = -lImlib2 + +# includes and libs +INCS = -I${X11INC} -I${FREETYPEINC} ${YAJLINC} ${PANGOINC} +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XRENDER} ${MPDCLIENT} ${XEXTLIB} ${XCBLIBS} ${KVMLIB} ${PANGOLIB} ${YAJLLIBS} ${IMLIB2LIBS} + +# flags +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} +CFLAGS = -std=c99 -pedantic -Wall -Wno-unused-function -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} +LDFLAGS = ${LIBS} + +# compiler and linker +CC = cc diff --git a/dwm/mkconfig/config.mk.solaris b/dwm/mkconfig/config.mk.solaris new file mode 100644 index 0000000..7a6d93f --- /dev/null +++ b/dwm/mkconfig/config.mk.solaris @@ -0,0 +1,58 @@ +# dwm version +VERSION = 6.3 + +# Customize below to fit your system + +# paths +PREFIX = /usr/local +MANPREFIX = ${PREFIX}/share/man + +X11INC = /usr/X11R6/include +X11LIB = /usr/X11R6/lib + +# Xinerama, comment if you don't want it +XINERAMALIBS = -lXinerama +XINERAMAFLAGS = -DXINERAMA + +# freetype +FREETYPELIBS = -lfontconfig -lXft +FREETYPEINC = /usr/include/freetype2 + +# Uncomment this for the alpha patch and the winicon patch (BAR_ALPHA_PATCH, BAR_WINICON_PATCH) +XRENDER = -lXrender + +# Uncomment this for the mdpcontrol patch / MDPCONTROL_PATCH +#MPDCLIENT = -lmpdclient + +# Uncomment for the pango patch / BAR_PANGO_PATCH +#PANGOINC = `pkg-config --cflags xft pango pangoxft` +#PANGOLIB = `pkg-config --libs xft pango pangoxft` + +# Uncomment for the ipc patch / IPC_PATCH +#YAJLLIBS = -lyajl +#YAJLINC = -I/usr/include/yajl + +# Uncomment this for the rounded corners patch / ROUNDED_CORNERS_PATCH +#XEXTLIB = -lXext + +# Uncomment this for the swallow patch / SWALLOW_PATCH +XCBLIBS = -lX11-xcb -lxcb -lxcb-res + +# This is needed for the winicon and tagpreview patches / BAR_WINICON_PATCH / BAR_TAGPREVIEW_PATCH +#IMLIB2LIBS = -lImlib2 + +# includes and libs +INCS = -I${X11INC} -I${FREETYPEINC} ${YAJLINC} ${PANGOINC} +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XRENDER} ${MPDCLIENT} ${XEXTLIB} ${XCBLIBS} ${KVMLIB} ${PANGOLIB} ${YAJLLIBS} ${IMLIB2LIBS} + +# flags +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} +CFLAGS = -std=c99 -pedantic -Wall -Wno-unused-function -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} +LDFLAGS = ${LIBS} + +CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" +LDFLAGS = ${LIBS} + +# compiler and linker +CC = cc diff --git a/dwm/patch/attachx.c b/dwm/patch/attachx.c new file mode 100644 index 0000000..c683dce --- /dev/null +++ b/dwm/patch/attachx.c @@ -0,0 +1,20 @@ +void +attachx(Client *c) +{ + Client *at; + + + unsigned int n; + for (at = c->mon->clients, n = 0; at; at = at->next) + if (!at->isfloating && ISVISIBLEONTAG(at, c->tags)) + if (++n >= c->mon->nmaster) + break; + + if (at && c->mon->nmaster) { + c->next = at->next; + at->next = c; + return; + } + attach(c); // master (default) +} + diff --git a/dwm/patch/attachx.h b/dwm/patch/attachx.h new file mode 100644 index 0000000..e522d27 --- /dev/null +++ b/dwm/patch/attachx.h @@ -0,0 +1,2 @@ +static void attachx(Client *c); + diff --git a/dwm/patch/bar.c b/dwm/patch/bar.c new file mode 100644 index 0000000..65e1a69 --- /dev/null +++ b/dwm/patch/bar.c @@ -0,0 +1,39 @@ +void +barhover(XEvent *e, Bar *bar) +{ + const BarRule *br; + Monitor *m = bar->mon; + XMotionEvent *ev = &e->xmotion; + BarArg barg = { 0, 0, 0, 0 }; + int r; + + for (r = 0; r < LENGTH(barrules); r++) { + br = &barrules[r]; + if (br->bar != bar->idx || (br->monitor == 'A' && m != selmon) || br->hoverfunc == NULL) + continue; + if (br->monitor != 'A' && br->monitor != -1 && br->monitor != bar->mon->num) + continue; + if (bar->x[r] > ev->x || ev->x > bar->x[r] + bar->w[r]) + continue; + + barg.x = ev->x - bar->x[r]; + barg.y = ev->y - bar->borderpx; + barg.w = bar->w[r]; + barg.h = bar->bh - 2 * bar->borderpx; + + br->hoverfunc(bar, &barg, ev); + break; + } +} + +Bar * +wintobar(Window win) +{ + Monitor *m; + Bar *bar; + for (m = mons; m; m = m->next) + for (bar = m->bar; bar; bar = bar->next) + if (bar->win == win) + return bar; + return NULL; +} diff --git a/dwm/patch/bar.h b/dwm/patch/bar.h new file mode 100644 index 0000000..3e006dc --- /dev/null +++ b/dwm/patch/bar.h @@ -0,0 +1,2 @@ +static void barhover(XEvent *e, Bar *bar); +static Bar *wintobar(Window win); diff --git a/dwm/patch/bar_alpha.c b/dwm/patch/bar_alpha.c new file mode 100644 index 0000000..465f6f2 --- /dev/null +++ b/dwm/patch/bar_alpha.c @@ -0,0 +1,43 @@ + +static int useargb = 0; +static Visual *visual; +static int depth; +static Colormap cmap; + +void +xinitvisual() +{ + XVisualInfo *infos; + XRenderPictFormat *fmt; + int nitems; + int i; + + XVisualInfo tpl = { + .screen = screen, + .depth = 32, + .class = TrueColor + }; + long masks = VisualScreenMask | VisualDepthMask | VisualClassMask; + + infos = XGetVisualInfo(dpy, masks, &tpl, &nitems); + visual = NULL; + for (i = 0; i < nitems; i ++) { + fmt = XRenderFindVisualFormat(dpy, infos[i].visual); + if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) { + visual = infos[i].visual; + depth = infos[i].depth; + cmap = XCreateColormap(dpy, root, visual, AllocNone); + useargb = 1; + break; + } + } + + XFree(infos); + + if (!visual) { + visual = DefaultVisual(dpy, screen); + depth = DefaultDepth(dpy, screen); + cmap = DefaultColormap(dpy, screen); + } +} + diff --git a/dwm/patch/bar_alpha.h b/dwm/patch/bar_alpha.h new file mode 100644 index 0000000..1c2a012 --- /dev/null +++ b/dwm/patch/bar_alpha.h @@ -0,0 +1,4 @@ +#define OPAQUE 0xffU + +static void xinitvisual(); + diff --git a/dwm/patch/bar_indicators.c b/dwm/patch/bar_indicators.c new file mode 100644 index 0000000..b003fc8 --- /dev/null +++ b/dwm/patch/bar_indicators.c @@ -0,0 +1,104 @@ +/* Indicator properties, you can override these in your config.h if you want. */ +#ifndef TAGSINDICATOR +#define TAGSINDICATOR 1 // 0 = off, 1 = on if >1 client/view tag, 2 = always on +#endif +#ifndef TAGSPX +#define TAGSPX 5 // # pixels for tag grid boxes +#endif +#ifndef TAGSROWS +#define TAGSROWS 3 // # rows in tag grid (9 tags, e.g. 3x3) +#endif + +void +drawindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert, int type) +{ + int i, boxw, boxs, indn = 0; + if (!(occ & 1 << tag) || type == INDICATOR_NONE) + return; + + boxs = drw->fonts->h / 9; + boxw = drw->fonts->h / 6 + 2; + if (filled == -1) + filled = m == selmon && m->sel && m->sel->tags & 1 << tag; + + switch (type) { + default: + case INDICATOR_TOP_LEFT_SQUARE: + drw_rect(drw, x + boxs, y + boxs, boxw, boxw, filled, invert); + break; + case INDICATOR_TOP_LEFT_LARGER_SQUARE: + drw_rect(drw, x + boxs + 2, y + boxs+1, boxw+1, boxw+1, filled, invert); + break; + case INDICATOR_TOP_BAR: + drw_rect(drw, x + boxw, y, w - ( 2 * boxw + 1), boxw/2, filled, invert); + break; + case INDICATOR_TOP_BAR_SLIM: + drw_rect(drw, x + boxw, y, w - ( 2 * boxw + 1), 1, 0, invert); + break; + case INDICATOR_BOTTOM_BAR: + drw_rect(drw, x + boxw, y + h - boxw/2, w - ( 2 * boxw + 1), boxw/2, filled, invert); + break; + case INDICATOR_BOTTOM_BAR_SLIM: + drw_rect(drw, x + boxw, y + h - 1, w - ( 2 * boxw + 1), 1, 0, invert); + break; + case INDICATOR_BOX: + drw_rect(drw, x + boxw, y, w - 2 * boxw, h, 0, invert); + break; + case INDICATOR_BOX_WIDER: + drw_rect(drw, x + boxw/2, y, w - boxw, h, 0, invert); + break; + case INDICATOR_BOX_FULL: + drw_rect(drw, x, y, w - 2, h, 0, invert); + break; + case INDICATOR_CLIENT_DOTS: + for (c = m->clients; c; c = c->next) { + if (c->tags & (1 << tag)) { + drw_rect(drw, x, 1 + (indn * 2), m->sel == c ? 6 : 1, 1, 1, invert); + indn++; + } + if (h <= 1 + (indn * 2)) { + indn = 0; + x += 2; + } + } + break; + case INDICATOR_RIGHT_TAGS: + if (!c) + break; + for (i = 0; i < NUMTAGS; i++) { + drw_rect(drw, + ( x + w - 2 - ((NUMTAGS / TAGSROWS) * TAGSPX) + - (i % (NUMTAGS/TAGSROWS)) + ((i % (NUMTAGS / TAGSROWS)) * TAGSPX) + ), + ( y + 2 + ((i / (NUMTAGS/TAGSROWS)) * TAGSPX) + - ((i / (NUMTAGS/TAGSROWS))) + ), + TAGSPX, TAGSPX, (c->tags >> i) & 1, 0 + ); + } + break; + case INDICATOR_PLUS_AND_LARGER_SQUARE: + boxs += 2; + boxw += 2; + /* falls through */ + case INDICATOR_PLUS_AND_SQUARE: + drw_rect(drw, x + boxs, y + boxs, boxw % 2 ? boxw : boxw + 1, boxw % 2 ? boxw : boxw + 1, filled, invert); + /* falls through */ + case INDICATOR_PLUS: + if (!(boxw % 2)) + boxw += 1; + drw_rect(drw, x + boxs + boxw / 2, y + boxs, 1, boxw, filled, invert); // | + drw_rect(drw, x + boxs, y + boxs + boxw / 2, boxw + 1, 1, filled, invert); // ‒ + break; + } +} + +void +drawstateindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert) +{ + if (c->isfloating) + drawindicator(m, c, occ, x, y, w, h, tag, filled, invert, floatindicatortype); + else + drawindicator(m, c, occ, x, y, w, h, tag, filled, invert, tiledindicatortype); +} + diff --git a/dwm/patch/bar_indicators.h b/dwm/patch/bar_indicators.h new file mode 100644 index 0000000..c66e4f0 --- /dev/null +++ b/dwm/patch/bar_indicators.h @@ -0,0 +1,21 @@ +enum { + INDICATOR_NONE, + INDICATOR_TOP_LEFT_SQUARE, + INDICATOR_TOP_LEFT_LARGER_SQUARE, + INDICATOR_TOP_BAR, + INDICATOR_TOP_BAR_SLIM, + INDICATOR_BOTTOM_BAR, + INDICATOR_BOTTOM_BAR_SLIM, + INDICATOR_BOX, + INDICATOR_BOX_WIDER, + INDICATOR_BOX_FULL, + INDICATOR_CLIENT_DOTS, + INDICATOR_RIGHT_TAGS, + INDICATOR_PLUS, + INDICATOR_PLUS_AND_SQUARE, + INDICATOR_PLUS_AND_LARGER_SQUARE, +}; + +static void drawindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert, int type); +static void drawstateindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert); + diff --git a/dwm/patch/bar_ltsymbol.c b/dwm/patch/bar_ltsymbol.c new file mode 100644 index 0000000..1fbd1b8 --- /dev/null +++ b/dwm/patch/bar_ltsymbol.c @@ -0,0 +1,18 @@ +int +width_ltsymbol(Bar *bar, BarArg *a) +{ + return TEXTW(bar->mon->ltsymbol); +} + +int +draw_ltsymbol(Bar *bar, BarArg *a) +{ + return drw_text(drw, a->x, a->y, a->w, a->h, lrpad / 2, bar->mon->ltsymbol, 0, False); +} + +int +click_ltsymbol(Bar *bar, Arg *arg, BarArg *a) +{ + return ClkLtSymbol; +} + diff --git a/dwm/patch/bar_ltsymbol.h b/dwm/patch/bar_ltsymbol.h new file mode 100644 index 0000000..4de5720 --- /dev/null +++ b/dwm/patch/bar_ltsymbol.h @@ -0,0 +1,4 @@ +static int width_ltsymbol(Bar *bar, BarArg *a); +static int draw_ltsymbol(Bar *bar, BarArg *a); +static int click_ltsymbol(Bar *bar, Arg *arg, BarArg *a); + diff --git a/dwm/patch/bar_status.c b/dwm/patch/bar_status.c new file mode 100644 index 0000000..65595e0 --- /dev/null +++ b/dwm/patch/bar_status.c @@ -0,0 +1,20 @@ +int +width_status(Bar *bar, BarArg *a) +{ + return TEXTWM(stext); +} + + +int +draw_status(Bar *bar, BarArg *a) +{ + return drw_text(drw, a->x, a->y, a->w, a->h, lrpad / 2, stext, 0, True); +} + + +int +click_status(Bar *bar, Arg *arg, BarArg *a) +{ + return ClkStatusText; +} + diff --git a/dwm/patch/bar_status.h b/dwm/patch/bar_status.h new file mode 100644 index 0000000..c580597 --- /dev/null +++ b/dwm/patch/bar_status.h @@ -0,0 +1,4 @@ +static int width_status(Bar *bar, BarArg *a); +static int draw_status(Bar *bar, BarArg *a); +static int click_status(Bar *bar, Arg *arg, BarArg *a); + diff --git a/dwm/patch/bar_tagicons.c b/dwm/patch/bar_tagicons.c new file mode 100644 index 0000000..57d1629 --- /dev/null +++ b/dwm/patch/bar_tagicons.c @@ -0,0 +1,9 @@ +char * +tagicon(Monitor *m, int tag) +{ + int tagindex = tag + NUMTAGS * m->num; + if (tagindex >= LENGTH(tagicons[DEFAULT_TAGS])) + tagindex = tagindex % LENGTH(tagicons[DEFAULT_TAGS]); + return tagicons[DEFAULT_TAGS][tagindex]; +} + diff --git a/dwm/patch/bar_tagicons.h b/dwm/patch/bar_tagicons.h new file mode 100644 index 0000000..16fad2a --- /dev/null +++ b/dwm/patch/bar_tagicons.h @@ -0,0 +1,8 @@ +enum { + DEFAULT_TAGS, + ALTERNATIVE_TAGS, + ALT_TAGS_DECORATION, +}; + +static char * tagicon(Monitor *m, int tag); + diff --git a/dwm/patch/bar_tags.c b/dwm/patch/bar_tags.c new file mode 100644 index 0000000..8aa37b2 --- /dev/null +++ b/dwm/patch/bar_tags.c @@ -0,0 +1,81 @@ +int +width_tags(Bar *bar, BarArg *a) +{ + int w, i; + Client *c; + unsigned int occ = 0; + for (c = bar->mon->clients; c; c = c->next) + occ |= c->tags == 255 ? 0 : c->tags; + + for (w = 0, i = 0; i < NUMTAGS; i++) { + if (!(occ & 1 << i || bar->mon->tagset[bar->mon->seltags] & 1 << i)) + continue; + w += TEXTW(tagicon(bar->mon, i)); + } + return w; +} + +int +draw_tags(Bar *bar, BarArg *a) +{ + int invert; + int w, x = a->x; + unsigned int i, occ = 0, urg = 0; + char *icon; + Client *c; + Monitor *m = bar->mon; + + for (c = m->clients; c; c = c->next) { + occ |= c->tags == 255 ? 0 : c->tags; + if (c->isurgent) + urg |= c->tags; + } + for (i = 0; i < NUMTAGS; i++) { + /* do not draw vacant tags */ + if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) + continue; + + icon = tagicon(bar->mon, i); + invert = 0; + w = TEXTW(icon); + drw_setscheme(drw, scheme[ + m->tagset[m->seltags] & 1 << i + ? SchemeTagsSel + : urg & 1 << i + ? SchemeUrg + : SchemeTagsNorm + ]); + drw_text(drw, x, a->y, w, a->h, lrpad / 2, icon, invert, False); + drawindicator(m, NULL, occ, x, a->y, w, a->h, i, -1, invert, tagindicatortype); + x += w; + } + + return 1; +} + +int +click_tags(Bar *bar, Arg *arg, BarArg *a) +{ + int i = 0, x = 0; + Client *c; + unsigned int occ = 0; + for (c = bar->mon->clients; c; c = c->next) + occ |= c->tags == 255 ? 0 : c->tags; + + do { + if (!(occ & 1 << i || bar->mon->tagset[bar->mon->seltags] & 1 << i)) + continue; + x += TEXTW(tagicon(bar->mon, i)); + } while (a->x >= x && ++i < NUMTAGS); + if (i < NUMTAGS) { + arg->ui = 1 << i; + } + return ClkTagBar; +} + +int +hover_tags(Bar *bar, BarArg *a, XMotionEvent *ev) +{ + + return 1; +} diff --git a/dwm/patch/bar_tags.h b/dwm/patch/bar_tags.h new file mode 100644 index 0000000..70040d2 --- /dev/null +++ b/dwm/patch/bar_tags.h @@ -0,0 +1,4 @@ +static int width_tags(Bar *bar, BarArg *a); +static int draw_tags(Bar *bar, BarArg *a); +static int click_tags(Bar *bar, Arg *arg, BarArg *a); +static int hover_tags(Bar *bar, BarArg *a, XMotionEvent *ev); diff --git a/dwm/patch/bar_wintitle.c b/dwm/patch/bar_wintitle.c new file mode 100644 index 0000000..d086736 --- /dev/null +++ b/dwm/patch/bar_wintitle.c @@ -0,0 +1,48 @@ +int +width_wintitle(Bar *bar, BarArg *a) +{ + return a->w; +} + +int +draw_wintitle(Bar *bar, BarArg *a) +{ + int x = a->x + lrpad / 2, w = a->w - lrpad / 2; + Monitor *m = bar->mon; + Client *c = m->sel; + + if (!c) { + drw_setscheme(drw, scheme[SchemeTitleNorm]); + drw_rect(drw, x, a->y, w, a->h, 1, 1); + return 0; + } + + int tpad = lrpad / 2; + int tx = x; + int tw = w; + + drw_setscheme(drw, scheme[m == selmon ? SchemeTitleSel : SchemeTitleNorm]); + + if (w <= TEXTW("A") - lrpad + tpad) // reduce text padding if wintitle is too small + tpad = (w - TEXTW("A") + lrpad < 0 ? 0 : (w - TEXTW("A") + lrpad) / 2); + + XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, a->y, w, a->h); + + + tx += tpad; + tw -= lrpad; + + + drw_text(drw, tx, a->y, tw, a->h, 0, c->name, 0, False); + + drawstateindicator(m, c, 1, x, a->y, w, a->h, 0, 0, c->isfixed); + return 1; +} + +int +click_wintitle(Bar *bar, Arg *arg, BarArg *a) +{ + return ClkWinTitle; +} + diff --git a/dwm/patch/bar_wintitle.h b/dwm/patch/bar_wintitle.h new file mode 100644 index 0000000..7e8cce5 --- /dev/null +++ b/dwm/patch/bar_wintitle.h @@ -0,0 +1,4 @@ +static int width_wintitle(Bar *bar, BarArg *a); +static int draw_wintitle(Bar *bar, BarArg *a); +static int click_wintitle(Bar *bar, Arg *arg, BarArg *a); + diff --git a/dwm/patch/cool_autostart.c b/dwm/patch/cool_autostart.c new file mode 100644 index 0000000..ffd4ba3 --- /dev/null +++ b/dwm/patch/cool_autostart.c @@ -0,0 +1,29 @@ +/* dwm will keep pid's of processes from autostart array and kill them at quit */ +static pid_t *autostart_pids; +static size_t autostart_len; + +/* execute command from autostart array */ +static void +autostart_exec() +{ + const char *const *p; + size_t i = 0; + + /* count entries */ + for (p = autostart; *p; autostart_len++, p++) + while (*++p); + + autostart_pids = malloc(autostart_len * sizeof(pid_t)); + for (p = autostart; *p; i++, p++) { + if ((autostart_pids[i] = fork()) == 0) { + setsid(); + execvp(*p, (char *const *)p); + fprintf(stderr, "dwm: execvp %s\n", *p); + perror(" failed"); + _exit(EXIT_FAILURE); + } + /* skip arguments */ + while (*++p); + } +} + diff --git a/dwm/patch/cool_autostart.h b/dwm/patch/cool_autostart.h new file mode 100644 index 0000000..5534d99 --- /dev/null +++ b/dwm/patch/cool_autostart.h @@ -0,0 +1,2 @@ +static void autostart_exec(void); + diff --git a/dwm/patch/dwmc b/dwm/patch/dwmc new file mode 100755 index 0000000..3880428 --- /dev/null +++ b/dwm/patch/dwmc @@ -0,0 +1,130 @@ +#!/usr/bin/env bash + +signal() { + xsetroot -name "fsignal:$*" +} + +case $# in +1) + case $1 in + focusurgent) ;& + mirrorlayout) ;& + mpdcontrol) ;& + pushdown) ;& + pushup) ;& + self_restart) ;& + setlayout) ;& + setcfact) ;& + switchcol) ;& + view) ;& + viewall) ;& + viewtoleft) ;& + viewtoright) ;& + tagtoleft) ;& + tagtoright) ;& + tagandviewtoleft) ;& + tagandviewtoright) ;& + transfer) ;& + transferall) ;& + togglealttag) ;& + togglebar) ;& + togglefloating) ;& + togglefullscreen) ;& + fullscreen) ;& + togglefakefullscreen) ;& + togglesticky) ;& + togglehorizontalmax) ;& + toggleverticalmax) ;& + togglemax) ;& + togglegaps) ;& + defaultgaps) ;& + unfloatvisible) ;& + winview) ;& + xrdb) ;& + zoom) ;& + killclient) ;& + quit) + signal $1 + ;; + *) + echo "Unknown command ($1) or missing one argument." + exit 1 + ;; + esac + ;; +2) + case $1 in + cyclelayout) ;& + explace) ;& + moveplace) ;& + mpdchange) ;& + setkeymode) ;& + switchtag) ;& + togglescratch) ;& + view) + signal $1 ui $2 + ;; + viewex) ;& + toggleviewex) ;& + tagallmon) ;& + tagswapmon) ;& + tagex) ;& + toggletagex) ;& + setborderpx) ;& + setgaps) ;& + setlayoutex) ;& + setlayoutaxisex) ;& + swapfocus) ;& + focusstack) ;& + pushstack) ;& + inplacerotate) ;& + rotatestack) ;& + rotatelayoutaxis) ;& + incnmaster) ;& + incnstack) ;& + incrgaps) ;& + incrigaps) ;& + incrogaps) ;& + incrihgaps) ;& + incrivgaps) ;& + incrohgaps) ;& + incrovgaps) ;& + movestack) ;& + shiftview) ;& + shiftviewclients) ;& + focusmon) ;& + tagmon) + signal $1 i $2 + ;; + setcfact) ;& + setmfact) + signal $1 f $2 + ;; + *) + echo "Unknown command ($1) or too many arguments" + exit 1 + ;; + esac + ;; +5) + case $1 in + setgaps) + # Expects "setgaps oh ov ih iv" where -1 means to keep existing values + [ $2 = -1 ] && oh=128 || oh=$2 + [ $3 = -1 ] && ov=128 || ov=$3 + [ $4 = -1 ] && ih=128 || ih=$4 + [ $5 = -1 ] && iv=128 || iv=$5 + signal $1 i $(((oh << 24) + (ov << 16) + (ih << 8) + iv)) + ;; + *) + echo "Unknown command ($1) or too many arguments" + exit 1 + ;; + esac + ;; +*) + echo "Unknown command ($1) or too many arguments" + exit 1 + ;; +esac + diff --git a/dwm/patch/dwmc.c b/dwm/patch/dwmc.c new file mode 100644 index 0000000..a892ff7 --- /dev/null +++ b/dwm/patch/dwmc.c @@ -0,0 +1,85 @@ +void +setlayoutex(const Arg *arg) +{ + setlayout(&((Arg) { .v = &layouts[arg->i] })); +} + +void +viewex(const Arg *arg) +{ + view(&((Arg) { .ui = 1 << arg->ui })); +} + +void +viewallex(const Arg *arg) +{ + view(&((Arg){.ui = ~SPTAGMASK})); +} + +void +toggleviewex(const Arg *arg) +{ + toggleview(&((Arg) { .ui = 1 << arg->ui })); +} + +void +tagex(const Arg *arg) +{ + tag(&((Arg) { .ui = 1 << arg->ui })); +} + +void +toggletagex(const Arg *arg) +{ + toggletag(&((Arg) { .ui = 1 << arg->ui })); +} + +void +tagallex(const Arg *arg) +{ + tag(&((Arg){.ui = ~SPTAGMASK})); +} + +int +fake_signal(void) +{ + char fsignal[256]; + char indicator[9] = "fsignal:"; + char str_sig[50]; + char param[16]; + int i, len_str_sig, n, paramn; + size_t len_fsignal, len_indicator = strlen(indicator); + Arg arg; + + // Get root name property + if (gettextprop(root, XA_WM_NAME, fsignal, sizeof(fsignal))) { + len_fsignal = strlen(fsignal); + + // Check if this is indeed a fake signal + if (len_indicator > len_fsignal ? 0 : strncmp(indicator, fsignal, len_indicator) == 0) { + paramn = sscanf(fsignal+len_indicator, "%s%n%s%n", str_sig, &len_str_sig, param, &n); + + if (paramn == 1) arg = (Arg) {0}; + else if (paramn > 2) return 1; + else if (strncmp(param, "i", n - len_str_sig) == 0) + sscanf(fsignal + len_indicator + n, "%i", &(arg.i)); + else if (strncmp(param, "ui", n - len_str_sig) == 0) + sscanf(fsignal + len_indicator + n, "%u", &(arg.ui)); + else if (strncmp(param, "f", n - len_str_sig) == 0) + sscanf(fsignal + len_indicator + n, "%f", &(arg.f)); + else return 1; + + // Check if a signal was found, and if so handle it + for (i = 0; i < LENGTH(signals); i++) + if (strncmp(str_sig, signals[i].sig, len_str_sig) == 0 && signals[i].func) + signals[i].func(&(arg)); + + // A fake signal was sent + return 1; + } + } + + // No fake signal was sent, so proceed with update + return 0; +} + diff --git a/dwm/patch/dwmc.h b/dwm/patch/dwmc.h new file mode 100644 index 0000000..66e23a9 --- /dev/null +++ b/dwm/patch/dwmc.h @@ -0,0 +1,14 @@ +typedef struct { + const char * sig; + void (*func)(const Arg *); +} Signal; + +static void setlayoutex(const Arg *arg); +static void viewex(const Arg *arg); +static void viewallex(const Arg *arg); +static void toggleviewex(const Arg *arg); +static void tagex(const Arg *arg); +static void toggletagex(const Arg *arg); +static void tagallex(const Arg *arg); +static int fake_signal(void); + diff --git a/dwm/patch/fullscreen.c b/dwm/patch/fullscreen.c new file mode 100644 index 0000000..5fb682a --- /dev/null +++ b/dwm/patch/fullscreen.c @@ -0,0 +1,15 @@ +Layout *last_layout; + +void +fullscreen(const Arg *arg) +{ + int monocle_pos = 0; + if (selmon->showbar || last_layout == NULL) { + for (last_layout = (Layout *)layouts; last_layout != selmon->lt[selmon->sellt]; last_layout++); + setlayout(&((Arg) { .v = &layouts[monocle_pos] })); + } else { + setlayout(&((Arg) { .v = last_layout })); + } + togglebar(arg); +} + diff --git a/dwm/patch/fullscreen.h b/dwm/patch/fullscreen.h new file mode 100644 index 0000000..72983e1 --- /dev/null +++ b/dwm/patch/fullscreen.h @@ -0,0 +1,2 @@ +static void fullscreen(const Arg *arg); + diff --git a/dwm/patch/include.c b/dwm/patch/include.c new file mode 100644 index 0000000..7130889 --- /dev/null +++ b/dwm/patch/include.c @@ -0,0 +1,27 @@ +/* Bar functionality */ +#include "bar_indicators.c" +#include "bar_tagicons.c" +#include "bar.c" + +#include "bar_alpha.c" +#include "bar_ltsymbol.c" +#include "bar_status.c" +#include "bar_tags.c" +#include "bar_wintitle.c" + +/* Other patches */ +#include "attachx.c" +#include "cool_autostart.c" +#include "dwmc.c" +#include "fullscreen.c" +#include "moveresize.c" +#include "movestack.c" +#include "scratchpad.c" +#include "swallow.c" +#include "togglefullscreen.c" +#include "vanitygaps.c" +#include "xrdb.c" +/* Layouts */ +#include "layout_facts.c" +#include "layout_tile.c" + diff --git a/dwm/patch/include.h b/dwm/patch/include.h new file mode 100644 index 0000000..de7c6ec --- /dev/null +++ b/dwm/patch/include.h @@ -0,0 +1,26 @@ +/* Bar functionality */ +#include "bar_indicators.h" +#include "bar_tagicons.h" +#include "bar.h" + +#include "bar_alpha.h" +#include "bar_ltsymbol.h" +#include "bar_status.h" +#include "bar_tags.h" +#include "bar_wintitle.h" + +/* Other patches */ +#include "attachx.h" +#include "cool_autostart.h" +#include "dwmc.h" +#include "fullscreen.h" +#include "moveresize.h" +#include "movestack.h" +#include "scratchpad.h" +#include "swallow.h" +#include "togglefullscreen.h" +#include "vanitygaps.h" +#include "xrdb.h" +/* Layouts */ +#include "layout_tile.h" + diff --git a/dwm/patch/ipc/IPCClient.h b/dwm/patch/ipc/IPCClient.h new file mode 100644 index 0000000..ee93030 --- /dev/null +++ b/dwm/patch/ipc/IPCClient.h @@ -0,0 +1,62 @@ +#ifndef IPC_CLIENT_H_ +#define IPC_CLIENT_H_ + +#include +#include +#include + +typedef struct IPCClient IPCClient; +/** + * This structure contains the details of an IPC Client and pointers for a + * linked list + */ +struct IPCClient { + int fd; + int subscriptions; + + char *buffer; + uint32_t buffer_size; + + struct epoll_event event; + IPCClient *next; + IPCClient *prev; +}; + +typedef IPCClient *IPCClientList; + +/** + * Allocate memory for new IPCClient with the specified file descriptor and + * initialize struct. + * + * @param fd File descriptor of IPC client + * + * @return Address to allocated IPCClient struct + */ +IPCClient *ipc_client_new(int fd); + +/** + * Add an IPC Client to the specified list + * + * @param list Address of the list to add the client to + * @param nc Address of the IPCClient + */ +void ipc_list_add_client(IPCClientList *list, IPCClient *nc); + +/** + * Remove an IPCClient from the specified list + * + * @param list Address of the list to remove the client from + * @param c Address of the IPCClient + */ +void ipc_list_remove_client(IPCClientList *list, IPCClient *c); + +/** + * Get an IPCClient from the specified IPCClient list + * + * @param list List to remove the client from + * @param fd File descriptor of the IPCClient + */ +IPCClient *ipc_list_get_client(IPCClientList list, int fd); + +#endif // IPC_CLIENT_H_ + diff --git a/dwm/patch/ipc/dwm-msg.c b/dwm/patch/ipc/dwm-msg.c new file mode 100644 index 0000000..ca1e1a4 --- /dev/null +++ b/dwm/patch/ipc/dwm-msg.c @@ -0,0 +1,549 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IPC_MAGIC "DWM-IPC" +// clang-format off +#define IPC_MAGIC_ARR { 'D', 'W', 'M', '-', 'I', 'P', 'C' } +// clang-format on +#define IPC_MAGIC_LEN 7 // Not including null char + +#define IPC_EVENT_TAG_CHANGE "tag_change_event" +#define IPC_EVENT_CLIENT_FOCUS_CHANGE "client_focus_change_event" +#define IPC_EVENT_LAYOUT_CHANGE "layout_change_event" +#define IPC_EVENT_MONITOR_FOCUS_CHANGE "monitor_focus_change_event" +#define IPC_EVENT_FOCUSED_TITLE_CHANGE "focused_title_change_event" +#define IPC_EVENT_FOCUSED_STATE_CHANGE "focused_state_change_event" + +#define YSTR(str) yajl_gen_string(gen, (unsigned char *)str, strlen(str)) +#define YINT(num) yajl_gen_integer(gen, num) +#define YDOUBLE(num) yajl_gen_double(gen, num) +#define YBOOL(v) yajl_gen_bool(gen, v) +#define YNULL() yajl_gen_null(gen) +#define YARR(body) \ + { \ + yajl_gen_array_open(gen); \ + body; \ + yajl_gen_array_close(gen); \ + } +#define YMAP(body) \ + { \ + yajl_gen_map_open(gen); \ + body; \ + yajl_gen_map_close(gen); \ + } + +typedef unsigned long Window; + +const char *DEFAULT_SOCKET_PATH = "/tmp/dwm.sock"; +static int sock_fd = -1; +static unsigned int ignore_reply = 0; + +typedef enum IPCMessageType { + IPC_TYPE_RUN_COMMAND = 0, + IPC_TYPE_GET_MONITORS = 1, + IPC_TYPE_GET_TAGS = 2, + IPC_TYPE_GET_LAYOUTS = 3, + IPC_TYPE_GET_DWM_CLIENT = 4, + IPC_TYPE_SUBSCRIBE = 5, + IPC_TYPE_EVENT = 6 +} IPCMessageType; + +// Every IPC message must begin with this +typedef struct dwm_ipc_header { + uint8_t magic[IPC_MAGIC_LEN]; + uint32_t size; + uint8_t type; +} __attribute((packed)) dwm_ipc_header_t; + +static int +recv_message(uint8_t *msg_type, uint32_t *reply_size, uint8_t **reply) +{ + uint32_t read_bytes = 0; + const int32_t to_read = sizeof(dwm_ipc_header_t); + char header[to_read]; + char *walk = header; + + // Try to read header + while (read_bytes < to_read) { + ssize_t n = read(sock_fd, header + read_bytes, to_read - read_bytes); + + if (n == 0) { + if (read_bytes == 0) { + fprintf(stderr, "Unexpectedly reached EOF while reading header."); + fprintf(stderr, + "Read %" PRIu32 " bytes, expected %" PRIu32 " total bytes.\n", + read_bytes, to_read); + return -2; + } else { + fprintf(stderr, "Unexpectedly reached EOF while reading header."); + fprintf(stderr, + "Read %" PRIu32 " bytes, expected %" PRIu32 " total bytes.\n", + read_bytes, to_read); + return -3; + } + } else if (n == -1) { + return -1; + } + + read_bytes += n; + } + + // Check if magic string in header matches + if (memcmp(walk, IPC_MAGIC, IPC_MAGIC_LEN) != 0) { + fprintf(stderr, "Invalid magic string. Got '%.*s', expected '%s'\n", + IPC_MAGIC_LEN, walk, IPC_MAGIC); + return -3; + } + + walk += IPC_MAGIC_LEN; + + // Extract reply size + memcpy(reply_size, walk, sizeof(uint32_t)); + walk += sizeof(uint32_t); + + // Extract message type + memcpy(msg_type, walk, sizeof(uint8_t)); + walk += sizeof(uint8_t); + + (*reply) = malloc(*reply_size); + + // Extract payload + read_bytes = 0; + while (read_bytes < *reply_size) { + ssize_t n = read(sock_fd, *reply + read_bytes, *reply_size - read_bytes); + + if (n == 0) { + fprintf(stderr, "Unexpectedly reached EOF while reading payload."); + fprintf(stderr, "Read %" PRIu32 " bytes, expected %" PRIu32 " bytes.\n", + read_bytes, *reply_size); + free(*reply); + return -2; + } else if (n == -1) { + if (errno == EINTR || errno == EAGAIN) continue; + free(*reply); + return -1; + } + + read_bytes += n; + } + + return 0; +} + +static int +read_socket(IPCMessageType *msg_type, uint32_t *msg_size, char **msg) +{ + int ret = -1; + + while (ret != 0) { + ret = recv_message((uint8_t *)msg_type, msg_size, (uint8_t **)msg); + + if (ret < 0) { + // Try again (non-fatal error) + if (ret == -1 && (errno == EINTR || errno == EAGAIN)) continue; + + fprintf(stderr, "Error receiving response from socket. "); + fprintf(stderr, "The connection might have been lost.\n"); + exit(2); + } + } + + return 0; +} + +static ssize_t +write_socket(const void *buf, size_t count) +{ + size_t written = 0; + + while (written < count) { + const ssize_t n = + write(sock_fd, ((uint8_t *)buf) + written, count - written); + + if (n == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) + continue; + else + return n; + } + written += n; + } + return written; +} + +static void +connect_to_socket() +{ + struct sockaddr_un addr; + + int sock = socket(AF_UNIX, SOCK_STREAM, 0); + + // Initialize struct to 0 + memset(&addr, 0, sizeof(struct sockaddr_un)); + + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, DEFAULT_SOCKET_PATH); + + connect(sock, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)); + + sock_fd = sock; +} + +static int +send_message(IPCMessageType msg_type, uint32_t msg_size, uint8_t *msg) +{ + dwm_ipc_header_t header = { + .magic = IPC_MAGIC_ARR, .size = msg_size, .type = msg_type}; + + size_t header_size = sizeof(dwm_ipc_header_t); + size_t total_size = header_size + msg_size; + + uint8_t buffer[total_size]; + + // Copy header to buffer + memcpy(buffer, &header, header_size); + // Copy message to buffer + memcpy(buffer + header_size, msg, header.size); + + write_socket(buffer, total_size); + + return 0; +} + +static int +is_float(const char *s) +{ + size_t len = strlen(s); + int is_dot_used = 0; + int is_minus_used = 0; + + // Floats can only have one decimal point in between or digits + // Optionally, floats can also be below zero (negative) + for (int i = 0; i < len; i++) { + if (isdigit(s[i])) + continue; + else if (!is_dot_used && s[i] == '.' && i != 0 && i != len - 1) { + is_dot_used = 1; + continue; + } else if (!is_minus_used && s[i] == '-' && i == 0) { + is_minus_used = 1; + continue; + } else + return 0; + } + + return 1; +} + +static int +is_unsigned_int(const char *s) +{ + size_t len = strlen(s); + + // Unsigned int can only have digits + for (int i = 0; i < len; i++) { + if (isdigit(s[i])) + continue; + else + return 0; + } + + return 1; +} + +static int +is_signed_int(const char *s) +{ + size_t len = strlen(s); + + // Signed int can only have digits and a negative sign at the start + for (int i = 0; i < len; i++) { + if (isdigit(s[i])) + continue; + else if (i == 0 && s[i] == '-') { + continue; + } else + return 0; + } + + return 1; +} + +static void +flush_socket_reply() +{ + IPCMessageType reply_type; + uint32_t reply_size; + char *reply; + + read_socket(&reply_type, &reply_size, &reply); + + free(reply); +} + +static void +print_socket_reply() +{ + IPCMessageType reply_type; + uint32_t reply_size; + char *reply; + + read_socket(&reply_type, &reply_size, &reply); + + printf("%.*s\n", reply_size, reply); + fflush(stdout); + free(reply); +} + +static int +run_command(const char *name, char *args[], int argc) +{ + const unsigned char *msg; + size_t msg_size; + + yajl_gen gen = yajl_gen_alloc(NULL); + + // Message format: + // { + // "command": "", + // "args": [ ... ] + // } + // clang-format off + YMAP( + YSTR("command"); YSTR(name); + YSTR("args"); YARR( + for (int i = 0; i < argc; i++) { + if (is_signed_int(args[i])) { + long long num = atoll(args[i]); + YINT(num); + } else if (is_float(args[i])) { + float num = atof(args[i]); + YDOUBLE(num); + } else { + YSTR(args[i]); + } + } + ) + ) + // clang-format on + + yajl_gen_get_buf(gen, &msg, &msg_size); + + send_message(IPC_TYPE_RUN_COMMAND, msg_size, (uint8_t *)msg); + + if (!ignore_reply) + print_socket_reply(); + else + flush_socket_reply(); + + yajl_gen_free(gen); + + return 0; +} + +static int +get_monitors() +{ + send_message(IPC_TYPE_GET_MONITORS, 1, (uint8_t *)""); + print_socket_reply(); + return 0; +} + +static int +get_tags() +{ + send_message(IPC_TYPE_GET_TAGS, 1, (uint8_t *)""); + print_socket_reply(); + + return 0; +} + +static int +get_layouts() +{ + send_message(IPC_TYPE_GET_LAYOUTS, 1, (uint8_t *)""); + print_socket_reply(); + + return 0; +} + +static int +get_dwm_client(Window win) +{ + const unsigned char *msg; + size_t msg_size; + + yajl_gen gen = yajl_gen_alloc(NULL); + + // Message format: + // { + // "client_window_id": "" + // } + // clang-format off + YMAP( + YSTR("client_window_id"); YINT(win); + ) + // clang-format on + + yajl_gen_get_buf(gen, &msg, &msg_size); + + send_message(IPC_TYPE_GET_DWM_CLIENT, msg_size, (uint8_t *)msg); + + print_socket_reply(); + + yajl_gen_free(gen); + + return 0; +} + +static int +subscribe(const char *event) +{ + const unsigned char *msg; + size_t msg_size; + + yajl_gen gen = yajl_gen_alloc(NULL); + + // Message format: + // { + // "event": "", + // "action": "subscribe" + // } + // clang-format off + YMAP( + YSTR("event"); YSTR(event); + YSTR("action"); YSTR("subscribe"); + ) + // clang-format on + + yajl_gen_get_buf(gen, &msg, &msg_size); + + send_message(IPC_TYPE_SUBSCRIBE, msg_size, (uint8_t *)msg); + + if (!ignore_reply) + print_socket_reply(); + else + flush_socket_reply(); + + yajl_gen_free(gen); + + return 0; +} + +static void +usage_error(const char *prog_name, const char *format, ...) +{ + va_list args; + va_start(args, format); + + fprintf(stderr, "Error: "); + vfprintf(stderr, format, args); + fprintf(stderr, "\nusage: %s [...]\n", prog_name); + fprintf(stderr, "Try '%s help'\n", prog_name); + + va_end(args); + exit(1); +} + +static void +print_usage(const char *name) +{ + printf("usage: %s [options] [...]\n", name); + puts(""); + puts("Commands:"); + puts(" run_command [args...] Run an IPC command"); + puts(""); + puts(" get_monitors Get monitor properties"); + puts(""); + puts(" get_tags Get list of tags"); + puts(""); + puts(" get_layouts Get list of layouts"); + puts(""); + puts(" get_dwm_client Get dwm client proprties"); + puts(""); + puts(" subscribe [events...] Subscribe to specified events"); + puts(" Options: " IPC_EVENT_TAG_CHANGE ","); + puts(" " IPC_EVENT_LAYOUT_CHANGE ","); + puts(" " IPC_EVENT_CLIENT_FOCUS_CHANGE ","); + puts(" " IPC_EVENT_MONITOR_FOCUS_CHANGE ","); + puts(" " IPC_EVENT_FOCUSED_TITLE_CHANGE ","); + puts(" " IPC_EVENT_FOCUSED_STATE_CHANGE); + puts(""); + puts(" help Display this message"); + puts(""); + puts("Options:"); + puts(" --ignore-reply Don't print reply messages from"); + puts(" run_command and subscribe."); + puts(""); +} + +int +main(int argc, char *argv[]) +{ + const char *prog_name = argv[0]; + + connect_to_socket(); + if (sock_fd == -1) { + fprintf(stderr, "Failed to connect to socket\n"); + return 1; + } + + int i = 1; + if (i < argc && strcmp(argv[i], "--ignore-reply") == 0) { + ignore_reply = 1; + i++; + } + + if (i >= argc) usage_error(prog_name, "Expected an argument, got none"); + + if (!argc || strcmp(argv[i], "help") == 0) + print_usage(prog_name); + else if (strcmp(argv[i], "run_command") == 0) { + if (++i >= argc) usage_error(prog_name, "No command specified"); + // Command name + char *command = argv[i]; + // Command arguments are everything after command name + char **command_args = argv + ++i; + // Number of command arguments + int command_argc = argc - i; + run_command(command, command_args, command_argc); + } else if (strcmp(argv[i], "get_monitors") == 0) { + get_monitors(); + } else if (strcmp(argv[i], "get_tags") == 0) { + get_tags(); + } else if (strcmp(argv[i], "get_layouts") == 0) { + get_layouts(); + } else if (strcmp(argv[i], "get_dwm_client") == 0) { + if (++i < argc) { + if (is_unsigned_int(argv[i])) { + Window win = atol(argv[i]); + get_dwm_client(win); + } else + usage_error(prog_name, "Expected unsigned integer argument"); + } else + usage_error(prog_name, "Expected the window id"); + } else if (strcmp(argv[i], "subscribe") == 0) { + if (++i < argc) { + for (int j = i; j < argc; j++) subscribe(argv[j]); + } else + usage_error(prog_name, "Expected event name"); + // Keep listening for events forever + while (1) { + print_socket_reply(); + } + } else + usage_error(prog_name, "Invalid argument '%s'", argv[i]); + + return 0; +} + diff --git a/dwm/patch/ipc/yajl_dumps.h b/dwm/patch/ipc/yajl_dumps.h new file mode 100644 index 0000000..bb57a17 --- /dev/null +++ b/dwm/patch/ipc/yajl_dumps.h @@ -0,0 +1,66 @@ +#ifndef YAJL_DUMPS_H_ +#define YAJL_DUMPS_H_ + +#include +#include + +#define YSTR(str) yajl_gen_string(gen, (unsigned char *)str, strlen(str)) +#define YINT(num) yajl_gen_integer(gen, num) +#define YDOUBLE(num) yajl_gen_double(gen, num) +#define YBOOL(v) yajl_gen_bool(gen, v) +#define YNULL() yajl_gen_null(gen) +#define YARR(body) \ + { \ + yajl_gen_array_open(gen); \ + body; \ + yajl_gen_array_close(gen); \ + } +#define YMAP(body) \ + { \ + yajl_gen_map_open(gen); \ + body; \ + yajl_gen_map_close(gen); \ + } + +int dump_tag(yajl_gen gen, const char *name, const int tag_mask); + +int dump_tags(yajl_gen gen, int tags_len); + +int dump_client(yajl_gen gen, Client *c); + +int dump_monitor(yajl_gen gen, Monitor *mon, int is_selected); + +int dump_monitors(yajl_gen gen, Monitor *mons, Monitor *selmon); + +int dump_layouts(yajl_gen gen, const Layout layouts[], const int layouts_len); + +int dump_tag_state(yajl_gen gen, TagState state); + +int dump_tag_event(yajl_gen gen, int mon_num, TagState old_state, + TagState new_state); + +int dump_client_focus_change_event(yajl_gen gen, Client *old_client, + Client *new_client, int mon_num); + +int dump_layout_change_event(yajl_gen gen, const int mon_num, + const char *old_symbol, const Layout *old_layout, + const char *new_symbol, const Layout *new_layout); + +int dump_monitor_focus_change_event(yajl_gen gen, const int last_mon_num, + const int new_mon_num); + +int dump_focused_title_change_event(yajl_gen gen, const int mon_num, + const Window client_id, + const char *old_name, const char *new_name); + +int dump_client_state(yajl_gen gen, const ClientState *state); + +int dump_focused_state_change_event(yajl_gen gen, const int mon_num, + const Window client_id, + const ClientState *old_state, + const ClientState *new_state); + +int dump_error_message(yajl_gen gen, const char *reason); + +#endif // YAJL_DUMPS_H_ + diff --git a/dwm/patch/layout_facts.c b/dwm/patch/layout_facts.c new file mode 100644 index 0000000..241d344 --- /dev/null +++ b/dwm/patch/layout_facts.c @@ -0,0 +1,24 @@ +void +getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr) +{ + unsigned int n; + float mfacts, sfacts; + int mtotal = 0, stotal = 0; + Client *c; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + mfacts = MIN(n, m->nmaster); + sfacts = n - m->nmaster; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) + if (n < m->nmaster) + mtotal += msize / mfacts; + else + stotal += ssize / sfacts; + + *mf = mfacts; // total factor of master area + *sf = sfacts; // total factor of stack area + *mr = msize - mtotal; // the remainder (rest) of pixels after an even master split + *sr = ssize - stotal; // the remainder (rest) of pixels after an even stack split +} + diff --git a/dwm/patch/layout_tile.c b/dwm/patch/layout_tile.c new file mode 100644 index 0000000..8d41d2a --- /dev/null +++ b/dwm/patch/layout_tile.c @@ -0,0 +1,41 @@ +static void +tile(Monitor *m) +{ + unsigned int i, n; + int mx = 0, my = 0, mh = 0, mw = 0; + int sx = 0, sy = 0, sh = 0, sw = 0; + float mfacts, sfacts; + int mrest, srest; + Client *c; + + + int oh, ov, ih, iv; + getgaps(m, &oh, &ov, &ih, &iv, &n); + + if (n == 0) + return; + + sx = mx = m->wx + ov; + sy = my = m->wy + oh; + mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1); + sh = m->wh - 2*oh - ih * (n - m->nmaster - 1); + sw = mw = m->ww - 2*ov; + + if (m->nmaster && n > m->nmaster) { + sw = (mw - iv) * (1 - m->mfact); + mw = (mw - iv) * m->mfact; + sx = mx + mw + iv; + } + + getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest); + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < m->nmaster) { + resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0); + my += HEIGHT(c) + ih; + } else { + resize(c, sx, sy, sw - (2*c->bw), (sh / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0); + sy += HEIGHT(c) + ih; + } +} + diff --git a/dwm/patch/layout_tile.h b/dwm/patch/layout_tile.h new file mode 100644 index 0000000..78cafc8 --- /dev/null +++ b/dwm/patch/layout_tile.h @@ -0,0 +1,2 @@ +static void tile(Monitor *); + diff --git a/dwm/patch/moveresize.c b/dwm/patch/moveresize.c new file mode 100644 index 0000000..75d58e2 --- /dev/null +++ b/dwm/patch/moveresize.c @@ -0,0 +1,65 @@ +void +moveresize(const Arg *arg) { + /* only floating windows can be moved */ + Client *c; + c = selmon->sel; + int x, y, w, h, nx, ny, nw, nh, ox, oy, ow, oh; + char xAbs, yAbs, wAbs, hAbs; + int msx, msy, dx, dy, nmx, nmy; + unsigned int dui; + Window dummy; + + if (!c || !arg) + return; + if (selmon->lt[selmon->sellt]->arrange && !c->isfloating) + return; + if (sscanf((char *)arg->v, "%d%c %d%c %d%c %d%c", &x, &xAbs, &y, &yAbs, &w, &wAbs, &h, &hAbs) != 8) + return; + + /* compute new window position; prevent window from be positioned outside the current monitor */ + nw = c->w + w; + if (wAbs == 'W') + nw = w < selmon->mw - 2 * c->bw ? w : selmon->mw - 2 * c->bw; + + nh = c->h + h; + if (hAbs == 'H') + nh = h < selmon->mh - 2 * c->bw ? h : selmon->mh - 2 * c->bw; + + nx = c->x + x; + if (xAbs == 'X') { + if (x < selmon->mx) + nx = selmon->mx; + else if (x > selmon->mx + selmon->mw) + nx = selmon->mx + selmon->mw - nw - 2 * c->bw; + else + nx = x; + } + + ny = c->y + y; + if (yAbs == 'Y') { + if (y < selmon->my) + ny = selmon->my; + else if (y > selmon->my + selmon->mh) + ny = selmon->my + selmon->mh - nh - 2 * c->bw; + else + ny = y; + } + + ox = c->x; + oy = c->y; + ow = c->w; + oh = c->h; + + XRaiseWindow(dpy, c->win); + Bool xqp = XQueryPointer(dpy, root, &dummy, &dummy, &msx, &msy, &dx, &dy, &dui); + resize(c, nx, ny, nw, nh, True); + + /* move cursor along with the window to avoid problems caused by the sloppy focus */ + if (xqp && ox <= msx && (ox + ow) >= msx && oy <= msy && (oy + oh) >= msy) + { + nmx = c->x - ox + c->w - ow; + nmy = c->y - oy + c->h - oh; + XWarpPointer(dpy, None, None, 0, 0, 0, 0, nmx, nmy); + } +} + diff --git a/dwm/patch/moveresize.h b/dwm/patch/moveresize.h new file mode 100644 index 0000000..919ebad --- /dev/null +++ b/dwm/patch/moveresize.h @@ -0,0 +1,2 @@ +static void moveresize(const Arg *arg); + diff --git a/dwm/patch/movestack.c b/dwm/patch/movestack.c new file mode 100644 index 0000000..fe97f1d --- /dev/null +++ b/dwm/patch/movestack.c @@ -0,0 +1,51 @@ +void +movestack(const Arg *arg) +{ + Client *c = NULL, *p = NULL, *pc = NULL, *i; + if (arg->i > 0) { + if (!selmon->sel) + return; + /* find the client after selmon->sel */ + for (c = selmon->sel->next; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); + if (!c) + for (c = selmon->clients; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); + } + else { + /* find the client before selmon->sel */ + for (i = selmon->clients; i != selmon->sel; i = i->next) + if(ISVISIBLE(i) && !i->isfloating) + c = i; + if (!c) + for (; i; i = i->next) + if (ISVISIBLE(i) && !i->isfloating) + c = i; + } + + /* find the client before selmon->sel and c */ + for (i = selmon->clients; i && (!p || !pc); i = i->next) { + if (i->next == selmon->sel) + p = i; + if (i->next == c) + pc = i; + } + + /* swap c and selmon->sel selmon->clients in the selmon->clients list */ + if (c && c != selmon->sel) { + Client *temp = selmon->sel->next==c?selmon->sel:selmon->sel->next; + selmon->sel->next = c->next==selmon->sel?c:c->next; + c->next = temp; + + if (p && p != c) + p->next = c; + if (pc && pc != selmon->sel) + pc->next = selmon->sel; + + if (selmon->sel == selmon->clients) + selmon->clients = c; + else if (c == selmon->clients) + selmon->clients = selmon->sel; + + arrange(selmon); + } +} + diff --git a/dwm/patch/movestack.h b/dwm/patch/movestack.h new file mode 100644 index 0000000..25f198f --- /dev/null +++ b/dwm/patch/movestack.h @@ -0,0 +1,2 @@ +static void movestack(const Arg *arg); + diff --git a/dwm/patch/scratchpad.c b/dwm/patch/scratchpad.c new file mode 100644 index 0000000..9e24ff6 --- /dev/null +++ b/dwm/patch/scratchpad.c @@ -0,0 +1,77 @@ +void +removescratch(const Arg *arg) +{ + Client *c = selmon->sel; + if (!c) + return; + unsigned int scratchtag = SPTAG(arg->ui); + c->tags = c->mon->tagset[c->mon->seltags] ^ scratchtag; + arrange(c->mon); +} + +void +setscratch(const Arg *arg) +{ + Client *c = selmon->sel; + if (!c) + return; + unsigned int scratchtag = SPTAG(arg->ui); + c->tags = scratchtag; + arrange(c->mon); +} + +void +togglescratch(const Arg *arg) +{ + Client *c = NULL, *next = NULL, *found = NULL; + Monitor *mon; + unsigned int scratchtag = SPTAG(arg->ui); + unsigned int newtagset = 0; + int nh = 0, nw = 0; + Arg sparg = {.v = scratchpads[arg->ui].cmd}; + + for (mon = mons; mon; mon = mon->next) { + for (c = mon->clients; c; c = next) { + next = c->next; + if (!(c->tags & scratchtag)) + continue; + + found = c; + + if (HIDDEN(c)) { + XMapWindow(dpy, c->win); + setclientstate(c, NormalState); + newtagset = 0; + } else + newtagset = selmon->tagset[selmon->seltags] ^ scratchtag; + + if (c->mon != selmon) { + if (c->mon->tagset[c->mon->seltags] & SPTAGMASK) + c->mon->tagset[c->mon->seltags] ^= scratchtag; + if (c->w > selmon->ww) + nw = selmon->ww - c->bw * 2; + if (c->h > selmon->wh) + nh = selmon->wh - c->bw * 2; + if (nw > 0 || nh > 0) + resizeclient(c, c->x, c->y, nw ? nw : c->w, nh ? nh : c->h); + sendmon(c, selmon); + } + } + } + + if (found) { + if (newtagset) { + selmon->tagset[selmon->seltags] = newtagset; + focus(NULL); + arrange(selmon); + } + if (ISVISIBLE(found)) { + focus(found); + restack(selmon); + } + } else { + selmon->tagset[selmon->seltags] |= scratchtag; + spawn(&sparg); + } +} + diff --git a/dwm/patch/scratchpad.h b/dwm/patch/scratchpad.h new file mode 100644 index 0000000..6230266 --- /dev/null +++ b/dwm/patch/scratchpad.h @@ -0,0 +1,9 @@ +typedef struct { + const char *name; + const void *cmd; +} Sp; + +static void removescratch(const Arg *arg); +static void setscratch(const Arg *arg); +static void togglescratch(const Arg *arg); + diff --git a/dwm/patch/swallow.c b/dwm/patch/swallow.c new file mode 100644 index 0000000..0d65353 --- /dev/null +++ b/dwm/patch/swallow.c @@ -0,0 +1,212 @@ +#include +#include +#ifdef __OpenBSD__ +#include +#include +#endif /* __OpenBSD__ */ + +static int scanner; +static xcb_connection_t *xcon; + +int +swallow(Client *p, Client *c) +{ + Client *s; + XWindowChanges wc; + + if (c->noswallow > 0 || c->isterminal) + return 0; + if (c->noswallow < 0 && !swallowfloating && c->isfloating) + return 0; + + XMapWindow(dpy, c->win); + + detach(c); + detachstack(c); + + setclientstate(c, WithdrawnState); + XUnmapWindow(dpy, p->win); + + p->swallowing = c; + c->mon = p->mon; + + Window w = p->win; + p->win = c->win; + c->win = w; + + XChangeProperty(dpy, c->win, netatom[NetClientList], XA_WINDOW, 32, PropModeReplace, + (unsigned char *) &(p->win), 1); + + updatetitle(p); + s = scanner ? c : p; + + wc.border_width = p->bw; + XConfigureWindow(dpy, p->win, CWBorderWidth, &wc); + XMoveResizeWindow(dpy, p->win, s->x, s->y, s->w, s->h); + XSetWindowBorder(dpy, p->win, scheme[SchemeNorm][ColBorder].pixel); + + arrange(p->mon); + configure(p); + updateclientlist(); + + return 1; +} + +void +unswallow(Client *c) +{ + XWindowChanges wc; + c->win = c->swallowing->win; + + free(c->swallowing); + c->swallowing = NULL; + + XDeleteProperty(dpy, c->win, netatom[NetClientList]); + + /* unfullscreen the client */ + setfullscreen(c, 0); + updatetitle(c); + arrange(c->mon); + XMapWindow(dpy, c->win); + + wc.border_width = c->bw; + XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); + XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); + + setclientstate(c, NormalState); + focus(NULL); + arrange(c->mon); +} + +pid_t +winpid(Window w) +{ + pid_t result = 0; + + #ifdef __linux__ + xcb_res_client_id_spec_t spec = {0}; + spec.client = w; + spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID; + + xcb_generic_error_t *e = NULL; + xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec); + xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e); + + if (!r) + return (pid_t)0; + + xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r); + for (; i.rem; xcb_res_client_id_value_next(&i)) { + spec = i.data->spec; + if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) { + uint32_t *t = xcb_res_client_id_value_value(i.data); + result = *t; + break; + } + } + + free(r); + + if (result == (pid_t)-1) + result = 0; + + #endif /* __linux__ */ + #ifdef __OpenBSD__ + Atom type; + int format; + unsigned long len, bytes; + unsigned char *prop; + pid_t ret; + + if (XGetWindowProperty(dpy, w, XInternAtom(dpy, "_NET_WM_PID", 1), 0, 1, False, AnyPropertyType, &type, &format, &len, &bytes, &prop) != Success || !prop) + return 0; + + ret = *(pid_t*)prop; + XFree(prop); + result = ret; + #endif /* __OpenBSD__ */ + + return result; +} + +pid_t +getparentprocess(pid_t p) +{ + unsigned int v = 0; + +#ifdef __linux__ + FILE *f; + char buf[256]; + snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p); + + if (!(f = fopen(buf, "r"))) + return (pid_t)0; + + if (fscanf(f, "%*u %*s %*c %u", (unsigned *)&v) != 1) + v = (pid_t)0; + fclose(f); +#endif /* __linux__ */ +#ifdef __OpenBSD__ + int n; + kvm_t *kd; + struct kinfo_proc *kp; + + kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, NULL); + if (!kd) + return 0; + + kp = kvm_getprocs(kd, KERN_PROC_PID, p, sizeof(*kp), &n); + v = kp->p_ppid; +#endif /* __OpenBSD__ */ + return (pid_t)v; +} + +int +isdescprocess(pid_t p, pid_t c) +{ + while (p != c && c != 0) + c = getparentprocess(c); + + return (int)c; +} + +Client * +termforwin(const Client *w) +{ + Client *c; + Monitor *m; + + if (!w->pid || w->isterminal) + return NULL; + + c = selmon->sel; + if (c && c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid)) + return c; + + for (m = mons; m; m = m->next) { + for (c = m->clients; c; c = c->next) { + if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid)) + return c; + } + } + + return NULL; +} + +Client * +swallowingclient(Window w) +{ + Client *c; + Monitor *m; + + for (m = mons; m; m = m->next) { + for (c = m->clients; c; c = c->next) { + if (c->swallowing && c->swallowing->win == w) + return c; + } + } + + return NULL; +} + diff --git a/dwm/patch/swallow.h b/dwm/patch/swallow.h new file mode 100644 index 0000000..529fea9 --- /dev/null +++ b/dwm/patch/swallow.h @@ -0,0 +1,8 @@ +static pid_t getparentprocess(pid_t p); +static int isdescprocess(pid_t p, pid_t c); +static int swallow(Client *p, Client *c); +static Client *swallowingclient(Window w); +static Client *termforwin(const Client *c); +static void unswallow(Client *c); +static pid_t winpid(Window w); + diff --git a/dwm/patch/togglefullscreen.c b/dwm/patch/togglefullscreen.c new file mode 100644 index 0000000..a62edef --- /dev/null +++ b/dwm/patch/togglefullscreen.c @@ -0,0 +1,10 @@ +void +togglefullscreen(const Arg *arg) +{ + Client *c = selmon->sel; + if (!c) + return; + + setfullscreen(c, !c->isfullscreen); +} + diff --git a/dwm/patch/togglefullscreen.h b/dwm/patch/togglefullscreen.h new file mode 100644 index 0000000..96a6770 --- /dev/null +++ b/dwm/patch/togglefullscreen.h @@ -0,0 +1,2 @@ +static void togglefullscreen(const Arg *arg); + diff --git a/dwm/patch/vanitygaps.c b/dwm/patch/vanitygaps.c new file mode 100644 index 0000000..d8d5e6e --- /dev/null +++ b/dwm/patch/vanitygaps.c @@ -0,0 +1,177 @@ +/* Settings */ +static int enablegaps = 1; + +static void +setgaps(int oh, int ov, int ih, int iv) +{ + if (oh < 0) oh = 0; + if (ov < 0) ov = 0; + if (ih < 0) ih = 0; + if (iv < 0) iv = 0; + + selmon->gappoh = oh; + selmon->gappov = ov; + selmon->gappih = ih; + selmon->gappiv = iv; + + + arrange(selmon); +} + +/* External function that takes one integer and splits it + * into four gap values: + * - outer horizontal (oh) + * - outer vertical (ov) + * - inner horizontal (ih) + * - inner vertical (iv) + * + * Each value is represented as one byte with the uppermost + * bit of each byte indicating whether or not to keep the + * current value. + * + * Example: + * + * 10000000 10000000 00001111 00001111 + * | | | | + * + keep oh + keep ov + ih 15px + iv 15px + * + * This gives an int of: + * 10000000100000000000111100001111 = 2155876111 + * + * Thus this command should set inner gaps to 15: + * xsetroot -name "fsignal:setgaps i 2155876111" + */ +static void +setgapsex(const Arg *arg) +{ + int oh = selmon->gappoh; + int ov = selmon->gappov; + int ih = selmon->gappih; + int iv = selmon->gappiv; + + if (!(arg->i & (1 << 31))) + oh = (arg->i & 0x7f000000) >> 24; + if (!(arg->i & (1 << 23))) + ov = (arg->i & 0x7f0000) >> 16; + if (!(arg->i & (1 << 15))) + ih = (arg->i & 0x7f00) >> 8; + if (!(arg->i & (1 << 7))) + iv = (arg->i & 0x7f); + + /* Auto enable gaps if disabled */ + if (!enablegaps) + enablegaps = 1; + + setgaps(oh, ov, ih, iv); +} + +static void +togglegaps(const Arg *arg) +{ + enablegaps = !enablegaps; + + arrange(NULL); +} + +static void +defaultgaps(const Arg *arg) +{ + setgaps(gappoh, gappov, gappih, gappiv); +} + +static void +incrgaps(const Arg *arg) +{ + setgaps( + selmon->gappoh + arg->i, + selmon->gappov + arg->i, + selmon->gappih + arg->i, + selmon->gappiv + arg->i + ); +} + +static void +incrigaps(const Arg *arg) +{ + setgaps( + selmon->gappoh, + selmon->gappov, + selmon->gappih + arg->i, + selmon->gappiv + arg->i + ); +} + +static void +incrogaps(const Arg *arg) +{ + setgaps( + selmon->gappoh + arg->i, + selmon->gappov + arg->i, + selmon->gappih, + selmon->gappiv + ); +} + +static void +incrohgaps(const Arg *arg) +{ + setgaps( + selmon->gappoh + arg->i, + selmon->gappov, + selmon->gappih, + selmon->gappiv + ); +} + +static void +incrovgaps(const Arg *arg) +{ + setgaps( + selmon->gappoh, + selmon->gappov + arg->i, + selmon->gappih, + selmon->gappiv + ); +} + +static void +incrihgaps(const Arg *arg) +{ + setgaps( + selmon->gappoh, + selmon->gappov, + selmon->gappih + arg->i, + selmon->gappiv + ); +} + +static void +incrivgaps(const Arg *arg) +{ + setgaps( + selmon->gappoh, + selmon->gappov, + selmon->gappih, + selmon->gappiv + arg->i + ); +} + +static void +getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc) +{ + unsigned int n, oe, ie; + oe = ie = enablegaps; + Client *c; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + if (n == 1) { + oe *= smartgaps_fact; // outer gaps disabled or multiplied when only one client + } + + *oh = m->gappoh*oe; // outer horizontal gap + *ov = m->gappov*oe; // outer vertical gap + *ih = m->gappih*ie; // inner horizontal gap + *iv = m->gappiv*ie; // inner vertical gap + *nc = n; // number of clients +} + diff --git a/dwm/patch/vanitygaps.h b/dwm/patch/vanitygaps.h new file mode 100644 index 0000000..8a3ed0b --- /dev/null +++ b/dwm/patch/vanitygaps.h @@ -0,0 +1,16 @@ +/* Key binding functions */ +static void defaultgaps(const Arg *arg); +static void incrgaps(const Arg *arg); +static void incrigaps(const Arg *arg); +static void incrogaps(const Arg *arg); +static void incrohgaps(const Arg *arg); +static void incrovgaps(const Arg *arg); +static void incrihgaps(const Arg *arg); +static void incrivgaps(const Arg *arg); +static void togglegaps(const Arg *arg); + +/* Internals */ +static void getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc); +static void setgaps(int oh, int ov, int ih, int iv); +static void setgapsex(const Arg *arg); + diff --git a/dwm/patch/xrdb.c b/dwm/patch/xrdb.c new file mode 100644 index 0000000..f450023 --- /dev/null +++ b/dwm/patch/xrdb.c @@ -0,0 +1,73 @@ +void +loadxrdb() +{ + Display *display; + char * resm; + XrmDatabase xrdb; + char *type; + XrmValue value; + + display = XOpenDisplay(NULL); + + if (display != NULL) { + resm = XResourceManagerString(display); + + if (resm != NULL) { + xrdb = XrmGetStringDatabase(resm); + + if (xrdb != NULL) { + XRDB_LOAD_COLOR("dwm.normfgcolor", normfgcolor); + XRDB_LOAD_COLOR("dwm.normbgcolor", normbgcolor); + XRDB_LOAD_COLOR("dwm.normbordercolor", normbordercolor); + XRDB_LOAD_COLOR("dwm.normfloatcolor", normfloatcolor); + XRDB_LOAD_COLOR("dwm.selfgcolor", selfgcolor); + XRDB_LOAD_COLOR("dwm.selbgcolor", selbgcolor); + XRDB_LOAD_COLOR("dwm.selbordercolor", selbordercolor); + XRDB_LOAD_COLOR("dwm.selfloatcolor", selfloatcolor); + XRDB_LOAD_COLOR("dwm.titlenormfgcolor", titlenormfgcolor); + XRDB_LOAD_COLOR("dwm.titlenormbgcolor", titlenormbgcolor); + XRDB_LOAD_COLOR("dwm.titlenormbordercolor", titlenormbordercolor); + XRDB_LOAD_COLOR("dwm.titlenormfloatcolor", titlenormfloatcolor); + XRDB_LOAD_COLOR("dwm.titleselfgcolor", titleselfgcolor); + XRDB_LOAD_COLOR("dwm.titleselbgcolor", titleselbgcolor); + XRDB_LOAD_COLOR("dwm.titleselbordercolor", titleselbordercolor); + XRDB_LOAD_COLOR("dwm.titleselfloatcolor", titleselfloatcolor); + XRDB_LOAD_COLOR("dwm.tagsnormfgcolor", tagsnormfgcolor); + XRDB_LOAD_COLOR("dwm.tagsnormbgcolor", tagsnormbgcolor); + XRDB_LOAD_COLOR("dwm.tagsnormbordercolor", tagsnormbordercolor); + XRDB_LOAD_COLOR("dwm.tagsnormfloatcolor", tagsnormfloatcolor); + XRDB_LOAD_COLOR("dwm.tagsselfgcolor", tagsselfgcolor); + XRDB_LOAD_COLOR("dwm.tagsselbgcolor", tagsselbgcolor); + XRDB_LOAD_COLOR("dwm.tagsselbordercolor", tagsselbordercolor); + XRDB_LOAD_COLOR("dwm.tagsselfloatcolor", tagsselfloatcolor); + XRDB_LOAD_COLOR("dwm.hidnormfgcolor", hidnormfgcolor); + XRDB_LOAD_COLOR("dwm.hidnormbgcolor", hidnormbgcolor); + XRDB_LOAD_COLOR("dwm.hidselfgcolor", hidselfgcolor); + XRDB_LOAD_COLOR("dwm.hidselbgcolor", hidselbgcolor); + XRDB_LOAD_COLOR("dwm.urgfgcolor", urgfgcolor); + XRDB_LOAD_COLOR("dwm.urgbgcolor", urgbgcolor); + XRDB_LOAD_COLOR("dwm.urgbordercolor", urgbordercolor); + XRDB_LOAD_COLOR("dwm.urgfloatcolor", urgfloatcolor); + + XrmDestroyDatabase(xrdb); + } + } + } + + XCloseDisplay(display); +} + +void +xrdb(const Arg *arg) +{ + loadxrdb(); + int i; + for (i = 0; i < LENGTH(colors); i++) + scheme[i] = drw_scm_create(drw, colors[i], + alphas[i], + ColCount + ); + focus(NULL); + arrange(NULL); +} + diff --git a/dwm/patch/xrdb.h b/dwm/patch/xrdb.h new file mode 100644 index 0000000..3787bec --- /dev/null +++ b/dwm/patch/xrdb.h @@ -0,0 +1,22 @@ +#include + +#define XRDB_LOAD_COLOR(R,V) if (XrmGetResource(xrdb, R, NULL, &type, &value) == True) { \ + if (value.addr != NULL && strnlen(value.addr, 8) == 7 && value.addr[0] == '#') { \ + int i = 1; \ + for (; i <= 6; i++) { \ + if (value.addr[i] < 48) break; \ + if (value.addr[i] > 57 && value.addr[i] < 65) break; \ + if (value.addr[i] > 70 && value.addr[i] < 97) break; \ + if (value.addr[i] > 102) break; \ + } \ + if (i == 7) { \ + strncpy(V, value.addr, 7); \ + V[7] = '\0'; \ + } \ + } \ + } + +static void loadxrdb(void); +static void xrdb(const Arg *arg); + + diff --git a/dwm/readme.dwm.txt b/dwm/readme.dwm.txt new file mode 100644 index 0000000..95d4fd0 --- /dev/null +++ b/dwm/readme.dwm.txt @@ -0,0 +1,48 @@ +dwm - dynamic window manager +============================ +dwm is an extremely fast, small, and dynamic window manager for X. + + +Requirements +------------ +In order to build dwm you need the Xlib header files. + + +Installation +------------ +Edit config.mk to match your local setup (dwm is installed into +the /usr/local namespace by default). + +Afterwards enter the following command to build and install dwm (if +necessary as root): + + make clean install + + +Running dwm +----------- +Add the following line to your .xinitrc to start dwm using startx: + + exec dwm + +In order to connect dwm to a specific display, make sure that +the DISPLAY environment variable is set correctly, e.g.: + + DISPLAY=foo.bar:1 exec dwm + +(This will start dwm on display :1 of the host foo.bar.) + +In order to display status info in the bar, you can do something +like this in your .xinitrc: + + while xsetroot -name "`date` `uptime | sed 's/.*,//'`" + do + sleep 1 + done & + exec dwm + + +Configuration +------------- +The configuration of dwm is done by creating a custom config.h +and (re)compiling the source code. diff --git a/dwm/transient.c b/dwm/transient.c new file mode 100644 index 0000000..158460f --- /dev/null +++ b/dwm/transient.c @@ -0,0 +1,43 @@ +/* cc transient.c -o transient -lX11 */ + +#include +#include +#include +#include + +int main(void) { + Display *d; + Window r, f, t = None; + XSizeHints h; + XEvent e; + + d = XOpenDisplay(NULL); + if (!d) + exit(1); + r = DefaultRootWindow(d); + + f = XCreateSimpleWindow(d, r, 100, 100, 400, 400, 0, 0, 0); + h.min_width = h.max_width = h.min_height = h.max_height = 400; + h.flags = PMinSize | PMaxSize; + XSetWMNormalHints(d, f, &h); + XStoreName(d, f, "floating"); + XMapWindow(d, f); + + XSelectInput(d, f, ExposureMask); + while (1) { + XNextEvent(d, &e); + + if (t == None) { + sleep(5); + t = XCreateSimpleWindow(d, r, 50, 50, 100, 100, 0, 0, 0); + XSetTransientForHint(d, t, f); + XStoreName(d, t, "transient"); + XMapWindow(d, t); + XSelectInput(d, t, ExposureMask); + } + } + + XCloseDisplay(d); + exit(0); +} + diff --git a/dwm/util.c b/dwm/util.c new file mode 100644 index 0000000..bcecb12 --- /dev/null +++ b/dwm/util.c @@ -0,0 +1,36 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include + +#include "util.h" + +void * +ecalloc(size_t nmemb, size_t size) +{ + void *p; + + if (!(p = calloc(nmemb, size))) + die("calloc:"); + return p; +} + +void +die(const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + if (fmt[0] && fmt[strlen(fmt)-1] == ':') { + fputc(' ', stderr); + perror(NULL); + } else { + fputc('\n', stderr); + } + + exit(1); +} + diff --git a/dwm/util.h b/dwm/util.h new file mode 100644 index 0000000..1e3cf9a --- /dev/null +++ b/dwm/util.h @@ -0,0 +1,19 @@ +/* See LICENSE file for copyright and license details. */ + +#ifndef MAX +#define MAX(A, B) ((A) > (B) ? (A) : (B)) +#endif +#ifndef MIN +#define MIN(A, B) ((A) < (B) ? (A) : (B)) +#endif +#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) + +#ifdef _DEBUG +#define DEBUG(...) fprintf(stderr, __VA_ARGS__) +#else +#define DEBUG(...) +#endif + +void die(const char *fmt, ...); +void *ecalloc(size_t nmemb, size_t size); + diff --git a/dwm/util.o b/dwm/util.o new file mode 100644 index 0000000000000000000000000000000000000000..c40fa4261e0053f7c2d769fbd8163175c25f4cc2 GIT binary patch literal 2272 zcmbtUO-vI}5S|5;ia@J!z~IjwR;3AUsA57uO$|j>(-{1VKbKOZKi8S%x!HY-ZMZB5l0i!21;>_Fk;APV$MkjflnQy+CoxV5k-5QJ^ zuhTS;qQOyE_aq81vSHnhax)68&;s9ryMCOtNm^Ih1rxOhe z3wA~-FR4YV95+H%>Ah8+HCD)6q~Iw?}7uDU!{_n zjFajE7#bMp(>sUk9CI8!(qkSpyY+l;SeO6}ST2N%wt48(d8h-Z5LSS3tWa*5V0y93)4P$8=3T(`FT}ULZjpyBTj*TZ$6O)L#89N8#`65d}9tn;M z_EegI?M)Co!1^RO7kmbOt$OmDquzXML|fvE0{8RZDEvl+|53r|jAR`?$LQ1i(QHZl zJK7|KtNh;_^>Df@k{_T!K_PxKE{V4Zocg3$m-u#tPdO6T(Iz22Eh&eEA#r&=U>2sc zEIEprxt^YomTPB{CbOp)m}5zn1aq`d0Mm8IA$r7&fSGc#S-iDi<{W05cs2JISTZ#! z{42SlnRgvLF*c2L-(1nU>{%d{&bLmqDaH%4{FZ-1-*_PB% z43JIlzbaP*L03VvWuDY06ilVwlLQs4!o7qT-7|GoDdoP%A0|f;|Nps)F{1kO-~DBN z26L;O{{n$1a$o5D>3+-a)B8$N?c0QRiiUbcA9Sawq(7f(`p+IA7!jaFjv}Jm8ba@X Qwftq#|BW@KXZZ8~0E+|^6951J literal 0 HcmV?d00001 diff --git a/suckless/slstatus/LICENSE b/slstatus/LICENSE similarity index 100% rename from suckless/slstatus/LICENSE rename to slstatus/LICENSE diff --git a/suckless/slstatus/Makefile b/slstatus/Makefile similarity index 100% rename from suckless/slstatus/Makefile rename to slstatus/Makefile diff --git a/suckless/slstatus/arg.h b/slstatus/arg.h similarity index 100% rename from suckless/slstatus/arg.h rename to slstatus/arg.h diff --git a/suckless/slstatus/components/battery.c b/slstatus/components/battery.c similarity index 100% rename from suckless/slstatus/components/battery.c rename to slstatus/components/battery.c diff --git a/suckless/slstatus/components/battery.o b/slstatus/components/battery.o similarity index 100% rename from suckless/slstatus/components/battery.o rename to slstatus/components/battery.o diff --git a/suckless/slstatus/components/cat.c b/slstatus/components/cat.c similarity index 100% rename from suckless/slstatus/components/cat.c rename to slstatus/components/cat.c diff --git a/suckless/slstatus/components/cat.o b/slstatus/components/cat.o similarity index 100% rename from suckless/slstatus/components/cat.o rename to slstatus/components/cat.o diff --git a/suckless/slstatus/components/cpu.c b/slstatus/components/cpu.c similarity index 100% rename from suckless/slstatus/components/cpu.c rename to slstatus/components/cpu.c diff --git a/suckless/slstatus/components/cpu.o b/slstatus/components/cpu.o similarity index 100% rename from suckless/slstatus/components/cpu.o rename to slstatus/components/cpu.o diff --git a/suckless/slstatus/components/datetime.c b/slstatus/components/datetime.c similarity index 100% rename from suckless/slstatus/components/datetime.c rename to slstatus/components/datetime.c diff --git a/suckless/slstatus/components/datetime.o b/slstatus/components/datetime.o similarity index 100% rename from suckless/slstatus/components/datetime.o rename to slstatus/components/datetime.o diff --git a/suckless/slstatus/components/disk.c b/slstatus/components/disk.c similarity index 100% rename from suckless/slstatus/components/disk.c rename to slstatus/components/disk.c diff --git a/suckless/slstatus/components/disk.o b/slstatus/components/disk.o similarity index 100% rename from suckless/slstatus/components/disk.o rename to slstatus/components/disk.o diff --git a/suckless/slstatus/components/entropy.c b/slstatus/components/entropy.c similarity index 100% rename from suckless/slstatus/components/entropy.c rename to slstatus/components/entropy.c diff --git a/suckless/slstatus/components/entropy.o b/slstatus/components/entropy.o similarity index 100% rename from suckless/slstatus/components/entropy.o rename to slstatus/components/entropy.o diff --git a/suckless/slstatus/components/hostname.c b/slstatus/components/hostname.c similarity index 100% rename from suckless/slstatus/components/hostname.c rename to slstatus/components/hostname.c diff --git a/suckless/slstatus/components/hostname.o b/slstatus/components/hostname.o similarity index 100% rename from suckless/slstatus/components/hostname.o rename to slstatus/components/hostname.o diff --git a/suckless/slstatus/components/ip.c b/slstatus/components/ip.c similarity index 100% rename from suckless/slstatus/components/ip.c rename to slstatus/components/ip.c diff --git a/suckless/slstatus/components/ip.o b/slstatus/components/ip.o similarity index 100% rename from suckless/slstatus/components/ip.o rename to slstatus/components/ip.o diff --git a/suckless/slstatus/components/kernel_release.c b/slstatus/components/kernel_release.c similarity index 100% rename from suckless/slstatus/components/kernel_release.c rename to slstatus/components/kernel_release.c diff --git a/suckless/slstatus/components/kernel_release.o b/slstatus/components/kernel_release.o similarity index 100% rename from suckless/slstatus/components/kernel_release.o rename to slstatus/components/kernel_release.o diff --git a/suckless/slstatus/components/keyboard_indicators.c b/slstatus/components/keyboard_indicators.c similarity index 100% rename from suckless/slstatus/components/keyboard_indicators.c rename to slstatus/components/keyboard_indicators.c diff --git a/suckless/slstatus/components/keyboard_indicators.o b/slstatus/components/keyboard_indicators.o similarity index 100% rename from suckless/slstatus/components/keyboard_indicators.o rename to slstatus/components/keyboard_indicators.o diff --git a/suckless/slstatus/components/keymap.c b/slstatus/components/keymap.c similarity index 100% rename from suckless/slstatus/components/keymap.c rename to slstatus/components/keymap.c diff --git a/suckless/slstatus/components/keymap.o b/slstatus/components/keymap.o similarity index 100% rename from suckless/slstatus/components/keymap.o rename to slstatus/components/keymap.o diff --git a/suckless/slstatus/components/load_avg.c b/slstatus/components/load_avg.c similarity index 100% rename from suckless/slstatus/components/load_avg.c rename to slstatus/components/load_avg.c diff --git a/suckless/slstatus/components/load_avg.o b/slstatus/components/load_avg.o similarity index 100% rename from suckless/slstatus/components/load_avg.o rename to slstatus/components/load_avg.o diff --git a/suckless/slstatus/components/netspeeds.c b/slstatus/components/netspeeds.c similarity index 100% rename from suckless/slstatus/components/netspeeds.c rename to slstatus/components/netspeeds.c diff --git a/suckless/slstatus/components/netspeeds.o b/slstatus/components/netspeeds.o similarity index 100% rename from suckless/slstatus/components/netspeeds.o rename to slstatus/components/netspeeds.o diff --git a/suckless/slstatus/components/num_files.c b/slstatus/components/num_files.c similarity index 100% rename from suckless/slstatus/components/num_files.c rename to slstatus/components/num_files.c diff --git a/suckless/slstatus/components/num_files.o b/slstatus/components/num_files.o similarity index 100% rename from suckless/slstatus/components/num_files.o rename to slstatus/components/num_files.o diff --git a/suckless/slstatus/components/pixVol.sh b/slstatus/components/pixVol.sh similarity index 100% rename from suckless/slstatus/components/pixVol.sh rename to slstatus/components/pixVol.sh diff --git a/suckless/slstatus/components/ram.c b/slstatus/components/ram.c similarity index 100% rename from suckless/slstatus/components/ram.c rename to slstatus/components/ram.c diff --git a/suckless/slstatus/components/ram.o b/slstatus/components/ram.o similarity index 100% rename from suckless/slstatus/components/ram.o rename to slstatus/components/ram.o diff --git a/suckless/slstatus/components/run_command.c b/slstatus/components/run_command.c similarity index 100% rename from suckless/slstatus/components/run_command.c rename to slstatus/components/run_command.c diff --git a/suckless/slstatus/components/run_command.o b/slstatus/components/run_command.o similarity index 100% rename from suckless/slstatus/components/run_command.o rename to slstatus/components/run_command.o diff --git a/suckless/slstatus/components/swap.c b/slstatus/components/swap.c similarity index 100% rename from suckless/slstatus/components/swap.c rename to slstatus/components/swap.c diff --git a/suckless/slstatus/components/swap.o b/slstatus/components/swap.o similarity index 100% rename from suckless/slstatus/components/swap.o rename to slstatus/components/swap.o diff --git a/suckless/slstatus/components/temperature.c b/slstatus/components/temperature.c similarity index 100% rename from suckless/slstatus/components/temperature.c rename to slstatus/components/temperature.c diff --git a/suckless/slstatus/components/temperature.o b/slstatus/components/temperature.o similarity index 100% rename from suckless/slstatus/components/temperature.o rename to slstatus/components/temperature.o diff --git a/suckless/slstatus/components/uptime.c b/slstatus/components/uptime.c similarity index 100% rename from suckless/slstatus/components/uptime.c rename to slstatus/components/uptime.c diff --git a/suckless/slstatus/components/uptime.o b/slstatus/components/uptime.o similarity index 100% rename from suckless/slstatus/components/uptime.o rename to slstatus/components/uptime.o diff --git a/suckless/slstatus/components/user.c b/slstatus/components/user.c similarity index 100% rename from suckless/slstatus/components/user.c rename to slstatus/components/user.c diff --git a/suckless/slstatus/components/user.o b/slstatus/components/user.o similarity index 100% rename from suckless/slstatus/components/user.o rename to slstatus/components/user.o diff --git a/suckless/slstatus/components/volume.c b/slstatus/components/volume.c similarity index 100% rename from suckless/slstatus/components/volume.c rename to slstatus/components/volume.c diff --git a/suckless/slstatus/components/volume.o b/slstatus/components/volume.o similarity index 100% rename from suckless/slstatus/components/volume.o rename to slstatus/components/volume.o diff --git a/suckless/slstatus/components/wifi.c b/slstatus/components/wifi.c similarity index 100% rename from suckless/slstatus/components/wifi.c rename to slstatus/components/wifi.c diff --git a/suckless/slstatus/components/wifi.o b/slstatus/components/wifi.o similarity index 100% rename from suckless/slstatus/components/wifi.o rename to slstatus/components/wifi.o diff --git a/suckless/slstatus/config.def.h b/slstatus/config.def.h similarity index 100% rename from suckless/slstatus/config.def.h rename to slstatus/config.def.h diff --git a/suckless/slstatus/config.h b/slstatus/config.h similarity index 93% rename from suckless/slstatus/config.h rename to slstatus/config.h index 7049fc6..4eb21be 100644 --- a/suckless/slstatus/config.h +++ b/slstatus/config.h @@ -66,9 +66,9 @@ static const char unknown_str[] = "n/a"; */ static const struct arg args[] = { /* function format argument */ - {run_command, "[%s%] ", "pamixer --get-volume"}, - {temp, "[%s°C] ", "/sys/class/thermal/thermal_zone3/temp"}, - {run_command, "[%s]", "sb-memory"}, - {run_command, " %s ", "bat-symbol"}, - {run_command, "[%s]", "date '+%a %d %b %I:%M %P'"}, + {run_command, "[vol %s%] ", "pamixer --get-volume"}, + {temp, "[tmp %s°C] ", "/sys/class/thermal/thermal_zone3/temp"}, + {run_command, "[mem %s]", "sb-memory"}, + {run_command, " [bat %s] ", "sb-battery"}, + {run_command, "[%s]", "date '+%a %I:%M %P'"}, }; diff --git a/suckless/slstatus/config.h~ b/slstatus/config.h~ similarity index 100% rename from suckless/slstatus/config.h~ rename to slstatus/config.h~ diff --git a/suckless/slstatus/config.mk b/slstatus/config.mk similarity index 100% rename from suckless/slstatus/config.mk rename to slstatus/config.mk diff --git a/suckless/slstatus/slstatus b/slstatus/slstatus similarity index 84% rename from suckless/slstatus/slstatus rename to slstatus/slstatus index 07fe4df9cf5deb7ae0f9f14948e32f45f3ec40a6..31508c2c34021505656a54ca7e3ab061d603c770 100755 GIT binary patch delta 1502 zcmZwHaZHqD90%~{cV5DYTz5k|PGomQjtJSEDNq{)R1PW#Y}&~k2lt-Qpdt|nFidc1 zG-H`l0xjPVb?+!m<+0apg z#8NFEwYcnUp76!|=CILW)N%gK;-WK5RvVpVyVYgC7|Co}kvYVg)kPEBfz0Vpr}go8 zdL(o`#Yd*T%}U+6+Y)<`i&Hb{Na*dm{pl=0|88;lKmUvYA!XQQ#cy2injlT=}9kW^%c(K)J+SKt>ge@bKkPQiuMElNH8i^$q2rG}sz?wiI9Fy@-bXHbI|;0TzUQ6+}!mgo4jT2oQNe-w>s<4>d~eV zcj8?x9ox`3hStf4yqPr1-Ch@Yc*dJeQ=H<9bKOcl%t_!!tey+1XT@ zL_to&c`fh2c^AKi^GE!Cse>lDyVPO$W0)_OKDYkk%Od8;eEKp9@a<1=uHQx5OtcV;uUS^{j{hb+-Hu~*AS1-ev@MZw!}0P$%{)@ z{bqa>r8c4!Afu6U0}lFzwLr3cCyFRRzqs9ODMXr{a~e4wK8c(r{yJczW*!b?QzhHA zJQ`q4bI}{zp(WFo+^r=fmZF*-)1Q!Qw!CRLusBsbhI$1Z-zk VV`l8~j=Tp+tQq4%y^Y0&e*qb==HvhX delta 1487 zcmZwHZA_b06bJBox^9#qwUy1%0cj_a4jF0HZIuKBoKuV}fL{uQLfZiw3L9_o;u~9t zvSqkHjz+(jjQGJUnUSp;+=pfL!(OUrhH)<2d|_@AHa3OHmd&^w{|_yg5TE4U-+j(= zp66b;r*~kM24-ovfa05z)ZEp~FHoOZZHeA3$QQ|BE{#POWUJ2cKe=Uy+RLL~STM9l zCyBJ3_n4g4UQhI4(d$tSvDx~0%;coQOlAv>u+{9eeih5?T9kQ$172uQXGBE9l6KoQfNco6RWt<*n3fAKdieXG7Zl{!!o5lxGeG% z^js0y2LFU#!t&omPQ%-9c3F>7-U*Qh;*^?%F1TwFFTj**BA>$+I0~oWWmq^R@(=t3 zCZi-Cx{it9DD=Y#*ag?z5cv>pgu}4;4=fPcr;#78)IGQ@7lZm4{Ke3IQ{*75hNocM zUziY%K!vRsm=$>x?!6`QtR~;8$f5#X?X}Py&ha`PS6_>mVnwR40<9hGPDI3x|K;!OowSwjdh_Wv=Tzp?G48H(lbsJ$TBwmDl};MvyOlP|WNTGAwQ?T% zR1To8x9}WAkatD8}B8aGB3SpK^oGM#6i1C3Jz$ z`AV!!D1lZjx5((yH5d)}X{cN*_aqlqJITW>=qGrnx`doOQ*EK09AA@8e{*(?g`VS0 z7!PwpjhoCoRP!R$@QoUa^`qZJUYq}Bi_xI1AsO2)oaVQr<)KLG=b!qF*cGKx(Tb7L z$7OySea|g^hqV?(l%hS{WHfC?nwE1AIa~PJd zz(L<}B#@HUh-!LT`$D17)T?`AZmMM5Y8AAPDVRbjoQD20&IzVdE&GBt%I7zOPp(Qp z9cio9t|GKBRylfH6+9ltVV#MGU)~wm9y@#t+Bt zM;68BU;`8}qp}|*d30g&TIO7-2O1|3RUOrtB{q%GNKi0V+{=cKRq0^nXa0G8b N5(o52p>SuZ?q5g7;RXNz diff --git a/suckless/slstatus/slstatus.1 b/slstatus/slstatus.1 similarity index 100% rename from suckless/slstatus/slstatus.1 rename to slstatus/slstatus.1 diff --git a/suckless/slstatus/slstatus.c b/slstatus/slstatus.c similarity index 100% rename from suckless/slstatus/slstatus.c rename to slstatus/slstatus.c diff --git a/suckless/slstatus/slstatus.h b/slstatus/slstatus.h similarity index 100% rename from suckless/slstatus/slstatus.h rename to slstatus/slstatus.h diff --git a/suckless/slstatus/slstatus.o b/slstatus/slstatus.o similarity index 55% rename from suckless/slstatus/slstatus.o rename to slstatus/slstatus.o index 9243c5bea233361adf74de65449abb9db8360fc1..222ed6c0b7f878afff51099182b713fd3f3328e0 100644 GIT binary patch delta 303 zcmX?Lc)@Uj2IGZ^nh#jY@^cg>b27@Xl;jpDOjc#oH_J`URZuOCWhhS41v2xCDj5`_ zlM+inVhSKZAiE?LC>jk?l#*DIs-Ui|nz*@<(T`>G1=a`LjJqdq6x3(DF!`aNIOE;P zKLzzAnHd?tzyU%rfVgZx%rn_hNS{$`a-onoqvGUFA$>_5sLBE~m4=%y3bivbYD|t4 zInL-hSy9xSaqi?uQF}&*$uogu#^jqovSG5Mm_6fz$&q6AtS?xBCQKIO6rQ|6OoQ>q ztsa{ Fc>r=mOzHpt delta 284 zcmca$c))Oi2IGN=nhz%PGRjQWWz^SIEskX 0: keypad application mode enabled - * * = 2: term.numlock = 1 - * * < 0: keypad application mode disabled - * appcursor value: - * * 0: no value - * * > 0: cursor application mode enabled - * * < 0: cursor application mode disabled - * - * Be careful with the order of the definitions because st searches in - * this table sequentially, so any XK_ANY_MOD must be in the last - * position for a key. - */ -/* - * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) - * to be mapped below, add them to this array. - */ static KeySym mappedkeys[] = { -1 }; -/* - * State bits to ignore when matching key or button events. By default, - * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. - */ static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; -/* - * This is the huge key array which defines all compatibility to the Linux - * world. Please decide about changes wisely. - */ + static Key key[] = { /* keysym mask string appkey appcursor */ { XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, diff --git a/suckless/st/config.h.save b/st/config.h.save similarity index 100% rename from suckless/st/config.h.save rename to st/config.h.save diff --git a/suckless/st/config.h.save.1 b/st/config.h.save.1 similarity index 100% rename from suckless/st/config.h.save.1 rename to st/config.h.save.1 diff --git a/suckless/st/config.h.save.2 b/st/config.h.save.2 similarity index 100% rename from suckless/st/config.h.save.2 rename to st/config.h.save.2 diff --git a/suckless/st/config.h.save.3 b/st/config.h.save.3 similarity index 100% rename from suckless/st/config.h.save.3 rename to st/config.h.save.3 diff --git a/suckless/st/config.h~ b/st/config.h~ similarity index 100% rename from suckless/st/config.h~ rename to st/config.h~ diff --git a/suckless/st/config.mk b/st/config.mk similarity index 100% rename from suckless/st/config.mk rename to st/config.mk diff --git a/suckless/st/graphics.c b/st/graphics.c similarity index 100% rename from suckless/st/graphics.c rename to st/graphics.c diff --git a/suckless/st/graphics.h b/st/graphics.h similarity index 100% rename from suckless/st/graphics.h rename to st/graphics.h diff --git a/suckless/st/hb.c b/st/hb.c similarity index 100% rename from suckless/st/hb.c rename to st/hb.c diff --git a/suckless/st/hb.h b/st/hb.h similarity index 100% rename from suckless/st/hb.h rename to st/hb.h diff --git a/suckless/st/hb.o b/st/hb.o similarity index 100% rename from suckless/st/hb.o rename to st/hb.o diff --git a/suckless/st/icat-mini.sh b/st/icat-mini.sh similarity index 100% rename from suckless/st/icat-mini.sh rename to st/icat-mini.sh diff --git a/suckless/st/khash.h b/st/khash.h similarity index 100% rename from suckless/st/khash.h rename to st/khash.h diff --git a/suckless/st/kvec.h b/st/kvec.h similarity index 100% rename from suckless/st/kvec.h rename to st/kvec.h diff --git a/suckless/st/rowcolumn_diacritics_helpers.c b/st/rowcolumn_diacritics_helpers.c similarity index 100% rename from suckless/st/rowcolumn_diacritics_helpers.c rename to st/rowcolumn_diacritics_helpers.c diff --git a/suckless/st/st b/st/st similarity index 74% rename from suckless/st/st rename to st/st index 78ff9259c8c19d10fd283c8a83feb8c18baa8a95..87645c97d3bd7106dac288a2ee6d265a351e2dd7 100755 GIT binary patch delta 7561 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 diff --git a/suckless/st/st-alpha-changealpha-20230519-b44f2ad.diff b/st/st-alpha-changealpha-20230519-b44f2ad.diff similarity index 100% rename from suckless/st/st-alpha-changealpha-20230519-b44f2ad.diff rename to st/st-alpha-changealpha-20230519-b44f2ad.diff diff --git a/suckless/st/st.1 b/st/st.1 similarity index 100% rename from suckless/st/st.1 rename to st/st.1 diff --git a/suckless/st/st.c b/st/st.c similarity index 100% rename from suckless/st/st.c rename to st/st.c diff --git a/suckless/st/st.h b/st/st.h similarity index 100% rename from suckless/st/st.h rename to st/st.h diff --git a/suckless/st/st.info b/st/st.info similarity index 100% rename from suckless/st/st.info rename to st/st.info diff --git a/suckless/st/st.o b/st/st.o similarity index 100% rename from suckless/st/st.o rename to st/st.o diff --git a/suckless/st/win.h b/st/win.h similarity index 100% rename from suckless/st/win.h rename to st/win.h diff --git a/suckless/st/x.c b/st/x.c similarity index 100% rename from suckless/st/x.c rename to st/x.c diff --git a/suckless/st/x.o b/st/x.o similarity index 89% rename from suckless/st/x.o rename to st/x.o index f6cae319e2040082c75de4e8fe6ba1749e14e070..32271eb3b42bd5a832fea294b1ca1191c56453a4 100644 GIT binary patch delta 192 zcmWm6uL{CY7zJ=YVZz0-BzpsAv$>>EuHf9CI1FNyZJ@y@8f0x~IBzhFlNBGq8*N4( zVYW5BU;1$lhf^0uQy95TkNW^oSH|lk-X@#XZdIvhN*BLVnM8z$63mxY13Z_?X`1Di^l{zxsHSqN9we^das)1DXvn8|2P^RN~kRH5NQ H9b)tYW=uSY diff --git a/suckless/dwm b/suckless/dwm deleted file mode 160000 index 5d20660..0000000 --- a/suckless/dwm +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5d206603f6d85a849a830b088e3d771e8da908fb