sites

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 556f2aae56b5862dbd1194abd184b39d55b667ed
parent 0ad093d1523cb7cd5d5761fd0602e48e3b4b5640
Author: Laslo Hunhold <dev@frign.de>
Date:   Sun,  5 Nov 2017 01:45:15 +0100

Tidy up dwm patch section into subdirectories

Diffstat:
Rdwm.suckless.org/patches/dwm-alpha-6.1.diff -> dwm.suckless.org/patches/alpha/dwm-alpha-6.1.diff | 0
Rdwm.suckless.org/patches/dwm-alpha.png -> dwm.suckless.org/patches/alpha/dwm-alpha.png | 0
Rdwm.suckless.org/patches/alpha.md -> dwm.suckless.org/patches/alpha/index.md | 0
Rdwm.suckless.org/patches/dwm-alwaysfullscreen-20160713-56a31dc.diff -> dwm.suckless.org/patches/alwaysfullscreen/dwm-alwaysfullscreen-20160713-56a31dc.diff | 0
Rdwm.suckless.org/patches/dwm-alwaysfullscreen-6.1.diff -> dwm.suckless.org/patches/alwaysfullscreen/dwm-alwaysfullscreen-6.1.diff | 0
Rdwm.suckless.org/patches/alwaysfullscreen.md -> dwm.suckless.org/patches/alwaysfullscreen/index.md | 0
Rdwm.suckless.org/patches/dwm-attachabove-20160713-56a31dc.diff -> dwm.suckless.org/patches/attachabove/dwm-attachabove-20160713-56a31dc.diff | 0
Rdwm.suckless.org/patches/dwm-attachabove-6.0.diff -> dwm.suckless.org/patches/attachabove/dwm-attachabove-6.0.diff | 0
Rdwm.suckless.org/patches/dwm-attachabove-6.1.diff -> dwm.suckless.org/patches/attachabove/dwm-attachabove-6.1.diff | 0
Rdwm.suckless.org/patches/attachabove.md -> dwm.suckless.org/patches/attachabove/index.md | 0
Rdwm.suckless.org/patches/dwm-attachaside-20160718-56a31dc.diff -> dwm.suckless.org/patches/attachaside/dwm-attachaside-20160718-56a31dc.diff | 0
Rdwm.suckless.org/patches/dwm-attachaside-6.1.diff -> dwm.suckless.org/patches/attachaside/dwm-attachaside-6.1.diff | 0
Rdwm.suckless.org/patches/attachaside.md -> dwm.suckless.org/patches/attachaside/index.md | 0
Rdwm.suckless.org/patches/dwm-autoresize-20160718-56a31dc.diff -> dwm.suckless.org/patches/autoresize/dwm-autoresize-20160718-56a31dc.diff | 0
Rdwm.suckless.org/patches/dwm-autoresize-6.0.diff -> dwm.suckless.org/patches/autoresize/dwm-autoresize-6.0.diff | 0
Rdwm.suckless.org/patches/dwm-autoresize-6.1.diff -> dwm.suckless.org/patches/autoresize/dwm-autoresize-6.1.diff | 0
Rdwm.suckless.org/patches/autoresize.md -> dwm.suckless.org/patches/autoresize/index.md | 0
Rdwm.suckless.org/patches/dwm-autostart-20161205-bb3bd6f.diff -> dwm.suckless.org/patches/autostart/dwm-autostart-20161205-bb3bd6f.diff | 0
Rdwm.suckless.org/patches/autostart.md -> dwm.suckless.org/patches/autostart/index.md | 0
Rdwm.suckless.org/patches/dwm-bottomstack-20160719-56a31dc.diff -> dwm.suckless.org/patches/bottomstack/dwm-bottomstack-20160719-56a31dc.diff | 0
Rdwm.suckless.org/patches/dwm-bottomstack-6.1.diff -> dwm.suckless.org/patches/bottomstack/dwm-bottomstack-6.1.diff | 0
Rdwm.suckless.org/patches/bottomstack.md -> dwm.suckless.org/patches/bottomstack/index.md | 0
Rdwm.suckless.org/patches/dwm-center-20160719-56a31dc.diff -> dwm.suckless.org/patches/center/dwm-center-20160719-56a31dc.diff | 0
Rdwm.suckless.org/patches/dwm-center-6.1.diff -> dwm.suckless.org/patches/center/dwm-center-6.1.diff | 0
Rdwm.suckless.org/patches/center.md -> dwm.suckless.org/patches/center/index.md | 0
Rdwm.suckless.org/patches/dwm-centeredmaster-20160719-56a31dc.diff -> dwm.suckless.org/patches/centeredmaster/dwm-centeredmaster-20160719-56a31dc.diff | 0
Rdwm.suckless.org/patches/dwm-centeredmaster-6.1.diff -> dwm.suckless.org/patches/centeredmaster/dwm-centeredmaster-6.1.diff | 0
Rdwm.suckless.org/patches/centeredmaster.md -> dwm.suckless.org/patches/centeredmaster/index.md | 0
Ddwm.suckless.org/patches/cfacts.md | 56--------------------------------------------------------
Rdwm.suckless.org/patches/dwm-6.1-cfacts.diff -> dwm.suckless.org/patches/cfacts/dwm-cfacts-6.1.diff | 0
Adwm.suckless.org/patches/cfacts/index.md | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rdwm.suckless.org/patches/dwm-clientspertag-5.6.1.diff -> dwm.suckless.org/patches/clientspertag/dwm-clientspertag-5.6.1.diff | 0
Rdwm.suckless.org/patches/clientspertag.md -> dwm.suckless.org/patches/clientspertag/index.md | 0
Rdwm.suckless.org/patches/dwm-columns-6.0.diff -> dwm.suckless.org/patches/columns/dwm-columns-6.0.diff | 0
Rdwm.suckless.org/patches/columns.md -> dwm.suckless.org/patches/columns/index.md | 0
Rdwm.suckless.org/patches/dwm-combo-5.9.diff -> dwm.suckless.org/patches/combo/dwm-combo-5.9.diff | 0
Rdwm.suckless.org/patches/dwm-combo-6.0.diff -> dwm.suckless.org/patches/combo/dwm-combo-6.0.diff | 0
Rdwm.suckless.org/patches/dwm-combo-6.1.diff -> dwm.suckless.org/patches/combo/dwm-combo-6.1.diff | 0
Rdwm.suckless.org/patches/combo.md -> dwm.suckless.org/patches/combo/index.md | 0
Rdwm.suckless.org/patches/dwm-cropwindows-20170709-ceac8c9.diff -> dwm.suckless.org/patches/cropwindows/dwm-cropwindows-20170709-ceac8c9.diff | 0
Rdwm.suckless.org/patches/cropwindows.md -> dwm.suckless.org/patches/cropwindows/index.md | 0
Rdwm.suckless.org/patches/dwm-current_desktop-5.8.2.diff -> dwm.suckless.org/patches/current_desktop/dwm-current_desktop-5.8.2.diff | 0
Rdwm.suckless.org/patches/current_desktop.md -> dwm.suckless.org/patches/current_desktop/index.md | 0
Ddwm.suckless.org/patches/deck.md | 40----------------------------------------
Rdwm.suckless.org/patches/dwm-deck-20170909-ceac8c9.diff -> dwm.suckless.org/patches/deck/dwm-deck-20170909-ceac8c9.diff | 0
Rdwm.suckless.org/patches/dwm-6.0-deck.diff -> dwm.suckless.org/patches/deck/dwm-deck-6.0.diff | 0
Adwm.suckless.org/patches/deck/index.md | 40++++++++++++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/defaulttransparency.md | 24------------------------
Rdwm.suckless.org/patches/dwm.defaultopacity.patch -> dwm.suckless.org/patches/defaulttransparency/dwm-defaulttransparency-r1521.diff | 0
Adwm.suckless.org/patches/defaulttransparency/index.md | 24++++++++++++++++++++++++
Rdwm.suckless.org/patches/dwm-dualstatus-6.0.diff -> dwm.suckless.org/patches/dualstatus/dwm-dualstatus-6.0.diff | 0
Rdwm.suckless.org/patches/dwm-dualstatus-6.1.diff -> dwm.suckless.org/patches/dualstatus/dwm-dualstatus-6.1.diff | 0
Rdwm.suckless.org/patches/dwm-dualstatus.png -> dwm.suckless.org/patches/dualstatus/dwm-dualstatus.png | 0
Rdwm.suckless.org/patches/dualstatus.md -> dwm.suckless.org/patches/dualstatus/index.md | 0
Rdwm.suckless.org/patches/dwm-dwmfifo-6.1.diff -> dwm.suckless.org/patches/dwmfifo/dwm-dwmfifo-6.1.diff | 0
Rdwm.suckless.org/patches/dwmfifo.md -> dwm.suckless.org/patches/dwmfifo/index.md | 0
Rdwm.suckless.org/patches/dwm-emptyview-6.0.diff -> dwm.suckless.org/patches/emptyview/dwm-emptyview-6.0.diff | 0
Rdwm.suckless.org/patches/emptyview.md -> dwm.suckless.org/patches/emptyview/index.md | 0
Ddwm.suckless.org/patches/exresize.md | 26--------------------------
Rdwm.suckless.org/patches/dwm-r1606-exresize.diff -> dwm.suckless.org/patches/exresize/dwm-exresize-r1606.diff | 0
Adwm.suckless.org/patches/exresize/index.md | 26++++++++++++++++++++++++++
Rdwm.suckless.org/patches/dwm-fakefullscreen-20170508-ceac8c9.diff -> dwm.suckless.org/patches/fakefullscreen/dwm-fakefullscreen-20170508-ceac8c9.diff | 0
Rdwm.suckless.org/patches/fakefullscreen.md -> dwm.suckless.org/patches/fakefullscreen/index.md | 0
Ddwm.suckless.org/patches/fancybar.md | 26--------------------------
Adwm.suckless.org/patches/fancybar/dwm-fancybar-5.6.1.diff | 121+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rdwm.suckless.org/patches/dwm-fancybar-6.1.diff -> dwm.suckless.org/patches/fancybar/dwm-fancybar-6.1.diff | 0
Rdwm.suckless.org/patches/dwm-fancybar-git-20160725-7af4d43.diff -> dwm.suckless.org/patches/fancybar/dwm-fancybar-git-20160725-7af4d43.diff | 0
Rdwm.suckless.org/patches/dwm-6.1-winview.diff -> dwm.suckless.org/patches/fancybar/fancybar.png | 0
Adwm.suckless.org/patches/fancybar/index.md | 24++++++++++++++++++++++++
Ddwm.suckless.org/patches/fancybarclickable.md | 24------------------------
Rdwm.suckless.org/patches/dwm-6.1-fancybarclickable.diff -> dwm.suckless.org/patches/fancybarclickable/dwm-fancybarclickable-6.1.diff | 0
Adwm.suckless.org/patches/fancybarclickable/fancybarclickable.png | 0
Adwm.suckless.org/patches/fancybarclickable/index.md | 21+++++++++++++++++++++
Ddwm.suckless.org/patches/fancycoloredbarclickable.md | 33---------------------------------
Rdwm.suckless.org/patches/dwm-fibonacci-5.8.2.diff -> dwm.suckless.org/patches/fibonacci/dwm-fibonacci-5.8.2.diff | 0
Rdwm.suckless.org/patches/fibonacci.md -> dwm.suckless.org/patches/fibonacci/index.md | 0
Adwm.suckless.org/patches/flextile/dwm-flextile-5.8.1.diff | 418+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rdwm.suckless.org/patches/dwm-flextile-5.8.2.diff -> dwm.suckless.org/patches/flextile/dwm-flextile-5.8.2.diff | 0
Rdwm.suckless.org/patches/flextile.md -> dwm.suckless.org/patches/flextile/index.md | 0
Rdwm.suckless.org/patches/dwm-float_border_color-6.0.diff -> dwm.suckless.org/patches/float_border_color/dwm-float_border_color-6.0.diff | 0
Rdwm.suckless.org/patches/dwm-float_border_color-6.1.diff -> dwm.suckless.org/patches/float_border_color/dwm-float_border_color-6.1.diff | 0
Rdwm.suckless.org/patches/dwm-float_border_color2-20160731-56a31dc.diff -> dwm.suckless.org/patches/float_border_color/dwm-float_border_color2-20160731-56a31dc.diff | 0
Rdwm.suckless.org/patches/float_border_color.md -> dwm.suckless.org/patches/float_border_color/index.md | 0
Ddwm.suckless.org/patches/focusadjacenttag.md | 29-----------------------------
Rdwm.suckless.org/patches/dwm-6.0-focusadjacenttag.diff -> dwm.suckless.org/patches/focusadjacenttag/dwm-focusadjacenttag-6.0.diff | 0
Adwm.suckless.org/patches/focusadjacenttag/index.md | 29+++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/focusonclick.md | 22----------------------
Rdwm.suckless.org/patches/dwm-focusonclick-20171030-6aa8e37.diff -> dwm.suckless.org/patches/focusonclick/dwm-focusonclick-20171030-6aa8e37.diff | 0
Rdwm.suckless.org/patches/dwm-focusonclick-6.0.diff -> dwm.suckless.org/patches/focusonclick/dwm-focusonclick-6.0.diff | 0
Rdwm.suckless.org/patches/dwm-focusonclick-bb3bd6f.diff -> dwm.suckless.org/patches/focusonclick/dwm-focusonclick-bb3bd6f.diff | 0
Adwm.suckless.org/patches/focusonclick/dwm-focusonclick-git-20100321.diff | 38++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/focusonclick/index.md | 22++++++++++++++++++++++
Ddwm.suckless.org/patches/focusurgent.md | 15---------------
Rdwm.suckless.org/patches/dwm-focusurgent-20160831-56a31dc.diff -> dwm.suckless.org/patches/focusurgent/dwm-focusurgent-20160831-56a31dc.diff | 0
Adwm.suckless.org/patches/focusurgent/index.md | 15+++++++++++++++
Ddwm.suckless.org/patches/gapless_grid.md | 33---------------------------------
Ddwm.suckless.org/patches/gaplessgrid.c | 36------------------------------------
Adwm.suckless.org/patches/gaplessgrid/dwm-5.2-gaplessgrid.diff | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rdwm.suckless.org/patches/dwm-gaplessgrid-20160731-56a31dc.diff -> dwm.suckless.org/patches/gaplessgrid/dwm-gaplessgrid-20160731-56a31dc.diff | 0
Rdwm.suckless.org/patches/dwm-gaplessgrid-6.1.diff -> dwm.suckless.org/patches/gaplessgrid/dwm-gaplessgrid-6.1.diff | 0
Adwm.suckless.org/patches/gaplessgrid/dwm-r1437-gaplessgrid.diff | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/gaplessgrid/gaplessgrid.c | 36++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/gaplessgrid/index.md | 33+++++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/gaps.md | 27---------------------------
Rdwm.suckless.org/patches/dwm-gaps-6.0.diff -> dwm.suckless.org/patches/gaps/dwm-gaps-6.0.diff | 0
Rdwm.suckless.org/patches/dwm-6.0-xtile-gaps.diff -> dwm.suckless.org/patches/gaps/dwm-gaps-xtile-6.0.diff | 0
Adwm.suckless.org/patches/gaps/index.md | 26++++++++++++++++++++++++++
Ddwm.suckless.org/patches/gestures.md | 16----------------
Rdwm.suckless.org/patches/dwm-5.8-gestures.diff -> dwm.suckless.org/patches/gestures/dwm-5.8-gestures.diff | 0
Adwm.suckless.org/patches/gestures/index.md | 16++++++++++++++++
Ddwm.suckless.org/patches/gridmode.md | 27---------------------------
Rdwm.suckless.org/patches/dwm-gridmode-20170909-ceac8c9.diff -> dwm.suckless.org/patches/gridmode/dwm-gridmode-20170909-ceac8c9.diff | 0
Rdwm.suckless.org/patches/dwm-gridmode-5.8.2.diff -> dwm.suckless.org/patches/gridmode/dwm-gridmode-5.8.2.diff | 0
Adwm.suckless.org/patches/gridmode/index.md | 27+++++++++++++++++++++++++++
Ddwm.suckless.org/patches/hide_vacant_tags.md | 29-----------------------------
Rdwm.suckless.org/patches/dwm-hide_vacant_tags-6.1.diff -> dwm.suckless.org/patches/hide_vacant_tags/dwm-hide_vacant_tags-6.1.diff | 0
Rdwm.suckless.org/patches/dwm-hide_vacant_tags-git-20160626-7af4d43.diff -> dwm.suckless.org/patches/hide_vacant_tags/dwm-hide_vacant_tags-git-20160626-7af4d43.diff | 0
Adwm.suckless.org/patches/hide_vacant_tags/index.md | 29+++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/historical/dwm-5.2-gaplessgrid.diff | 59-----------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-5.7.2-statuscolors.diff | 234-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-5.8.2-pertag_without_bar.diff | 165-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-5.8.2-statuscolors.diff | 232-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-6.0-tab-v2.diff | 720-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-6.0-tab-v2a.diff | 720-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-6.0-tab-v2b.diff | 720-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-6.0-winview.diff | 65-----------------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-fancybar-5.6.1.diff | 121-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-flextile-5.8.1.diff | 418-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-gap-5.7.2.diff | 23-----------------------
Ddwm.suckless.org/patches/historical/dwm-git-20100321-focusonclick.diff | 38--------------------------------------
Ddwm.suckless.org/patches/historical/dwm-master_2013-08-27_cdec978-pertag-tab-v2a.diff | 672-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-master_2013-08-27_cdec978-tab-v2a.diff | 505-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-master_2015-03-05_14343e-pertag-tab-v2b.diff | 693-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-master_2015-03-05_14343e-tab-v2b.diff | 506-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-master_2015-10-20_7e1182c-pertag-tab-v2b.diff | 692-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-master_2015-10-20_7e1182c-tab-v2b.diff | 506-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-master_2015-12-19_3465be-pertag-tab-v2b.diff | 844-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-master_2015-12-19_3465be-tab-v2b.diff | 500-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-movestack-5.8.2.diff | 73-------------------------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-pertag-5.1.diff | 125-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-pertag-5.2.diff | 123-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-pertag-5.4.diff | 123-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-pertag-5.6.1.diff | 184-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-pertag-5.7.2.diff | 184-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-pertag-5.8.2.diff | 180-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-r1437-gaplessgrid.diff | 59-----------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-r1578-pertag.diff | 189-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/historical/dwm-uselessgap-5.8.diff | 49-------------------------------------------------
Ddwm.suckless.org/patches/horizgrid.md | 37-------------------------------------
Rdwm.suckless.org/patches/dwm-horizgrid-6.1.diff -> dwm.suckless.org/patches/horizgrid/dwm-horizgrid-6.1.diff | 0
Adwm.suckless.org/patches/horizgrid/index.md | 37+++++++++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/ispermanent.md | 18------------------
Rdwm.suckless.org/patches/dwm-6.0-ispermanent.diff -> dwm.suckless.org/patches/ispermanent/dwm-ispermanent-6.0.diff | 0
Adwm.suckless.org/patches/ispermanent/index.md | 18++++++++++++++++++
Ddwm.suckless.org/patches/keycodes.md | 14--------------
Rdwm.suckless.org/patches/dwm-keycodes-20170511-ceac8c9.diff -> dwm.suckless.org/patches/keycodes/dwm-keycodes-20170511-ceac8c9.diff | 0
Rdwm.suckless.org/patches/dwm-keycodes-6.1.diff -> dwm.suckless.org/patches/keycodes/dwm-keycodes-6.1.diff | 0
Adwm.suckless.org/patches/keycodes/index.md | 14++++++++++++++
Ddwm.suckless.org/patches/keymodes-5.8.2-vim-config.h | 163-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/keymodes-5.8.2-vim.diff | 583-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/keymodes-5.8.2.diff | 239-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/keymodes.md | 55-------------------------------------------------------
Adwm.suckless.org/patches/keymodes/dwm-keymodes-5.8.2.diff | 239+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/keymodes/dwm-keymodes-vim-5.8.2.diff | 583+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/keymodes/dwm-keymodes-vim-config.h | 163+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/keymodes/index.md | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/keypressrelease.md | 37-------------------------------------
Rdwm.suckless.org/patches/dwm-keypressrelease-6.0.diff -> dwm.suckless.org/patches/keypressrelease/dwm-keypressrelease-6.0.diff | 0
Adwm.suckless.org/patches/keypressrelease/index.md | 36++++++++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/killunsel.md | 23-----------------------
Rdwm.suckless.org/patches/dwm-killunsel-ceac8c91ff.diff -> dwm.suckless.org/patches/killunsel/dwm-killunsel-ceac8c91ff.diff | 0
Adwm.suckless.org/patches/killunsel/index.md | 23+++++++++++++++++++++++
Ddwm.suckless.org/patches/mark.md | 51---------------------------------------------------
Rdwm.suckless.org/patches/dwm-mark-6.1.diff -> dwm.suckless.org/patches/mark/dwm-mark-6.1.diff | 0
Rdwm.suckless.org/patches/dwm-mark-new-6.1.diff -> dwm.suckless.org/patches/mark/dwm-mark-new-6.1.diff | 0
Adwm.suckless.org/patches/mark/index.md | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/maximize.md | 27---------------------------
Rdwm.suckless.org/patches/dwm-maximize_vert_horz-20160731-56a31dc.diff -> dwm.suckless.org/patches/maximize/dwm-maximize_vert_horz-20160731-56a31dc.diff | 0
Rdwm.suckless.org/patches/dwm-maximize_vert_horz-6.0.diff -> dwm.suckless.org/patches/maximize/dwm-maximize_vert_horz-6.0.diff | 0
Rdwm.suckless.org/patches/dwm-maximize_vert_horz-6.1.diff -> dwm.suckless.org/patches/maximize/dwm-maximize_vert_horz-6.1.diff | 0
Adwm.suckless.org/patches/maximize/index.md | 27+++++++++++++++++++++++++++
Ddwm.suckless.org/patches/monocle_count.md | 16----------------
Rdwm.suckless.org/patches/dwm-monocle_count-5.8.2.diff -> dwm.suckless.org/patches/monocle_count/dwm-monocle_count-5.8.2.diff | 0
Adwm.suckless.org/patches/monocle_count/index.md | 16++++++++++++++++
Ddwm.suckless.org/patches/moveontagmon.md | 13-------------
Rdwm.suckless.org/patches/dwm-r1437-moveontagmon.diff -> dwm.suckless.org/patches/moveontagmon/dwm-r1437-moveontagmon.diff | 0
Adwm.suckless.org/patches/moveontagmon/index.md | 13+++++++++++++
Ddwm.suckless.org/patches/moveresize.md | 72------------------------------------------------------------------------
Rdwm.suckless.org/patches/dwm-10e232f9ace7-moveresize.diff -> dwm.suckless.org/patches/moveresize/dwm-10e232f9ace7-moveresize.diff | 0
Rdwm.suckless.org/patches/dwm-moveresize-20160731-56a31dc.diff -> dwm.suckless.org/patches/moveresize/dwm-moveresize-20160731-56a31dc.diff | 0
Rdwm.suckless.org/patches/dwm-moveresize-6.0.diff -> dwm.suckless.org/patches/moveresize/dwm-moveresize-6.0.diff | 0
Rdwm.suckless.org/patches/dwm-moveresize-6.1.diff -> dwm.suckless.org/patches/moveresize/dwm-moveresize-6.1.diff | 0
Adwm.suckless.org/patches/moveresize/index.md | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/movestack.md | 39---------------------------------------
Adwm.suckless.org/patches/movestack/dwm-movestack-5.8.2.diff | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rdwm.suckless.org/patches/dwm-movestack-6.1.diff -> dwm.suckless.org/patches/movestack/dwm-movestack-6.1.diff | 0
Adwm.suckless.org/patches/movestack/index.md | 39+++++++++++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/mpdcontrol.md | 24------------------------
Rdwm.suckless.org/patches/dwm-r1615-mpdcontrol.diff -> dwm.suckless.org/patches/mpdcontrol/dwm-r1615-mpdcontrol.diff | 0
Adwm.suckless.org/patches/mpdcontrol/index.md | 24++++++++++++++++++++++++
Ddwm.suckless.org/patches/nametag.md | 22----------------------
Rdwm.suckless.org/patches/dwm-nametag-5.7.2.diff -> dwm.suckless.org/patches/nametag/dwm-nametag-5.7.2.diff | 0
Rdwm.suckless.org/patches/dwm-nametag-6.1.diff -> dwm.suckless.org/patches/nametag/dwm-nametag-6.1.diff | 0
Rdwm.suckless.org/patches/dwm-nametag-prepend-6.1.diff -> dwm.suckless.org/patches/nametag/dwm-nametag-prepend-6.1.diff | 0
Adwm.suckless.org/patches/nametag/index.md | 22++++++++++++++++++++++
Ddwm.suckless.org/patches/nextprev.md | 33---------------------------------
Adwm.suckless.org/patches/nextprev/index.md | 33+++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/nextprev/nextprevtag.c | 21+++++++++++++++++++++
Ddwm.suckless.org/patches/nextprevtag.c | 21---------------------
Ddwm.suckless.org/patches/nmaster-ncol.c | 163-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/nmaster-sym.c | 126-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/nmaster.c | 122-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/nmaster.md | 66------------------------------------------------------------------
Adwm.suckless.org/patches/nmaster/index.md | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/nmaster/nmaster-ncol.c | 163+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/nmaster/nmaster-sym.c | 126+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/nmaster/nmaster.c | 122+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/noborder.md | 21---------------------
Rdwm.suckless.org/patches/dwm-noborder-20160718-56a31dc.diff -> dwm.suckless.org/patches/noborder/dwm-noborder-20160718-56a31dc.diff | 0
Rdwm.suckless.org/patches/dwm-noborder-20170207-bb3bd6f.diff -> dwm.suckless.org/patches/noborder/dwm-noborder-20170207-bb3bd6f.diff | 0
Rdwm.suckless.org/patches/dwm-noborder-6.1.diff -> dwm.suckless.org/patches/noborder/dwm-noborder-6.1.diff | 0
Adwm.suckless.org/patches/noborder/index.md | 21+++++++++++++++++++++
Ddwm.suckless.org/patches/pango.md | 40----------------------------------------
Rdwm.suckless.org/patches/dwm-pango-6.0.diff -> dwm.suckless.org/patches/pango/dwm-pango-6.0.diff | 0
Adwm.suckless.org/patches/pango/index.md | 40++++++++++++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/pertag.md | 51---------------------------------------------------
Adwm.suckless.org/patches/pertag/dwm-5.8.2-pertag_without_bar.diff | 165+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rdwm.suckless.org/patches/dwm-6.0-pertag_without_bar.diff -> dwm.suckless.org/patches/pertag/dwm-6.0-pertag_without_bar.diff | 0
Rdwm.suckless.org/patches/dwm-6.1-pertag_without_bar.diff -> dwm.suckless.org/patches/pertag/dwm-6.1-pertag_without_bar.diff | 0
Rdwm.suckless.org/patches/dwm-git-20120406-pertag.diff -> dwm.suckless.org/patches/pertag/dwm-git-20120406-pertag.diff | 0
Rdwm.suckless.org/patches/dwm-pertag-20170513-ceac8c9.diff -> dwm.suckless.org/patches/pertag/dwm-pertag-20170513-ceac8c9.diff | 0
Adwm.suckless.org/patches/pertag/dwm-pertag-5.1.diff | 125+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/pertag/dwm-pertag-5.2.diff | 123+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/pertag/dwm-pertag-5.4.diff | 123+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/pertag/dwm-pertag-5.6.1.diff | 184+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/pertag/dwm-pertag-5.7.2.diff | 184+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/pertag/dwm-pertag-5.8.2.diff | 180+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rdwm.suckless.org/patches/dwm-pertag-6.0.diff -> dwm.suckless.org/patches/pertag/dwm-pertag-6.0.diff | 0
Rdwm.suckless.org/patches/dwm-pertag-6.1.diff -> dwm.suckless.org/patches/pertag/dwm-pertag-6.1.diff | 0
Adwm.suckless.org/patches/pertag/dwm-r1578-pertag.diff | 189+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/pertag/index.md | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/push.md | 32--------------------------------
Rdwm.suckless.org/patches/dwm-6.0-push_no_master.diff -> dwm.suckless.org/patches/push/dwm-6.0-push_no_master.diff | 0
Rdwm.suckless.org/patches/dwm-6.1-push_no_master.diff -> dwm.suckless.org/patches/push/dwm-6.1-push_no_master.diff | 0
Rdwm.suckless.org/patches/dwm-push-20160731-56a31dc.diff -> dwm.suckless.org/patches/push/dwm-push-20160731-56a31dc.diff | 0
Rdwm.suckless.org/patches/dwm-push-6.0.diff -> dwm.suckless.org/patches/push/dwm-push-6.0.diff | 0
Rdwm.suckless.org/patches/dwm-push-6.1.diff -> dwm.suckless.org/patches/push/dwm-push-6.1.diff | 0
Adwm.suckless.org/patches/push/index.md | 32++++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/pwkl.md | 23-----------------------
Rdwm.suckless.org/patches/dwm-pwkl-5.9.diff -> dwm.suckless.org/patches/pwkl/dwm-pwkl-5.9.diff | 0
Rdwm.suckless.org/patches/dwm-pwkl-6.1.diff -> dwm.suckless.org/patches/pwkl/dwm-pwkl-6.1.diff | 0
Adwm.suckless.org/patches/pwkl/index.md | 23+++++++++++++++++++++++
Ddwm.suckless.org/patches/resizecorners.md | 15---------------
Rdwm.suckless.org/patches/dwm-resizecorners-6.0.diff -> dwm.suckless.org/patches/resizecorners/dwm-resizecorners-6.0.diff | 0
Rdwm.suckless.org/patches/dwm-resizecorners-6.1.diff -> dwm.suckless.org/patches/resizecorners/dwm-resizecorners-6.1.diff | 0
Adwm.suckless.org/patches/resizecorners/index.md | 15+++++++++++++++
Ddwm.suckless.org/patches/rmaster.md | 21---------------------
Rdwm.suckless.org/patches/dwm-rmaster-6.1.diff -> dwm.suckless.org/patches/rmaster/dwm-rmaster-6.1.diff | 0
Adwm.suckless.org/patches/rmaster/index.md | 21+++++++++++++++++++++
Ddwm.suckless.org/patches/rotatestack.md | 24------------------------
Rdwm.suckless.org/patches/dwm-rotatestack-20161021-ab9571b.diff -> dwm.suckless.org/patches/rotatestack/dwm-rotatestack-20161021-ab9571b.diff | 0
Adwm.suckless.org/patches/rotatestack/index.md | 24++++++++++++++++++++++++
Ddwm.suckless.org/patches/runorraise.md | 35-----------------------------------
Rdwm.suckless.org/patches/dwm-6.1-runorraise.diff -> dwm.suckless.org/patches/runorraise/dwm-6.1-runorraise.diff | 0
Adwm.suckless.org/patches/runorraise/index.md | 35+++++++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/save_floats.md | 20--------------------
Rdwm.suckless.org/patches/dwm-10e232f9ace7-save_floats.diff -> dwm.suckless.org/patches/save_floats/dwm-10e232f9ace7-save_floats.diff | 0
Rdwm.suckless.org/patches/dwm-6.1-save_floats.diff -> dwm.suckless.org/patches/save_floats/dwm-6.1-save_floats.diff | 0
Rdwm.suckless.org/patches/dwm-save_floats-6.0.diff -> dwm.suckless.org/patches/save_floats/dwm-save_floats-6.0.diff | 0
Rdwm.suckless.org/patches/dwm-savefloats-20160723-56a31dc.diff -> dwm.suckless.org/patches/save_floats/dwm-savefloats-20160723-56a31dc.diff | 0
Adwm.suckless.org/patches/save_floats/index.md | 20++++++++++++++++++++
Ddwm.suckless.org/patches/schemeSwitch.md | 31-------------------------------
Rdwm.suckless.org/patches/dwm-schemeSwitch-20170804-ceac8c9.diff -> dwm.suckless.org/patches/scheme_switch/dwm-scheme_switch-20170804-ceac8c9.diff | 0
Adwm.suckless.org/patches/scheme_switch/index.md | 31+++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/scratchpad.md | 24------------------------
Rdwm.suckless.org/patches/dwm-scratchpad-20170207-bb3bd6f.diff -> dwm.suckless.org/patches/scratchpad/dwm-scratchpad-20170207-bb3bd6f.diff | 0
Adwm.suckless.org/patches/scratchpad/index.md | 24++++++++++++++++++++++++
Ddwm.suckless.org/patches/selfrestart.md | 15---------------
Rdwm.suckless.org/patches/dwm-r1615-selfrestart.diff -> dwm.suckless.org/patches/selfrestart/dwm-r1615-selfrestart.diff | 0
Adwm.suckless.org/patches/selfrestart/index.md | 15+++++++++++++++
Ddwm.suckless.org/patches/single_tagset.md | 53-----------------------------------------------------
Rdwm.suckless.org/patches/dwm-10e232f9ace7-single_tagset.diff -> dwm.suckless.org/patches/single_tagset/dwm-10e232f9ace7-single_tagset.diff | 0
Rdwm.suckless.org/patches/dwm-6.1-single_tagset.diff -> dwm.suckless.org/patches/single_tagset/dwm-6.1-single_tagset.diff | 0
Rdwm.suckless.org/patches/dwm-single_tagset-20160731-56a31dc.diff -> dwm.suckless.org/patches/single_tagset/dwm-single_tagset-20160731-56a31dc.diff | 0
Rdwm.suckless.org/patches/dwm-single_tagset-6.0.diff -> dwm.suckless.org/patches/single_tagset/dwm-single_tagset-6.0.diff | 0
Adwm.suckless.org/patches/single_tagset/index.md | 34++++++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/singularborders.md | 43-------------------------------------------
Rdwm.suckless.org/patches/dwm-6.0-singularborders.diff -> dwm.suckless.org/patches/singularborders/dwm-6.0-singularborders.diff | 0
Rdwm.suckless.org/patches/dwm-6.0-singularborders_bstack.diff -> dwm.suckless.org/patches/singularborders/dwm-6.0-singularborders_bstack.diff | 0
Adwm.suckless.org/patches/singularborders/index.md | 43+++++++++++++++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/sizehints.md | 19-------------------
Rdwm.suckless.org/patches/dwm-sizehints-5.7.2.diff -> dwm.suckless.org/patches/sizehints/dwm-sizehints-5.7.2.diff | 0
Adwm.suckless.org/patches/sizehints/index.md | 19+++++++++++++++++++
Ddwm.suckless.org/patches/spawn_cwd.md | 16----------------
Rdwm.suckless.org/patches/dwm-5.9.1-spawn_cwd.diff -> dwm.suckless.org/patches/spawn_cwd/dwm-5.9.1-spawn_cwd.diff | 0
Adwm.suckless.org/patches/spawn_cwd/index.md | 16++++++++++++++++
Ddwm.suckless.org/patches/stacker.md | 61-------------------------------------------------------------
Rdwm.suckless.org/patches/dwm-stacker-6.0.diff -> dwm.suckless.org/patches/stacker/dwm-stacker-6.0.diff | 0
Adwm.suckless.org/patches/stacker/index.md | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/stackmfact.md | 38--------------------------------------
Rdwm.suckless.org/patches/dwm-6.0-smfact.diff -> dwm.suckless.org/patches/stackmfact/dwm-6.0-smfact.diff | 0
Adwm.suckless.org/patches/stackmfact/index.md | 38++++++++++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/status2d.md | 36------------------------------------
Ddwm.suckless.org/patches/status2d.png | 0
Rdwm.suckless.org/patches/dwm-status2d-20161231-bb3bd6f.diff -> dwm.suckless.org/patches/status2d/dwm-status2d-20161231-bb3bd6f.diff | 0
Adwm.suckless.org/patches/status2d/index.md | 35+++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/status2d/status2d.png | 0
Ddwm.suckless.org/patches/statusallmons.md | 22----------------------
Rdwm.suckless.org/patches/dwm-10e232f9ace7-statusallmons.diff -> dwm.suckless.org/patches/statusallmons/dwm-10e232f9ace7-statusallmons.diff | 0
Rdwm.suckless.org/patches/dwm-6.1-statusallmons.diff -> dwm.suckless.org/patches/statusallmons/dwm-6.1-statusallmons.diff | 0
Rdwm.suckless.org/patches/dwm-statusallmons-20160731-56a31dc.diff -> dwm.suckless.org/patches/statusallmons/dwm-statusallmons-20160731-56a31dc.diff | 0
Rdwm.suckless.org/patches/dwm-statusallmons-5.8.2.diff -> dwm.suckless.org/patches/statusallmons/dwm-statusallmons-5.8.2.diff | 0
Rdwm.suckless.org/patches/dwm-statusallmons-6.0.diff -> dwm.suckless.org/patches/statusallmons/dwm-statusallmons-6.0.diff | 0
Adwm.suckless.org/patches/statusallmons/index.md | 22++++++++++++++++++++++
Ddwm.suckless.org/patches/statuscolors.md | 62--------------------------------------------------------------
Adwm.suckless.org/patches/statuscolors/dwm-5.7.2-statuscolors.diff | 234+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/statuscolors/dwm-5.8.2-statuscolors.diff | 232+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rdwm.suckless.org/patches/dwm-statuscolors-5.9.diff -> dwm.suckless.org/patches/statuscolors/dwm-statuscolors-5.9.diff | 0
Rdwm.suckless.org/patches/dwm-statuscolors-6.1.diff -> dwm.suckless.org/patches/statuscolors/dwm-statuscolors-6.1.diff | 0
Adwm.suckless.org/patches/statuscolors/index.md | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rdwm.suckless.org/patches/dwm-5.7.2-statuscolors.png -> dwm.suckless.org/patches/statuscolors/statuscolors.png | 0
Ddwm.suckless.org/patches/stdin.md | 21---------------------
Rdwm.suckless.org/patches/dwm-r1533-stdin.diff -> dwm.suckless.org/patches/stdin/dwm-r1533-stdin.diff | 0
Adwm.suckless.org/patches/stdin/index.md | 21+++++++++++++++++++++
Ddwm.suckless.org/patches/sticky.md | 16----------------
Rdwm.suckless.org/patches/dwm-sticky-20160911-ab9571b.diff -> dwm.suckless.org/patches/sticky/dwm-sticky-20160911-ab9571b.diff | 0
Rdwm.suckless.org/patches/dwm-sticky-6.1.diff -> dwm.suckless.org/patches/sticky/dwm-sticky-6.1.diff | 0
Adwm.suckless.org/patches/sticky/index.md | 16++++++++++++++++
Ddwm.suckless.org/patches/swallow.md | 52----------------------------------------------------
Rdwm.suckless.org/patches/dwm-swallow-20160717-56a31dc.diff -> dwm.suckless.org/patches/swallow/dwm-swallow-20160717-56a31dc.diff | 0
Rdwm.suckless.org/patches/dwm-swallow-20170909-ceac8c9.diff -> dwm.suckless.org/patches/swallow/dwm-swallow-20170909-ceac8c9.diff | 0
Rdwm.suckless.org/patches/dwm-swallow-6.1.diff -> dwm.suckless.org/patches/swallow/dwm-swallow-6.1.diff | 0
Adwm.suckless.org/patches/swallow/index.md | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/swapfocus.md | 18------------------
Rdwm.suckless.org/patches/dwm-10e232f9ace7-swapfocus.diff -> dwm.suckless.org/patches/swapfocus/dwm-10e232f9ace7-swapfocus.diff | 0
Rdwm.suckless.org/patches/dwm-5.8.2-swap.diff -> dwm.suckless.org/patches/swapfocus/dwm-5.8.2-swap.diff | 0
Rdwm.suckless.org/patches/dwm-6.1-swapfocus.diff -> dwm.suckless.org/patches/swapfocus/dwm-6.1-swapfocus.diff | 0
Rdwm.suckless.org/patches/dwm-swapfocus-20160731-56a31dc.diff -> dwm.suckless.org/patches/swapfocus/dwm-swapfocus-20160731-56a31dc.diff | 0
Rdwm.suckless.org/patches/dwm-swapfocus-6.0.diff -> dwm.suckless.org/patches/swapfocus/dwm-swapfocus-6.0.diff | 0
Adwm.suckless.org/patches/swapfocus/index.md | 18++++++++++++++++++
Ddwm.suckless.org/patches/switchcol.md | 20--------------------
Rdwm.suckless.org/patches/dwm-switchcol-6.1.diff -> dwm.suckless.org/patches/switchcol/dwm-switchcol-6.1.diff | 0
Adwm.suckless.org/patches/switchcol/index.md | 20++++++++++++++++++++
Ddwm.suckless.org/patches/systray.md | 27---------------------------
Rdwm.suckless.org/patches/dwm-6.1-systray.diff -> dwm.suckless.org/patches/systray/dwm-6.1-systray.diff | 0
Rdwm.suckless.org/patches/dwm-git-20130119-systray.diff -> dwm.suckless.org/patches/systray/dwm-git-20130119-systray.diff | 0
Rdwm.suckless.org/patches/dwm-git-20160103-systray.diff -> dwm.suckless.org/patches/systray/dwm-git-20160103-systray.diff | 0
Rdwm.suckless.org/patches/dwm-systray-20160731-56a31dc.diff -> dwm.suckless.org/patches/systray/dwm-systray-20160731-56a31dc.diff | 0
Rdwm.suckless.org/patches/dwm-systray-20161218-bb3bd6f.diff -> dwm.suckless.org/patches/systray/dwm-systray-20161218-bb3bd6f.diff | 0
Rdwm.suckless.org/patches/dwm-systray-6.0.diff -> dwm.suckless.org/patches/systray/dwm-systray-6.0.diff | 0
Rdwm.suckless.org/patches/dwm-systray-git-20160626-7af4d43.diff -> dwm.suckless.org/patches/systray/dwm-systray-git-20160626-7af4d43.diff | 0
Adwm.suckless.org/patches/systray/index.md | 27+++++++++++++++++++++++++++
Ddwm.suckless.org/patches/tab.md | 149-------------------------------------------------------------------------------
Rdwm.suckless.org/patches/dwm-6.1-pertag-tab-v2b.diff -> dwm.suckless.org/patches/tab/dwm-6.1-pertag-tab-v2b.diff | 0
Rdwm.suckless.org/patches/dwm-6.1-tab-v2b.diff -> dwm.suckless.org/patches/tab/dwm-6.1-tab-v2b.diff | 0
Rdwm.suckless.org/patches/dwm-tab-v2b-56a31dc.diff -> dwm.suckless.org/patches/tab/dwm-tab-v2b-56a31dc.diff | 0
Rdwm.suckless.org/patches/dwm-tab-v2b-pertab-56a31dc.diff -> dwm.suckless.org/patches/tab/dwm-tab-v2b-pertab-56a31dc.diff | 0
Adwm.suckless.org/patches/tab/index.md | 137+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/tagall.md | 31-------------------------------
Rdwm.suckless.org/patches/dwm-10e232f9ace7-tagall.diff -> dwm.suckless.org/patches/tagall/dwm-10e232f9ace7-tagall.diff | 0
Rdwm.suckless.org/patches/dwm-tagall-20160731-56a31dc.diff -> dwm.suckless.org/patches/tagall/dwm-tagall-20160731-56a31dc.diff | 0
Rdwm.suckless.org/patches/dwm-tagall-6.0.diff -> dwm.suckless.org/patches/tagall/dwm-tagall-6.0.diff | 0
Rdwm.suckless.org/patches/dwm-tagall-6.1.diff -> dwm.suckless.org/patches/tagall/dwm-tagall-6.1.diff | 0
Adwm.suckless.org/patches/tagall/index.md | 31+++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/taggrid.md | 79-------------------------------------------------------------------------------
Ddwm.suckless.org/patches/taggrid.png | 0
Rdwm.suckless.org/patches/dwm-6.1-taggrid.diff -> dwm.suckless.org/patches/taggrid/dwm-6.1-taggrid.diff | 0
Adwm.suckless.org/patches/taggrid/index.md | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/taggrid/taggrid.png | 0
Ddwm.suckless.org/patches/tagintostack.md | 21---------------------
Rdwm.suckless.org/patches/dwm-6.1-tagintostack-allmaster.diff -> dwm.suckless.org/patches/tagintostack/dwm-6.1-tagintostack-allmaster.diff | 0
Rdwm.suckless.org/patches/dwm-6.1-tagintostack-onemaster.diff -> dwm.suckless.org/patches/tagintostack/dwm-6.1-tagintostack-onemaster.diff | 0
Adwm.suckless.org/patches/tagintostack/index.md | 21+++++++++++++++++++++
Ddwm.suckless.org/patches/tcl.c | 74--------------------------------------------------------------------------
Ddwm.suckless.org/patches/three-column.md | 38--------------------------------------
Adwm.suckless.org/patches/three-column/index.md | 38++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/three-column/tcl.c | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/tilegap.md | 16----------------
Rdwm.suckless.org/patches/dwm-tilegap-6.0.diff -> dwm.suckless.org/patches/tilegap/dwm-tilegap-6.0.diff | 0
Adwm.suckless.org/patches/tilegap/index.md | 16++++++++++++++++
Ddwm.suckless.org/patches/transparency.md | 15---------------
Ddwm.suckless.org/patches/urgentborder.md | 15---------------
Rdwm.suckless.org/patches/dwm-6.1-urg-border.diff -> dwm.suckless.org/patches/urgentborder/dwm-6.1-urg-border.diff | 0
Adwm.suckless.org/patches/urgentborder/index.md | 15+++++++++++++++
Ddwm.suckless.org/patches/uselessgap.md | 64----------------------------------------------------------------
Adwm.suckless.org/patches/uselessgap/dwm-gap-5.7.2.diff | 23+++++++++++++++++++++++
Adwm.suckless.org/patches/uselessgap/dwm-uselessgap-5.8.diff | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Rdwm.suckless.org/patches/dwm-uselessgap-5.9.diff -> dwm.suckless.org/patches/uselessgap/dwm-uselessgap-5.9.diff | 0
Rdwm.suckless.org/patches/dwm-uselessgap-6.1.diff -> dwm.suckless.org/patches/uselessgap/dwm-uselessgap-6.1.diff | 0
Adwm.suckless.org/patches/uselessgap/index.md | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/viewontag.md | 14--------------
Rdwm.suckless.org/patches/dwm-r1522-viewontag.diff -> dwm.suckless.org/patches/viewontag/dwm-r1522-viewontag.diff | 0
Adwm.suckless.org/patches/viewontag/index.md | 14++++++++++++++
Ddwm.suckless.org/patches/warp.md | 24------------------------
Rdwm.suckless.org/patches/dwm-warp-5.9.diff -> dwm.suckless.org/patches/warp/dwm-warp-5.9.diff | 0
Rdwm.suckless.org/patches/dwm-warp-6.1.diff -> dwm.suckless.org/patches/warp/dwm-warp-6.1.diff | 0
Rdwm.suckless.org/patches/dwm-warp-git-20160626-7af4d43.diff -> dwm.suckless.org/patches/warp/dwm-warp-git-20160626-7af4d43.diff | 0
Adwm.suckless.org/patches/warp/index.md | 24++++++++++++++++++++++++
Ddwm.suckless.org/patches/winview.md | 54------------------------------------------------------
Adwm.suckless.org/patches/winview/dwm-6.0-winview.diff | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rdwm.suckless.org/patches/dwm-6.1-winview.diff -> dwm.suckless.org/patches/winview/dwm-6.1-winview.diff | 0
Adwm.suckless.org/patches/winview/index.md | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/xkb.md | 33---------------------------------
Rdwm.suckless.org/patches/dwm-6.1-xkb.diff -> dwm.suckless.org/patches/xkb/dwm-6.1-xkb.diff | 0
Adwm.suckless.org/patches/xkb/index.md | 33+++++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/xtile.md | 169-------------------------------------------------------------------------------
Rdwm.suckless.org/patches/dwm-6.0-xtile.diff -> dwm.suckless.org/patches/xtile/dwm-6.0-xtile.diff | 0
Adwm.suckless.org/patches/xtile/index.md | 169+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ddwm.suckless.org/patches/zoomswap.md | 52----------------------------------------------------
Rdwm.suckless.org/patches/dwm-6.1-zoomswap.diff -> dwm.suckless.org/patches/zoomswap/dwm-6.1-zoomswap.diff | 0
Rdwm.suckless.org/patches/dwm-zoomswap-20160731-56a31dc.diff -> dwm.suckless.org/patches/zoomswap/dwm-zoomswap-20160731-56a31dc.diff | 0
Rdwm.suckless.org/patches/dwm-zoomswap-6.0.diff -> dwm.suckless.org/patches/zoomswap/dwm-zoomswap-6.0.diff | 0
Adwm.suckless.org/patches/zoomswap/index.md | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
413 files changed, 6683 insertions(+), 13853 deletions(-)

diff --git a/dwm.suckless.org/patches/dwm-alpha-6.1.diff b/dwm.suckless.org/patches/alpha/dwm-alpha-6.1.diff diff --git a/dwm.suckless.org/patches/dwm-alpha.png b/dwm.suckless.org/patches/alpha/dwm-alpha.png Binary files differ. diff --git a/dwm.suckless.org/patches/alpha.md b/dwm.suckless.org/patches/alpha/index.md diff --git a/dwm.suckless.org/patches/dwm-alwaysfullscreen-20160713-56a31dc.diff b/dwm.suckless.org/patches/alwaysfullscreen/dwm-alwaysfullscreen-20160713-56a31dc.diff diff --git a/dwm.suckless.org/patches/dwm-alwaysfullscreen-6.1.diff b/dwm.suckless.org/patches/alwaysfullscreen/dwm-alwaysfullscreen-6.1.diff diff --git a/dwm.suckless.org/patches/alwaysfullscreen.md b/dwm.suckless.org/patches/alwaysfullscreen/index.md diff --git a/dwm.suckless.org/patches/dwm-attachabove-20160713-56a31dc.diff b/dwm.suckless.org/patches/attachabove/dwm-attachabove-20160713-56a31dc.diff diff --git a/dwm.suckless.org/patches/dwm-attachabove-6.0.diff b/dwm.suckless.org/patches/attachabove/dwm-attachabove-6.0.diff diff --git a/dwm.suckless.org/patches/dwm-attachabove-6.1.diff b/dwm.suckless.org/patches/attachabove/dwm-attachabove-6.1.diff diff --git a/dwm.suckless.org/patches/attachabove.md b/dwm.suckless.org/patches/attachabove/index.md diff --git a/dwm.suckless.org/patches/dwm-attachaside-20160718-56a31dc.diff b/dwm.suckless.org/patches/attachaside/dwm-attachaside-20160718-56a31dc.diff diff --git a/dwm.suckless.org/patches/dwm-attachaside-6.1.diff b/dwm.suckless.org/patches/attachaside/dwm-attachaside-6.1.diff diff --git a/dwm.suckless.org/patches/attachaside.md b/dwm.suckless.org/patches/attachaside/index.md diff --git a/dwm.suckless.org/patches/dwm-autoresize-20160718-56a31dc.diff b/dwm.suckless.org/patches/autoresize/dwm-autoresize-20160718-56a31dc.diff diff --git a/dwm.suckless.org/patches/dwm-autoresize-6.0.diff b/dwm.suckless.org/patches/autoresize/dwm-autoresize-6.0.diff diff --git a/dwm.suckless.org/patches/dwm-autoresize-6.1.diff b/dwm.suckless.org/patches/autoresize/dwm-autoresize-6.1.diff diff --git a/dwm.suckless.org/patches/autoresize.md b/dwm.suckless.org/patches/autoresize/index.md diff --git a/dwm.suckless.org/patches/dwm-autostart-20161205-bb3bd6f.diff b/dwm.suckless.org/patches/autostart/dwm-autostart-20161205-bb3bd6f.diff diff --git a/dwm.suckless.org/patches/autostart.md b/dwm.suckless.org/patches/autostart/index.md diff --git a/dwm.suckless.org/patches/dwm-bottomstack-20160719-56a31dc.diff b/dwm.suckless.org/patches/bottomstack/dwm-bottomstack-20160719-56a31dc.diff diff --git a/dwm.suckless.org/patches/dwm-bottomstack-6.1.diff b/dwm.suckless.org/patches/bottomstack/dwm-bottomstack-6.1.diff diff --git a/dwm.suckless.org/patches/bottomstack.md b/dwm.suckless.org/patches/bottomstack/index.md diff --git a/dwm.suckless.org/patches/dwm-center-20160719-56a31dc.diff b/dwm.suckless.org/patches/center/dwm-center-20160719-56a31dc.diff diff --git a/dwm.suckless.org/patches/dwm-center-6.1.diff b/dwm.suckless.org/patches/center/dwm-center-6.1.diff diff --git a/dwm.suckless.org/patches/center.md b/dwm.suckless.org/patches/center/index.md diff --git a/dwm.suckless.org/patches/dwm-centeredmaster-20160719-56a31dc.diff b/dwm.suckless.org/patches/centeredmaster/dwm-centeredmaster-20160719-56a31dc.diff diff --git a/dwm.suckless.org/patches/dwm-centeredmaster-6.1.diff b/dwm.suckless.org/patches/centeredmaster/dwm-centeredmaster-6.1.diff diff --git a/dwm.suckless.org/patches/centeredmaster.md b/dwm.suckless.org/patches/centeredmaster/index.md diff --git a/dwm.suckless.org/patches/cfacts.md b/dwm.suckless.org/patches/cfacts.md @@ -1,56 +0,0 @@ -cfacts -====== - -Description ------------ - -This patch provides the ability to assign different weights to -clients in their respective stack in tiled layout. It implements -a new function setcfact which will modify the cfact-value for the -currently selected client. It accepts the following values: - -* A positive float to increase a clients weight, thus increasing - the space the client is allocated in its current stack. - -* A negative float to decrease a clients weight, thus decreasing - the space the client is allocated in its current stack. - -* A zero-value float to reset a clients weight to default. - -Default cfact-value for each client is 1.0. If a client is -assigned a cfact value of 0.5 it will be allocated half of the -space other clients would be allocated. If a client is assigned a -cfact value of 2.0 it will be allocated twice the space other -clients would be allocated. - -The following illustrates the behavior. The clients cfact-values -are represented by floats inside the clients rectangles. - - +---------------------+ - | | 0.5 | - | 1.0 +----------+ - +----------+ | - | | 1.0 | - | +----------+ - | 2.0 | | - | | 1.0 | - +----------+----------+ - -Default key bindings --------------------- - - Key | Argument | Description -:---------:|:----------:|:---------------- - `Mod-H` | `+0.25` | Increase cfact - `Mod-L` | `-0.25` | Decrease cfact - `Mod-O` | ` 0.00` | Reset cfact - -Download --------- - -* [dwm-6.1-cfacts.diff](dwm-6.1-cfacts.diff) - -Author ------- - -* Patrick Steinhardt (pks) <ps@pks.im> diff --git a/dwm.suckless.org/patches/dwm-6.1-cfacts.diff b/dwm.suckless.org/patches/cfacts/dwm-cfacts-6.1.diff diff --git a/dwm.suckless.org/patches/cfacts/index.md b/dwm.suckless.org/patches/cfacts/index.md @@ -0,0 +1,56 @@ +cfacts +====== + +Description +----------- + +This patch provides the ability to assign different weights to +clients in their respective stack in tiled layout. It implements +a new function setcfact which will modify the cfact-value for the +currently selected client. It accepts the following values: + +* A positive float to increase a clients weight, thus increasing + the space the client is allocated in its current stack. + +* A negative float to decrease a clients weight, thus decreasing + the space the client is allocated in its current stack. + +* A zero-value float to reset a clients weight to default. + +Default cfact-value for each client is 1.0. If a client is +assigned a cfact value of 0.5 it will be allocated half of the +space other clients would be allocated. If a client is assigned a +cfact value of 2.0 it will be allocated twice the space other +clients would be allocated. + +The following illustrates the behavior. The clients cfact-values +are represented by floats inside the clients rectangles. + + +---------------------+ + | | 0.5 | + | 1.0 +----------+ + +----------+ | + | | 1.0 | + | +----------+ + | 2.0 | | + | | 1.0 | + +----------+----------+ + +Default key bindings +-------------------- + + Key | Argument | Description +:---------:|:----------:|:---------------- + `Mod-H` | `+0.25` | Increase cfact + `Mod-L` | `-0.25` | Decrease cfact + `Mod-O` | ` 0.00` | Reset cfact + +Download +-------- + +* [dwm-cfacts-6.1.diff](dwm-cfacts-6.1.diff) + +Author +------ + +* Patrick Steinhardt (pks) <ps@pks.im> diff --git a/dwm.suckless.org/patches/dwm-clientspertag-5.6.1.diff b/dwm.suckless.org/patches/clientspertag/dwm-clientspertag-5.6.1.diff diff --git a/dwm.suckless.org/patches/clientspertag.md b/dwm.suckless.org/patches/clientspertag/index.md diff --git a/dwm.suckless.org/patches/dwm-columns-6.0.diff b/dwm.suckless.org/patches/columns/dwm-columns-6.0.diff diff --git a/dwm.suckless.org/patches/columns.md b/dwm.suckless.org/patches/columns/index.md diff --git a/dwm.suckless.org/patches/dwm-combo-5.9.diff b/dwm.suckless.org/patches/combo/dwm-combo-5.9.diff diff --git a/dwm.suckless.org/patches/dwm-combo-6.0.diff b/dwm.suckless.org/patches/combo/dwm-combo-6.0.diff diff --git a/dwm.suckless.org/patches/dwm-combo-6.1.diff b/dwm.suckless.org/patches/combo/dwm-combo-6.1.diff diff --git a/dwm.suckless.org/patches/combo.md b/dwm.suckless.org/patches/combo/index.md diff --git a/dwm.suckless.org/patches/dwm-cropwindows-20170709-ceac8c9.diff b/dwm.suckless.org/patches/cropwindows/dwm-cropwindows-20170709-ceac8c9.diff diff --git a/dwm.suckless.org/patches/cropwindows.md b/dwm.suckless.org/patches/cropwindows/index.md diff --git a/dwm.suckless.org/patches/dwm-current_desktop-5.8.2.diff b/dwm.suckless.org/patches/current_desktop/dwm-current_desktop-5.8.2.diff diff --git a/dwm.suckless.org/patches/current_desktop.md b/dwm.suckless.org/patches/current_desktop/index.md diff --git a/dwm.suckless.org/patches/deck.md b/dwm.suckless.org/patches/deck.md @@ -1,40 +0,0 @@ -deck layout -=========== - -Description ------------ -`deck` is a new layout for DWM (inspired by the TTWM window manager). It is like tile(), but with monocle in the stack. You have a master client (complete with nmaster et all), but the stack clients now overlap one another as in monocle(). (The stacked clients are like a deck of cards, hence the name). - - - Tile : - +-----------------+--------+ - | | | - | | S1 | - | | | - | M +--------+ - | | | - | | S2 | - | | | - +-----------------+--------+ - - - Deck : - +-----------------+--------+ - | | | - | | | - | | | - | M | S1 | - | | | - | | | - | | | - +-----------------+--------+ - -Download --------- -* [dwm-6.0-deck.diff](dwm-6.0-deck.diff) -* [dwm-deck-20170909-ceac8c9.diff](dwm-deck-20170909-ceac8c9.diff) - - -Author ------- -* Jente Hidskes - `<jthidskes at outlook dot com>` diff --git a/dwm.suckless.org/patches/dwm-deck-20170909-ceac8c9.diff b/dwm.suckless.org/patches/deck/dwm-deck-20170909-ceac8c9.diff diff --git a/dwm.suckless.org/patches/dwm-6.0-deck.diff b/dwm.suckless.org/patches/deck/dwm-deck-6.0.diff diff --git a/dwm.suckless.org/patches/deck/index.md b/dwm.suckless.org/patches/deck/index.md @@ -0,0 +1,40 @@ +deck layout +=========== + +Description +----------- +`deck` is a new layout for DWM (inspired by the TTWM window manager). It is like tile(), but with monocle in the stack. You have a master client (complete with nmaster et all), but the stack clients now overlap one another as in monocle(). (The stacked clients are like a deck of cards, hence the name). + + + Tile : + +-----------------+--------+ + | | | + | | S1 | + | | | + | M +--------+ + | | | + | | S2 | + | | | + +-----------------+--------+ + + + Deck : + +-----------------+--------+ + | | | + | | | + | | | + | M | S1 | + | | | + | | | + | | | + +-----------------+--------+ + +Download +-------- +* [dwm-deck-6.0.diff](dwm-deck-6.0.diff) +* [dwm-deck-20170909-ceac8c9.diff](dwm-deck-20170909-ceac8c9.diff) + + +Author +------ +* Jente Hidskes - `<jthidskes at outlook dot com>` diff --git a/dwm.suckless.org/patches/defaulttransparency.md b/dwm.suckless.org/patches/defaulttransparency.md @@ -1,24 +0,0 @@ -# defaulttransparency - -## Description - -This patch adds a default transparency parameter to config.h, which specifies the -transparency, all windows are started with. - -Additionally it adds some shortcuts: - - * MOD + Shift + s -> decrease transparency of current focused window - * MOD + Shift + d -> increase transparency of current focused window - * MOD + Shift + f -> set window to default opacity (.75) - -It is based on the transparency patch of Stefan Mark. - -## Download - - * [dwm.defaultopacity.patch](//dwm.suckless.org/patches/dwm.defaultopacity.patch) - latest patch (against r1521) - -## Author - - * Christoph Lohmann - <20h@r-36.net> - diff --git a/dwm.suckless.org/patches/dwm.defaultopacity.patch b/dwm.suckless.org/patches/defaulttransparency/dwm-defaulttransparency-r1521.diff diff --git a/dwm.suckless.org/patches/defaulttransparency/index.md b/dwm.suckless.org/patches/defaulttransparency/index.md @@ -0,0 +1,24 @@ +# defaulttransparency + +## Description + +This patch adds a default transparency parameter to config.h, which specifies the +transparency, all windows are started with. + +Additionally it adds some shortcuts: + + * MOD + Shift + s -> decrease transparency of current focused window + * MOD + Shift + d -> increase transparency of current focused window + * MOD + Shift + f -> set window to default opacity (.75) + +It is based on the transparency patch of Stefan Mark. + +## Download + + * [dwm-defaulttransparency-r1521.diff](dwm-defaulttransparency-r1521.diff) + latest patch (against r1521) + +## Author + + * Christoph Lohmann - <20h@r-36.net> + diff --git a/dwm.suckless.org/patches/dwm-dualstatus-6.0.diff b/dwm.suckless.org/patches/dualstatus/dwm-dualstatus-6.0.diff diff --git a/dwm.suckless.org/patches/dwm-dualstatus-6.1.diff b/dwm.suckless.org/patches/dualstatus/dwm-dualstatus-6.1.diff diff --git a/dwm.suckless.org/patches/dwm-dualstatus.png b/dwm.suckless.org/patches/dualstatus/dwm-dualstatus.png Binary files differ. diff --git a/dwm.suckless.org/patches/dualstatus.md b/dwm.suckless.org/patches/dualstatus/index.md diff --git a/dwm.suckless.org/patches/dwm-dwmfifo-6.1.diff b/dwm.suckless.org/patches/dwmfifo/dwm-dwmfifo-6.1.diff diff --git a/dwm.suckless.org/patches/dwmfifo.md b/dwm.suckless.org/patches/dwmfifo/index.md diff --git a/dwm.suckless.org/patches/dwm-emptyview-6.0.diff b/dwm.suckless.org/patches/emptyview/dwm-emptyview-6.0.diff diff --git a/dwm.suckless.org/patches/emptyview.md b/dwm.suckless.org/patches/emptyview/index.md diff --git a/dwm.suckless.org/patches/exresize.md b/dwm.suckless.org/patches/exresize.md @@ -1,26 +0,0 @@ -exresize -======== - -Description ------------ - -This allows the user to change size and placement of floating windows using only -the keyboard. It also allows for temporary vertical and horizontal extension of -windows similar to other WMs fill command. This patch is inspired by -[maximize](//dwm.suckless.org/patches/maximize) and -[moveresize](//dwm.suckless.org/patches/moveresize) but fixes a lot of -problems I had with those patches. It also includes the functionality of -[save floats](//dwm.suckless.org/patches/save_floats) judging by it's -description. - -Download --------- - -<!-- This patch used to say (20121117), but it doesn't build against commits - from that date. Author emailed. --> - * [dwm-r1606-exresize.diff](dwm-r1606-exresize.diff) (Old patch, unknown version) - -Authors -------- - - * Krister Svanlund - `<krister.svanlund@gmail.com>` diff --git a/dwm.suckless.org/patches/dwm-r1606-exresize.diff b/dwm.suckless.org/patches/exresize/dwm-exresize-r1606.diff diff --git a/dwm.suckless.org/patches/exresize/index.md b/dwm.suckless.org/patches/exresize/index.md @@ -0,0 +1,26 @@ +exresize +======== + +Description +----------- + +This allows the user to change size and placement of floating windows using only +the keyboard. It also allows for temporary vertical and horizontal extension of +windows similar to other WMs fill command. This patch is inspired by +[maximize](//dwm.suckless.org/patches/maximize) and +[moveresize](//dwm.suckless.org/patches/moveresize) but fixes a lot of +problems I had with those patches. It also includes the functionality of +[save floats](//dwm.suckless.org/patches/save_floats) judging by it's +description. + +Download +-------- + +<!-- This patch used to say (20121117), but it doesn't build against commits + from that date. Author emailed. --> + * [dwm-exresize-r1606.diff](dwm-exresize-r1606.diff) (Old patch, unknown version) + +Authors +------- + + * Krister Svanlund - `<krister.svanlund@gmail.com>` diff --git a/dwm.suckless.org/patches/dwm-fakefullscreen-20170508-ceac8c9.diff b/dwm.suckless.org/patches/fakefullscreen/dwm-fakefullscreen-20170508-ceac8c9.diff diff --git a/dwm.suckless.org/patches/fakefullscreen.md b/dwm.suckless.org/patches/fakefullscreen/index.md diff --git a/dwm.suckless.org/patches/fancybar.md b/dwm.suckless.org/patches/fancybar.md @@ -1,26 +0,0 @@ -# fancybar - -## Description - -This patch provides a status bar that shows the titles of all visible windows -(as opposed to showing just the selected one). When the titles don't completely -fit, they're cropped. The title of the selected window is inverted. - -[![Fancybar][1]][1] - -*Fancybar in action* - -## Download - - * [dwm-fancybar-5.6.1.diff](historical/dwm-fancybar-5.6.1.diff) - * [dwm-fancybar-6.1.diff](dwm-fancybar-6.1.diff) - * [dwm-fancybar-git-20160725-7af4d43.diff](dwm-fancybar-git-20160725-7af4d43.diff) - -## Author - - * Mate Nagy - <mnagy@port70.net> - * [Jochen Sprickerhof](mailto:project@firstname.lastname.de) (rewrite) - -This patch was inspired by the decorated tabbed layout of Xmonad. - -[1]: http://s27.postimg.org/nvlkivn03/2015_10_14_132203_727x15_scrot.png diff --git a/dwm.suckless.org/patches/fancybar/dwm-fancybar-5.6.1.diff b/dwm.suckless.org/patches/fancybar/dwm-fancybar-5.6.1.diff @@ -0,0 +1,121 @@ +diff -r e47a47bd3ed4 dwm.c +--- a/dwm.c Tue Jul 21 10:57:54 2009 +0100 ++++ b/dwm.c Mon Aug 24 18:28:57 2009 +0200 +@@ -169,6 +169,7 @@ + static Monitor *dirtomon(int dir); + static void drawbar(Monitor *m); + static void drawbars(void); ++static void drawvline(unsigned long col[ColLast]); + static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]); + static void drawtext(const char *text, unsigned long col[ColLast], Bool invert); + static void enternotify(XEvent *e); +@@ -648,10 +649,11 @@ + + void + drawbar(Monitor *m) { +- int x; ++ int x, ow, mw = 0, extra, tw; + unsigned int i, n = 0, occ = 0, urg = 0; + unsigned long *col; +- Client *c; ++ Client *c, *firstvis, *lastvis = NULL; ++ DC seldc; + + for(c = m->clients; c; c = c->next) { + if(ISVISIBLE(c)) +@@ -689,16 +691,62 @@ + } + else + dc.x = m->ww; +- if((dc.w = dc.x - x) > bh) { +- dc.x = x; +- if(m->sel) { +- col = m == selmon ? dc.sel : dc.norm; +- drawtext(m->sel->name, col, False); +- drawsquare(m->sel->isfixed, m->sel->isfloating, False, col); ++ ++ for(c = m->clients; c && !ISVISIBLE(c); c = c->next); ++ firstvis = c; ++ ++ col = m == selmon ? dc.sel : dc.norm; ++ dc.w = dc.x - x; ++ dc.x = x; ++ ++ if(n > 0) { ++ mw = dc.w / n; ++ extra = 0; ++ seldc = dc; ++ i = 0; ++ ++ while(c) { ++ lastvis = c; ++ tw = TEXTW(c->name); ++ if(tw < mw) extra += (mw - tw); else i++; ++ for(c = c->next; c && !ISVISIBLE(c); c = c->next); + } +- else ++ ++ if(i > 0) mw += extra / i; ++ ++ c = firstvis; ++ x = dc.x; ++ } ++ ++ while(dc.w > bh) { ++ if(c) { ++ ow = dc.w; ++ tw = TEXTW(c->name); ++ dc.w = MIN(ow, tw); ++ ++ if(dc.w > mw) dc.w = mw; ++ if(m->sel == c) seldc = dc; ++ if(c == lastvis) dc.w = ow; ++ ++ drawtext(c->name, col, False); ++ if(c != firstvis) drawvline(col); ++ drawsquare(c->isfixed, c->isfloating, False, col); ++ ++ dc.x += dc.w; ++ dc.w = ow - dc.w; ++ for(c = c->next; c && !ISVISIBLE(c); c = c->next); ++ } else { + drawtext(NULL, dc.norm, False); ++ break; ++ } + } ++ ++ if(m == selmon && m->sel && ISVISIBLE(m->sel)) { ++ dc = seldc; ++ drawtext(m->sel->name, col, True); ++ drawsquare(m->sel->isfixed, m->sel->isfloating, True, col); ++ } ++ + XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->ww, bh, 0, 0); + XSync(dpy, False); + } +@@ -709,6 +757,15 @@ + + for(m = mons; m; m = m->next) + drawbar(m); ++} ++ ++void ++drawvline(unsigned long col[ColLast]) { ++ XGCValues gcv; ++ ++ gcv.foreground = col[ColFG]; ++ XChangeGC(dpy, dc.gc, GCForeground, &gcv); ++ XDrawLine(dpy, dc.drawable, dc.gc, dc.x, dc.y, dc.x, dc.y + (dc.font.ascent + dc.font.descent + 2)); + } + + void +@@ -1235,8 +1292,7 @@ + } + if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { + updatetitle(c); +- if(c == selmon->sel) +- drawbars(); ++ drawbars(); + } + } + } diff --git a/dwm.suckless.org/patches/dwm-fancybar-6.1.diff b/dwm.suckless.org/patches/fancybar/dwm-fancybar-6.1.diff diff --git a/dwm.suckless.org/patches/dwm-fancybar-git-20160725-7af4d43.diff b/dwm.suckless.org/patches/fancybar/dwm-fancybar-git-20160725-7af4d43.diff diff --git a/dwm.suckless.org/patches/dwm-6.1-winview.diff b/dwm.suckless.org/patches/fancybar/fancybar.png diff --git a/dwm.suckless.org/patches/fancybar/index.md b/dwm.suckless.org/patches/fancybar/index.md @@ -0,0 +1,24 @@ +# fancybar + +## Description + +This patch provides a status bar that shows the titles of all visible windows +(as opposed to showing just the selected one). When the titles don't completely +fit, they're cropped. The title of the selected window is inverted. + +[![Screenshot][fancybar.png]][fancybar.png] + +*Fancybar in action* + +## Download + + * [dwm-fancybar-5.6.1.diff](dwm-fancybar-5.6.1.diff) + * [dwm-fancybar-6.1.diff](dwm-fancybar-6.1.diff) + * [dwm-fancybar-git-20160725-7af4d43.diff](dwm-fancybar-git-20160725-7af4d43.diff) + +## Author + + * Mate Nagy - <mnagy@port70.net> + * [Jochen Sprickerhof](mailto:project@firstname.lastname.de) (rewrite) + +This patch was inspired by the decorated tabbed layout of Xmonad. diff --git a/dwm.suckless.org/patches/fancybarclickable.md b/dwm.suckless.org/patches/fancybarclickable.md @@ -1,24 +0,0 @@ -fancybarclickable -================= - -Description ------------ -`fancybarclickable` is basically [fancycoloredbarclickable](fancycoloredbarclickable) -minus the [statuscolors](statuscolors). It uses the dwm bar to show you the -titles of all the windows in the current tag and lets you select windows by -selecting their title in the dwm bar. - -[![Fancybarclickable][1]][1] - -Download --------- -* [dwm-6.1-fancybarclickable.diff](dwm-6.1-fancybarclickable.diff) (Unclean patch) - -Authors -------- -* Stefan Mark wrote [fancycoloredbarclickable](fancycoloredbarclickable.md). -* Mate Nagy wrote [fancybar](fancybar.md). -* An anonymous Canadian updated the fancybar patch and added the - `selectby-click-on-title` function from fancycoloredbarclickable to it. - -[1]: http://s4.postimg.org/ql2f934wd/fancybar.png diff --git a/dwm.suckless.org/patches/dwm-6.1-fancybarclickable.diff b/dwm.suckless.org/patches/fancybarclickable/dwm-fancybarclickable-6.1.diff diff --git a/dwm.suckless.org/patches/fancybarclickable/fancybarclickable.png b/dwm.suckless.org/patches/fancybarclickable/fancybarclickable.png Binary files differ. diff --git a/dwm.suckless.org/patches/fancybarclickable/index.md b/dwm.suckless.org/patches/fancybarclickable/index.md @@ -0,0 +1,21 @@ +fancybarclickable +================= + +Description +----------- +`fancybarclickable` is basically [fancycoloredbarclickable](fancycoloredbarclickable) +minus the [statuscolors](statuscolors). It uses the dwm bar to show you the +titles of all the windows in the current tag and lets you select windows by +selecting their title in the dwm bar. + +[![Screenshot][fancybarclickable.png]][fancybarclickable.png] + +Download +-------- +* [dwm-fancybarclickable-6.1.diff](dwm-fancybarclickable-6.1.diff) (Unclean patch) + +Authors +------- +* Mate Nagy wrote [fancybar](../fancybar/). +* An anonymous Canadian updated the fancybar patch and added the + `selectby-click-on-title` function from fancycoloredbarclickable to it. diff --git a/dwm.suckless.org/patches/fancycoloredbarclickable.md b/dwm.suckless.org/patches/fancycoloredbarclickable.md @@ -1,33 +0,0 @@ -fancycoloredbarclickable -======================== - -Description ------------ -`fancycoloredbarclickable` provides colors in the status area, shows the -titles of all visible clients, and provides a function to select a client by -clicking on its title. - -This patch combines [fancybar](fancybar) and [statuscolors](statuscolors) with -the additional `selectby-click-on-title` function. - -The fancybar patch used is rather new and unchanged, while the statuscolor -patch is older and modified. The original statuscolor patch made gaps after -changing the color and used its own color definition everywhere. This modified -version creates no gaps and the default color definition is used everywhere -but in the status area. - -[dwmd][2] is an extensible status script with color support. - -Download --------- -* [dwm-fancycoloredbarclickable.diff][1] - -Gluer ------ -...for this is a patch of patches; I'm not really the author, but the one who -glued things together. ;) - -* Stefan Mark - <0mark@unserver.de> - -[1]: https://svn.0mark.unserver.de/dwm/trunk/patches/dwm-fancycoloredbarclickable.diff -[2]: http://0mark.unserver.de/dwmd diff --git a/dwm.suckless.org/patches/dwm-fibonacci-5.8.2.diff b/dwm.suckless.org/patches/fibonacci/dwm-fibonacci-5.8.2.diff diff --git a/dwm.suckless.org/patches/fibonacci.md b/dwm.suckless.org/patches/fibonacci/index.md diff --git a/dwm.suckless.org/patches/flextile/dwm-flextile-5.8.1.diff b/dwm.suckless.org/patches/flextile/dwm-flextile-5.8.1.diff @@ -0,0 +1,418 @@ +diff -up ../dwm-5.8.1-0/config.def.h ./config.def.h +--- ../dwm-5.8.1-0/config.def.h 2010-05-29 13:49:12.000000000 +0200 ++++ ./config.def.h 2010-05-31 15:18:43.686311000 +0200 +@@ -25,6 +25,11 @@ static const Rule rules[] = { + /* layout(s) */ + static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ + static const Bool resizehints = True; /* True means respect size hints in tiled resizals */ ++static const int layoutaxis[] = { ++ 1, /* layout axis: 1 = x, 2 = y; negative values mirror the layout, setting the master area to the right / bottom instead of left / top */ ++ 2, /* master axis: 1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle) */ ++ 2, /* stack axis: 1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle) */ ++}; + + static const Layout layouts[] = { + /* symbol arrange function */ +@@ -81,6 +86,12 @@ static Key keys[] = { + TAGKEYS( XK_8, 7) + TAGKEYS( XK_9, 8) + { MODKEY|ShiftMask, XK_q, quit, {0} }, ++ { MODKEY|ControlMask, XK_t, rotatelayoutaxis, {.i = 0} }, /* 0 = layout axis */ ++ { MODKEY|ControlMask, XK_Tab, rotatelayoutaxis, {.i = 1} }, /* 1 = master axis */ ++ { MODKEY|ControlMask|ShiftMask, XK_Tab, rotatelayoutaxis, {.i = 2} }, /* 2 = stack axis */ ++ { MODKEY|ControlMask, XK_Return, mirrorlayout, {0} }, ++ { MODKEY|ControlMask, XK_j, shiftmastersplit, {.i = -1} }, /* reduce the number of tiled clients in the master area */ ++ { MODKEY|ControlMask, XK_k, shiftmastersplit, {.i = +1} }, /* increase the number of tiled clients in the master area */ + }; + + /* button definitions */ +diff -up ../dwm-5.8.1-0/dwm.c ./dwm.c +--- ../dwm-5.8.1-0/dwm.c 2010-05-29 13:49:12.000000000 +0200 ++++ ./dwm.c 2010-05-31 16:02:14.553316000 +0200 +@@ -120,26 +120,6 @@ typedef struct { + void (*arrange)(Monitor *); + } Layout; + +-struct Monitor { +- char ltsymbol[16]; +- float mfact; +- int num; +- int by; /* bar geometry */ +- int mx, my, mw, mh; /* screen size */ +- int wx, wy, ww, wh; /* window area */ +- unsigned int seltags; +- unsigned int sellt; +- unsigned int tagset[2]; +- Bool showbar; +- Bool topbar; +- Client *clients; +- Client *sel; +- Client *stack; +- Monitor *next; +- Window barwin; +- const Layout *lt[2]; +-}; +- + typedef struct { + const char *class; + const char *instance; +@@ -193,6 +173,7 @@ 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 mirrorlayout(const Arg *arg); + static void monocle(Monitor *m); + static void movemouse(const Arg *arg); + static Client *nexttiled(Client *c); +@@ -202,6 +183,7 @@ static void quit(const Arg *arg); + static void resize(Client *c, int x, int y, int w, int h, Bool interact); + static void resizemouse(const Arg *arg); + static void restack(Monitor *m); ++static void rotatelayoutaxis(const Arg *arg); + static void run(void); + static void scan(void); + static void sendmon(Client *c, Monitor *m); +@@ -209,6 +191,7 @@ static void setclientstate(Client *c, lo + static void setlayout(const Arg *arg); + static void setmfact(const Arg *arg); + static void setup(void); ++static void shiftmastersplit(const Arg *arg); + static void showhide(Client *c); + static void sigchld(int unused); + static void spawn(const Arg *arg); +@@ -275,6 +258,34 @@ static Window root; + + /* compile-time check if all tags fit into an unsigned int bit array. */ + struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; ++struct Monitor { ++ char ltsymbol[16]; ++ float mfact; ++ double mfacts[LENGTH(tags) + 1]; ++ int ltaxis[3]; ++ int ltaxes[LENGTH(tags) + 1][3]; ++ int num; ++ int curtag; ++ int prevtag; ++ int by; /* bar geometry */ ++ int mx, my, mw, mh; /* screen size */ ++ int wx, wy, ww, wh; /* window area */ ++ unsigned int msplit; ++ unsigned int msplits[LENGTH(tags) + 1]; ++ unsigned int seltags; ++ unsigned int sellt; ++ unsigned int tagset[2]; ++ Bool showbar; ++ Bool showbars[LENGTH(tags) + 1]; ++ Bool topbar; ++ Client *clients; ++ Client *sel; ++ Client *stack; ++ Monitor *next; ++ Window barwin; ++ const Layout *lt[2]; ++ const Layout *lts[LENGTH(tags) + 1]; ++}; + + /* function implementations */ + void +@@ -616,6 +627,10 @@ createmon(void) { + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); ++ m->ltaxis[0] = layoutaxis[0]; ++ m->ltaxis[1] = layoutaxis[1]; ++ m->ltaxis[2] = layoutaxis[2]; ++ m->msplit = 1; + return m; + } + +@@ -1173,6 +1188,15 @@ maprequest(XEvent *e) { + } + + void ++mirrorlayout(const Arg *arg) { ++ if(!selmon->lt[selmon->sellt]->arrange) ++ return; ++ selmon->ltaxis[0] *= -1; ++ selmon->ltaxes[selmon->curtag][0] = selmon->ltaxis[0]; ++ arrange(selmon); ++} ++ ++void + monocle(Monitor *m) { + unsigned int n = 0; + Client *c; +@@ -1387,6 +1411,21 @@ restack(Monitor *m) { + } + + void ++rotatelayoutaxis(const Arg *arg) { ++ if(!selmon->lt[selmon->sellt]->arrange) ++ return; ++ if(arg->i == 0) { ++ if(selmon->ltaxis[0] > 0) ++ selmon->ltaxis[0] = selmon->ltaxis[0] + 1 > 2 ? 1 : selmon->ltaxis[0] + 1; ++ else ++ selmon->ltaxis[0] = selmon->ltaxis[0] - 1 < -2 ? -1 : selmon->ltaxis[0] - 1; ++ } else ++ selmon->ltaxis[arg->i] = selmon->ltaxis[arg->i] + 1 > 3 ? 1 : selmon->ltaxis[arg->i] + 1; ++ selmon->ltaxes[selmon->curtag][arg->i] = selmon->ltaxis[arg->i]; ++ arrange(selmon); ++} ++ ++void + run(void) { + XEvent ev; + /* main event loop */ +@@ -1451,7 +1490,7 @@ 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; ++ selmon->lt[selmon->sellt] = selmon->lts[selmon->curtag] = (Layout *)arg->v; + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); + if(selmon->sel) + arrange(selmon); +@@ -1469,14 +1508,16 @@ setmfact(const Arg *arg) { + f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; + if(f < 0.1 || f > 0.9) + return; +- selmon->mfact = f; ++ selmon->mfact = selmon->mfacts[selmon->curtag] = f; + arrange(selmon); + } + + void + setup(void) { + XSetWindowAttributes wa; +- ++ Monitor *m; ++ unsigned int i; ++ + /* clean up any zombies immediately */ + sigchld(0); + +@@ -1511,7 +1552,19 @@ setup(void) { + XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); + if(!dc.font.set) + XSetFont(dpy, dc.gc, dc.font.xfont->fid); +- /* init bars */ ++ /* init tags, bars, layouts, axes, msplits and mfacts */ ++ for(m = mons; m; m = m->next) { ++ m->curtag = m->prevtag = 1; ++ for(i=0; i < LENGTH(tags) + 1; i++) { ++ m->showbars[i] = m->showbar; ++ m->lts[i] = &layouts[0]; ++ m->mfacts[i] = m->mfact; ++ m->ltaxes[i][0] = m->ltaxis[0]; ++ m->ltaxes[i][1] = m->ltaxis[1]; ++ m->ltaxes[i][2] = m->ltaxis[2]; ++ m->msplits[i] = m->msplit; ++ } ++ } + updatebars(); + updatestatus(); + /* EWMH support per view */ +@@ -1528,6 +1581,19 @@ setup(void) { + } + + void ++shiftmastersplit(const Arg *arg) { ++ unsigned int n; ++ Client *c; ++ ++ for(n = 0, c = nexttiled(selmon->clients); c; c = nexttiled(c->next), n++); ++ if(!arg || !selmon->lt[selmon->sellt]->arrange || selmon->msplit + arg->i < 1 || selmon->msplit + arg->i > n) ++ return; ++ selmon->msplit += arg->i; ++ selmon->msplits[selmon->curtag] = selmon->msplit; ++ arrange(selmon); ++} ++ ++void + showhide(Client *c) { + if(!c) + return; +@@ -1592,37 +1658,95 @@ textnw(const char *text, unsigned int le + + void + tile(Monitor *m) { +- int x, y, h, w, mw; +- unsigned int i, n; ++ char sym1 = 61, sym2 = 93, sym3 = 61, sym; ++ int x1 = m->wx, y1 = m->wy, h1 = m->wh, w1 = m->ww, X1 = x1 + w1, Y1 = y1 + h1; ++ int x2 = m->wx, y2 = m->wy, h2 = m->wh, w2 = m->ww, X2 = x2 + w2, Y2 = y2 + h2; ++ unsigned int i, n, n1, n2; + Client *c; + + for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); ++ if(m->msplit > n) ++ m->msplit = (n == 0) ? 1 : n; ++ if(n == 0 && m->ltaxis[1] != 3) ++ return; ++ /* layout symbol */ ++ if(abs(m->ltaxis[0]) == m->ltaxis[1]) /* explicitly: ((abs(m->ltaxis[0]) == 1 && m->ltaxis[1] == 1) || (abs(m->ltaxis[0]) == 2 && m->ltaxis[1] == 2)) */ ++ sym1 = 124; ++ if(abs(m->ltaxis[0]) == m->ltaxis[2]) ++ sym3 = 124; ++ if(m->ltaxis[1] == 3) ++ sym1 = (n == 0) ? 0 : m->msplit; ++ if(m->ltaxis[2] == 3) ++ sym3 = (n == 0) ? 0 : n - m->msplit; ++ if(m->ltaxis[0] < 0) { ++ sym = sym1; ++ sym1 = sym3; ++ sym2 = 91; ++ sym3 = sym; ++ } ++ if(m->msplit == 1) { ++ if(m->ltaxis[0] > 0) ++ sym1 = 91; ++ else ++ sym3 = 93; ++ } ++ if(m->msplit > 1 && m->ltaxis[1] == 3 && m->ltaxis[2] == 3) ++ snprintf(m->ltsymbol, sizeof m->ltsymbol, "%d%c%d", sym1, sym2, sym3); ++ else if((m->msplit > 1 && m->ltaxis[1] == 3 && m->ltaxis[0] > 0) || (m->ltaxis[2] == 3 && m->ltaxis[0] < 0)) ++ snprintf(m->ltsymbol, sizeof m->ltsymbol, "%d%c%c", sym1, sym2, sym3); ++ else if((m->ltaxis[2] == 3 && m->ltaxis[0] > 0) || (m->msplit > 1 && m->ltaxis[1] == 3 && m->ltaxis[0] < 0)) ++ snprintf(m->ltsymbol, sizeof m->ltsymbol, "%c%c%d", sym1, sym2, sym3); ++ else ++ snprintf(m->ltsymbol, sizeof m->ltsymbol, "%c%c%c", sym1, sym2, sym3); + if(n == 0) + return; ++ /* master and stack area */ ++ if(abs(m->ltaxis[0]) == 1 && n > m->msplit) { ++ w1 *= m->mfact; ++ w2 -= w1; ++ x1 += (m->ltaxis[0] < 0) ? w2 : 0; ++ x2 += (m->ltaxis[0] < 0) ? 0 : w1; ++ X1 = x1 + w1; ++ X2 = x2 + w2; ++ } else if(abs(m->ltaxis[0]) == 2 && n > m->msplit) { ++ h1 *= m->mfact; ++ h2 -= h1; ++ y1 += (m->ltaxis[0] < 0) ? h2 : 0; ++ y2 += (m->ltaxis[0] < 0) ? 0 : h1; ++ Y1 = y1 + h1; ++ Y2 = y2 + h2; ++ } + /* master */ +- c = nexttiled(m->clients); +- mw = m->mfact * m->ww; +- resize(c, m->wx, m->wy, (n == 1 ? m->ww : mw) - 2 * c->bw, m->wh - 2 * c->bw, False); +- if(--n == 0) +- return; +- /* tile stack */ +- x = (m->wx + mw > c->x + c->w) ? c->x + c->w + 2 * c->bw : m->wx + mw; +- y = m->wy; +- w = (m->wx + mw > c->x + c->w) ? m->wx + m->ww - x : m->ww - mw; +- h = m->wh / n; +- if(h < bh) +- h = m->wh; +- for(i = 0, c = nexttiled(c->next); c; c = nexttiled(c->next), i++) { +- resize(c, x, y, w - 2 * c->bw, /* remainder */ ((i + 1 == n) +- ? m->wy + m->wh - y - 2 * c->bw : h - 2 * c->bw), False); +- if(h != m->wh) +- y = c->y + HEIGHT(c); ++ n1 = (m->ltaxis[1] != 1 || w1 / m->msplit < bh) ? 1 : m->msplit; ++ n2 = (m->ltaxis[1] != 2 || h1 / m->msplit < bh) ? 1 : m->msplit; ++ for(i = 0, c = nexttiled(m->clients); i < m->msplit; c = nexttiled(c->next), i++) { ++ resize(c, x1, y1, ++ (m->ltaxis[1] == 1 && i + 1 == m->msplit) ? X1 - x1 - 2 * c->bw : w1 / n1 - 2 * c->bw, ++ (m->ltaxis[1] == 2 && i + 1 == m->msplit) ? Y1 - y1 - 2 * c->bw : h1 / n2 - 2 * c->bw, False); ++ if(n1 > 1) ++ x1 = c->x + WIDTH(c); ++ if(n2 > 1) ++ y1 = c->y + HEIGHT(c); ++ } ++ /* stack */ ++ if(n > m->msplit) { ++ n1 = (m->ltaxis[2] != 1 || w2 / (n - m->msplit) < bh) ? 1 : n - m->msplit; ++ n2 = (m->ltaxis[2] != 2 || h2 / (n - m->msplit) < bh) ? 1 : n - m->msplit; ++ for(i = 0; c; c = nexttiled(c->next), i++) { ++ resize(c, x2, y2, ++ (m->ltaxis[2] == 1 && i + 1 == n - m->msplit) ? X2 - x2 - 2 * c->bw : w2 / n1 - 2 * c->bw, ++ (m->ltaxis[2] == 2 && i + 1 == n - m->msplit) ? Y2 - y2 - 2 * c->bw : h2 / n2 - 2 * c->bw, False); ++ if(n1 > 1) ++ x2 = c->x + WIDTH(c); ++ if(n2 > 1) ++ y2 = c->y + HEIGHT(c); ++ } + } + } + + void + togglebar(const Arg *arg) { +- selmon->showbar = !selmon->showbar; ++ selmon->showbar = selmon->showbars[selmon->curtag] = !selmon->showbar; + updatebarpos(selmon); + XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); + arrange(selmon); +@@ -1642,12 +1766,31 @@ togglefloating(const Arg *arg) { + void + toggletag(const Arg *arg) { + unsigned int newtags; ++ unsigned int i; + + if(!selmon->sel) + return; + newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); + if(newtags) { + selmon->sel->tags = newtags; ++ if(newtags == ~0) { ++ selmon->prevtag = selmon->curtag; ++ selmon->curtag = 0; ++ } ++ if(!(newtags & 1 << (selmon->curtag - 1))) { ++ selmon->prevtag = selmon->curtag; ++ for (i=0; !(newtags & 1 << i); i++); ++ selmon->curtag = i + 1; ++ } ++ selmon->sel->tags = newtags; ++ selmon->lt[selmon->sellt] = selmon->lts[selmon->curtag]; ++ selmon->mfact = selmon->mfacts[selmon->curtag]; ++ if (selmon->showbar != selmon->showbars[selmon->curtag]) ++ togglebar(NULL); ++ selmon->ltaxis[0] = selmon->ltaxes[selmon->curtag][0]; ++ selmon->ltaxis[1] = selmon->ltaxes[selmon->curtag][1]; ++ selmon->ltaxis[2] = selmon->ltaxes[selmon->curtag][2]; ++ selmon->msplit = selmon->msplits[selmon->curtag]; + arrange(selmon); + } + } +@@ -1914,11 +2057,33 @@ updatewmhints(Client *c) { + + void + view(const Arg *arg) { ++ unsigned int i; ++ + if((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) + return; + selmon->seltags ^= 1; /* toggle sel tagset */ +- if(arg->ui & TAGMASK) ++ if(arg->ui & TAGMASK) { + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; ++ selmon->prevtag = selmon->curtag; ++ if(arg->ui == ~0) ++ selmon->curtag = 0; ++ else { ++ for (i=0; !(arg->ui & 1 << i); i++); ++ selmon->curtag = i + 1; ++ } ++ } else { ++ selmon->prevtag = selmon->curtag ^ selmon->prevtag; ++ selmon->curtag ^= selmon->prevtag; ++ selmon->prevtag = selmon->curtag ^ selmon->prevtag; ++ } ++ selmon->lt[selmon->sellt] = selmon->lts[selmon->curtag]; ++ selmon->mfact = selmon->mfacts[selmon->curtag]; ++ if(selmon->showbar != selmon->showbars[selmon->curtag]) ++ togglebar(NULL); ++ selmon->ltaxis[0] = selmon->ltaxes[selmon->curtag][0]; ++ selmon->ltaxis[1] = selmon->ltaxes[selmon->curtag][1]; ++ selmon->ltaxis[2] = selmon->ltaxes[selmon->curtag][2]; ++ selmon->msplit = selmon->msplits[selmon->curtag]; + arrange(selmon); + } + diff --git a/dwm.suckless.org/patches/dwm-flextile-5.8.2.diff b/dwm.suckless.org/patches/flextile/dwm-flextile-5.8.2.diff diff --git a/dwm.suckless.org/patches/flextile.md b/dwm.suckless.org/patches/flextile/index.md diff --git a/dwm.suckless.org/patches/dwm-float_border_color-6.0.diff b/dwm.suckless.org/patches/float_border_color/dwm-float_border_color-6.0.diff diff --git a/dwm.suckless.org/patches/dwm-float_border_color-6.1.diff b/dwm.suckless.org/patches/float_border_color/dwm-float_border_color-6.1.diff diff --git a/dwm.suckless.org/patches/dwm-float_border_color2-20160731-56a31dc.diff b/dwm.suckless.org/patches/float_border_color/dwm-float_border_color2-20160731-56a31dc.diff diff --git a/dwm.suckless.org/patches/float_border_color.md b/dwm.suckless.org/patches/float_border_color/index.md diff --git a/dwm.suckless.org/patches/focusadjacenttag.md b/dwm.suckless.org/patches/focusadjacenttag.md @@ -1,29 +0,0 @@ -focus adjacent tag -================== - -Description ------------ - -This patch provides the ability to focus the tag on the immediate left or right -of the currently focused tag. It also allows to send the focused window either -on the left or the right tag. - -Default key bindings --------------------- - - Key | Description -:-------------------:|:-------------------------------------------------- - `Mod-Left` | Focus tag on the left, if any. - `Mod-Right` | Focus tag on the right, if any. - `Mod-Shift-Left` | Send focused window to tag on the left, if any. - `Mod-Shift-Right` | Send focused window to tag on the right, if any. - -Download --------- - -<!-- Author emailed about this issue already --> - * [dwm-6.0-focusadjacenttag.diff](dwm-6.0-focusadjacenttag.diff) (Unclean patch) - -Authors -------- - * Fabio Banfi - `<fbanfi90 at gmail dot com>` diff --git a/dwm.suckless.org/patches/dwm-6.0-focusadjacenttag.diff b/dwm.suckless.org/patches/focusadjacenttag/dwm-focusadjacenttag-6.0.diff diff --git a/dwm.suckless.org/patches/focusadjacenttag/index.md b/dwm.suckless.org/patches/focusadjacenttag/index.md @@ -0,0 +1,29 @@ +focus adjacent tag +================== + +Description +----------- + +This patch provides the ability to focus the tag on the immediate left or right +of the currently focused tag. It also allows to send the focused window either +on the left or the right tag. + +Default key bindings +-------------------- + + Key | Description +:-------------------:|:-------------------------------------------------- + `Mod-Left` | Focus tag on the left, if any. + `Mod-Right` | Focus tag on the right, if any. + `Mod-Shift-Left` | Send focused window to tag on the left, if any. + `Mod-Shift-Right` | Send focused window to tag on the right, if any. + +Download +-------- + +<!-- Author emailed about this issue already --> + * [dwm-focusadjacenttag-6.0.diff](dwm-focusadjacenttag-6.0.diff) (Unclean patch) + +Authors +------- + * Fabio Banfi - `<fbanfi90 at gmail dot com>` diff --git a/dwm.suckless.org/patches/focusonclick.md b/dwm.suckless.org/patches/focusonclick.md @@ -1,22 +0,0 @@ -# focusonclick - -## Description - - * Switch focus only by mouse click and not sloppy. - -## Download - - * [dwm-focusonclick-20171030-6aa8e37.diff](dwm-focusonclick-20171030-6aa8e37.diff) (2017-10-17) - * [dwm-focusonclick-bb3bd6f.diff](dwm-focusonclick-bb3bd6f.diff) (2017-01-04) - * [dwm-focusonclick-6.0.diff](dwm-focusonclick-6.0.diff) (2012-11-24) - * [dwm-git-20100321-focusonclick.diff](historical/dwm-git-20100321-focusonclick.diff) - -## Author - - * Wolfgang S. - ezzieyguywuf at gmail . com (added 6aa8e37 patch fix) - * Markus P. - peters_mops at arcor . de - * Eric Pruitt - added option to disable focus changing with the scroll wheel - * [Alessandro Di Martino][1] - Maintainer of the 6.0 version. - * Markus Teich - Update and fix - -[1]: http://www.alessandrodimartino.com diff --git a/dwm.suckless.org/patches/dwm-focusonclick-20171030-6aa8e37.diff b/dwm.suckless.org/patches/focusonclick/dwm-focusonclick-20171030-6aa8e37.diff diff --git a/dwm.suckless.org/patches/dwm-focusonclick-6.0.diff b/dwm.suckless.org/patches/focusonclick/dwm-focusonclick-6.0.diff diff --git a/dwm.suckless.org/patches/dwm-focusonclick-bb3bd6f.diff b/dwm.suckless.org/patches/focusonclick/dwm-focusonclick-bb3bd6f.diff diff --git a/dwm.suckless.org/patches/focusonclick/dwm-focusonclick-git-20100321.diff b/dwm.suckless.org/patches/focusonclick/dwm-focusonclick-git-20100321.diff @@ -0,0 +1,38 @@ +diff -r 72e52c5333ef config.def.h +--- a/config.def.h Wed Nov 25 13:56:17 2009 +0000 ++++ b/config.def.h Sun Mar 21 00:38:45 2010 +0100 +@@ -12,6 +12,7 @@ + static const unsigned int snap = 32; /* snap pixel */ + static const Bool showbar = True; /* False means no bar */ + static const Bool topbar = True; /* False means bottom bar */ ++static const Bool focusonclick = True; /* Change focus only on click */ + + /* tagging */ + static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; +diff -r 72e52c5333ef dwm.c +--- a/dwm.c Wed Nov 25 13:56:17 2009 +0000 ++++ b/dwm.c Sun Mar 21 00:38:45 2010 +0100 +@@ -791,14 +791,16 @@ + + if((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) + return; +- if((m = wintomon(ev->window)) && m != selmon) { +- unfocus(selmon->sel); +- selmon = m; ++ if (!focusonclick) { ++ if((m = wintomon(ev->window)) && m != selmon) { ++ unfocus(selmon->sel); ++ selmon = m; ++ } ++ if((c = wintoclient(ev->window))) ++ focus(c); ++ else ++ focus(NULL); + } +- if((c = wintoclient(ev->window))) +- focus(c); +- else +- focus(NULL); + } + + void diff --git a/dwm.suckless.org/patches/focusonclick/index.md b/dwm.suckless.org/patches/focusonclick/index.md @@ -0,0 +1,22 @@ +# focusonclick + +## Description + + * Switch focus only by mouse click and not sloppy. + +## Download + + * [dwm-focusonclick-20171030-6aa8e37.diff](dwm-focusonclick-20171030-6aa8e37.diff) (2017-10-17) + * [dwm-focusonclick-bb3bd6f.diff](dwm-focusonclick-bb3bd6f.diff) (2017-01-04) + * [dwm-focusonclick-6.0.diff](dwm-focusonclick-6.0.diff) (2012-11-24) + * [dwm-focusonclick-git-20100321.diff](dwm-focusonclick-git-20100321.diff) + +## Author + + * Wolfgang S. - ezzieyguywuf at gmail . com (added 6aa8e37 patch fix) + * Markus P. - peters_mops at arcor . de + * Eric Pruitt - added option to disable focus changing with the scroll wheel + * [Alessandro Di Martino][1] - Maintainer of the 6.0 version. + * Markus Teich - Update and fix + +[1]: http://www.alessandrodimartino.com diff --git a/dwm.suckless.org/patches/focusurgent.md b/dwm.suckless.org/patches/focusurgent.md @@ -1,15 +0,0 @@ -# focusurgent - -## Description - - * Selects the next window having the urgent flag regardless of the tag it is on - * The urgent flag can be artificially set with the following xdotool command on - any window: `xdotool selectwindow -- set_window --urgency 1` - -## Download - - * [dwm-focusurgent-20160831-56a31dc.diff](dwm-focusurgent-20160831-56a31dc.diff) - -## Author - - * Jan Christoph Ebersbach <jceb@e-jc.de> diff --git a/dwm.suckless.org/patches/dwm-focusurgent-20160831-56a31dc.diff b/dwm.suckless.org/patches/focusurgent/dwm-focusurgent-20160831-56a31dc.diff diff --git a/dwm.suckless.org/patches/focusurgent/index.md b/dwm.suckless.org/patches/focusurgent/index.md @@ -0,0 +1,15 @@ +# focusurgent + +## Description + + * Selects the next window having the urgent flag regardless of the tag it is on + * The urgent flag can be artificially set with the following xdotool command on + any window: `xdotool selectwindow -- set_window --urgency 1` + +## Download + + * [dwm-focusurgent-20160831-56a31dc.diff](dwm-focusurgent-20160831-56a31dc.diff) + +## Author + + * Jan Christoph Ebersbach <jceb@e-jc.de> diff --git a/dwm.suckless.org/patches/gapless_grid.md b/dwm.suckless.org/patches/gapless_grid.md @@ -1,33 +0,0 @@ -# gapless grid layout - -## Description - -This patch is an altered [gridmode](historical/gridmode) layout for dwm, -which arranges the windows in a grid. -Instead of using a regular grid, which might leave empty cells when there are -not enough windows to fill the grid, it adjusts the number of windows in the -first few columns to avoid empty cells. - -## Usage - -Download `gaplessgrid.c` and add the gapless layout to your `config.h`: - - #include "gaplessgrid.c" - - static const Layout layouts[] = { - /* symbol arrange function */ - { "###", gaplessgrid }, - ... - - static Key keys[] = { - /* modifier key function argument */ - { MODKEY, XK_g, setlayout, {.v = &layouts[0] } }, - ... - -## Download - -* [dwm-gaplessgrid-20160731-56a31dc.diff](dwm-gaplessgrid-20160731-56a31dc.diff) -* [dwm-gaplessgrid-6.1.diff](dwm-gaplessgrid-6.1.diff) (1180b) (20140209) -* [gaplessgrid.c](gaplessgrid.c) (dwm 5.6.1) (20090908) -* [dwm-r1437-gaplessgrid.diff](historical/dwm-r1437-gaplessgrid.diff) (1.9k) (20090704) -* [dwm-5.2-gaplessgrid.diff](historical/dwm-5.2-gaplessgrid.diff) (1.9k) (20081020) diff --git a/dwm.suckless.org/patches/gaplessgrid.c b/dwm.suckless.org/patches/gaplessgrid.c @@ -1,36 +0,0 @@ -void -gaplessgrid(Monitor *m) { - unsigned int n, cols, rows, cn, rn, i, cx, cy, cw, ch; - Client *c; - - for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) - n++; - if(n == 0) - return; - - /* grid dimensions */ - for(cols = 0; cols <= n/2; cols++) - if(cols*cols >= n) - break; - if(n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */ - cols = 2; - rows = n/cols; - - /* window geometries */ - cw = cols ? m->ww / cols : m->ww; - cn = 0; /* current column number */ - rn = 0; /* current row number */ - for(i = 0, c = nexttiled(m->clients); c; i++, c = nexttiled(c->next)) { - if(i/rows + 1 > cols - n%cols) - rows = n/cols + 1; - ch = rows ? m->wh / rows : m->wh; - cx = m->wx + cn*cw; - cy = m->wy + rn*ch; - resize(c, cx, cy, cw - 2 * c->bw, ch - 2 * c->bw, False); - rn++; - if(rn >= rows) { - rn = 0; - cn++; - } - } -} diff --git a/dwm.suckless.org/patches/gaplessgrid/dwm-5.2-gaplessgrid.diff b/dwm.suckless.org/patches/gaplessgrid/dwm-5.2-gaplessgrid.diff @@ -0,0 +1,59 @@ +diff -up dwm-5.2-original/config.def.h dwm-5.2-modified/config.def.h +--- dwm-5.2-original/config.def.h 2008-09-09 21:46:17.000000000 +0200 ++++ dwm-5.2-modified/config.def.h 2008-10-20 20:07:42.000000000 +0200 +@@ -28,11 +28,13 @@ static Rule rules[] = { + static float mfact = 0.55; /* factor of master area size [0.05..0.95] */ + static Bool resizehints = True; /* False means respect size hints in tiled resizals */ + ++#include "gaplessgrid.c" + static Layout layouts[] = { + /* symbol arrange function */ + { "[]=", tile }, /* first entry is default */ + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, ++ { "###", gaplessgrid }, + }; + + /* key definitions */ +diff -up dwm-5.2-original/gaplessgrid.c dwm-5.2-modified/gaplessgrid.c +--- /dev/null 2008-10-20 20:09:51.000000000 +0200 ++++ dwm-5.2-modified/gaplessgrid.c 2008-10-20 20:06:59.000000000 +0200 +@@ -0,0 +1,38 @@ ++void ++gaplessgrid() { ++ unsigned int n, cols, rows, cn, rn, i, cx, cy, cw, ch; ++ Client *c; ++ ++ for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) ++ n++; ++ if(n == 0) ++ return; ++ ++ /* grid dimensions */ ++ for(cols = 0; cols <= n/2; cols++) ++ if(cols*cols >= n) ++ break; ++ if(n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */ ++ cols = 2; ++ rows = n/cols; ++ ++ /* window geometries (cell height/width/x/y) */ ++ cw = ww / (cols ? cols : 1); ++ cn = 0; /* current column number */ ++ rn = 0; /* current row number */ ++ for(i = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) { ++ if(i/rows+1 > cols-n%cols) ++ rows = n/cols+1; ++ ch = wh / (rows ? rows : 1); ++ cx = wx + cn*cw; ++ cy = wy + rn*ch; ++ resize(c, cx, cy, cw - 2 * c->bw, ch - 2 * c->bw, False); ++ ++ i++; ++ rn++; ++ if(rn >= rows) { /* jump to the next column */ ++ rn = 0; ++ cn++; ++ } ++ } ++} diff --git a/dwm.suckless.org/patches/dwm-gaplessgrid-20160731-56a31dc.diff b/dwm.suckless.org/patches/gaplessgrid/dwm-gaplessgrid-20160731-56a31dc.diff diff --git a/dwm.suckless.org/patches/dwm-gaplessgrid-6.1.diff b/dwm.suckless.org/patches/gaplessgrid/dwm-gaplessgrid-6.1.diff diff --git a/dwm.suckless.org/patches/gaplessgrid/dwm-r1437-gaplessgrid.diff b/dwm.suckless.org/patches/gaplessgrid/dwm-r1437-gaplessgrid.diff @@ -0,0 +1,59 @@ +diff -up dwm-5.2-original/config.def.h dwm-5.2-modified/config.def.h +--- dwm-5.2-original/config.def.h 2008-09-09 21:46:17.000000000 +0200 ++++ dwm-5.2-modified/config.def.h 2008-10-20 20:07:42.000000000 +0200 +@@ -28,11 +28,13 @@ static Rule rules[] = { + static float mfact = 0.55; /* factor of master area size [0.05..0.95] */ + static Bool resizehints = True; /* False means respect size hints in tiled resizals */ + ++#include "gaplessgrid.c" + static Layout layouts[] = { + /* symbol arrange function */ + { "[]=", tile }, /* first entry is default */ + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, ++ { "###", gaplessgrid }, + }; + + /* key definitions */ +diff -up dwm-5.2-original/gaplessgrid.c dwm-5.2-modified/gaplessgrid.c +--- /dev/null 2008-10-20 20:09:51.000000000 +0200 ++++ dwm-5.2-modified/gaplessgrid.c 2008-10-20 20:06:59.000000000 +0200 +@@ -0,0 +1,38 @@ ++void ++gaplessgrid(Monitor *m) { ++ unsigned int n, cols, rows, cn, rn, i, cx, cy, cw, ch; ++ Client *c; ++ ++ for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) ++ n++; ++ if(n == 0) ++ return; ++ ++ /* grid dimensions */ ++ for(cols = 0; cols <= n/2; cols++) ++ if(cols*cols >= n) ++ break; ++ if(n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */ ++ cols = 2; ++ rows = n/cols; ++ ++ /* window geometries (cell height/width/x/y) */ ++ cw = m->ww / (cols ? cols : 1); ++ cn = 0; /* current column number */ ++ rn = 0; /* current row number */ ++ for(i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) { ++ if(i/rows+1 > cols-n%cols) ++ rows = n/cols+1; ++ ch = m->wh / (rows ? rows : 1); ++ cx = m->wx + cn*cw; ++ cy = m->wy + rn*ch; ++ resize(c, cx, cy, cw - 2 * c->bw, ch - 2 * c->bw); ++ ++ i++; ++ rn++; ++ if(rn >= rows) { /* jump to the next column */ ++ rn = 0; ++ cn++; ++ } ++ } ++} diff --git a/dwm.suckless.org/patches/gaplessgrid/gaplessgrid.c b/dwm.suckless.org/patches/gaplessgrid/gaplessgrid.c @@ -0,0 +1,36 @@ +void +gaplessgrid(Monitor *m) { + unsigned int n, cols, rows, cn, rn, i, cx, cy, cw, ch; + Client *c; + + for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) + n++; + if(n == 0) + return; + + /* grid dimensions */ + for(cols = 0; cols <= n/2; cols++) + if(cols*cols >= n) + break; + if(n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */ + cols = 2; + rows = n/cols; + + /* window geometries */ + cw = cols ? m->ww / cols : m->ww; + cn = 0; /* current column number */ + rn = 0; /* current row number */ + for(i = 0, c = nexttiled(m->clients); c; i++, c = nexttiled(c->next)) { + if(i/rows + 1 > cols - n%cols) + rows = n/cols + 1; + ch = rows ? m->wh / rows : m->wh; + cx = m->wx + cn*cw; + cy = m->wy + rn*ch; + resize(c, cx, cy, cw - 2 * c->bw, ch - 2 * c->bw, False); + rn++; + if(rn >= rows) { + rn = 0; + cn++; + } + } +} diff --git a/dwm.suckless.org/patches/gaplessgrid/index.md b/dwm.suckless.org/patches/gaplessgrid/index.md @@ -0,0 +1,33 @@ +# gapless grid layout + +## Description + +This patch is an altered [gridmode](historical/gridmode) layout for dwm, +which arranges the windows in a grid. +Instead of using a regular grid, which might leave empty cells when there are +not enough windows to fill the grid, it adjusts the number of windows in the +first few columns to avoid empty cells. + +## Usage + +Download `gaplessgrid.c` and add the gapless layout to your `config.h`: + + #include "gaplessgrid.c" + + static const Layout layouts[] = { + /* symbol arrange function */ + { "###", gaplessgrid }, + ... + + static Key keys[] = { + /* modifier key function argument */ + { MODKEY, XK_g, setlayout, {.v = &layouts[0] } }, + ... + +## Download + +* [dwm-gaplessgrid-20160731-56a31dc.diff](dwm-gaplessgrid-20160731-56a31dc.diff) +* [dwm-gaplessgrid-6.1.diff](dwm-gaplessgrid-6.1.diff) (20140209) +* [gaplessgrid.c](gaplessgrid.c) (dwm 5.6.1) (20090908) +* [dwm-r1437-gaplessgrid.diff](dwm-r1437-gaplessgrid.diff) (20090704) +* [dwm-5.2-gaplessgrid.diff](dwm-5.2-gaplessgrid.diff) (20081020) diff --git a/dwm.suckless.org/patches/gaps.md b/dwm.suckless.org/patches/gaps.md @@ -1,27 +0,0 @@ - -Gaps -==== - -Description ------------ - -This patch modifies the tile layout to add a gap between clients that helps to visually -differentiate between selected borders and normal borders and so provides an additional -visual hint to identify the currently selected client. OTOH, there's no gap between a -client and the screen frame in order to reduce the waste of screen space. - -To configure the gap size just set the configuration variable `gappx`. - -There is a variation of the patch for the [xtile](xtile) layout also. - -Download --------- - -* For vanilla tile: [dwm-gaps-6.0.diff](dwm-gaps-6.0.diff) - -* For xtile tile: [dwm-6.0-xtile-gaps.diff](dwm-6.0-xtile-gaps.diff) - -Author ------- - -* Carlos Pita (memeplex) <carlosjosepita@gmail.com> diff --git a/dwm.suckless.org/patches/dwm-gaps-6.0.diff b/dwm.suckless.org/patches/gaps/dwm-gaps-6.0.diff diff --git a/dwm.suckless.org/patches/dwm-6.0-xtile-gaps.diff b/dwm.suckless.org/patches/gaps/dwm-gaps-xtile-6.0.diff diff --git a/dwm.suckless.org/patches/gaps/index.md b/dwm.suckless.org/patches/gaps/index.md @@ -0,0 +1,26 @@ +gaps +==== + +Description +----------- + +This patch modifies the tile layout to add a gap between clients that helps to visually +differentiate between selected borders and normal borders and so provides an additional +visual hint to identify the currently selected client. OTOH, there's no gap between a +client and the screen frame in order to reduce the waste of screen space. + +To configure the gap size just set the configuration variable `gappx`. + +There is a variation of the patch for the [xtile](xtile) layout also. + +Download +-------- + +* For vanilla tile: [dwm-gaps-6.0.diff](dwm-gaps-6.0.diff) + +* For xtile tile: [dwm-gaps-xtile-6.0.diff](dwm-gaps-xtile-6.0.diff) + +Author +------ + +* Carlos Pita (memeplex) <carlosjosepita@gmail.com> diff --git a/dwm.suckless.org/patches/gestures.md b/dwm.suckless.org/patches/gestures.md @@ -1,16 +0,0 @@ -gestures -======== - -Description ------------ -`gestures` adds support for simple mouse gestures to dwm. The patch assumes make has been run -and adds a gestures array to config.h. A gesture can call any dwm function. I usually call spawn. - -Download --------- -<!-- Author email bounced (removed it), patch needs fixed --> -* [dwm-5.8-gestures.diff](dwm-5.8-gestures.diff) (Unclean patch) - -Author ------- -* David Galos diff --git a/dwm.suckless.org/patches/dwm-5.8-gestures.diff b/dwm.suckless.org/patches/gestures/dwm-5.8-gestures.diff diff --git a/dwm.suckless.org/patches/gestures/index.md b/dwm.suckless.org/patches/gestures/index.md @@ -0,0 +1,16 @@ +gestures +======== + +Description +----------- +`gestures` adds support for simple mouse gestures to dwm. The patch assumes make has been run +and adds a gestures array to config.h. A gesture can call any dwm function. I usually call spawn. + +Download +-------- +<!-- Author email bounced (removed it), patch needs fixed --> +* [dwm-5.8-gestures.diff](dwm-5.8-gestures.diff) (Unclean patch) + +Author +------ +* David Galos diff --git a/dwm.suckless.org/patches/gridmode.md b/dwm.suckless.org/patches/gridmode.md @@ -1,27 +0,0 @@ -gridmode -======== - -Description ------------ -This patch adds an extra layout mode to dwm called `grid` in which the windows -are arranged in a grid of equal sizes. It comes in very handy, especially with -tools that operate on multiple windows at once; e.g. Cluster SSH. - -Download --------- -* [dwm-gridmode-20170909-ceac8c9.diff](dwm-grid-20170909-ceac8c9.diff) -* [dwm-gridmode-5.8.2.diff](dwm-gridmode-5.8.2.diff) -* See older versions in [historical](historical/gridmode). - -Authors -------- -* Alexandru E. Ungur - `<grid at rb.no-ip dot biz>` -* Updated by Jan Christoph Ebersbach - `<jceb at e-jc dot de>` -* Updated to 5.2 & small fix by V4hn - `v4hn.de` - -Feedback is more than welcome :-) - -Acknowledgements ----------------- -The patch would look a lot uglier without Jukka Salmi's constant help. -Thanks Jukka :-) diff --git a/dwm.suckless.org/patches/dwm-gridmode-20170909-ceac8c9.diff b/dwm.suckless.org/patches/gridmode/dwm-gridmode-20170909-ceac8c9.diff diff --git a/dwm.suckless.org/patches/dwm-gridmode-5.8.2.diff b/dwm.suckless.org/patches/gridmode/dwm-gridmode-5.8.2.diff diff --git a/dwm.suckless.org/patches/gridmode/index.md b/dwm.suckless.org/patches/gridmode/index.md @@ -0,0 +1,27 @@ +gridmode +======== + +Description +----------- +This patch adds an extra layout mode to dwm called `grid` in which the windows +are arranged in a grid of equal sizes. It comes in very handy, especially with +tools that operate on multiple windows at once; e.g. Cluster SSH. + +Download +-------- +* [dwm-gridmode-20170909-ceac8c9.diff](dwm-grid-20170909-ceac8c9.diff) +* [dwm-gridmode-5.8.2.diff](dwm-gridmode-5.8.2.diff) +* See older versions in [historical](historical/gridmode). + +Authors +------- +* Alexandru E. Ungur - `<grid at rb.no-ip dot biz>` +* Updated by Jan Christoph Ebersbach - `<jceb at e-jc dot de>` +* Updated to 5.2 & small fix by V4hn - `v4hn.de` + +Feedback is more than welcome :-) + +Acknowledgements +---------------- +The patch would look a lot uglier without Jukka Salmi's constant help. +Thanks Jukka :-) diff --git a/dwm.suckless.org/patches/hide_vacant_tags.md b/dwm.suckless.org/patches/hide_vacant_tags.md @@ -1,29 +0,0 @@ -hide vacant tags -================ - -Description ------------ - -This patch prevents dwm from drawing tags with no clients -(i.e. vacant) on the bar. - -It also makes sure that pressing a tag on the bar behaves accordingly -by not reserving reactive regions on the bar for vacant tags. - -It also stops drawing empty rectangles on the bar for non-vacant -tags as there is no need anymore to distinguish vacant -tags and it offers a more visible contrast than if there were -filled/empty rectangles. - -Download --------- - -* [dwm-hide_vacant_tags-6.1.diff](dwm-hide_vacant_tags-6.1.diff) - 2016-01-22 -* [dwm-hide_vacant_tags-git-20160626-7af4d43.diff](dwm-hide_vacant_tags-git-20160626-7af4d43.diff) - -Author ------- - -* [Ondřej Grover](mailto:ondrej.grover@gmail.com) -* Matthew Boswell - mordervomubel+suckless at lockmail dot us (mechanical update for dwm 6.1 release) -* [Jochen Sprickerhof](mailto:project@firstname.lastname.de) (hide 0 tagged clients) diff --git a/dwm.suckless.org/patches/dwm-hide_vacant_tags-6.1.diff b/dwm.suckless.org/patches/hide_vacant_tags/dwm-hide_vacant_tags-6.1.diff diff --git a/dwm.suckless.org/patches/dwm-hide_vacant_tags-git-20160626-7af4d43.diff b/dwm.suckless.org/patches/hide_vacant_tags/dwm-hide_vacant_tags-git-20160626-7af4d43.diff diff --git a/dwm.suckless.org/patches/hide_vacant_tags/index.md b/dwm.suckless.org/patches/hide_vacant_tags/index.md @@ -0,0 +1,29 @@ +hide vacant tags +================ + +Description +----------- + +This patch prevents dwm from drawing tags with no clients +(i.e. vacant) on the bar. + +It also makes sure that pressing a tag on the bar behaves accordingly +by not reserving reactive regions on the bar for vacant tags. + +It also stops drawing empty rectangles on the bar for non-vacant +tags as there is no need anymore to distinguish vacant +tags and it offers a more visible contrast than if there were +filled/empty rectangles. + +Download +-------- + +* [dwm-hide_vacant_tags-6.1.diff](dwm-hide_vacant_tags-6.1.diff) - 2016-01-22 +* [dwm-hide_vacant_tags-git-20160626-7af4d43.diff](dwm-hide_vacant_tags-git-20160626-7af4d43.diff) + +Author +------ + +* [Ondřej Grover](mailto:ondrej.grover@gmail.com) +* Matthew Boswell - mordervomubel+suckless at lockmail dot us (mechanical update for dwm 6.1 release) +* [Jochen Sprickerhof](mailto:project@firstname.lastname.de) (hide 0 tagged clients) diff --git a/dwm.suckless.org/patches/historical/dwm-5.2-gaplessgrid.diff b/dwm.suckless.org/patches/historical/dwm-5.2-gaplessgrid.diff @@ -1,59 +0,0 @@ -diff -up dwm-5.2-original/config.def.h dwm-5.2-modified/config.def.h ---- dwm-5.2-original/config.def.h 2008-09-09 21:46:17.000000000 +0200 -+++ dwm-5.2-modified/config.def.h 2008-10-20 20:07:42.000000000 +0200 -@@ -28,11 +28,13 @@ static Rule rules[] = { - static float mfact = 0.55; /* factor of master area size [0.05..0.95] */ - static Bool resizehints = True; /* False means respect size hints in tiled resizals */ - -+#include "gaplessgrid.c" - static Layout layouts[] = { - /* symbol arrange function */ - { "[]=", tile }, /* first entry is default */ - { "><>", NULL }, /* no layout function means floating behavior */ - { "[M]", monocle }, -+ { "###", gaplessgrid }, - }; - - /* key definitions */ -diff -up dwm-5.2-original/gaplessgrid.c dwm-5.2-modified/gaplessgrid.c ---- /dev/null 2008-10-20 20:09:51.000000000 +0200 -+++ dwm-5.2-modified/gaplessgrid.c 2008-10-20 20:06:59.000000000 +0200 -@@ -0,0 +1,38 @@ -+void -+gaplessgrid() { -+ unsigned int n, cols, rows, cn, rn, i, cx, cy, cw, ch; -+ Client *c; -+ -+ for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) -+ n++; -+ if(n == 0) -+ return; -+ -+ /* grid dimensions */ -+ for(cols = 0; cols <= n/2; cols++) -+ if(cols*cols >= n) -+ break; -+ if(n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */ -+ cols = 2; -+ rows = n/cols; -+ -+ /* window geometries (cell height/width/x/y) */ -+ cw = ww / (cols ? cols : 1); -+ cn = 0; /* current column number */ -+ rn = 0; /* current row number */ -+ for(i = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) { -+ if(i/rows+1 > cols-n%cols) -+ rows = n/cols+1; -+ ch = wh / (rows ? rows : 1); -+ cx = wx + cn*cw; -+ cy = wy + rn*ch; -+ resize(c, cx, cy, cw - 2 * c->bw, ch - 2 * c->bw, False); -+ -+ i++; -+ rn++; -+ if(rn >= rows) { /* jump to the next column */ -+ rn = 0; -+ cn++; -+ } -+ } -+} diff --git a/dwm.suckless.org/patches/historical/dwm-5.7.2-statuscolors.diff b/dwm.suckless.org/patches/historical/dwm-5.7.2-statuscolors.diff @@ -1,234 +0,0 @@ -diff -r 2bcd25cce4ab config.def.h ---- a/config.def.h Sun Sep 27 20:20:14 2009 +0100 -+++ b/config.def.h Mon Oct 05 22:01:49 2009 -0300 -@@ -1,13 +1,16 @@ - /* See LICENSE file for copyright and license details. */ - - /* appearance */ -+#define NUMCOLORS 4 // need at least 3 -+static const char colors[NUMCOLORS][ColLast][8] = { -+ // border foreground background -+ { "#cccccc", "#000000", "#cccccc" }, // 0 = normal -+ { "#0066ff", "#ffffff", "#0066ff" }, // 1 = selected -+ { "#0066ff", "#0066ff", "#ffffff" }, // 2 = urgent/warning -+ { "#ff0000", "#ffffff", "#ff0000" }, // 3 = error -+ // add more here -+}; - static const char font[] = "-*-*-medium-*-*-*-14-*-*-*-*-*-*-*"; --static const char normbordercolor[] = "#cccccc"; --static const char normbgcolor[] = "#cccccc"; --static const char normfgcolor[] = "#000000"; --static const char selbordercolor[] = "#0066ff"; --static const char selbgcolor[] = "#0066ff"; --static const char selfgcolor[] = "#ffffff"; - static const unsigned int borderpx = 1; /* border pixel of windows */ - static const unsigned int snap = 32; /* snap pixel */ - static const Bool showbar = True; /* False means no bar */ -@@ -45,7 +48,7 @@ - #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } - - /* commands */ --static const char *dmenucmd[] = { "dmenu_run", "-fn", font, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL }; -+static const char *dmenucmd[] = { "dmenu_run", "-fn", font, "-nb", colors[0][ColBG], "-nf", colors[0][ColFG], "-sb", colors[1][ColBG], "-sf", colors[1][ColFG], NULL }; - static const char *termcmd[] = { "uxterm", NULL }; - - static Key keys[] = { -diff -r 2bcd25cce4ab dwm.c ---- a/dwm.c Sun Sep 27 20:20:14 2009 +0100 -+++ b/dwm.c Mon Oct 05 22:01:49 2009 -0300 -@@ -48,6 +48,7 @@ - #define LENGTH(X) (sizeof X / sizeof X[0]) - #define MAX(A, B) ((A) > (B) ? (A) : (B)) - #define MIN(A, B) ((A) < (B) ? (A) : (B)) -+#define MAXCOLORS 8 - #define MOUSEMASK (BUTTONMASK|PointerMotionMask) - #define WIDTH(X) ((X)->w + 2 * (X)->bw) - #define HEIGHT(X) ((X)->h + 2 * (X)->bw) -@@ -95,8 +96,7 @@ - - typedef struct { - int x, y, w, h; -- unsigned long norm[ColLast]; -- unsigned long sel[ColLast]; -+ unsigned long colors[MAXCOLORS][ColLast]; - Drawable drawable; - GC gc; - struct { -@@ -172,8 +172,9 @@ - static Monitor *dirtomon(int dir); - static void drawbar(Monitor *m); - static void drawbars(void); --static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]); --static void drawtext(const char *text, unsigned long col[ColLast], Bool invert); -+static void drawcoloredtext(char *text); -+static void drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]); -+static void drawtext(const char *text, unsigned long col[ColLast], Bool pad); - static void enternotify(XEvent *e); - static void expose(XEvent *e); - static void focus(Client *c); -@@ -691,14 +692,13 @@ - dc.x = 0; - for(i = 0; i < LENGTH(tags); i++) { - dc.w = TEXTW(tags[i]); -- col = m->tagset[m->seltags] & 1 << i ? dc.sel : dc.norm; -- drawtext(tags[i], col, urg & 1 << i); -- drawsquare(m == selmon && selmon->sel && selmon->sel->tags & 1 << i, -- occ & 1 << i, urg & 1 << i, col); -+ col = dc.colors[ (m->tagset[m->seltags] & 1 << i ? 1:(urg & 1 << i ? 2:0))]; -+ drawtext(tags[i], col, True); -+ drawsquare(m == selmon && selmon->sel && selmon->sel->tags & 1 << i, occ & 1 << i, col); - dc.x += dc.w; - } - dc.w = blw = TEXTW(m->ltsymbol); -- drawtext(m->ltsymbol, dc.norm, False); -+ drawtext(m->ltsymbol, dc.colors[0], True); - dc.x += dc.w; - x = dc.x; - if(m == selmon) { /* status is only drawn on selected monitor */ -@@ -708,19 +708,19 @@ - dc.x = x; - dc.w = m->ww - x; - } -- drawtext(stext, dc.norm, False); -+ drawcoloredtext(stext); - } - else - dc.x = m->ww; - if((dc.w = dc.x - x) > bh) { - dc.x = x; - if(m->sel) { -- col = m == selmon ? dc.sel : dc.norm; -- drawtext(m->sel->name, col, False); -- drawsquare(m->sel->isfixed, m->sel->isfloating, False, col); -+ col = m == selmon ? dc.colors[1] : dc.colors[0]; -+ drawtext(m->sel->name, col, True); -+ drawsquare(m->sel->isfixed, m->sel->isfloating, col); - } - else -- drawtext(NULL, dc.norm, False); -+ drawtext(NULL, dc.colors[0], False); - } - XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->ww, bh, 0, 0); - XSync(dpy, False); -@@ -735,12 +735,42 @@ - } - - void --drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) { -+drawcoloredtext(char *text) { -+ Bool first=True; -+ char *buf = text, *ptr = buf, c = 1; -+ unsigned long *col = dc.colors[0]; -+ int i, ox = dc.x; -+ -+ while( *ptr ) { -+ for( i = 0; *ptr < 0 || *ptr > NUMCOLORS; i++, ptr++); -+ if( !*ptr ) break; -+ c=*ptr; -+ *ptr=0; -+ if( i ) { -+ dc.w = selmon->ww - dc.x; -+ drawtext(buf, col, first); -+ dc.x += textnw(buf, i) + textnw(&c,1); -+ if( first ) dc.x += ( dc.font.ascent + dc.font.descent ) / 2; -+ first = False; -+ } else if( first ) { -+ ox = dc.x += textnw(&c,1); -+ } -+ *ptr = c; -+ col = dc.colors[ c-1 ]; -+ buf = ++ptr; -+ } -+ if( !first ) dc.x-=(dc.font.ascent+dc.font.descent)/2; -+ drawtext(buf, col, True); -+ dc.x = ox; -+} -+ -+void -+drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]) { - int x; - XGCValues gcv; - XRectangle r = { dc.x, dc.y, dc.w, dc.h }; - -- gcv.foreground = col[invert ? ColBG : ColFG]; -+ gcv.foreground = col[ ColFG ]; - XChangeGC(dpy, dc.gc, GCForeground, &gcv); - x = (dc.font.ascent + dc.font.descent + 2) / 4; - r.x = dc.x + 1; -@@ -756,18 +786,18 @@ - } - - void --drawtext(const char *text, unsigned long col[ColLast], Bool invert) { -+drawtext(const char *text, unsigned long col[ColLast], Bool pad) { - char buf[256]; - int i, x, y, h, len, olen; - XRectangle r = { dc.x, dc.y, dc.w, dc.h }; - -- XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]); -+ XSetForeground(dpy, dc.gc, col[ ColBG ]); - XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); - if(!text) - return; - olen = strlen(text); -- h = dc.font.ascent + dc.font.descent; -- y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent; -+ h = pad ? (dc.font.ascent + dc.font.descent) : 0; -+ y = dc.y + ((dc.h + dc.font.ascent - dc.font.descent) / 2); - x = dc.x + (h / 2); - /* shorten text if necessary */ - for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w - h; len--); -@@ -776,7 +806,7 @@ - memcpy(buf, text, len); - if(len < olen) - for(i = len; i && i > len - 3; buf[--i] = '.'); -- XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]); -+ XSetForeground(dpy, dc.gc, col[ ColFG ]); - if(dc.font.set) - XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len); - else -@@ -824,7 +854,7 @@ - detachstack(c); - attachstack(c); - grabbuttons(c, True); -- XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]); -+ XSetWindowBorder(dpy, c->win, dc.colors[1][ColBorder]); - XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); - } - else -@@ -1132,7 +1162,7 @@ - } - wc.border_width = c->bw; - XConfigureWindow(dpy, w, CWBorderWidth, &wc); -- XSetWindowBorder(dpy, w, dc.norm[ColBorder]); -+ XSetWindowBorder(dpy, w, dc.colors[0][ColBorder]); - configure(c); /* propagates border_width, if size doesn't change */ - updatesizehints(c); - XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); -@@ -1498,12 +1528,11 @@ - cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); - cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); - /* init appearance */ -- dc.norm[ColBorder] = getcolor(normbordercolor); -- dc.norm[ColBG] = getcolor(normbgcolor); -- dc.norm[ColFG] = getcolor(normfgcolor); -- dc.sel[ColBorder] = getcolor(selbordercolor); -- dc.sel[ColBG] = getcolor(selbgcolor); -- dc.sel[ColFG] = getcolor(selfgcolor); -+ for(int i=0; i<NUMCOLORS; i++) { -+ dc.colors[i][ColBorder] = getcolor( colors[i][ColBorder] ); -+ dc.colors[i][ColFG] = getcolor( colors[i][ColFG] ); -+ dc.colors[i][ColBG] = getcolor( colors[i][ColBG] ); -+ } - dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen)); - dc.gc = XCreateGC(dpy, root, 0, NULL); - XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); -@@ -1665,7 +1694,7 @@ - if(!c) - return; - grabbuttons(c, False); -- XSetWindowBorder(dpy, c->win, dc.norm[ColBorder]); -+ XSetWindowBorder(dpy, c->win, dc.colors[0][ColBorder]); - XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); - } - diff --git a/dwm.suckless.org/patches/historical/dwm-5.8.2-pertag_without_bar.diff b/dwm.suckless.org/patches/historical/dwm-5.8.2-pertag_without_bar.diff @@ -1,165 +0,0 @@ -diff --git a/dwm.c b/dwm.c ---- a/dwm.c -+++ b/dwm.c -@@ -122,26 +122,6 @@ typedef struct { - void (*arrange)(Monitor *); - } Layout; - --struct Monitor { -- char ltsymbol[16]; -- float mfact; -- int num; -- int by; /* bar geometry */ -- int mx, my, mw, mh; /* screen size */ -- int wx, wy, ww, wh; /* window area */ -- unsigned int seltags; -- unsigned int sellt; -- unsigned int tagset[2]; -- Bool showbar; -- Bool topbar; -- Client *clients; -- Client *sel; -- Client *stack; -- Monitor *next; -- Window barwin; -- const Layout *lt[2]; --}; -- - typedef struct { - const char *class; - const char *instance; -@@ -278,6 +258,30 @@ static Window root; - /* configuration, allows nested code to access above variables */ - #include "config.h" - -+struct Monitor { -+ char ltsymbol[16]; -+ float mfact; -+ int num; -+ int by; /* bar geometry */ -+ int mx, my, mw, mh; /* screen size */ -+ int wx, wy, ww, wh; /* window area */ -+ unsigned int seltags; -+ unsigned int sellt; -+ unsigned int tagset[2]; -+ Bool showbar; -+ Bool topbar; -+ Client *clients; -+ Client *sel; -+ Client *stack; -+ Monitor *next; -+ Window barwin; -+ const Layout *lt[2]; -+ int curtag; -+ int prevtag; -+ const Layout *lts[LENGTH(tags) + 1]; -+ double mfacts[LENGTH(tags) + 1]; -+}; -+ - /* compile-time check if all tags fit into an unsigned int bit array. */ - struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; - -@@ -609,6 +613,7 @@ configurerequest(XEvent *e) { - Monitor * - createmon(void) { - Monitor *m; -+ unsigned int i; - - if(!(m = (Monitor *)calloc(1, sizeof(Monitor)))) - die("fatal: could not malloc() %u bytes\n", sizeof(Monitor)); -@@ -619,6 +624,14 @@ createmon(void) { - m->lt[0] = &layouts[0]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); -+ -+ /* pertag init */ -+ m->curtag = m->prevtag = 1; -+ for(i=0; i < LENGTH(tags) + 1 ; i++) { -+ m->mfacts[i] = mfact; -+ m->lts[i] = &layouts[0]; -+ } -+ - return m; - } - -@@ -1486,7 +1499,7 @@ 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; -+ selmon->lt[selmon->sellt] = selmon->lts[selmon->curtag] = (Layout *)arg->v; - strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); - if(selmon->sel) - arrange(selmon); -@@ -1504,7 +1517,7 @@ setmfact(const Arg *arg) { - f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; - if(f < 0.1 || f > 0.9) - return; -- selmon->mfact = f; -+ selmon->mfact = selmon->mfacts[selmon->curtag] = f; - arrange(selmon); - } - -@@ -1547,7 +1560,6 @@ setup(void) { - XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); - if(!dc.font.set) - XSetFont(dpy, dc.gc, dc.font.xfont->fid); -- /* init bars */ - updatebars(); - updatestatus(); - /* EWMH support per view */ -@@ -1678,12 +1690,25 @@ togglefloating(const Arg *arg) { - void - toggletag(const Arg *arg) { - unsigned int newtags; -+ unsigned int i; - - if(!selmon->sel) - return; - newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); - if(newtags) { - selmon->sel->tags = newtags; -+ if(newtags == ~0) { -+ selmon->prevtag = selmon->curtag; -+ selmon->curtag = 0; -+ } -+ if(!(newtags & 1 << (selmon->curtag - 1))) { -+ selmon->prevtag = selmon->curtag; -+ for (i=0; !(newtags & 1 << i); i++); -+ selmon->curtag = i + 1; -+ } -+ selmon->sel->tags = newtags; -+ selmon->lt[selmon->sellt] = selmon->lts[selmon->curtag]; -+ selmon->mfact = selmon->mfacts[selmon->curtag]; - arrange(selmon); - } - } -@@ -1950,11 +1975,27 @@ updatewmhints(Client *c) { - - void - view(const Arg *arg) { -+ unsigned int i; -+ - if((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) - return; - selmon->seltags ^= 1; /* toggle sel tagset */ -- if(arg->ui & TAGMASK) -+ if(arg->ui & TAGMASK) { - selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; -+ selmon->prevtag = selmon->curtag; -+ if(arg->ui == ~0) -+ selmon->curtag = 0; -+ else { -+ for (i=0; !(arg->ui & 1 << i); i++); -+ selmon->curtag = i + 1; -+ } -+ } else { -+ selmon->prevtag= selmon->curtag ^ selmon->prevtag; -+ selmon->curtag^= selmon->prevtag; -+ selmon->prevtag= selmon->curtag ^ selmon->prevtag; -+ } -+ selmon->lt[selmon->sellt]= selmon->lts[selmon->curtag]; -+ selmon->mfact = selmon->mfacts[selmon->curtag]; - arrange(selmon); - } - diff --git a/dwm.suckless.org/patches/historical/dwm-5.8.2-statuscolors.diff b/dwm.suckless.org/patches/historical/dwm-5.8.2-statuscolors.diff @@ -1,232 +0,0 @@ ---- a/config.def.h 2010-10-16 15:49:03.000000000 +0200 -+++ b/config.def.h 2010-10-16 15:51:35.000000000 +0200 -@@ -1,13 +1,16 @@ - /* See LICENSE file for copyright and license details. */ - - /* appearance */ -+#define NUMCOLORS 4 // need at least 3 -+static const char colors[NUMCOLORS][ColLast][8] = { -+ // border foreground background -+ { "#cccccc", "#000000", "#cccccc" }, // 0 = normal -+ { "#0066ff", "#ffffff", "#0066ff" }, // 1 = selected -+ { "#0066ff", "#0066ff", "#ffffff" }, // 2 = urgent/warning -+ { "#ff0000", "#ffffff", "#ff0000" }, // 3 = error -+ // add more here -+}; - static const char font[] = "-*-terminus-medium-r-*-*-16-*-*-*-*-*-*-*"; --static const char normbordercolor[] = "#cccccc"; --static const char normbgcolor[] = "#cccccc"; --static const char normfgcolor[] = "#000000"; --static const char selbordercolor[] = "#0066ff"; --static const char selbgcolor[] = "#0066ff"; --static const char selfgcolor[] = "#ffffff"; - static const unsigned int borderpx = 1; /* border pixel of windows */ - static const unsigned int snap = 32; /* snap pixel */ - static const Bool showbar = True; /* False means no bar */ -@@ -45,7 +48,7 @@ - #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } - - /* commands */ --static const char *dmenucmd[] = { "dmenu_run", "-fn", font, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL }; -+static const char *dmenucmd[] = { "dmenu_run", "-fn", font, "-nb", colors[0][ColBG], "-nf", colors[0][ColFG],"-sb", colors[1][ColBG], "-sf", colors[1][ColFG], NULL }; - static const char *termcmd[] = { "uxterm", NULL }; - - static Key keys[] = { ---- a//dwm.c 2010-06-04 12:39:15.000000000 +0200 -+++ b/dwm.c 2010-11-03 20:36:50.000000000 +0100 -@@ -48,6 +48,7 @@ - #define LENGTH(X) (sizeof X / sizeof X[0]) - #define MAX(A, B) ((A) > (B) ? (A) : (B)) - #define MIN(A, B) ((A) < (B) ? (A) : (B)) -+#define MAXCOLORS 8 - #define MOUSEMASK (BUTTONMASK|PointerMotionMask) - #define WIDTH(X) ((X)->w + 2 * (X)->bw) - #define HEIGHT(X) ((X)->h + 2 * (X)->bw) -@@ -97,8 +98,7 @@ - - typedef struct { - int x, y, w, h; -- unsigned long norm[ColLast]; -- unsigned long sel[ColLast]; -+ unsigned long colors[MAXCOLORS][ColLast]; - Drawable drawable; - GC gc; - struct { -@@ -175,8 +175,9 @@ - static Monitor *dirtomon(int dir); - static void drawbar(Monitor *m); - static void drawbars(void); --static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]); --static void drawtext(const char *text, unsigned long col[ColLast], Bool invert); -+static void drawcoloredtext(char *text); -+static void drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]); -+static void drawtext(const char *text, unsigned long col[ColLast], Bool pad); - static void enternotify(XEvent *e); - static void expose(XEvent *e); - static void focus(Client *c); -@@ -696,14 +697,13 @@ - dc.x = 0; - for(i = 0; i < LENGTH(tags); i++) { - dc.w = TEXTW(tags[i]); -- col = m->tagset[m->seltags] & 1 << i ? dc.sel : dc.norm; -- drawtext(tags[i], col, urg & 1 << i); -- drawsquare(m == selmon && selmon->sel && selmon->sel->tags & 1 << i, -- occ & 1 << i, urg & 1 << i, col); -+ col = dc.colors[ (m->tagset[m->seltags] & 1 << i ? 1:(urg & 1 << i ? 2:0))]; -+ drawtext(tags[i], col, True); -+ drawsquare(m == selmon && selmon->sel && selmon->sel->tags & 1 << i, occ & 1 << i, col); - dc.x += dc.w; - } - dc.w = blw = TEXTW(m->ltsymbol); -- drawtext(m->ltsymbol, dc.norm, False); -+ drawtext(m->ltsymbol, dc.colors[0], True); - dc.x += dc.w; - x = dc.x; - if(m == selmon) { /* status is only drawn on selected monitor */ -@@ -713,19 +713,19 @@ - dc.x = x; - dc.w = m->ww - x; - } -- drawtext(stext, dc.norm, False); -+ drawcoloredtext(stext); - } - else - dc.x = m->ww; - if((dc.w = dc.x - x) > bh) { - dc.x = x; - if(m->sel) { -- col = m == selmon ? dc.sel : dc.norm; -- drawtext(m->sel->name, col, False); -- drawsquare(m->sel->isfixed, m->sel->isfloating, False, col); -+ col = m == selmon ? dc.colors[1] : dc.colors[0]; -+ drawtext(m->sel->name, col, True); -+ drawsquare(m->sel->isfixed, m->sel->isfloating, col); - } - else -- drawtext(NULL, dc.norm, False); -+ drawtext(NULL, dc.colors[0], False); - } - XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->ww, bh, 0, 0); - XSync(dpy, False); -@@ -740,12 +740,42 @@ - } - - void --drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) { -+drawcoloredtext(char *text) { -+ Bool first=True; -+ char *buf = text, *ptr = buf, c = 1; -+ unsigned long *col = dc.colors[0]; -+ int i, ox = dc.x; -+ -+ while( *ptr ) { -+ for( i = 0; *ptr < 0 || *ptr > NUMCOLORS; i++, ptr++); -+ if( !*ptr ) break; -+ c=*ptr; -+ *ptr=0; -+ if( i ) { -+ dc.w = selmon->ww - dc.x; -+ drawtext(buf, col, first); -+ dc.x += textnw(buf, i) + textnw(&c,1); -+ if( first ) dc.x += ( dc.font.ascent + dc.font.descent ) / 2; -+ first = False; -+ } else if( first ) { -+ ox = dc.x += textnw(&c,1); -+ } -+ *ptr = c; -+ col = dc.colors[ c-1 ]; -+ buf = ++ptr; -+ } -+ if( !first ) dc.x-=(dc.font.ascent+dc.font.descent)/2; -+ drawtext(buf, col, True); -+ dc.x = ox; -+} -+ -+void -+drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]) { - int x; - XGCValues gcv; - XRectangle r = { dc.x, dc.y, dc.w, dc.h }; - -- gcv.foreground = col[invert ? ColBG : ColFG]; -+ gcv.foreground = col[ ColFG ]; - XChangeGC(dpy, dc.gc, GCForeground, &gcv); - x = (dc.font.ascent + dc.font.descent + 2) / 4; - r.x = dc.x + 1; -@@ -761,18 +791,18 @@ - } - - void --drawtext(const char *text, unsigned long col[ColLast], Bool invert) { -+drawtext(const char *text, unsigned long col[ColLast], Bool pad) { - char buf[256]; - int i, x, y, h, len, olen; - XRectangle r = { dc.x, dc.y, dc.w, dc.h }; - -- XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]); -+ XSetForeground(dpy, dc.gc, col[ ColBG ]); - XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); - if(!text) - return; - olen = strlen(text); -- h = dc.font.ascent + dc.font.descent; -- y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent; -+ h = pad ? (dc.font.ascent + dc.font.descent) : 0; -+ y = dc.y + ((dc.h + dc.font.ascent - dc.font.descent) / 2); - x = dc.x + (h / 2); - /* shorten text if necessary */ - for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w - h; len--); -@@ -781,7 +811,7 @@ - memcpy(buf, text, len); - if(len < olen) - for(i = len; i && i > len - 3; buf[--i] = '.'); -- XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]); -+ XSetForeground(dpy, dc.gc, col[ ColFG ]); - if(dc.font.set) - XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len); - else -@@ -830,7 +860,7 @@ - detachstack(c); - attachstack(c); - grabbuttons(c, True); -- XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]); -+ XSetWindowBorder(dpy, c->win, dc.colors[1][ColBorder]); - XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); - } - else -@@ -1139,7 +1169,7 @@ - } - wc.border_width = c->bw; - XConfigureWindow(dpy, w, CWBorderWidth, &wc); -- XSetWindowBorder(dpy, w, dc.norm[ColBorder]); -+ XSetWindowBorder(dpy, w, dc.colors[0][ColBorder]); - configure(c); /* propagates border_width, if size doesn't change */ - updatesizehints(c); - XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); -@@ -1544,12 +1574,11 @@ - cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); - cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); - /* init appearance */ -- dc.norm[ColBorder] = getcolor(normbordercolor); -- dc.norm[ColBG] = getcolor(normbgcolor); -- dc.norm[ColFG] = getcolor(normfgcolor); -- dc.sel[ColBorder] = getcolor(selbordercolor); -- dc.sel[ColBG] = getcolor(selbgcolor); -- dc.sel[ColFG] = getcolor(selfgcolor); -+ for(int i=0; i<NUMCOLORS; i++) { -+ dc.colors[i][ColBorder] = getcolor( colors[i][ColBorder] ); -+ dc.colors[i][ColFG] = getcolor( colors[i][ColFG] ); -+ dc.colors[i][ColBG] = getcolor( colors[i][ColBG] ); -+ } - dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen)); - dc.gc = XCreateGC(dpy, root, 0, NULL); - XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); -@@ -1711,7 +1740,7 @@ - if(!c) - return; - grabbuttons(c, False); -- XSetWindowBorder(dpy, c->win, dc.norm[ColBorder]); -+ XSetWindowBorder(dpy, c->win, dc.colors[0][ColBorder]); - if(setfocus) - XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); - } diff --git a/dwm.suckless.org/patches/historical/dwm-6.0-tab-v2.diff b/dwm.suckless.org/patches/historical/dwm-6.0-tab-v2.diff @@ -1,720 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 77ff358..666b9c0 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -12,6 +12,13 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ - static const unsigned int snap = 32; /* snap pixel */ - static const Bool showbar = True; /* False means no bar */ - static const Bool topbar = True; /* False means bottom bar */ -+/* Display modes of the tab bar: never shown, always shown, shown only in */ -+/* monocle mode in presence of several windows. */ -+/* Modes after showtab_nmodes are disabled */ -+enum showtab_modes { showtab_never, showtab_auto, showtab_nmodes, showtab_always}; -+static const int showtab = showtab_auto; /* Default tab bar show mode */ -+static const Bool toptab = False; /* False means bottom tab bar */ -+ - - /* tagging */ - static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; -@@ -25,7 +32,7 @@ static const Rule rules[] = { - /* 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 Bool resizehints = True; /* True means respect size hints in tiled resizals */ -+static const Bool resizehints = False; /* True means respect size hints in tiled resizals */ - - static const Layout layouts[] = { - /* symbol arrange function */ -@@ -54,6 +61,7 @@ static Key keys[] = { - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, - { MODKEY, XK_b, togglebar, {0} }, -+ { MODKEY, XK_w, tabmode, {-1} }, - { MODKEY, XK_j, focusstack, {.i = +1 } }, - { MODKEY, XK_k, focusstack, {.i = -1 } }, - { MODKEY, XK_i, incnmaster, {.i = +1 } }, -@@ -101,5 +109,6 @@ static Button buttons[] = { - { ClkTagBar, 0, Button3, toggleview, {0} }, - { ClkTagBar, MODKEY, Button1, tag, {0} }, - { ClkTagBar, MODKEY, Button3, toggletag, {0} }, -+ { ClkTabBar, 0, Button1, focuswin, {0} }, - }; - -diff --git a/dwm.1 b/dwm.1 -index 5268a06..d213208 100644 ---- a/dwm.1 -+++ b/dwm.1 -@@ -19,14 +19,22 @@ layout applied. - 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. -+Each screen contains two small status bars. -+.P -+One bar 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 -+Another bar contains a tab for each window of the current view and allows -+navigation from window to window, especially in the monocle mode. The different -+display modes of this bar are described under the Mod1\-w Keybord command -+section. When a single tag is selected, that tag is recalled in the left corner -+of the tab bar. - .P - dwm draws a small border around windows to indicate the focus state. - .SH OPTIONS -@@ -43,7 +51,8 @@ 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. -+label toggles between tiled and floating layout, click on a window name in the -+tab bar brings focus to that window. - .TP - .B Button3 - click on a tag label adds/removes all windows with that tag to/from the view. -@@ -104,6 +113,12 @@ Increase master area size. - .B Mod1\-h - Decrease master area size. - .TP -+.B Mod1\-w -+Cycle over the tab bar display modes: never displayed, always displayed, -+displayed only in monocle mode when the view contains than one window (auto -+mode). Some display modes can be disabled in the configuration, config.h. In -+the default configuration only "always" and "auto" display modes are enabled. -+.TP - .B Mod1\-Return - Zooms/cycles focused window to/from master area (tiled layouts only). - .TP -diff --git a/dwm.c b/dwm.c -index 1d78655..a892b7a 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -44,7 +44,7 @@ - #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))) -+ * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) - #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) - #define LENGTH(X) (sizeof X / sizeof X[0]) - #define MAX(A, B) ((A) > (B) ? (A) : (B)) -@@ -62,7 +62,7 @@ enum { NetSupported, NetWMName, NetWMState, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetLast }; /* EWMH atoms */ - enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ --enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, -+enum { ClkTagBar, ClkTabBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, - ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ - - typedef union { -@@ -102,6 +102,7 @@ typedef struct { - unsigned long norm[ColLast]; - unsigned long sel[ColLast]; - Drawable drawable; -+ Drawable tabdrawable; - GC gc; - struct { - int ascent; -@@ -124,24 +125,32 @@ typedef struct { - void (*arrange)(Monitor *); - } Layout; - -+#define MAXTABS 50 -+ - struct Monitor { - char ltsymbol[16]; - float mfact; - int nmaster; - int num; - int by; /* bar geometry */ -+ int ty; /* tab bar geometry */ - int mx, my, mw, mh; /* screen size */ - int wx, wy, ww, wh; /* window area */ - unsigned int seltags; - unsigned int sellt; - unsigned int tagset[2]; - Bool showbar; -+ Bool showtab; - Bool topbar; -+ Bool toptab; - Client *clients; - Client *sel; - Client *stack; - Monitor *next; - Window barwin; -+ Window tabwin; -+ int ntabs; -+ int tab_widths[MAXTABS]; - const Layout *lt[2]; - }; - -@@ -178,11 +187,15 @@ static void die(const char *errstr, ...); - static Monitor *dirtomon(int dir); - static void drawbar(Monitor *m); - static void drawbars(void); -+static void drawtab(Monitor *m); -+static void drawtabs(void); - static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]); --static void drawtext(const char *text, unsigned long col[ColLast], Bool invert); -+static void drawtext(Drawable drawable, const char *text, unsigned long col[ColLast], Bool invert); -+//static void drawtabtext(const char *text, unsigned long col[ColLast], Bool invert); - static void enternotify(XEvent *e); - static void expose(XEvent *e); - static void focus(Client *c); -+static void focuswin(const Arg* arg); - static void focusin(XEvent *e); - static void focusmon(const Arg *arg); - static void focusstack(const Arg *arg); -@@ -229,6 +242,7 @@ static void tagmon(const Arg *arg); - static int textnw(const char *text, unsigned int len); - static void tile(Monitor *); - static void togglebar(const Arg *arg); -+static void tabmode(const Arg *arg); - static void togglefloating(const Arg *arg); - static void toggletag(const Arg *arg); - static void toggleview(const Arg *arg); -@@ -258,6 +272,7 @@ static char stext[256]; - static int screen; - static int sw, sh; /* X display screen geometry width, height */ - static int bh, blw = 0; /* bar geometry */ -+static int th = 0; /* tab bar geometry */ - static int (*xerrorxlib)(Display *, XErrorEvent *); - static unsigned int numlockmask = 0; - static void (*handler[LASTEvent]) (XEvent *) = { -@@ -405,6 +420,9 @@ arrange(Monitor *m) { - - void - arrangemon(Monitor *m) { -+ updatebarpos(m); -+ XMoveResizeWindow(dpy, m->tabwin, m->wx, m->ty, m->ww, th); -+ - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); - if(m->lt[m->sellt]->arrange) - m->lt[m->sellt]->arrange(m); -@@ -454,14 +472,32 @@ buttonpress(XEvent *e) { - else - click = ClkWinTitle; - } -+ if(ev->window == selmon->tabwin) { -+ i = 0; x = 0; -+ for(c = selmon->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ x += selmon->tab_widths[i]; -+ if (ev->x > x) -+ ++i; -+ else -+ break; -+ if(i >= m->ntabs) break; -+ } -+ if(c) { -+ click = ClkTabBar; -+ arg.ui = i; -+ } -+ } - else if((c = wintoclient(ev->window))) { - focus(c); - 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); -+ && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)){ -+ buttons[i].func(((click == ClkTagBar || click == ClkTabBar) -+ && buttons[i].arg.i == 0) ? &arg : &buttons[i].arg); -+ } - } - - void -@@ -491,6 +527,7 @@ cleanup(void) { - XFreeFont(dpy, dc.font.xfont); - XUngrabKey(dpy, AnyKey, AnyModifier, root); - XFreePixmap(dpy, dc.drawable); -+ XFreePixmap(dpy, dc.tabdrawable); - XFreeGC(dpy, dc.gc); - XFreeCursor(dpy, cursor[CurNormal]); - XFreeCursor(dpy, cursor[CurResize]); -@@ -513,6 +550,8 @@ cleanupmon(Monitor *mon) { - } - XUnmapWindow(dpy, mon->barwin); - XDestroyWindow(dpy, mon->barwin); -+ XUnmapWindow(dpy, mon->tabwin); -+ XDestroyWindow(dpy, mon->tabwin); - free(mon); - } - -@@ -538,7 +577,7 @@ clientmessage(XEvent *e) { - 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))); -+ || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); - } - else if(cme->message_type == netatom[NetActiveWindow]) { - if(!ISVISIBLE(c)) { -@@ -581,9 +620,13 @@ configurenotify(XEvent *e) { - if(dc.drawable != 0) - XFreePixmap(dpy, dc.drawable); - dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); -+ if(dc.tabdrawable != 0) -+ XFreePixmap(dpy, dc.tabdrawable); -+ dc.tabdrawable = XCreatePixmap(dpy, root, sw, th, DefaultDepth(dpy, screen)); - updatebars(); -- for(m = mons; m; m = m->next) -+ for(m = mons; m; m = m->next){ - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); -+ } - focus(NULL); - arrange(NULL); - } -@@ -653,7 +696,10 @@ createmon(void) { - m->mfact = mfact; - m->nmaster = nmaster; - m->showbar = showbar; -+ m->showtab = showtab; - m->topbar = topbar; -+ m->toptab = toptab; -+ m->ntabs = 0; - m->lt[0] = &layouts[0]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); -@@ -731,13 +777,13 @@ drawbar(Monitor *m) { - for(i = 0; i < LENGTH(tags); i++) { - dc.w = TEXTW(tags[i]); - col = m->tagset[m->seltags] & 1 << i ? dc.sel : dc.norm; -- drawtext(tags[i], col, urg & 1 << i); -+ drawtext(dc.drawable, tags[i], col, urg & 1 << i); - drawsquare(m == selmon && selmon->sel && selmon->sel->tags & 1 << i, -- occ & 1 << i, urg & 1 << i, col); -+ occ & 1 << i, urg & 1 << i, col); - dc.x += dc.w; - } - dc.w = blw = TEXTW(m->ltsymbol); -- drawtext(m->ltsymbol, dc.norm, False); -+ drawtext(dc.drawable, m->ltsymbol, dc.norm, False); - dc.x += dc.w; - x = dc.x; - if(m == selmon) { /* status is only drawn on selected monitor */ -@@ -747,19 +793,20 @@ drawbar(Monitor *m) { - dc.x = x; - dc.w = m->ww - x; - } -- drawtext(stext, dc.norm, False); -+ drawtext(dc.drawable, stext, dc.norm, False); - } - else - dc.x = m->ww; - if((dc.w = dc.x - x) > bh) { - dc.x = x; - if(m->sel) { -- col = m == selmon ? dc.sel : dc.norm; -- drawtext(m->sel->name, col, False); -+ // col = m == selmon ? dc.sel : dc.norm; -+ // drawtext(dc.drawable, m->sel->name, col, False); -+ drawtext(dc.drawable, m->sel->name, dc.norm, False); - drawsquare(m->sel->isfixed, m->sel->isfloating, False, col); - } - else -- drawtext(NULL, dc.norm, False); -+ drawtext(dc.drawable, NULL, dc.norm, False); - } - XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->ww, bh, 0, 0); - XSync(dpy, False); -@@ -774,6 +821,104 @@ drawbars(void) { - } - - void -+drawtabs(void) { -+ Monitor *m; -+ -+ for(m = mons; m; m = m->next) -+ drawtab(m); -+} -+ -+static int -+cmpint(const void *p1, const void *p2) { -+ /* The actual arguments to this function are "pointers to -+ pointers to char", but strcmp(3) arguments are "pointers -+ to char", hence the following cast plus dereference */ -+ return *((int*) p1) > * (int*) p2; -+} -+ -+ -+void -+drawtab(Monitor *m) { -+ unsigned long *col; -+ Client *c; -+ int i; -+ int itag = -1; -+ char view_info[50]; -+ int view_info_w = 0; -+ int sorted_label_widths[MAXTABS]; -+ int tot_width; -+ int maxsize = bh; -+ dc.x = 0; -+ -+ //view_info: indicate the tag which is displayed in the view -+ for(i = 0; i < LENGTH(tags); ++i){ -+ if((selmon->tagset[selmon->seltags] >> i) & 1) { -+ if(itag >=0){ //more than one tag selected -+ itag = -1; -+ break; -+ } -+ itag = i; -+ } -+ } -+ if(0 <= itag && itag < LENGTH(tags)){ -+ snprintf(view_info, sizeof view_info, "[%s]", tags[itag]); -+ } else { -+ strncpy(view_info, "[...]", sizeof view_info); -+ } -+ view_info[sizeof(view_info) - 1 ] = 0; -+ view_info_w = TEXTW(view_info); -+ tot_width = view_info_w; -+ -+ /* Calculates number of labels and their width */ -+ m->ntabs = 0; -+ for(c = m->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ m->tab_widths[m->ntabs] = TEXTW(c->name); -+ tot_width += m->tab_widths[m->ntabs]; -+ ++m->ntabs; -+ if(m->ntabs >= MAXTABS) break; -+ } -+ -+ if(tot_width > m->ww){ //not enough space to display the labels, they need to be truncated -+ memcpy(sorted_label_widths, m->tab_widths, sizeof(int) * m->ntabs); -+ qsort(sorted_label_widths, m->ntabs, sizeof(int), cmpint); -+ tot_width = view_info_w; -+ for(i = 0; i < m->ntabs; ++i){ -+ if(tot_width + (m->ntabs - i) * sorted_label_widths[i] > m->ww) -+ break; -+ tot_width += sorted_label_widths[i]; -+ } -+ maxsize = (m->ww - tot_width) / (m->ntabs - i); -+ } else{ -+ maxsize = m->ww; -+ } -+ i = 0; -+ for(c = m->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ if(i >= m->ntabs) break; -+ if(m->tab_widths[i] > maxsize) m->tab_widths[i] = maxsize; -+ dc.w = m->tab_widths[i]; -+ col = (c == m->sel) ? dc.sel : dc.norm; -+ drawtext(dc.tabdrawable, c->name, col, 0); -+ dc.x += dc.w; -+ ++i; -+ } -+ -+ /* cleans interspace between window names and current viewed tag label */ -+ dc.w = m->ww - view_info_w - dc.x; -+ drawtext(dc.tabdrawable, NULL, dc.norm, 0); -+ -+ /* view info */ -+ dc.x += dc.w; -+ dc.w = view_info_w; -+ drawtext(dc.tabdrawable, view_info, dc.norm, 0); -+ -+ XCopyArea(dpy, dc.tabdrawable, m->tabwin, dc.gc, 0, 0, m->ww, th, 0, 0); -+ XSync(dpy, False); -+} -+ -+ -+void - drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) { - int x; - -@@ -785,13 +930,14 @@ drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) { - XDrawRectangle(dpy, dc.drawable, dc.gc, dc.x+1, dc.y+1, x, x); - } - -+ - void --drawtext(const char *text, unsigned long col[ColLast], Bool invert) { -+drawtext(Drawable drawable, const char *text, unsigned long col[ColLast], Bool invert) { - char buf[256]; - int i, x, y, h, len, olen; - - XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]); -- XFillRectangle(dpy, dc.drawable, dc.gc, dc.x, dc.y, dc.w, dc.h); -+ XFillRectangle(dpy, drawable, dc.gc, dc.x, dc.y, dc.w, dc.h); - if(!text) - return; - olen = strlen(text); -@@ -807,11 +953,12 @@ drawtext(const char *text, unsigned long col[ColLast], Bool invert) { - for(i = len; i && i > len - 3; buf[--i] = '.'); - XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]); - if(dc.font.set) -- XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len); -+ XmbDrawString(dpy, drawable, dc.font.set, dc.gc, x, y, buf, len); - else -- XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len); -+ XDrawString(dpy, drawable, dc.gc, x, y, buf, len); - } - -+ - void - enternotify(XEvent *e) { - Client *c; -@@ -836,8 +983,10 @@ expose(XEvent *e) { - Monitor *m; - XExposeEvent *ev = &e->xexpose; - -- if(ev->count == 0 && (m = wintomon(ev->window))) -+ if(ev->count == 0 && (m = wintomon(ev->window))){ - drawbar(m); -+ drawtab(m); -+ } - } - - void -@@ -862,6 +1011,7 @@ focus(Client *c) { - XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); - selmon->sel = c; - drawbars(); -+ drawtabs(); - } - - void -@@ -911,6 +1061,19 @@ focusstack(const Arg *arg) { - } - } - -+void -+focuswin(const Arg* arg){ -+ int iwin = arg->i; -+ Client* c = NULL; -+ for(c = selmon->clients; c && (iwin || !ISVISIBLE(c)) ; c = c->next){ -+ if(ISVISIBLE(c)) --iwin; -+ }; -+ if(c) { -+ focus(c); -+ restack(selmon); -+ } -+} -+ - Atom - getatomprop(Client *c, Atom prop) { - int di; -@@ -919,7 +1082,7 @@ getatomprop(Client *c, Atom prop) { - Atom da, atom = None; - - if(XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, -- &da, &di, &dl, &dl, &p) == Success && p) { -+ &da, &di, &dl, &dl, &p) == Success && p) { - atom = *(Atom *)p; - XFree(p); - } -@@ -954,7 +1117,7 @@ getstate(Window w) { - Atom real; - - if(XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], -- &real, &format, &n, &extra, (unsigned char **)&p) != Success) -+ &real, &format, &n, &extra, (unsigned char **)&p) != Success) - return -1; - if(n != 0) - result = *p; -@@ -999,13 +1162,13 @@ grabbuttons(Client *c, Bool focused) { - 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); -+ buttons[i].mask | modifiers[j], -+ c->win, False, BUTTONMASK, -+ GrabModeAsync, GrabModeSync, None, None); - } - else - XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, -- BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); -+ BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); - } - } - -@@ -1139,7 +1302,7 @@ manage(Window w, XWindowAttributes *wa) { - 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->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); -+ && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); - c->bw = borderpx; - - wc.border_width = c->bw; -@@ -1311,12 +1474,14 @@ propertynotify(XEvent *e) { - case XA_WM_HINTS: - updatewmhints(c); - drawbars(); -+ drawtabs(); - break; - } - if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { - updatetitle(c); - if(c == c->mon->sel) - drawbar(c->mon); -+ drawtab(c->mon); - } - if(ev->atom == netatom[NetWMWindowType]) - updatewindowtype(c); -@@ -1375,7 +1540,7 @@ resizemouse(const Arg *arg) { - ocx = c->x; - ocy = c->y; - if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, -- None, cursor[CurResize], CurrentTime) != GrabSuccess) -+ None, cursor[CurResize], CurrentTime) != GrabSuccess) - return; - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); - do { -@@ -1418,6 +1583,7 @@ restack(Monitor *m) { - XWindowChanges wc; - - drawbar(m); -+ drawtab(m); - if(!m->sel) - return; - if(m->sel->isfloating || !m->lt[m->sellt]->arrange) -@@ -1529,7 +1695,7 @@ void - setfullscreen(Client *c, Bool fullscreen) { - if(fullscreen) { - XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, -- PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); -+ PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); - c->isfullscreen = True; - c->oldstate = c->isfloating; - c->oldbw = c->bw; -@@ -1540,7 +1706,7 @@ setfullscreen(Client *c, Bool fullscreen) { - } - else { - XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, -- PropModeReplace, (unsigned char*)0, 0); -+ PropModeReplace, (unsigned char*)0, 0); - c->isfullscreen = False; - c->isfloating = c->oldstate; - c->bw = c->oldbw; -@@ -1594,6 +1760,7 @@ setup(void) { - sw = DisplayWidth(dpy, screen); - sh = DisplayHeight(dpy, screen); - bh = dc.h = dc.font.height + 2; -+ th = bh; - updategeom(); - /* init atoms */ - wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); -@@ -1619,6 +1786,7 @@ setup(void) { - dc.sel[ColBG] = getcolor(selbgcolor); - dc.sel[ColFG] = getcolor(selfgcolor); - dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen)); -+ dc.tabdrawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), th, DefaultDepth(dpy, screen)); - dc.gc = XCreateGC(dpy, root, 0, NULL); - XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); - if(!dc.font.set) -@@ -1632,7 +1800,7 @@ setup(void) { - /* select for events */ - wa.cursor = cursor[CurNormal]; - wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask|PointerMotionMask -- |EnterWindowMask|LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; -+ |EnterWindowMask|LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; - XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); - XSelectInput(dpy, root, wa.event_mask); - grabkeys(); -@@ -1736,6 +1904,16 @@ togglebar(const Arg *arg) { - } - - void -+tabmode(const Arg *arg) { -+ if(arg && arg->i >= 0) -+ selmon->showtab = arg->ui % showtab_nmodes; -+ else -+ selmon->showtab = (selmon->showtab + 1 ) % showtab_nmodes; -+ arrange(selmon); -+} -+ -+ -+void - togglefloating(const Arg *arg) { - if(!selmon->sel) - return; -@@ -1828,24 +2006,47 @@ updatebars(void) { - }; - for(m = mons; m; m = m->next) { - m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), -- CopyFromParent, DefaultVisual(dpy, screen), -- CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); -+ CopyFromParent, DefaultVisual(dpy, screen), -+ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); - XDefineCursor(dpy, m->barwin, cursor[CurNormal]); - XMapRaised(dpy, m->barwin); -+ m->tabwin = XCreateWindow(dpy, root, m->wx, m->ty, m->ww, th, 0, DefaultDepth(dpy, screen), -+ CopyFromParent, DefaultVisual(dpy, screen), -+ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); -+ XDefineCursor(dpy, m->tabwin, cursor[CurNormal]); -+ XMapRaised(dpy, m->tabwin); - } - } - - void - updatebarpos(Monitor *m) { -+ Client *c; -+ int nvis = 0; -+ - m->wy = m->my; - m->wh = m->mh; - if(m->showbar) { - m->wh -= bh; - m->by = m->topbar ? m->wy : m->wy + m->wh; -- m->wy = m->topbar ? m->wy + bh : m->wy; -- } -- else -+ if ( m->topbar ) -+ m->wy += bh; -+ } else { - m->by = -bh; -+ } -+ -+ for(c = m->clients; c; c = c->next){ -+ if(ISVISIBLE(c)) ++nvis; -+ } -+ -+ if(m->showtab == showtab_always -+ || ((m->showtab == showtab_auto) && (nvis > 1) && (m->lt[m->sellt]->arrange == monocle))){ -+ m->wh -= th; -+ m->ty = m->toptab ? m->wy : m->wy + m->wh; -+ if ( m->toptab ) -+ m->wy += th; -+ } else { -+ m->ty = -th; -+ } - } - - Bool -@@ -1992,7 +2193,7 @@ updatesizehints(Client *c) { - else - c->maxa = c->mina = 0.0; - c->isfixed = (c->maxw && c->minw && c->maxh && c->minh -- && c->maxw == c->minw && c->maxh == c->minh); -+ && c->maxw == c->minw && c->maxh == c->minh); - } - - void -@@ -2073,7 +2274,7 @@ wintomon(Window w) { - if(w == root && getrootptr(&x, &y)) - return recttomon(x, y, 1, 1); - for(m = mons; m; m = m->next) -- if(w == m->barwin) -+ if(w == m->barwin || w == m->tabwin) - return m; - if((c = wintoclient(w))) - return c->mon; diff --git a/dwm.suckless.org/patches/historical/dwm-6.0-tab-v2a.diff b/dwm.suckless.org/patches/historical/dwm-6.0-tab-v2a.diff @@ -1,720 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 77ff358..666b9c0 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -12,6 +12,13 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ - static const unsigned int snap = 32; /* snap pixel */ - static const Bool showbar = True; /* False means no bar */ - static const Bool topbar = True; /* False means bottom bar */ -+/* Display modes of the tab bar: never shown, always shown, shown only in */ -+/* monocle mode in presence of several windows. */ -+/* Modes after showtab_nmodes are disabled */ -+enum showtab_modes { showtab_never, showtab_auto, showtab_nmodes, showtab_always}; -+static const int showtab = showtab_auto; /* Default tab bar show mode */ -+static const Bool toptab = False; /* False means bottom tab bar */ -+ - - /* tagging */ - static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; -@@ -25,7 +32,7 @@ static const Rule rules[] = { - /* 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 Bool resizehints = True; /* True means respect size hints in tiled resizals */ -+static const Bool resizehints = False; /* True means respect size hints in tiled resizals */ - - static const Layout layouts[] = { - /* symbol arrange function */ -@@ -54,6 +61,7 @@ static Key keys[] = { - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, - { MODKEY, XK_b, togglebar, {0} }, -+ { MODKEY, XK_w, tabmode, {-1} }, - { MODKEY, XK_j, focusstack, {.i = +1 } }, - { MODKEY, XK_k, focusstack, {.i = -1 } }, - { MODKEY, XK_i, incnmaster, {.i = +1 } }, -@@ -101,5 +109,6 @@ static Button buttons[] = { - { ClkTagBar, 0, Button3, toggleview, {0} }, - { ClkTagBar, MODKEY, Button1, tag, {0} }, - { ClkTagBar, MODKEY, Button3, toggletag, {0} }, -+ { ClkTabBar, 0, Button1, focuswin, {0} }, - }; - -diff --git a/dwm.1 b/dwm.1 -index 5268a06..19b4f1d 100644 ---- a/dwm.1 -+++ b/dwm.1 -@@ -19,14 +19,22 @@ layout applied. - 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. -+Each screen contains two small status bars. -+.P -+One bar 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 -+Another bar contains a tab for each window of the current view and allows -+navigation between windows, especially in the monocle mode. The different -+display modes of this bar are described under the Mod1\-w Keybord command -+section. When a single tag is selected, that tag is indicated in the left corner -+of the tab bar. - .P - dwm draws a small border around windows to indicate the focus state. - .SH OPTIONS -@@ -43,7 +51,8 @@ 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. -+label toggles between tiled and floating layout, click on a window name in the -+tab bar brings focus to that window. - .TP - .B Button3 - click on a tag label adds/removes all windows with that tag to/from the view. -@@ -104,6 +113,12 @@ Increase master area size. - .B Mod1\-h - Decrease master area size. - .TP -+.B Mod1\-w -+Cycle over the tab bar display modes: never displayed, always displayed, -+displayed only in monocle mode when the view contains than one window (auto -+mode). Some display modes can be disabled in the configuration, config.h. In -+the default configuration only "never" and "auto" display modes are enabled. -+.TP - .B Mod1\-Return - Zooms/cycles focused window to/from master area (tiled layouts only). - .TP -diff --git a/dwm.c b/dwm.c -index 1d78655..a892b7a 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -44,7 +44,7 @@ - #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))) -+ * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) - #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) - #define LENGTH(X) (sizeof X / sizeof X[0]) - #define MAX(A, B) ((A) > (B) ? (A) : (B)) -@@ -62,7 +62,7 @@ enum { NetSupported, NetWMName, NetWMState, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetLast }; /* EWMH atoms */ - enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ --enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, -+enum { ClkTagBar, ClkTabBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, - ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ - - typedef union { -@@ -102,6 +102,7 @@ typedef struct { - unsigned long norm[ColLast]; - unsigned long sel[ColLast]; - Drawable drawable; -+ Drawable tabdrawable; - GC gc; - struct { - int ascent; -@@ -124,24 +125,32 @@ typedef struct { - void (*arrange)(Monitor *); - } Layout; - -+#define MAXTABS 50 -+ - struct Monitor { - char ltsymbol[16]; - float mfact; - int nmaster; - int num; - int by; /* bar geometry */ -+ int ty; /* tab bar geometry */ - int mx, my, mw, mh; /* screen size */ - int wx, wy, ww, wh; /* window area */ - unsigned int seltags; - unsigned int sellt; - unsigned int tagset[2]; - Bool showbar; -+ Bool showtab; - Bool topbar; -+ Bool toptab; - Client *clients; - Client *sel; - Client *stack; - Monitor *next; - Window barwin; -+ Window tabwin; -+ int ntabs; -+ int tab_widths[MAXTABS]; - const Layout *lt[2]; - }; - -@@ -178,11 +187,15 @@ static void die(const char *errstr, ...); - static Monitor *dirtomon(int dir); - static void drawbar(Monitor *m); - static void drawbars(void); -+static void drawtab(Monitor *m); -+static void drawtabs(void); - static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]); --static void drawtext(const char *text, unsigned long col[ColLast], Bool invert); -+static void drawtext(Drawable drawable, const char *text, unsigned long col[ColLast], Bool invert); -+//static void drawtabtext(const char *text, unsigned long col[ColLast], Bool invert); - static void enternotify(XEvent *e); - static void expose(XEvent *e); - static void focus(Client *c); -+static void focuswin(const Arg* arg); - static void focusin(XEvent *e); - static void focusmon(const Arg *arg); - static void focusstack(const Arg *arg); -@@ -229,6 +242,7 @@ static void tagmon(const Arg *arg); - static int textnw(const char *text, unsigned int len); - static void tile(Monitor *); - static void togglebar(const Arg *arg); -+static void tabmode(const Arg *arg); - static void togglefloating(const Arg *arg); - static void toggletag(const Arg *arg); - static void toggleview(const Arg *arg); -@@ -258,6 +272,7 @@ static char stext[256]; - static int screen; - static int sw, sh; /* X display screen geometry width, height */ - static int bh, blw = 0; /* bar geometry */ -+static int th = 0; /* tab bar geometry */ - static int (*xerrorxlib)(Display *, XErrorEvent *); - static unsigned int numlockmask = 0; - static void (*handler[LASTEvent]) (XEvent *) = { -@@ -405,6 +420,9 @@ arrange(Monitor *m) { - - void - arrangemon(Monitor *m) { -+ updatebarpos(m); -+ XMoveResizeWindow(dpy, m->tabwin, m->wx, m->ty, m->ww, th); -+ - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); - if(m->lt[m->sellt]->arrange) - m->lt[m->sellt]->arrange(m); -@@ -454,14 +472,32 @@ buttonpress(XEvent *e) { - else - click = ClkWinTitle; - } -+ if(ev->window == selmon->tabwin) { -+ i = 0; x = 0; -+ for(c = selmon->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ x += selmon->tab_widths[i]; -+ if (ev->x > x) -+ ++i; -+ else -+ break; -+ if(i >= m->ntabs) break; -+ } -+ if(c) { -+ click = ClkTabBar; -+ arg.ui = i; -+ } -+ } - else if((c = wintoclient(ev->window))) { - focus(c); - 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); -+ && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)){ -+ buttons[i].func(((click == ClkTagBar || click == ClkTabBar) -+ && buttons[i].arg.i == 0) ? &arg : &buttons[i].arg); -+ } - } - - void -@@ -491,6 +527,7 @@ cleanup(void) { - XFreeFont(dpy, dc.font.xfont); - XUngrabKey(dpy, AnyKey, AnyModifier, root); - XFreePixmap(dpy, dc.drawable); -+ XFreePixmap(dpy, dc.tabdrawable); - XFreeGC(dpy, dc.gc); - XFreeCursor(dpy, cursor[CurNormal]); - XFreeCursor(dpy, cursor[CurResize]); -@@ -513,6 +550,8 @@ cleanupmon(Monitor *mon) { - } - XUnmapWindow(dpy, mon->barwin); - XDestroyWindow(dpy, mon->barwin); -+ XUnmapWindow(dpy, mon->tabwin); -+ XDestroyWindow(dpy, mon->tabwin); - free(mon); - } - -@@ -538,7 +577,7 @@ clientmessage(XEvent *e) { - 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))); -+ || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); - } - else if(cme->message_type == netatom[NetActiveWindow]) { - if(!ISVISIBLE(c)) { -@@ -581,9 +620,13 @@ configurenotify(XEvent *e) { - if(dc.drawable != 0) - XFreePixmap(dpy, dc.drawable); - dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); -+ if(dc.tabdrawable != 0) -+ XFreePixmap(dpy, dc.tabdrawable); -+ dc.tabdrawable = XCreatePixmap(dpy, root, sw, th, DefaultDepth(dpy, screen)); - updatebars(); -- for(m = mons; m; m = m->next) -+ for(m = mons; m; m = m->next){ - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); -+ } - focus(NULL); - arrange(NULL); - } -@@ -653,7 +696,10 @@ createmon(void) { - m->mfact = mfact; - m->nmaster = nmaster; - m->showbar = showbar; -+ m->showtab = showtab; - m->topbar = topbar; -+ m->toptab = toptab; -+ m->ntabs = 0; - m->lt[0] = &layouts[0]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); -@@ -731,13 +777,13 @@ drawbar(Monitor *m) { - for(i = 0; i < LENGTH(tags); i++) { - dc.w = TEXTW(tags[i]); - col = m->tagset[m->seltags] & 1 << i ? dc.sel : dc.norm; -- drawtext(tags[i], col, urg & 1 << i); -+ drawtext(dc.drawable, tags[i], col, urg & 1 << i); - drawsquare(m == selmon && selmon->sel && selmon->sel->tags & 1 << i, -- occ & 1 << i, urg & 1 << i, col); -+ occ & 1 << i, urg & 1 << i, col); - dc.x += dc.w; - } - dc.w = blw = TEXTW(m->ltsymbol); -- drawtext(m->ltsymbol, dc.norm, False); -+ drawtext(dc.drawable, m->ltsymbol, dc.norm, False); - dc.x += dc.w; - x = dc.x; - if(m == selmon) { /* status is only drawn on selected monitor */ -@@ -747,19 +793,20 @@ drawbar(Monitor *m) { - dc.x = x; - dc.w = m->ww - x; - } -- drawtext(stext, dc.norm, False); -+ drawtext(dc.drawable, stext, dc.norm, False); - } - else - dc.x = m->ww; - if((dc.w = dc.x - x) > bh) { - dc.x = x; - if(m->sel) { -- col = m == selmon ? dc.sel : dc.norm; -- drawtext(m->sel->name, col, False); -+ // col = m == selmon ? dc.sel : dc.norm; -+ // drawtext(dc.drawable, m->sel->name, col, False); -+ drawtext(dc.drawable, m->sel->name, dc.norm, False); - drawsquare(m->sel->isfixed, m->sel->isfloating, False, col); - } - else -- drawtext(NULL, dc.norm, False); -+ drawtext(dc.drawable, NULL, dc.norm, False); - } - XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->ww, bh, 0, 0); - XSync(dpy, False); -@@ -774,6 +821,104 @@ drawbars(void) { - } - - void -+drawtabs(void) { -+ Monitor *m; -+ -+ for(m = mons; m; m = m->next) -+ drawtab(m); -+} -+ -+static int -+cmpint(const void *p1, const void *p2) { -+ /* The actual arguments to this function are "pointers to -+ pointers to char", but strcmp(3) arguments are "pointers -+ to char", hence the following cast plus dereference */ -+ return *((int*) p1) > * (int*) p2; -+} -+ -+ -+void -+drawtab(Monitor *m) { -+ unsigned long *col; -+ Client *c; -+ int i; -+ int itag = -1; -+ char view_info[50]; -+ int view_info_w = 0; -+ int sorted_label_widths[MAXTABS]; -+ int tot_width; -+ int maxsize = bh; -+ dc.x = 0; -+ -+ //view_info: indicate the tag which is displayed in the view -+ for(i = 0; i < LENGTH(tags); ++i){ -+ if((selmon->tagset[selmon->seltags] >> i) & 1) { -+ if(itag >=0){ //more than one tag selected -+ itag = -1; -+ break; -+ } -+ itag = i; -+ } -+ } -+ if(0 <= itag && itag < LENGTH(tags)){ -+ snprintf(view_info, sizeof view_info, "[%s]", tags[itag]); -+ } else { -+ strncpy(view_info, "[...]", sizeof view_info); -+ } -+ view_info[sizeof(view_info) - 1 ] = 0; -+ view_info_w = TEXTW(view_info); -+ tot_width = view_info_w; -+ -+ /* Calculates number of labels and their width */ -+ m->ntabs = 0; -+ for(c = m->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ m->tab_widths[m->ntabs] = TEXTW(c->name); -+ tot_width += m->tab_widths[m->ntabs]; -+ ++m->ntabs; -+ if(m->ntabs >= MAXTABS) break; -+ } -+ -+ if(tot_width > m->ww){ //not enough space to display the labels, they need to be truncated -+ memcpy(sorted_label_widths, m->tab_widths, sizeof(int) * m->ntabs); -+ qsort(sorted_label_widths, m->ntabs, sizeof(int), cmpint); -+ tot_width = view_info_w; -+ for(i = 0; i < m->ntabs; ++i){ -+ if(tot_width + (m->ntabs - i) * sorted_label_widths[i] > m->ww) -+ break; -+ tot_width += sorted_label_widths[i]; -+ } -+ maxsize = (m->ww - tot_width) / (m->ntabs - i); -+ } else{ -+ maxsize = m->ww; -+ } -+ i = 0; -+ for(c = m->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ if(i >= m->ntabs) break; -+ if(m->tab_widths[i] > maxsize) m->tab_widths[i] = maxsize; -+ dc.w = m->tab_widths[i]; -+ col = (c == m->sel) ? dc.sel : dc.norm; -+ drawtext(dc.tabdrawable, c->name, col, 0); -+ dc.x += dc.w; -+ ++i; -+ } -+ -+ /* cleans interspace between window names and current viewed tag label */ -+ dc.w = m->ww - view_info_w - dc.x; -+ drawtext(dc.tabdrawable, NULL, dc.norm, 0); -+ -+ /* view info */ -+ dc.x += dc.w; -+ dc.w = view_info_w; -+ drawtext(dc.tabdrawable, view_info, dc.norm, 0); -+ -+ XCopyArea(dpy, dc.tabdrawable, m->tabwin, dc.gc, 0, 0, m->ww, th, 0, 0); -+ XSync(dpy, False); -+} -+ -+ -+void - drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) { - int x; - -@@ -785,13 +930,14 @@ drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) { - XDrawRectangle(dpy, dc.drawable, dc.gc, dc.x+1, dc.y+1, x, x); - } - -+ - void --drawtext(const char *text, unsigned long col[ColLast], Bool invert) { -+drawtext(Drawable drawable, const char *text, unsigned long col[ColLast], Bool invert) { - char buf[256]; - int i, x, y, h, len, olen; - - XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]); -- XFillRectangle(dpy, dc.drawable, dc.gc, dc.x, dc.y, dc.w, dc.h); -+ XFillRectangle(dpy, drawable, dc.gc, dc.x, dc.y, dc.w, dc.h); - if(!text) - return; - olen = strlen(text); -@@ -807,11 +953,12 @@ drawtext(const char *text, unsigned long col[ColLast], Bool invert) { - for(i = len; i && i > len - 3; buf[--i] = '.'); - XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]); - if(dc.font.set) -- XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len); -+ XmbDrawString(dpy, drawable, dc.font.set, dc.gc, x, y, buf, len); - else -- XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len); -+ XDrawString(dpy, drawable, dc.gc, x, y, buf, len); - } - -+ - void - enternotify(XEvent *e) { - Client *c; -@@ -836,8 +983,10 @@ expose(XEvent *e) { - Monitor *m; - XExposeEvent *ev = &e->xexpose; - -- if(ev->count == 0 && (m = wintomon(ev->window))) -+ if(ev->count == 0 && (m = wintomon(ev->window))){ - drawbar(m); -+ drawtab(m); -+ } - } - - void -@@ -862,6 +1011,7 @@ focus(Client *c) { - XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); - selmon->sel = c; - drawbars(); -+ drawtabs(); - } - - void -@@ -911,6 +1061,19 @@ focusstack(const Arg *arg) { - } - } - -+void -+focuswin(const Arg* arg){ -+ int iwin = arg->i; -+ Client* c = NULL; -+ for(c = selmon->clients; c && (iwin || !ISVISIBLE(c)) ; c = c->next){ -+ if(ISVISIBLE(c)) --iwin; -+ }; -+ if(c) { -+ focus(c); -+ restack(selmon); -+ } -+} -+ - Atom - getatomprop(Client *c, Atom prop) { - int di; -@@ -919,7 +1082,7 @@ getatomprop(Client *c, Atom prop) { - Atom da, atom = None; - - if(XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, -- &da, &di, &dl, &dl, &p) == Success && p) { -+ &da, &di, &dl, &dl, &p) == Success && p) { - atom = *(Atom *)p; - XFree(p); - } -@@ -954,7 +1117,7 @@ getstate(Window w) { - Atom real; - - if(XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], -- &real, &format, &n, &extra, (unsigned char **)&p) != Success) -+ &real, &format, &n, &extra, (unsigned char **)&p) != Success) - return -1; - if(n != 0) - result = *p; -@@ -999,13 +1162,13 @@ grabbuttons(Client *c, Bool focused) { - 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); -+ buttons[i].mask | modifiers[j], -+ c->win, False, BUTTONMASK, -+ GrabModeAsync, GrabModeSync, None, None); - } - else - XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, -- BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); -+ BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); - } - } - -@@ -1139,7 +1302,7 @@ manage(Window w, XWindowAttributes *wa) { - 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->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); -+ && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); - c->bw = borderpx; - - wc.border_width = c->bw; -@@ -1311,12 +1474,14 @@ propertynotify(XEvent *e) { - case XA_WM_HINTS: - updatewmhints(c); - drawbars(); -+ drawtabs(); - break; - } - if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { - updatetitle(c); - if(c == c->mon->sel) - drawbar(c->mon); -+ drawtab(c->mon); - } - if(ev->atom == netatom[NetWMWindowType]) - updatewindowtype(c); -@@ -1375,7 +1540,7 @@ resizemouse(const Arg *arg) { - ocx = c->x; - ocy = c->y; - if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, -- None, cursor[CurResize], CurrentTime) != GrabSuccess) -+ None, cursor[CurResize], CurrentTime) != GrabSuccess) - return; - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); - do { -@@ -1418,6 +1583,7 @@ restack(Monitor *m) { - XWindowChanges wc; - - drawbar(m); -+ drawtab(m); - if(!m->sel) - return; - if(m->sel->isfloating || !m->lt[m->sellt]->arrange) -@@ -1529,7 +1695,7 @@ void - setfullscreen(Client *c, Bool fullscreen) { - if(fullscreen) { - XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, -- PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); -+ PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); - c->isfullscreen = True; - c->oldstate = c->isfloating; - c->oldbw = c->bw; -@@ -1540,7 +1706,7 @@ setfullscreen(Client *c, Bool fullscreen) { - } - else { - XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, -- PropModeReplace, (unsigned char*)0, 0); -+ PropModeReplace, (unsigned char*)0, 0); - c->isfullscreen = False; - c->isfloating = c->oldstate; - c->bw = c->oldbw; -@@ -1594,6 +1760,7 @@ setup(void) { - sw = DisplayWidth(dpy, screen); - sh = DisplayHeight(dpy, screen); - bh = dc.h = dc.font.height + 2; -+ th = bh; - updategeom(); - /* init atoms */ - wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); -@@ -1619,6 +1786,7 @@ setup(void) { - dc.sel[ColBG] = getcolor(selbgcolor); - dc.sel[ColFG] = getcolor(selfgcolor); - dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen)); -+ dc.tabdrawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), th, DefaultDepth(dpy, screen)); - dc.gc = XCreateGC(dpy, root, 0, NULL); - XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); - if(!dc.font.set) -@@ -1632,7 +1800,7 @@ setup(void) { - /* select for events */ - wa.cursor = cursor[CurNormal]; - wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask|PointerMotionMask -- |EnterWindowMask|LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; -+ |EnterWindowMask|LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; - XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); - XSelectInput(dpy, root, wa.event_mask); - grabkeys(); -@@ -1736,6 +1904,16 @@ togglebar(const Arg *arg) { - } - - void -+tabmode(const Arg *arg) { -+ if(arg && arg->i >= 0) -+ selmon->showtab = arg->ui % showtab_nmodes; -+ else -+ selmon->showtab = (selmon->showtab + 1 ) % showtab_nmodes; -+ arrange(selmon); -+} -+ -+ -+void - togglefloating(const Arg *arg) { - if(!selmon->sel) - return; -@@ -1828,24 +2006,47 @@ updatebars(void) { - }; - for(m = mons; m; m = m->next) { - m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), -- CopyFromParent, DefaultVisual(dpy, screen), -- CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); -+ CopyFromParent, DefaultVisual(dpy, screen), -+ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); - XDefineCursor(dpy, m->barwin, cursor[CurNormal]); - XMapRaised(dpy, m->barwin); -+ m->tabwin = XCreateWindow(dpy, root, m->wx, m->ty, m->ww, th, 0, DefaultDepth(dpy, screen), -+ CopyFromParent, DefaultVisual(dpy, screen), -+ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); -+ XDefineCursor(dpy, m->tabwin, cursor[CurNormal]); -+ XMapRaised(dpy, m->tabwin); - } - } - - void - updatebarpos(Monitor *m) { -+ Client *c; -+ int nvis = 0; -+ - m->wy = m->my; - m->wh = m->mh; - if(m->showbar) { - m->wh -= bh; - m->by = m->topbar ? m->wy : m->wy + m->wh; -- m->wy = m->topbar ? m->wy + bh : m->wy; -- } -- else -+ if ( m->topbar ) -+ m->wy += bh; -+ } else { - m->by = -bh; -+ } -+ -+ for(c = m->clients; c; c = c->next){ -+ if(ISVISIBLE(c)) ++nvis; -+ } -+ -+ if(m->showtab == showtab_always -+ || ((m->showtab == showtab_auto) && (nvis > 1) && (m->lt[m->sellt]->arrange == monocle))){ -+ m->wh -= th; -+ m->ty = m->toptab ? m->wy : m->wy + m->wh; -+ if ( m->toptab ) -+ m->wy += th; -+ } else { -+ m->ty = -th; -+ } - } - - Bool -@@ -1992,7 +2193,7 @@ updatesizehints(Client *c) { - else - c->maxa = c->mina = 0.0; - c->isfixed = (c->maxw && c->minw && c->maxh && c->minh -- && c->maxw == c->minw && c->maxh == c->minh); -+ && c->maxw == c->minw && c->maxh == c->minh); - } - - void -@@ -2073,7 +2274,7 @@ wintomon(Window w) { - if(w == root && getrootptr(&x, &y)) - return recttomon(x, y, 1, 1); - for(m = mons; m; m = m->next) -- if(w == m->barwin) -+ if(w == m->barwin || w == m->tabwin) - return m; - if((c = wintoclient(w))) - return c->mon; diff --git a/dwm.suckless.org/patches/historical/dwm-6.0-tab-v2b.diff b/dwm.suckless.org/patches/historical/dwm-6.0-tab-v2b.diff @@ -1,720 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 77ff358..666b9c0 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -12,6 +12,13 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ - static const unsigned int snap = 32; /* snap pixel */ - static const Bool showbar = True; /* False means no bar */ - static const Bool topbar = True; /* False means bottom bar */ -+/* Display modes of the tab bar: never shown, always shown, shown only in */ -+/* monocle mode in presence of several windows. */ -+/* Modes after showtab_nmodes are disabled */ -+enum showtab_modes { showtab_never, showtab_auto, showtab_nmodes, showtab_always}; -+static const int showtab = showtab_auto; /* Default tab bar show mode */ -+static const Bool toptab = False; /* False means bottom tab bar */ -+ - - /* tagging */ - static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; -@@ -25,7 +32,7 @@ static const Rule rules[] = { - /* 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 Bool resizehints = True; /* True means respect size hints in tiled resizals */ -+static const Bool resizehints = False; /* True means respect size hints in tiled resizals */ - - static const Layout layouts[] = { - /* symbol arrange function */ -@@ -54,6 +61,7 @@ static Key keys[] = { - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, - { MODKEY, XK_b, togglebar, {0} }, -+ { MODKEY, XK_w, tabmode, {-1} }, - { MODKEY, XK_j, focusstack, {.i = +1 } }, - { MODKEY, XK_k, focusstack, {.i = -1 } }, - { MODKEY, XK_i, incnmaster, {.i = +1 } }, -@@ -101,5 +109,6 @@ static Button buttons[] = { - { ClkTagBar, 0, Button3, toggleview, {0} }, - { ClkTagBar, MODKEY, Button1, tag, {0} }, - { ClkTagBar, MODKEY, Button3, toggletag, {0} }, -+ { ClkTabBar, 0, Button1, focuswin, {0} }, - }; - -diff --git a/dwm.1 b/dwm.1 -index 5268a06..19b4f1d 100644 ---- a/dwm.1 -+++ b/dwm.1 -@@ -19,14 +19,22 @@ layout applied. - 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. -+Each screen contains two small status bars. -+.P -+One bar 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 -+Another bar contains a tab for each window of the current view and allows -+navigation between windows, especially in the monocle mode. The different -+display modes of this bar are described under the Mod1\-w Keybord command -+section. When a single tag is selected, that tag is indicated in the left corner -+of the tab bar. - .P - dwm draws a small border around windows to indicate the focus state. - .SH OPTIONS -@@ -43,7 +51,8 @@ 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. -+label toggles between tiled and floating layout, click on a window name in the -+tab bar brings focus to that window. - .TP - .B Button3 - click on a tag label adds/removes all windows with that tag to/from the view. -@@ -104,6 +113,12 @@ Increase master area size. - .B Mod1\-h - Decrease master area size. - .TP -+.B Mod1\-w -+Cycle over the tab bar display modes: never displayed, always displayed, -+displayed only in monocle mode when the view contains than one window (auto -+mode). Some display modes can be disabled in the configuration, config.h. In -+the default configuration only "never" and "auto" display modes are enabled. -+.TP - .B Mod1\-Return - Zooms/cycles focused window to/from master area (tiled layouts only). - .TP -diff --git a/dwm.c b/dwm.c -index 1d78655..a892b7a 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -44,7 +44,7 @@ - #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))) -+ * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) - #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) - #define LENGTH(X) (sizeof X / sizeof X[0]) - #define MAX(A, B) ((A) > (B) ? (A) : (B)) -@@ -62,7 +62,7 @@ enum { NetSupported, NetWMName, NetWMState, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetLast }; /* EWMH atoms */ - enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ --enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, -+enum { ClkTagBar, ClkTabBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, - ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ - - typedef union { -@@ -102,6 +102,7 @@ typedef struct { - unsigned long norm[ColLast]; - unsigned long sel[ColLast]; - Drawable drawable; -+ Drawable tabdrawable; - GC gc; - struct { - int ascent; -@@ -124,24 +125,32 @@ typedef struct { - void (*arrange)(Monitor *); - } Layout; - -+#define MAXTABS 50 -+ - struct Monitor { - char ltsymbol[16]; - float mfact; - int nmaster; - int num; - int by; /* bar geometry */ -+ int ty; /* tab bar geometry */ - int mx, my, mw, mh; /* screen size */ - int wx, wy, ww, wh; /* window area */ - unsigned int seltags; - unsigned int sellt; - unsigned int tagset[2]; - Bool showbar; -+ Bool showtab; - Bool topbar; -+ Bool toptab; - Client *clients; - Client *sel; - Client *stack; - Monitor *next; - Window barwin; -+ Window tabwin; -+ int ntabs; -+ int tab_widths[MAXTABS]; - const Layout *lt[2]; - }; - -@@ -178,11 +187,15 @@ static void die(const char *errstr, ...); - static Monitor *dirtomon(int dir); - static void drawbar(Monitor *m); - static void drawbars(void); -+static void drawtab(Monitor *m); -+static void drawtabs(void); - static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]); --static void drawtext(const char *text, unsigned long col[ColLast], Bool invert); -+static void drawtext(Drawable drawable, const char *text, unsigned long col[ColLast], Bool invert); -+//static void drawtabtext(const char *text, unsigned long col[ColLast], Bool invert); - static void enternotify(XEvent *e); - static void expose(XEvent *e); - static void focus(Client *c); -+static void focuswin(const Arg* arg); - static void focusin(XEvent *e); - static void focusmon(const Arg *arg); - static void focusstack(const Arg *arg); -@@ -229,6 +242,7 @@ static void tagmon(const Arg *arg); - static int textnw(const char *text, unsigned int len); - static void tile(Monitor *); - static void togglebar(const Arg *arg); -+static void tabmode(const Arg *arg); - static void togglefloating(const Arg *arg); - static void toggletag(const Arg *arg); - static void toggleview(const Arg *arg); -@@ -258,6 +272,7 @@ static char stext[256]; - static int screen; - static int sw, sh; /* X display screen geometry width, height */ - static int bh, blw = 0; /* bar geometry */ -+static int th = 0; /* tab bar geometry */ - static int (*xerrorxlib)(Display *, XErrorEvent *); - static unsigned int numlockmask = 0; - static void (*handler[LASTEvent]) (XEvent *) = { -@@ -405,6 +420,9 @@ arrange(Monitor *m) { - - void - arrangemon(Monitor *m) { -+ updatebarpos(m); -+ XMoveResizeWindow(dpy, m->tabwin, m->wx, m->ty, m->ww, th); -+ - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); - if(m->lt[m->sellt]->arrange) - m->lt[m->sellt]->arrange(m); -@@ -454,14 +472,32 @@ buttonpress(XEvent *e) { - else - click = ClkWinTitle; - } -+ if(ev->window == selmon->tabwin) { -+ i = 0; x = 0; -+ for(c = selmon->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ x += selmon->tab_widths[i]; -+ if (ev->x > x) -+ ++i; -+ else -+ break; -+ if(i >= m->ntabs) break; -+ } -+ if(c) { -+ click = ClkTabBar; -+ arg.ui = i; -+ } -+ } - else if((c = wintoclient(ev->window))) { - focus(c); - 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); -+ && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)){ -+ buttons[i].func(((click == ClkTagBar || click == ClkTabBar) -+ && buttons[i].arg.i == 0) ? &arg : &buttons[i].arg); -+ } - } - - void -@@ -491,6 +527,7 @@ cleanup(void) { - XFreeFont(dpy, dc.font.xfont); - XUngrabKey(dpy, AnyKey, AnyModifier, root); - XFreePixmap(dpy, dc.drawable); -+ XFreePixmap(dpy, dc.tabdrawable); - XFreeGC(dpy, dc.gc); - XFreeCursor(dpy, cursor[CurNormal]); - XFreeCursor(dpy, cursor[CurResize]); -@@ -513,6 +550,8 @@ cleanupmon(Monitor *mon) { - } - XUnmapWindow(dpy, mon->barwin); - XDestroyWindow(dpy, mon->barwin); -+ XUnmapWindow(dpy, mon->tabwin); -+ XDestroyWindow(dpy, mon->tabwin); - free(mon); - } - -@@ -538,7 +577,7 @@ clientmessage(XEvent *e) { - 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))); -+ || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); - } - else if(cme->message_type == netatom[NetActiveWindow]) { - if(!ISVISIBLE(c)) { -@@ -581,9 +620,13 @@ configurenotify(XEvent *e) { - if(dc.drawable != 0) - XFreePixmap(dpy, dc.drawable); - dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); -+ if(dc.tabdrawable != 0) -+ XFreePixmap(dpy, dc.tabdrawable); -+ dc.tabdrawable = XCreatePixmap(dpy, root, sw, th, DefaultDepth(dpy, screen)); - updatebars(); -- for(m = mons; m; m = m->next) -+ for(m = mons; m; m = m->next){ - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); -+ } - focus(NULL); - arrange(NULL); - } -@@ -653,7 +696,10 @@ createmon(void) { - m->mfact = mfact; - m->nmaster = nmaster; - m->showbar = showbar; -+ m->showtab = showtab; - m->topbar = topbar; -+ m->toptab = toptab; -+ m->ntabs = 0; - m->lt[0] = &layouts[0]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); -@@ -731,13 +777,13 @@ drawbar(Monitor *m) { - for(i = 0; i < LENGTH(tags); i++) { - dc.w = TEXTW(tags[i]); - col = m->tagset[m->seltags] & 1 << i ? dc.sel : dc.norm; -- drawtext(tags[i], col, urg & 1 << i); -+ drawtext(dc.drawable, tags[i], col, urg & 1 << i); - drawsquare(m == selmon && selmon->sel && selmon->sel->tags & 1 << i, -- occ & 1 << i, urg & 1 << i, col); -+ occ & 1 << i, urg & 1 << i, col); - dc.x += dc.w; - } - dc.w = blw = TEXTW(m->ltsymbol); -- drawtext(m->ltsymbol, dc.norm, False); -+ drawtext(dc.drawable, m->ltsymbol, dc.norm, False); - dc.x += dc.w; - x = dc.x; - if(m == selmon) { /* status is only drawn on selected monitor */ -@@ -747,19 +793,20 @@ drawbar(Monitor *m) { - dc.x = x; - dc.w = m->ww - x; - } -- drawtext(stext, dc.norm, False); -+ drawtext(dc.drawable, stext, dc.norm, False); - } - else - dc.x = m->ww; - if((dc.w = dc.x - x) > bh) { - dc.x = x; - if(m->sel) { -- col = m == selmon ? dc.sel : dc.norm; -- drawtext(m->sel->name, col, False); -+ // col = m == selmon ? dc.sel : dc.norm; -+ // drawtext(dc.drawable, m->sel->name, col, False); -+ drawtext(dc.drawable, m->sel->name, dc.norm, False); - drawsquare(m->sel->isfixed, m->sel->isfloating, False, col); - } - else -- drawtext(NULL, dc.norm, False); -+ drawtext(dc.drawable, NULL, dc.norm, False); - } - XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->ww, bh, 0, 0); - XSync(dpy, False); -@@ -774,6 +821,104 @@ drawbars(void) { - } - - void -+drawtabs(void) { -+ Monitor *m; -+ -+ for(m = mons; m; m = m->next) -+ drawtab(m); -+} -+ -+static int -+cmpint(const void *p1, const void *p2) { -+ /* The actual arguments to this function are "pointers to -+ pointers to char", but strcmp(3) arguments are "pointers -+ to char", hence the following cast plus dereference */ -+ return *((int*) p1) > * (int*) p2; -+} -+ -+ -+void -+drawtab(Monitor *m) { -+ unsigned long *col; -+ Client *c; -+ int i; -+ int itag = -1; -+ char view_info[50]; -+ int view_info_w = 0; -+ int sorted_label_widths[MAXTABS]; -+ int tot_width; -+ int maxsize = bh; -+ dc.x = 0; -+ -+ //view_info: indicate the tag which is displayed in the view -+ for(i = 0; i < LENGTH(tags); ++i){ -+ if((selmon->tagset[selmon->seltags] >> i) & 1) { -+ if(itag >=0){ //more than one tag selected -+ itag = -1; -+ break; -+ } -+ itag = i; -+ } -+ } -+ if(0 <= itag && itag < LENGTH(tags)){ -+ snprintf(view_info, sizeof view_info, "[%s]", tags[itag]); -+ } else { -+ strncpy(view_info, "[...]", sizeof view_info); -+ } -+ view_info[sizeof(view_info) - 1 ] = 0; -+ view_info_w = TEXTW(view_info); -+ tot_width = view_info_w; -+ -+ /* Calculates number of labels and their width */ -+ m->ntabs = 0; -+ for(c = m->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ m->tab_widths[m->ntabs] = TEXTW(c->name); -+ tot_width += m->tab_widths[m->ntabs]; -+ ++m->ntabs; -+ if(m->ntabs >= MAXTABS) break; -+ } -+ -+ if(tot_width > m->ww){ //not enough space to display the labels, they need to be truncated -+ memcpy(sorted_label_widths, m->tab_widths, sizeof(int) * m->ntabs); -+ qsort(sorted_label_widths, m->ntabs, sizeof(int), cmpint); -+ tot_width = view_info_w; -+ for(i = 0; i < m->ntabs; ++i){ -+ if(tot_width + (m->ntabs - i) * sorted_label_widths[i] > m->ww) -+ break; -+ tot_width += sorted_label_widths[i]; -+ } -+ maxsize = (m->ww - tot_width) / (m->ntabs - i); -+ } else{ -+ maxsize = m->ww; -+ } -+ i = 0; -+ for(c = m->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ if(i >= m->ntabs) break; -+ if(m->tab_widths[i] > maxsize) m->tab_widths[i] = maxsize; -+ dc.w = m->tab_widths[i]; -+ col = (c == m->sel) ? dc.sel : dc.norm; -+ drawtext(dc.tabdrawable, c->name, col, 0); -+ dc.x += dc.w; -+ ++i; -+ } -+ -+ /* cleans interspace between window names and current viewed tag label */ -+ dc.w = m->ww - view_info_w - dc.x; -+ drawtext(dc.tabdrawable, NULL, dc.norm, 0); -+ -+ /* view info */ -+ dc.x += dc.w; -+ dc.w = view_info_w; -+ drawtext(dc.tabdrawable, view_info, dc.norm, 0); -+ -+ XCopyArea(dpy, dc.tabdrawable, m->tabwin, dc.gc, 0, 0, m->ww, th, 0, 0); -+ XSync(dpy, False); -+} -+ -+ -+void - drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) { - int x; - -@@ -785,13 +930,14 @@ drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) { - XDrawRectangle(dpy, dc.drawable, dc.gc, dc.x+1, dc.y+1, x, x); - } - -+ - void --drawtext(const char *text, unsigned long col[ColLast], Bool invert) { -+drawtext(Drawable drawable, const char *text, unsigned long col[ColLast], Bool invert) { - char buf[256]; - int i, x, y, h, len, olen; - - XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]); -- XFillRectangle(dpy, dc.drawable, dc.gc, dc.x, dc.y, dc.w, dc.h); -+ XFillRectangle(dpy, drawable, dc.gc, dc.x, dc.y, dc.w, dc.h); - if(!text) - return; - olen = strlen(text); -@@ -807,11 +953,12 @@ drawtext(const char *text, unsigned long col[ColLast], Bool invert) { - for(i = len; i && i > len - 3; buf[--i] = '.'); - XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]); - if(dc.font.set) -- XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len); -+ XmbDrawString(dpy, drawable, dc.font.set, dc.gc, x, y, buf, len); - else -- XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len); -+ XDrawString(dpy, drawable, dc.gc, x, y, buf, len); - } - -+ - void - enternotify(XEvent *e) { - Client *c; -@@ -836,8 +983,10 @@ expose(XEvent *e) { - Monitor *m; - XExposeEvent *ev = &e->xexpose; - -- if(ev->count == 0 && (m = wintomon(ev->window))) -+ if(ev->count == 0 && (m = wintomon(ev->window))){ - drawbar(m); -+ drawtab(m); -+ } - } - - void -@@ -862,6 +1011,7 @@ focus(Client *c) { - XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); - selmon->sel = c; - drawbars(); -+ drawtabs(); - } - - void -@@ -911,6 +1061,19 @@ focusstack(const Arg *arg) { - } - } - -+void -+focuswin(const Arg* arg){ -+ int iwin = arg->i; -+ Client* c = NULL; -+ for(c = selmon->clients; c && (iwin || !ISVISIBLE(c)) ; c = c->next){ -+ if(ISVISIBLE(c)) --iwin; -+ }; -+ if(c) { -+ focus(c); -+ restack(selmon); -+ } -+} -+ - Atom - getatomprop(Client *c, Atom prop) { - int di; -@@ -919,7 +1082,7 @@ getatomprop(Client *c, Atom prop) { - Atom da, atom = None; - - if(XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, -- &da, &di, &dl, &dl, &p) == Success && p) { -+ &da, &di, &dl, &dl, &p) == Success && p) { - atom = *(Atom *)p; - XFree(p); - } -@@ -954,7 +1117,7 @@ getstate(Window w) { - Atom real; - - if(XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], -- &real, &format, &n, &extra, (unsigned char **)&p) != Success) -+ &real, &format, &n, &extra, (unsigned char **)&p) != Success) - return -1; - if(n != 0) - result = *p; -@@ -999,13 +1162,13 @@ grabbuttons(Client *c, Bool focused) { - 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); -+ buttons[i].mask | modifiers[j], -+ c->win, False, BUTTONMASK, -+ GrabModeAsync, GrabModeSync, None, None); - } - else - XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, -- BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); -+ BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); - } - } - -@@ -1139,7 +1302,7 @@ manage(Window w, XWindowAttributes *wa) { - 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->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); -+ && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); - c->bw = borderpx; - - wc.border_width = c->bw; -@@ -1311,12 +1474,14 @@ propertynotify(XEvent *e) { - case XA_WM_HINTS: - updatewmhints(c); - drawbars(); -+ drawtabs(); - break; - } - if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { - updatetitle(c); - if(c == c->mon->sel) - drawbar(c->mon); -+ drawtab(c->mon); - } - if(ev->atom == netatom[NetWMWindowType]) - updatewindowtype(c); -@@ -1375,7 +1540,7 @@ resizemouse(const Arg *arg) { - ocx = c->x; - ocy = c->y; - if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, -- None, cursor[CurResize], CurrentTime) != GrabSuccess) -+ None, cursor[CurResize], CurrentTime) != GrabSuccess) - return; - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); - do { -@@ -1418,6 +1583,7 @@ restack(Monitor *m) { - XWindowChanges wc; - - drawbar(m); -+ drawtab(m); - if(!m->sel) - return; - if(m->sel->isfloating || !m->lt[m->sellt]->arrange) -@@ -1529,7 +1695,7 @@ void - setfullscreen(Client *c, Bool fullscreen) { - if(fullscreen) { - XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, -- PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); -+ PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); - c->isfullscreen = True; - c->oldstate = c->isfloating; - c->oldbw = c->bw; -@@ -1540,7 +1706,7 @@ setfullscreen(Client *c, Bool fullscreen) { - } - else { - XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, -- PropModeReplace, (unsigned char*)0, 0); -+ PropModeReplace, (unsigned char*)0, 0); - c->isfullscreen = False; - c->isfloating = c->oldstate; - c->bw = c->oldbw; -@@ -1594,6 +1760,7 @@ setup(void) { - sw = DisplayWidth(dpy, screen); - sh = DisplayHeight(dpy, screen); - bh = dc.h = dc.font.height + 2; -+ th = bh; - updategeom(); - /* init atoms */ - wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); -@@ -1619,6 +1786,7 @@ setup(void) { - dc.sel[ColBG] = getcolor(selbgcolor); - dc.sel[ColFG] = getcolor(selfgcolor); - dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen)); -+ dc.tabdrawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), th, DefaultDepth(dpy, screen)); - dc.gc = XCreateGC(dpy, root, 0, NULL); - XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); - if(!dc.font.set) -@@ -1632,7 +1800,7 @@ setup(void) { - /* select for events */ - wa.cursor = cursor[CurNormal]; - wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask|PointerMotionMask -- |EnterWindowMask|LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; -+ |EnterWindowMask|LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; - XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); - XSelectInput(dpy, root, wa.event_mask); - grabkeys(); -@@ -1736,6 +1904,16 @@ togglebar(const Arg *arg) { - } - - void -+tabmode(const Arg *arg) { -+ if(arg && arg->i >= 0) -+ selmon->showtab = arg->ui % showtab_nmodes; -+ else -+ selmon->showtab = (selmon->showtab + 1 ) % showtab_nmodes; -+ arrange(selmon); -+} -+ -+ -+void - togglefloating(const Arg *arg) { - if(!selmon->sel) - return; -@@ -1828,24 +2006,47 @@ updatebars(void) { - }; - for(m = mons; m; m = m->next) { - m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), -- CopyFromParent, DefaultVisual(dpy, screen), -- CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); -+ CopyFromParent, DefaultVisual(dpy, screen), -+ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); - XDefineCursor(dpy, m->barwin, cursor[CurNormal]); - XMapRaised(dpy, m->barwin); -+ m->tabwin = XCreateWindow(dpy, root, m->wx, m->ty, m->ww, th, 0, DefaultDepth(dpy, screen), -+ CopyFromParent, DefaultVisual(dpy, screen), -+ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); -+ XDefineCursor(dpy, m->tabwin, cursor[CurNormal]); -+ XMapRaised(dpy, m->tabwin); - } - } - - void - updatebarpos(Monitor *m) { -+ Client *c; -+ int nvis = 0; -+ - m->wy = m->my; - m->wh = m->mh; - if(m->showbar) { - m->wh -= bh; - m->by = m->topbar ? m->wy : m->wy + m->wh; -- m->wy = m->topbar ? m->wy + bh : m->wy; -- } -- else -+ if ( m->topbar ) -+ m->wy += bh; -+ } else { - m->by = -bh; -+ } -+ -+ for(c = m->clients; c; c = c->next){ -+ if(ISVISIBLE(c)) ++nvis; -+ } -+ -+ if(m->showtab == showtab_always -+ || ((m->showtab == showtab_auto) && (nvis > 1) && (m->lt[m->sellt]->arrange == monocle))){ -+ m->wh -= th; -+ m->ty = m->toptab ? m->wy : m->wy + m->wh; -+ if ( m->toptab ) -+ m->wy += th; -+ } else { -+ m->ty = -th; -+ } - } - - Bool -@@ -1992,7 +2193,7 @@ updatesizehints(Client *c) { - else - c->maxa = c->mina = 0.0; - c->isfixed = (c->maxw && c->minw && c->maxh && c->minh -- && c->maxw == c->minw && c->maxh == c->minh); -+ && c->maxw == c->minw && c->maxh == c->minh); - } - - void -@@ -2073,7 +2274,7 @@ wintomon(Window w) { - if(w == root && getrootptr(&x, &y)) - return recttomon(x, y, 1, 1); - for(m = mons; m; m = m->next) -- if(w == m->barwin) -+ if(w == m->barwin || w == m->tabwin) - return m; - if((c = wintoclient(w))) - return c->mon; diff --git a/dwm.suckless.org/patches/historical/dwm-6.0-winview.diff b/dwm.suckless.org/patches/historical/dwm-6.0-winview.diff @@ -1,65 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 77ff358..3ba0efe 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -84,6 +84,7 @@ static Key keys[] = { - TAGKEYS( XK_8, 7) - TAGKEYS( XK_9, 8) - { MODKEY|ShiftMask, XK_q, quit, {0} }, -+ { MODKEY, XK_o, winview, {0} }, - }; - - /* button definitions */ -diff --git a/dwm.1 b/dwm.1 -index 5268a06..1188c82 100644 ---- a/dwm.1 -+++ b/dwm.1 -@@ -104,6 +104,9 @@ Increase master area size. - .B Mod1\-h - Decrease master area size. - .TP -+.B Mod1\-o -+Select view of the window in focus. The list of tags to be displayed is matched to the window tag list. -+.TP - .B Mod1\-Return - Zooms/cycles focused window to/from master area (tiled layouts only). - .TP -diff --git a/dwm.c b/dwm.c -index 1d78655..abf944c 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -247,6 +247,7 @@ static void updatewmhints(Client *c); - static void view(const Arg *arg); - static Client *wintoclient(Window w); - static Monitor *wintomon(Window w); -+static void winview(const Arg* arg); - static int xerror(Display *dpy, XErrorEvent *ee); - static int xerrordummy(Display *dpy, XErrorEvent *ee); - static int xerrorstart(Display *dpy, XErrorEvent *ee); -@@ -2080,6 +2081,26 @@ wintomon(Window w) { - return selmon; - } - -+/* Selects for the view of the focused window. The list of tags */ -+/* to be displayed is matched to the focused window tag list. */ -+void -+winview(const Arg* arg){ -+ Window win, win_r, win_p, *win_c; -+ unsigned nc; -+ int unused; -+ Client* c; -+ Arg a; -+ -+ if (!XGetInputFocus(dpy, &win, &unused)) return; -+ while(XQueryTree(dpy, win, &win_r, &win_p, &win_c, &nc) -+ && win_p != win_r) win = win_p; -+ -+ if (!(c = wintoclient(win))) return; -+ -+ a.ui = c->tags; -+ view(&a); -+} -+ - /* 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. */ diff --git a/dwm.suckless.org/patches/historical/dwm-fancybar-5.6.1.diff b/dwm.suckless.org/patches/historical/dwm-fancybar-5.6.1.diff @@ -1,121 +0,0 @@ -diff -r e47a47bd3ed4 dwm.c ---- a/dwm.c Tue Jul 21 10:57:54 2009 +0100 -+++ b/dwm.c Mon Aug 24 18:28:57 2009 +0200 -@@ -169,6 +169,7 @@ - static Monitor *dirtomon(int dir); - static void drawbar(Monitor *m); - static void drawbars(void); -+static void drawvline(unsigned long col[ColLast]); - static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]); - static void drawtext(const char *text, unsigned long col[ColLast], Bool invert); - static void enternotify(XEvent *e); -@@ -648,10 +649,11 @@ - - void - drawbar(Monitor *m) { -- int x; -+ int x, ow, mw = 0, extra, tw; - unsigned int i, n = 0, occ = 0, urg = 0; - unsigned long *col; -- Client *c; -+ Client *c, *firstvis, *lastvis = NULL; -+ DC seldc; - - for(c = m->clients; c; c = c->next) { - if(ISVISIBLE(c)) -@@ -689,16 +691,62 @@ - } - else - dc.x = m->ww; -- if((dc.w = dc.x - x) > bh) { -- dc.x = x; -- if(m->sel) { -- col = m == selmon ? dc.sel : dc.norm; -- drawtext(m->sel->name, col, False); -- drawsquare(m->sel->isfixed, m->sel->isfloating, False, col); -+ -+ for(c = m->clients; c && !ISVISIBLE(c); c = c->next); -+ firstvis = c; -+ -+ col = m == selmon ? dc.sel : dc.norm; -+ dc.w = dc.x - x; -+ dc.x = x; -+ -+ if(n > 0) { -+ mw = dc.w / n; -+ extra = 0; -+ seldc = dc; -+ i = 0; -+ -+ while(c) { -+ lastvis = c; -+ tw = TEXTW(c->name); -+ if(tw < mw) extra += (mw - tw); else i++; -+ for(c = c->next; c && !ISVISIBLE(c); c = c->next); - } -- else -+ -+ if(i > 0) mw += extra / i; -+ -+ c = firstvis; -+ x = dc.x; -+ } -+ -+ while(dc.w > bh) { -+ if(c) { -+ ow = dc.w; -+ tw = TEXTW(c->name); -+ dc.w = MIN(ow, tw); -+ -+ if(dc.w > mw) dc.w = mw; -+ if(m->sel == c) seldc = dc; -+ if(c == lastvis) dc.w = ow; -+ -+ drawtext(c->name, col, False); -+ if(c != firstvis) drawvline(col); -+ drawsquare(c->isfixed, c->isfloating, False, col); -+ -+ dc.x += dc.w; -+ dc.w = ow - dc.w; -+ for(c = c->next; c && !ISVISIBLE(c); c = c->next); -+ } else { - drawtext(NULL, dc.norm, False); -+ break; -+ } - } -+ -+ if(m == selmon && m->sel && ISVISIBLE(m->sel)) { -+ dc = seldc; -+ drawtext(m->sel->name, col, True); -+ drawsquare(m->sel->isfixed, m->sel->isfloating, True, col); -+ } -+ - XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->ww, bh, 0, 0); - XSync(dpy, False); - } -@@ -709,6 +757,15 @@ - - for(m = mons; m; m = m->next) - drawbar(m); -+} -+ -+void -+drawvline(unsigned long col[ColLast]) { -+ XGCValues gcv; -+ -+ gcv.foreground = col[ColFG]; -+ XChangeGC(dpy, dc.gc, GCForeground, &gcv); -+ XDrawLine(dpy, dc.drawable, dc.gc, dc.x, dc.y, dc.x, dc.y + (dc.font.ascent + dc.font.descent + 2)); - } - - void -@@ -1235,8 +1292,7 @@ - } - if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { - updatetitle(c); -- if(c == selmon->sel) -- drawbars(); -+ drawbars(); - } - } - } diff --git a/dwm.suckless.org/patches/historical/dwm-flextile-5.8.1.diff b/dwm.suckless.org/patches/historical/dwm-flextile-5.8.1.diff @@ -1,418 +0,0 @@ -diff -up ../dwm-5.8.1-0/config.def.h ./config.def.h ---- ../dwm-5.8.1-0/config.def.h 2010-05-29 13:49:12.000000000 +0200 -+++ ./config.def.h 2010-05-31 15:18:43.686311000 +0200 -@@ -25,6 +25,11 @@ static const Rule rules[] = { - /* layout(s) */ - static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ - static const Bool resizehints = True; /* True means respect size hints in tiled resizals */ -+static const int layoutaxis[] = { -+ 1, /* layout axis: 1 = x, 2 = y; negative values mirror the layout, setting the master area to the right / bottom instead of left / top */ -+ 2, /* master axis: 1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle) */ -+ 2, /* stack axis: 1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle) */ -+}; - - static const Layout layouts[] = { - /* symbol arrange function */ -@@ -81,6 +86,12 @@ static Key keys[] = { - TAGKEYS( XK_8, 7) - TAGKEYS( XK_9, 8) - { MODKEY|ShiftMask, XK_q, quit, {0} }, -+ { MODKEY|ControlMask, XK_t, rotatelayoutaxis, {.i = 0} }, /* 0 = layout axis */ -+ { MODKEY|ControlMask, XK_Tab, rotatelayoutaxis, {.i = 1} }, /* 1 = master axis */ -+ { MODKEY|ControlMask|ShiftMask, XK_Tab, rotatelayoutaxis, {.i = 2} }, /* 2 = stack axis */ -+ { MODKEY|ControlMask, XK_Return, mirrorlayout, {0} }, -+ { MODKEY|ControlMask, XK_j, shiftmastersplit, {.i = -1} }, /* reduce the number of tiled clients in the master area */ -+ { MODKEY|ControlMask, XK_k, shiftmastersplit, {.i = +1} }, /* increase the number of tiled clients in the master area */ - }; - - /* button definitions */ -diff -up ../dwm-5.8.1-0/dwm.c ./dwm.c ---- ../dwm-5.8.1-0/dwm.c 2010-05-29 13:49:12.000000000 +0200 -+++ ./dwm.c 2010-05-31 16:02:14.553316000 +0200 -@@ -120,26 +120,6 @@ typedef struct { - void (*arrange)(Monitor *); - } Layout; - --struct Monitor { -- char ltsymbol[16]; -- float mfact; -- int num; -- int by; /* bar geometry */ -- int mx, my, mw, mh; /* screen size */ -- int wx, wy, ww, wh; /* window area */ -- unsigned int seltags; -- unsigned int sellt; -- unsigned int tagset[2]; -- Bool showbar; -- Bool topbar; -- Client *clients; -- Client *sel; -- Client *stack; -- Monitor *next; -- Window barwin; -- const Layout *lt[2]; --}; -- - typedef struct { - const char *class; - const char *instance; -@@ -193,6 +173,7 @@ 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 mirrorlayout(const Arg *arg); - static void monocle(Monitor *m); - static void movemouse(const Arg *arg); - static Client *nexttiled(Client *c); -@@ -202,6 +183,7 @@ static void quit(const Arg *arg); - static void resize(Client *c, int x, int y, int w, int h, Bool interact); - static void resizemouse(const Arg *arg); - static void restack(Monitor *m); -+static void rotatelayoutaxis(const Arg *arg); - static void run(void); - static void scan(void); - static void sendmon(Client *c, Monitor *m); -@@ -209,6 +191,7 @@ static void setclientstate(Client *c, lo - static void setlayout(const Arg *arg); - static void setmfact(const Arg *arg); - static void setup(void); -+static void shiftmastersplit(const Arg *arg); - static void showhide(Client *c); - static void sigchld(int unused); - static void spawn(const Arg *arg); -@@ -275,6 +258,34 @@ static Window root; - - /* compile-time check if all tags fit into an unsigned int bit array. */ - struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; -+struct Monitor { -+ char ltsymbol[16]; -+ float mfact; -+ double mfacts[LENGTH(tags) + 1]; -+ int ltaxis[3]; -+ int ltaxes[LENGTH(tags) + 1][3]; -+ int num; -+ int curtag; -+ int prevtag; -+ int by; /* bar geometry */ -+ int mx, my, mw, mh; /* screen size */ -+ int wx, wy, ww, wh; /* window area */ -+ unsigned int msplit; -+ unsigned int msplits[LENGTH(tags) + 1]; -+ unsigned int seltags; -+ unsigned int sellt; -+ unsigned int tagset[2]; -+ Bool showbar; -+ Bool showbars[LENGTH(tags) + 1]; -+ Bool topbar; -+ Client *clients; -+ Client *sel; -+ Client *stack; -+ Monitor *next; -+ Window barwin; -+ const Layout *lt[2]; -+ const Layout *lts[LENGTH(tags) + 1]; -+}; - - /* function implementations */ - void -@@ -616,6 +627,10 @@ createmon(void) { - m->lt[0] = &layouts[0]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); -+ m->ltaxis[0] = layoutaxis[0]; -+ m->ltaxis[1] = layoutaxis[1]; -+ m->ltaxis[2] = layoutaxis[2]; -+ m->msplit = 1; - return m; - } - -@@ -1173,6 +1188,15 @@ maprequest(XEvent *e) { - } - - void -+mirrorlayout(const Arg *arg) { -+ if(!selmon->lt[selmon->sellt]->arrange) -+ return; -+ selmon->ltaxis[0] *= -1; -+ selmon->ltaxes[selmon->curtag][0] = selmon->ltaxis[0]; -+ arrange(selmon); -+} -+ -+void - monocle(Monitor *m) { - unsigned int n = 0; - Client *c; -@@ -1387,6 +1411,21 @@ restack(Monitor *m) { - } - - void -+rotatelayoutaxis(const Arg *arg) { -+ if(!selmon->lt[selmon->sellt]->arrange) -+ return; -+ if(arg->i == 0) { -+ if(selmon->ltaxis[0] > 0) -+ selmon->ltaxis[0] = selmon->ltaxis[0] + 1 > 2 ? 1 : selmon->ltaxis[0] + 1; -+ else -+ selmon->ltaxis[0] = selmon->ltaxis[0] - 1 < -2 ? -1 : selmon->ltaxis[0] - 1; -+ } else -+ selmon->ltaxis[arg->i] = selmon->ltaxis[arg->i] + 1 > 3 ? 1 : selmon->ltaxis[arg->i] + 1; -+ selmon->ltaxes[selmon->curtag][arg->i] = selmon->ltaxis[arg->i]; -+ arrange(selmon); -+} -+ -+void - run(void) { - XEvent ev; - /* main event loop */ -@@ -1451,7 +1490,7 @@ 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; -+ selmon->lt[selmon->sellt] = selmon->lts[selmon->curtag] = (Layout *)arg->v; - strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); - if(selmon->sel) - arrange(selmon); -@@ -1469,14 +1508,16 @@ setmfact(const Arg *arg) { - f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; - if(f < 0.1 || f > 0.9) - return; -- selmon->mfact = f; -+ selmon->mfact = selmon->mfacts[selmon->curtag] = f; - arrange(selmon); - } - - void - setup(void) { - XSetWindowAttributes wa; -- -+ Monitor *m; -+ unsigned int i; -+ - /* clean up any zombies immediately */ - sigchld(0); - -@@ -1511,7 +1552,19 @@ setup(void) { - XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); - if(!dc.font.set) - XSetFont(dpy, dc.gc, dc.font.xfont->fid); -- /* init bars */ -+ /* init tags, bars, layouts, axes, msplits and mfacts */ -+ for(m = mons; m; m = m->next) { -+ m->curtag = m->prevtag = 1; -+ for(i=0; i < LENGTH(tags) + 1; i++) { -+ m->showbars[i] = m->showbar; -+ m->lts[i] = &layouts[0]; -+ m->mfacts[i] = m->mfact; -+ m->ltaxes[i][0] = m->ltaxis[0]; -+ m->ltaxes[i][1] = m->ltaxis[1]; -+ m->ltaxes[i][2] = m->ltaxis[2]; -+ m->msplits[i] = m->msplit; -+ } -+ } - updatebars(); - updatestatus(); - /* EWMH support per view */ -@@ -1528,6 +1581,19 @@ setup(void) { - } - - void -+shiftmastersplit(const Arg *arg) { -+ unsigned int n; -+ Client *c; -+ -+ for(n = 0, c = nexttiled(selmon->clients); c; c = nexttiled(c->next), n++); -+ if(!arg || !selmon->lt[selmon->sellt]->arrange || selmon->msplit + arg->i < 1 || selmon->msplit + arg->i > n) -+ return; -+ selmon->msplit += arg->i; -+ selmon->msplits[selmon->curtag] = selmon->msplit; -+ arrange(selmon); -+} -+ -+void - showhide(Client *c) { - if(!c) - return; -@@ -1592,37 +1658,95 @@ textnw(const char *text, unsigned int le - - void - tile(Monitor *m) { -- int x, y, h, w, mw; -- unsigned int i, n; -+ char sym1 = 61, sym2 = 93, sym3 = 61, sym; -+ int x1 = m->wx, y1 = m->wy, h1 = m->wh, w1 = m->ww, X1 = x1 + w1, Y1 = y1 + h1; -+ int x2 = m->wx, y2 = m->wy, h2 = m->wh, w2 = m->ww, X2 = x2 + w2, Y2 = y2 + h2; -+ unsigned int i, n, n1, n2; - Client *c; - - for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); -+ if(m->msplit > n) -+ m->msplit = (n == 0) ? 1 : n; -+ if(n == 0 && m->ltaxis[1] != 3) -+ return; -+ /* layout symbol */ -+ if(abs(m->ltaxis[0]) == m->ltaxis[1]) /* explicitly: ((abs(m->ltaxis[0]) == 1 && m->ltaxis[1] == 1) || (abs(m->ltaxis[0]) == 2 && m->ltaxis[1] == 2)) */ -+ sym1 = 124; -+ if(abs(m->ltaxis[0]) == m->ltaxis[2]) -+ sym3 = 124; -+ if(m->ltaxis[1] == 3) -+ sym1 = (n == 0) ? 0 : m->msplit; -+ if(m->ltaxis[2] == 3) -+ sym3 = (n == 0) ? 0 : n - m->msplit; -+ if(m->ltaxis[0] < 0) { -+ sym = sym1; -+ sym1 = sym3; -+ sym2 = 91; -+ sym3 = sym; -+ } -+ if(m->msplit == 1) { -+ if(m->ltaxis[0] > 0) -+ sym1 = 91; -+ else -+ sym3 = 93; -+ } -+ if(m->msplit > 1 && m->ltaxis[1] == 3 && m->ltaxis[2] == 3) -+ snprintf(m->ltsymbol, sizeof m->ltsymbol, "%d%c%d", sym1, sym2, sym3); -+ else if((m->msplit > 1 && m->ltaxis[1] == 3 && m->ltaxis[0] > 0) || (m->ltaxis[2] == 3 && m->ltaxis[0] < 0)) -+ snprintf(m->ltsymbol, sizeof m->ltsymbol, "%d%c%c", sym1, sym2, sym3); -+ else if((m->ltaxis[2] == 3 && m->ltaxis[0] > 0) || (m->msplit > 1 && m->ltaxis[1] == 3 && m->ltaxis[0] < 0)) -+ snprintf(m->ltsymbol, sizeof m->ltsymbol, "%c%c%d", sym1, sym2, sym3); -+ else -+ snprintf(m->ltsymbol, sizeof m->ltsymbol, "%c%c%c", sym1, sym2, sym3); - if(n == 0) - return; -+ /* master and stack area */ -+ if(abs(m->ltaxis[0]) == 1 && n > m->msplit) { -+ w1 *= m->mfact; -+ w2 -= w1; -+ x1 += (m->ltaxis[0] < 0) ? w2 : 0; -+ x2 += (m->ltaxis[0] < 0) ? 0 : w1; -+ X1 = x1 + w1; -+ X2 = x2 + w2; -+ } else if(abs(m->ltaxis[0]) == 2 && n > m->msplit) { -+ h1 *= m->mfact; -+ h2 -= h1; -+ y1 += (m->ltaxis[0] < 0) ? h2 : 0; -+ y2 += (m->ltaxis[0] < 0) ? 0 : h1; -+ Y1 = y1 + h1; -+ Y2 = y2 + h2; -+ } - /* master */ -- c = nexttiled(m->clients); -- mw = m->mfact * m->ww; -- resize(c, m->wx, m->wy, (n == 1 ? m->ww : mw) - 2 * c->bw, m->wh - 2 * c->bw, False); -- if(--n == 0) -- return; -- /* tile stack */ -- x = (m->wx + mw > c->x + c->w) ? c->x + c->w + 2 * c->bw : m->wx + mw; -- y = m->wy; -- w = (m->wx + mw > c->x + c->w) ? m->wx + m->ww - x : m->ww - mw; -- h = m->wh / n; -- if(h < bh) -- h = m->wh; -- for(i = 0, c = nexttiled(c->next); c; c = nexttiled(c->next), i++) { -- resize(c, x, y, w - 2 * c->bw, /* remainder */ ((i + 1 == n) -- ? m->wy + m->wh - y - 2 * c->bw : h - 2 * c->bw), False); -- if(h != m->wh) -- y = c->y + HEIGHT(c); -+ n1 = (m->ltaxis[1] != 1 || w1 / m->msplit < bh) ? 1 : m->msplit; -+ n2 = (m->ltaxis[1] != 2 || h1 / m->msplit < bh) ? 1 : m->msplit; -+ for(i = 0, c = nexttiled(m->clients); i < m->msplit; c = nexttiled(c->next), i++) { -+ resize(c, x1, y1, -+ (m->ltaxis[1] == 1 && i + 1 == m->msplit) ? X1 - x1 - 2 * c->bw : w1 / n1 - 2 * c->bw, -+ (m->ltaxis[1] == 2 && i + 1 == m->msplit) ? Y1 - y1 - 2 * c->bw : h1 / n2 - 2 * c->bw, False); -+ if(n1 > 1) -+ x1 = c->x + WIDTH(c); -+ if(n2 > 1) -+ y1 = c->y + HEIGHT(c); -+ } -+ /* stack */ -+ if(n > m->msplit) { -+ n1 = (m->ltaxis[2] != 1 || w2 / (n - m->msplit) < bh) ? 1 : n - m->msplit; -+ n2 = (m->ltaxis[2] != 2 || h2 / (n - m->msplit) < bh) ? 1 : n - m->msplit; -+ for(i = 0; c; c = nexttiled(c->next), i++) { -+ resize(c, x2, y2, -+ (m->ltaxis[2] == 1 && i + 1 == n - m->msplit) ? X2 - x2 - 2 * c->bw : w2 / n1 - 2 * c->bw, -+ (m->ltaxis[2] == 2 && i + 1 == n - m->msplit) ? Y2 - y2 - 2 * c->bw : h2 / n2 - 2 * c->bw, False); -+ if(n1 > 1) -+ x2 = c->x + WIDTH(c); -+ if(n2 > 1) -+ y2 = c->y + HEIGHT(c); -+ } - } - } - - void - togglebar(const Arg *arg) { -- selmon->showbar = !selmon->showbar; -+ selmon->showbar = selmon->showbars[selmon->curtag] = !selmon->showbar; - updatebarpos(selmon); - XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); - arrange(selmon); -@@ -1642,12 +1766,31 @@ togglefloating(const Arg *arg) { - void - toggletag(const Arg *arg) { - unsigned int newtags; -+ unsigned int i; - - if(!selmon->sel) - return; - newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); - if(newtags) { - selmon->sel->tags = newtags; -+ if(newtags == ~0) { -+ selmon->prevtag = selmon->curtag; -+ selmon->curtag = 0; -+ } -+ if(!(newtags & 1 << (selmon->curtag - 1))) { -+ selmon->prevtag = selmon->curtag; -+ for (i=0; !(newtags & 1 << i); i++); -+ selmon->curtag = i + 1; -+ } -+ selmon->sel->tags = newtags; -+ selmon->lt[selmon->sellt] = selmon->lts[selmon->curtag]; -+ selmon->mfact = selmon->mfacts[selmon->curtag]; -+ if (selmon->showbar != selmon->showbars[selmon->curtag]) -+ togglebar(NULL); -+ selmon->ltaxis[0] = selmon->ltaxes[selmon->curtag][0]; -+ selmon->ltaxis[1] = selmon->ltaxes[selmon->curtag][1]; -+ selmon->ltaxis[2] = selmon->ltaxes[selmon->curtag][2]; -+ selmon->msplit = selmon->msplits[selmon->curtag]; - arrange(selmon); - } - } -@@ -1914,11 +2057,33 @@ updatewmhints(Client *c) { - - void - view(const Arg *arg) { -+ unsigned int i; -+ - if((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) - return; - selmon->seltags ^= 1; /* toggle sel tagset */ -- if(arg->ui & TAGMASK) -+ if(arg->ui & TAGMASK) { - selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; -+ selmon->prevtag = selmon->curtag; -+ if(arg->ui == ~0) -+ selmon->curtag = 0; -+ else { -+ for (i=0; !(arg->ui & 1 << i); i++); -+ selmon->curtag = i + 1; -+ } -+ } else { -+ selmon->prevtag = selmon->curtag ^ selmon->prevtag; -+ selmon->curtag ^= selmon->prevtag; -+ selmon->prevtag = selmon->curtag ^ selmon->prevtag; -+ } -+ selmon->lt[selmon->sellt] = selmon->lts[selmon->curtag]; -+ selmon->mfact = selmon->mfacts[selmon->curtag]; -+ if(selmon->showbar != selmon->showbars[selmon->curtag]) -+ togglebar(NULL); -+ selmon->ltaxis[0] = selmon->ltaxes[selmon->curtag][0]; -+ selmon->ltaxis[1] = selmon->ltaxes[selmon->curtag][1]; -+ selmon->ltaxis[2] = selmon->ltaxes[selmon->curtag][2]; -+ selmon->msplit = selmon->msplits[selmon->curtag]; - arrange(selmon); - } - diff --git a/dwm.suckless.org/patches/historical/dwm-gap-5.7.2.diff b/dwm.suckless.org/patches/historical/dwm-gap-5.7.2.diff @@ -1,23 +0,0 @@ ---- a/dwm.c 2009-09-17 10:48:57.000000000 +0200 -+++ b/dwm.c 2009-09-16 18:54:37.000000000 +0200 -@@ -1270,10 +1270,10 @@ - XWindowChanges wc; - - if(applysizehints(c, &x, &y, &w, &h, interact)) { -- c->x = wc.x = x; -- c->y = wc.y = y; -- c->w = wc.width = w; -- c->h = wc.height = h; -+ c->x = wc.x = x + gappx; -+ c->y = wc.y = y + gappx; -+ c->w = wc.width = w - 2 * gappx ; -+ c->h = wc.height = h - 2 * gappx ; - wc.border_width = c->bw; - XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); - configure(c); - -diff -r 72e52c5333ef config.def.h ---- a/config.def.h Wed Nov 25 13:56:17 2009 +0000 -+++ b/config.def.h Tue Dec 15 18:39:44 2009 +0100 -@@ -7,14 +7,15 @@ -+static const unsigned int gappx = 4; /* gap pixel between windows */ diff --git a/dwm.suckless.org/patches/historical/dwm-git-20100321-focusonclick.diff b/dwm.suckless.org/patches/historical/dwm-git-20100321-focusonclick.diff @@ -1,38 +0,0 @@ -diff -r 72e52c5333ef config.def.h ---- a/config.def.h Wed Nov 25 13:56:17 2009 +0000 -+++ b/config.def.h Sun Mar 21 00:38:45 2010 +0100 -@@ -12,6 +12,7 @@ - static const unsigned int snap = 32; /* snap pixel */ - static const Bool showbar = True; /* False means no bar */ - static const Bool topbar = True; /* False means bottom bar */ -+static const Bool focusonclick = True; /* Change focus only on click */ - - /* tagging */ - static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; -diff -r 72e52c5333ef dwm.c ---- a/dwm.c Wed Nov 25 13:56:17 2009 +0000 -+++ b/dwm.c Sun Mar 21 00:38:45 2010 +0100 -@@ -791,14 +791,16 @@ - - if((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) - return; -- if((m = wintomon(ev->window)) && m != selmon) { -- unfocus(selmon->sel); -- selmon = m; -+ if (!focusonclick) { -+ if((m = wintomon(ev->window)) && m != selmon) { -+ unfocus(selmon->sel); -+ selmon = m; -+ } -+ if((c = wintoclient(ev->window))) -+ focus(c); -+ else -+ focus(NULL); - } -- if((c = wintoclient(ev->window))) -- focus(c); -- else -- focus(NULL); - } - - void diff --git a/dwm.suckless.org/patches/historical/dwm-master_2013-08-27_cdec978-pertag-tab-v2a.diff b/dwm.suckless.org/patches/historical/dwm-master_2013-08-27_cdec978-pertag-tab-v2a.diff @@ -1,672 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 875885b..406fdd8 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -12,10 +12,22 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ - static const unsigned int snap = 32; /* snap pixel */ - static const Bool showbar = True; /* False means no bar */ - static const Bool topbar = True; /* False means bottom bar */ -+/* Display modes of the tab bar: never shown, always shown, shown only in */ -+/* monocle mode in presence of several windows. */ -+/* Modes after showtab_nmodes are disabled */ -+enum showtab_modes { showtab_never, showtab_auto, showtab_nmodes, showtab_always}; -+static const int showtab = showtab_auto; /* Default tab bar show mode */ -+static const Bool toptab = False; /* False means bottom tab bar */ -+ - - /* tagging */ - static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; - -+/* default layout per tags */ -+/* The first element is for all-tag view, following i-th element corresponds to */ -+/* tags[i]. Layout is referred using the layouts array index.*/ -+static int def_layouts[1 + LENGTH(tags)] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -+ - static const Rule rules[] = { - /* xprop(1): - * WM_CLASS(STRING) = instance, class -@@ -29,7 +41,7 @@ static const Rule rules[] = { - /* 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 Bool resizehints = True; /* True means respect size hints in tiled resizals */ -+static const Bool resizehints = False; /* True means respect size hints in tiled resizals */ - - static const Layout layouts[] = { - /* symbol arrange function */ -@@ -59,6 +71,7 @@ static Key keys[] = { - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, - { MODKEY, XK_b, togglebar, {0} }, -+ { MODKEY, XK_w, tabmode, {-1} }, - { MODKEY, XK_j, focusstack, {.i = +1 } }, - { MODKEY, XK_k, focusstack, {.i = -1 } }, - { MODKEY, XK_i, incnmaster, {.i = +1 } }, -@@ -106,5 +119,6 @@ static Button buttons[] = { - { ClkTagBar, 0, Button3, toggleview, {0} }, - { ClkTagBar, MODKEY, Button1, tag, {0} }, - { ClkTagBar, MODKEY, Button3, toggletag, {0} }, -+ { ClkTabBar, 0, Button1, focuswin, {0} }, - }; - -diff --git a/dwm.1 b/dwm.1 -index 6687011..9f5c274 100644 ---- a/dwm.1 -+++ b/dwm.1 -@@ -19,14 +19,22 @@ layout applied. - 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. -+Each screen contains two small status bars. -+.P -+One bar 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 -+Another bar contains a tab for each window of the current view and allows -+navigation between windows, especially in the monocle mode. The different -+display modes of this bar are described under the Mod1\-w Keybord command -+section. When a single tag is selected, that tag is indicated in the left corner -+of the tab bar. - .P - dwm draws a small border around windows to indicate the focus state. - .SH OPTIONS -@@ -43,7 +51,8 @@ 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. -+label toggles between tiled and floating layout, click on a window name in the -+tab bar brings focus to that window. - .TP - .B Button3 - click on a tag label adds/removes all windows with that tag to/from the view. -@@ -104,6 +113,12 @@ Increase master area size. - .B Mod1\-h - Decrease master area size. - .TP -+.B Mod1\-w -+Cycle over the tab bar display modes: never displayed, always displayed, -+displayed only in monocle mode when the view contains than one window (auto -+mode). Some display modes can be disabled in the configuration, config.h. In -+the default configuration only "never" and "auto" display modes are enabled. -+.TP - .B Mod1\-Return - Zooms/cycles focused window to/from master area (tiled layouts only). - .TP -diff --git a/dwm.c b/dwm.c -index 1bbb4b3..a9a11b2 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -63,7 +63,7 @@ enum { NetSupported, NetWMName, NetWMState, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ - enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ --enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, -+enum { ClkTagBar, ClkTabBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, - ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ - - typedef union { -@@ -110,25 +110,36 @@ typedef struct { - void (*arrange)(Monitor *); - } Layout; - -+typedef struct Pertag Pertag; -+ -+#define MAXTABS 50 -+ - struct Monitor { - char ltsymbol[16]; - float mfact; - int nmaster; - int num; - int by; /* bar geometry */ -+ int ty; /* tab bar geometry */ - int mx, my, mw, mh; /* screen size */ - int wx, wy, ww, wh; /* window area */ - unsigned int seltags; - unsigned int sellt; - unsigned int tagset[2]; - Bool showbar; -+ Bool showtab; - Bool topbar; -+ Bool toptab; - Client *clients; - Client *sel; - Client *stack; - Monitor *next; - Window barwin; -+ Window tabwin; -+ int ntabs; -+ int tab_widths[MAXTABS]; - const Layout *lt[2]; -+ Pertag *pertag; - }; - - typedef struct { -@@ -163,12 +174,15 @@ static void detachstack(Client *c); - static Monitor *dirtomon(int dir); - static void drawbar(Monitor *m); - static void drawbars(void); -+static void drawtab(Monitor *m); -+static void drawtabs(void); - 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 void focuswin(const Arg* arg); - static Bool getrootptr(int *x, int *y); - static long getstate(Window w); - static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); -@@ -205,6 +219,7 @@ static void setup(void); - static void showhide(Client *c); - static void sigchld(int unused); - static void spawn(const Arg *arg); -+static void tabmode(const Arg *arg); - static void tag(const Arg *arg); - static void tagmon(const Arg *arg); - static void tile(Monitor *); -@@ -239,6 +254,7 @@ static char stext[256]; - static int screen; - static int sw, sh; /* X display screen geometry width, height */ - static int bh, blw = 0; /* bar geometry */ -+static int th = 0; /* tab bar geometry */ - static int (*xerrorxlib)(Display *, XErrorEvent *); - static unsigned int numlockmask = 0; - static void (*handler[LASTEvent]) (XEvent *) = { -@@ -270,6 +286,15 @@ static Window root; - /* configuration, allows nested code to access above variables */ - #include "config.h" - -+struct Pertag { -+ unsigned int curtag, prevtag; /* current and previous tag */ -+ int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */ -+ float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */ -+ unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */ -+ const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes */ -+ Bool showbars[LENGTH(tags) + 1]; /* display bar for the current tag */ -+}; -+ - /* compile-time check if all tags fit into an unsigned int bit array. */ - struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; - -@@ -389,6 +414,9 @@ arrange(Monitor *m) { - - void - arrangemon(Monitor *m) { -+ updatebarpos(m); -+ XMoveResizeWindow(dpy, m->tabwin, m->wx, m->ty, m->ww, th); -+ - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); - if(m->lt[m->sellt]->arrange) - m->lt[m->sellt]->arrange(m); -@@ -437,14 +465,32 @@ buttonpress(XEvent *e) { - else - click = ClkWinTitle; - } -+ if(ev->window == selmon->tabwin) { -+ i = 0; x = 0; -+ for(c = selmon->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ x += selmon->tab_widths[i]; -+ if (ev->x > x) -+ ++i; -+ else -+ break; -+ if(i >= m->ntabs) break; -+ } -+ if(c) { -+ click = ClkTabBar; -+ arg.ui = i; -+ } -+ } - else if((c = wintoclient(ev->window))) { - focus(c); - 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); -+ && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)){ -+ buttons[i].func(((click == ClkTagBar || click == ClkTabBar) -+ && buttons[i].arg.i == 0) ? &arg : &buttons[i].arg); -+ } - } - - void -@@ -499,6 +545,8 @@ cleanupmon(Monitor *mon) { - } - XUnmapWindow(dpy, mon->barwin); - XDestroyWindow(dpy, mon->barwin); -+ XUnmapWindow(dpy, mon->tabwin); -+ XDestroyWindow(dpy, mon->tabwin); - free(mon); - } - -@@ -567,8 +615,11 @@ configurenotify(XEvent *e) { - if(updategeom() || dirty) { - drw_resize(drw, sw, bh); - updatebars(); -- for(m = mons; m; m = m->next) -+ //refreshing display of status bar. The tab bar is handled by the arrange() -+ //method, which is called below -+ for(m = mons; m; m = m->next){ - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); -+ } - focus(NULL); - arrange(NULL); - } -@@ -631,6 +682,7 @@ configurerequest(XEvent *e) { - Monitor * - createmon(void) { - Monitor *m; -+ int i; - - if(!(m = (Monitor *)calloc(1, sizeof(Monitor)))) - die("fatal: could not malloc() %u bytes\n", sizeof(Monitor)); -@@ -638,10 +690,31 @@ createmon(void) { - m->mfact = mfact; - m->nmaster = nmaster; - m->showbar = showbar; -+ m->showtab = showtab; - m->topbar = topbar; -- m->lt[0] = &layouts[0]; -+ m->ntabs = 0; -+ m->sellt = 0; -+ m->lt[0] = &layouts[def_layouts[1] % LENGTH(layouts)]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); -+ if(!(m->pertag = (Pertag *)calloc(1, sizeof(Pertag)))) -+ die("fatal: could not malloc() %u bytes\n", sizeof(Pertag)); -+ m->pertag->curtag = m->pertag->prevtag = 1; -+ for(i=0; i <= LENGTH(tags); i++) { -+ /* init nmaster */ -+ m->pertag->nmasters[i] = m->nmaster; -+ -+ /* init mfacts */ -+ m->pertag->mfacts[i] = m->mfact; -+ -+ /* init layouts */ -+ m->pertag->ltidxs[i][0] = m->lt[0]; -+ m->pertag->ltidxs[i][1] = m->lt[1]; -+ m->pertag->sellts[i] = m->sellt; -+ -+ /* init showbar */ -+ m->pertag->showbars[i] = m->showbar; -+ } - return m; - } - -@@ -750,6 +823,104 @@ drawbars(void) { - } - - void -+drawtabs(void) { -+ Monitor *m; -+ -+ for(m = mons; m; m = m->next) -+ drawtab(m); -+} -+ -+static int -+cmpint(const void *p1, const void *p2) { -+ /* The actual arguments to this function are "pointers to -+ pointers to char", but strcmp(3) arguments are "pointers -+ to char", hence the following cast plus dereference */ -+ return *((int*) p1) > * (int*) p2; -+} -+ -+ -+void -+drawtab(Monitor *m) { -+ Client *c; -+ int i; -+ int itag = -1; -+ char view_info[50]; -+ int view_info_w = 0; -+ int sorted_label_widths[MAXTABS]; -+ int tot_width; -+ int maxsize = bh; -+ int x = 0; -+ int w = 0; -+ -+ //view_info: indicate the tag which is displayed in the view -+ for(i = 0; i < LENGTH(tags); ++i){ -+ if((selmon->tagset[selmon->seltags] >> i) & 1) { -+ if(itag >=0){ //more than one tag selected -+ itag = -1; -+ break; -+ } -+ itag = i; -+ } -+ } -+ if(0 <= itag && itag < LENGTH(tags)){ -+ snprintf(view_info, sizeof view_info, "[%s]", tags[itag]); -+ } else { -+ strncpy(view_info, "[...]", sizeof view_info); -+ } -+ view_info[sizeof(view_info) - 1 ] = 0; -+ view_info_w = TEXTW(view_info); -+ tot_width = view_info_w; -+ -+ /* Calculates number of labels and their width */ -+ m->ntabs = 0; -+ for(c = m->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ m->tab_widths[m->ntabs] = TEXTW(c->name); -+ tot_width += m->tab_widths[m->ntabs]; -+ ++m->ntabs; -+ if(m->ntabs >= MAXTABS) break; -+ } -+ -+ if(tot_width > m->ww){ //not enough space to display the labels, they need to be truncated -+ memcpy(sorted_label_widths, m->tab_widths, sizeof(int) * m->ntabs); -+ qsort(sorted_label_widths, m->ntabs, sizeof(int), cmpint); -+ tot_width = view_info_w; -+ for(i = 0; i < m->ntabs; ++i){ -+ if(tot_width + (m->ntabs - i) * sorted_label_widths[i] > m->ww) -+ break; -+ tot_width += sorted_label_widths[i]; -+ } -+ maxsize = (m->ww - tot_width) / (m->ntabs - i); -+ } else{ -+ maxsize = m->ww; -+ } -+ i = 0; -+ for(c = m->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ if(i >= m->ntabs) break; -+ if(m->tab_widths[i] > maxsize) m->tab_widths[i] = maxsize; -+ w = m->tab_widths[i]; -+ drw_setscheme(drw, (c == m->sel) ? &scheme[SchemeSel] : &scheme[SchemeNorm]); -+ drw_text(drw, x, 0, w, th, c->name, 0); -+ x += w; -+ ++i; -+ } -+ -+ drw_setscheme(drw, &scheme[SchemeNorm]); -+ -+ /* cleans interspace between window names and current viewed tag label */ -+ w = m->ww - view_info_w - x; -+ drw_text(drw, x, 0, w, th, NULL, 0); -+ -+ /* view info */ -+ x += w; -+ w = view_info_w; -+ drw_text(drw, x, 0, w, th, view_info, 0); -+ -+ drw_map(drw, m->tabwin, 0, 0, m->ww, th); -+} -+ -+void - enternotify(XEvent *e) { - Client *c; - Monitor *m; -@@ -773,8 +944,10 @@ expose(XEvent *e) { - Monitor *m; - XExposeEvent *ev = &e->xexpose; - -- if(ev->count == 0 && (m = wintomon(ev->window))) -+ if(ev->count == 0 && (m = wintomon(ev->window))){ - drawbar(m); -+ drawtab(m); -+ } - } - - void -@@ -801,6 +974,7 @@ focus(Client *c) { - } - selmon->sel = c; - drawbars(); -+ drawtabs(); - } - - void -@@ -851,6 +1025,19 @@ focusstack(const Arg *arg) { - } - } - -+void -+focuswin(const Arg* arg){ -+ int iwin = arg->i; -+ Client* c = NULL; -+ for(c = selmon->clients; c && (iwin || !ISVISIBLE(c)) ; c = c->next){ -+ if(ISVISIBLE(c)) --iwin; -+ }; -+ if(c) { -+ focus(c); -+ restack(selmon); -+ } -+} -+ - Atom - getatomprop(Client *c, Atom prop) { - int di; -@@ -958,7 +1145,7 @@ grabkeys(void) { - - void - incnmaster(const Arg *arg) { -- selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); -+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0); - arrange(selmon); - } - -@@ -1212,12 +1399,14 @@ propertynotify(XEvent *e) { - case XA_WM_HINTS: - updatewmhints(c); - drawbars(); -+ drawtabs(); - break; - } - if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { - updatetitle(c); - if(c == c->mon->sel) - drawbar(c->mon); -+ drawtab(c->mon); - } - if(ev->atom == netatom[NetWMWindowType]) - updatewindowtype(c); -@@ -1321,6 +1510,7 @@ restack(Monitor *m) { - XWindowChanges wc; - - drawbar(m); -+ drawtab(m); - if(!m->sel) - return; - if(m->sel->isfloating || !m->lt[m->sellt]->arrange) -@@ -1462,10 +1652,13 @@ setfullscreen(Client *c, Bool fullscreen) { - - void - setlayout(const Arg *arg) { -- if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) -- selmon->sellt ^= 1; -+ if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) { -+ selmon->pertag->sellts[selmon->pertag->curtag] ^= 1; -+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; -+ } - if(arg && arg->v) -- selmon->lt[selmon->sellt] = (Layout *)arg->v; -+ selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v; -+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; - strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); - if(selmon->sel) - arrange(selmon); -@@ -1483,7 +1676,7 @@ setmfact(const Arg *arg) { - f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; - if(f < 0.1 || f > 0.9) - return; -- selmon->mfact = f; -+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; - arrange(selmon); - } - -@@ -1501,6 +1694,7 @@ setup(void) { - sw = DisplayWidth(dpy, screen); - sh = DisplayHeight(dpy, screen); - bh = fnt->h + 2; -+ th = bh; - drw = drw_create(dpy, screen, root, sw, sh); - drw_setfont(drw, fnt); - updategeom(); -@@ -1627,13 +1821,23 @@ tile(Monitor *m) { - - void - togglebar(const Arg *arg) { -- selmon->showbar = !selmon->showbar; -+ selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar; - updatebarpos(selmon); - XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); - arrange(selmon); - } - - void -+tabmode(const Arg *arg) { -+ if(arg && arg->i >= 0) -+ selmon->showtab = arg->ui % showtab_nmodes; -+ else -+ selmon->showtab = (selmon->showtab + 1 ) % showtab_nmodes; -+ arrange(selmon); -+} -+ -+ -+void - togglefloating(const Arg *arg) { - if(!selmon->sel) - return; -@@ -1663,9 +1867,29 @@ toggletag(const Arg *arg) { - void - toggleview(const Arg *arg) { - unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); -+ int i; - - if(newtagset) { -+ if(newtagset == ~0) { -+ selmon->pertag->prevtag = selmon->pertag->curtag; -+ selmon->pertag->curtag = 0; -+ } -+ /* test if the user did not select the same tag */ -+ if(!(newtagset & 1 << (selmon->pertag->curtag - 1))) { -+ selmon->pertag->prevtag = selmon->pertag->curtag; -+ for (i=0; !(newtagset & 1 << i); i++) ; -+ selmon->pertag->curtag = i + 1; -+ } - selmon->tagset[selmon->seltags] = newtagset; -+ -+ /* apply settings for this view */ -+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; -+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; -+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; -+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; -+ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; -+ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) -+ togglebar(NULL); - focus(NULL); - arrange(selmon); - } -@@ -1737,20 +1961,43 @@ updatebars(void) { - CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); - XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); - XMapRaised(dpy, m->barwin); -+ m->tabwin = XCreateWindow(dpy, root, m->wx, m->ty, m->ww, th, 0, DefaultDepth(dpy, screen), -+ CopyFromParent, DefaultVisual(dpy, screen), -+ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); -+ XDefineCursor(dpy, m->tabwin, cursor[CurNormal]->cursor); -+ XMapRaised(dpy, m->tabwin); - } - } - - void - updatebarpos(Monitor *m) { -+ Client *c; -+ int nvis = 0; -+ - m->wy = m->my; - m->wh = m->mh; - if(m->showbar) { - m->wh -= bh; - m->by = m->topbar ? m->wy : m->wy + m->wh; -- m->wy = m->topbar ? m->wy + bh : m->wy; -- } -- else -+ if ( m->topbar ) -+ m->wy += bh; -+ } else { - m->by = -bh; -+ } -+ -+ for(c = m->clients; c; c = c->next){ -+ if(ISVISIBLE(c)) ++nvis; -+ } -+ -+ if(m->showtab == showtab_always -+ || ((m->showtab == showtab_auto) && (nvis > 1) && (m->lt[m->sellt]->arrange == monocle))){ -+ m->wh -= th; -+ m->ty = m->toptab ? m->wy : m->wy + m->wh; -+ if ( m->toptab ) -+ m->wy += th; -+ } else { -+ m->ty = -th; -+ } - } - - void -@@ -1960,11 +2207,33 @@ updatewmhints(Client *c) { - - void - view(const Arg *arg) { -+ int i; -+ unsigned int tmptag; -+ - if((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) - return; - selmon->seltags ^= 1; /* toggle sel tagset */ -- if(arg->ui & TAGMASK) -+ if(arg->ui & TAGMASK) { -+ selmon->pertag->prevtag = selmon->pertag->curtag; - selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; -+ if(arg->ui == ~0) -+ selmon->pertag->curtag = 0; -+ else { -+ for (i=0; !(arg->ui & 1 << i); i++) ; -+ selmon->pertag->curtag = i + 1; -+ } -+ } else { -+ tmptag = selmon->pertag->prevtag; -+ selmon->pertag->prevtag = selmon->pertag->curtag; -+ selmon->pertag->curtag = tmptag; -+ } -+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; -+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; -+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; -+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; -+ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; -+ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) -+ togglebar(NULL); - focus(NULL); - arrange(selmon); - } -@@ -1990,7 +2259,7 @@ wintomon(Window w) { - if(w == root && getrootptr(&x, &y)) - return recttomon(x, y, 1, 1); - for(m = mons; m; m = m->next) -- if(w == m->barwin) -+ if(w == m->barwin || w == m->tabwin) - return m; - if((c = wintoclient(w))) - return c->mon; diff --git a/dwm.suckless.org/patches/historical/dwm-master_2013-08-27_cdec978-tab-v2a.diff b/dwm.suckless.org/patches/historical/dwm-master_2013-08-27_cdec978-tab-v2a.diff @@ -1,505 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 875885b..4f653c5 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -12,6 +12,13 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ - static const unsigned int snap = 32; /* snap pixel */ - static const Bool showbar = True; /* False means no bar */ - static const Bool topbar = True; /* False means bottom bar */ -+/* Display modes of the tab bar: never shown, always shown, shown only in */ -+/* monocle mode in presence of several windows. */ -+/* Modes after showtab_nmodes are disabled */ -+enum showtab_modes { showtab_never, showtab_auto, showtab_nmodes, showtab_always}; -+static const int showtab = showtab_auto; /* Default tab bar show mode */ -+static const Bool toptab = False; /* False means bottom tab bar */ -+ - - /* tagging */ - static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; -@@ -29,7 +36,7 @@ static const Rule rules[] = { - /* 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 Bool resizehints = True; /* True means respect size hints in tiled resizals */ -+static const Bool resizehints = False; /* True means respect size hints in tiled resizals */ - - static const Layout layouts[] = { - /* symbol arrange function */ -@@ -59,6 +66,7 @@ static Key keys[] = { - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, - { MODKEY, XK_b, togglebar, {0} }, -+ { MODKEY, XK_w, tabmode, {-1} }, - { MODKEY, XK_j, focusstack, {.i = +1 } }, - { MODKEY, XK_k, focusstack, {.i = -1 } }, - { MODKEY, XK_i, incnmaster, {.i = +1 } }, -@@ -106,5 +114,6 @@ static Button buttons[] = { - { ClkTagBar, 0, Button3, toggleview, {0} }, - { ClkTagBar, MODKEY, Button1, tag, {0} }, - { ClkTagBar, MODKEY, Button3, toggletag, {0} }, -+ { ClkTabBar, 0, Button1, focuswin, {0} }, - }; - -diff --git a/dwm.1 b/dwm.1 -index 6687011..9f5c274 100644 ---- a/dwm.1 -+++ b/dwm.1 -@@ -19,14 +19,22 @@ layout applied. - 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. -+Each screen contains two small status bars. -+.P -+One bar 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 -+Another bar contains a tab for each window of the current view and allows -+navigation between windows, especially in the monocle mode. The different -+display modes of this bar are described under the Mod1\-w Keybord command -+section. When a single tag is selected, that tag is indicated in the left corner -+of the tab bar. - .P - dwm draws a small border around windows to indicate the focus state. - .SH OPTIONS -@@ -43,7 +51,8 @@ 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. -+label toggles between tiled and floating layout, click on a window name in the -+tab bar brings focus to that window. - .TP - .B Button3 - click on a tag label adds/removes all windows with that tag to/from the view. -@@ -104,6 +113,12 @@ Increase master area size. - .B Mod1\-h - Decrease master area size. - .TP -+.B Mod1\-w -+Cycle over the tab bar display modes: never displayed, always displayed, -+displayed only in monocle mode when the view contains than one window (auto -+mode). Some display modes can be disabled in the configuration, config.h. In -+the default configuration only "never" and "auto" display modes are enabled. -+.TP - .B Mod1\-Return - Zooms/cycles focused window to/from master area (tiled layouts only). - .TP -diff --git a/dwm.c b/dwm.c -index 1bbb4b3..b73d6ca 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -63,7 +63,7 @@ enum { NetSupported, NetWMName, NetWMState, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ - enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ --enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, -+enum { ClkTagBar, ClkTabBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, - ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ - - typedef union { -@@ -110,24 +110,32 @@ typedef struct { - void (*arrange)(Monitor *); - } Layout; - -+#define MAXTABS 50 -+ - struct Monitor { - char ltsymbol[16]; - float mfact; - int nmaster; - int num; - int by; /* bar geometry */ -+ int ty; /* tab bar geometry */ - int mx, my, mw, mh; /* screen size */ - int wx, wy, ww, wh; /* window area */ - unsigned int seltags; - unsigned int sellt; - unsigned int tagset[2]; - Bool showbar; -+ Bool showtab; - Bool topbar; -+ Bool toptab; - Client *clients; - Client *sel; - Client *stack; - Monitor *next; - Window barwin; -+ Window tabwin; -+ int ntabs; -+ int tab_widths[MAXTABS]; - const Layout *lt[2]; - }; - -@@ -163,12 +171,15 @@ static void detachstack(Client *c); - static Monitor *dirtomon(int dir); - static void drawbar(Monitor *m); - static void drawbars(void); -+static void drawtab(Monitor *m); -+static void drawtabs(void); - 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 void focuswin(const Arg* arg); - static Bool getrootptr(int *x, int *y); - static long getstate(Window w); - static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); -@@ -205,6 +216,7 @@ static void setup(void); - static void showhide(Client *c); - static void sigchld(int unused); - static void spawn(const Arg *arg); -+static void tabmode(const Arg *arg); - static void tag(const Arg *arg); - static void tagmon(const Arg *arg); - static void tile(Monitor *); -@@ -239,6 +251,7 @@ static char stext[256]; - static int screen; - static int sw, sh; /* X display screen geometry width, height */ - static int bh, blw = 0; /* bar geometry */ -+static int th = 0; /* tab bar geometry */ - static int (*xerrorxlib)(Display *, XErrorEvent *); - static unsigned int numlockmask = 0; - static void (*handler[LASTEvent]) (XEvent *) = { -@@ -389,6 +402,9 @@ arrange(Monitor *m) { - - void - arrangemon(Monitor *m) { -+ updatebarpos(m); -+ XMoveResizeWindow(dpy, m->tabwin, m->wx, m->ty, m->ww, th); -+ - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); - if(m->lt[m->sellt]->arrange) - m->lt[m->sellt]->arrange(m); -@@ -437,14 +453,32 @@ buttonpress(XEvent *e) { - else - click = ClkWinTitle; - } -+ if(ev->window == selmon->tabwin) { -+ i = 0; x = 0; -+ for(c = selmon->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ x += selmon->tab_widths[i]; -+ if (ev->x > x) -+ ++i; -+ else -+ break; -+ if(i >= m->ntabs) break; -+ } -+ if(c) { -+ click = ClkTabBar; -+ arg.ui = i; -+ } -+ } - else if((c = wintoclient(ev->window))) { - focus(c); - 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); -+ && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)){ -+ buttons[i].func(((click == ClkTagBar || click == ClkTabBar) -+ && buttons[i].arg.i == 0) ? &arg : &buttons[i].arg); -+ } - } - - void -@@ -499,6 +533,8 @@ cleanupmon(Monitor *mon) { - } - XUnmapWindow(dpy, mon->barwin); - XDestroyWindow(dpy, mon->barwin); -+ XUnmapWindow(dpy, mon->tabwin); -+ XDestroyWindow(dpy, mon->tabwin); - free(mon); - } - -@@ -567,8 +603,11 @@ configurenotify(XEvent *e) { - if(updategeom() || dirty) { - drw_resize(drw, sw, bh); - updatebars(); -- for(m = mons; m; m = m->next) -+ //refreshing display of status bar. The tab bar is handled by the arrange() -+ //method, which is called below -+ for(m = mons; m; m = m->next){ - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); -+ } - focus(NULL); - arrange(NULL); - } -@@ -638,7 +677,10 @@ createmon(void) { - m->mfact = mfact; - m->nmaster = nmaster; - m->showbar = showbar; -+ m->showtab = showtab; - m->topbar = topbar; -+ m->toptab = toptab; -+ m->ntabs = 0; - m->lt[0] = &layouts[0]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); -@@ -750,6 +792,104 @@ drawbars(void) { - } - - void -+drawtabs(void) { -+ Monitor *m; -+ -+ for(m = mons; m; m = m->next) -+ drawtab(m); -+} -+ -+static int -+cmpint(const void *p1, const void *p2) { -+ /* The actual arguments to this function are "pointers to -+ pointers to char", but strcmp(3) arguments are "pointers -+ to char", hence the following cast plus dereference */ -+ return *((int*) p1) > * (int*) p2; -+} -+ -+ -+void -+drawtab(Monitor *m) { -+ Client *c; -+ int i; -+ int itag = -1; -+ char view_info[50]; -+ int view_info_w = 0; -+ int sorted_label_widths[MAXTABS]; -+ int tot_width; -+ int maxsize = bh; -+ int x = 0; -+ int w = 0; -+ -+ //view_info: indicate the tag which is displayed in the view -+ for(i = 0; i < LENGTH(tags); ++i){ -+ if((selmon->tagset[selmon->seltags] >> i) & 1) { -+ if(itag >=0){ //more than one tag selected -+ itag = -1; -+ break; -+ } -+ itag = i; -+ } -+ } -+ if(0 <= itag && itag < LENGTH(tags)){ -+ snprintf(view_info, sizeof view_info, "[%s]", tags[itag]); -+ } else { -+ strncpy(view_info, "[...]", sizeof view_info); -+ } -+ view_info[sizeof(view_info) - 1 ] = 0; -+ view_info_w = TEXTW(view_info); -+ tot_width = view_info_w; -+ -+ /* Calculates number of labels and their width */ -+ m->ntabs = 0; -+ for(c = m->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ m->tab_widths[m->ntabs] = TEXTW(c->name); -+ tot_width += m->tab_widths[m->ntabs]; -+ ++m->ntabs; -+ if(m->ntabs >= MAXTABS) break; -+ } -+ -+ if(tot_width > m->ww){ //not enough space to display the labels, they need to be truncated -+ memcpy(sorted_label_widths, m->tab_widths, sizeof(int) * m->ntabs); -+ qsort(sorted_label_widths, m->ntabs, sizeof(int), cmpint); -+ tot_width = view_info_w; -+ for(i = 0; i < m->ntabs; ++i){ -+ if(tot_width + (m->ntabs - i) * sorted_label_widths[i] > m->ww) -+ break; -+ tot_width += sorted_label_widths[i]; -+ } -+ maxsize = (m->ww - tot_width) / (m->ntabs - i); -+ } else{ -+ maxsize = m->ww; -+ } -+ i = 0; -+ for(c = m->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ if(i >= m->ntabs) break; -+ if(m->tab_widths[i] > maxsize) m->tab_widths[i] = maxsize; -+ w = m->tab_widths[i]; -+ drw_setscheme(drw, (c == m->sel) ? &scheme[SchemeSel] : &scheme[SchemeNorm]); -+ drw_text(drw, x, 0, w, th, c->name, 0); -+ x += w; -+ ++i; -+ } -+ -+ drw_setscheme(drw, &scheme[SchemeNorm]); -+ -+ /* cleans interspace between window names and current viewed tag label */ -+ w = m->ww - view_info_w - x; -+ drw_text(drw, x, 0, w, th, NULL, 0); -+ -+ /* view info */ -+ x += w; -+ w = view_info_w; -+ drw_text(drw, x, 0, w, th, view_info, 0); -+ -+ drw_map(drw, m->tabwin, 0, 0, m->ww, th); -+} -+ -+void - enternotify(XEvent *e) { - Client *c; - Monitor *m; -@@ -773,8 +913,10 @@ expose(XEvent *e) { - Monitor *m; - XExposeEvent *ev = &e->xexpose; - -- if(ev->count == 0 && (m = wintomon(ev->window))) -+ if(ev->count == 0 && (m = wintomon(ev->window))){ - drawbar(m); -+ drawtab(m); -+ } - } - - void -@@ -801,6 +943,7 @@ focus(Client *c) { - } - selmon->sel = c; - drawbars(); -+ drawtabs(); - } - - void -@@ -851,6 +994,19 @@ focusstack(const Arg *arg) { - } - } - -+void -+focuswin(const Arg* arg){ -+ int iwin = arg->i; -+ Client* c = NULL; -+ for(c = selmon->clients; c && (iwin || !ISVISIBLE(c)) ; c = c->next){ -+ if(ISVISIBLE(c)) --iwin; -+ }; -+ if(c) { -+ focus(c); -+ restack(selmon); -+ } -+} -+ - Atom - getatomprop(Client *c, Atom prop) { - int di; -@@ -1212,12 +1368,14 @@ propertynotify(XEvent *e) { - case XA_WM_HINTS: - updatewmhints(c); - drawbars(); -+ drawtabs(); - break; - } - if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { - updatetitle(c); - if(c == c->mon->sel) - drawbar(c->mon); -+ drawtab(c->mon); - } - if(ev->atom == netatom[NetWMWindowType]) - updatewindowtype(c); -@@ -1321,6 +1479,7 @@ restack(Monitor *m) { - XWindowChanges wc; - - drawbar(m); -+ drawtab(m); - if(!m->sel) - return; - if(m->sel->isfloating || !m->lt[m->sellt]->arrange) -@@ -1501,6 +1660,7 @@ setup(void) { - sw = DisplayWidth(dpy, screen); - sh = DisplayHeight(dpy, screen); - bh = fnt->h + 2; -+ th = bh; - drw = drw_create(dpy, screen, root, sw, sh); - drw_setfont(drw, fnt); - updategeom(); -@@ -1634,6 +1794,16 @@ togglebar(const Arg *arg) { - } - - void -+tabmode(const Arg *arg) { -+ if(arg && arg->i >= 0) -+ selmon->showtab = arg->ui % showtab_nmodes; -+ else -+ selmon->showtab = (selmon->showtab + 1 ) % showtab_nmodes; -+ arrange(selmon); -+} -+ -+ -+void - togglefloating(const Arg *arg) { - if(!selmon->sel) - return; -@@ -1737,20 +1907,43 @@ updatebars(void) { - CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); - XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); - XMapRaised(dpy, m->barwin); -+ m->tabwin = XCreateWindow(dpy, root, m->wx, m->ty, m->ww, th, 0, DefaultDepth(dpy, screen), -+ CopyFromParent, DefaultVisual(dpy, screen), -+ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); -+ XDefineCursor(dpy, m->tabwin, cursor[CurNormal]->cursor); -+ XMapRaised(dpy, m->tabwin); - } - } - - void - updatebarpos(Monitor *m) { -+ Client *c; -+ int nvis = 0; -+ - m->wy = m->my; - m->wh = m->mh; - if(m->showbar) { - m->wh -= bh; - m->by = m->topbar ? m->wy : m->wy + m->wh; -- m->wy = m->topbar ? m->wy + bh : m->wy; -- } -- else -+ if ( m->topbar ) -+ m->wy += bh; -+ } else { - m->by = -bh; -+ } -+ -+ for(c = m->clients; c; c = c->next){ -+ if(ISVISIBLE(c)) ++nvis; -+ } -+ -+ if(m->showtab == showtab_always -+ || ((m->showtab == showtab_auto) && (nvis > 1) && (m->lt[m->sellt]->arrange == monocle))){ -+ m->wh -= th; -+ m->ty = m->toptab ? m->wy : m->wy + m->wh; -+ if ( m->toptab ) -+ m->wy += th; -+ } else { -+ m->ty = -th; -+ } - } - - void -@@ -1990,7 +2183,7 @@ wintomon(Window w) { - if(w == root && getrootptr(&x, &y)) - return recttomon(x, y, 1, 1); - for(m = mons; m; m = m->next) -- if(w == m->barwin) -+ if(w == m->barwin || w == m->tabwin) - return m; - if((c = wintoclient(w))) - return c->mon; diff --git a/dwm.suckless.org/patches/historical/dwm-master_2015-03-05_14343e-pertag-tab-v2b.diff b/dwm.suckless.org/patches/historical/dwm-master_2015-03-05_14343e-pertag-tab-v2b.diff @@ -1,693 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index eaae8f3..a07814b 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -17,10 +17,22 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ - static const unsigned int snap = 32; /* snap pixel */ - static const Bool showbar = True; /* False means no bar */ - static const Bool topbar = True; /* False means bottom bar */ -+/* Display modes of the tab bar: never shown, always shown, shown only in */ -+/* monocle mode in presence of several windows. */ -+/* Modes after showtab_nmodes are disabled */ -+enum showtab_modes { showtab_never, showtab_auto, showtab_nmodes, showtab_always}; -+static const int showtab = showtab_auto; /* Default tab bar show mode */ -+static const Bool toptab = False; /* False means bottom tab bar */ -+ - - /* tagging */ - static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; - -+/* default layout per tags */ -+/* The first element is for all-tag view, following i-th element corresponds to */ -+/* tags[i]. Layout is referred using the layouts array index.*/ -+static int def_layouts[1 + LENGTH(tags)] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -+ - static const Rule rules[] = { - /* xprop(1): - * WM_CLASS(STRING) = instance, class -@@ -34,7 +46,7 @@ static const Rule rules[] = { - /* 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 Bool resizehints = True; /* True means respect size hints in tiled resizals */ -+static const Bool resizehints = False; /* True means respect size hints in tiled resizals */ - - static const Layout layouts[] = { - /* symbol arrange function */ -@@ -64,6 +76,7 @@ static Key keys[] = { - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, - { MODKEY, XK_b, togglebar, {0} }, -+ { MODKEY, XK_w, tabmode, {-1} }, - { MODKEY, XK_j, focusstack, {.i = +1 } }, - { MODKEY, XK_k, focusstack, {.i = -1 } }, - { MODKEY, XK_i, incnmaster, {.i = +1 } }, -@@ -111,5 +124,6 @@ static Button buttons[] = { - { ClkTagBar, 0, Button3, toggleview, {0} }, - { ClkTagBar, MODKEY, Button1, tag, {0} }, - { ClkTagBar, MODKEY, Button3, toggletag, {0} }, -+ { ClkTabBar, 0, Button1, focuswin, {0} }, - }; - -diff --git a/dwm.1 b/dwm.1 -index 6687011..077d92b 100644 ---- a/dwm.1 -+++ b/dwm.1 -@@ -19,14 +19,22 @@ layout applied. - 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. -+Each screen contains two small status bars. -+.P -+One bar 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 -+Another bar contains a tab for each window of the current view and allows -+navigation between windows, especially in the monocle mode. The different -+display modes of this bar are described under the Mod1\-w Keybord command -+section. When a single tag is selected, that tag is indicated in the left corner -+of the tab bar. - .P - dwm draws a small border around windows to indicate the focus state. - .SH OPTIONS -@@ -43,7 +51,8 @@ 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. -+label toggles between tiled and floating layout, click on a window name in the -+tab bar brings focus to that window. - .TP - .B Button3 - click on a tag label adds/removes all windows with that tag to/from the view. -@@ -104,6 +113,12 @@ Increase master area size. - .B Mod1\-h - Decrease master area size. - .TP -+.B Mod1\-w -+Cycle over the tab bar display modes: never displayed, always displayed, -+displayed only in monocle mode when the view contains than one window (auto -+mode). Some display modes can be disabled in the configuration, config.h. In -+the default configuration only "never" and "auto" display modes are enabled. -+.TP - .B Mod1\-Return - Zooms/cycles focused window to/from master area (tiled layouts only). - .TP -diff --git a/dwm.c b/dwm.c -index 169adcb..515a30f 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -64,7 +64,7 @@ enum { NetSupported, NetWMName, NetWMState, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ - enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ --enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, -+enum { ClkTagBar, ClkTabBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, - ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ - - typedef union { -@@ -111,25 +111,35 @@ typedef struct { - void (*arrange)(Monitor *); - } Layout; - -+#define MAXTABS 50 -+ -+typedef struct Pertag Pertag; - struct Monitor { - char ltsymbol[16]; - float mfact; - int nmaster; - int num; - int by; /* bar geometry */ -+ int ty; /* tab bar geometry */ - int mx, my, mw, mh; /* screen size */ - int wx, wy, ww, wh; /* window area */ - unsigned int seltags; - unsigned int sellt; - unsigned int tagset[2]; - Bool showbar; -+ Bool showtab; - Bool topbar; -+ Bool toptab; - Client *clients; - Client *sel; - Client *stack; - Monitor *next; - Window barwin; -+ Window tabwin; -+ int ntabs; -+ int tab_widths[MAXTABS]; - const Layout *lt[2]; -+ Pertag *pertag; - }; - - typedef struct { -@@ -164,12 +174,15 @@ static void detachstack(Client *c); - static Monitor *dirtomon(int dir); - static void drawbar(Monitor *m); - static void drawbars(void); -+static void drawtab(Monitor *m); -+static void drawtabs(void); - 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 void focuswin(const Arg* arg); - static Bool getrootptr(int *x, int *y); - static long getstate(Window w); - static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); -@@ -206,6 +219,7 @@ static void setup(void); - static void showhide(Client *c); - static void sigchld(int unused); - static void spawn(const Arg *arg); -+static void tabmode(const Arg *arg); - static void tag(const Arg *arg); - static void tagmon(const Arg *arg); - static void tile(Monitor *); -@@ -240,6 +254,7 @@ static char stext[256]; - static int screen; - static int sw, sh; /* X display screen geometry width, height */ - static int bh, blw = 0; /* bar geometry */ -+static int th = 0; /* tab bar geometry */ - static int (*xerrorxlib)(Display *, XErrorEvent *); - static unsigned int numlockmask = 0; - static void (*handler[LASTEvent]) (XEvent *) = { -@@ -270,6 +285,16 @@ static Window root; - /* configuration, allows nested code to access above variables */ - #include "config.h" - -+struct Pertag { -+ unsigned int curtag, prevtag; /* current and previous tag */ -+ int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */ -+ float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */ -+ unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */ -+ const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes */ -+ Bool showbars[LENGTH(tags) + 1]; /* display bar for the current tag */ -+ Client *prevzooms[LENGTH(tags) + 1]; /* store zoom information */ -+}; -+ - /* compile-time check if all tags fit into an unsigned int bit array. */ - struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; - -@@ -389,6 +414,9 @@ arrange(Monitor *m) { - - void - arrangemon(Monitor *m) { -+ updatebarpos(m); -+ XMoveResizeWindow(dpy, m->tabwin, m->wx, m->ty, m->ww, th); -+ - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); - if(m->lt[m->sellt]->arrange) - m->lt[m->sellt]->arrange(m); -@@ -437,14 +465,32 @@ buttonpress(XEvent *e) { - else - click = ClkWinTitle; - } -+ if(ev->window == selmon->tabwin) { -+ i = 0; x = 0; -+ for(c = selmon->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ x += selmon->tab_widths[i]; -+ if (ev->x > x) -+ ++i; -+ else -+ break; -+ if(i >= m->ntabs) break; -+ } -+ if(c) { -+ click = ClkTabBar; -+ arg.ui = i; -+ } -+ } - else if((c = wintoclient(ev->window))) { - focus(c); - 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); -+ && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)){ -+ buttons[i].func(((click == ClkTagBar || click == ClkTabBar) -+ && buttons[i].arg.i == 0) ? &arg : &buttons[i].arg); -+ } - } - - void -@@ -498,6 +544,8 @@ cleanupmon(Monitor *mon) { - } - XUnmapWindow(dpy, mon->barwin); - XDestroyWindow(dpy, mon->barwin); -+ XUnmapWindow(dpy, mon->tabwin); -+ XDestroyWindow(dpy, mon->tabwin); - free(mon); - } - -@@ -517,6 +565,7 @@ void - clientmessage(XEvent *e) { - XClientMessageEvent *cme = &e->xclient; - Client *c = wintoclient(cme->window); -+ int i; - - if(!c) - return; -@@ -529,6 +578,8 @@ clientmessage(XEvent *e) { - if(!ISVISIBLE(c)) { - c->mon->seltags ^= 1; - c->mon->tagset[c->mon->seltags] = c->tags; -+ for(i=0; !(c->tags & 1 << i); i++); -+ view(&(Arg){.ui = 1 << i}); - } - pop(c); - } -@@ -566,8 +617,11 @@ configurenotify(XEvent *e) { - if(updategeom() || dirty) { - drw_resize(drw, sw, bh); - updatebars(); -- for(m = mons; m; m = m->next) -+ //refreshing display of status bar. The tab bar is handled by the arrange() -+ //method, which is called below -+ for(m = mons; m; m = m->next){ - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); -+ } - focus(NULL); - arrange(NULL); - } -@@ -630,6 +684,7 @@ configurerequest(XEvent *e) { - Monitor * - createmon(void) { - Monitor *m; -+ int i; - - if(!(m = (Monitor *)calloc(1, sizeof(Monitor)))) - die("fatal: could not malloc() %u bytes\n", sizeof(Monitor)); -@@ -637,10 +692,34 @@ createmon(void) { - m->mfact = mfact; - m->nmaster = nmaster; - m->showbar = showbar; -+ m->showtab = showtab; - m->topbar = topbar; -- m->lt[0] = &layouts[0]; -+ m->toptab = toptab; -+ m->ntabs = 0; -+ m->lt[0] = &layouts[def_layouts[1] % LENGTH(layouts)]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); -+ if(!(m->pertag = (Pertag *)calloc(1, sizeof(Pertag)))) -+ die("fatal: could not malloc() %u bytes\n", sizeof(Pertag)); -+ m->pertag->curtag = m->pertag->prevtag = 1; -+ for(i=0; i <= LENGTH(tags); i++) { -+ /* init nmaster */ -+ m->pertag->nmasters[i] = m->nmaster; -+ -+ /* init mfacts */ -+ m->pertag->mfacts[i] = m->mfact; -+ -+ /* init layouts */ -+ m->pertag->ltidxs[i][0] = &layouts[def_layouts[i % LENGTH(def_layouts)] % LENGTH(layouts)]; -+ m->pertag->ltidxs[i][1] = m->lt[1]; -+ m->pertag->sellts[i] = m->sellt; -+ -+ /* init showbar */ -+ m->pertag->showbars[i] = m->showbar; -+ -+ /* swap focus and zoomswap*/ -+ m->pertag->prevzooms[i] = NULL; -+ } - return m; - } - -@@ -749,6 +828,104 @@ drawbars(void) { - } - - void -+drawtabs(void) { -+ Monitor *m; -+ -+ for(m = mons; m; m = m->next) -+ drawtab(m); -+} -+ -+static int -+cmpint(const void *p1, const void *p2) { -+ /* The actual arguments to this function are "pointers to -+ pointers to char", but strcmp(3) arguments are "pointers -+ to char", hence the following cast plus dereference */ -+ return *((int*) p1) > * (int*) p2; -+} -+ -+ -+void -+drawtab(Monitor *m) { -+ Client *c; -+ int i; -+ int itag = -1; -+ char view_info[50]; -+ int view_info_w = 0; -+ int sorted_label_widths[MAXTABS]; -+ int tot_width; -+ int maxsize = bh; -+ int x = 0; -+ int w = 0; -+ -+ //view_info: indicate the tag which is displayed in the view -+ for(i = 0; i < LENGTH(tags); ++i){ -+ if((selmon->tagset[selmon->seltags] >> i) & 1) { -+ if(itag >=0){ //more than one tag selected -+ itag = -1; -+ break; -+ } -+ itag = i; -+ } -+ } -+ if(0 <= itag && itag < LENGTH(tags)){ -+ snprintf(view_info, sizeof view_info, "[%s]", tags[itag]); -+ } else { -+ strncpy(view_info, "[...]", sizeof view_info); -+ } -+ view_info[sizeof(view_info) - 1 ] = 0; -+ view_info_w = TEXTW(view_info); -+ tot_width = view_info_w; -+ -+ /* Calculates number of labels and their width */ -+ m->ntabs = 0; -+ for(c = m->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ m->tab_widths[m->ntabs] = TEXTW(c->name); -+ tot_width += m->tab_widths[m->ntabs]; -+ ++m->ntabs; -+ if(m->ntabs >= MAXTABS) break; -+ } -+ -+ if(tot_width > m->ww){ //not enough space to display the labels, they need to be truncated -+ memcpy(sorted_label_widths, m->tab_widths, sizeof(int) * m->ntabs); -+ qsort(sorted_label_widths, m->ntabs, sizeof(int), cmpint); -+ tot_width = view_info_w; -+ for(i = 0; i < m->ntabs; ++i){ -+ if(tot_width + (m->ntabs - i) * sorted_label_widths[i] > m->ww) -+ break; -+ tot_width += sorted_label_widths[i]; -+ } -+ maxsize = (m->ww - tot_width) / (m->ntabs - i); -+ } else{ -+ maxsize = m->ww; -+ } -+ i = 0; -+ for(c = m->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ if(i >= m->ntabs) break; -+ if(m->tab_widths[i] > maxsize) m->tab_widths[i] = maxsize; -+ w = m->tab_widths[i]; -+ drw_setscheme(drw, (c == m->sel) ? &scheme[SchemeSel] : &scheme[SchemeNorm]); -+ drw_text(drw, x, 0, w, th, c->name, 0); -+ x += w; -+ ++i; -+ } -+ -+ drw_setscheme(drw, &scheme[SchemeNorm]); -+ -+ /* cleans interspace between window names and current viewed tag label */ -+ w = m->ww - view_info_w - x; -+ drw_text(drw, x, 0, w, th, NULL, 0); -+ -+ /* view info */ -+ x += w; -+ w = view_info_w; -+ drw_text(drw, x, 0, w, th, view_info, 0); -+ -+ drw_map(drw, m->tabwin, 0, 0, m->ww, th); -+} -+ -+void - enternotify(XEvent *e) { - Client *c; - Monitor *m; -@@ -772,8 +949,10 @@ expose(XEvent *e) { - Monitor *m; - XExposeEvent *ev = &e->xexpose; - -- if(ev->count == 0 && (m = wintomon(ev->window))) -+ if(ev->count == 0 && (m = wintomon(ev->window))){ - drawbar(m); -+ drawtab(m); -+ } - } - - void -@@ -800,6 +979,7 @@ focus(Client *c) { - } - selmon->sel = c; - drawbars(); -+ drawtabs(); - } - - void -@@ -850,6 +1030,19 @@ focusstack(const Arg *arg) { - } - } - -+void -+focuswin(const Arg* arg){ -+ int iwin = arg->i; -+ Client* c = NULL; -+ for(c = selmon->clients; c && (iwin || !ISVISIBLE(c)) ; c = c->next){ -+ if(ISVISIBLE(c)) --iwin; -+ }; -+ if(c) { -+ focus(c); -+ restack(selmon); -+ } -+} -+ - Atom - getatomprop(Client *c, Atom prop) { - int di; -@@ -957,7 +1150,7 @@ grabkeys(void) { - - void - incnmaster(const Arg *arg) { -- selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); -+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0); - arrange(selmon); - } - -@@ -1216,12 +1409,14 @@ propertynotify(XEvent *e) { - case XA_WM_HINTS: - updatewmhints(c); - drawbars(); -+ drawtabs(); - break; - } - if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { - updatetitle(c); - if(c == c->mon->sel) - drawbar(c->mon); -+ drawtab(c->mon); - } - if(ev->atom == netatom[NetWMWindowType]) - updatewindowtype(c); -@@ -1329,6 +1524,7 @@ restack(Monitor *m) { - XWindowChanges wc; - - drawbar(m); -+ drawtab(m); - if(!m->sel) - return; - if(m->sel->isfloating || !m->lt[m->sellt]->arrange) -@@ -1470,10 +1666,13 @@ setfullscreen(Client *c, Bool fullscreen) { - - void - setlayout(const Arg *arg) { -- if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) -- selmon->sellt ^= 1; -+ if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) { -+ selmon->pertag->sellts[selmon->pertag->curtag] ^= 1; -+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; -+ } - if(arg && arg->v) -- selmon->lt[selmon->sellt] = (Layout *)arg->v; -+ selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v; -+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; - strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); - if(selmon->sel) - arrange(selmon); -@@ -1491,7 +1690,7 @@ setmfact(const Arg *arg) { - f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; - if(f < 0.1 || f > 0.9) - return; -- selmon->mfact = f; -+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; - arrange(selmon); - } - -@@ -1512,6 +1711,8 @@ setup(void) { - if (!drw->fontcount) - die("No fonts could be loaded.\n"); - bh = drw->fonts[0]->h + 2; -+ th = bh; -+ - updategeom(); - /* init atoms */ - wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); -@@ -1636,13 +1837,23 @@ tile(Monitor *m) { - - void - togglebar(const Arg *arg) { -- selmon->showbar = !selmon->showbar; -+ selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar; - updatebarpos(selmon); - XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); - arrange(selmon); - } - - void -+tabmode(const Arg *arg) { -+ if(arg && arg->i >= 0) -+ selmon->showtab = arg->ui % showtab_nmodes; -+ else -+ selmon->showtab = (selmon->showtab + 1 ) % showtab_nmodes; -+ arrange(selmon); -+} -+ -+ -+void - togglefloating(const Arg *arg) { - if(!selmon->sel) - return; -@@ -1672,9 +1883,29 @@ toggletag(const Arg *arg) { - void - toggleview(const Arg *arg) { - unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); -+ int i; - - if(newtagset) { -+ if(newtagset == ~0) { -+ selmon->pertag->prevtag = selmon->pertag->curtag; -+ selmon->pertag->curtag = 0; -+ } -+ /* test if the user did not select the same tag */ -+ if(!(newtagset & 1 << (selmon->pertag->curtag - 1))) { -+ selmon->pertag->prevtag = selmon->pertag->curtag; -+ for (i=0; !(newtagset & 1 << i); i++) ; -+ selmon->pertag->curtag = i + 1; -+ } - selmon->tagset[selmon->seltags] = newtagset; -+ -+ /* apply settings for this view */ -+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; -+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; -+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; -+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; -+ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; -+ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) -+ togglebar(NULL); - focus(NULL); - arrange(selmon); - } -@@ -1746,20 +1977,43 @@ updatebars(void) { - CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); - XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); - XMapRaised(dpy, m->barwin); -+ m->tabwin = XCreateWindow(dpy, root, m->wx, m->ty, m->ww, th, 0, DefaultDepth(dpy, screen), -+ CopyFromParent, DefaultVisual(dpy, screen), -+ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); -+ XDefineCursor(dpy, m->tabwin, cursor[CurNormal]->cursor); -+ XMapRaised(dpy, m->tabwin); - } - } - - void - updatebarpos(Monitor *m) { -+ Client *c; -+ int nvis = 0; -+ - m->wy = m->my; - m->wh = m->mh; - if(m->showbar) { - m->wh -= bh; - m->by = m->topbar ? m->wy : m->wy + m->wh; -- m->wy = m->topbar ? m->wy + bh : m->wy; -- } -- else -+ if ( m->topbar ) -+ m->wy += bh; -+ } else { - m->by = -bh; -+ } -+ -+ for(c = m->clients; c; c = c->next){ -+ if(ISVISIBLE(c)) ++nvis; -+ } -+ -+ if(m->showtab == showtab_always -+ || ((m->showtab == showtab_auto) && (nvis > 1) && (m->lt[m->sellt]->arrange == monocle))){ -+ m->wh -= th; -+ m->ty = m->toptab ? m->wy : m->wy + m->wh; -+ if ( m->toptab ) -+ m->wy += th; -+ } else { -+ m->ty = -th; -+ } - } - - void -@@ -1969,11 +2223,33 @@ updatewmhints(Client *c) { - - void - view(const Arg *arg) { -+ int i; -+ unsigned int tmptag; -+ - if((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) - return; - selmon->seltags ^= 1; /* toggle sel tagset */ -- if(arg->ui & TAGMASK) -+ if(arg->ui & TAGMASK) { -+ selmon->pertag->prevtag = selmon->pertag->curtag; - selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; -+ if(arg->ui == ~0) -+ selmon->pertag->curtag = 0; -+ else { -+ for (i=0; !(arg->ui & 1 << i); i++) ; -+ selmon->pertag->curtag = i + 1; -+ } -+ } else { -+ tmptag = selmon->pertag->prevtag; -+ selmon->pertag->prevtag = selmon->pertag->curtag; -+ selmon->pertag->curtag = tmptag; -+ } -+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; -+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; -+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; -+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; -+ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; -+ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) -+ togglebar(NULL); - focus(NULL); - arrange(selmon); - } -@@ -1999,7 +2275,7 @@ wintomon(Window w) { - if(w == root && getrootptr(&x, &y)) - return recttomon(x, y, 1, 1); - for(m = mons; m; m = m->next) -- if(w == m->barwin) -+ if(w == m->barwin || w == m->tabwin) - return m; - if((c = wintoclient(w))) - return c->mon; diff --git a/dwm.suckless.org/patches/historical/dwm-master_2015-03-05_14343e-tab-v2b.diff b/dwm.suckless.org/patches/historical/dwm-master_2015-03-05_14343e-tab-v2b.diff @@ -1,506 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index eaae8f3..9161486 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -17,6 +17,13 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ - static const unsigned int snap = 32; /* snap pixel */ - static const Bool showbar = True; /* False means no bar */ - static const Bool topbar = True; /* False means bottom bar */ -+/* Display modes of the tab bar: never shown, always shown, shown only in */ -+/* monocle mode in presence of several windows. */ -+/* Modes after showtab_nmodes are disabled */ -+enum showtab_modes { showtab_never, showtab_auto, showtab_nmodes, showtab_always}; -+static const int showtab = showtab_auto; /* Default tab bar show mode */ -+static const Bool toptab = False; /* False means bottom tab bar */ -+ - - /* tagging */ - static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; -@@ -34,7 +41,7 @@ static const Rule rules[] = { - /* 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 Bool resizehints = True; /* True means respect size hints in tiled resizals */ -+static const Bool resizehints = False; /* True means respect size hints in tiled resizals */ - - static const Layout layouts[] = { - /* symbol arrange function */ -@@ -64,6 +71,7 @@ static Key keys[] = { - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, - { MODKEY, XK_b, togglebar, {0} }, -+ { MODKEY, XK_w, tabmode, {-1} }, - { MODKEY, XK_j, focusstack, {.i = +1 } }, - { MODKEY, XK_k, focusstack, {.i = -1 } }, - { MODKEY, XK_i, incnmaster, {.i = +1 } }, -@@ -111,5 +119,6 @@ static Button buttons[] = { - { ClkTagBar, 0, Button3, toggleview, {0} }, - { ClkTagBar, MODKEY, Button1, tag, {0} }, - { ClkTagBar, MODKEY, Button3, toggletag, {0} }, -+ { ClkTabBar, 0, Button1, focuswin, {0} }, - }; - -diff --git a/dwm.1 b/dwm.1 -index 6687011..9f5c274 100644 ---- a/dwm.1 -+++ b/dwm.1 -@@ -19,14 +19,22 @@ layout applied. - 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. -+Each screen contains two small status bars. -+.P -+One bar 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 -+Another bar contains a tab for each window of the current view and allows -+navigation between windows, especially in the monocle mode. The different -+display modes of this bar are described under the Mod1\-w Keybord command -+section. When a single tag is selected, that tag is indicated in the left corner -+of the tab bar. - .P - dwm draws a small border around windows to indicate the focus state. - .SH OPTIONS -@@ -43,7 +51,8 @@ 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. -+label toggles between tiled and floating layout, click on a window name in the -+tab bar brings focus to that window. - .TP - .B Button3 - click on a tag label adds/removes all windows with that tag to/from the view. -@@ -104,6 +113,12 @@ Increase master area size. - .B Mod1\-h - Decrease master area size. - .TP -+.B Mod1\-w -+Cycle over the tab bar display modes: never displayed, always displayed, -+displayed only in monocle mode when the view contains than one window (auto -+mode). Some display modes can be disabled in the configuration, config.h. In -+the default configuration only "never" and "auto" display modes are enabled. -+.TP - .B Mod1\-Return - Zooms/cycles focused window to/from master area (tiled layouts only). - .TP -diff --git a/dwm.c b/dwm.c -index 169adcb..4ec61fb 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -64,7 +64,7 @@ enum { NetSupported, NetWMName, NetWMState, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ - enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ --enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, -+enum { ClkTagBar, ClkTabBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, - ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ - - typedef union { -@@ -111,24 +111,32 @@ typedef struct { - void (*arrange)(Monitor *); - } Layout; - -+#define MAXTABS 50 -+ - struct Monitor { - char ltsymbol[16]; - float mfact; - int nmaster; - int num; - int by; /* bar geometry */ -+ int ty; /* tab bar geometry */ - int mx, my, mw, mh; /* screen size */ - int wx, wy, ww, wh; /* window area */ - unsigned int seltags; - unsigned int sellt; - unsigned int tagset[2]; - Bool showbar; -+ Bool showtab; - Bool topbar; -+ Bool toptab; - Client *clients; - Client *sel; - Client *stack; - Monitor *next; - Window barwin; -+ Window tabwin; -+ int ntabs; -+ int tab_widths[MAXTABS]; - const Layout *lt[2]; - }; - -@@ -164,12 +172,15 @@ static void detachstack(Client *c); - static Monitor *dirtomon(int dir); - static void drawbar(Monitor *m); - static void drawbars(void); -+static void drawtab(Monitor *m); -+static void drawtabs(void); - 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 void focuswin(const Arg* arg); - static Bool getrootptr(int *x, int *y); - static long getstate(Window w); - static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); -@@ -206,6 +217,7 @@ static void setup(void); - static void showhide(Client *c); - static void sigchld(int unused); - static void spawn(const Arg *arg); -+static void tabmode(const Arg *arg); - static void tag(const Arg *arg); - static void tagmon(const Arg *arg); - static void tile(Monitor *); -@@ -240,6 +252,7 @@ static char stext[256]; - static int screen; - static int sw, sh; /* X display screen geometry width, height */ - static int bh, blw = 0; /* bar geometry */ -+static int th = 0; /* tab bar geometry */ - static int (*xerrorxlib)(Display *, XErrorEvent *); - static unsigned int numlockmask = 0; - static void (*handler[LASTEvent]) (XEvent *) = { -@@ -389,6 +402,9 @@ arrange(Monitor *m) { - - void - arrangemon(Monitor *m) { -+ updatebarpos(m); -+ XMoveResizeWindow(dpy, m->tabwin, m->wx, m->ty, m->ww, th); -+ - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); - if(m->lt[m->sellt]->arrange) - m->lt[m->sellt]->arrange(m); -@@ -437,14 +453,32 @@ buttonpress(XEvent *e) { - else - click = ClkWinTitle; - } -+ if(ev->window == selmon->tabwin) { -+ i = 0; x = 0; -+ for(c = selmon->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ x += selmon->tab_widths[i]; -+ if (ev->x > x) -+ ++i; -+ else -+ break; -+ if(i >= m->ntabs) break; -+ } -+ if(c) { -+ click = ClkTabBar; -+ arg.ui = i; -+ } -+ } - else if((c = wintoclient(ev->window))) { - focus(c); - 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); -+ && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)){ -+ buttons[i].func(((click == ClkTagBar || click == ClkTabBar) -+ && buttons[i].arg.i == 0) ? &arg : &buttons[i].arg); -+ } - } - - void -@@ -498,6 +532,8 @@ cleanupmon(Monitor *mon) { - } - XUnmapWindow(dpy, mon->barwin); - XDestroyWindow(dpy, mon->barwin); -+ XUnmapWindow(dpy, mon->tabwin); -+ XDestroyWindow(dpy, mon->tabwin); - free(mon); - } - -@@ -566,8 +602,11 @@ configurenotify(XEvent *e) { - if(updategeom() || dirty) { - drw_resize(drw, sw, bh); - updatebars(); -- for(m = mons; m; m = m->next) -+ //refreshing display of status bar. The tab bar is handled by the arrange() -+ //method, which is called below -+ for(m = mons; m; m = m->next){ - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); -+ } - focus(NULL); - arrange(NULL); - } -@@ -637,7 +676,10 @@ createmon(void) { - m->mfact = mfact; - m->nmaster = nmaster; - m->showbar = showbar; -+ m->showtab = showtab; - m->topbar = topbar; -+ m->toptab = toptab; -+ m->ntabs = 0; - m->lt[0] = &layouts[0]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); -@@ -749,6 +791,104 @@ drawbars(void) { - } - - void -+drawtabs(void) { -+ Monitor *m; -+ -+ for(m = mons; m; m = m->next) -+ drawtab(m); -+} -+ -+static int -+cmpint(const void *p1, const void *p2) { -+ /* The actual arguments to this function are "pointers to -+ pointers to char", but strcmp(3) arguments are "pointers -+ to char", hence the following cast plus dereference */ -+ return *((int*) p1) > * (int*) p2; -+} -+ -+ -+void -+drawtab(Monitor *m) { -+ Client *c; -+ int i; -+ int itag = -1; -+ char view_info[50]; -+ int view_info_w = 0; -+ int sorted_label_widths[MAXTABS]; -+ int tot_width; -+ int maxsize = bh; -+ int x = 0; -+ int w = 0; -+ -+ //view_info: indicate the tag which is displayed in the view -+ for(i = 0; i < LENGTH(tags); ++i){ -+ if((selmon->tagset[selmon->seltags] >> i) & 1) { -+ if(itag >=0){ //more than one tag selected -+ itag = -1; -+ break; -+ } -+ itag = i; -+ } -+ } -+ if(0 <= itag && itag < LENGTH(tags)){ -+ snprintf(view_info, sizeof view_info, "[%s]", tags[itag]); -+ } else { -+ strncpy(view_info, "[...]", sizeof view_info); -+ } -+ view_info[sizeof(view_info) - 1 ] = 0; -+ view_info_w = TEXTW(view_info); -+ tot_width = view_info_w; -+ -+ /* Calculates number of labels and their width */ -+ m->ntabs = 0; -+ for(c = m->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ m->tab_widths[m->ntabs] = TEXTW(c->name); -+ tot_width += m->tab_widths[m->ntabs]; -+ ++m->ntabs; -+ if(m->ntabs >= MAXTABS) break; -+ } -+ -+ if(tot_width > m->ww){ //not enough space to display the labels, they need to be truncated -+ memcpy(sorted_label_widths, m->tab_widths, sizeof(int) * m->ntabs); -+ qsort(sorted_label_widths, m->ntabs, sizeof(int), cmpint); -+ tot_width = view_info_w; -+ for(i = 0; i < m->ntabs; ++i){ -+ if(tot_width + (m->ntabs - i) * sorted_label_widths[i] > m->ww) -+ break; -+ tot_width += sorted_label_widths[i]; -+ } -+ maxsize = (m->ww - tot_width) / (m->ntabs - i); -+ } else{ -+ maxsize = m->ww; -+ } -+ i = 0; -+ for(c = m->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ if(i >= m->ntabs) break; -+ if(m->tab_widths[i] > maxsize) m->tab_widths[i] = maxsize; -+ w = m->tab_widths[i]; -+ drw_setscheme(drw, (c == m->sel) ? &scheme[SchemeSel] : &scheme[SchemeNorm]); -+ drw_text(drw, x, 0, w, th, c->name, 0); -+ x += w; -+ ++i; -+ } -+ -+ drw_setscheme(drw, &scheme[SchemeNorm]); -+ -+ /* cleans interspace between window names and current viewed tag label */ -+ w = m->ww - view_info_w - x; -+ drw_text(drw, x, 0, w, th, NULL, 0); -+ -+ /* view info */ -+ x += w; -+ w = view_info_w; -+ drw_text(drw, x, 0, w, th, view_info, 0); -+ -+ drw_map(drw, m->tabwin, 0, 0, m->ww, th); -+} -+ -+void - enternotify(XEvent *e) { - Client *c; - Monitor *m; -@@ -772,8 +912,10 @@ expose(XEvent *e) { - Monitor *m; - XExposeEvent *ev = &e->xexpose; - -- if(ev->count == 0 && (m = wintomon(ev->window))) -+ if(ev->count == 0 && (m = wintomon(ev->window))){ - drawbar(m); -+ drawtab(m); -+ } - } - - void -@@ -800,6 +942,7 @@ focus(Client *c) { - } - selmon->sel = c; - drawbars(); -+ drawtabs(); - } - - void -@@ -850,6 +993,19 @@ focusstack(const Arg *arg) { - } - } - -+void -+focuswin(const Arg* arg){ -+ int iwin = arg->i; -+ Client* c = NULL; -+ for(c = selmon->clients; c && (iwin || !ISVISIBLE(c)) ; c = c->next){ -+ if(ISVISIBLE(c)) --iwin; -+ }; -+ if(c) { -+ focus(c); -+ restack(selmon); -+ } -+} -+ - Atom - getatomprop(Client *c, Atom prop) { - int di; -@@ -1216,12 +1372,14 @@ propertynotify(XEvent *e) { - case XA_WM_HINTS: - updatewmhints(c); - drawbars(); -+ drawtabs(); - break; - } - if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { - updatetitle(c); - if(c == c->mon->sel) - drawbar(c->mon); -+ drawtab(c->mon); - } - if(ev->atom == netatom[NetWMWindowType]) - updatewindowtype(c); -@@ -1329,6 +1487,7 @@ restack(Monitor *m) { - XWindowChanges wc; - - drawbar(m); -+ drawtab(m); - if(!m->sel) - return; - if(m->sel->isfloating || !m->lt[m->sellt]->arrange) -@@ -1512,6 +1671,8 @@ setup(void) { - if (!drw->fontcount) - die("No fonts could be loaded.\n"); - bh = drw->fonts[0]->h + 2; -+ th = bh; -+ - updategeom(); - /* init atoms */ - wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); -@@ -1643,6 +1804,16 @@ togglebar(const Arg *arg) { - } - - void -+tabmode(const Arg *arg) { -+ if(arg && arg->i >= 0) -+ selmon->showtab = arg->ui % showtab_nmodes; -+ else -+ selmon->showtab = (selmon->showtab + 1 ) % showtab_nmodes; -+ arrange(selmon); -+} -+ -+ -+void - togglefloating(const Arg *arg) { - if(!selmon->sel) - return; -@@ -1746,20 +1917,43 @@ updatebars(void) { - CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); - XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); - XMapRaised(dpy, m->barwin); -+ m->tabwin = XCreateWindow(dpy, root, m->wx, m->ty, m->ww, th, 0, DefaultDepth(dpy, screen), -+ CopyFromParent, DefaultVisual(dpy, screen), -+ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); -+ XDefineCursor(dpy, m->tabwin, cursor[CurNormal]->cursor); -+ XMapRaised(dpy, m->tabwin); - } - } - - void - updatebarpos(Monitor *m) { -+ Client *c; -+ int nvis = 0; -+ - m->wy = m->my; - m->wh = m->mh; - if(m->showbar) { - m->wh -= bh; - m->by = m->topbar ? m->wy : m->wy + m->wh; -- m->wy = m->topbar ? m->wy + bh : m->wy; -- } -- else -+ if ( m->topbar ) -+ m->wy += bh; -+ } else { - m->by = -bh; -+ } -+ -+ for(c = m->clients; c; c = c->next){ -+ if(ISVISIBLE(c)) ++nvis; -+ } -+ -+ if(m->showtab == showtab_always -+ || ((m->showtab == showtab_auto) && (nvis > 1) && (m->lt[m->sellt]->arrange == monocle))){ -+ m->wh -= th; -+ m->ty = m->toptab ? m->wy : m->wy + m->wh; -+ if ( m->toptab ) -+ m->wy += th; -+ } else { -+ m->ty = -th; -+ } - } - - void -@@ -1999,7 +2193,7 @@ wintomon(Window w) { - if(w == root && getrootptr(&x, &y)) - return recttomon(x, y, 1, 1); - for(m = mons; m; m = m->next) -- if(w == m->barwin) -+ if(w == m->barwin || w == m->tabwin) - return m; - if((c = wintoclient(w))) - return c->mon; diff --git a/dwm.suckless.org/patches/historical/dwm-master_2015-10-20_7e1182c-pertag-tab-v2b.diff b/dwm.suckless.org/patches/historical/dwm-master_2015-10-20_7e1182c-pertag-tab-v2b.diff @@ -1,692 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 3fde3cf..ef6d4d3 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -15,10 +15,22 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ - static const unsigned int snap = 32; /* snap pixel */ - static const Bool showbar = True; /* False means no bar */ - static const Bool topbar = True; /* False means bottom bar */ -+/* Display modes of the tab bar: never shown, always shown, shown only in */ -+/* monocle mode in presence of several windows. */ -+/* Modes after showtab_nmodes are disabled */ -+enum showtab_modes { showtab_never, showtab_auto, showtab_nmodes, showtab_always}; -+static const int showtab = showtab_auto; /* Default tab bar show mode */ -+static const Bool toptab = False; /* False means bottom tab bar */ -+ - - /* tagging */ - static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; - -+/* default layout per tags */ -+/* The first element is for all-tag view, following i-th element corresponds to */ -+/* tags[i]. Layout is referred using the layouts array index.*/ -+static int def_layouts[1 + LENGTH(tags)] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -+ - static const Rule rules[] = { - /* xprop(1): - * WM_CLASS(STRING) = instance, class -@@ -32,7 +44,7 @@ static const Rule rules[] = { - /* 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 Bool resizehints = True; /* True means respect size hints in tiled resizals */ -+static const Bool resizehints = False; /* True means respect size hints in tiled resizals */ - - static const Layout layouts[] = { - /* symbol arrange function */ -@@ -62,6 +74,7 @@ static Key keys[] = { - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, - { MODKEY, XK_b, togglebar, {0} }, -+ { MODKEY, XK_w, tabmode, {-1} }, - { MODKEY, XK_j, focusstack, {.i = +1 } }, - { MODKEY, XK_k, focusstack, {.i = -1 } }, - { MODKEY, XK_i, incnmaster, {.i = +1 } }, -@@ -109,5 +122,6 @@ static Button buttons[] = { - { ClkTagBar, 0, Button3, toggleview, {0} }, - { ClkTagBar, MODKEY, Button1, tag, {0} }, - { ClkTagBar, MODKEY, Button3, toggletag, {0} }, -+ { ClkTabBar, 0, Button1, focuswin, {0} }, - }; - -diff --git a/dwm.1 b/dwm.1 -index 6687011..077d92b 100644 ---- a/dwm.1 -+++ b/dwm.1 -@@ -19,14 +19,22 @@ layout applied. - 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. -+Each screen contains two small status bars. -+.P -+One bar 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 -+Another bar contains a tab for each window of the current view and allows -+navigation between windows, especially in the monocle mode. The different -+display modes of this bar are described under the Mod1\-w Keybord command -+section. When a single tag is selected, that tag is indicated in the left corner -+of the tab bar. - .P - dwm draws a small border around windows to indicate the focus state. - .SH OPTIONS -@@ -43,7 +51,8 @@ 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. -+label toggles between tiled and floating layout, click on a window name in the -+tab bar brings focus to that window. - .TP - .B Button3 - click on a tag label adds/removes all windows with that tag to/from the view. -@@ -104,6 +113,12 @@ Increase master area size. - .B Mod1\-h - Decrease master area size. - .TP -+.B Mod1\-w -+Cycle over the tab bar display modes: never displayed, always displayed, -+displayed only in monocle mode when the view contains than one window (auto -+mode). Some display modes can be disabled in the configuration, config.h. In -+the default configuration only "never" and "auto" display modes are enabled. -+.TP - .B Mod1\-Return - Zooms/cycles focused window to/from master area (tiled layouts only). - .TP -diff --git a/dwm.c b/dwm.c -index 96b43f7..c0aab5d 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -64,7 +64,7 @@ enum { NetSupported, NetWMName, NetWMState, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ - enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ --enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, -+enum { ClkTagBar, ClkTabBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, - ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ - - typedef union { -@@ -111,25 +111,35 @@ typedef struct { - void (*arrange)(Monitor *); - } Layout; - -+#define MAXTABS 50 -+ -+typedef struct Pertag Pertag; - struct Monitor { - char ltsymbol[16]; - float mfact; - int nmaster; - int num; - int by; /* bar geometry */ -+ int ty; /* tab bar geometry */ - int mx, my, mw, mh; /* screen size */ - int wx, wy, ww, wh; /* window area */ - unsigned int seltags; - unsigned int sellt; - unsigned int tagset[2]; - Bool showbar; -+ Bool showtab; - Bool topbar; -+ Bool toptab; - Client *clients; - Client *sel; - Client *stack; - Monitor *next; - Window barwin; -+ Window tabwin; -+ int ntabs; -+ int tab_widths[MAXTABS]; - const Layout *lt[2]; -+ Pertag *pertag; - }; - - typedef struct { -@@ -164,12 +174,15 @@ static void detachstack(Client *c); - static Monitor *dirtomon(int dir); - static void drawbar(Monitor *m); - static void drawbars(void); -+static void drawtab(Monitor *m); -+static void drawtabs(void); - 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 void focuswin(const Arg* arg); - static Bool getrootptr(int *x, int *y); - static long getstate(Window w); - static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); -@@ -206,6 +219,7 @@ static void setup(void); - static void showhide(Client *c); - static void sigchld(int unused); - static void spawn(const Arg *arg); -+static void tabmode(const Arg *arg); - static void tag(const Arg *arg); - static void tagmon(const Arg *arg); - static void tile(Monitor *); -@@ -240,6 +254,7 @@ static char stext[256]; - static int screen; - static int sw, sh; /* X display screen geometry width, height */ - static int bh, blw = 0; /* bar geometry */ -+static int th = 0; /* tab bar geometry */ - static int (*xerrorxlib)(Display *, XErrorEvent *); - static unsigned int numlockmask = 0; - static void (*handler[LASTEvent]) (XEvent *) = { -@@ -270,6 +285,16 @@ static Window root; - /* configuration, allows nested code to access above variables */ - #include "config.h" - -+struct Pertag { -+ unsigned int curtag, prevtag; /* current and previous tag */ -+ int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */ -+ float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */ -+ unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */ -+ const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes */ -+ Bool showbars[LENGTH(tags) + 1]; /* display bar for the current tag */ -+ Client *prevzooms[LENGTH(tags) + 1]; /* store zoom information */ -+}; -+ - /* compile-time check if all tags fit into an unsigned int bit array. */ - struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; - -@@ -389,6 +414,9 @@ arrange(Monitor *m) { - - void - arrangemon(Monitor *m) { -+ updatebarpos(m); -+ XMoveResizeWindow(dpy, m->tabwin, m->wx, m->ty, m->ww, th); -+ - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); - if(m->lt[m->sellt]->arrange) - m->lt[m->sellt]->arrange(m); -@@ -437,14 +465,32 @@ buttonpress(XEvent *e) { - else - click = ClkWinTitle; - } -+ if(ev->window == selmon->tabwin) { -+ i = 0; x = 0; -+ for(c = selmon->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ x += selmon->tab_widths[i]; -+ if (ev->x > x) -+ ++i; -+ else -+ break; -+ if(i >= m->ntabs) break; -+ } -+ if(c) { -+ click = ClkTabBar; -+ arg.ui = i; -+ } -+ } - else if((c = wintoclient(ev->window))) { - focus(c); - 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); -+ && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)){ -+ buttons[i].func(((click == ClkTagBar || click == ClkTabBar) -+ && buttons[i].arg.i == 0) ? &arg : &buttons[i].arg); -+ } - } - - void -@@ -497,6 +543,8 @@ cleanupmon(Monitor *mon) { - } - XUnmapWindow(dpy, mon->barwin); - XDestroyWindow(dpy, mon->barwin); -+ XUnmapWindow(dpy, mon->tabwin); -+ XDestroyWindow(dpy, mon->tabwin); - free(mon); - } - -@@ -516,6 +564,7 @@ void - clientmessage(XEvent *e) { - XClientMessageEvent *cme = &e->xclient; - Client *c = wintoclient(cme->window); -+ int i; - - if(!c) - return; -@@ -528,6 +577,8 @@ clientmessage(XEvent *e) { - if(!ISVISIBLE(c)) { - c->mon->seltags ^= 1; - c->mon->tagset[c->mon->seltags] = c->tags; -+ for(i=0; !(c->tags & 1 << i); i++); -+ view(&(Arg){.ui = 1 << i}); - } - pop(c); - } -@@ -565,8 +616,11 @@ configurenotify(XEvent *e) { - if(updategeom() || dirty) { - drw_resize(drw, sw, bh); - updatebars(); -- for(m = mons; m; m = m->next) -+ //refreshing display of status bar. The tab bar is handled by the arrange() -+ //method, which is called below -+ for(m = mons; m; m = m->next){ - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); -+ } - focus(NULL); - arrange(NULL); - } -@@ -629,16 +683,41 @@ configurerequest(XEvent *e) { - Monitor * - createmon(void) { - Monitor *m; -+ int i; - - m = ecalloc(1, sizeof(Monitor)); - m->tagset[0] = m->tagset[1] = 1; - m->mfact = mfact; - m->nmaster = nmaster; - m->showbar = showbar; -+ m->showtab = showtab; - m->topbar = topbar; -- m->lt[0] = &layouts[0]; -+ m->toptab = toptab; -+ m->ntabs = 0; -+ m->lt[0] = &layouts[def_layouts[1] % LENGTH(layouts)]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); -+ if(!(m->pertag = (Pertag *)calloc(1, sizeof(Pertag)))) -+ die("fatal: could not malloc() %u bytes\n", sizeof(Pertag)); -+ m->pertag->curtag = m->pertag->prevtag = 1; -+ for(i=0; i <= LENGTH(tags); i++) { -+ /* init nmaster */ -+ m->pertag->nmasters[i] = m->nmaster; -+ -+ /* init mfacts */ -+ m->pertag->mfacts[i] = m->mfact; -+ -+ /* init layouts */ -+ m->pertag->ltidxs[i][0] = &layouts[def_layouts[i % LENGTH(def_layouts)] % LENGTH(layouts)]; -+ m->pertag->ltidxs[i][1] = m->lt[1]; -+ m->pertag->sellts[i] = m->sellt; -+ -+ /* init showbar */ -+ m->pertag->showbars[i] = m->showbar; -+ -+ /* swap focus and zoomswap*/ -+ m->pertag->prevzooms[i] = NULL; -+ } - return m; - } - -@@ -749,6 +828,104 @@ drawbars(void) { - } - - void -+drawtabs(void) { -+ Monitor *m; -+ -+ for(m = mons; m; m = m->next) -+ drawtab(m); -+} -+ -+static int -+cmpint(const void *p1, const void *p2) { -+ /* The actual arguments to this function are "pointers to -+ pointers to char", but strcmp(3) arguments are "pointers -+ to char", hence the following cast plus dereference */ -+ return *((int*) p1) > * (int*) p2; -+} -+ -+ -+void -+drawtab(Monitor *m) { -+ Client *c; -+ int i; -+ int itag = -1; -+ char view_info[50]; -+ int view_info_w = 0; -+ int sorted_label_widths[MAXTABS]; -+ int tot_width; -+ int maxsize = bh; -+ int x = 0; -+ int w = 0; -+ -+ //view_info: indicate the tag which is displayed in the view -+ for(i = 0; i < LENGTH(tags); ++i){ -+ if((selmon->tagset[selmon->seltags] >> i) & 1) { -+ if(itag >=0){ //more than one tag selected -+ itag = -1; -+ break; -+ } -+ itag = i; -+ } -+ } -+ if(0 <= itag && itag < LENGTH(tags)){ -+ snprintf(view_info, sizeof view_info, "[%s]", tags[itag]); -+ } else { -+ strncpy(view_info, "[...]", sizeof view_info); -+ } -+ view_info[sizeof(view_info) - 1 ] = 0; -+ view_info_w = TEXTW(view_info); -+ tot_width = view_info_w; -+ -+ /* Calculates number of labels and their width */ -+ m->ntabs = 0; -+ for(c = m->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ m->tab_widths[m->ntabs] = TEXTW(c->name); -+ tot_width += m->tab_widths[m->ntabs]; -+ ++m->ntabs; -+ if(m->ntabs >= MAXTABS) break; -+ } -+ -+ if(tot_width > m->ww){ //not enough space to display the labels, they need to be truncated -+ memcpy(sorted_label_widths, m->tab_widths, sizeof(int) * m->ntabs); -+ qsort(sorted_label_widths, m->ntabs, sizeof(int), cmpint); -+ tot_width = view_info_w; -+ for(i = 0; i < m->ntabs; ++i){ -+ if(tot_width + (m->ntabs - i) * sorted_label_widths[i] > m->ww) -+ break; -+ tot_width += sorted_label_widths[i]; -+ } -+ maxsize = (m->ww - tot_width) / (m->ntabs - i); -+ } else{ -+ maxsize = m->ww; -+ } -+ i = 0; -+ for(c = m->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ if(i >= m->ntabs) break; -+ if(m->tab_widths[i] > maxsize) m->tab_widths[i] = maxsize; -+ w = m->tab_widths[i]; -+ drw_setscheme(drw, (c == m->sel) ? &scheme[SchemeSel] : &scheme[SchemeNorm]); -+ drw_text(drw, x, 0, w, th, c->name, 0); -+ x += w; -+ ++i; -+ } -+ -+ drw_setscheme(drw, &scheme[SchemeNorm]); -+ -+ /* cleans interspace between window names and current viewed tag label */ -+ w = m->ww - view_info_w - x; -+ drw_text(drw, x, 0, w, th, NULL, 0); -+ -+ /* view info */ -+ x += w; -+ w = view_info_w; -+ drw_text(drw, x, 0, w, th, view_info, 0); -+ -+ drw_map(drw, m->tabwin, 0, 0, m->ww, th); -+} -+ -+void - enternotify(XEvent *e) { - Client *c; - Monitor *m; -@@ -772,8 +949,10 @@ expose(XEvent *e) { - Monitor *m; - XExposeEvent *ev = &e->xexpose; - -- if(ev->count == 0 && (m = wintomon(ev->window))) -+ if(ev->count == 0 && (m = wintomon(ev->window))){ - drawbar(m); -+ drawtab(m); -+ } - } - - void -@@ -800,6 +979,7 @@ focus(Client *c) { - } - selmon->sel = c; - drawbars(); -+ drawtabs(); - } - - void -@@ -850,6 +1030,19 @@ focusstack(const Arg *arg) { - } - } - -+void -+focuswin(const Arg* arg){ -+ int iwin = arg->i; -+ Client* c = NULL; -+ for(c = selmon->clients; c && (iwin || !ISVISIBLE(c)) ; c = c->next){ -+ if(ISVISIBLE(c)) --iwin; -+ }; -+ if(c) { -+ focus(c); -+ restack(selmon); -+ } -+} -+ - Atom - getatomprop(Client *c, Atom prop) { - int di; -@@ -957,7 +1150,7 @@ grabkeys(void) { - - void - incnmaster(const Arg *arg) { -- selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); -+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0); - arrange(selmon); - } - -@@ -1215,12 +1408,14 @@ propertynotify(XEvent *e) { - case XA_WM_HINTS: - updatewmhints(c); - drawbars(); -+ drawtabs(); - break; - } - if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { - updatetitle(c); - if(c == c->mon->sel) - drawbar(c->mon); -+ drawtab(c->mon); - } - if(ev->atom == netatom[NetWMWindowType]) - updatewindowtype(c); -@@ -1328,6 +1523,7 @@ restack(Monitor *m) { - XWindowChanges wc; - - drawbar(m); -+ drawtab(m); - if(!m->sel) - return; - if(m->sel->isfloating || !m->lt[m->sellt]->arrange) -@@ -1469,10 +1665,13 @@ setfullscreen(Client *c, Bool fullscreen) { - - void - setlayout(const Arg *arg) { -- if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) -- selmon->sellt ^= 1; -+ if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) { -+ selmon->pertag->sellts[selmon->pertag->curtag] ^= 1; -+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; -+ } - if(arg && arg->v) -- selmon->lt[selmon->sellt] = (Layout *)arg->v; -+ selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v; -+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; - strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); - if(selmon->sel) - arrange(selmon); -@@ -1490,7 +1689,7 @@ setmfact(const Arg *arg) { - f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; - if(f < 0.1 || f > 0.9) - return; -- selmon->mfact = f; -+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; - arrange(selmon); - } - -@@ -1511,6 +1710,8 @@ setup(void) { - if (!drw->fontcount) - die("no fonts could be loaded.\n"); - bh = drw->fonts[0]->h + 2; -+ th = bh; -+ - updategeom(); - /* init atoms */ - wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); -@@ -1635,13 +1836,23 @@ tile(Monitor *m) { - - void - togglebar(const Arg *arg) { -- selmon->showbar = !selmon->showbar; -+ selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar; - updatebarpos(selmon); - XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); - arrange(selmon); - } - - void -+tabmode(const Arg *arg) { -+ if(arg && arg->i >= 0) -+ selmon->showtab = arg->ui % showtab_nmodes; -+ else -+ selmon->showtab = (selmon->showtab + 1 ) % showtab_nmodes; -+ arrange(selmon); -+} -+ -+ -+void - togglefloating(const Arg *arg) { - if(!selmon->sel) - return; -@@ -1671,9 +1882,29 @@ toggletag(const Arg *arg) { - void - toggleview(const Arg *arg) { - unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); -+ int i; - - if(newtagset) { -+ if(newtagset == ~0) { -+ selmon->pertag->prevtag = selmon->pertag->curtag; -+ selmon->pertag->curtag = 0; -+ } -+ /* test if the user did not select the same tag */ -+ if(!(newtagset & 1 << (selmon->pertag->curtag - 1))) { -+ selmon->pertag->prevtag = selmon->pertag->curtag; -+ for (i=0; !(newtagset & 1 << i); i++) ; -+ selmon->pertag->curtag = i + 1; -+ } - selmon->tagset[selmon->seltags] = newtagset; -+ -+ /* apply settings for this view */ -+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; -+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; -+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; -+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; -+ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; -+ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) -+ togglebar(NULL); - focus(NULL); - arrange(selmon); - } -@@ -1745,20 +1976,43 @@ updatebars(void) { - CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); - XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); - XMapRaised(dpy, m->barwin); -+ m->tabwin = XCreateWindow(dpy, root, m->wx, m->ty, m->ww, th, 0, DefaultDepth(dpy, screen), -+ CopyFromParent, DefaultVisual(dpy, screen), -+ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); -+ XDefineCursor(dpy, m->tabwin, cursor[CurNormal]->cursor); -+ XMapRaised(dpy, m->tabwin); - } - } - - void - updatebarpos(Monitor *m) { -+ Client *c; -+ int nvis = 0; -+ - m->wy = m->my; - m->wh = m->mh; - if(m->showbar) { - m->wh -= bh; - m->by = m->topbar ? m->wy : m->wy + m->wh; -- m->wy = m->topbar ? m->wy + bh : m->wy; -- } -- else -+ if ( m->topbar ) -+ m->wy += bh; -+ } else { - m->by = -bh; -+ } -+ -+ for(c = m->clients; c; c = c->next){ -+ if(ISVISIBLE(c)) ++nvis; -+ } -+ -+ if(m->showtab == showtab_always -+ || ((m->showtab == showtab_auto) && (nvis > 1) && (m->lt[m->sellt]->arrange == monocle))){ -+ m->wh -= th; -+ m->ty = m->toptab ? m->wy : m->wy + m->wh; -+ if ( m->toptab ) -+ m->wy += th; -+ } else { -+ m->ty = -th; -+ } - } - - void -@@ -1967,11 +2221,33 @@ updatewmhints(Client *c) { - - void - view(const Arg *arg) { -+ int i; -+ unsigned int tmptag; -+ - if((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) - return; - selmon->seltags ^= 1; /* toggle sel tagset */ -- if(arg->ui & TAGMASK) -+ if(arg->ui & TAGMASK) { -+ selmon->pertag->prevtag = selmon->pertag->curtag; - selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; -+ if(arg->ui == ~0) -+ selmon->pertag->curtag = 0; -+ else { -+ for (i=0; !(arg->ui & 1 << i); i++) ; -+ selmon->pertag->curtag = i + 1; -+ } -+ } else { -+ tmptag = selmon->pertag->prevtag; -+ selmon->pertag->prevtag = selmon->pertag->curtag; -+ selmon->pertag->curtag = tmptag; -+ } -+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; -+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; -+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; -+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; -+ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; -+ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) -+ togglebar(NULL); - focus(NULL); - arrange(selmon); - } -@@ -1997,7 +2273,7 @@ wintomon(Window w) { - if(w == root && getrootptr(&x, &y)) - return recttomon(x, y, 1, 1); - for(m = mons; m; m = m->next) -- if(w == m->barwin) -+ if(w == m->barwin || w == m->tabwin) - return m; - if((c = wintoclient(w))) - return c->mon; diff --git a/dwm.suckless.org/patches/historical/dwm-master_2015-10-20_7e1182c-tab-v2b.diff b/dwm.suckless.org/patches/historical/dwm-master_2015-10-20_7e1182c-tab-v2b.diff @@ -1,506 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 3fde3cf..6a7ad0f 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -15,6 +15,13 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ - static const unsigned int snap = 32; /* snap pixel */ - static const Bool showbar = True; /* False means no bar */ - static const Bool topbar = True; /* False means bottom bar */ -+/* Display modes of the tab bar: never shown, always shown, shown only in */ -+/* monocle mode in presence of several windows. */ -+/* Modes after showtab_nmodes are disabled */ -+enum showtab_modes { showtab_never, showtab_auto, showtab_nmodes, showtab_always}; -+static const int showtab = showtab_auto; /* Default tab bar show mode */ -+static const Bool toptab = False; /* False means bottom tab bar */ -+ - - /* tagging */ - static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; -@@ -32,7 +39,7 @@ static const Rule rules[] = { - /* 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 Bool resizehints = True; /* True means respect size hints in tiled resizals */ -+static const Bool resizehints = False; /* True means respect size hints in tiled resizals */ - - static const Layout layouts[] = { - /* symbol arrange function */ -@@ -62,6 +69,7 @@ static Key keys[] = { - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, - { MODKEY, XK_b, togglebar, {0} }, -+ { MODKEY, XK_w, tabmode, {-1} }, - { MODKEY, XK_j, focusstack, {.i = +1 } }, - { MODKEY, XK_k, focusstack, {.i = -1 } }, - { MODKEY, XK_i, incnmaster, {.i = +1 } }, -@@ -109,5 +117,6 @@ static Button buttons[] = { - { ClkTagBar, 0, Button3, toggleview, {0} }, - { ClkTagBar, MODKEY, Button1, tag, {0} }, - { ClkTagBar, MODKEY, Button3, toggletag, {0} }, -+ { ClkTabBar, 0, Button1, focuswin, {0} }, - }; - -diff --git a/dwm.1 b/dwm.1 -index 6687011..f736591 100644 ---- a/dwm.1 -+++ b/dwm.1 -@@ -19,14 +19,22 @@ layout applied. - 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. -+Each screen contains two small status bars. -+.P -+One bar 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 -+Another bar contains a tab for each window of the current view and allows -+navigation between windows, especially in the monocle mode. The different -+display modes of this bar are described under the Mod1\-w Keybord command -+section. When a single tag is selected, that tag is indicated in the left -+corner of the tab bar. - .P - dwm draws a small border around windows to indicate the focus state. - .SH OPTIONS -@@ -43,7 +51,8 @@ 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. -+label toggles between tiled and floating layout, click on a window name in the -+tab bar brings focus to that window. - .TP - .B Button3 - click on a tag label adds/removes all windows with that tag to/from the view. -@@ -104,6 +113,12 @@ Increase master area size. - .B Mod1\-h - Decrease master area size. - .TP -+.B Mod1\-w -+Cycle over the tab bar display modes: never displayed, always displayed, -+displayed only in monocle mode when the view contains than one window (auto -+mode). Some display modes can be disabled in the configuration, config.h. In -+the default configuration only "never" and "auto" display modes are enabled. -+.TP - .B Mod1\-Return - Zooms/cycles focused window to/from master area (tiled layouts only). - .TP -diff --git a/dwm.c b/dwm.c -index 96b43f7..585dd7b 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -64,7 +64,7 @@ enum { NetSupported, NetWMName, NetWMState, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ - enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ --enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, -+enum { ClkTagBar, ClkTabBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, - ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ - - typedef union { -@@ -111,24 +111,32 @@ typedef struct { - void (*arrange)(Monitor *); - } Layout; - -+#define MAXTABS 50 -+ - struct Monitor { - char ltsymbol[16]; - float mfact; - int nmaster; - int num; - int by; /* bar geometry */ -+ int ty; /* tab bar geometry */ - int mx, my, mw, mh; /* screen size */ - int wx, wy, ww, wh; /* window area */ - unsigned int seltags; - unsigned int sellt; - unsigned int tagset[2]; - Bool showbar; -+ Bool showtab; - Bool topbar; -+ Bool toptab; - Client *clients; - Client *sel; - Client *stack; - Monitor *next; - Window barwin; -+ Window tabwin; -+ int ntabs; -+ int tab_widths[MAXTABS]; - const Layout *lt[2]; - }; - -@@ -164,12 +172,15 @@ static void detachstack(Client *c); - static Monitor *dirtomon(int dir); - static void drawbar(Monitor *m); - static void drawbars(void); -+static void drawtab(Monitor *m); -+static void drawtabs(void); - 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 void focuswin(const Arg* arg); - static Bool getrootptr(int *x, int *y); - static long getstate(Window w); - static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); -@@ -206,6 +217,7 @@ static void setup(void); - static void showhide(Client *c); - static void sigchld(int unused); - static void spawn(const Arg *arg); -+static void tabmode(const Arg *arg); - static void tag(const Arg *arg); - static void tagmon(const Arg *arg); - static void tile(Monitor *); -@@ -240,6 +252,7 @@ static char stext[256]; - static int screen; - static int sw, sh; /* X display screen geometry width, height */ - static int bh, blw = 0; /* bar geometry */ -+static int th = 0; /* tab bar geometry */ - static int (*xerrorxlib)(Display *, XErrorEvent *); - static unsigned int numlockmask = 0; - static void (*handler[LASTEvent]) (XEvent *) = { -@@ -389,6 +402,9 @@ arrange(Monitor *m) { - - void - arrangemon(Monitor *m) { -+ updatebarpos(m); -+ XMoveResizeWindow(dpy, m->tabwin, m->wx, m->ty, m->ww, th); -+ - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); - if(m->lt[m->sellt]->arrange) - m->lt[m->sellt]->arrange(m); -@@ -437,14 +453,32 @@ buttonpress(XEvent *e) { - else - click = ClkWinTitle; - } -+ if(ev->window == selmon->tabwin) { -+ i = 0; x = 0; -+ for(c = selmon->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ x += selmon->tab_widths[i]; -+ if (ev->x > x) -+ ++i; -+ else -+ break; -+ if(i >= m->ntabs) break; -+ } -+ if(c) { -+ click = ClkTabBar; -+ arg.ui = i; -+ } -+ } - else if((c = wintoclient(ev->window))) { - focus(c); - 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); -+ && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)){ -+ buttons[i].func(((click == ClkTagBar || click == ClkTabBar) -+ && buttons[i].arg.i == 0) ? &arg : &buttons[i].arg); -+ } - } - - void -@@ -497,6 +531,8 @@ cleanupmon(Monitor *mon) { - } - XUnmapWindow(dpy, mon->barwin); - XDestroyWindow(dpy, mon->barwin); -+ XUnmapWindow(dpy, mon->tabwin); -+ XDestroyWindow(dpy, mon->tabwin); - free(mon); - } - -@@ -565,8 +601,11 @@ configurenotify(XEvent *e) { - if(updategeom() || dirty) { - drw_resize(drw, sw, bh); - updatebars(); -- for(m = mons; m; m = m->next) -+ //refreshing display of status bar. The tab bar is handled by the arrange() -+ //method, which is called below -+ for(m = mons; m; m = m->next){ - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); -+ } - focus(NULL); - arrange(NULL); - } -@@ -635,7 +674,10 @@ createmon(void) { - m->mfact = mfact; - m->nmaster = nmaster; - m->showbar = showbar; -+ m->showtab = showtab; - m->topbar = topbar; -+ m->toptab = toptab; -+ m->ntabs = 0; - m->lt[0] = &layouts[0]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); -@@ -749,6 +791,104 @@ drawbars(void) { - } - - void -+drawtabs(void) { -+ Monitor *m; -+ -+ for(m = mons; m; m = m->next) -+ drawtab(m); -+} -+ -+static int -+cmpint(const void *p1, const void *p2) { -+ /* The actual arguments to this function are "pointers to -+ pointers to char", but strcmp(3) arguments are "pointers -+ to char", hence the following cast plus dereference */ -+ return *((int*) p1) > * (int*) p2; -+} -+ -+ -+void -+drawtab(Monitor *m) { -+ Client *c; -+ int i; -+ int itag = -1; -+ char view_info[50]; -+ int view_info_w = 0; -+ int sorted_label_widths[MAXTABS]; -+ int tot_width; -+ int maxsize = bh; -+ int x = 0; -+ int w = 0; -+ -+ //view_info: indicate the tag which is displayed in the view -+ for(i = 0; i < LENGTH(tags); ++i){ -+ if((selmon->tagset[selmon->seltags] >> i) & 1) { -+ if(itag >=0){ //more than one tag selected -+ itag = -1; -+ break; -+ } -+ itag = i; -+ } -+ } -+ if(0 <= itag && itag < LENGTH(tags)){ -+ snprintf(view_info, sizeof view_info, "[%s]", tags[itag]); -+ } else { -+ strncpy(view_info, "[...]", sizeof view_info); -+ } -+ view_info[sizeof(view_info) - 1 ] = 0; -+ view_info_w = TEXTW(view_info); -+ tot_width = view_info_w; -+ -+ /* Calculates number of labels and their width */ -+ m->ntabs = 0; -+ for(c = m->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ m->tab_widths[m->ntabs] = TEXTW(c->name); -+ tot_width += m->tab_widths[m->ntabs]; -+ ++m->ntabs; -+ if(m->ntabs >= MAXTABS) break; -+ } -+ -+ if(tot_width > m->ww){ //not enough space to display the labels, they need to be truncated -+ memcpy(sorted_label_widths, m->tab_widths, sizeof(int) * m->ntabs); -+ qsort(sorted_label_widths, m->ntabs, sizeof(int), cmpint); -+ tot_width = view_info_w; -+ for(i = 0; i < m->ntabs; ++i){ -+ if(tot_width + (m->ntabs - i) * sorted_label_widths[i] > m->ww) -+ break; -+ tot_width += sorted_label_widths[i]; -+ } -+ maxsize = (m->ww - tot_width) / (m->ntabs - i); -+ } else{ -+ maxsize = m->ww; -+ } -+ i = 0; -+ for(c = m->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ if(i >= m->ntabs) break; -+ if(m->tab_widths[i] > maxsize) m->tab_widths[i] = maxsize; -+ w = m->tab_widths[i]; -+ drw_setscheme(drw, (c == m->sel) ? &scheme[SchemeSel] : &scheme[SchemeNorm]); -+ drw_text(drw, x, 0, w, th, c->name, 0); -+ x += w; -+ ++i; -+ } -+ -+ drw_setscheme(drw, &scheme[SchemeNorm]); -+ -+ /* cleans interspace between window names and current viewed tag label */ -+ w = m->ww - view_info_w - x; -+ drw_text(drw, x, 0, w, th, NULL, 0); -+ -+ /* view info */ -+ x += w; -+ w = view_info_w; -+ drw_text(drw, x, 0, w, th, view_info, 0); -+ -+ drw_map(drw, m->tabwin, 0, 0, m->ww, th); -+} -+ -+void - enternotify(XEvent *e) { - Client *c; - Monitor *m; -@@ -772,8 +912,10 @@ expose(XEvent *e) { - Monitor *m; - XExposeEvent *ev = &e->xexpose; - -- if(ev->count == 0 && (m = wintomon(ev->window))) -+ if(ev->count == 0 && (m = wintomon(ev->window))){ - drawbar(m); -+ drawtab(m); -+ } - } - - void -@@ -800,6 +942,7 @@ focus(Client *c) { - } - selmon->sel = c; - drawbars(); -+ drawtabs(); - } - - void -@@ -850,6 +993,19 @@ focusstack(const Arg *arg) { - } - } - -+void -+focuswin(const Arg* arg){ -+ int iwin = arg->i; -+ Client* c = NULL; -+ for(c = selmon->clients; c && (iwin || !ISVISIBLE(c)) ; c = c->next){ -+ if(ISVISIBLE(c)) --iwin; -+ }; -+ if(c) { -+ focus(c); -+ restack(selmon); -+ } -+} -+ - Atom - getatomprop(Client *c, Atom prop) { - int di; -@@ -1215,12 +1371,14 @@ propertynotify(XEvent *e) { - case XA_WM_HINTS: - updatewmhints(c); - drawbars(); -+ drawtabs(); - break; - } - if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { - updatetitle(c); - if(c == c->mon->sel) - drawbar(c->mon); -+ drawtab(c->mon); - } - if(ev->atom == netatom[NetWMWindowType]) - updatewindowtype(c); -@@ -1328,6 +1486,7 @@ restack(Monitor *m) { - XWindowChanges wc; - - drawbar(m); -+ drawtab(m); - if(!m->sel) - return; - if(m->sel->isfloating || !m->lt[m->sellt]->arrange) -@@ -1511,6 +1670,8 @@ setup(void) { - if (!drw->fontcount) - die("no fonts could be loaded.\n"); - bh = drw->fonts[0]->h + 2; -+ th = bh; -+ - updategeom(); - /* init atoms */ - wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); -@@ -1642,6 +1803,16 @@ togglebar(const Arg *arg) { - } - - void -+tabmode(const Arg *arg) { -+ if(arg && arg->i >= 0) -+ selmon->showtab = arg->ui % showtab_nmodes; -+ else -+ selmon->showtab = (selmon->showtab + 1 ) % showtab_nmodes; -+ arrange(selmon); -+} -+ -+ -+void - togglefloating(const Arg *arg) { - if(!selmon->sel) - return; -@@ -1745,20 +1916,43 @@ updatebars(void) { - CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); - XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); - XMapRaised(dpy, m->barwin); -+ m->tabwin = XCreateWindow(dpy, root, m->wx, m->ty, m->ww, th, 0, DefaultDepth(dpy, screen), -+ CopyFromParent, DefaultVisual(dpy, screen), -+ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); -+ XDefineCursor(dpy, m->tabwin, cursor[CurNormal]->cursor); -+ XMapRaised(dpy, m->tabwin); - } - } - - void - updatebarpos(Monitor *m) { -+ Client *c; -+ int nvis = 0; -+ - m->wy = m->my; - m->wh = m->mh; - if(m->showbar) { - m->wh -= bh; - m->by = m->topbar ? m->wy : m->wy + m->wh; -- m->wy = m->topbar ? m->wy + bh : m->wy; -- } -- else -+ if ( m->topbar ) -+ m->wy += bh; -+ } else { - m->by = -bh; -+ } -+ -+ for(c = m->clients; c; c = c->next){ -+ if(ISVISIBLE(c)) ++nvis; -+ } -+ -+ if(m->showtab == showtab_always -+ || ((m->showtab == showtab_auto) && (nvis > 1) && (m->lt[m->sellt]->arrange == monocle))){ -+ m->wh -= th; -+ m->ty = m->toptab ? m->wy : m->wy + m->wh; -+ if ( m->toptab ) -+ m->wy += th; -+ } else { -+ m->ty = -th; -+ } - } - - void -@@ -1997,7 +2191,7 @@ wintomon(Window w) { - if(w == root && getrootptr(&x, &y)) - return recttomon(x, y, 1, 1); - for(m = mons; m; m = m->next) -- if(w == m->barwin) -+ if(w == m->barwin || w == m->tabwin) - return m; - if((c = wintoclient(w))) - return c->mon; diff --git a/dwm.suckless.org/patches/historical/dwm-master_2015-12-19_3465be-pertag-tab-v2b.diff b/dwm.suckless.org/patches/historical/dwm-master_2015-12-19_3465be-pertag-tab-v2b.diff @@ -1,844 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 7054c06..f0b33c5 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -15,10 +15,21 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ - static const unsigned int snap = 32; /* snap pixel */ - static const int showbar = 1; /* 0 means no bar */ - static const int topbar = 1; /* 0 means bottom bar */ -+/* Display modes of the tab bar: never shown, always shown, shown only in */ -+/* monocle mode in presence of several windows. */ -+/* Modes after showtab_nmodes are disabled */ -+enum showtab_modes { showtab_never, showtab_auto, showtab_nmodes, showtab_always}; -+static const int showtab = showtab_auto; /* Default tab bar show mode */ -+static const Bool toptab = False; /* False means bottom tab bar */ - - /* tagging */ - static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; - -+/* default layout per tags */ -+/* The first element is for all-tag view, following i-th element corresponds to */ -+/* tags[i]. Layout is referred using the layouts array index.*/ -+static int def_layouts[1 + LENGTH(tags)] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -+ - static const Rule rules[] = { - /* xprop(1): - * WM_CLASS(STRING) = instance, class -@@ -62,6 +73,7 @@ static Key keys[] = { - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, - { MODKEY, XK_b, togglebar, {0} }, -+ { MODKEY, XK_w, tabmode, {-1} }, - { MODKEY, XK_j, focusstack, {.i = +1 } }, - { MODKEY, XK_k, focusstack, {.i = -1 } }, - { MODKEY, XK_i, incnmaster, {.i = +1 } }, -@@ -109,5 +121,6 @@ static Button buttons[] = { - { ClkTagBar, 0, Button3, toggleview, {0} }, - { ClkTagBar, MODKEY, Button1, tag, {0} }, - { ClkTagBar, MODKEY, Button3, toggletag, {0} }, -+ { ClkTabBar, 0, Button1, focuswin, {0} }, - }; - -diff --git a/dwm.1 b/dwm.1 -index 6687011..077d92b 100644 ---- a/dwm.1 -+++ b/dwm.1 -@@ -19,14 +19,22 @@ layout applied. - 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. -+Each screen contains two small status bars. -+.P -+One bar 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 -+Another bar contains a tab for each window of the current view and allows -+navigation between windows, especially in the monocle mode. The different -+display modes of this bar are described under the Mod1\-w Keybord command -+section. When a single tag is selected, that tag is indicated in the left corner -+of the tab bar. - .P - dwm draws a small border around windows to indicate the focus state. - .SH OPTIONS -@@ -43,7 +51,8 @@ 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. -+label toggles between tiled and floating layout, click on a window name in the -+tab bar brings focus to that window. - .TP - .B Button3 - click on a tag label adds/removes all windows with that tag to/from the view. -@@ -104,6 +113,12 @@ Increase master area size. - .B Mod1\-h - Decrease master area size. - .TP -+.B Mod1\-w -+Cycle over the tab bar display modes: never displayed, always displayed, -+displayed only in monocle mode when the view contains than one window (auto -+mode). Some display modes can be disabled in the configuration, config.h. In -+the default configuration only "never" and "auto" display modes are enabled. -+.TP - .B Mod1\-Return - Zooms/cycles focused window to/from master area (tiled layouts only). - .TP -diff --git a/dwm.c b/dwm.c -index ff7e096..830d2c2 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -64,7 +64,7 @@ enum { NetSupported, NetWMName, NetWMState, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ - enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ --enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, -+enum { ClkTagBar, ClkTabBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, - ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ - - typedef union { -@@ -111,25 +111,35 @@ typedef struct { - void (*arrange)(Monitor *); - } Layout; - -+#define MAXTABS 50 -+ -+typedef struct Pertag Pertag; - struct Monitor { - char ltsymbol[16]; - float mfact; - int nmaster; - int num; - int by; /* bar geometry */ -+ int ty; /* tab bar geometry */ - int mx, my, mw, mh; /* screen size */ - int wx, wy, ww, wh; /* window area */ - unsigned int seltags; - unsigned int sellt; - unsigned int tagset[2]; - int showbar; -+ int showtab; - int topbar; -+ int toptab; - Client *clients; - Client *sel; - Client *stack; - Monitor *next; - Window barwin; -+ Window tabwin; -+ int ntabs; -+ int tab_widths[MAXTABS]; - const Layout *lt[2]; -+ Pertag *pertag; - }; - - typedef struct { -@@ -164,12 +174,15 @@ static void detachstack(Client *c); - static Monitor *dirtomon(int dir); - static void drawbar(Monitor *m); - static void drawbars(void); -+static void drawtab(Monitor *m); -+static void drawtabs(void); - 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 void focuswin(const Arg* arg); - static int getrootptr(int *x, int *y); - static long getstate(Window w); - static int gettextprop(Window w, Atom atom, char *text, unsigned int size); -@@ -206,6 +219,7 @@ static void setup(void); - static void showhide(Client *c); - static void sigchld(int unused); - static void spawn(const Arg *arg); -+static void tabmode(const Arg *arg); - static void tag(const Arg *arg); - static void tagmon(const Arg *arg); - static void tile(Monitor *); -@@ -240,6 +254,7 @@ static char stext[256]; - static int screen; - static int sw, sh; /* X display screen geometry width, height */ - static int bh, blw = 0; /* bar geometry */ -+static int th = 0; /* tab bar geometry */ - static int (*xerrorxlib)(Display *, XErrorEvent *); - static unsigned int numlockmask = 0; - static void (*handler[LASTEvent]) (XEvent *) = { -@@ -270,6 +285,16 @@ static Window root; - /* configuration, allows nested code to access above variables */ - #include "config.h" - -+struct Pertag { -+ unsigned int curtag, prevtag; /* current and previous tag */ -+ int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */ -+ float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */ -+ unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */ -+ const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes */ -+ Bool showbars[LENGTH(tags) + 1]; /* display bar for the current tag */ -+ Client *prevzooms[LENGTH(tags) + 1]; /* store zoom information */ -+}; -+ - /* compile-time check if all tags fit into an unsigned int bit array. */ - struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; - -@@ -393,6 +418,8 @@ arrange(Monitor *m) - void - arrangemon(Monitor *m) - { -+ updatebarpos(m); -+ XMoveResizeWindow(dpy, m->tabwin, m->wx, m->ty, m->ww, th); - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); - if (m->lt[m->sellt]->arrange) - m->lt[m->sellt]->arrange(m); -@@ -442,14 +469,33 @@ buttonpress(XEvent *e) - click = ClkStatusText; - else - click = ClkWinTitle; -- } else if ((c = wintoclient(ev->window))) { -+ } -+ if(ev->window == selmon->tabwin) { -+ i = 0; x = 0; -+ for(c = selmon->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ x += selmon->tab_widths[i]; -+ if (ev->x > x) -+ ++i; -+ else -+ break; -+ if(i >= m->ntabs) break; -+ } -+ if(c) { -+ click = ClkTabBar; -+ arg.ui = i; -+ } -+ } -+ else if((c = wintoclient(ev->window))) { - focus(c); - 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); -+ 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 || click == ClkTabBar) -+ && buttons[i].arg.i == 0) ? &arg : &buttons[i].arg); -+ } - } - - void -@@ -469,23 +515,24 @@ cleanup(void) - Arg a = {.ui = ~0}; - Layout foo = { "", NULL }; - Monitor *m; -- size_t i; - - view(&a); - selmon->lt[selmon->sellt] = &foo; - for (m = mons; m; m = m->next) -- while (m->stack) -- unmanage(m->stack, 0); -+ while(m->stack) -+ unmanage(m->stack, False); - 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 < SchemeLast; i++) { -- drw_clr_free(scheme[i].border); -- drw_clr_free(scheme[i].bg); -- drw_clr_free(scheme[i].fg); -- } -+ drw_cur_free(drw, cursor[CurNormal]); -+ drw_cur_free(drw, cursor[CurResize]); -+ drw_cur_free(drw, cursor[CurMove]); -+ drw_clr_free(scheme[SchemeNorm].border); -+ drw_clr_free(scheme[SchemeNorm].bg); -+ drw_clr_free(scheme[SchemeNorm].fg); -+ drw_clr_free(scheme[SchemeSel].border); -+ drw_clr_free(scheme[SchemeSel].bg); -+ drw_clr_free(scheme[SchemeSel].fg); - drw_free(drw); - XSync(dpy, False); - XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); -@@ -505,6 +552,8 @@ cleanupmon(Monitor *mon) - } - XUnmapWindow(dpy, mon->barwin); - XDestroyWindow(dpy, mon->barwin); -+ XUnmapWindow(dpy, mon->tabwin); -+ XDestroyWindow(dpy, mon->tabwin); - free(mon); - } - -@@ -526,6 +575,7 @@ clientmessage(XEvent *e) - { - XClientMessageEvent *cme = &e->xclient; - Client *c = wintoclient(cme->window); -+ int i; - - if (!c) - return; -@@ -537,6 +587,8 @@ clientmessage(XEvent *e) - if (!ISVISIBLE(c)) { - c->mon->seltags ^= 1; - c->mon->tagset[c->mon->seltags] = c->tags; -+ for(i=0; !(c->tags & 1 << i); i++); -+ view(&(Arg){.ui = 1 << i}); - } - pop(c); - } -@@ -565,11 +617,10 @@ void - configurenotify(XEvent *e) - { - Monitor *m; -- Client *c; - XConfigureEvent *ev = &e->xconfigure; - int dirty; - -- /* TODO: updategeom handling sucks, needs to be simplified */ -+ // TODO: updategeom handling sucks, needs to be simplified - if (ev->window == root) { - dirty = (sw != ev->width || sh != ev->height); - sw = ev->width; -@@ -577,10 +628,9 @@ configurenotify(XEvent *e) - if (updategeom() || dirty) { - drw_resize(drw, sw, bh); - 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); -+ //refreshing display of status bar. The tab bar is handled by the arrange() -+ //method, which is called below -+ for (m = mons; m; m = m->next){ - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); - } - focus(NULL); -@@ -645,16 +695,41 @@ Monitor * - createmon(void) - { - Monitor *m; -+ int i; - - m = ecalloc(1, sizeof(Monitor)); - m->tagset[0] = m->tagset[1] = 1; - m->mfact = mfact; - m->nmaster = nmaster; - m->showbar = showbar; -+ m->showtab = showtab; - m->topbar = topbar; -- m->lt[0] = &layouts[0]; -+ m->toptab = toptab; -+ m->ntabs = 0; -+ m->lt[0] = &layouts[def_layouts[1] % LENGTH(layouts)]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); -+ if(!(m->pertag = (Pertag *)calloc(1, sizeof(Pertag)))) -+ die("fatal: could not malloc() %u bytes\n", sizeof(Pertag)); -+ m->pertag->curtag = m->pertag->prevtag = 1; -+ for(i=0; i <= LENGTH(tags); i++) { -+ /* init nmaster */ -+ m->pertag->nmasters[i] = m->nmaster; -+ -+ /* init mfacts */ -+ m->pertag->mfacts[i] = m->mfact; -+ -+ /* init layouts */ -+ m->pertag->ltidxs[i][0] = &layouts[def_layouts[i % LENGTH(def_layouts)] % LENGTH(layouts)]; -+ m->pertag->ltidxs[i][1] = m->lt[1]; -+ m->pertag->sellts[i] = m->sellt; -+ -+ /* init showbar */ -+ m->pertag->showbars[i] = m->showbar; -+ -+ /* swap focus and zoomswap*/ -+ m->pertag->prevzooms[i] = NULL; -+ } - return m; - } - -@@ -768,6 +843,104 @@ drawbars(void) - } - - void -+drawtabs(void) { -+ Monitor *m; -+ -+ for(m = mons; m; m = m->next) -+ drawtab(m); -+} -+ -+static int -+cmpint(const void *p1, const void *p2) { -+ /* The actual arguments to this function are "pointers to -+ pointers to char", but strcmp(3) arguments are "pointers -+ to char", hence the following cast plus dereference */ -+ return *((int*) p1) > * (int*) p2; -+} -+ -+ -+void -+drawtab(Monitor *m) { -+ Client *c; -+ int i; -+ int itag = -1; -+ char view_info[50]; -+ int view_info_w = 0; -+ int sorted_label_widths[MAXTABS]; -+ int tot_width; -+ int maxsize = bh; -+ int x = 0; -+ int w = 0; -+ -+ //view_info: indicate the tag which is displayed in the view -+ for(i = 0; i < LENGTH(tags); ++i){ -+ if((selmon->tagset[selmon->seltags] >> i) & 1) { -+ if(itag >=0){ //more than one tag selected -+ itag = -1; -+ break; -+ } -+ itag = i; -+ } -+ } -+ if(0 <= itag && itag < LENGTH(tags)){ -+ snprintf(view_info, sizeof view_info, "[%s]", tags[itag]); -+ } else { -+ strncpy(view_info, "[...]", sizeof view_info); -+ } -+ view_info[sizeof(view_info) - 1 ] = 0; -+ view_info_w = TEXTW(view_info); -+ tot_width = view_info_w; -+ -+ /* Calculates number of labels and their width */ -+ m->ntabs = 0; -+ for(c = m->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ m->tab_widths[m->ntabs] = TEXTW(c->name); -+ tot_width += m->tab_widths[m->ntabs]; -+ ++m->ntabs; -+ if(m->ntabs >= MAXTABS) break; -+ } -+ -+ if(tot_width > m->ww){ //not enough space to display the labels, they need to be truncated -+ memcpy(sorted_label_widths, m->tab_widths, sizeof(int) * m->ntabs); -+ qsort(sorted_label_widths, m->ntabs, sizeof(int), cmpint); -+ tot_width = view_info_w; -+ for(i = 0; i < m->ntabs; ++i){ -+ if(tot_width + (m->ntabs - i) * sorted_label_widths[i] > m->ww) -+ break; -+ tot_width += sorted_label_widths[i]; -+ } -+ maxsize = (m->ww - tot_width) / (m->ntabs - i); -+ } else{ -+ maxsize = m->ww; -+ } -+ i = 0; -+ for(c = m->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ if(i >= m->ntabs) break; -+ if(m->tab_widths[i] > maxsize) m->tab_widths[i] = maxsize; -+ w = m->tab_widths[i]; -+ drw_setscheme(drw, (c == m->sel) ? &scheme[SchemeSel] : &scheme[SchemeNorm]); -+ drw_text(drw, x, 0, w, th, c->name, 0); -+ x += w; -+ ++i; -+ } -+ -+ drw_setscheme(drw, &scheme[SchemeNorm]); -+ -+ /* cleans interspace between window names and current viewed tag label */ -+ w = m->ww - view_info_w - x; -+ drw_text(drw, x, 0, w, th, "", 0); -+ -+ /* view info */ -+ x += w; -+ w = view_info_w; -+ drw_text(drw, x, 0, w, th, view_info, 0); -+ -+ drw_map(drw, m->tabwin, 0, 0, m->ww, th); -+} -+ -+void - enternotify(XEvent *e) - { - Client *c; -@@ -792,8 +965,10 @@ expose(XEvent *e) - Monitor *m; - XExposeEvent *ev = &e->xexpose; - -- if (ev->count == 0 && (m = wintomon(ev->window))) -+ if (ev->count == 0 && (m = wintomon(ev->window))){ - drawbar(m); -+ drawtab(m); -+ } - } - - void -@@ -811,7 +986,7 @@ focus(Client *c) - clearurgent(c); - detachstack(c); - attachstack(c); -- grabbuttons(c, 1); -+ grabbuttons(c, True); - XSetWindowBorder(dpy, c->win, scheme[SchemeSel].border->pix); - setfocus(c); - } else { -@@ -820,6 +995,7 @@ focus(Client *c) - } - selmon->sel = c; - drawbars(); -+ drawtabs(); - } - - /* there are some broken focus acquiring clients */ -@@ -873,6 +1049,19 @@ focusstack(const Arg *arg) - } - } - -+void -+focuswin(const Arg* arg){ -+ int iwin = arg->i; -+ Client* c = NULL; -+ for(c = selmon->clients; c && (iwin || !ISVISIBLE(c)) ; c = c->next){ -+ if(ISVISIBLE(c)) --iwin; -+ }; -+ if(c) { -+ focus(c); -+ restack(selmon); -+ } -+} -+ - Atom - getatomprop(Client *c, Atom prop) - { -@@ -986,7 +1175,7 @@ grabkeys(void) - void - incnmaster(const Arg *arg) - { -- selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); -+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0); - arrange(selmon); - } - -@@ -1144,7 +1333,7 @@ motionnotify(XEvent *e) - if (ev->window != root) - return; - if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { -- unfocus(selmon->sel, 1); -+ unfocus(selmon->sel, True); - selmon = m; - focus(NULL); - } -@@ -1164,11 +1353,13 @@ movemouse(const Arg *arg) - return; - if (c->isfullscreen) /* no support moving fullscreen windows by mouse */ - return; -+ if(c->isfullscreen) /* no support moving fullscreen windows by mouse */ -+ return; - restack(selmon); - ocx = c->x; - ocy = c->y; - if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, -- None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) -+ None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) - return; - if (!getrootptr(&x, &y)) - return; -@@ -1255,12 +1446,14 @@ propertynotify(XEvent *e) - case XA_WM_HINTS: - updatewmhints(c); - drawbars(); -+ drawtabs(); - break; - } - if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { - updatetitle(c); - if (c == c->mon->sel) - drawbar(c->mon); -+ drawtab(c->mon); - } - if (ev->atom == netatom[NetWMWindowType]) - updatewindowtype(c); -@@ -1322,11 +1515,13 @@ resizemouse(const Arg *arg) - return; - if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ - return; -+ if(c->isfullscreen) /* no support resizing fullscreen windows by mouse */ -+ return; - restack(selmon); - ocx = c->x; - ocy = c->y; - if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, -- None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) -+ 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); - do { -@@ -1374,6 +1569,7 @@ restack(Monitor *m) - XWindowChanges wc; - - drawbar(m); -+ drawtab(m); - if (!m->sel) - return; - if (m->sel->isfloating || !m->lt[m->sellt]->arrange) -@@ -1482,11 +1678,11 @@ sendevent(Client *c, Atom proto) - void - setfocus(Client *c) - { -- if (!c->neverfocus) { -+ if(!c->neverfocus) { - XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); - XChangeProperty(dpy, root, netatom[NetActiveWindow], -- XA_WINDOW, 32, PropModeReplace, -- (unsigned char *) &(c->win), 1); -+ XA_WINDOW, 32, PropModeReplace, -+ (unsigned char *) &(c->win), 1); - } - sendevent(c, wmatom[WMTakeFocus]); - } -@@ -1522,10 +1718,13 @@ setfullscreen(Client *c, int fullscreen) - 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; -+ if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) { -+ selmon->pertag->sellts[selmon->pertag->curtag] ^= 1; -+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; -+ } -+ if(arg && arg->v) -+ selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v; -+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; - strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); - if (selmon->sel) - arrange(selmon); -@@ -1544,7 +1743,7 @@ setmfact(const Arg *arg) - f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; - if (f < 0.1 || f > 0.9) - return; -- selmon->mfact = f; -+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; - arrange(selmon); - } - -@@ -1564,8 +1763,9 @@ setup(void) - drw = drw_create(dpy, screen, root, sw, sh); - drw_load_fonts(drw, fonts, LENGTH(fonts)); - if (!drw->fontcount) -- die("no fonts could be loaded.\n"); -+ die("No fonts could be loaded.\n"); - bh = drw->fonts[0]->h + 2; -+ th = bh; - updategeom(); - /* init atoms */ - wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); -@@ -1637,10 +1837,10 @@ sigchld(int unused) - void - spawn(const Arg *arg) - { -- if (arg->v == dmenucmd) -+ if(arg->v == dmenucmd) - dmenumon[0] = '0' + selmon->num; -- if (fork() == 0) { -- if (dpy) -+ if(fork() == 0) { -+ if(dpy) - close(ConnectionNumber(dpy)); - setsid(); - execvp(((char **)arg->v)[0], (char **)arg->v); -@@ -1697,18 +1897,29 @@ tile(Monitor *m) - void - togglebar(const Arg *arg) - { -- selmon->showbar = !selmon->showbar; -+ selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar; - updatebarpos(selmon); - XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); - arrange(selmon); - } - - void -+tabmode(const Arg *arg) -+{ -+ if(arg && arg->i >= 0) -+ selmon->showtab = arg->ui % showtab_nmodes; -+ else -+ selmon->showtab = (selmon->showtab + 1 ) % showtab_nmodes; -+ arrange(selmon); -+} -+ -+ -+void - togglefloating(const Arg *arg) - { -- if (!selmon->sel) -+ if(!selmon->sel) - return; -- if (selmon->sel->isfullscreen) /* no support for fullscreen windows */ -+ if(selmon->sel->isfullscreen) /* no support for fullscreen windows */ - return; - selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; - if (selmon->sel->isfloating) -@@ -1736,9 +1947,29 @@ void - toggleview(const Arg *arg) - { - unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); -+ int i; - - if (newtagset) { -+ if(newtagset == ~0) { -+ selmon->pertag->prevtag = selmon->pertag->curtag; -+ selmon->pertag->curtag = 0; -+ } -+ /* test if the user did not select the same tag */ -+ if(!(newtagset & 1 << (selmon->pertag->curtag - 1))) { -+ selmon->pertag->prevtag = selmon->pertag->curtag; -+ for (i=0; !(newtagset & 1 << i); i++) ; -+ selmon->pertag->curtag = i + 1; -+ } - selmon->tagset[selmon->seltags] = newtagset; -+ -+ /* apply settings for this view */ -+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; -+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; -+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; -+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; -+ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; -+ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) -+ togglebar(NULL); - focus(NULL); - arrange(selmon); - } -@@ -1749,7 +1980,7 @@ unfocus(Client *c, int setfocus) - { - if (!c) - return; -- grabbuttons(c, 0); -+ grabbuttons(c, False); - XSetWindowBorder(dpy, c->win, scheme[SchemeNorm].border->pix); - if (setfocus) { - XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); -@@ -1814,20 +2045,44 @@ updatebars(void) - CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); - XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); - XMapRaised(dpy, m->barwin); -+ m->tabwin = XCreateWindow(dpy, root, m->wx, m->ty, m->ww, th, 0, DefaultDepth(dpy, screen), -+ CopyFromParent, DefaultVisual(dpy, screen), -+ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); -+ XDefineCursor(dpy, m->tabwin, cursor[CurNormal]->cursor); -+ XMapRaised(dpy, m->tabwin); - } - } - - void - updatebarpos(Monitor *m) - { -+ Client *c; -+ int nvis = 0; -+ - m->wy = m->my; - m->wh = m->mh; - if (m->showbar) { - m->wh -= bh; - m->by = m->topbar ? m->wy : m->wy + m->wh; -- m->wy = m->topbar ? m->wy + bh : m->wy; -- } else -+ if ( m->topbar ) -+ m->wy += bh; -+ } else { - m->by = -bh; -+ } -+ -+ for(c = m->clients; c; c = c->next){ -+ if(ISVISIBLE(c)) ++nvis; -+ } -+ -+ if(m->showtab == showtab_always -+ || ((m->showtab == showtab_auto) && (nvis > 1) && (m->lt[m->sellt]->arrange == monocle))){ -+ m->wh -= th; -+ m->ty = m->toptab ? m->wy : m->wy + m->wh; -+ if ( m->toptab ) -+ m->wy += th; -+ } else { -+ m->ty = -th; -+ } - } - - void -@@ -2009,9 +2264,9 @@ updatewindowtype(Client *c) - Atom wtype = getatomprop(c, netatom[NetWMWindowType]); - - if (state == netatom[NetWMFullscreen]) -- setfullscreen(c, 1); -+ setfullscreen(c, True); - if (wtype == netatom[NetWMWindowTypeDialog]) -- c->isfloating = 1; -+ c->isfloating = True; - } - - void -@@ -2036,11 +2291,33 @@ updatewmhints(Client *c) - void - view(const Arg *arg) - { -- if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) -+ int i; -+ unsigned int tmptag; -+ -+ if((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) - return; - selmon->seltags ^= 1; /* toggle sel tagset */ -- if (arg->ui & TAGMASK) -+ if(arg->ui & TAGMASK) { -+ selmon->pertag->prevtag = selmon->pertag->curtag; - selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; -+ if(arg->ui == ~0) -+ selmon->pertag->curtag = 0; -+ else { -+ for (i=0; !(arg->ui & 1 << i); i++) ; -+ selmon->pertag->curtag = i + 1; -+ } -+ } else { -+ tmptag = selmon->pertag->prevtag; -+ selmon->pertag->prevtag = selmon->pertag->curtag; -+ selmon->pertag->curtag = tmptag; -+ } -+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; -+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; -+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; -+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; -+ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; -+ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) -+ togglebar(NULL); - focus(NULL); - arrange(selmon); - } -@@ -2068,7 +2345,7 @@ wintomon(Window w) - if (w == root && getrootptr(&x, &y)) - return recttomon(x, y, 1, 1); - for (m = mons; m; m = m->next) -- if (w == m->barwin) -+ if(w == m->barwin || w == m->tabwin) - return m; - if ((c = wintoclient(w))) - return c->mon; diff --git a/dwm.suckless.org/patches/historical/dwm-master_2015-12-19_3465be-tab-v2b.diff b/dwm.suckless.org/patches/historical/dwm-master_2015-12-19_3465be-tab-v2b.diff @@ -1,500 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 7054c06..e784231 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -15,6 +15,12 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ - static const unsigned int snap = 32; /* snap pixel */ - static const int showbar = 1; /* 0 means no bar */ - static const int topbar = 1; /* 0 means bottom bar */ -+/* Display modes of the tab bar: never shown, always shown, shown only in */ -+/* monocle mode in presence of several windows. */ -+/* Modes after showtab_nmodes are disabled */ -+enum showtab_modes { showtab_never, showtab_auto, showtab_nmodes, showtab_always}; -+static const int showtab = showtab_auto; /* Default tab bar show mode */ -+static const int toptab = False; /* False means bottom tab bar */ - - /* tagging */ - static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; -@@ -62,6 +68,7 @@ static Key keys[] = { - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, - { MODKEY, XK_b, togglebar, {0} }, -+ { MODKEY, XK_w, tabmode, {-1} }, - { MODKEY, XK_j, focusstack, {.i = +1 } }, - { MODKEY, XK_k, focusstack, {.i = -1 } }, - { MODKEY, XK_i, incnmaster, {.i = +1 } }, -@@ -109,5 +116,6 @@ static Button buttons[] = { - { ClkTagBar, 0, Button3, toggleview, {0} }, - { ClkTagBar, MODKEY, Button1, tag, {0} }, - { ClkTagBar, MODKEY, Button3, toggletag, {0} }, -+ { ClkTabBar, 0, Button1, focuswin, {0} }, - }; - -diff --git a/dwm.1 b/dwm.1 -index 6687011..9ff827c 100644 ---- a/dwm.1 -+++ b/dwm.1 -@@ -19,14 +19,22 @@ layout applied. - 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. -+Each screen contains two small status bars. -+.P -+One bar 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 -+Another bar contains a tab for each window of the current view and allows -+navigation between windows, especially in the monocle mode. The different -+display modes of this bar are described under the Mod1\-w Keybord command -+section. When a single tag is selected, this tag is indicated in the left corner -+of the tab bar. - .P - dwm draws a small border around windows to indicate the focus state. - .SH OPTIONS -@@ -43,7 +51,8 @@ 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. -+label toggles between tiled and floating layout, click on a window name in the -+tab bar brings focus to that window. - .TP - .B Button3 - click on a tag label adds/removes all windows with that tag to/from the view. -@@ -104,6 +113,12 @@ Increase master area size. - .B Mod1\-h - Decrease master area size. - .TP -+.B Mod1\-w -+Cycle over the tab bar display modes: never displayed, always displayed, -+displayed only in monocle mode when the view contains more than one window (auto -+mode). Some display modes can be disabled in the configuration, config.h. In -+the default configuration only "never" and "auto" display modes are enabled. -+.TP - .B Mod1\-Return - Zooms/cycles focused window to/from master area (tiled layouts only). - .TP -diff --git a/dwm.c b/dwm.c -index ff7e096..fb285ec 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -64,7 +64,7 @@ enum { NetSupported, NetWMName, NetWMState, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ - enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ --enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, -+enum { ClkTagBar, ClkTabBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, - ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ - - typedef union { -@@ -111,24 +111,32 @@ typedef struct { - void (*arrange)(Monitor *); - } Layout; - -+#define MAXTABS 50 -+ - struct Monitor { - char ltsymbol[16]; - float mfact; - int nmaster; - int num; - int by; /* bar geometry */ -+ int ty; /* tab bar geometry */ - int mx, my, mw, mh; /* screen size */ - int wx, wy, ww, wh; /* window area */ - unsigned int seltags; - unsigned int sellt; - unsigned int tagset[2]; - int showbar; -+ int showtab; - int topbar; -+ int toptab; - Client *clients; - Client *sel; - Client *stack; - Monitor *next; - Window barwin; -+ Window tabwin; -+ int ntabs; -+ int tab_widths[MAXTABS]; - const Layout *lt[2]; - }; - -@@ -164,12 +172,15 @@ static void detachstack(Client *c); - static Monitor *dirtomon(int dir); - static void drawbar(Monitor *m); - static void drawbars(void); -+static void drawtab(Monitor *m); -+static void drawtabs(void); - 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 void focuswin(const Arg* arg); - static int getrootptr(int *x, int *y); - static long getstate(Window w); - static int gettextprop(Window w, Atom atom, char *text, unsigned int size); -@@ -206,6 +217,7 @@ static void setup(void); - static void showhide(Client *c); - static void sigchld(int unused); - static void spawn(const Arg *arg); -+static void tabmode(const Arg *arg); - static void tag(const Arg *arg); - static void tagmon(const Arg *arg); - static void tile(Monitor *); -@@ -240,6 +252,7 @@ static char stext[256]; - static int screen; - static int sw, sh; /* X display screen geometry width, height */ - static int bh, blw = 0; /* bar geometry */ -+static int th = 0; /* tab bar geometry */ - static int (*xerrorxlib)(Display *, XErrorEvent *); - static unsigned int numlockmask = 0; - static void (*handler[LASTEvent]) (XEvent *) = { -@@ -391,8 +404,9 @@ arrange(Monitor *m) - } - - void --arrangemon(Monitor *m) --{ -+arrangemon(Monitor *m) { -+ updatebarpos(m); -+ XMoveResizeWindow(dpy, m->tabwin, m->wx, m->ty, m->ww, th); - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); - if (m->lt[m->sellt]->arrange) - m->lt[m->sellt]->arrange(m); -@@ -442,14 +456,33 @@ buttonpress(XEvent *e) - click = ClkStatusText; - else - click = ClkWinTitle; -- } else if ((c = wintoclient(ev->window))) { -+ } -+ if(ev->window == selmon->tabwin) { -+ i = 0; x = 0; -+ for(c = selmon->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ x += selmon->tab_widths[i]; -+ if (ev->x > x) -+ ++i; -+ else -+ break; -+ if(i >= m->ntabs) break; -+ } -+ if(c) { -+ click = ClkTabBar; -+ arg.ui = i; -+ } -+ } -+ else if((c = wintoclient(ev->window))) { - focus(c); - 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); -+ && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)){ -+ buttons[i].func(((click == ClkTagBar || click == ClkTabBar) -+ && buttons[i].arg.i == 0) ? &arg : &buttons[i].arg); -+ } - } - - void -@@ -505,6 +538,8 @@ cleanupmon(Monitor *mon) - } - XUnmapWindow(dpy, mon->barwin); - XDestroyWindow(dpy, mon->barwin); -+ XUnmapWindow(dpy, mon->tabwin); -+ XDestroyWindow(dpy, mon->tabwin); - free(mon); - } - -@@ -577,7 +612,9 @@ configurenotify(XEvent *e) - if (updategeom() || dirty) { - drw_resize(drw, sw, bh); - updatebars(); -- for (m = mons; m; m = m->next) { -+ //refreshing display of status bar. The tab bar is handled by the arrange() -+ //method, which is called below -+ 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); -@@ -651,7 +688,10 @@ createmon(void) - m->mfact = mfact; - m->nmaster = nmaster; - m->showbar = showbar; -+ m->showtab = showtab; - m->topbar = topbar; -+ m->toptab = toptab; -+ m->ntabs = 0; - m->lt[0] = &layouts[0]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); -@@ -768,6 +808,105 @@ drawbars(void) - } - - void -+drawtabs(void) { -+ Monitor *m; -+ -+ for(m = mons; m; m = m->next) -+ drawtab(m); -+} -+ -+static int -+cmpint(const void *p1, const void *p2) { -+ /* The actual arguments to this function are "pointers to -+ pointers to char", but strcmp(3) arguments are "pointers -+ to char", hence the following cast plus dereference */ -+ return *((int*) p1) > * (int*) p2; -+} -+ -+ -+void -+drawtab(Monitor *m) { -+ Client *c; -+ int i; -+ int itag = -1; -+ char view_info[50]; -+ int view_info_w = 0; -+ int sorted_label_widths[MAXTABS]; -+ int tot_width; -+ int maxsize = bh; -+ int x = 0; -+ int w = 0; -+ -+ //view_info: indicate the tag which is displayed in the view -+ for(i = 0; i < LENGTH(tags); ++i){ -+ if((selmon->tagset[selmon->seltags] >> i) & 1) { -+ if(itag >=0){ //more than one tag selected -+ itag = -1; -+ break; -+ } -+ itag = i; -+ } -+ } -+ -+ if(0 <= itag && itag < LENGTH(tags)){ -+ snprintf(view_info, sizeof view_info, "[%s]", tags[itag]); -+ } else { -+ strncpy(view_info, "[...]", sizeof view_info); -+ } -+ view_info[sizeof(view_info) - 1 ] = 0; -+ view_info_w = TEXTW(view_info); -+ tot_width = view_info_w; -+ -+ /* Calculates number of labels and their width */ -+ m->ntabs = 0; -+ for(c = m->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ m->tab_widths[m->ntabs] = TEXTW(c->name); -+ tot_width += m->tab_widths[m->ntabs]; -+ ++m->ntabs; -+ if(m->ntabs >= MAXTABS) break; -+ } -+ -+ if(tot_width > m->ww){ //not enough space to display the labels, they need to be truncated -+ memcpy(sorted_label_widths, m->tab_widths, sizeof(int) * m->ntabs); -+ qsort(sorted_label_widths, m->ntabs, sizeof(int), cmpint); -+ tot_width = view_info_w; -+ for(i = 0; i < m->ntabs; ++i){ -+ if(tot_width + (m->ntabs - i) * sorted_label_widths[i] > m->ww) -+ break; -+ tot_width += sorted_label_widths[i]; -+ } -+ maxsize = (m->ww - tot_width) / (m->ntabs - i); -+ } else{ -+ maxsize = m->ww; -+ } -+ i = 0; -+ for(c = m->clients; c; c = c->next){ -+ if(!ISVISIBLE(c)) continue; -+ if(i >= m->ntabs) break; -+ if(m->tab_widths[i] > maxsize) m->tab_widths[i] = maxsize; -+ w = m->tab_widths[i]; -+ drw_setscheme(drw, (c == m->sel) ? &scheme[SchemeSel] : &scheme[SchemeNorm]); -+ drw_text(drw, x, 0, w, th, c->name, 0); -+ x += w; -+ ++i; -+ } -+ -+ drw_setscheme(drw, &scheme[SchemeNorm]); -+ -+ /* cleans interspace between window names and current viewed tag label */ -+ w = m->ww - view_info_w - x; -+ drw_text(drw, x, 0, w, th, "", 0); -+ -+ /* view info */ -+ x += w; -+ w = view_info_w; -+ drw_text(drw, x, 0, w, th, view_info, 0); -+ -+ drw_map(drw, m->tabwin, 0, 0, m->ww, th); -+} -+ -+void - enternotify(XEvent *e) - { - Client *c; -@@ -792,8 +931,10 @@ expose(XEvent *e) - Monitor *m; - XExposeEvent *ev = &e->xexpose; - -- if (ev->count == 0 && (m = wintomon(ev->window))) -+ if(ev->count == 0 && (m = wintomon(ev->window))){ - drawbar(m); -+ drawtab(m); -+ } - } - - void -@@ -820,6 +961,7 @@ focus(Client *c) - } - selmon->sel = c; - drawbars(); -+ drawtabs(); - } - - /* there are some broken focus acquiring clients */ -@@ -873,6 +1015,19 @@ focusstack(const Arg *arg) - } - } - -+void -+focuswin(const Arg* arg){ -+ int iwin = arg->i; -+ Client* c = NULL; -+ for(c = selmon->clients; c && (iwin || !ISVISIBLE(c)) ; c = c->next){ -+ if(ISVISIBLE(c)) --iwin; -+ }; -+ if(c) { -+ focus(c); -+ restack(selmon); -+ } -+} -+ - Atom - getatomprop(Client *c, Atom prop) - { -@@ -1255,12 +1410,14 @@ propertynotify(XEvent *e) - case XA_WM_HINTS: - updatewmhints(c); - drawbars(); -+ drawtabs(); - break; - } - if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { - updatetitle(c); - if (c == c->mon->sel) - drawbar(c->mon); -+ drawtab(c->mon); - } - if (ev->atom == netatom[NetWMWindowType]) - updatewindowtype(c); -@@ -1374,6 +1531,7 @@ restack(Monitor *m) - XWindowChanges wc; - - drawbar(m); -+ drawtab(m); - if (!m->sel) - return; - if (m->sel->isfloating || !m->lt[m->sellt]->arrange) -@@ -1566,6 +1724,8 @@ setup(void) - if (!drw->fontcount) - die("no fonts could be loaded.\n"); - bh = drw->fonts[0]->h + 2; -+ th = bh; -+ - updategeom(); - /* init atoms */ - wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); -@@ -1704,6 +1864,17 @@ togglebar(const Arg *arg) - } - - void -+tabmode(const Arg *arg) -+{ -+ if(arg && arg->i >= 0) -+ selmon->showtab = arg->ui % showtab_nmodes; -+ else -+ selmon->showtab = (selmon->showtab + 1 ) % showtab_nmodes; -+ arrange(selmon); -+} -+ -+ -+void - togglefloating(const Arg *arg) - { - if (!selmon->sel) -@@ -1814,20 +1985,44 @@ updatebars(void) - CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); - XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); - XMapRaised(dpy, m->barwin); -+ m->tabwin = XCreateWindow(dpy, root, m->wx, m->ty, m->ww, th, 0, DefaultDepth(dpy, screen), -+ CopyFromParent, DefaultVisual(dpy, screen), -+ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); -+ XDefineCursor(dpy, m->tabwin, cursor[CurNormal]->cursor); -+ XMapRaised(dpy, m->tabwin); - } - } - - void - updatebarpos(Monitor *m) - { -+ Client *c; -+ int nvis = 0; -+ - m->wy = m->my; - m->wh = m->mh; - if (m->showbar) { - m->wh -= bh; - m->by = m->topbar ? m->wy : m->wy + m->wh; -- m->wy = m->topbar ? m->wy + bh : m->wy; -- } else -+ if ( m->topbar ) -+ m->wy += bh; -+ } else { - m->by = -bh; -+ } -+ -+ for(c = m->clients; c; c = c->next){ -+ if(ISVISIBLE(c)) ++nvis; -+ } -+ -+ if(m->showtab == showtab_always -+ || ((m->showtab == showtab_auto) && (nvis > 1) && (m->lt[m->sellt]->arrange == monocle))){ -+ m->wh -= th; -+ m->ty = m->toptab ? m->wy : m->wy + m->wh; -+ if ( m->toptab ) -+ m->wy += th; -+ } else { -+ m->ty = -th; -+ } - } - - void -@@ -2068,7 +2263,7 @@ wintomon(Window w) - if (w == root && getrootptr(&x, &y)) - return recttomon(x, y, 1, 1); - for (m = mons; m; m = m->next) -- if (w == m->barwin) -+ if (w == m->barwin || w == m->tabwin) - return m; - if ((c = wintoclient(w))) - return c->mon; diff --git a/dwm.suckless.org/patches/historical/dwm-movestack-5.8.2.diff b/dwm.suckless.org/patches/historical/dwm-movestack-5.8.2.diff @@ -1,73 +0,0 @@ -diff -r 050d521d66d8 config.def.h ---- a/config.def.h Tue Aug 24 13:13:20 2010 +0100 -+++ b/config.def.h Sun Sep 05 18:43:07 2010 +0200 -@@ -48,6 +48,7 @@ - static const char *dmenucmd[] = { "dmenu_run", "-fn", font, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL }; - static const char *termcmd[] = { "uxterm", NULL }; - -+#include "movestack.c" - static Key keys[] = { - /* modifier key function argument */ - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, -@@ -57,6 +58,8 @@ - { MODKEY, XK_k, focusstack, {.i = -1 } }, - { MODKEY, XK_h, setmfact, {.f = -0.05} }, - { MODKEY, XK_l, setmfact, {.f = +0.05} }, -+ { MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } }, -+ { MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } }, - { MODKEY, XK_Return, zoom, {0} }, - { MODKEY, XK_Tab, view, {0} }, - { MODKEY|ShiftMask, XK_c, killclient, {0} }, -diff -r 050d521d66d8 movestack.c ---- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/movestack.c Sun Sep 05 18:43:07 2010 +0200 -@@ -0,0 +1,49 @@ -+void -+movestack(const Arg *arg) { -+ Client *c = NULL, *p = NULL, *pc = NULL, *i; -+ -+ if(arg->i > 0) { -+ /* 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.suckless.org/patches/historical/dwm-pertag-5.1.diff b/dwm.suckless.org/patches/historical/dwm-pertag-5.1.diff @@ -1,125 +0,0 @@ -diff -NrU3 dwm-5.1/dwm.c dwm-5.1.playground-pertag/dwm.c ---- dwm-5.1/dwm.c 2008-07-29 20:18:32.000000000 +0200 -+++ dwm-5.1-pertag/dwm.c 2008-08-01 18:46:49.000000000 +0200 -@@ -238,6 +238,11 @@ - /* configuration, allows nested code to access above variables */ - #include "config.h" - -+static int curtag = 1, prevtag = 1; -+static Layout *lts[LENGTH(tags) + 1]; -+static double mfacts[LENGTH(tags) + 1]; -+static Bool showbars[LENGTH(tags) + 1]; -+ - /* compile-time check if all tags fit into an unsigned int bit array. */ - struct NumTags { char limitexceeded[sizeof(unsigned int) * 8 < LENGTH(tags) ? -1 : 1]; }; - -@@ -1307,7 +1312,7 @@ - if(!arg || !arg->v || arg->v != lt[sellt]) - sellt ^= 1; - if(arg && arg->v) -- lt[sellt] = (Layout *)arg->v; -+ lt[sellt] = lts[curtag] = (Layout *)arg->v; - if(sel) - arrange(); - else -@@ -1324,7 +1329,7 @@ - f = arg->f < 1.0 ? arg->f + mfact : arg->f - 1.0; - if(f < 0.1 || f > 0.9) - return; -- mfact = f; -+ mfact = mfacts[curtag] = f; - arrange(); - } - -@@ -1373,12 +1378,27 @@ - if(!dc.font.set) - XSetFont(dpy, dc.gc, dc.font.xfont->fid); - -+ /* init mfacts */ -+ for(i=0; i < LENGTH(tags) + 1 ; i++) { -+ mfacts[i] = mfact; -+ } -+ -+ /* init layouts */ -+ for(i=0; i < LENGTH(tags) + 1; i++) { -+ lts[i] = &layouts[0]; -+ } -+ -+ - /* init bar */ - for(blw = i = 0; LENGTH(layouts) > 1 && i < LENGTH(layouts); i++) { - w = TEXTW(layouts[i].symbol); - blw = MAX(blw, w); - } - -+ for(i=0; i < LENGTH(tags) + 1; i++) { -+ showbars[i] = showbar; -+ } -+ - wa.override_redirect = 1; - wa.background_pixmap = ParentRelative; - wa.event_mask = ButtonPressMask|ExposureMask; -@@ -1479,7 +1499,7 @@ - - void - togglebar(const Arg *arg) { -- showbar = !showbar; -+ showbar = showbars[curtag] = !showbar; - updategeom(); - updatebar(); - arrange(); -@@ -1508,9 +1528,23 @@ - void - toggleview(const Arg *arg) { - unsigned int mask = tagset[seltags] ^ (arg->ui & TAGMASK); -+ unsigned int i; - - if(mask) { -+ if(mask == ~0) { -+ prevtag = curtag; -+ curtag = 0; -+ } -+ if(!(mask & 1 << (curtag - 1))) { -+ prevtag = curtag; -+ for (i=0; !(mask & 1 << i); i++); -+ curtag = i + 1; -+ } - tagset[seltags] = mask; -+ lt[sellt] = lts[curtag]; -+ mfact = mfacts[curtag]; -+ if (showbar != showbars[curtag]) -+ togglebar(NULL); - clearurgent(); - arrange(); - } -@@ -1663,11 +1697,29 @@ - - void - view(const Arg *arg) { -+ unsigned int i; -+ - if(arg && (arg->i & TAGMASK) == tagset[seltags]) - return; - seltags ^= 1; /* toggle sel tagset */ -- if(arg && (arg->ui & TAGMASK)) -+ if(arg && (arg->ui & TAGMASK)) { - tagset[seltags] = arg->i & TAGMASK; -+ prevtag = curtag; -+ if(arg->ui == ~0) -+ curtag = 0; -+ else { -+ for (i=0; !(arg->ui & 1 << i); i++); -+ curtag = i + 1; -+ } -+ } else { -+ prevtag= curtag ^ prevtag; -+ curtag^= prevtag; -+ prevtag= curtag ^ prevtag; -+ } -+ lt[sellt]= lts[curtag]; -+ mfact = mfacts[curtag]; -+ if(showbar != showbars[curtag]) -+ togglebar(NULL); - clearurgent(); - arrange(); - } diff --git a/dwm.suckless.org/patches/historical/dwm-pertag-5.2.diff b/dwm.suckless.org/patches/historical/dwm-pertag-5.2.diff @@ -1,123 +0,0 @@ ---- dwm-5.2/dwm.c 2008-09-09 21:46:17.000000000 +0200 -+++ dwm-5.2-pertag/dwm.c 2008-10-12 23:53:30.000000000 +0200 -@@ -240,6 +240,11 @@ - /* configuration, allows nested code to access above variables */ - #include "config.h" - -+static int curtag = 1, prevtag = 1; -+static Layout *lts[LENGTH(tags) + 1]; -+static double mfacts[LENGTH(tags) + 1]; -+static Bool showbars[LENGTH(tags) + 1]; -+ - /* compile-time check if all tags fit into an unsigned int bit array. */ - struct NumTags { char limitexceeded[sizeof(unsigned int) * 8 < LENGTH(tags) ? -1 : 1]; }; - -@@ -1272,7 +1277,7 @@ - if(!arg || !arg->v || arg->v != lt[sellt]) - sellt ^= 1; - if(arg && arg->v) -- lt[sellt] = (Layout *)arg->v; -+ lt[sellt] = lts[curtag] = (Layout *)arg->v; - if(sel) - arrange(); - else -@@ -1289,7 +1294,7 @@ - f = arg->f < 1.0 ? arg->f + mfact : arg->f - 1.0; - if(f < 0.1 || f > 0.9) - return; -- mfact = f; -+ mfact = mfacts[curtag] = f; - arrange(); - } - -@@ -1337,12 +1342,27 @@ - if(!dc.font.set) - XSetFont(dpy, dc.gc, dc.font.xfont->fid); - -+ /* init mfacts */ -+ for(i=0; i < LENGTH(tags) + 1 ; i++) { -+ mfacts[i] = mfact; -+ } -+ -+ /* init layouts */ -+ for(i=0; i < LENGTH(tags) + 1; i++) { -+ lts[i] = &layouts[0]; -+ } -+ -+ - /* init bar */ - for(blw = i = 0; LENGTH(layouts) > 1 && i < LENGTH(layouts); i++) { - w = TEXTW(layouts[i].symbol); - blw = MAX(blw, w); - } - -+ for(i=0; i < LENGTH(tags) + 1; i++) { -+ showbars[i] = showbar; -+ } -+ - wa.override_redirect = 1; - wa.background_pixmap = ParentRelative; - wa.event_mask = ButtonPressMask|ExposureMask; -@@ -1457,7 +1477,7 @@ - - void - togglebar(const Arg *arg) { -- showbar = !showbar; -+ showbar = showbars[curtag] = !showbar; - updategeom(); - updatebar(); - arrange(); -@@ -1490,9 +1510,23 @@ - void - toggleview(const Arg *arg) { - unsigned int mask = tagset[seltags] ^ (arg->ui & TAGMASK); -+ unsigned int i; - - if(mask) { -+ if(mask == ~0) { -+ prevtag = curtag; -+ curtag = 0; -+ } -+ if(!(mask & 1 << (curtag - 1))) { -+ prevtag = curtag; -+ for (i=0; !(mask & 1 << i); i++); -+ curtag = i + 1; -+ } - tagset[seltags] = mask; -+ lt[sellt] = lts[curtag]; -+ mfact = mfacts[curtag]; -+ if (showbar != showbars[curtag]) -+ togglebar(NULL); - clearurgent(); - arrange(); - } -@@ -1661,11 +1695,28 @@ - - void - view(const Arg *arg) { -+ unsigned int i; - if((arg->ui & TAGMASK) == tagset[seltags]) - return; - seltags ^= 1; /* toggle sel tagset */ -- if(arg->ui & TAGMASK) -+ if(arg->ui & TAGMASK) { - tagset[seltags] = arg->ui & TAGMASK; -+ prevtag = curtag; -+ if(arg->ui == ~0) -+ curtag = 0; -+ else { -+ for (i=0; !(arg->ui & 1 << i); i++); -+ curtag = i + 1; -+ } -+ } else { -+ prevtag= curtag ^ prevtag; -+ curtag^= prevtag; -+ prevtag= curtag ^ prevtag; -+ } -+ lt[sellt]= lts[curtag]; -+ mfact = mfacts[curtag]; -+ if(showbar != showbars[curtag]) -+ togglebar(NULL); - clearurgent(); - arrange(); - } diff --git a/dwm.suckless.org/patches/historical/dwm-pertag-5.4.diff b/dwm.suckless.org/patches/historical/dwm-pertag-5.4.diff @@ -1,123 +0,0 @@ -diff -r add6eb26ebaa dwm.c ---- a/dwm.c Sat Dec 20 12:02:14 2008 +0000 -+++ b/dwm.c Sun Dec 21 18:39:14 2008 +0100 -@@ -240,6 +240,11 @@ static Window root, barwin; - static Window root, barwin; - /* configuration, allows nested code to access above variables */ - #include "config.h" -+ -+static int curtag = 1, prevtag = 1; -+static Layout *lts[LENGTH(tags) + 1]; -+static double mfacts[LENGTH(tags) + 1]; -+static Bool showbars[LENGTH(tags) + 1]; - - /* compile-time check if all tags fit into an unsigned int bit array. */ - struct NumTags { char limitexceeded[sizeof(unsigned int) * 8 < LENGTH(tags) ? -1 : 1]; }; -@@ -1244,7 +1249,7 @@ setlayout(const Arg *arg) { - if(!arg || !arg->v || arg->v != lt[sellt]) - sellt ^= 1; - if(arg && arg->v) -- lt[sellt] = (Layout *)arg->v; -+ lt[sellt] = lts[curtag] = (Layout *)arg->v; - if(sel) - arrange(); - else -@@ -1261,7 +1266,7 @@ setmfact(const Arg *arg) { - f = arg->f < 1.0 ? arg->f + mfact : arg->f - 1.0; - if(f < 0.1 || f > 0.9) - return; -- mfact = f; -+ mfact = mfacts[curtag] = f; - arrange(); - } - -@@ -1309,11 +1314,26 @@ setup(void) { - if(!dc.font.set) - XSetFont(dpy, dc.gc, dc.font.xfont->fid); - -+ /* init mfacts */ -+ for(i=0; i < LENGTH(tags) + 1 ; i++) { -+ mfacts[i] = mfact; -+ } -+ -+ /* init layouts */ -+ for(i=0; i < LENGTH(tags) + 1; i++) { -+ lts[i] = &layouts[0]; -+ } -+ -+ - /* init bar */ - for(blw = i = 0; LENGTH(layouts) > 1 && i < LENGTH(layouts); i++) { - w = TEXTW(layouts[i].symbol); - blw = MAX(blw, w); - } -+ -+ for(i=0; i < LENGTH(tags) + 1; i++) { -+ showbars[i] = showbar; -+ } - - wa.override_redirect = 1; - wa.background_pixmap = ParentRelative; -@@ -1434,7 +1454,7 @@ tile(void) { - - void - togglebar(const Arg *arg) { -- showbar = !showbar; -+ showbar = showbars[curtag] = !showbar; - update