Browse Source

Starting switching to suckless utilities

main
Yiğit Çolakoğlu 4 years ago
parent
commit
e5f281e6be
353 changed files with 21606 additions and 6930 deletions
  1. +3
    -0
      .gitmodules
  2. +17
    -6
      chroot/AUR.txt
  3. +57
    -2
      chroot/nonAUR.txt
  4. +2
    -2
      gtk/gtk-3.0/settings.ini
  5. +1
    -0
      gtk/themes/material-ocean
  6. +2
    -1
      install.sh
  7. +0
    -149
      misc/rofi/config.rasi
  8. +0
    -10
      misc/rofi/music_menu
  9. +0
    -109
      misc/rofi/sidebar-mod.rasi
  10. +0
    -149
      misc/rofi/themes/denvit.rasi
  11. +0
    -44
      misc/rofi/themes/dmenu.rasi
  12. +290
    -0
      scripts/dmenu-bluetooth
  13. +1
    -1
      scripts/dmenu-logout
  14. +5
    -0
      scripts/edit_screen.sh
  15. +7
    -0
      scripts/layoutmenu.sh
  16. +874
    -0
      scripts/networkmanager_dmenu
  17. +1
    -1
      scripts/status-bar/arch
  18. +0
    -17
      scripts/status-bar/arch-block
  19. +10
    -10
      scripts/status-bar/battery
  20. +0
    -49
      scripts/status-bar/battery-blocks
  21. +0
    -14
      scripts/status-bar/capslock
  22. +0
    -12
      scripts/status-bar/clima
  23. +0
    -27
      scripts/status-bar/clima-icon
  24. +1
    -1
      scripts/status-bar/cpu-temp
  25. +0
    -9
      scripts/status-bar/fecha
  26. +0
    -11
      scripts/status-bar/fecha-block
  27. +0
    -10
      scripts/status-bar/listener
  28. +19
    -0
      scripts/status-bar/network
  29. +0
    -9
      scripts/status-bar/red
  30. +0
    -14
      scripts/status-bar/red-texto
  31. +0
    -3
      scripts/status-bar/sep1
  32. +0
    -14
      scripts/status-bar/spotify-bar
  33. +0
    -17
      scripts/status-bar/spotify-block
  34. +0
    -122
      scripts/status-bar/spotify_status.py
  35. +9
    -0
      scripts/status-bar/time
  36. +0
    -24
      scripts/status-bar/volume
  37. +0
    -29
      scripts/status-bar/volume-block
  38. +31
    -0
      scripts/status-bar/weather
  39. +76
    -0
      scripts/surf_linkselect.sh
  40. +10
    -0
      suckless/clipmenu/.travis.yml
  41. +5
    -0
      suckless/clipmenu/LICENSE
  42. +12
    -0
      suckless/clipmenu/Makefile
  43. +100
    -0
      suckless/clipmenu/README.md
  44. +52
    -0
      suckless/clipmenu/clipctl
  45. +93
    -0
      suckless/clipmenu/clipdel
  46. +28
    -0
      suckless/clipmenu/clipfsck
  47. +71
    -0
      suckless/clipmenu/clipmenu
  48. +253
    -0
      suckless/clipmenu/clipmenud
  49. +21
    -0
      suckless/clipmenu/init/clipmenud.service
  50. +93
    -0
      suckless/clipmenu/tests/test-clipmenu
  51. +87
    -0
      suckless/clipmenu/tests/test-perf
  52. +0
    -245
      suckless/dwm/,
  53. +5
    -0
      suckless/dwm/.gitignore
  54. +23
    -1
      suckless/dwm/Makefile
  55. +0
    -50
      suckless/dwm/Makefile.bak
  56. +48
    -0
      suckless/dwm/README
  57. +0
    -32
      suckless/dwm/README.es.org
  58. +690
    -0
      suckless/dwm/README.md
  59. +0
    -35
      suckless/dwm/README.org
  60. +33
    -0
      suckless/dwm/config.bak
  61. +27
    -236
      suckless/dwm/config.h
  62. +24
    -2
      suckless/dwm/config.mk
  63. +259
    -8
      suckless/dwm/drw.c
  64. +51
    -6
      suckless/dwm/drw.h
  65. +0
    -727
      suckless/dwm/dwm-systray-20200914-61bb8b2.diff
  66. +0
    -9
      suckless/dwm/dwm.1
  67. +2712
    -803
      suckless/dwm/dwm.c
  68. +0
    -28
      suckless/dwm/dwm_config_pulseaudio.h
  69. +0
    -66
      suckless/dwm/fibonacci.c
  70. +345
    -0
      suckless/dwm/flexipatch-finalizer.sh
  71. +132
    -0
      suckless/dwm/keybind.h
  72. +0
    -27
      suckless/dwm/layouts.c
  73. +24
    -0
      suckless/dwm/patch/aspectresize.c
  74. +1
    -0
      suckless/dwm/patch/aspectresize.h
  75. +42
    -0
      suckless/dwm/patch/attachx.c
  76. +1
    -0
      suckless/dwm/patch/attachx.h
  77. +83
    -0
      suckless/dwm/patch/autostart.c
  78. +1
    -0
      suckless/dwm/patch/autostart.h
  79. +42
    -0
      suckless/dwm/patch/bar_alpha.c
  80. +3
    -0
      suckless/dwm/patch/bar_alpha.h
  81. +6
    -0
      suckless/dwm/patch/bar_alternativetags.c
  82. +1
    -0
      suckless/dwm/patch/bar_alternativetags.h
  83. +82
    -0
      suckless/dwm/patch/bar_anybar.c
  84. +4
    -0
      suckless/dwm/patch/bar_anybar.h
  85. +79
    -0
      suckless/dwm/patch/bar_awesomebar.c
  86. +3
    -0
      suckless/dwm/patch/bar_awesomebar.h
  87. +31
    -0
      suckless/dwm/patch/bar_dwmblocks.c
  88. +2
    -0
      suckless/dwm/patch/bar_dwmblocks.h
  89. +52
    -0
      suckless/dwm/patch/bar_ewmhtags.c
  90. +6
    -0
      suckless/dwm/patch/bar_ewmhtags.h
  91. +70
    -0
      suckless/dwm/patch/bar_fancybar.c
  92. +3
    -0
      suckless/dwm/patch/bar_fancybar.h
  93. +436
    -0
      suckless/dwm/patch/bar_flexwintitle.c
  94. +10
    -0
      suckless/dwm/patch/bar_flexwintitle.h
  95. +37
    -0
      suckless/dwm/patch/bar_holdbar.c
  96. +2
    -0
      suckless/dwm/patch/bar_holdbar.h
  97. +110
    -0
      suckless/dwm/patch/bar_indicators.c
  98. +20
    -0
      suckless/dwm/patch/bar_indicators.h
  99. +18
    -0
      suckless/dwm/patch/bar_layoutmenu.c
  100. +1
    -0
      suckless/dwm/patch/bar_layoutmenu.h

+ 3
- 0
.gitmodules View File

@ -0,0 +1,3 @@
[submodule "gtk/themes/material-ocean"]
path = gtk/themes/material-ocean
url = https://github.com/material-ocean/Gtk-Theme.git

+ 17
- 6
chroot/AUR.txt View File

@ -1,37 +1,48 @@
activitywatch-bin
aic94xx-firmware
antibody
betterdiscord
betterlockscreen
capt-src
checkupdates+aur
checkupdates-aur
cordless-bin
direnv
gconf
ghidra-darcula
git-secret
gitkraken
gksu
glxinfo
google-cloud-sdk
i3lock-color
ifuse
jetbrains-toolbox
libgksu
ly
mailspring
mconnect-git
nerd-fonts-hack
ngrok
numix-icon-theme-git
perl-checkupdates-aur
perl-www-aur
plymouth-git
plymouth-theme-cubes-git
plymouth-theme-darth-vader-git
postman-bin
qt5-styleplugins
rofi-bluetooth-git
rofi-dmenu
ruby-erubis
ruby-xdg
spicetify-cli
spotify
spotify-tui
sublime-text-3
surf
terminal_dimensions-git
termpdf-git
ttf-material-design-icons
ttf-symbola
vue-cli
wd719x-firmware
whatsapp-nativefier-dark
yay
xmenu
yaft
zoom

+ 57
- 2
chroot/nonAUR.txt View File

@ -1,3 +1,4 @@
ack
arandr
arc-gtk-theme
autoconf
@ -7,13 +8,18 @@ base
bat
binutils
bison
blackarch-keyring
blueman
bluez-utils
borgmatic
calibre
chrony
clipmenu
cmake
code
conky
ctags
cups
cups-pdf
discord
dunst
efibootmgr
@ -30,6 +36,7 @@ gcc
gdm
gettext
git
gksu
gnome-bluetooth
gnome-keyring
gparted
@ -38,17 +45,24 @@ grep
groff
grub
gvfs-afc
gvim
gzip
hexchat
htop
inetutils
intel-ucode
ipython
jdk11-openjdk
jq
jre11-openjdk
keepass
kitty
libgnome-keyring
libreoffice-fresh
libtool
lightdm
lightdm-gtk-greeter
lighttpd
linux
linux-firmware
linux-headers
@ -59,10 +73,13 @@ mariadb
mlocate
mysql-workbench
nemo
neofetch
neovim
net-tools
networkmanager
nextcloud-client
ngrok
noto-fonts
noto-fonts-emoji
npm
ntfs-3g
@ -71,32 +88,68 @@ pacman
pamixer
patch
pavucontrol
perl-image-exiftool
php
picom
pkgconf
playerctl
polkit-gnome
pulseaudio
pulseaudio-alsa
pulseaudio-bluetooth
python-pdftotext
python-pip
python-pylint
python-pynvim
python2
qt5ct
ranger
rclone
redis
refind
ripgrep
rofi
rsync
sbsigntools
scrot
sed
shotwell
sonic-visualiser
stegoveritas
sudo
sxiv
sysbench
system-config-printer
tcsh
telegram-desktop
termite
texinfo
texlive-bibtexextra
texlive-core
texlive-fontsextra
texlive-formatsextra
texlive-games
texlive-humanities
texlive-latexextra
texlive-music
texlive-pictures
texlive-pstricks
texlive-publishers
texlive-science
thunar
thunderbird
thunderbird-extension-enigmail
tmate
tmux
tor
torbrowser-launcher
tree
ttf-dejavu
ttf-inconsolata
ttf-joypixels
ttf-linux-libertine
unzip
vi
vim
virtualbox
virtualbox-host-dkms
vlc
@ -156,6 +209,8 @@ xorg-xwininfo
xorg-xwud
xss-lock
xterm
yay
youtube-dl
zathura
zathura-pdf-mupdf
zsh

+ 2
- 2
gtk/gtk-3.0/settings.ini View File

@ -1,6 +1,6 @@
[Settings]
gtk-theme-name=Arc-Dark
gtk-icon-theme-name=Numix
gtk-theme-name=material-ocean
gtk-icon-theme-name=Tela-orange-dark
gtk-font-name=Cantarell 11
gtk-cursor-theme-name=Adwaita
gtk-cursor-theme-size=0


+ 1
- 0
gtk/themes/material-ocean

@ -0,0 +1 @@
Subproject commit aaa7a1d92ce53ecddeab35faaf4d0648ae7f4e93

+ 2
- 1
install.sh View File

@ -5,13 +5,13 @@ ln -s ~/.dotfiles/vim/vimrc ~/.vimrc
ln -s ~/.dotfiles/vim/vim ~/.vim
# GTK
ln -s ~/.dotfiles/gtk/themes ~/.themes
ln -s ~/.dotfiles/gtk/gtk-2.0 ~/.config/gtk-2.0
ln -s ~/.dotfiles/gtk/gtk-3.0 ~/.config/gtk-3.0
ln -s ~/.dotfiles/gtk/gtk-4.0 ~/.config/gtk-4.0
# Miscellaneous
ln -s ~/.dotfiles/misc/dunst ~/.config/dunst
ln -s ~/.dotfiles/misc/rofi ~/.config/rofi
ln -s ~/.dotfiles/misc/zathura ~/.config/zathura
ln -s ~/.dotfiles/misc/termite/ ~/.config/termite
ln -s ~/.dotfiles/misc/systemd ~/.config/systemd
@ -29,6 +29,7 @@ ln -s ~/.dotfiles/tmux/tmux.conf ~/.tmux.conf
# Xorg
ln -s ~/.dotfiles/xorg/xinitrc ~/.xinitrc
ln -s ~/.dotfiles/xorg/xmodmap ~/.xmodmap
ln -s ~/.dotfiles/xorg/Xresources ~/.Xresources
# Zsh
ln -s ~/.dotfiles/zsh/antibody ~/.config/antibody


+ 0
- 149
misc/rofi/config.rasi View File

@ -1,149 +0,0 @@
configuration {
modi: "window,run,ssh,drun";
/* width: 50;*/
lines: 15;
/* columns: 1;*/
font: "Cascadia Code 12";
/* bw: 1;*/
/* location: 0;*/
/* padding: 5;*/
/* yoffset: 0;*/
/* xoffset: 0;*/
/* fixed-num-lines: true;*/
/* show-icons: false;*/
/* terminal: "rofi-sensible-terminal";*/
/* ssh-client: "ssh";*/
/* ssh-command: "{terminal} -e {ssh-client} {host} [-p {port}]";*/
/* run-command: "{cmd}";*/
/* run-list-command: "";*/
/* run-shell-command: "{terminal} -e {cmd}";*/
/* window-command: "wmctrl -i -R {window}";*/
/* window-match-fields: "all";*/
/* icon-theme: ;*/
/* drun-match-fields: "name,generic,exec,categories";*/
/* drun-show-actions: false;*/
/* drun-display-format: "{name} [<span weight='light' size='small'><i>({generic})</i></span>]";*/
/* disable-history: false;*/
/* ignored-prefixes: "";*/
/* sort: false;*/
/* sorting-method: ;*/
/* case-sensitive: false;*/
/* cycle: true;*/
/* sidebar-mode: false;*/
/* eh: 1;*/
/* auto-select: false;*/
/* parse-hosts: false;*/
/* parse-known-hosts: true;*/
/* combi-modi: "window,run";*/
/* matching: "normal";*/
/* tokenize: true;*/
/* m: "-5";*/
/* line-margin: 2;*/
/* line-padding: 1;*/
/* filter: ;*/
/* separator-style: "dash";*/
/* hide-scrollbar: false;*/
/* fullscreen: false;*/
/* fake-transparency: false;*/
/* dpi: -1;*/
/* threads: 0;*/
/* scrollbar-width: 8;*/
/* scroll-method: 0;*/
/* fake-background: "screenshot";*/
/* window-format: "{w} {c} {t}";*/
/* click-to-exit: true;*/
/* show-match: true;*/
/* theme: ;*/
/* color-normal: ;*/
/* color-urgent: ;*/
/* color-active: ;*/
/* color-window: ;*/
/* max-history-size: 25;*/
/* combi-hide-mode-prefix: false;*/
/* matching-negate-char: '-' /* unsupported */;*/
/* cache-dir: ;*/
/* pid: "/run/user/1000/rofi.pid";*/
/* display-window: ;*/
/* display-windowcd: ;*/
/* display-run: ;*/
/* display-ssh: ;*/
/* display-drun: ;*/
/* display-combi: ;*/
/* display-keys: ;*/
/* kb-primary-paste: "Control+V,Shift+Insert";*/
/* kb-secondary-paste: "Control+v,Insert";*/
/* kb-clear-line: "Control+w";*/
/* kb-move-front: "Control+a";*/
/* kb-move-end: "Control+e";*/
/* kb-move-word-back: "Alt+b,Control+Left";*/
/* kb-move-word-forward: "Alt+f,Control+Right";*/
/* kb-move-char-back: "Left,Control+b";*/
/* kb-move-char-forward: "Right,Control+f";*/
/* kb-remove-word-back: "Control+Alt+h,Control+BackSpace";*/
/* kb-remove-word-forward: "Control+Alt+d";*/
/* kb-remove-char-forward: "Delete,Control+d";*/
/* kb-remove-char-back: "BackSpace,Shift+BackSpace,Control+h";*/
/* kb-remove-to-eol: "Control+k";*/
/* kb-remove-to-sol: "Control+u";*/
/* kb-accept-entry: "Control+j,Control+m,Return,KP_Enter";*/
/* kb-accept-custom: "Control+Return";*/
/* kb-accept-alt: "Shift+Return";*/
/* kb-delete-entry: "Shift+Delete";*/
/* kb-mode-next: "Shift+Right,Control+Tab";*/
/* kb-mode-previous: "Shift+Left,Control+ISO_Left_Tab";*/
/* kb-row-left: "Control+Page_Up";*/
/* kb-row-right: "Control+Page_Down";*/
/* kb-row-up: "Up,Control+p,ISO_Left_Tab";*/
/* kb-row-down: "Down,Control+n";*/
/* kb-row-tab: "Tab";*/
/* kb-page-prev: "Page_Up";*/
/* kb-page-next: "Page_Down";*/
/* kb-row-first: "Home,KP_Home";*/
/* kb-row-last: "End,KP_End";*/
/* kb-row-select: "Control+space";*/
/* kb-screenshot: "Alt+S";*/
/* kb-ellipsize: "Alt+period";*/
/* kb-toggle-case-sensitivity: "grave,dead_grave";*/
/* kb-toggle-sort: "Alt+grave";*/
/* kb-cancel: "Escape,Control+g,Control+bracketleft";*/
/* kb-custom-1: "Alt+1";*/
/* kb-custom-2: "Alt+2";*/
/* kb-custom-3: "Alt+3";*/
/* kb-custom-4: "Alt+4";*/
/* kb-custom-5: "Alt+5";*/
/* kb-custom-6: "Alt+6";*/
/* kb-custom-7: "Alt+7";*/
/* kb-custom-8: "Alt+8";*/
/* kb-custom-9: "Alt+9";*/
/* kb-custom-10: "Alt+0";*/
/* kb-custom-11: "Alt+exclam";*/
/* kb-custom-12: "Alt+at";*/
/* kb-custom-13: "Alt+numbersign";*/
/* kb-custom-14: "Alt+dollar";*/
/* kb-custom-15: "Alt+percent";*/
/* kb-custom-16: "Alt+dead_circumflex";*/
/* kb-custom-17: "Alt+ampersand";*/
/* kb-custom-18: "Alt+asterisk";*/
/* kb-custom-19: "Alt+parenleft";*/
/* kb-select-1: "Super+1";*/
/* kb-select-2: "Super+2";*/
/* kb-select-3: "Super+3";*/
/* kb-select-4: "Super+4";*/
/* kb-select-5: "Super+5";*/
/* kb-select-6: "Super+6";*/
/* kb-select-7: "Super+7";*/
/* kb-select-8: "Super+8";*/
/* kb-select-9: "Super+9";*/
/* kb-select-10: "Super+0";*/
/* ml-row-left: "ScrollLeft";*/
/* ml-row-right: "ScrollRight";*/
/* ml-row-up: "ScrollUp";*/
/* ml-row-down: "ScrollDown";*/
/* me-select-entry: "MousePrimary";*/
/* me-accept-entry: "MouseDPrimary";*/
/* me-accept-custom: "Control+MouseDPrimary";*/
}
@import "/home/yigit/.config/rofi/themes/dmenu.rasi"
/* vim:ft=css

+ 0
- 10
misc/rofi/music_menu View File

@ -1,10 +0,0 @@
action=$(echo '
' | rofi -dmenu -theme music_actions )
if [ $action = '' ]
then
playerctl previous &
elif [ $action = '' ]
then
playerctl next &
fi

+ 0
- 109
misc/rofi/sidebar-mod.rasi View File

@ -1,109 +0,0 @@
/**
* User: qball
* Copyright: Dave Davenport
*/
* {
text-color: #f4f2f0;
background-color: rgba(0,0,0,0);
dark: #2c2541;
// Black
black: #3d335c;
lightblack: #483c6c;
//
// Red
red: #cd5c5c;
lightred: #cc5533;
//
// Green
green: #86af80;
lightgreen: #88cc22;
//
// Yellow
yellow: #e8ae5b;
lightyellow: #ffa75d;
//
// Blue
blue: #6495ed;
lightblue: #87ceeb;
//
// Magenta
magenta: #deb887;
lightmagenta: #996600;
//
// Cyan
cyan: #b0c4de;
lightcyan: #b0c4de;
//
// White
white: #bbaa99;
lightwhite: #ddccbb;
//
// Bold, Italic, Underline
highlight: bold #ffffff;
}
#window {
height: 50%;
width: 15em;
location: north east;
anchor: north east;
border: 0px 0px 0px 0px;
x-offset: -30px;
y-offset: 39px;
text-color: @lightwhite;
border-radius: 0px 0px 19px 19px;
}
#mode-switcher {
border: 2px 0px 0px 0px;
background-color: @lightblack;
padding: 4px;
}
#button selected {
border-color: @lightgreen;
text-color: @lightgreen;
}
#inputbar {
background-color: #2c2541;
text-color: @lightgreen;
padding: 4px 4px 4px 4px;
border: 0px 0px 0px 0px;
}
#mainbox {
expand: true;
background-color: #1c1c1cee;
spacing: 1em;
}
#listview {
padding: 0em 1em 0em 1em;
dynamic: false;
lines: 0;
}
#prompt {
margin: 0px 6px 0px 0px;
}
#element selected normal {
background-color: #da0f7a;
}
#element normal active {
text-color: @lightblue;
}
#element normal urgent {
text-color: @lightred;
}
#element alternate normal {
}
#element alternate active {
text-color: @lightblue;
}
#element alternate urgent {
text-color: @lightred;
}
#element selected active {
background-color: @lightblue;
text-color: @dark;
}
#element selected urgent {
background-color: @lightred;
text-color: @dark;
}

+ 0
- 149
misc/rofi/themes/denvit.rasi View File

@ -1,149 +0,0 @@
/* vim:ft=css */
/************************************************
* ROFI Color theme
* User: leofa
* Copyright: 2017 leofa
***********************************************/
* {
selected-normal-foreground: rgba ( 249, 249, 249, 100 % );
foreground: rgba ( 248, 248, 242, 100 % );
normal-foreground: @foreground;
alternate-normal-background: rgba ( 35, 49, 63, 95%);
red: rgba ( 189, 147, 249, 100 % );
selected-urgent-foreground: rgba ( 249, 249, 249, 100 % );
blue: rgba ( 38, 139, 210, 100 % );
urgent-foreground: rgba ( 204, 102, 102, 100 % );
alternate-urgent-background: rgba ( 75, 81, 96, 90 % );
active-foreground: rgba ( 101, 172, 255, 100 % );
lightbg: rgba ( 238, 232, 213, 100 % );
selected-active-foreground: rgba ( 249, 249, 249, 100 % );
alternate-active-background: rgba ( 52,73,94, 60%);
background: rgba ( 189, 147, 249, 95 % );
alternate-normal-foreground: @foreground;
normal-background: @background;
lightfg: rgba ( 88, 104, 117, 100 % );
selected-normal-background: rgba ( 189, 147, 249, 100 % );
border-color: rgba ( 124, 131, 137, 100 % );
spacing: 2;
separatorcolor: rgba ( 29, 31, 33, 100 % );
urgent-background: rgba ( 29, 31, 33, 17 % );
selected-urgent-background: rgba ( 189, 147, 249, 100 % );
alternate-urgent-foreground: @urgent-foreground;
background-color: rgba ( 0, 0, 0, 0 % );
alternate-active-foreground: @active-foreground;
active-background: rgba ( 29, 31, 33, 17 % );
selected-active-background: rgba ( 189, 147, 249, 100 % );
}
#window {
background-color: @background;
border: 1;
padding: 5;
}
#mainbox {
border: 0;
padding: 0;
}
#message {
border: 2px 0px 0px ;
border-color: @separatorcolor;
padding: 1px ;
}
#textbox {
text-color: @foreground;
}
#listview {
fixed-height: 0;
border: 0px 0px 0px ;
border-color: @separatorcolor;
spacing: 2px ;
scrollbar: true;
padding: 2px 0px 0px ;
}
#element {
border: 0;
padding: 1px;
}
#element.normal.normal {
background-color: @normal-background;
text-color: @normal-foreground;
}
#element.normal.urgent {
background-color: @urgent-background;
text-color: @urgent-foreground;
}
#element.normal.active {
background-color: @active-background;
text-color: @active-foreground;
}
#element.selected.normal {
background-color: @selected-normal-background;
text-color: @selected-normal-foreground;
}
#element.selected.urgent {
background-color: @selected-urgent-background;
text-color: @selected-urgent-foreground;
}
#element.selected.active {
background-color: @selected-active-background;
text-color: @selected-active-foreground;
}
#element.alternate.normal {
background-color: @alternate-normal-background;
text-color: @alternate-normal-foreground;
}
#element.alternate.urgent {
background-color: @alternate-urgent-background;
text-color: @alternate-urgent-foreground;
}
#element.alternate.active {
background-color: @alternate-active-background;
text-color: @alternate-active-foreground;
}
#scrollbar {
width: 4px ;
border: 0;
handle-color: @normal-foreground;
handle-width: 8px ;
padding: 0;
}
#sidebar {
border: 0px 0px 0px;
padding: 5px 0 0;
border-color: @separatorcolor;
}
#button {
spacing: 0;
text-color: @normal-foreground;
}
#button.selected {
background-color: @selected-normal-background;
text-color: @selected-normal-foreground;
}
#inputbar {
spacing: 0;
text-color: @normal-foreground;
padding: 1px ;
}
#case-indicator {
spacing: 0;
text-color: @normal-foreground;
}
#entry {
spacing: 0;
text-color: @normal-foreground;
}
#prompt {
spacing: 0;
text-color: @normal-foreground;
}
#inputbar {
children: [ prompt,textbox-prompt-colon,entry,case-indicator ];
}
#textbox-prompt-colon {
expand: false;
str: ":";
margin: 0px 0.3em 0em 0em ;
text-color: @normal-foreground;
}

+ 0
- 44
misc/rofi/themes/dmenu.rasi View File

@ -1,44 +0,0 @@
/**
* ROFI Color theme
* User: Qball
* Copyright: Dave Davenport
*/
* {
background-color: rgba(40, 42, 54, 1);
border-color: rgba(248, 248, 242, 1);
text-color: rgba(248, 248, 242, 1);
font: "Hack Nerd Font 10";
}
window {
anchor: north;
location: north;
width: 100%;
padding: 6px;
children: [ horibox ];
}
horibox {
orientation: horizontal;
children: [ prompt, entry, listview ];
}
listview {
layout: horizontal;
spacing: 5px;
lines: 100;
}
entry {
expand: false;
width: 10em;
}
element {
padding: 0px 2px;
}
element selected {
background-color: rgba(189, 147, 249, 1);
}
/* vim:ft=css

+ 290
- 0
scripts/dmenu-bluetooth View File

@ -0,0 +1,290 @@
#!/usr/bin/env bash
# _ _ _ _ _ _
# __| |_ __ ___ ___ _ __ _ _ | |__ | |_ _ ___| |_ ___ ___ | |_ | |__
# / _` | '_ ` _ \ / _ \ '_ \| | | |_____| '_ \| | | | |/ _ \ __/ _ \ / _ \| __|| '_ \
# | (_| | | | | | | __/ | | | |_| |_____| |_) | | |_| | __/ || (_) | (_) | |_ | | | |
# \__,_|_| |_| |_|\___|_| |_|\__,_| |_.__/|_|\__,_|\___|\__\___/ \___/ \__||_| |_|
#
# Author: Nick Clyde (clydedroid)
# dmenu support by: Layerex
#
# A script that generates a dmenu menu that uses bluetoothctl to
# connect to bluetooth devices and display status info.
#
# Inspired by networkmanager-dmenu (https://github.com/firecat53/networkmanager-dmenu)
# Thanks to x70b1 (https://github.com/polybar/polybar-scripts/tree/master/polybar-scripts/system-bluetooth-bluetoothctl)
#
# Depends on:
# Arch repositories: dmenu, bluez-utils (contains bluetoothctl)
# Checks if bluetooth controller is powered on
power_on() {
if bluetoothctl show | grep -q "Powered: yes"; then
return 0
else
return 1
fi
}
# Toggles power state
toggle_power() {
if power_on; then
bluetoothctl power off
else
bluetoothctl power on
fi
}
# Checks if controller is scanning for new devices
scan_on() {
if bluetoothctl show | grep -q "Discovering: yes"; then
echo "Scan: on"
return 0
else
echo "Scan: off"
return 1
fi
}
# Toggles scanning state
toggle_scan() {
if scan_on; then
kill $(pgrep -f "bluetoothctl scan on")
bluetoothctl scan off
else
bluetoothctl scan on &
fi
}
# Checks if controller is able to pair to devices
pairable_on() {
if bluetoothctl show | grep -q "Pairable: yes"; then
echo "Pairable: on"
return 0
else
echo "Pairable: off"
return 1
fi
}
# Toggles pairable state
toggle_pairable() {
if pairable_on; then
bluetoothctl pairable off
else
bluetoothctl pairable on
fi
}
# Checks if controller is discoverable by other devices
discoverable_on() {
if bluetoothctl show | grep -q "Discoverable: yes"; then
echo "Discoverable: on"
return 0
else
echo "Discoverable: off"
return 1
fi
}
# Toggles discoverable state
toggle_discoverable() {
if discoverable_on; then
bluetoothctl discoverable off
else
bluetoothctl discoverable on
fi
}
# Checks if a device is connected
device_connected() {
device_info=$(bluetoothctl info "$1")
if echo "$device_info" | grep -q "Connected: yes"; then
return 0
else
return 1
fi
}
# Toggles device connection
toggle_connection() {
if device_connected $1; then
bluetoothctl disconnect $1
else
bluetoothctl connect $1
fi
}
# Checks if a device is paired
device_paired() {
device_info=$(bluetoothctl info "$1")
if echo "$device_info" | grep -q "Paired: yes"; then
echo "Paired: yes"
return 0
else
echo "Paired: no"
return 1
fi
}
# Toggles device paired state
toggle_paired() {
if device_paired $1; then
bluetoothctl remove $1
else
bluetoothctl pair $1
fi
}
# Checks if a device is trusted
device_trusted() {
device_info=$(bluetoothctl info "$1")
if echo "$device_info" | grep -q "Trusted: yes"; then
echo "Trusted: yes"
return 0
else
echo "Trusted: no"
return 1
fi
}
# Toggles device connection
toggle_trust() {
if device_trusted $1; then
bluetoothctl untrust $1
else
bluetoothctl trust $1
fi
}
# Prints a short string with the current bluetooth status
# Useful for status bars like polybar, etc.
print_status() {
if power_on; then
printf ''
mapfile -t paired_devices < <(bluetoothctl paired-devices | grep Device | cut -d ' ' -f 2)
counter=0
for device in "${paired_devices[@]}"; do
if device_connected $device; then
device_alias=$(bluetoothctl info $device | grep "Alias" | cut -d ' ' -f 2-)
if [ $counter -gt 0 ]; then
printf ", %s" "$device_alias"
else
printf " %s" "$device_alias"
fi
((counter++))
fi
done
if [ $counter -eq 0 ]; then
printf " On"
fi
else
echo " Off"
fi
}
# A submenu for a specific device that allows connecting, pairing, and trusting
device_menu() {
device=$1
# Get device name and mac address
device_name=$(echo $device | cut -d ' ' -f 3-)
mac=$(echo $device | cut -d ' ' -f 2)
# Build options
if device_connected $mac; then
connected="Connected: yes"
else
connected="Connected: no"
fi
paired=$(device_paired $mac)
trusted=$(device_trusted $mac)
options="$connected\n$paired\n$trusted"
# Open dmenu menu, read chosen option
chosen="$(echo -e "$options" | $dmenu_command "$device_name")"
# Match chosen option to command
case $chosen in
"")
echo "No option chosen."
;;
$connected)
toggle_connection $mac
;;
$paired)
toggle_paired $mac
;;
$trusted)
toggle_trust $mac
;;
esac
}
# Opens a dmenu menu with current bluetooth status and options to connect
show_menu() {
# Get menu options
if power_on; then
power="Power: on"
# Human-readable names of devices, one per line
# If scan is off, will only list paired devices
devices=$(bluetoothctl devices | grep Device | cut -d ' ' -f 3-)
# Get controller flags
scan=$(scan_on)
pairable=$(pairable_on)
discoverable=$(discoverable_on)
divider="---------"
# Options passed to dmenu
options="$devices\n$divider\n$power\n$scan\n$pairable\n$discoverable"
else
power="Power: off"
options="$power"
fi
# Open dmenu menu, read chosen option
chosen="$(echo -e "$options" | $dmenu_command "Bluetooth")"
# Match chosen option to command
case $chosen in
"" | $divider)
echo "No option chosen."
;;
$power)
toggle_power
;;
$scan)
toggle_scan
;;
$discoverable)
toggle_discoverable
;;
$pairable)
toggle_pairable
;;
*)
device=$(bluetoothctl devices | grep "$chosen")
# Open a submenu if a device is selected
if [[ $device ]]; then device_menu "$device"; fi
;;
esac
}
# dmenu command to pipe into, can add any options here
dmenu_command="dmenu -z 1900 -x 10 -y 10 -i -p"
case "$1" in
--status)
print_status
;;
*)
show_menu
;;
esac

+ 1
- 1
scripts/dmenu-logout View File

@ -26,7 +26,7 @@ logout() {
# Load dmenu config
# shellcheck source=/dev/null
[ -f "$HOME/.dmenurc" ] && . "$HOME/.dmenurc" || DMENU='dmenu -i'
[ -f "$HOME/.dmenurc" ] && . "$HOME/.dmenurc" || DMENU='dmenu -z 1900 -x 10 -y 10 -i'
# Menu items
items="logout


+ 5
- 0
scripts/edit_screen.sh View File

@ -0,0 +1,5 @@
#!/bin/sh
tmpfile=$(mktemp /tmp/st-edit.XXXXXX)
trap 'rm "$tmpfile"' 0 1 15
cat > "$tmpfile"
st -e "$EDITOR" "$tmpfile"

+ 7
- 0
scripts/layoutmenu.sh View File

@ -0,0 +1,7 @@
#!/bin/sh
cat <<EOF | xmenu
[]= Tiled Layout 0
><> Floating Layout 1
[M] Monocle Layout 2
EOF

+ 874
- 0
scripts/networkmanager_dmenu View File

@ -0,0 +1,874 @@
#!/usr/bin/env python3
# encoding:utf8
"""NetworkManager command line dmenu script.
To add new connections or enable/disable networking requires policykit
permissions setup per:
https://wiki.archlinux.org/index.php/NetworkManager#Set_up_PolicyKit_permissions
OR running the script as root
Add dmenu formatting options and default terminal if desired to
~/.config/networkmanager-dmenu/config.ini
"""
import pathlib
import struct
import configparser
import itertools
import locale
import os
from os.path import expanduser
import shlex
import sys
import uuid
from subprocess import Popen, PIPE
import gi
gi.require_version('NM', '1.0')
from gi.repository import GLib, NM # pylint: disable=wrong-import-position
ENV = os.environ.copy()
ENV['LC_ALL'] = 'C'
ENC = locale.getpreferredencoding()
CLIENT = NM.Client.new(None)
LOOP = GLib.MainLoop()
CONNS = CLIENT.get_connections()
CONF = configparser.ConfigParser()
CONF.read(expanduser("~/.config/networkmanager-dmenu/config.ini"))
def dmenu_cmd(num_lines, prompt="Networks", active_lines=None): # pylint: disable=too-many-branches
"""Parse config.ini if it exists and add options to the dmenu command
Args: args - num_lines: number of lines to display
prompt: prompt to show
Returns: command invocation (as a list of strings) for
dmenu -l <num_lines> -p <prompt> -i ...
"""
dmenu_command = "dmenu"
if not CONF.sections():
res = [dmenu_command, "-z", "1900", "-x", "10", "-y", "10", "-i", "-l", str(num_lines), "-p", str(prompt)]
res.extend(sys.argv[1:])
return res
if CONF.has_section('dmenu'):
args = CONF.items('dmenu')
args_dict = dict(args)
dmenu_args = []
if "dmenu_command" in args_dict:
command = shlex.split(args_dict["dmenu_command"])
dmenu_command = command[0]
dmenu_args = command[1:]
del args_dict["dmenu_command"]
if "p" in args_dict and prompt == "Networks":
prompt = args_dict["p"]
del args_dict["p"]
elif "p" in args_dict:
del args_dict["p"]
if "rofi" in dmenu_command:
lines = "-i -dmenu -lines"
# rofi doesn't support 0 length line, it requires at least -lines=1
# see https://github.com/DaveDavenport/rofi/issues/252
num_lines = num_lines or 1
else:
lines = "-i -l"
if "l" in args_dict:
# rofi doesn't support 0 length line, it requires at least -lines=1
# see https://github.com/DaveDavenport/rofi/issues/252
if "rofi" in dmenu_command:
args_dict['l'] = min(num_lines, int(args_dict['l'])) or 1
lines = "{} {}".format(lines, args_dict['l'])
del args_dict['l']
else:
lines = "{} {}".format(lines, num_lines)
if "pinentry" in args_dict:
del args_dict["pinentry"]
if "compact" in args_dict:
del args_dict["compact"]
if "wifi_chars" in args_dict:
del args_dict["wifi_chars"]
rofi_highlight = CONF.getboolean('dmenu', 'rofi_highlight', fallback=False)
if CONF.has_option('dmenu', 'rofi_highlight'):
del args_dict["rofi_highlight"]
if rofi_highlight is True and "rofi" in dmenu_command:
if active_lines:
dmenu_args.extend(["-a", ",".join([str(num)
for num in active_lines])])
if prompt == "Passphrase":
if CONF.has_section('dmenu_passphrase'):
args = CONF.items('dmenu_passphrase')
args_dict.update(args)
rofi_obscure = CONF.getboolean('dmenu_passphrase', 'rofi_obscure', fallback=True)
if CONF.has_option('dmenu_passphrase', 'rofi_obscure'):
del args_dict["rofi_obscure"]
if rofi_obscure is True and "rofi" in dmenu_command:
dmenu_args.extend(["-password"])
dmenu_password = CONF.getboolean('dmenu_passphrase', 'dmenu_password', fallback=False)
if CONF.has_option('dmenu_passphrase', 'dmenu_password'):
del args_dict["dmenu_password"]
if dmenu_password is True:
dmenu_args.extend(["-P"])
extras = (["-" + str(k), str(v)] for (k, v) in args_dict.items())
res = [dmenu_command, "-p", str(prompt)]
res.extend(dmenu_args)
res += list(itertools.chain.from_iterable(extras))
res[1:1] = lines.split()
res = list(filter(None, res)) # Remove empty list elements
res.extend(sys.argv[1:])
return res
def choose_adapter(client):
"""If there is more than one wifi adapter installed, ask which one to use
"""
devices = client.get_devices()
devices = [i for i in devices if i.get_device_type() == NM.DeviceType.WIFI]
if not devices: # pylint: disable=no-else-return
return None
elif len(devices) == 1:
return devices[0]
device_names = "\n".join([d.get_iface() for d in devices]).encode(ENC)
sel = Popen(dmenu_cmd(len(devices), "CHOOSE ADAPTER:"),
stdin=PIPE,
stdout=PIPE,
env=ENV).communicate(input=device_names)[0].decode(ENC)
if not sel.strip():
sys.exit()
devices = [i for i in devices if i.get_iface() == sel.strip()]
assert len(devices) == 1
return devices[0]
def is_modemmanager_installed():
"""Check if ModemManager is installed"""
with open(os.devnull) as devnull:
try:
Popen(["ModemManager"], stdout=devnull, stderr=devnull).communicate()
except OSError:
return False
return True
def bluetooth_get_enabled():
"""Check if bluetooth is enabled via rfkill.
Returns None if no bluetooth device was found.
"""
# See https://www.kernel.org/doc/Documentation/ABI/stable/sysfs-class-rfkill
for path in pathlib.Path('/sys/class/rfkill/').glob('rfkill*'):
if (path / 'type').read_text().strip() == 'bluetooth':
return (path / 'soft').read_text().strip() == '0'
return None
def create_other_actions(client):
"""Return list of other actions that can be taken
"""
networking_enabled = client.networking_get_enabled()
networking_action = "Disable" if networking_enabled else "Enable"
wifi_enabled = client.wireless_get_enabled()
wifi_action = "Disable" if wifi_enabled else "Enable"
bluetooth_enabled = bluetooth_get_enabled()
bluetooth_action = "Disable" if bluetooth_enabled else "Enable"
actions = [Action("{} Wifi".format(wifi_action), toggle_wifi,
not wifi_enabled),
Action("{} Networking".format(networking_action),
toggle_networking, not networking_enabled)]
if bluetooth_enabled is not None:
actions.append(Action("{} Bluetooth".format(bluetooth_action),
toggle_bluetooth, not bluetooth_enabled))
actions += [Action("Launch Connection Manager", launch_connection_editor),
Action("Delete a Connection", delete_connection)]
if wifi_enabled:
actions.append(Action("Rescan Wifi Networks", rescan_wifi))
return actions
def rescan_wifi():
"""
Rescan Wifi Access Points
"""
for dev in CLIENT.get_devices():
if gi.repository.NM.DeviceWifi == type(dev):
try:
dev.request_scan_async(None, rescan_cb, None)
LOOP.run()
except gi.repository.GLib.Error as err:
# Too frequent rescan error
notify("Wifi rescan failed", urgency="critical")
if not err.code == 6: # pylint: disable=no-member
raise err
def rescan_cb(dev, res, data):
"""Callback for rescan_wifi. Just for notifications
"""
if dev.request_scan_finish(res) is True:
notify("Wifi scan complete")
else:
notify("Wifi scan failed", urgency="critical")
LOOP.quit()
def ssid_to_utf8(nm_ap):
""" Convert binary ssid to utf-8 """
ssid = nm_ap.get_ssid()
if not ssid:
return ""
ret = NM.utils_ssid_to_utf8(ssid.get_data())
return ret
def prompt_saved(saved_cons):
"""Prompt for a saved connection."""
actions = create_saved_actions(saved_cons)
sel = get_selection(actions)
sel()
def ap_security(nm_ap):
"""Parse the security flags to return a string with 'WPA2', etc. """
flags = nm_ap.get_flags()
wpa_flags = nm_ap.get_wpa_flags()
rsn_flags = nm_ap.get_rsn_flags()
sec_str = ""
if ((flags & getattr(NM, '80211ApFlags').PRIVACY) and
(wpa_flags == 0) and (rsn_flags == 0)):
sec_str += " WEP"
if wpa_flags != 0:
sec_str += " WPA1"
if rsn_flags != 0:
sec_str += " WPA2"
if ((wpa_flags & getattr(NM, '80211ApSecurityFlags').KEY_MGMT_802_1X) or
(rsn_flags & getattr(NM, '80211ApSecurityFlags').KEY_MGMT_802_1X)):
sec_str += " 802.1X"
# If there is no security use "--"
if sec_str == "":
sec_str = "--"
return sec_str.lstrip()
class Action(): # pylint: disable=too-few-public-methods
"""Helper class to execute functions from a string variable"""
def __init__(self,
name,
func,
args=None,
active=False):
self.name = name
self.func = func
self.is_active = active
if args is None:
self.args = None
elif isinstance(args, list):
self.args = args
else:
self.args = [args]
def __str__(self):
return self.name
def __call__(self):
if self.args is None:
self.func()
else:
self.func(*self.args)
def process_ap(nm_ap, is_active, adapter):
"""Activate/Deactivate a connection and get password if required"""
if is_active:
CLIENT.deactivate_connection_async(nm_ap, None, deactivate_cb, nm_ap)
else:
conns_cur = [i for i in CONNS if
i.get_setting_wireless() is not None and
i.get_setting_wireless().get_mac_address() ==
adapter.get_permanent_hw_address()]
con = nm_ap.filter_connections(conns_cur)
if len(con) > 1:
raise ValueError("There are multiple connections possible")
if len(con) == 1:
CLIENT.activate_connection_async(con[0], adapter, nm_ap.get_path(),
None, activate_cb, nm_ap)
else:
if ap_security(nm_ap) != "--":
password = get_passphrase()
else:
password = ""
set_new_connection(nm_ap, password, adapter)
LOOP.run()
def activate_cb(dev, res, data):
"""Notification if activate connection completed successfully
"""
try:
conn = dev.activate_connection_finish(res)
except GLib.Error:
conn = None
if conn is not None:
notify("Activated {}".format(conn.get_id()))
else:
notify("Problem activating {}".format(data.get_id()),
urgency="critical")
LOOP.quit()
def deactivate_cb(dev, res, data):
"""Notification if deactivate connection completed successfully
"""
if dev.deactivate_connection_finish(res) is True:
notify("Deactivated {}".format(data.get_id()))
else:
notify("Problem deactivating {}".format(data.get_id()),
urgency="critical")
LOOP.quit()
def process_vpngsm(con, activate):
"""Activate/deactive VPN or GSM connections"""
if activate:
CLIENT.activate_connection_async(con, None, None,
None, activate_cb, con)
else:
CLIENT.deactivate_connection_async(con, None, deactivate_cb, con)
LOOP.run()
def create_ap_actions(aps, active_ap, active_connection, adapter): # pylint: disable=too-many-locals
"""For each AP in a list, create the string and its attached function
(activate/deactivate)
"""
active_ap_bssid = active_ap.get_bssid() if active_ap is not None else ""
names = [ssid_to_utf8(ap) for ap in aps]
max_len_name = max([len(name) for name in names]) if names else 0
secs = [ap_security(ap) for ap in aps]
max_len_sec = max([len(sec) for sec in secs]) if secs else 0
ap_actions = []
for nm_ap, name, sec in zip(aps, names, secs):
bars = NM.utils_wifi_strength_bars(nm_ap.get_strength())
wifi_chars = CONF.get("dmenu", "wifi_chars", fallback=False)
if wifi_chars:
bars = "".join([wifi_chars[i] for i, j in enumerate(bars) if j == '*'])
is_active = nm_ap.get_bssid() == active_ap_bssid
compact = CONF.getboolean("dmenu", "compact", fallback=False)
if compact:
action_name = u"{} {} {}".format(name, sec, bars)
else:
action_name = u"{:<{}s} {:<{}s} {}".format(name, max_len_name, sec,
max_len_sec, bars)
if is_active:
ap_actions.append(Action(action_name, process_ap,
[active_connection, True, adapter],
active=True))
else:
ap_actions.append(Action(action_name, process_ap,
[nm_ap, False, adapter]))
return ap_actions
def create_vpn_actions(vpns, active):
"""Create the list of strings to display with associated function
(activate/deactivate) for VPN connections.
"""
active_vpns = [i for i in active if i.get_vpn()]
return _create_vpngsm_actions(vpns, active_vpns, "VPN")
def create_wireguard_actions(wgs, active):
"""Create the list of strings to display with associated function
(activate/deactivate) for Wireguard connections.
"""
active_wgs = [i for i in active if i.get_connection_type() == "wireguard"]
return _create_vpngsm_actions(wgs, active_wgs, "Wireguard")
def create_eth_actions(eths, active):
"""Create the list of strings to display with associated function
(activate/deactivate) for Ethernet connections.
"""
active_eths = [i for i in active if 'ethernet' in i.get_connection_type()]
return _create_vpngsm_actions(eths, active_eths, "Eth")
def create_gsm_actions(gsms, active):
"""Create the list of strings to display with associated function
(activate/deactivate) GSM connections."""
active_gsms = [i for i in active if
i.get_connection() is not None and
i.get_connection().is_type(NM.SETTING_GSM_SETTING_NAME)]
return _create_vpngsm_actions(gsms, active_gsms, "GSM")
def create_blue_actions(blues, active):
"""Create the list of strings to display with associated function
(activate/deactivate) Bluetooth connections."""
active_blues = [i for i in active if
i.get_connection() is not None and
i.get_connection().is_type(NM.SETTING_BLUETOOTH_SETTING_NAME)]
return _create_vpngsm_actions(blues, active_blues, "Bluetooth")
def create_saved_actions(saved):
"""Create the list of strings to display with associated function
(activate/deactivate) for VPN connections.
"""
return _create_vpngsm_actions(saved, [], "SAVED")
def _create_vpngsm_actions(cons, active_cons, label):
active_con_ids = [a.get_id() for a in active_cons]
actions = []
for con in cons:
is_active = con.get_id() in active_con_ids
action_name = u"{}:{}".format(con.get_id(), label)
if is_active:
active_connection = [a for a in active_cons
if a.get_id() == con.get_id()]
if len(active_connection) != 1:
raise ValueError(u"Multiple active connections match"
" the connection: {}".format(con.get_id()))
active_connection = active_connection[0]
actions.append(Action(action_name, process_vpngsm,
[active_connection, False], active=True))
else:
actions.append(Action(action_name, process_vpngsm,
[con, True]))
return actions
def create_wwan_actions(client):
"""Create WWWAN actions
"""
wwan_enabled = client.wwan_get_enabled()
wwan_action = "Disable" if wwan_enabled else "Enable"
return [Action("{} WWAN".format(wwan_action), toggle_wwan, not wwan_enabled)]
def combine_actions(eths, aps, vpns, wgs, gsms, blues, wwan, others, saved):
"""Combine all given actions into a list of actions.
Args: args - eths: list of Actions
aps: list of Actions
vpns: list of Actions
gsms: list of Actions
blues: list of Actions
wwan: list of Actions
others: list of Actions
"""
compact = CONF.getboolean("dmenu", "compact", fallback=False)
empty_action = [Action('', None)] if not compact else []
all_actions = []
all_actions += eths + empty_action if eths else []
all_actions += aps + empty_action if aps else []
all_actions += vpns + empty_action if vpns else []
all_actions += wgs + empty_action if wgs else []
all_actions += gsms + empty_action if (gsms and wwan) else []
all_actions += blues + empty_action if blues else []
all_actions += wwan + empty_action if wwan else []
all_actions += others + empty_action if others else []
all_actions += saved + empty_action if saved else []
return all_actions
def get_selection(all_actions):
"""Spawn dmenu for selection and execute the associated action."""
rofi_highlight = CONF.getboolean('dmenu', 'rofi_highlight', fallback=False)
inp = []
if rofi_highlight is True:
inp = [str(action) for action in all_actions]
else:
inp = [('== ' if action.is_active else ' ') + str(action)
for action in all_actions]
active_lines = [index for index, action in enumerate(all_actions)
if action.is_active]
inp_bytes = "\n".join(inp).encode(ENC)
command = dmenu_cmd(len(inp), active_lines=active_lines)
sel = Popen(command, stdin=PIPE, stdout=PIPE,
env=ENV).communicate(input=inp_bytes)[0].decode(ENC)
if not sel.rstrip():
sys.exit()
if rofi_highlight is False:
action = [i for i in all_actions
if ((str(i).strip() == str(sel.strip())
and not i.is_active) or
('== ' + str(i) == str(sel.rstrip('\n'))
and i.is_active))]
else:
action = [i for i in all_actions if str(i).strip() == sel.strip()]
assert len(action) == 1, \
u"Selection was ambiguous: '{}'".format(str(sel.strip()))
return action[0]
def toggle_networking(enable):
"""Enable/disable networking
Args: enable - boolean
"""
toggle = GLib.Variant.new_tuple(GLib.Variant.new_boolean(enable))
try:
CLIENT.dbus_call(NM.DBUS_PATH, NM.DBUS_INTERFACE, "Enable", toggle,
None, -1, None, None, None)
except AttributeError:
# Workaround for older versions of python-gobject
CLIENT.networking_set_enabled(enable)
notify("Networking {}".format("enabled" if enable is True else "disabled"))
def toggle_wifi(enable):
"""Enable/disable Wifi
Args: enable - boolean
"""
toggle = GLib.Variant.new_boolean(enable)
try:
CLIENT.dbus_set_property(NM.DBUS_PATH, NM.DBUS_INTERFACE, "WirelessEnabled", toggle,
-1, None, None, None)
except AttributeError:
# Workaround for older versions of python-gobject
CLIENT.wireless_set_enabled(enable)
notify("Wifi {}".format("enabled" if enable is True else "disabled"))
def toggle_wwan(enable):
"""Enable/disable WWAN
Args: enable - boolean
"""
toggle = GLib.Variant.new_boolean(enable)
try:
CLIENT.dbus_set_property(NM.DBUS_PATH, NM.DBUS_INTERFACE, "WwanEnabled", toggle,
-1, None, None, None)
except AttributeError:
# Workaround for older versions of python-gobject
CLIENT.wwan_set_enabled(enable)
notify("Wwan {}".format("enabled" if enable is True else "disabled"))
def toggle_bluetooth(enable):
"""Enable/disable Bluetooth
Args: enable - boolean
References:
https://github.com/blueman-project/blueman/blob/master/blueman/plugins/mechanism/RfKill.py
https://www.kernel.org/doc/html/latest/driver-api/rfkill.html
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/include/uapi/linux/rfkill.h?h=v5.8.9
"""
type_bluetooth = 2
op_change_all = 3
idx = 0
soft_state = 0 if enable else 1
hard_state = 0
data = struct.pack("IBBBB", idx, type_bluetooth, op_change_all,
soft_state, hard_state)
try:
with open('/dev/rfkill', 'r+b', buffering=0) as rff:
rff.write(data)
except PermissionError:
notify("Lacking permission to write to /dev/rfkill.",
"Maybe you need to add your user to the 'rfkill' group?",
urgency="critical")
else:
notify("Bluetooth {}".format("enabled" if enable else "disabled"))
def launch_connection_editor():
"""Launch nmtui or the gui nm-connection-editor
"""
terminal = CONF.get("editor", "terminal", fallback="xterm")
gui_if_available = CONF.getboolean("editor", "gui_if_available", fallback=True)
if gui_if_available is True:
try:
Popen(["gnome-control-center", "network"]).communicate()
except OSError:
try:
Popen(["nm-connection-editor"]).communicate()
except OSError:
Popen([terminal, "-e", "nmtui"]).communicate()
else:
Popen([terminal, "-e", "nmtui"]).communicate()
def get_passphrase():
"""Get a password
Returns: string
"""
pinentry = CONF.get("dmenu", "pinentry", fallback=None)
if pinentry:
pin = ""
out = Popen(pinentry,
stdout=PIPE,
stdin=PIPE).communicate(input=b'setdesc Get network password\ngetpin\n')[0]
if out:
res = out.decode(ENC).split("\n")[2]
if res.startswith("D "):
pin = res.split("D ")[1]
return pin
return Popen(dmenu_cmd(0, "Passphrase"),
stdin=PIPE, stdout=PIPE).communicate()[0].decode(ENC)
def delete_connection():
"""Display list of NM connections and delete the selected one
"""
conn_acts = [Action(i.get_id(), i.delete_async, args=[None, delete_cb, None]) for i in CONNS]
conn_names = "\n".join([str(i) for i in conn_acts]).encode(ENC)
sel = Popen(dmenu_cmd(len(conn_acts), "CHOOSE CONNECTION TO DELETE:"),
stdin=PIPE,
stdout=PIPE,
env=ENV).communicate(input=conn_names)[0].decode(ENC)
if not sel.strip():
sys.exit()
action = [i for i in conn_acts if str(i) == sel.rstrip("\n")]
assert len(action) == 1, u"Selection was ambiguous: {}".format(str(sel))
action[0]()
LOOP.run()
def delete_cb(dev, res, data):
"""Notification if delete completed successfully
"""
if dev.delete_finish(res) is True:
notify("Deleted {}".format(dev.get_id()))
else:
notify("Problem deleting {}".format(dev.get_id()), urgency="critical")
LOOP.quit()
def set_new_connection(nm_ap, nm_pw, adapter):
"""Setup a new NetworkManager connection
Args: ap - NM.AccessPoint
pw - string
"""
nm_pw = str(nm_pw).strip()
profile = create_wifi_profile(nm_ap, nm_pw, adapter)
CLIENT.add_and_activate_connection_async(profile, adapter, nm_ap.get_path(),
None, verify_conn, profile)
LOOP.run()
def create_wifi_profile(nm_ap, password, adapter):
# pylint: disable=C0301
# From https://cgit.freedesktop.org/NetworkManager/NetworkManager/tree/examples/python/gi/add_connection.py
# and https://cgit.freedesktop.org/NetworkManager/NetworkManager/tree/examples/python/dbus/add-wifi-psk-connection.py
# pylint: enable=C0301
"""Create the NM profile given the AP and passphrase"""
ap_sec = ap_security(nm_ap)
profile = NM.SimpleConnection.new()
s_con = NM.SettingConnection.new()
s_con.set_property(NM.SETTING_CONNECTION_ID, ssid_to_utf8(nm_ap))
s_con.set_property(NM.SETTING_CONNECTION_UUID, str(uuid.uuid4()))
s_con.set_property(NM.SETTING_CONNECTION_TYPE, "802-11-wireless")
profile.add_setting(s_con)
s_wifi = NM.SettingWireless.new()
s_wifi.set_property(NM.SETTING_WIRELESS_SSID, nm_ap.get_ssid())
s_wifi.set_property(NM.SETTING_WIRELESS_MODE, 'infrastructure')
s_wifi.set_property(NM.SETTING_WIRELESS_MAC_ADDRESS, adapter.get_permanent_hw_address())
profile.add_setting(s_wifi)
s_ip4 = NM.SettingIP4Config.new()
s_ip4.set_property(NM.SETTING_IP_CONFIG_METHOD, "auto")
profile.add_setting(s_ip4)
s_ip6 = NM.SettingIP6Config.new()
s_ip6.set_property(NM.SETTING_IP_CONFIG_METHOD, "auto")
profile.add_setting(s_ip6)
if ap_sec != "--":
s_wifi_sec = NM.SettingWirelessSecurity.new()
if "WPA" in ap_sec:
s_wifi_sec.set_property(NM.SETTING_WIRELESS_SECURITY_KEY_MGMT,
"wpa-psk")
s_wifi_sec.set_property(NM.SETTING_WIRELESS_SECURITY_AUTH_ALG,
"open")
s_wifi_sec.set_property(NM.SETTING_WIRELESS_SECURITY_PSK, password)
elif "WEP" in ap_sec:
s_wifi_sec.set_property(NM.SETTING_WIRELESS_SECURITY_KEY_MGMT,
"None")
s_wifi_sec.set_property(NM.SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE,
NM.WepKeyType.PASSPHRASE)
s_wifi_sec.set_wep_key(0, password)
profile.add_setting(s_wifi_sec)
return profile
def verify_conn(client, result, data):
"""Callback function for add_and_activate_connection_async
Check if connection completes successfully. Delete the connection if there
is an error.
"""
try:
act_conn = client.add_and_activate_connection_finish(result)
conn = act_conn.get_connection()
if not all([conn.verify(),
conn.verify_secrets(),
data.verify(),
data.verify_secrets()]):
raise GLib.Error
notify("Added {}".format(conn.get_id()))
except GLib.Error: # pylint: disable=catching-non-exception
try:
notify("Connection to {} failed".format(conn.get_id()),
urgency="critical")
conn.delete_async(None, None, None)
except UnboundLocalError:
pass
finally:
LOOP.quit()
def create_ap_list(adapter, active_connections):
"""Generate list of access points. Remove duplicate APs , keeping strongest
ones and the active AP
Args: adapter
active_connections - list of all active connections
Returns: aps - list of access points
active_ap - active AP
active_ap_con - active Connection
adapter
"""
aps = []
ap_names = []
active_ap = adapter.get_active_access_point()
aps_all = sorted(adapter.get_access_points(),
key=lambda a: a.get_strength(), reverse=True)
conns_cur = [i for i in CONNS if
i.get_setting_wireless() is not None and
i.get_setting_wireless().get_mac_address() ==
adapter.get_permanent_hw_address()]
try:
ap_conns = active_ap.filter_connections(conns_cur)
active_ap_name = ssid_to_utf8(active_ap)
active_ap_con = [active_conn for active_conn in active_connections
if active_conn.get_connection() in ap_conns]
except AttributeError:
active_ap_name = None
active_ap_con = []
if len(active_ap_con) > 1:
raise ValueError("Multiple connection profiles match"
" the wireless AP")
active_ap_con = active_ap_con[0] if active_ap_con else None
for nm_ap in aps_all:
ap_name = ssid_to_utf8(nm_ap)
if nm_ap != active_ap and ap_name == active_ap_name:
# Skip adding AP if it's not active but same name as active AP
continue
if ap_name not in ap_names:
ap_names.append(ap_name)
aps.append(nm_ap)
return aps, active_ap, active_ap_con, adapter
def notify(message, details=None, urgency="low"):
"""Use notify-send if available for notifications
"""
args = ["-u", urgency, message]
if details is not None:
args.append(details)
try:
Popen(["notify-send"] + args,
stdout=PIPE, stderr=PIPE).communicate()
except FileNotFoundError:
pass
def run():
"""Main script entrypoint"""
active = CLIENT.get_active_connections()
adapter = choose_adapter(CLIENT)
if adapter:
ap_actions = create_ap_actions(*create_ap_list(adapter, active))
else:
ap_actions = []
vpns = [i for i in CONNS if i.is_type(NM.SETTING_VPN_SETTING_NAME)]
try:
wgs = [i for i in CONNS if i.is_type(NM.SETTING_WIREGUARD_SETTING_NAME)]
except AttributeError:
# Workaround for older versions of python-gobject with no wireguard support
wgs = []
eths = [i for i in CONNS if i.is_type(NM.SETTING_WIRED_SETTING_NAME)]
blues = [i for i in CONNS if i.is_type(NM.SETTING_BLUETOOTH_SETTING_NAME)]
vpn_actions = create_vpn_actions(vpns, active)
wg_actions = create_wireguard_actions(wgs, active)
eth_actions = create_eth_actions(eths, active)
blue_actions = create_blue_actions(blues, active)
other_actions = create_other_actions(CLIENT)
wwan_installed = is_modemmanager_installed()
if wwan_installed:
gsms = [i for i in CONNS if i.is_type(NM.SETTING_GSM_SETTING_NAME)]
gsm_actions = create_gsm_actions(gsms, active)
wwan_actions = create_wwan_actions(CLIENT)
else:
gsm_actions = []
wwan_actions = []
list_saved = CONF.getboolean('dmenu', 'list_saved', fallback=False)
saved_cons = [i for i in CONNS if i not in vpns + wgs + eths + blues]
if list_saved:
saved_actions = create_saved_actions(saved_cons)
else:
saved_actions = [Action("Saved connections", prompt_saved, [saved_cons])]
actions = combine_actions(eth_actions, ap_actions, vpn_actions, wg_actions,
gsm_actions, blue_actions, wwan_actions,
other_actions, saved_actions)
sel = get_selection(actions)
sel()
if __name__ == '__main__':
run()
# vim: set et ts=4 sw=4 :

+ 1
- 1
scripts/status-bar/arch View File

@ -9,4 +9,4 @@ fi
echo $updates > ~/.cache/pacman_updates
#echo "$ifg $icon $tfg$(cat ~/.cache/pacman_updates)"
echo "$icon $(cat ~/.cache/pacman_updates)"
echo "^c#a48ead^$icon ^d^ $(cat ~/.cache/pacman_updates)"

+ 0
- 17
scripts/status-bar/arch-block View File

@ -1,17 +0,0 @@
#!/bin/sh
icon=󰮯
ibg=^b#705B86^
ifg=^c#fabd2f^
tfg=^c#292541^
tbg=^b#cdabb8^
reset=^d^
if ! updates=$(checkupdates 2> /dev/null | wc -l ); then
updates=0t
fi
echo $updates > ~/.cache/pacman_updates
echo "$ibg$ifg $icon $tfg$tbg $(cat ~/.cache/pacman_updates) $reset"

+ 10
- 10
scripts/status-bar/battery View File

@ -15,23 +15,23 @@ ramp90=
ramp100=
if [[ $bat -lt 10 ]]; then
echo " $ramp10 $bat% "
echo "^c#ebcb8b^$ramp10^d^ $bat% "
elif [[ $bat -lt 20 ]]; then
echo " $ramp20 $bat% "
echo "^c#ebcb8b^$ramp20^d^ $bat% "
elif [[ $bat -lt "30" ]]; then
echo " $ramp30 $bat% "
echo "^c#ebcb8b^$ramp30^d^ $bat% "
elif [[ $bat -lt "40" ]]; then
echo " $ramp40 $bat% "
echo "^c#ebcb8b^$ramp40^d^ $bat% "
elif [[ $bat -lt "50" ]]; then
echo " $ramp50 $bat% "
echo "^c#ebcb8b^$ramp50^d^ $bat% "
elif [[ $bat -lt "60" ]]; then
echo " $ramp60 $bat% "
echo "^c#ebcb8b^$ramp60^d^ $bat% "
elif [[ $bat -lt "70" ]]; then
echo " $ramp70 $bat% "
echo "^c#ebcb8b^$ramp70^d^ $bat% "
elif [[ $bat -lt "80" ]]; then
echo " $ramp80 $bat% "
echo "^c#ebcb8b^$ramp80^d^ $bat% "
elif [[ $bat -lt "90" ]]; then
echo " $ramp90 $bat% "
echo "^c#ebcb8b^$ramp90^d^ $bat% "
elif [[ $bat -le "100" ]]; then
echo " $ramp100 $bat% "
echo "^c#ebcb8b^$ramp100^d^ $bat% "
fi

+ 0
- 49
scripts/status-bar/battery-blocks View File

@ -1,49 +0,0 @@
#! /bin/sh
bat=$(cat /sys/class/power_supply/BAT0/capacity)
status=$(cat /sys/class/power_supply/BAT0/status)
ramp10=󰁺
ramp20=󰁻
ramp30=󰁼
ramp40=󰁽
ramp50=󰁾
ramp60=󰁿
ramp70=󰂀
ramp80=󰂁
ramp90=󰂂
ramp100=󰁹
tbg=^b#cdabb8^
tfg=^c#292541^
reset=^d^
if [[ $status == "Discharging" ]]; then
ibg=^b#705b86^
elif [[ $status == "Full" ]]; then
ibg=^b#50FA7B^
else
ibg=^b#50FA7B^
fi
if [[ $bat -lt 10 ]]; then
echo "$ibg$tfg $ramp10 $tbg $bat% $reset"
elif [[ $bat -lt 20 ]]; then
echo "$ibg$tfg $ramp20 $tbg $bat% $reset"
elif [[ $bat -lt "30" ]]; then
echo "$ibg$tfg $ramp30 $tbg $bat% $reset"
elif [[ $bat -lt "40" ]]; then
echo "$ibg$tfg $ramp40 $tbg $bat% $reset"
elif [[ $bat -lt "50" ]]; then
echo "$ibg$tfg $ramp50 $tbg $bat% $reset"
elif [[ $bat -lt "60" ]]; then
echo "$ibg$tfg $ramp60 $tbg $bat% $reset"
elif [[ $bat -lt "70" ]]; then
echo "$ibg$tfg $ramp70 $tbg $bat% $reset"
elif [[ $bat -lt "80" ]]; then
echo "$ibg$tfg $ramp80 $tbg $bat% $reset"
elif [[ $bat -lt "90" ]]; then
echo "$ibg$tfg $ramp90 $tbg $bat% $reset"
elif [[ $bat -le "100" ]]; then
echo "$ibg$tfg $ramp100 $tbg $bat% $reset"
fi

+ 0
- 14
scripts/status-bar/capslock View File

@ -1,14 +0,0 @@
#! /bin/sh
icon=󰘲
bfg=^b#292541^
tfg=^c#cc241d^
reset=^d^
cmd=$(cat /sys/class/leds/input3::capslock/brightness)
if [[ "$cmd" == "1" ]]; then
echo "$tfg$tbg $icon $reset"
else
echo ""
fi

+ 0
- 12
scripts/status-bar/clima View File

@ -1,12 +0,0 @@
#! /bin/sh
#localización
#initloc=$(curl -s ifconfig.co/city)
#if [ "$initloc" == "La Paz" ]; then
# loc="LAP"
#else
# loc=init-loc
#fi
# obtener clima
#curl -s "wttr.in/$loc?format=%t"
curl -s "wttr.in/?format=%t"

+ 0
- 27
scripts/status-bar/clima-icon View File

@ -1,27 +0,0 @@
#! /bin/sh
estado=$(curl -s "wttr.in/?format=%C" )
case $estado in
Unknown) icon="";;
Cloudy) icon="";;
Fog) icon="";;
"Heavy rain") icon="";;
"Heavy showers") icon="";;
"Heavy snow") icon="";;
"Heavy snow showers") icon="";;
"Light rain") icon="";;
"Light showers") icon="";;
"Light sleet") icon="";;
"Light sleet showers") icon="";;
"Light snow") icon="";;
"Light snow showers") icon="";;
"Partly cloudy") icon="";;
"Sunny") icon="";;
"Clear") icon="";;
"Thundery heavy rain") icon="";;
"Thundery showers") icon="";;
"Thundery snow showers") icon="";;
"Very cloudy") icon="";;
esac
echo $icon

+ 1
- 1
scripts/status-bar/cpu-temp View File

@ -3,4 +3,4 @@
temp=$(sed 's/[0-9][0-9][0-9]$/°C/' /sys/class/thermal/thermal_zone4/temp)
icon=
echo "$icon $temp "
echo "^c#bf616a^$icon^d^ $temp "

+ 0
- 9
scripts/status-bar/fecha View File

@ -1,9 +0,0 @@
#! /bin/sh
icon=
cmd=$(date +"%b %e, %R")
#echo "$ifg $icon $tfg$cmd"
echo "$icon $cmd"

+ 0
- 11
scripts/status-bar/fecha-block View File

@ -1,11 +0,0 @@
#! /bin/sh
icon=󰸘
tfg=^c#292541^
ibg=^b#705b86^
tbg=^b#cdabb8^
reset=^d^
cmd=$(date +"%b %e, %R")
echo "$tfg$ibg$ifg $icon $tbg $cmd $reset"

+ 0
- 10
scripts/status-bar/listener View File

@ -1,10 +0,0 @@
#! /bin/sh
while true; do
read -t 1 -n 1 key
if [[ $key == o ]]; then
notify-send "presionaste la o"
fi
done

+ 19
- 0
scripts/status-bar/network View File

@ -0,0 +1,19 @@
#!/bin/sh
ETH_IT=enp2s0
WLAN_IT=wlp3s0
is_eth_used=$(cat /sys/class/net/${ETH_IT}/carrier)
is_wlan_used=$(cat /sys/class/net/${WLAN_IT}/carrier)
echo -n "^c#88c0d0^"
if [ "$is_eth_used" -eq 1 ]; then # wired network is carrying
icon="^d^ " #uF6FF
elif [ "$is_wlan_used" -eq 1 ]; then # wireless network is carrying
icon="直 ^d^ $(nmcli -t -f active,ssid dev wifi | egrep '^yes' | cut -d\' -f2 | cut -d ':' -f2)" #uF1EB
else
icon="^d^" #uf128 # no network
fi
echo -n $icon

+ 0
- 9
scripts/status-bar/red View File

@ -1,9 +0,0 @@
#! /bin/sh
if [[ $(cat /sys/class/net/wlp*/operstate) == "up" ]]; then
echo " 直 "
else
echo " 睊 "
fi

+ 0
- 14
scripts/status-bar/red-texto View File

@ -1,14 +0,0 @@
#! /bin/sh
if [[ $(cat /sys/class/net/wlp*/operstate) == "up" ]]; then
echo " WiFi "
else
ping -c 1 google.com
if [[ $? == 0 ]]; then
echo "Eth"
else
" "
fi
fi

+ 0
- 3
scripts/status-bar/sep1 View File

@ -1,3 +0,0 @@
#! /bin/sh
echo ""

+ 0
- 14
scripts/status-bar/spotify-bar View File

@ -1,14 +0,0 @@
#! /bin/sh
icon=" "
#status=$(~/.local/bin/status-bar/spotify_status.py -f '{artist} - {song}')
status=$(playerctl metadata --format '{{artist}} - {{title}}' | cut -c 1-50)
runstate=$(playerctl status)
if [[ $runstate == "Playing" ]]; then
echo " $icon $status"
else
echo ""
fi

+ 0
- 17
scripts/status-bar/spotify-block View File

@ -1,17 +0,0 @@
#! /bin/sh
icon="󰓇"
ibg=^b#875B82^
ifg=^c#1DB954^
tfg=^c#292541^
tbg=^b#cdabb8^
reset=^d^
status=$(~/.local/bin/status-bar/spotify_status.py)
runstate=$(pgrep -c spotify)
if [[ $runstate -le 1 ]]; then
echo ""
else
echo "$ibg$ifg $icon $tbg$tfg $status $reset"
fi

+ 0
- 122
scripts/status-bar/spotify_status.py View File

@ -1,122 +0,0 @@
#!/bin/python
import sys
import dbus
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
'-t',
'--trunclen',
type=int,
metavar='trunclen'
)
parser.add_argument(
'-f',
'--format',
type=str,
metavar='custom format',
dest='custom_format'
)
parser.add_argument(
'-p',
'--playpause',
type=str,
metavar='play-pause indicator',
dest='play_pause'
)
parser.add_argument(
'--font',
type=str,
metavar='the index of the font to use for the main label',
dest='font'
)
parser.add_argument(
'--playpause-font',
type=str,
metavar='the index of the font to use to display the playpause indicator',
dest='play_pause_font'
)
args = parser.parse_args()
def fix_string(string):
# corrects encoding for the python version used
if sys.version_info.major == 3:
return string
else:
return string.encode('utf-8')
# Default parameters
output = fix_string(u'{play_pause} {artist}: {song}')
trunclen = 35
play_pause = fix_string(u'\u25B6,\u23F8') # first character is play, second is paused
label_with_font = '%{{T{font}}}{label}%{{T-}}'
font = args.font
play_pause_font = args.play_pause_font
# parameters can be overwritten by args
if args.trunclen is not None:
trunclen = args.trunclen
if args.custom_format is not None:
output = args.custom_format
if args.play_pause is not None:
play_pause = args.play_pause
try:
session_bus = dbus.SessionBus()
spotify_bus = session_bus.get_object(
'org.mpris.MediaPlayer2.spotify',
'/org/mpris/MediaPlayer2'
)
spotify_properties = dbus.Interface(
spotify_bus,
'org.freedesktop.DBus.Properties'
)
metadata = spotify_properties.Get('org.mpris.MediaPlayer2.Player', 'Metadata')
status = spotify_properties.Get('org.mpris.MediaPlayer2.Player', 'PlaybackStatus')
# Handle play/pause label
play_pause = play_pause.split(',')
if status == 'Playing':
play_pause = play_pause[0]
elif status == 'Paused':
play_pause = play_pause[1]
else:
play_pause = str()
if play_pause_font:
play_pause = label_with_font.format(font=play_pause_font, label=play_pause)
# Handle main label
artist = fix_string(metadata['xesam:artist'][0]) if metadata['xesam:artist'] else ''
song = fix_string(metadata['xesam:title']) if metadata['xesam:title'] else ''
if not artist and not song:
print('')
else:
if len(song) > trunclen:
song = song[0:trunclen]
song += '...'
if ('(' in song) and (')' not in song):
song += ')'
if font:
artist = label_with_font.format(font=font, label=artist)
song = label_with_font.format(font=font, label=song)
print(output.format(artist=artist, song=song, play_pause=play_pause))
except Exception as e:
if isinstance(e, dbus.exceptions.DBusException):
print('')
else:
print(e)

+ 9
- 0
scripts/status-bar/time View File

@ -0,0 +1,9 @@
#! /bin/sh
icon=
cmd=$(date +"%R")
#echo "$ifg $icon $tfg$cmd"
echo -n "^c#0f111a^^b#bf616a^ $icon $cmd ^d^"

+ 0
- 24
scripts/status-bar/volume View File

@ -1,24 +0,0 @@
#! /bin/sh
#mute=$(amixer get Master | awk -F'[][]' 'END{ print $6 }' )
#vol=$(amixer get Master | awk -F'[][]' 'END{ print $2 }' )
mute=$(pamixer --get-mute)
vol=$(pamixer --get-volume)
iconmute=婢
ramp1=奄
ramp2=奔
ramp3=墳
#if [[ $mute == "true" ]]; then
# echo " $iconmute $vol% "
if [[ $mute == "true" ]]; then
echo " $iconmute mute"
elif [[ "$vol" -ge "100" ]]; then
echo "$ramp3 $vol% "
elif [[ "$vol" -le "33" ]]; then
echo "$ramp1 $vol% "
elif [[ "$vol" -le "66" ]]; then
echo "$ramp2 $vol% "
elif [[ "$vol" -ge "66" ]]; then
echo "$ramp3 $vol% "
fi

+ 0
- 29
scripts/status-bar/volume-block View File

@ -1,29 +0,0 @@
#! /bin/sh
#mute=$(amixer get Master | awk -F'[][]' 'END{ print $6 }' )
#vol=$(amixer get Master | awk -F'[][]' 'END{ print $2 }' )
mute=$(pamixer --get-mute)
vol=$(pamixer --get-volume)
iconmute=󰖁
ramp1=󰕿
ramp2=󰖀
ramp3=󰕾
mbg=^b#cc241d^
tfg=^c#292541^
ibg=^b#875b82^
tbg=^b#cdabb8^
reset=^d^
if [[ $mute == "true" ]]; then
echo "$mbg$tfg $iconmute $tbg$tfg $vol% $reset"
elif [[ "$vol" == "100" ]]; then
echo "$ibg$tfg $ramp3 $tbg$tfg $vol% $reset"
elif [[ "$vol" < "33" ]]; then
echo "$ibg$tfg $ramp1 $tbg$tfg $vol% $reset"
elif [[ "$vol" < "66" ]]; then
echo "$ibg$tfg $ramp2 $tbg$tfg $vol% $reset"
elif [[ "$vol" = "66" ]]; then
echo "$ibg$tfg $ramp2 $tbg$tfg $vol% $reset"
elif [[ "$vol" > "66" ]]; then
echo "$ibg$tfg $ramp3 $tbg$tfg $vol% $reset"
fi

+ 31
- 0
scripts/status-bar/weather View File

@ -0,0 +1,31 @@
#!/bin/sh
export LOCATION=ankara
weatherreport="${XDG_DATA_HOME:-$HOME/.local/share}/weatherreport"
getforecast() { curl -sf "wttr.in/$LOCATION" > "$weatherreport" || exit 1 ;}
# Some very particular and terse stream manipulation. We get the maximum
# precipitation chance and the daily high and low from the downloaded file and
# display them with coresponding emojis.
showweather() { printf "%s" "$(sed '16q;d' "$weatherreport" |
grep -wo "[0-9]*%" | sort -rn | sed "s/^/\^c#81a1c1\^  \^d\^/g;1q" | tr -d '\n')"
sed '13q;d' "$weatherreport" | grep -o "m\\([-+]\\)*[0-9]\\+" | sort -n -t 'm' -k 2n | sed -e 1b -e '$!d' | tr '\n|m' ' ' | awk '{print " ﰕ " $1 "°","^c#ebcb8b^滛 ^d^" $2 "°"}' ;}
case $BLOCK_BUTTON in
1) setsid -f "$TERMINAL" -e less -Srf "$weatherreport" ;;
2) getforecast && showweather ;;
3) notify-send " Weather module" "\- Left click for full forecast.
- Middle click to update forecast.
: Chance of rain/snow
ﰕ: Daily low
滛: Daily high" ;;
6) "$TERMINAL" -e "$EDITOR" "$0" ;;
esac
# The test if our forcecast is updated to the day. If it isn't download a new
# weather report from wttr.in with the above function.
[ "$(stat -c %y "$weatherreport" 2>/dev/null | cut -d' ' -f1)" = "$(date '+%Y-%m-%d')" ] ||
getforecast
showweather

+ 76
- 0
scripts/surf_linkselect.sh View File

@ -0,0 +1,76 @@
#!/usr/bin/env sh
# surf_linkselect.sh:
# Usage: curl somesite.com | surf_linkselect [SURFWINDOWID] [PROMPT]
# Deps: xmllint, dmenu
# Info:
# Designed to be used w/ surf externalpipe patch. Enables keyboard-only
# link selection via dmenu. Given HTML stdin, extracts links one per line
# Selected link is normalized based on current URI and printed to STDOUT.
# Pipe the result to a new surf or xprop _SURF_URI accordingly.
SURF_WINDOW="${1:-$(xprop -root | sed -n '/^_NET_ACTIVE_WINDOW/ s/.* //p')}"
DMENU_PROMPT="${2:-Link}"
function dump_links_with_titles() {
awk '{
input = $0;
$0 = input;
gsub("<[^>]*>", "");
gsub(/[ ]+/, " ");
gsub("&amp;", "\\&");
gsub("&lt;", "<");
gsub("&gt;", ">");
$1 = $1;
title = ($0 == "" ? "None" : $0);
$0 = input;
match($0, /\<[ ]*[aA][^>]* [hH][rR][eE][fF]=["]([^"]+)["]/, linkextract);
$0 = linkextract[1];
gsub(/^[ \t]+/,"");
gsub(/[ \t]+$/,"");
gsub("[ ]", "%20");
link = $0;
if (link != "") {
print title ": " link;
}
}'
}
function link_normalize() {
URI=$1
awk -v uri=$URI '{
gsub("&amp;", "\\&");
if ($0 ~ /^https?:\/\// || $0 ~ /^\/\/.+$/) {
print $0;
} else if ($0 ~/^#/) {
gsub(/[#?][^#?]+/, "", uri);
print uri $0;
} else if ($0 ~/^\//) {
split(uri, uri_parts, "/");
print uri_parts[3] $0;
} else {
gsub(/[#][^#]+/, "", uri);
uri_parts_size = split(uri, uri_parts, "/");
delete uri_parts[uri_parts_size];
for (v in uri_parts) {
uri_pagestripped = uri_pagestripped uri_parts[v] "/"
}
print uri_pagestripped $0;
}
}'
}
function link_select() {
tr '\n\r' ' ' |
xmllint --html --xpath "//a" - |
dump_links_with_titles |
awk '!x[$0]++' |
# sort | uniq
dmenu -p "$DMENU_PROMPT" -l 10 -i -w $SURF_WINDOW |
awk -F' ' '{print $NF}' |
link_normalize $(xprop -id $SURF_WINDOW _SURF_URI | cut -d '"' -f 2)
}
link_select

+ 10
- 0
suckless/clipmenu/.travis.yml View File

@ -0,0 +1,10 @@
language: bash
dist: xenial
script:
- shellcheck -s bash clipmenu clipmenud clipdel clipfsck clipctl
- tests/test-clipmenu
matrix:
fast_finish: true

+ 5
- 0
suckless/clipmenu/LICENSE View File

@ -0,0 +1,5 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.

+ 12
- 0
suckless/clipmenu/Makefile View File

@ -0,0 +1,12 @@
# `dmenu` is not a hard dependency, but you need it unless
# you plan to set CM_LAUNCHER to another value like `rofi`
REQUIRED_BINS := xsel clipnotify
PREFIX ?= /usr
$(foreach bin,$(REQUIRED_BINS),\
$(if $(shell command -v $(bin) 2> /dev/null),$(info Found `$(bin)`),$(error Missing Dep. Please install `$(bin)`)))
.PHONY: install
install:
install --target "${PREFIX}/bin" -D -m755 clipmenu clipmenud clipdel clipctl
install -D -m644 init/clipmenud.service "${PREFIX}/lib/systemd/user/clipmenud.service"

+ 100
- 0
suckless/clipmenu/README.md View File

@ -0,0 +1,100 @@
[![Tests](https://img.shields.io/travis/cdown/clipmenu/develop.svg)](https://travis-ci.org/cdown/clipmenu)
clipmenu is a simple clipboard manager using [dmenu][] (or [rofi][] with
`CM_LAUNCHER=rofi`) and [xsel][].
# Demo
![Demo](https://cloud.githubusercontent.com/assets/660663/24079784/6f76da94-0c88-11e7-8251-40b1f02ebf3c.gif)
# Usage
## clipmenud
Start `clipmenud`, then run `clipmenu` to select something to put on the
clipboard. For systemd users, a user service called `clipmenud` is packaged as
part of the project.
For those using a systemd unit and not using a desktop environment which does
it automatically, you must import `$DISPLAY` so that `clipmenud` knows which X
server to use. For example, in your `~/.xinitrc` do this prior to launching
clipmenud:
systemctl --user import-environment DISPLAY
## clipmenu
You may wish to bind a shortcut in your window manager to launch `clipmenu`.
All args passed to clipmenu are transparently dispatched to dmenu. That is, if
you usually call dmenu with args to set colours and other properties, you can
invoke clipmenu in exactly the same way to get the same effect, like so:
clipmenu -i -fn Terminus:size=8 -nb '#002b36' -nf '#839496' -sb '#073642' -sf '#93a1a1'
For a full list of environment variables that clipmenud can take, please see
`clipmenud --help`.
# Features
The behavior of `clipmenud` can be customized through environment variables.
Despite being only <300 lines, clipmenu has many useful features, including:
* Customising the maximum number of clips stored (default 1000)
* Disabling clip collection temporarily with `clipctl disable`, reenabling with
`clipctl enable`
* Not storing clipboard changes from certain applications, like password
managers
* Taking direct ownership of the clipboard
* ...and much more.
Check `clipmenud --help` to view all possible environment variables and what
they do. If you manage `clipmenud` with `systemd`, you can override the
defaults by using `systemctl --user edit clipmenud` to generate an override
file.
# Supported launchers
Any dmenu-compliant application will work, but here are `CM_LAUNCHER`
configurations that are known to work:
- `dmenu` (the default)
- `fzf`
- `rofi`
- `rofi-script`, for [rofi's script
mode](https://github.com/davatorium/rofi-scripts/tree/master/mode-scripts)
# Installation
Several distributions, including Arch and Nix, provide clipmenu as an official
package called `clipmenu`.
## Manual installation
If your distribution doesn't provide a package, you can manually install using
`make install` (or better yet, create a package for your distribution!). You
will need `xsel` and `clipnotify` installed, and also `dmenu` unless you plan
to use a different launcher.
# How does it work?
clipmenud is less than 300 lines, and clipmenu is less than 100, so hopefully
it should be fairly self-explanatory. However, at the most basic level:
## clipmenud
1. `clipmenud` uses [clipnotify](https://github.com/cdown/clipnotify) to wait
for new clipboard events.
2. If `clipmenud` detects changes to the clipboard contents, it writes them out
to the cache directory and an index using a hash as the filename.
## clipmenu
1. `clipmenu` reads the index to find all available clips.
2. `dmenu` is executed to allow the user to select a clip.
3. After selection, the clip is put onto the PRIMARY and CLIPBOARD X
selections.
[dmenu]: http://tools.suckless.org/dmenu/
[rofi]: https://github.com/DaveDavenport/Rofi
[xsel]: http://www.vergenet.net/~conrad/software/xsel/

+ 52
- 0
suckless/clipmenu/clipctl View File

@ -0,0 +1,52 @@
#!/usr/bin/env bash
: "${CM_DIR:="${XDG_RUNTIME_DIR-"${TMPDIR-/tmp}"}"}"
if [[ -z $1 ]] || [[ $1 == --help ]] || [[ $1 == -h ]]; then
cat << 'EOF'
clipctl provides controls for the clipmenud daemon.
Commands:
enable: enable clip collection
disable: disable clip collection
status: returns "enabled" or "disabled"
toggle: toggles clip collection
version: returns major version
cache-dir: returns the directory used for caching
EOF
exit 0
fi
clipmenud_pid=$(pgrep -u "$(id -u)" -nf 'clipmenud$')
case $1 in
enable|disable|toggle|status)
if [[ -z "$clipmenud_pid" ]]; then
echo "clipmenud is not running" >&2
exit 2
fi
;;
esac
major_version=6
cache_dir=$CM_DIR/clipmenu.$major_version.$USER
status_file=$cache_dir/status
case $1 in
enable) kill -USR2 "$clipmenud_pid" ;;
disable) kill -USR1 "$clipmenud_pid" ;;
status) cat "$status_file" ;;
toggle)
if [[ $(clipctl status) == "enabled" ]]; then
clipctl disable
else
clipctl enable
fi
;;
version) echo "$major_version" ;;
cache-dir) echo "$cache_dir" ;;
*)
printf 'Unknown command: %s\n' "$1" >&2
exit 1
;;
esac

+ 93
- 0
suckless/clipmenu/clipdel View File

@ -0,0 +1,93 @@
#!/usr/bin/env bash
CM_REAL_DELETE=0
if [[ $1 == -d ]]; then
CM_REAL_DELETE=1
shift
fi
shopt -s nullglob
cache_dir=$(clipctl cache-dir)
cache_file=$cache_dir/line_cache
lock_file=$cache_dir/lock
lock_timeout=2
if [[ $1 == --help ]] || [[ $1 == -h ]]; then
cat << 'EOF'
clipdel deletes clipmenu entries matching a regex. By default, just lists what
it would delete, pass -d to do it for real. If no pattern is passed as an argument,
it will try to read one from standard input.
".*" is special, it will just nuke the entire data directory, including the
line caches and all other state.
Arguments:
-d Delete for real.
Environment variables:
- $CM_DIR: specify the base directory to store the cache dir in (default: $XDG_RUNTIME_DIR, $TMPDIR, or /tmp)
EOF
exit 0
fi
if ! [[ -f $cache_file ]]; then
printf '%s\n' "No line cache file found, no clips exist" >&2
exit 0 # Well, this is a kind of success...
fi
if [[ -n $1 ]]; then
raw_pattern=$1
elif ! [[ -t 0 ]]; then
IFS= read -r raw_pattern
fi
esc_pattern=${raw_pattern//\#/'\#'}
# We use 2 separate sed commands so "esc_pattern" matches only the 'clip' text
# without the timestamp (e.g. $> clipdel '^delete_exact_match$')
sed_common_command="s#^[0-9]\+ ##;\\#${esc_pattern}#"
if ! [[ $raw_pattern ]]; then
printf '%s\n' 'No pattern provided, see --help' >&2
exit 2
fi
exec {lock_fd}> "$lock_file"
if (( CM_REAL_DELETE )) && [[ "$raw_pattern" == ".*" ]]; then
flock -x -w "$lock_timeout" "$lock_fd" || exit
rm -rf -- "$cache_dir"
mkdir -p -- "$cache_dir"
exit 0
else
mapfile -t matches < <(
sed -n "${sed_common_command}p" "$cache_file" |
sort -u
)
if (( CM_REAL_DELETE )); then
flock -x -w "$lock_timeout" "$lock_fd" || exit
for match in "${matches[@]}"; do
ck=$(cksum <<< "$match")
rm -f -- "$cache_dir/$ck"
done
temp=$(mktemp)
# sed 'h' and 'g' here means save and restore the line, so
# timestamps are not removed from non-deleted lines. 'd' deletes the
# line and restarts, skipping 'g'/restore.
# https://www.gnu.org/software/sed/manual/html_node/Other-Commands.html#Other-Commands
sed "h;${sed_common_command}d;g" "$cache_file" > "$temp"
mv -- "$temp" "$cache_file"
flock -u "$lock_fd"
else
if (( ${#matches[@]} )); then
printf '%s\n' "${matches[@]}"
fi
fi
fi

+ 28
- 0
suckless/clipmenu/clipfsck View File

@ -0,0 +1,28 @@
#!/usr/bin/env bash
shopt -s nullglob
cache_dir=$(clipctl cache-dir)
cache_file=$cache_dir/line_cache
declare -A cksums
while IFS= read -r line; do
cksum=$(cksum <<< "$line")
cksums["$cksum"]="$line"
# Are all cache entries represented by a file?
full_file=$cache_dir/$cksum
if ! [[ -f $full_file ]]; then
printf 'cache entry without file: %s -> %s\n' "$line" "$full_file" >&2
fi
done < <(cut -d' ' -f2- < "$cache_file")
# Are all files represented by a cache entry?
for file in "$cache_dir"/[012346789]*; do
cksum=${file##*/}
line=${cksums["$cksum"]-_missing_}
if [[ $line == _missing_ ]]; then
printf 'file without cache entry: %s\n' "$file"
fi
done

+ 71
- 0
suckless/clipmenu/clipmenu View File

@ -0,0 +1,71 @@
#!/usr/bin/env bash
: "${CM_LAUNCHER=dmenu}"
: "${CM_HISTLENGTH=8}"
shopt -s nullglob
cache_dir=$(clipctl cache-dir)
cache_file=$cache_dir/line_cache
# Not -h, see #142
if [[ $1 == --help ]]; then
cat << 'EOF'
clipmenu is a simple clipboard manager using dmenu and xsel. Launch this
when you want to select a clip.
All arguments are passed through to dmenu itself.
Environment variables:
- $CM_DIR: specify the base directory to store the cache dir in (default: $XDG_RUNTIME_DIR, $TMPDIR, or /tmp)
- $CM_HISTLENGTH: specify the number of lines to show in dmenu/rofi (default: 8)
- $CM_LAUNCHER: specify a dmenu-compatible launcher (default: dmenu)
- $CM_OUTPUT_CLIP: if set, output clip selection to stdout
EOF
exit 0
fi
if ! [[ -f "$cache_file" ]]; then
printf '%s\n' 'No cache file yet, did you run clipmenud?'
exit 2
fi
# Blacklist of non-dmenu launchers
launcher_args=(-l "${CM_HISTLENGTH}")
if [[ "$CM_LAUNCHER" == fzf ]]; then
launcher_args=()
fi
# rofi supports dmenu-like arguments through the -dmenu flag
[[ "$CM_LAUNCHER" == rofi ]] && set -- -dmenu "$@"
list_clips() {
LC_ALL=C sort -rnk 1 < "$cache_file" | cut -d' ' -f2- | awk '!seen[$0]++'
}
if [[ "$CM_LAUNCHER" == rofi-script ]]; then
if (( $# )); then
chosen_line="${!#}"
else
list_clips
exit
fi
else
chosen_line=$(list_clips | "$CM_LAUNCHER" "${launcher_args[@]}" "$@")
launcher_exit=$?
fi
[[ $chosen_line ]] || exit 1
file=$cache_dir/$(cksum <<< "$chosen_line")
[[ -f "$file" ]] || exit 2
for selection in clipboard primary; do
xsel --logfile /dev/null -i --"$selection" < "$file"
done
if (( CM_OUTPUT_CLIP )); then
cat "$file"
fi
exit "${launcher_exit:-"$?"}"

+ 253
- 0
suckless/clipmenu/clipmenud View File

@ -0,0 +1,253 @@
#!/usr/bin/env bash
: "${CM_ONESHOT=0}"
: "${CM_OWN_CLIPBOARD=0}"
: "${CM_SYNC_PRIMARY_TO_CLIPBOARD=0}"
: "${CM_DEBUG=0}"
: "${CM_MAX_CLIPS:=1000}"
# Buffer to batch to avoid calling too much. Only used if CM_MAX_CLIPS >0.
CM_MAX_CLIPS_THRESH=$(( CM_MAX_CLIPS + 10 ))
: "${CM_SELECTIONS:=clipboard primary}"
read -r -a selections <<< "$CM_SELECTIONS"
cache_dir=$(clipctl cache-dir)
cache_file=$cache_dir/line_cache
status_file=$cache_dir/status
# lock_file: lock for *one* iteration of clipboard capture/propagation
# session_lock_file: lock to prevent multiple clipmenud daemons
lock_file=$cache_dir/lock
session_lock_file=$cache_dir/session_lock
lock_timeout=2
has_xdotool=0
_xsel() { timeout 1 xsel --logfile /dev/null "$@"; }
error() { printf 'ERROR: %s\n' "${1?}" >&2; }
info() { printf 'INFO: %s\n' "${1?}"; }
die() {
error "${2?}"
exit "${1?}"
}
make_line_cksums() { while read -r line; do cksum <<< "${line#* }"; done; }
get_first_line() {
data=${1?}
# We look for the first line matching regex /./ here because we want the
# first line that can provide reasonable context to the user.
awk -v limit=300 '
BEGIN { printed = 0; }
printed == 0 && NF {
$0 = substr($0, 0, limit);
printf("%s", $0);
printed = 1;
}
END {
if (NR > 1)
printf(" (%d lines)", NR);
printf("\n");
}' <<< "$data"
}
debug() { (( CM_DEBUG )) && printf '%s\n' "$@" >&2; }
sig_disable() {
info "Received disable signal, suspending clipboard capture"
_CM_DISABLED=1
_CM_FIRST_DISABLE=1
echo "disabled" > "$status_file"
[[ -v _CM_CLIPNOTIFY_PID ]] && kill "$_CM_CLIPNOTIFY_PID"
}
sig_enable() {
if ! (( _CM_DISABLED )); then
info "Received enable signal but we're not disabled, so doing nothing"
return
fi
# Still store the last data so we don't end up eventually putting it in the
# clipboard if it wasn't changed
for selection in "${selections[@]}"; do
data=$(_xsel -o --"$selection"; printf x)
last_data_sel[$selection]=${data%x}
done
info "Received enable signal, resuming clipboard capture"
_CM_DISABLED=0
echo "enabled" > "$status_file"
}
kill_background_jobs() {
# While we usually _are_, there are no guarantees that we're the process
# group leader. As such, all we can do is look at the pending jobs. Bash
# avoids a subshell here, so the job list is in the right shell.
local bg
bg=$(jobs -p)
# Don't log `kill' failures, since with KillMode=control-group, we're
# racing with init.
[[ $bg ]] && kill -- "$bg" 2>/dev/null
}
if [[ $1 == --help ]] || [[ $1 == -h ]]; then
cat << 'EOF'
clipmenud collects and caches what's on the clipboard. You can manage its
operation with clipctl.
Environment variables:
- $CM_DEBUG: turn on debugging output (default: 0)
- $CM_DIR: specify the base directory to store the cache dir in (default: $XDG_RUNTIME_DIR, $TMPDIR, or /tmp)
- $CM_MAX_CLIPS: soft maximum number of clips to store, 0 for inf. At $CM_MAX_CLIPS + 10, the number of clips is reduced to $CM_MAX_CLIPS (default: 1000)
- $CM_ONESHOT: run once immediately, do not loop (default: 0)
- $CM_OWN_CLIPBOARD: take ownership of the clipboard. Note: this may cause missed copies if some other application also handles the clipboard directly (default: 0)
- $CM_SELECTIONS: space separated list of the selections to manage (default: "clipboard primary")
- $CM_SYNC_PRIMARY_TO_CLIPBOARD: sync selections from primary to clipboard immediately (default: 0)
- $CM_IGNORE_WINDOW: disable recording the clipboard in windows where the windowname matches the given regex (e.g. a password manager), do not ignore any windows if unset or empty (default: unset)
EOF
exit 0
fi
[[ $DISPLAY ]] || die 2 'The X display is unset, is your X server running?'
# It's ok that this only applies to the final directory.
# shellcheck disable=SC2174
mkdir -p -m0700 "$cache_dir"
echo "enabled" > "$status_file"
exec {session_lock_fd}> "$session_lock_file"
flock -x -n "$session_lock_fd" ||
die 2 "Can't lock session file -- is another clipmenud running?"
declare -A last_data_sel
declare -A updated_sel
command -v clipnotify >/dev/null 2>&1 || die 2 "clipnotify not in PATH"
command -v xdotool >/dev/null 2>&1 && has_xdotool=1
if [[ $CM_IGNORE_WINDOW ]] && ! (( has_xdotool )); then
echo "WARN: CM_IGNORE_WINDOW does not work without xdotool, which is not installed" >&2
fi
exec {lock_fd}> "$lock_file"
trap sig_disable USR1
trap sig_enable USR2
trap 'trap - INT TERM EXIT; kill_background_jobs; exit 0' INT TERM EXIT
while true; do
if ! (( CM_ONESHOT )); then
# Make sure we're interruptible for the sig_{en,dis}able traps
clipnotify &
_CM_CLIPNOTIFY_PID="$!"
wait "$_CM_CLIPNOTIFY_PID"
fi
if (( _CM_DISABLED )); then
# The first one will just be from interrupting `wait`, so don't print
if (( _CM_FIRST_DISABLE )); then
unset _CM_FIRST_DISABLE
else
info "Got a clipboard notification, but we are disabled, skipping"
fi
continue
fi
if [[ $CM_IGNORE_WINDOW ]] && (( has_xdotool )); then
windowname="$(xdotool getactivewindow getwindowname)"
if [[ "$windowname" =~ $CM_IGNORE_WINDOW ]]; then
debug "ignoring clipboard because windowname \"$windowname\" matches \"${CM_IGNORE_WINDOW}\""
continue
fi
fi
if ! flock -x -w "$lock_timeout" "$lock_fd"; then
if (( CM_ONESHOT )); then
die 1 "Timed out waiting for lock"
else
error "Timed out waiting for lock, skipping this iteration"
continue
fi
fi
for selection in "${selections[@]}"; do
updated_sel[$selection]=0
data=$(_xsel -o --"$selection"; printf x)
data=${data%x} # avoid trailing newlines being stripped
[[ $data == *[^[:space:]]* ]] || continue
[[ $last_data == "$data" ]] && continue
[[ ${last_data_sel[$selection]} == "$data" ]] && continue
if [[ $last_data && $data == "$last_data"* ]] ||
[[ $last_data && $data == *"$last_data" ]]; then
# Don't actually remove the file yet, because it might be
# referenced by an older entry. These will be dealt with at vacuum.
debug "$selection: $last_data is a possible partial of $data"
previous_size=$(wc -c <<< "$last_cache_file_output")
truncate -s -"$previous_size" "$cache_file"
fi
first_line=$(get_first_line "$data")
debug "New clipboard entry on $selection selection: \"$first_line\""
cache_file_output="$(date +%s%N) $first_line"
filename="$cache_dir/$(cksum <<< "$first_line")"
last_cache_file_output=$cache_file_output
last_data=$data
last_data_sel[$selection]=$data
updated_sel[$selection]=1
debug "Writing $data to $filename"
printf '%s' "$data" > "$filename"
debug "Writing $cache_file_output to $cache_file"
printf '%s\n' "$cache_file_output" >> "$cache_file"
if (( CM_OWN_CLIPBOARD )) && [[ $selection == clipboard ]]; then
# Only clipboard, since apps like urxvt will unhilight for PRIMARY
_xsel -o --clipboard | _xsel -i --clipboard
fi
done
if (( CM_SYNC_PRIMARY_TO_CLIPBOARD )) && (( updated_sel[primary] )); then
_xsel -o --primary | _xsel -i --clipboard
fi
# The cache file may not exist if this is the first run and data is skipped
if (( CM_MAX_CLIPS )) && [[ -f "$cache_file" ]] && (( "$(wc -l < "$cache_file")" > CM_MAX_CLIPS_THRESH )); then
info "Trimming clip cache to CM_MAX_CLIPS ($CM_MAX_CLIPS)"
trunc_tmp=$(mktemp)
tail -n "$CM_MAX_CLIPS" "$cache_file" | uniq > "$trunc_tmp"
mv -- "$trunc_tmp" "$cache_file"
# Vacuum up unreferenced clips. They may either have been
# unreferenced by the above CM_MAX_CLIPS code, or they may be old
# possible partials.
declare -A cksums
while IFS= read -r line; do
cksum=$(cksum <<< "$line")
cksums["$cksum"]="$line"
done < <(cut -d' ' -f2- < "$cache_file")
num_vacuumed=0
for file in "$cache_dir"/[012346789]*; do
cksum=${file##*/}
if [[ ${cksums["$cksum"]-_missing_} == _missing_ ]]; then
debug "Vacuuming due to lack of reference: $file"
(( ++num_vacuumed ))
rm -- "$file"
fi
done
unset cksums
info "Vacuumed $num_vacuumed clip files."
fi
flock -u "$lock_fd"
(( CM_ONESHOT )) && break
done

+ 21
- 0
suckless/clipmenu/init/clipmenud.service View File

@ -0,0 +1,21 @@
[Unit]
Description=Clipmenu daemon
[Service]
ExecStart=/usr/bin/clipmenud
Restart=always
RestartSec=500ms
MemoryDenyWriteExecute=yes
NoNewPrivileges=yes
ProtectControlGroups=yes
ProtectKernelTunables=yes
RestrictAddressFamilies=
RestrictRealtime=yes
# We don't need to do any clean up, so if something hangs (borked xclip, etc),
# it's going to stay that way. Just forcefully kill and get it over with.
TimeoutStopSec=2
[Install]
WantedBy=default.target

+ 93
- 0
suckless/clipmenu/tests/test-clipmenu View File

@ -0,0 +1,93 @@
#!/usr/bin/env bash
set -x
set -e
set -o pipefail
dir=$(./clipctl cache-dir)
cache_file=$dir/line_cache
if [[ $0 == /* ]]; then
location=${0%/*}
else
location=$PWD/${0#./}
location=${location%/*}
fi
cat - "$location/../clipmenu" > /tmp/clipmenu << 'EOF'
#!/usr/bin/env bash
shopt -s expand_aliases
shim() {
printf '%s args:' "$1" >&2
printf ' %q' "${@:2}" >&2
printf '\n' >&2
i=0
while IFS= read -r line; do
let i++
printf '%s line %d stdin: %s\n' "$1" "$i" "$line" >&2
done
if [[ -v SHIM_STDOUT ]]; then
printf '%s\n' "$SHIM_STDOUT"
fi
}
# Cannot be an alias due to expansion order with $CM_LAUNCHER
dmenu() {
SHIM_STDOUT="Selected text. (2 lines)" shim dmenu "$@"
}
rofi() {
SHIM_STDOUT="Selected text. (2 lines)" shim rofi "$@"
}
alias xsel='shim xsel'
alias xclip='shim xclip'
alias clipctl='./clipctl'
EOF
chmod a+x /tmp/clipmenu
rm -rf "$dir"
mkdir -p "$dir"
cat > "$cache_file" << 'EOF'
1234 Selected text. (2 lines)
1235 Selected text 2. (2 lines)
EOF
cat > "$dir/$(cksum <<< 'Selected text. (2 lines)')" << 'EOF'
Selected text.
Yes, it's selected text.
EOF
### TESTS ###
temp=$(mktemp)
trap 'cat "$temp"' EXIT
/tmp/clipmenu --foo bar > "$temp" 2>&1
# Arguments are transparently passed to dmenu
grep -Fxq 'dmenu args: -l 8 --foo bar' "$temp"
# Output from cache file should get to dmenu, reversed
grep -Fxq 'dmenu line 1 stdin: Selected text 2. (2 lines)' "$temp"
grep -Fxq 'dmenu line 2 stdin: Selected text. (2 lines)' "$temp"
# xsel should copy both to clipboard *and* primary
grep -Fxq 'xsel args: --logfile /dev/null -i --clipboard' "$temp"
grep -Fxq 'xsel args: --logfile /dev/null -i --primary' "$temp"
grep -Fxq 'xsel line 1 stdin: Selected text.' "$temp"
grep -Fxq "xsel line 2 stdin: Yes, it's selected text." "$temp"
CM_LAUNCHER=rofi /tmp/clipmenu --foo bar > "$temp" 2>&1
# We have a special case to add -dmenu for rofi
grep -Fxq 'rofi args: -l 8 -dmenu --foo bar' "$temp"

+ 87
- 0
suckless/clipmenu/tests/test-perf View File

@ -0,0 +1,87 @@
#!/usr/bin/env bash
msg() {
printf '>>> %s\n' "$@" >&2
}
dir=$(clipctl cache-dir)
cache_file=$dir/line_cache
log=$(mktemp)
tim=$(mktemp)
clipmenu_shim=$(mktemp)
num_files=1500
trap 'rm -f -- "$log" "$tim" "$clipmenu_shim"' EXIT
if [[ $0 == /* ]]; then
location=${0%/*}
else
location=$PWD/${0#./}
location=${location%/*}
fi
msg 'Setting up edited clipmenu'
cat - "$location/../clipmenu" > /tmp/clipmenu << EOF
#!/usr/bin/env bash
exec 3>&2 2> >(tee "$log" |
sed -u 's/^.*$/now/' |
date -f - +%s.%N > "$tim")
set -x
dmenu() { :; }
xsel() { :; }
EOF
chmod a+x /tmp/clipmenu
if ! (( NO_RECREATE )); then
rm -rf "$dir"
mkdir -p "$dir"
msg "Writing $num_files clipboard files"
for (( i = 0; i <= num_files; i++ )); do
(( i % 100 )) || printf '%s... ' "$i"
line_len=$(( (RANDOM % 10000) + 1 ))
num_lines=$(( (RANDOM % 10) + 1 ))
data=$(
tr -dc 'a-zA-Z0-9' < /dev/urandom |
fold -w "$line_len" |
head -"$num_lines"
)
read -r first_line_raw <<< "$data"
printf -v first_line '%s (%s lines)\n' "$first_line_raw" "$num_lines"
printf '%d %s' "$i" "$first_line" >> "$cache_file"
fn=$dir/$(cksum <<< "$first_line")
printf '%s' "$data" > "$fn"
done
printf 'done\n'
else
msg 'Not nuking/creating new clipmenu files'
fi
msg 'Running modified clipmenu'
time /tmp/clipmenu
(( TIME_ONLY )) && exit 0
msg 'Displaying perf data'
# modified from http://stackoverflow.com/a/20855353/945780
paste <(
while read -r tim ;do
[ -z "$last" ] && last=${tim//.} && first=${tim//.}
crt=000000000$((${tim//.}-10#0$last))
ctot=000000000$((${tim//.}-10#0$first))
printf "%12.9f %12.9f\n" ${crt:0:${#crt}-9}.${crt:${#crt}-9} \
${ctot:0:${#ctot}-9}.${ctot:${#ctot}-9}
last=${tim//.}
done < "$tim"
) "$log" | less

+ 0
- 245
suckless/dwm/, View File

@ -1,245 +0,0 @@
/* See LICENSE file for copyright and license details. */
#include <X11/XF86keysym.h>
/* appearance */
static const unsigned int borderpx = 3; /* border pixel of windows */
static const unsigned int gappx = 6;
static const unsigned int snap = 32; /* snap pixel */
static const int rmaster = 0; /* 1 = master at right*/
static const int showbar = 1; /* 0 means no bar */
static const int topbar = 1; /* 0 means bottom bar */
static const int user_bh = 27; /* 0 means that dwm will calculate bar height, >= 1 means dwm will user_bh as bar height */
static const int tag_padding = 0;
static const int vertpad = 0; /* vertical padding of bar */
static const int sidepad = 0; /* horizontal padding of bar */
static const char *fonts[] = {"Hack Nerd Font:Regular:size=10", "Material Design Icons:Regular:pixelsize=16:antialias=true"};
static const char dmenufont[] = "Hack Nerd Font:size=10";
static const char fore[] = "#f8f8f2";
static const char back[] = "#282a36";
static const char border[] = "#f8f8f2";
static const char col0[] = "#000000";
static const char col1[] = "#FF5555";
static const char col2[] = "#50FA7B";
static const char col3[] = "#F1FA8C";
static const char col4[] = "#BD93F9";
static const char col5[] = "#FF79C6";
static const char col6[] = "#8BE9FD";
static const char col7[] = "#BFBFBF";
static const char col8[] = "#4D4D4D";
static const char col9[] = "#FF6E67";
static const char col10[] = "#5AF78E";
static const char col11[] = "#F4F99D";
static const char col12[] = "#CAA9FA";
static const char col13[] = "#FF92D0";
static const char col14[] = "#9AEDFE";
static const char col15[] = "#E6E6E6";
static const char spotify[]= "#1FC167";
static const char *colors[][3] = {
/* fg bg border */
[SchemeNorm] = { fore, back, back }, // \x0b
[SchemeSel] = { fore, back, border }, // \x0c
[SchemeStatus] = { fore, back, border }, // \x0d Statusbar right
[SchemeTagsSel] = { col4, back, border }, // \x0e Tagbar left selected
[SchemeTagsNorm] = { fore, back, border }, // \x0f Tagbar left unselected
[SchemeInfoSel] = { fore, back, border }, // \x10 infobar middle selected
[SchemeInfoNorm] = { fore, back, border }, // \x11 infobar middle unselected
[SchemeCol1] = { col1, back, col0 }, // \x12
[SchemeCol2] = { col2, back, col0 }, // \x13
[SchemeCol3] = { col3, back, col0 }, // \x14
[SchemeCol4] = { col4, back, col0 }, // \x15
[SchemeCol5] = { col5, back, col0 }, // \x16
[SchemeCol6] = { col6, back, col0 }, // \x17
[SchemeCol7] = { col7, back, col0 }, // \x18
[SchemeCol8] = { col8, back, col0 }, // \x19
[SchemeCol9] = { col9, back, col0 }, // \x1a
[SchemeCol10] = { col10, back, col0 }, // \x1b
[SchemeCol11] = { col11, back, col0 }, // \x1c
[SchemeCol12] = { spotify, back, col0 }, // \x1d Spotify
};
/* tagging */
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"};
//static const char *alttags[] = { "󰄯", "󰄯", "󰄯", "󰄯"};
static const Rule rules[] = {
/* xprop(1):
* WM_CLASS(STRING) = instance, class
* WM_NAME(STRING) = title
*/
/* class instance title tags mask isfloating monitor */
{ "discord", NULL, NULL, 1 << 8, 0, -1 },
{ "Termite", NULL, NULL, 1 << 0, 0, -1 },
{ "firefoxdeveloperedition", NULL, NULL, 1 << 1, 0, -1 },
{ "Tor Browser", NULL, NULL, 1 << 1, 0, -1 },
{ "Chromium", NULL, NULL, 1 << 1, 0, -1 },
{ "zoom", NULL, NULL, 1 << 4, 0, -1 },
{ "TelegramDesktop", NULL, NULL, 1 << 8, 0, -1 },
{ "whatsapp-nativefier-d52542", NULL, NULL, 1 << 8, 0, -1 },
{ "neomutt", NULL, NULL, 1 << 7, 0, -1 },
{ "Sublime_Text", NULL, NULL, 1 << 2, 0, -1 },
{ "code-oss", NULL, NULL, 1 << 2, 0, -1 },
{ "jetbrains-idea", NULL, NULL, 1 << 2, 0, -1 },
{ "Nemo", NULL, NULL, 1 << 3, 1, -1 },
{ "Spotify", NULL, NULL, 1 << 9, 0, -1 },
};
/* layout(s) */
static const float mfact = 0.5; /* factor of master area size [0.05..0.95] */
static const int nmaster = 1; /* number of clients in master area */
static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */
#include "fibonacci.c"
#include "layouts.c"
static const Layout layouts[] = {
/* symbol arrange function */
{ "鉶", tile }, /* first entry is default */
{ "", dwindle },
{ "ﱖ", grid },
{ "", centeredmaster },
{ "", centeredfloatingmaster },
{ "[M]", monocle },
{ "[D]", deck },
{ NULL, NULL },
};
/* key definitions */
#define MODKEY Mod4Mask
#define TAGKEYS(KEY,TAG) \
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
{ MODKEY|Mod1Mask, KEY, toggleview, {.ui = 1 << TAG} }, \
{ MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
{ MODKEY|ControlMask, KEY, toggletag, {.ui = 1 << TAG} },
/* COSAS QUE TENGO QUE AVERIGUAR COMO QUITAR */
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
static const char *dmenucmd[] = { "/usr/bin/rofi","-show","drun", NULL };
static const char *termcmd[] = { "/usr/bin/termite", "--title", "Terminal", NULL };
static const char *upvol[] = { "/usr/bin/pactl", "set-sink-volume", "0", "+5%", NULL };
static const char *downvol[] = { "/usr/bin/pactl", "set-sink-volume", "0", "-5%", NULL };
static const char *mutevol[] = { "/usr/bin/pactl", "set-sink-mute", "0", "toggle", NULL };
static const char *upbright[] = {"/usr/bin/xbacklight","-inc","10",NULL};
static const char *downbright[] = {"/usr/bin/xbacklight","-dec","10",NULL};
static const char *lock[] = {"/usr/bin/betterlockscreen","-l","-t","Stay the fuck out!",NULL};
static const char *clipmenu[] = {"/usr/bin/clipmenu","-i",NULL};
static const char *play[] = {"/usr/bin/playerctl","play-pause",NULL};
static const char *prev[] = {"/usr/bin/playerctl","previous",NULL};
static const char *next[] = {"/usr/bin/playerctl","next",NULL};
static const char *outmenu[] = {"/home/yigit/.scripts/dmenu-logout"};
static const char *bwmenu[] = {"/usr/bin/bwmenu", "--auto-lock", "-1"};
static const char *trackpad[] = {"/home/yigit/.scripts/toggle_touchpad.sh"};
static const char *screenshot[] = { "scrot","-d","3", "%Y-%m-%d-%s_$wx$h.jpg", "-e","xclip -selection clipboard -t image/jpg < $f; mv $f ~/Pictures/Screenshots/;dunstify -a 'SNAP' 'Email taken'", NULL };
static const char *windowshot[] = { "scrot", "-u", "-d","3", "%Y-%m-%d-%s_$wx$h.jpg", "-e","xclip -selection clipboard -t image/jpg < $f; mv $f ~/Pictures/Screenshots/;dunstify -a 'SNAP' 'Email taken'", NULL };
/* commands */
#include "movestack.c"
#include "shiftview.c"
static Key keys[] = {
/* modifier key function argument */
{ MODKEY, XK_d, spawn, {.v = dmenucmd } },
{ MODKEY, XK_p, spawn, {.v = bwmenu } },
{ MODKEY, XK_Return, spawn, {.v = termcmd } },
{ MODKEY, XK_b, togglebar, {0} },
{ MODKEY, XK_j, focusstack, {.i = +1 } },
{ MODKEY, XK_k, focusstack, {.i = -1 } },
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
{ MODKEY, XK_s, incnmaster, {.i = -1 } },
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
{ MODKEY|ShiftMask, XK_Return, zoom, {0} },
{ MODKEY, XK_Tab, view, {0} },
{ MODKEY, XK_q, killclient, {0} },
{ MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } }, /*Mover ventana hacia abajo*/
{ MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } }, /*Mover ventana hacia arriba*/
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, /*tiled*/
{ MODKEY|Mod1Mask, XK_f, setlayout, {.v = &layouts[1]} }, /*Spiral*/
{ MODKEY|Mod1Mask, XK_g, setlayout, {.v = &layouts[2]} }, /*Grid*/
{ MODKEY|Mod1Mask, XK_c, setlayout, {.v = &layouts[3]} }, /*center*/
{ MODKEY, XK_m, setlayout, {.v = &layouts[5]} }, /*monocle*/
{ MODKEY|ShiftMask, XK_m, setlayout, {.v = &layouts[6]} }, /*Deck*/
{ MODKEY, XK_s, togglefloating, {0} }, /*float*/
{ MODKEY, XK_f, togglefullscr, {0} }, /*Fullscreen*/
{ MODKEY|Mod1Mask, XK_comma, cyclelayout, {.i = -1 } }, /*Ciclar layouts*/
{ MODKEY|Mod1Mask, XK_period, cyclelayout, {.i = +1 } }, /*Ciclar layouts*/
{ MODKEY, XK_a, view, {.ui = ~0 } },
{ MODKEY|ShiftMask, XK_a, tag, {.ui = ~0 } },
{ MODKEY, XK_comma, focusmon, {.i = -1 } },
{ MODKEY, XK_period, focusmon, {.i = +1 } },
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
/*Monitores*/
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, /*Mandar ventana a monitor anterior*/
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, /*Mandar ventana a monitor siguiente*/
TAGKEYS( XK_1, 0)
TAGKEYS( XK_2, 1)
TAGKEYS( XK_3, 2)
TAGKEYS( XK_4, 3)
TAGKEYS( XK_5, 4)
TAGKEYS( XK_6, 5)
TAGKEYS( XK_7, 6)
TAGKEYS( XK_8, 7)
TAGKEYS( XK_9, 8)
TAGKEYS( XK_0, 9)
{ MODKEY|ShiftMask, XK_q, spawn, {.v = outmenu} },
{ MODKEY|ShiftMask, XK_t, spawn, {.v = trackpad} },
{ MODKEY, XK_x, spawn, {.v = lock } },
{ MODKEY, XK_c, spawn, {.v = clipmenu } },
{ 0, XF86XK_AudioLowerVolume, spawn, {.v = downvol } },
{ 0, XF86XK_MonBrightnessUp, spawn, {.v = upbright } },
{ 0, XF86XK_MonBrightnessDown, spawn, {.v = downbright } },
{ 0, XF86XK_AudioMute, spawn, {.v = mutevol } },
{ 0, XF86XK_AudioRaiseVolume, spawn, {.v = upvol } },
{ 0, XF86XK_AudioPrev, spawn, {.v = prev } },
{ 0, XF86XK_AudioPlay, spawn, {.v = play } },
{ 0, XF86XK_AudioNext, spawn, {.v = next } },
{ 0, XK_Print, spawn, {.v = screenshot } },
{ MODKEY, XK_Print, spawn, {.v = windowshot } },
};
/* button definitions */
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
static Button buttons[] = {
/* click event mask button function argument */
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
{ ClkWinTitle, 0, Button2, zoom, {0} },
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
{ ClkTagBar, 0, Button1, view, {0} },
{ ClkTagBar, 0, Button3, toggleview, {0} },
{ ClkTagBar, MODKEY, Button1, tag, {0} },
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
};
/*
static Button buttons[] = {
// click event mask button function argument
{ ClkLtSymbol, 0, Button1, cyclelayout, {.i = +1 } },
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[5]} },
{ ClkWinTitle, 0, Button2, zoom, {0} },
{ ClkStatusText, 0, Button1, sigdwmblocks, {.i = 1} },
{ ClkStatusText, 0, Button2, sigdwmblocks, {.i = 2} },
{ ClkStatusText, 0, Button3, sigdwmblocks, {.i = 3} },
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
{ ClkTagBar, 0, Button1, view, {0} },
{ ClkTagBar, 0, Button3, toggleview, {0} },
{ ClkTagBar, MODKEY, Button1, tag, {0} },
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
{ ClkClientWin, 0, Button1, winview, {0} },
};
*/

+ 5
- 0
suckless/dwm/.gitignore View File

@ -0,0 +1,5 @@
*.o
dwm
dwm-msg
config.h
patches.h

+ 23
- 1
suckless/dwm/Makefile View File

@ -6,7 +6,13 @@ include config.mk
SRC = drw.c dwm.c util.c
OBJ = ${SRC:.c=.o}
# FreeBSD users, prefix all ifdef, else and endif statements with a . for this to work (e.g. .ifdef)
ifdef YAJLLIBS
all: options dwm dwm-msg
else
all: options dwm
endif
options:
@echo dwm build options:
@ -17,16 +23,25 @@ options:
.c.o:
${CC} -c ${CFLAGS} $<
${OBJ}: config.h config.mk
${OBJ}: config.h config.mk patches.h
config.h:
cp config.def.h $@
patches.h:
cp patches.def.h $@
dwm: ${OBJ}
${CC} -o $@ ${OBJ} ${LDFLAGS}
ifdef YAJLLIBS
dwm-msg:
${CC} -o $@ patch/ipc/dwm-msg.c ${LDFLAGS}
endif
clean:
rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz
rm -f dwm-msg
dist: clean
mkdir -p dwm-${VERSION}
@ -39,7 +54,14 @@ dist: clean
install: all
mkdir -p ${DESTDIR}${PREFIX}/bin
cp -f dwm ${DESTDIR}${PREFIX}/bin
ifdef YAJLLIBS
cp -f dwm-msg ${DESTDIR}${PREFIX}/bin
endif
#cp -f patch/dwmc ${DESTDIR}${PREFIX}/bin
chmod 755 ${DESTDIR}${PREFIX}/bin/dwm
ifdef YAJLLIBS
chmod 755 ${DESTDIR}${PREFIX}/bin/dwm-msg
endif
mkdir -p ${DESTDIR}${MANPREFIX}/man1
sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1
chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1


+ 0
- 50
suckless/dwm/Makefile.bak View File

@ -1,50 +0,0 @@
# dwm - dynamic window manager
# See LICENSE file for copyright and license details.
include config.mk
SRC = drw.c dwm.c util.c
OBJ = ${SRC:.c=.o}
all: options dwm
options:
@echo dwm build options:
@echo "CFLAGS = ${CFLAGS}"
@echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}"
.c.o:
${CC} -c ${CFLAGS} $<
${OBJ}: config.h config.mk
config.h:
cp config.def.h $@
dwm: ${OBJ}
${CC} -o $@ ${OBJ} ${LDFLAGS}
clean:
rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz
dist: clean
mkdir -p dwm-${VERSION}
cp -R LICENSE Makefile README config.def.h config.mk\
dwm.1 drw.h util.h ${SRC} dwm.png transient.c dwm-${VERSION}
tar -cf dwm-${VERSION}.tar dwm-${VERSION}
gzip dwm-${VERSION}.tar
rm -rf dwm-${VERSION}
install: all
mkdir -p ~/.local
cp -f dwm ~/.local
chmod 755 ~/.local/dwm
# pkill dwm
# ~/.local/dwmblocks &
uninstall:
rm -f ${DESTDIR}${PREFIX}/bin/dwm\
${DESTDIR}${MANPREFIX}/man1/dwm.1
.PHONY: all options clean dist install uninstall

+ 48
- 0
suckless/dwm/README View File

@ -0,0 +1,48 @@
dwm - dynamic window manager
============================
dwm is an extremely fast, small, and dynamic window manager for X.
Requirements
------------
In order to build dwm you need the Xlib header files.
Installation
------------
Edit config.mk to match your local setup (dwm is installed into
the /usr/local namespace by default).
Afterwards enter the following command to build and install dwm (if
necessary as root):
make clean install
Running dwm
-----------
Add the following line to your .xinitrc to start dwm using startx:
exec dwm
In order to connect dwm to a specific display, make sure that
the DISPLAY environment variable is set correctly, e.g.:
DISPLAY=foo.bar:1 exec dwm
(This will start dwm on display :1 of the host foo.bar.)
In order to display status info in the bar, you can do something
like this in your .xinitrc:
while xsetroot -name "`date` `uptime | sed 's/.*,//'`"
do
sleep 1
done &
exec dwm
Configuration
-------------
The configuration of dwm is done by creating a custom config.h
and (re)compiling the source code.

+ 0
- 32
suckless/dwm/README.es.org View File

@ -1,32 +0,0 @@
* Dynamic Window Manager
Este es mi propio build de DWM, con algunos parches y configuraciones.
*** Parches
**** Funcionales
Aquellos parches que añaden nuevas funciones a DWM, algunas de ellas son funciones sencillas que están presentes en otros TWM.
- [[https://dwm.suckless.org/patches/actualfullscreen/dwm-actualfullscreen-20191112-cb3f58a.diff][actualfullscreen:]] Permite activar verdadera pantalla completa en lugar de solo activar el modo monocle y esconder el panel.
- [[https://dwm.suckless.org/patches/alwayscenter/][alwayscenter]]: Las ventanas flotantes siempre se colocan al centro de la pantalla.
- [[https://dwm.suckless.org/patches/cyclelayouts/dwm-cyclelayouts-20180524-6.2.diff][cyclelayouts:]] Pasa por la lista de layouts con una combinación de botones.
- [[https://dwm.suckless.org/patches/inplacerotate/][inplacerotate]]: Permite rotar las ventanas en el stack sin cambiar master.
- [[https://dwm.suckless.org/patches/movestack/dwm-movestack-6.1.diff][movestack:]] Permite mover las ventanas en la parte stack, cuando se usa el esquema por defecto.
- [[https://dwm.suckless.org/patches/pertag/dwm-pertag-20170513-ceac8c9.diff][pertag:]] Por defecto, dwm usa el mismo esquema para todos los tags. Con este parche cada tag tiene un esquema diferente (el esquema inicial es tile).
- [[https://dwm.suckless.org/patches/switchcol/][switchcol:]] Permite cambiar el foco entre master y stack con un solo /keybinding/. Útil con el layout /deck/.
- [[https://dwm.suckless.org/patches/winview/][winview]]: Si están viendo varios tags a la vez, al presionar un /keybinding/ se cambia al tag de la ventana enfocada.
**** Layouts
Son aquellas /layouts/ nuevas que he agregado a DWM.
- [[https://dwm.suckless.org/patches/centeredmaster/][centeredmaster:]] La ventana /master/ se coloca en el centro mientras las otras aparecen en rejilla alrededor.
- [[https://dwm.suckless.org/patches/deck/][deck:]] La parte /stack/ solo muestra una ventana a la vez. Si se usa con /inplacerotate/ es posible cambiar la ventana en el /stack/ sin mover /master/.
- [[https://dwm.suckless.org/patches/fibonacci/dwm-fibonacci-5.8.2.diff][fibonacci:]] Dos esquemas nuevos: spiral y dwindle (à la bspwm).
- [[https://dwm.suckless.org/patches/gridmode/dwm-gridmode-20170909-ceac8c9.diff][gridmode:]] Esquema de rejilla para.
- [[https://dwm.suckless.org/patches/rmaster/dwm-rmaster-6.1.diff][rmaster:]] Permite invertir el orden del esquema tile: master a la izquierda y stack a la derecha.
**** Estéticos
Parches que unicamente sirven para mejorar el aspecto estético del WM y aportan poco o nada al aspecto funcional.
- [[https://dwm.suckless.org/patches/alttagsdecoration/][alttagsdecoration]]: Permite declarar íconos diferentes para cada tag cuando están ocupados.
- [[https://dwm.suckless.org/patches/colorbar/][colorbar]]: Añade esquemas de colores nuevos para cada sección del panel.
- [[https://github.com/ashish-yadav11/dwmblocks][dwmblocks]]: Agrega soporte para texto coloreado y poder presionar en los módulos.
- [[https://dwm.suckless.org/patches/alpha/dwm-fixborders-6.2.diff][fixborders]]: Arregla los bordes transparentes cuando se usa compton/picom.
- [[https://dwm.suckless.org/patches/uselessgap/dwm-uselessgap-6.2.diff][uselessgap:]] Añade separaciones inútiles entre ventanas. Apesar de no ser el único parche, si es el más sencillo de aplicar.

+ 690
- 0
suckless/dwm/README.md View File

@ -0,0 +1,690 @@
This dwm 6.2 (bb2e72, 2020-07-08) side project has a different take on dwm patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. Due to the complexity of some of the patches dwm-flexipatch has diverged from mainstream dwm by making some core patches non-optional for maintenance reasons. For the classic dwm-flexipatch build refer to branch [dwm-flexipatch-1.0](https://github.com/bakkeby/dwm-flexipatch/tree/dwm-flexipatch-1.0).
For example to include the `alpha` patch then you would only need to flip this setting from 0 to 1 in [patches.h](https://github.com/bakkeby/dwm-flexipatch/blob/master/patches.def.h):
```c
#define BAR_ALPHA_PATCH 1
```
So if you have ever been curious about trying out dwm, but have been discouraged by manual patching, then this may be a good starting point to see what a "fully fledged" dwm can look like. Want to try out the `pertag` patch? Just flip a config and recompile. Once you have found out what works for you and what doesn't then you should be in a better position to choose patches should you want to start patching from scratch.
Alternatively if you have found the patches you want, but don't want the rest of the flexipatch entanglement on your plate then you may want to have a look at [flexipatch-finalizer](https://github.com/bakkeby/flexipatch-finalizer); a custom pre-processor tool that removes all the unused flexipatch code leaving you with a build that contains the patches you selected.
Refer to [https://dwm.suckless.org/](https://dwm.suckless.org/) for details on the dwm window manager, how to install it and how it works.
---
### Changelog:
2021-02-11 - Added the riodraw and focusdir patches
2021-01-22 - Added the placemouse patch
2021-01-02 - Added the Layoutmenu patch
2020-10-26 - Added the \_NET\_CLIENT\_LIST\_STACKING patch
2020-09-29 - Added the on\_empty\_keys patch (ported from InstantOS)
2020-09-28 - Added the \_IS\_FLOATING patch (embedded in the EWMHTAGS patch)
2020-09-18 - Added the nomodbuttons patch allowing for toggleable mouse button bindings that have no modifiers
2020-09-10 - Added the anybar patch (with experimental support for dwm bar(s) + anybar)
2020-09-09 - Added the bar border patch
2020-09-08 - Added ipc v1.5.5 patch
2020-09-07 - Scratchpads improvement (multi-monitor support)
2020-09-05 - Assortment of fullscreen improvements
2020-08-27 - Added aspectresize patch
2020-08-25 - Unified tag icon handling while adding support for different icons per monitor. Added alttagsdecoration patch.
2020-08-22 - Added logic to auto-hide bars if nothing is drawn on them (e.g. for standalone bars that only show certain clients). Added clientindicators patch and unified indicator code. Simplified Pango integration by settling on common function signatures.
2020-08-21 - Simplification of color configuration; settling on a set of color schemes that is shared between multiple patches (urgentborder, floatborder and titlecolor patches made non-optional)
2020-08-20 - Added experimental flexwintitle patch based on bartabgroups
2020-08-13 - Added bartabgroups patch
2020-08-11 - Added decoration hints and focusmaster patches
2020-08-10 - Added cool autostart, insets and steam patches
2020-08-02 - Added reorganizetags patch
2020-07-19 - Added barmodules patch - making extrabar, leftlayout, staticstatus and statusallmons patches redundant, added powerline patch
2020-07-18 - **Note**: Up until now building dwm-flexipath without any patches selected would have given you something more or less identical with mainstream dwm. In order to reduce complexity when it comes to maintainance future versions of dwm-flexipatch may diverge from this by making some patches non-optional. For the classic dwm-flexipatch and its many patch integration hints refer to branch [dwm-flexipatch-1.0](https://github.com/bakkeby/dwm-flexipatch/tree/dwm-flexipatch-1.0) which will be subject to bug fixes and mainstream dwm updates as far as feasible.
2020-07-05 - Extrabar compatibility improvements (staticstatus, status2d, dwmblocks) and fix for systray randomly causing dwm to crash when first systray application starts
2020-06-24 - Added resizepoint, statusbutton and sendmon_keepfocus patches
2020-06-21 - Added floatpos and bar_height patches
2020-06-19 - Added tagothermonitor patch
2020-06-15 - Added sizehints patch
2020-06-14 - Added RULE macro to replace rules setup making the default config less of an abomination and making it simpler to include new rules based patches
2020-06-11 - Added the pango patch
2020-06-10 - Added the staticstatus patch
2020-05-31 - Added the keymodes patch
2020-05-29 - Added the color emoji patch
2020-05-26 - Added the status2d patch (with alpha, systray, statuspadding and dwmblocks compatibility, no statuscolors or extrabar compatibility)
2020-05-21 - Added the moveplace and moveresize patches
2020-05-03 - Added the shiftviewclients patch and the no transparent borders patch which removes opacity from window borders when the alpha patch is not used
2020-05-02 - Added dwmblocks patch
2020-04-27 - Upgraded the tagmonfixfs patch to better support moving fullscreen windows to adjacent monitors
2020-04-26 - Expanded monitor rules patch to include nmaster, showbar and topbar options
2020-04-23 - Improved swallow and switchtag compatibility
2020-04-16 - Upgraded the scratchpad patch to the multiple scratchpads patch \[[ref](https://lists.suckless.org/hackers/2004/17205.html)\]. Updated the statuscolors patch with the width computation fix \[[ref](https://lists.suckless.org/hackers/2004/17207.html)\].
2020-04-13 - Added statuscmd patch
2020-03-31 - Added the rounded corners patch
2020-03-27 - Revamped the dragmfact patch to support both horizontal and vertical layout splits as well as centered master variants
2020-03-25 - Added dragcfact patch
2020-03-23 - Added stacker patch
2020-03-21 - Reworked a series of layouts to re-allocate remaining pixels following an even (or cfacts) split with the aim of presenting a pixel perfect layout. This affects the following layouts: tile, bstack, bstackhoriz, centered master, centered floating master, columns, deck, and corresponding flextile-deluxe layouts
2020-02-11 - Added swaptags and vtcolor patches
2020-02-09 - Added alternative scratchpad patch
2020-02-02 - Added fsignal and transferall patches
2020-01-29 - Added swapfocus and shiftview patches
2020-01-26 - Added transfer patch
2020-01-24 - Added barpadding patch (incl. statusallmons, statuspadding, statuscolors, systray, alpha, holdbar and extrabar patch compatibility). Moved patches.h to patches.def.h to mimic the config pattern of having default and personal settings.
2020-01-17 - Added inplacerotate patch
2019-12-15 - Updated dragmfact patch to include fix patch to make it work with multiple monitors
2019-11-26 - Added dmenumatchtop patch, added improvements to the switchtag patch based on ideas from the switchtotag patch
2019-11-21 - Added fakefullscreenclient patch
2019-10-24 - Added dragmfact, extrabar, exresize and nodmenu patches
2019-10-22 - Added ispermanent and swallow patches
2019-10-16 - Introduced [flexipatch-finalizer](https://github.com/bakkeby/flexipatch-finalizer)
2019-10-11 - Added the patch to ignore Xft errors when drawing text in the status bar
2019-10-10 - Added mpdcontrol, scratchpad and spawn_cwd cpatches
2019-10-08 - Added columns layout and fakefullscreen patch
2019-10-07 - Added sortscreens and dwmc patches, fixed minor cross-compatibility issues for combo, holdbar, leftlayout, hidevacanttags, taggrid and activetagindicatorbar
2019-10-06 - Added statuscolors and statusallmons patches, fixed minor cross-compatibility issues for killunsel, fullscreen, noborder, tagintostack patches
2019-10-05 - Added killunsel, taggrid, hidevacanttags and cmdcustomize patches
2019-10-04 - Added maximize, movestack, monoclesymbol, noborder, tagall and tagintostack patches
2019-10-03 - Added onlyquitonempty and switchcol patches
2019-10-02 - Added restartsig, emptyview, focusurgent and focusadjacenttag patches
2019-10-01 - Added leftlayout, fullscreen, holdbar and unfloatvisible patches
2019-09-30 - Replaced flextile with flextile-deluxe, refactored monitor rules to support predetermined layouts per tag
2019-09-15 - Added focusonclick, xrdb, viewontag, urgentborder and winview patches
2019-09-14 - Added setborderpx, selfrestart and push (no master variant), sticky and warp patches
2019-09-13 - Added titlecolor and push patches
2019-09-12 - Added activetagindicatorbar, alwaysfullscreen and autoresize patches
2019-09-11 - Added monitor rules, combo and ewmhtags patches
2019-09-10 - Minor tweaks to awesomebar patch (incl. alpha and systray compatibility). Added floatbordercolor patch.
2019-09-09 - Added deck, fibonacci (dwindle and spiral), gridmode, gapplessgrid, horizgrid, nrowgrid, centeredmaster and flextile layouts. Added alternativetags and awesomebar patches.
2019-09-08 - Added cfacts and vanitygaps patches, added bstack and bstackhoriz layouts
2019-09-07 - Added cyclelayouts, resizecorners, rotatestack, savefloats, statuspadding, switchtag, center and windowrolerule patches
2019-09-06 - Added attachabove, attachaside, attachbelow, attachbottom, autostart, fancybar, focusonnetactive and losefullscreen patches
2019-09-05 - Alpha, systray, togglefullscreen, tagallmon, tagmonfixfs, tagswapmon, pertag and zoomswap patches added
### Patches included:
- [activetagindicatorbar](https://dwm.suckless.org/patches/activetagindicatorbar/)
- this patch changes the rectangle indicating if a tag is used by a client into a bar above the tag name
- [alpha](https://dwm.suckless.org/patches/alpha/)
- adds transparency for the status bar
- [alternativetags](https://dwm.suckless.org/patches/alternativetags/)
- adds alternative tags which can be toggled on the fly for the sole purpose of providing visual aid
- [alttagsdecoration](https://dwm.suckless.org/patches/alttagsdecoration/)
- provides the ability to use alternative text for tags which contain at least one window
- [alwaysfullscreen](https://dwm.suckless.org/patches/alwaysfullscreen/)
- prevents the focus to drift from the active fullscreen client when using focusstack\(\)
- [anybar](https://dwm.suckless.org/patches/anybar/)
- enables dwm to manage external status bars such as lemonbar and polybar
- dwm treats the external bar as it would its own, so all regular dwm commands such as togglebar affect the external bar in the same way
- [aspectresize](https://dwm.suckless.org/patches/aspectresize/)
- allows windows to be resized with its aspect ratio remaining constant
- [attachabove](https://dwm.suckless.org/patches/attachabove/)
- new windows are placed above selected client
- [attachaside](https://dwm.suckless.org/patches/attachaside/)
- new windows are placed on top of the stack
- [attachbelow](https://dwm.suckless.org/patches/attachbelow/)
- new windows are placed below selected client
- [attachbottom](https://dwm.suckless.org/patches/attachbottom/)
- new windows are placed at the bottom of the stack
- [autoresize](https://dwm.suckless.org/patches/autoresize/)
- by default, windows that are not visible when requesting a resize/move will not get resized/moved, with this patch, however, they will
- [autostart](https://dwm.suckless.org/patches/autostart/)
- makes dwm run `~/.dwm/autostart_blocking.sh` and `~/.dwm/autostart.sh &` on startup
- [awesomebar](https://dwm.suckless.org/patches/awesomebar/)
- enhanced taskbar that allows focus / hiding / unhiding of windows by clicking on the status bar
- [bar_border](https://codemadness.org/paste/dwm-border-bar.patch)
- adds a border around the bar similarly to how client windows have borders
- [bar_height](https://dwm.suckless.org/patches/bar_height/)
- allows the bar height to be explicitly set rather than being derived from font
- [barmodules](https://github.com/bakkeby/patches/wiki/barmodules/)
- splits the dwm bar into modules allowing for re-arrangement of the bar and easier integration for new features
- [barpadding](https://dwm.suckless.org/patches/barpadding/)
- adds vertical and horizontal space between the statusbar and the edge of the screen
- [bartabgroups](https://dwm.suckless.org/patches/bartabgroups/)
- turns the titlebar area into a mfact-respecting tab-bar showing each client's title
- [center](https://dwm.suckless.org/patches/center/)
- adds an iscentered rule to automatically center clients on the current monitor
- [cfacts](https://dwm.suckless.org/patches/cfacts/)
- the cfacts patch provides the ability to assign different weights to clients in their respective stack in tiled layout
- [clientindicators](https://dwm.suckless.org/patches/clientindicators/)
- draws a dot indicator overlayed on each tag icon for each client
- the selected client is drawn as a larger horizontal line
- [cmdcustomize](https://dwm.suckless.org/patches/cmdcustomize/)
- allows color attributes to be set through the command line
- [colorbar](https://dwm.suckless.org/patches/colorbar/)
- lets you change the foreground and background color of every statusbar element
- color_emoji
- enables color emoji in dmenu by removing a workaround for a BadLength error in the Xft library when color glyphs are used
- enabling this will crash dwm on encountering such glyphs unless you also have an updated Xft library that can handle them
- [combo](https://dwm.suckless.org/patches/combo/)
- allows you to select multiple tags by pressing all the right keys as a combo, e.g. hold MOD and press and hold 1 and 3 together to view those two tags
- [cool_autostart](https://dwm.suckless.org/patches/cool_autostart/)
- allows dwm to execute commands from an array in the config.h file
- when dwm exits all processes from the autostart array will be killed automatically
- [cyclelayouts](https://dwm.suckless.org/patches/cyclelayouts/)
- lets you cycle through all your layouts
- [decoration_hints](https://dwm.suckless.org/patches/decoration_hints/)
- make dwm respect \_MOTIF\_WM\_HINTS property, and not draw borders around windows requesting for it
- some applications use this property to notify window managers to not draw window decorations
- not respecting this property leads to issues with applications that draw their own borders, like chromium (with "Use system title bar and borders" turned off) or vlc in fullscreen mode
- [dmenumatchtop](https://dwm.suckless.org/patches/dmenumatchtop)
- updates the position of dmenu to match that of the bar
- i.e. if topbar is 0 then dmenu will appear at the bottom and if 1 then dmenu will appear at the top
- [dragcfact](https://github.com/bakkeby/patches/wiki/dragcfact/)
- lets you resize clients' size (i.e. modify cfact) by holding modkey + shift + right-click and dragging the mouse
- [dragmfact](https://github.com/bakkeby/patches/wiki/dragmfact/)
- lets you resize the split in layouts (i.e. modify mfact) by holding the modkey + shift + left-click and dragging the mouse
- this is a bespoke patch that supports vertical and horizontal layout splits as well as centered master variants
- [dwmblocks](https://gist.github.com/danbyl/54f7c1d57fc6507242a95b71c3d8fdea)
- signal integration to use dwm with a patched [dwmblocks](https://github.com/torrinfail/dwmblocks)
- combined with the statuscmd patch this gives a clickable statusbar
- [dwmc](http://dwm.suckless.org/patches/dwmc/)
- a simple dwmc client using a fork of fsignal to communicate with dwm
- [emptyview](https://dwm.suckless.org/patches/emptyview/)
- allows no tag at all to be selected
- dwm will start with no tag selected and when a client with no tag rule is started and no tag is selected then it will be opened on the first tag
- [ewmhtags](https://dwm.suckless.org/patches/ewmhtags/)
- adds EWMH support for \_NET_NUMBER_OF_DESKTOPS, \_NET_CURRENT_DESKTOP, \_NET_DESKTOP_NAMES and \_NET_DESKTOP_VIEWPORT, which allows for compatibility with other bars and programs that request workspace information, e.g. polybar's xworkspaces module
- [exresize](https://dwm.suckless.org/patches/exresize/)
- this patch 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
- [~extrabar~](https://dwm.suckless.org/patches/extrabar/)
- ~enables an extra status bar in dwm in a similar manner to the dualstatus patch~
- ~if the primary status is at the top via topbar then the extra status bar will be placed at the bottom and vice versa~
- extrastatus
- formerly extrabar - now only splits the status into to statuses by using a status separator
- [fakefullscreen](https://dwm.suckless.org/patches/fakefullscreen/)
- only allow clients to "fullscreen" into the space currently given to them
- as an example, this will allow you to view a fullscreen video in your browser on one half of the screen, while having the other half available for other tasks
- [fakefullscreenclient](https://github.com/bakkeby/patches/wiki/fakefullscreenclient/)
- similarly to the fakefullscreen patch this patch only allows clients to "fullscreen" into the space currently given to them
- as an example, this will allow you to view a fullscreen video in your browser on one half of the screen, while having the other half available for other tasks
- the "twist" with this patch is that fake fullscreen can be toggled on a per client basis rather than applying to all clients globally
- [fancybar](https://dwm.suckless.org/patches/fancybar/)
- shows the titles of all visible windows in the status bar
- flexwintitle
- based on the bartabgroups patch, this is a layout aware barmodules module for handling window titles intended to be used with flextile-deluxe
- [~floatbordercolor~](https://dwm.suckless.org/patches/float_border_color/)
- ~this patch allows a different border color to be chosen for floating windows~
- [floatpos](https://github.com/bakkeby/patches/wiki/floatpos/)
- adds a float rule allowing the size and position of floating windows to be specified
- control the size and position of floating windows similar to exresize, moveresize, moveplace patches
- specify size and position using absolute, relative or fixed co-ordinates or
- position floating windows in a grid-like manner
- [focusadjacenttag](https://dwm.suckless.org/patches/focusadjacenttag/)
- 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
- [focusdir](https://github.com/bakkeby/patches/wiki/focusdir)
- allows focusing on clients based on direction (up, down, left, right) instead of client order
- [focusmaster](https://dwm.suckless.org/patches/focusmaster/)
- a simple patch that just puts focus back to the master client
- [focusonclick](https://dwm.suckless.org/patches/focusonclick/)
- this patch makes you switch focus only by mouse click and not sloppy (focus follows mouse pointer)
- [focusonnetactive](https://dwm.suckless.org/patches/focusonnetactive/)
- by default, dwm responds to \_NET_ACTIVE_WINDOW client messages by setting the urgency bit on the named window
- this patch activates the window instead
- [focusurgent](https://dwm.suckless.org/patches/focusurgent/)
- adds a keyboard shortcut to select the next window having the urgent flag regardless of the tag it is on
- [fsignal](https://dwm.suckless.org/patches/fsignal/)
- send "fake signals" to dwm for handling, using xsetroot
- this will not conflict with the status bar, which also is managed using xsetroot
- [fullscreen](https://dwm.suckless.org/patches/fullscreen/)
- applies the monocle layout with the focused client on top and hides the bar
- when pressed again it shows the bar and restores the layout that was active before going fullscreen
- [hidevacanttags](https://dwm.suckless.org/patches/hide_vacant_tags/)
- prevents dwm from drawing tags with no clients (i.e. vacant) on the bar
- [holdbar](http://dwm.suckless.org/patches/holdbar/)
- with this patch dwm's built-in status bar is only shown when HOLDKEY is pressed
- additionally the bar will now overlay the display
- [ignore-xft-errors-when-drawing-text](https://groups.google.com/forum/m/#!topic/wmii/7bncCahYIww)
- sometimes dwm crashes when it cannot render some glyphs in window titles (usually emoji)
- this patch is essentially a hack to ignore any errors when drawing text on the status bar and may be removed if a more appropriate solution comes up
- [inplacerotate](https://dwm.suckless.org/patches/inplacerotate/)
- allows rotation of all clients in the master or stack area without affecting the other area
- [insets](https://dwm.suckless.org/patches/insets/)
- lets custom insets from each edge of the screen to be defined
- an example use case would be to make space for an external bar
- [ipc](https://github.com/mihirlad55/dwm-ipc)
- implements inter-process communication through a UNIX socket for dwm
- allows for the window manager to be queried for information, e.g. listen for events such as tag or layout changes, as well as send commands to control the window manager via other programs
- [\_IS\_FLOATING](https://github.com/bakkeby/dwm-flexipatch/issues/50)
- adds the \_IS\_FLOATING xproperty for floating windows
- this can allow for a compositor to handle floating windows differently to tiled windows, e.g. only show shadows on floating windows
- this patch is enabled via the ewmhtags patch
- [ispermanent](https://dwm.suckless.org/patches/ispermanent/)
- adds rule option for clients to avoid accidental termination by killclient for sticky windows
- [keymodes](https://dwm.suckless.org/patches/keymodes/)
- this patch adds key modes (like in vim or emacs) where chains of keyboard shortcuts can be performed
- [~leftlayout~](http://dwm.suckless.org/patches/leftlayout/)
- ~moves the layout symbol in the status bar to the left hand side~
- [losefullscreen](https://github.com/bakkeby/patches/wiki/losefullscreen/)
- by default in dwm it is possible to make an application fullscreen, then use the focusstack keybindings to focus on other windows beneath the current window
- it is also possible to spawn new windows (e.g. a terminal) that end up getting focus while the previous window remains in fullscreen
- this patch ensures that in such scenarios the previous window loses fullscreen
- [maximize](https://dwm.suckless.org/patches/maximize/)
- adds helper functions for maximizing, horizontally and vertically, floating windows using keybindings
- [mpdcontrol](https://dwm.suckless.org/patches/mpdcontrol/)
- adds keyboard bindings to control MDP (Music Player Daemon)
- [monitorrules](https://github.com/bakkeby/patches/wiki/monitorrules/)
- adds rules per monitor, e.g. have default layouts per monitor
- the use case for this is if the second monitor is vertical (i.e. rotated) then you may want to use a different default layout for this monitor than what is used for the main monitor (for example normal vertical split for main monitor and horizontal split for the second)
- [monoclesymbol](https://dwm.suckless.org/patches/monoclesymbol/)
- always display the the monocle-symbol as defined in config.h if the monocle-layout is activated
- do not display the number of open clients in the current tag
- [moveresize](https://dwm.suckless.org/patches/moveresize/)
- allows you to move and resize dwm's clients using keyboard bindings
- [movestack](https://dwm.suckless.org/patches/movestack/)
- allows you to move clients around in the stack and swap them with the master
- [netclientliststacking](https://github.com/bakkeby/patches/wiki/netclientliststacking)
- adds support for the \_NET\_CLIENT\_LIST\_STACKING atom, needed by certain applications like the Zoom video conferencing application
- [noborder](https://dwm.suckless.org/patches/noborder/)
- removes the border when there is only one window visible
- [nodmenu](https://dwm.suckless.org/patches/nodmenu/)
- enable modifying dmenu in config.def.h which resulted previously in a compilation error because two lines of code hardcode dmenu into dwm
- allows complete removal of dmenu, should you want to do that
- nomodbuttons
- allows for toggleable client button bindings that have no modifiers
- this can, for example, allow you to move or resize using the mouse alone without holding down a modifier key, which can be practical if you have extra buttons on your mouse
- [no_transparent_borders](https://github.com/szatanjl/dwm/commit/1529909466206016f2101457bbf37c67195714c8)
- when terminals have transparency then their borders also become transparent
- this patch ensures that borders have no transparency
- note that this patch is only relevant if you are not using the alpha patch
- [on\_empty\_keys](https://github.com/bakkeby/dwm-flexipatch/issues/51)
- port of InstantVM's on_empty_keys functionality allowing keybindings that apply only when a tag/view is empty
- an example use case is being able to launch applications with first hand keys like "f" to launch firefox
- [onlyquitonempty](https://dwm.suckless.org/patches/onlyquitonempty/)
- makes it so dwm will only exit via quit() if no windows are open (in order to prevent accidental loss of work)
- [pango](https://dwm.suckless.org/patches/pango/)
- adds simple markup for status messages using pango markup
- [pertag](https://dwm.suckless.org/patches/pertag/)
- adds nmaster, mfact, layouts and more per tag rather than per monitor
- [placemouse](https://github.com/bakkeby/patches/wiki/placemouse)
- lets the user change the position of a client in the stack using the mouse.
- [powerline](https://gitlab.com/udiboy1209-suckless/dwm/-/commit/071f5063e8ac4280666828179f92788d893eea40#4b1a539194be7467cefbda22f675a3b7c19ceca7)
- adds drawing of powerline arrows (and diagonal lines) for both the status bar and the tags
- [push](https://dwm.suckless.org/patches/push/)
- this patch provides a way to move clients up and down inside the client list
- [reorganizetags](https://dwm.suckless.org/patches/reorganizetags/)
- shifts all clients per tag to leftmost unoccupied tags
- e.g. if clients A, B, C are tagged on tags 1, 5, 9 respectively, when reorganized they will now be on tag 1, 2, and 3
- [resizecorners](https://dwm.suckless.org/patches/resizecorners/)
- by default, windows only resize from the bottom right corner
- with this patch the mouse is warped to the nearest corner and you resize from there
- [resizepoint](https://github.com/bakkeby/patches/wiki/resizepoint/)
- practically the same as resizecorners, but the cursor does not warp to any of the window corners
- [restartsig](https://dwm.suckless.org/patches/restartsig/)
- adds a keyboard shortcut to restart dwm or alternatively by using kill -HUP dwmpid
- additionally dwm can quit cleanly by using kill -TERM dwmpid
- [riodraw](https://github.com/bakkeby/patches/wiki/riodraw/)
- adds rio-like drawing to spawn new windows or to resize the selected client (backported from instantWM)
- depends on an external tool slop being installed
- [rotatestack](https://dwm.suckless.org/patches/rotatestack/)
- let's you rotate through the stack using keyboard shortcuts
- [roundedcorners](https://github.com/mitchweaver/suckless/blob/master/dwm/patches/mitch-06-rounded_corners-f04cac6d6e39cd9e3fc4fae526e3d1e8df5e34b2.patch)
- adds rounded corners to client windows
- [savefloats](https://dwm.suckless.org/patches/save_floats/)
- saves size and position of every floating window before it is forced into tiled mode
- if the window is made floating again then the old dimensions will be restored
- [scratchpad](https://dwm.suckless.org/patches/scratchpad/)
- the scratchpad patch allows you to spawn or restore a floating terminal window
- [scratchpad_alt_1](https://github.com/GasparVardanyan/dwm-scratchpad)
- this alternative patch enables a scratchpad feature in dwm similar to the scratchpad feature in i3wm
- [selfrestart](https://dwm.suckless.org/patches/selfrestart/)
- restart dwm without the unnecessary dependency of an external script
- [sendmon_keepfocus](https://github.com/bakkeby/patches/wiki/sendmon_keepfocus/)
- minor patch that allow clients to keep focus when being sent to another monitor
- [setborderpx](https://dwm.suckless.org/patches/setborderpx/)
- this patch allows border pixels to be changed during runtime
- [shiftview](https://github.com/chau-bao-long/dotfiles/blob/master/suckless/dwm/shiftview.diff)
- adds keybindings for left and right circular shift through tags
- also see focusadjacenttag
- [shiftviewclients](https://github.com/bakkeby/patches/wiki/shiftviewclients/)
- variant of the shiftview patch which skips tags that have no clients
- [sizehints](https://dwm.suckless.org/patches/sizehints/)
- makes dwm obey even "soft" sizehints for new clients
- [sortscreens](https://www.mail-archive.com/hackers@suckless.org/msg09400.html)
- this patch aims to address some inconsistencies when it comes to focusmon, tagmon and similar functionality by explicitly sorting screens left to right (or top to bottom in a vertical layout)
- [spawn_cwd](https://dwm.suckless.org/patches/spawn_cwd/)
- spawns programs from currently focused client's working directory
- [stacker](https://dwm.suckless.org/patches/stacker/)
- provides comprehensive utilities for managing the client stack
- [~staticstatus~](https://dwm.suckless.org/patches/staticstatus/)
- ~allows the status text to be fixed to the bar on a specific monitor rather than being drawn on the focused monitor~
- [status2d](https://dwm.suckless.org/patches/status2d/)
- allows colors and rectangle drawing in the dwm status bar
- [~statusallmons~](https://dwm.suckless.org/patches/statuspadding/)
- ~this patch draws and updates the statusbar on all monitors~
- [statusbutton](https://dwm.suckless.org/patches/statusbutton/)
- adds a clickable button to the left hand side of the statusbar
- [statuscmd](https://dwm.suckless.org/patches/statuscmd/)
- adds the ability to execute shell commands based on the mouse button and position when clicking the status bar
- [statuscolors](https://dwm.suckless.org/patches/statuscolors/)
- enables colored text in the status bar allowing multiple color combinations for use in the status script
- [statuspadding](https://dwm.suckless.org/patches/statuspadding/)
- adds configuration options for horizontal and vertical padding in the status bar
- [steam](https://github.com/bakkeby/patches/wiki/steam)
- a minor patch that works around the issue of floating Steam windows jumping around the screen when they receive focus
- [sticky](https://dwm.suckless.org/patches/sticky/)
- adds toggleable keyboard shortcut to make a client 'sticky', i.e. visible on all tags
- [swallow](https://dwm.suckless.org/patches/swallow/)
- this patch adds "window swallowing" to dwm as known from Plan 9's windowing system rio
- clients marked with isterminal in config.h swallow a window opened by any child process, e.g. running xclock in a terminal
- closing the xclock window restores the terminal window in the current position
- [swapfocus](https://dwm.suckless.org/patches/swapfocus/)
- this patch depends on the pertag patch and makes it possible to switch focus with a single shortcut (mod-s) instead of having to think if you should use mod-j or mod-k for reaching the previously used window
- [swaptags](https://dwm.suckless.org/patches/swaptags/)
- allows swapping the contents of the currently selected tag with another tag by using keyboard shortcuts
- [switchcol](https://dwm.suckless.org/patches/switchcol/)
- allows you to switch focus between the master and stack columns using a single keybinding
- [switchtag](https://github.com/bakkeby/patches/wiki/switchtag/)
- when an application opens on a specific tab this patch adds the option to also switch to that tag when the application starts
- optionally, the previous view can also be restored when the client is closed
- [systray](https://dwm.suckless.org/patches/systray/)
- adds system tray in the status bar
- [tagall](https://dwm.suckless.org/patches/tagall/)
- adds keyboard shortcuts to move all (or only floating) windows from one tag to another
- [tagallmon](https://github.com/bakkeby/patches/wiki/tagallmon/)
- move all visible windows to an adjacent monitor
- [tagintostack](https://dwm.suckless.org/patches/tagintostack/)
- makes new clients attach into the stack area when you toggle a new tag into view
- this means your master area will remain unchanged when toggling views
- [taggrid](https://dwm.suckless.org/patches/taggrid/)
- adds an option to place tags in rows like in many other window managers
- [tagmonfixfs](https://github.com/bakkeby/patches/wiki/tagmonfixfs/)
- allows moving a fullscreen window to another monitor while remaining in fullscreen
- [tagothermonitor](https://dwm.suckless.org/patches/tagothermonitor/)
- adds functions and keybindings to tag a window to a desired tag on an adjacent monitor
- [tagswapmon](https://github.com/bakkeby/patches/wiki/tagswapmon/)
- swap all visible windows on one monitor with those of an adjacent monitor
- [~titlecolor~](https://dwm.suckless.org/patches/titlecolor/)
- ~adds a new color scheme used by the (selected) window title in the bar~
- [togglefullscreen](https://github.com/bakkeby/patches/wiki/togglefullscreen/)
- allows you to toggle fullscreen on and off using a single shortcut key
- [transfer](https://dwm.suckless.org/patches/transfer/)
- lets you transfer the currently focused client between the master and stack area while increasing or decreasing the master area (nmaster) accordingly
- [transferall](https://dwm.suckless.org/patches/transfer/)
- lets you transfer all clients between the master and stack area while increasing or decreasing the master area (nmaster) accordingly
- [unfloatvisible](https://dwm.suckless.org/patches/unfloatvisible/)
- resets isfloating on any visible windows that have it set and optionally also applies a layout
- [killunsel](https://dwm.suckless.org/patches/killunsel/)
- kills all visible clients that are not selected (only the selected client will remain)
- [~urgentborder~](https://dwm.suckless.org/patches/urgentborder/)
- ~this patch makes "urgent" windows have different colors~
- [vanitygaps](https://github.com/bakkeby/patches/blob/master/dwm/dwm-vanitygaps-6.2.diff)
- adds configurable gaps between windows differentiating between outer, inner, horizontal and vertical gaps
- [viewontag](https://dwm.suckless.org/patches/viewontag/)
- follow a window to the tag it is being moved to
- [vtcolor](https://dwm.suckless.org/patches/vtcolors/)
- this patch adds the ability for dwm to read colors from the linux virtual console essentially allowing you to use the same color scheme as your regular tty
- [warp](https://dwm.suckless.org/patches/warp/)
- warps the mouse cursor to the center of the currently focused window or screen when the mouse cursor is (a) on a different screen or (b) on top of a different window
- [windowrolerule](https://github.com/bakkeby/patches/wiki/windowrolerule/)
- sometimes a single application opens different windows depending on the task at hand and this is often reflected in the WM_WINDOW_ROLE(STRING) x property
- this patch adds the role field to the rule configuration so that one can differentiate between, say, Firefox "browser" vs "Preferences" vs "Manager" or Google-chrome "browser" vs "pop-up".
- [winview](http://dwm.suckless.org/patches/winview/)
- allows switching the view to that of a given client from the all-window view (Mod-0) using a keyboard shortcut
- [xrdb](http://dwm.suckless.org/patches/xrdb/)
- allows dwm to read colors from xrdb (.Xresources) during runtime
- [zoomfloating](https://www.reddit.com/r/suckless/comments/ie5fe3/zoomfloating_my_own_simple_original_patch/)
- a simple patch that allows floating windows to be zoomed into the master stack position
- [zoomswap](https://dwm.suckless.org/patches/zoomswap/)
- allows a master and a stack window to swap places rather than every window on the screen changing position
### Layouts included:
- [bstack](https://dwm.suckless.org/patches/bottomstack/)
- bottomstack layout
- [bstackhoriz](https://dwm.suckless.org/patches/bottomstack/)
- bottomstack horizontal layout
- [centeredmaster](https://dwm.suckless.org/patches/centeredmaster/)
- centeredmaster layout
- [centeredfloatingmaster](https://dwm.suckless.org/patches/centeredmaster/)
- centeredfloatingmaster layout
- [columns](https://dwm.suckless.org/patches/columns/)
- same as the default tile layout except clients in the master area are arranged in columns (i.e. left to right)
- [deck](https://dwm.suckless.org/patches/deck/)
- deck layout - clients in the stack area are arranged on top of each other (like monocle)
- [fibonacci](https://dwm.suckless.org/patches/fibonacci/)
- fibonacci (dwindle and spiral) layouts
- [flextile-deluxe](https://github.com/bakkeby/patches/wiki/flextile-deluxe/)
- a re-envisioned, flexible and over-the-top version of the original [flextile](https://dwm.suckless.org/patches/flextile/) patch supporting
- multiple split layouts (horizontal, vertical, centered, floating, fixed)
- tile arrangement on a per split basis (stack horizontally, stack vertically, grids, fibonacci)
- pertag, cfacts, rmaster, vanitygaps compatibility
- tile, deck, monocle, centeredmaster, bstack, bstackhoriz, gapplessgrid and more
- this gives you a lot of versatility in terms of layout
- [gapplessgrid](https://dwm.suckless.org/patches/gaplessgrid/)
- gappless grid layout
- [gridmode](https://dwm.suckless.org/patches/gridmode/)
- gridmode (grid) layout
- [horizgrid](https://dwm.suckless.org/patches/horizgrid/)
- horizontal grid layout
- [nrowgrid](https://dwm.suckless.org/patches/nrowgrid/)
- nrowgrid layout, number of rows in grid controlled by nmaster

+ 0
- 35
suckless/dwm/README.org View File

@ -1,35 +0,0 @@
#+TITLE:DWM: Dynamic Window Manager
This is my own build of DWM with some patches and configurations.
*** Patches
**** Feature related
Those patches that add new features to DWM, some of them are simple features that are present in other TWMs.
- [[https://dwm.suckless.org/patches/actualfullscreen/dwm-actualfullscreen-20191112-cb3f58a.diff][actualfullscreen:]] Allows to activate true fullscreen instead of just change to monocle layout and hide the bar.
- [[https://dwm.suckless.org/patches/alwayscenter/][alwayscenter]]: Floating windows are always placed at the center of the screen.
- [[https://dwm.suckless.org/patches/cyclelayouts/dwm-cyclelayouts-20180524-6.2.diff][cyclelayouts:]] Go through the layout list with a button combination.
- [[https://dwm.suckless.org/patches/inplacerotate/][inplacerotate]]: Allows to rotate the windows in the stack without changing master.
- [[https://dwm.suckless.org/patches/movestack/dwm-movestack-6.1.diff][movestack:]] Allows to move the windows in the stack part, when using the default layout.
- [[https://dwm.suckless.org/patches/pertag/dwm-pertag-20170513-ceac8c9.diff][pertag:]] By default, dwm uses the same layout for all tags. With this patch each tag has a different layout (the initial scheme is tile).
- [[https://dwm.suckless.org/patches/switchcol/][switchcol:]] It allows to change the focus between master and stack with a single keybinding. Useful with the /deck/ layout.
- [[https://dwm.suckless.org/patches/winview/][winview]]: If you are seeing several tags at once, pressing a keybinding switches to the tag in the focused window.
**** Layouts
New layout I've added to DWM.
- [[https://dwm.suckless.org/patches/centeredmaster/][centeredmaster:]] The /master/ window is placed in the center while the others appear in a grid around it.
- [[https://dwm.suckless.org/patches/deck/][deck:]] The /stack/ part only shows one window at a time. If used with /inplacerotate/ it is possible to change the window in /stack/ without moving /master/.
- [[https://dwm.suckless.org/patches/fibonacci/dwm-fibonacci-5.8.2.diff][fibonacci:]] Two new layouts: spiral y dwindle (à la bspwm).
- [[https://dwm.suckless.org/patches/gridmode/dwm-gridmode-20170909-ceac8c9.diff][gridmode:]] Grid layout.
- [[https://dwm.suckless.org/patches/rmaster/dwm-rmaster-6.1.diff][rmaster:]] Allows to reverse the order of the tile scheme: master on the left and stack on the right.
**** Aesthetic related
Patches that only serve to improve the aesthetic aspect of the WM and contribute little or nothing to the functional aspect.
- [[https://dwm.suckless.org/patches/alttagsdecoration/][alttagsdecoration]]: Allows you to declare different icons for each tag when they are busy.
- [[https://dwm.suckless.org/patches/barpadding/][barpadding:]] Add vertical andhorizontal padding to the bar from the screen.
- [[https://dwm.suckless.org/patches/colorbar/][colorbar]]: Add new color schemes for each section of the panel.
- [[https://github.com/ashish-yadav11/dwmblocks][dwmblocks]]: Add support for colored text and click on the dwmblocks modules.
- [[https://dwm.suckless.org/patches/alpha/dwm-fixborders-6.2.diff][fixborders]]: Fix the transparent borders when using compton/picom.
- [[https://dwm.suckless.org/patches/uselessgap/dwm-uselessgap-6.2.diff][uselessgap:]] Add useless gaps between windows. Although it is not the only patch, it is the easiest to apply.

+ 33
- 0
suckless/dwm/config.bak View File

@ -0,0 +1,33 @@
/* See LICENSE file for copyright and license details. */
#include <X11/XF86keysym.h>
/* appearance */
static const int rmaster = 0; /* 1 = master at right*/
static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */
static const unsigned int systrayspacing = 2; /* systray spacing */
static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/
static const int showsystray = 1; /* 0 means no systray */
static const int tag_padding = 0;
static const int vertpad = 0; /* vertical padding of bar */
static const int sidepad = 0; /* horizontal padding of bar */
/* tagging */
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"};
//static const char *alttags[] = { "󰄯", "󰄯", "󰄯", "󰄯"};
/* layout(s) */
static const float mfact = 0.5; /* factor of master area size [0.05..0.95] */
static const int nmaster = 1; /* number of clients in master area */
static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */
static const Layout layouts[] = {
/* symbol arrange function */
{ "鉶", tile }, /* first entry is default */
/* { "", dwindle }, */
{ "ﱖ", grid },
{ "", centeredmaster },
{ "", centeredfloatingmaster },
{ "[M]", monocle },
{ "[D]", deck },
{ NULL, NULL },
};

+ 27
- 236
suckless/dwm/config.h View File

@ -2,262 +2,53 @@
#include <X11/XF86keysym.h>
/* appearance */
static const unsigned int borderpx = 3; /* border pixel of windows */
static const unsigned int gappx = 6;
static const unsigned int snap = 32; /* snap pixel */
static const int rmaster = 0; /* 1 = master at right*/
static const int showbar = 1; /* 0 means no bar */
static const int rmaster = 0; /* 1 = master at right*/
static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */
static const unsigned int systrayspacing = 2; /* systray spacing */
static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/
static const int showsystray = 1; /* 0 means no systray */
static const int topbar = 1; /* 0 means bottom bar */
static const int user_bh = 27; /* 0 means that dwm will calculate bar height, >= 1 means dwm will user_bh as bar height */
static const int tag_padding = 0;
static const int vertpad = 0; /* vertical padding of bar */
static const int sidepad = 0; /* horizontal padding of bar */
static const char *fonts[] = {"Hack Nerd Font:Regular:size=10", "Material Design Icons:Regular:pixelsize=16:antialias=true"};
static const char dmenufont[] = "Hack Nerd Font:size=10";
static const char fore[] = "#f8f8f2";
static const char back[] = "#282a36";
static const char border[] = "#f8f8f2";
static const char col0[] = "#000000";
static const char col1[] = "#FF5555";
static const char col2[] = "#50FA7B";
static const char col3[] = "#F1FA8C";
static const char col4[] = "#BD93F9";
static const char col5[] = "#FF79C6";
static const char col6[] = "#8BE9FD";
static const char col7[] = "#BFBFBF";
static const char col8[] = "#4D4D4D";
static const char col9[] = "#FF6E67";
static const char col10[] = "#5AF78E";
static const char col11[] = "#F4F99D";
static const char col12[] = "#CAA9FA";
static const char col13[] = "#FF92D0";
static const char col14[] = "#9AEDFE";
static const char col15[] = "#E6E6E6";
static const char spotify[]= "#1FC167";
static const char *colors[][3] = {
/* fg bg border */
[SchemeNorm] = { fore, back, back }, // \x0b
[SchemeSel] = { fore, back, border }, // \x0c
[SchemeStatus] = { fore, back, border }, // \x0d Statusbar right
[SchemeTagsSel] = { col4, back, border }, // \x0e Tagbar left selected
[SchemeTagsNorm] = { fore, back, border }, // \x0f Tagbar left unselected
[SchemeInfoSel] = { fore, back, border }, // \x10 infobar middle selected
[SchemeInfoNorm] = { fore, back, border }, // \x11 infobar middle unselected
[SchemeCol1] = { col1, back, col0 }, // \x12
[SchemeCol2] = { col2, back, col0 }, // \x13
[SchemeCol3] = { col3, back, col0 }, // \x14
[SchemeCol4] = { col4, back, col0 }, // \x15
[SchemeCol5] = { col5, back, col0 }, // \x16
[SchemeCol6] = { col6, back, col0 }, // \x17
[SchemeCol7] = { col7, back, col0 }, // \x18
[SchemeCol8] = { col8, back, col0 }, // \x19
[SchemeCol9] = { col9, back, col0 }, // \x1a
[SchemeCol10] = { col10, back, col0 }, // \x1b
[SchemeCol11] = { col11, back, col0 }, // \x1c
[SchemeCol12] = { spotify, back, col0 }, // \x1d Spotify
};
static int showsystray = 1; /* 0 means no systray */
static const int tag_padding = 0;
static const char *layoutmenu_cmd = "layoutmenu.sh";
/* systray */
static int tagindicatortype = INDICATOR_TOP_LEFT_SQUARE;
static int tiledindicatortype = INDICATOR_NONE;
static int floatindicatortype = INDICATOR_TOP_LEFT_SQUARE;
/* vanity gaps */
static const unsigned int gappih = 20; /* horiz inner gap between windows */
static const unsigned int gappiv = 10; /* vert inner gap between windows */
static const unsigned int gappoh = 10; /* horiz outer gap between windows and screen edge */
static const unsigned int gappov = 30; /* vert outer gap between windows and screen edge */
static const int smartgaps = 0; /* 1 means no outer gap when there is only one window */
/* tagging */
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"};
//static const char *alttags[] = { "󰄯", "󰄯", "󰄯", "󰄯"};
static const Rule rules[] = {
/* xprop(1):
* WM_CLASS(STRING) = instance, class
* WM_NAME(STRING) = title
*/
/* class instance title tags mask isfloating monitor */
{ "discord", NULL, NULL, 1 << 8, 0, -1 },
{ "Mailspring", NULL, NULL, 1 << 7, 0, -1 },
{ "Thunderbird", NULL, NULL, 1 << 7, 0, -1 },
{ "Termite", NULL, NULL, 1 << 0, 0, -1 },
{ "firefoxdeveloperedition", NULL, NULL, 1 << 1, 0, -1 },
{ "Tor Browser", NULL, NULL, 1 << 1, 0, -1 },
{ "Chromium", NULL, NULL, 1 << 1, 0, -1 },
// { "zoom", NULL, NULL, 1 << 4, 0, -1 },
{ "TelegramDesktop", NULL, NULL, 1 << 8, 0, -1 },
{ "whatsapp-nativefier-d52542", NULL, NULL, 1 << 8, 0, -1 },
{ "neomutt", NULL, NULL, 1 << 7, 0, -1 },
{ "Sublime_Text", NULL, NULL, 1 << 2, 0, -1 },
{ "code-oss", NULL, NULL, 1 << 2, 0, -1 },
{ "jetbrains-idea", NULL, NULL, 1 << 2, 0, -1 },
{ "Nemo", NULL, NULL, 1 << 3, 0, -1 },
{ "Spotify", NULL, NULL, 1 << 9, 0, -1 },
static char *tagicons[][NUMTAGS] = {
[DEFAULT_TAGS] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" },
[ALTERNATIVE_TAGS] = { "A", "B", "C", "D", "E", "F", "G", "H", "I" },
};
/* layout(s) */
static const float mfact = 0.5; /* factor of master area size [0.05..0.95] */
static const int nmaster = 1; /* number of clients in master area */
static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */
#include "fibonacci.c"
#include "layouts.c"
static const Layout layouts[] = {
/* symbol arrange function */
{ "", tile }, /* first entry is default */
{ "", dwindle },
{ "", dwindle },
{ "", grid },
{ "", centeredmaster },
{ "", centeredfloatingmaster },
{ "[M]", monocle },
{ "[D]", deck },
{ NULL, NULL },
};
/* key definitions */
#define MODKEY Mod4Mask
#define TAGKEYS(KEY,TAG) \
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
{ MODKEY|Mod1Mask, KEY, toggleview, {.ui = 1 << TAG} }, \
{ MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
{ MODKEY|ControlMask, KEY, toggletag, {.ui = 1 << TAG} },
/* COSAS QUE TENGO QUE AVERIGUAR COMO QUITAR */
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
static const char *dmenucmd[] = { "/usr/bin/rofi","-show","drun", NULL };
static const char *termcmd[] = { "/usr/bin/termite", "--title", "Terminal", NULL };
static const char *upvol[] = { "/usr/bin/pactl", "set-sink-volume", "0", "+5%", NULL };
static const char *downvol[] = { "/usr/bin/pactl", "set-sink-volume", "0", "-5%", NULL };
static const char *mutevol[] = { "/usr/bin/pactl", "set-sink-mute", "0", "toggle", NULL };
static const char *upbright[] = {"/usr/bin/xbacklight","-inc","10",NULL};
static const char *downbright[] = {"/usr/bin/xbacklight","-dec","10",NULL};
static const char *lock[] = {"/usr/bin/betterlockscreen","-l","-t","Stay the fuck out!",NULL};
static const char *clipmenu[] = {"/usr/bin/clipmenu","-i",NULL};
static const char *play[] = {"/usr/bin/playerctl","play-pause",NULL};
static const char *prev[] = {"/usr/bin/playerctl","previous",NULL};
static const char *next[] = {"/usr/bin/playerctl","next",NULL};
static const char *outmenu[] = {"/home/yigit/.scripts/dmenu-logout"};
static const char *notification_off[] = {"/home/yigit/.scripts/dunst_toggle.sh","-s",NULL};
static const char *notification_on[] = {"/home/yigit/.scripts/dunst_toggle.sh", "-e",NULL};
static const char *bwmenu[] = {"/usr/bin/bwmenu", "--auto-lock", "-1", NULL};
static const char *trackpad[] = {"/home/yigit/.scripts/toggle_touchpad.sh"};
static const char *kdeconnect[] = {"/home/yigit/.local/bin/dmenu_kdeconnect.sh", NULL};
static const char *bluetooth[] = {"/usr/bin/rofi-bluetooth", NULL};
static const char *screenshot[] = { "scrot","-d","3", "%Y-%m-%d-%s_$wx$h.jpg", "-e","xclip -selection clipboard -t image/jpg < $f; mv $f ~/Pictures/Screenshots/;dunstify --icon='/home/yigit/.icons/Numix-Circle/48/apps/camera.svg' -a 'SNAP' 'Screenshot taken'", NULL };
static const char *windowshot[] = { "scrot", "-u", "-d","3", "%Y-%m-%d-%s_$wx$h.jpg", "-e","xclip -selection clipboard -t image/jpg < $f; mv $f ~/Pictures/Screenshots/;dunstify --icon='/home/yigit/.icons/Numix-Circle/48/apps/camera.svg' -a 'SNAP' 'Screenshot taken'", NULL };
/* commands */
#include "movestack.c"
#include "shiftview.c"
static Key keys[] = {
/* modifier key function argument */
{ MODKEY, XK_d, spawn, {.v = dmenucmd } },
{ MODKEY, XK_p, spawn, {.v = bwmenu } },
{ MODKEY, XK_Return, spawn, {.v = termcmd } },
{ MODKEY, XK_b, togglebar, {0} },
{ MODKEY, XK_j, focusstack, {.i = +1 } },
{ MODKEY, XK_n, spawn, {.v = notification_off} },
{ MODKEY|ShiftMask, XK_n, spawn, {.v = notification_on } },
{ MODKEY, XK_k, focusstack, {.i = -1 } },
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
{ MODKEY, XK_s, incnmaster, {.i = -1 } },
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
{ MODKEY|ShiftMask, XK_Return, zoom, {0} },
{ MODKEY, XK_Tab, view, {0} },
{ MODKEY, XK_q, killclient, {0} },
{ MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } }, /*Mover ventana hacia abajo*/
{ MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } }, /*Mover ventana hacia arriba*/
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, /*tiled*/
{ MODKEY|Mod1Mask, XK_f, setlayout, {.v = &layouts[1]} }, /*Spiral*/
{ MODKEY|Mod1Mask, XK_g, setlayout, {.v = &layouts[2]} }, /*Grid*/
{ MODKEY|Mod1Mask, XK_c, setlayout, {.v = &layouts[3]} }, /*center*/
{ MODKEY, XK_m, setlayout, {.v = &layouts[5]} }, /*monocle*/
{ MODKEY|ShiftMask, XK_m, setlayout, {.v = &layouts[6]} }, /*Deck*/
{ MODKEY, XK_s, togglefloating, {0} }, /*float*/
{ MODKEY, XK_f, togglefullscr, {0} }, /*Fullscreen*/
{ MODKEY|Mod1Mask, XK_comma, cyclelayout, {.i = -1 } }, /*Ciclar layouts*/
{ MODKEY|Mod1Mask, XK_period, cyclelayout, {.i = +1 } }, /*Ciclar layouts*/
{ MODKEY, XK_a, view, {.ui = ~0 } },
{ MODKEY|ShiftMask, XK_a, tag, {.ui = ~0 } },
{ MODKEY, XK_comma, focusmon, {.i = -1 } },
{ MODKEY, XK_period, focusmon, {.i = +1 } },
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
/*Monitores*/
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, /*Mandar ventana a monitor anterior*/
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, /*Mandar ventana a monitor siguiente*/
TAGKEYS( XK_1, 0)
TAGKEYS( XK_2, 1)
TAGKEYS( XK_3, 2)
TAGKEYS( XK_4, 3)
TAGKEYS( XK_5, 4)
TAGKEYS( XK_6, 5)
TAGKEYS( XK_7, 6)
TAGKEYS( XK_8, 7)
TAGKEYS( XK_9, 8)
TAGKEYS( XK_0, 9)
{ MODKEY|ShiftMask, XK_q, spawn, {.v = outmenu} },
{ MODKEY|ShiftMask, XK_t, spawn, {.v = trackpad} },
{ MODKEY, XK_x, spawn, {.v = lock } },
{ MODKEY, XK_c, spawn, {.v = clipmenu } },
{ MODKEY|ShiftMask, XK_p, spawn, {.v = kdeconnect } },
{ MODKEY|ShiftMask, XK_b, spawn, {.v = bluetooth } },
{ 0, XF86XK_AudioLowerVolume, spawn, {.v = downvol } },
{ 0, XF86XK_MonBrightnessUp, spawn, {.v = upbright } },
{ 0, XF86XK_MonBrightnessDown, spawn, {.v = downbright } },
{ 0, XF86XK_AudioMute, spawn, {.v = mutevol } },
{ 0, XF86XK_AudioRaiseVolume, spawn, {.v = upvol } },
{ 0, XF86XK_AudioPrev, spawn, {.v = prev } },
{ 0, XF86XK_AudioPlay, spawn, {.v = play } },
{ 0, XF86XK_AudioNext, spawn, {.v = next } },
{ 0, XK_Print, spawn, {.v = screenshot } },
{ MODKEY, XK_Print, spawn, {.v = windowshot } },
};
/* button definitions */
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
static Button buttons[] = {
/* click event mask button function argument */
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
{ ClkWinTitle, 0, Button2, zoom, {0} },
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
{ ClkTagBar, 0, Button1, view, {0} },
{ ClkTagBar, 0, Button3, toggleview, {0} },
{ ClkTagBar, MODKEY, Button1, tag, {0} },
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
};
/*
static Button buttons[] = {
// click event mask button function argument
{ ClkLtSymbol, 0, Button1, cyclelayout, {.i = +1 } },
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[5]} },
{ ClkWinTitle, 0, Button2, zoom, {0} },
{ ClkStatusText, 0, Button1, sigdwmblocks, {.i = 1} },
{ ClkStatusText, 0, Button2, sigdwmblocks, {.i = 2} },
{ ClkStatusText, 0, Button3, sigdwmblocks, {.i = 3} },
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
{ ClkTagBar, 0, Button1, view, {0} },
{ ClkTagBar, 0, Button3, toggleview, {0} },
{ ClkTagBar, MODKEY, Button1, tag, {0} },
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
{ ClkClientWin, 0, Button1, winview, {0} },
static const BarRule barrules[] = {
/* monitor bar alignment widthfunc drawfunc clickfunc name */
{ -1, 0, BAR_ALIGN_LEFT, width_tags, draw_tags, click_tags, "tags" },
//{ 0, 0, BAR_ALIGN_RIGHT, width_systray, draw_systray, click_systray, "systray" },
{ -1, 0, BAR_ALIGN_LEFT, width_ltsymbol, draw_ltsymbol, click_ltsymbol, "layout" },
{ 'A', 0, BAR_ALIGN_RIGHT, width_status2d, draw_status2d, click_statuscmd, "status2d" },
};
*/

+ 24
- 2
suckless/dwm/config.mk View File

@ -19,10 +19,32 @@ FREETYPELIBS = -lfontconfig -lXft
FREETYPEINC = /usr/include/freetype2
# OpenBSD (uncomment)
#FREETYPEINC = ${X11INC}/freetype2
# OpenBSD - Uncomment this for the swallow patch / SWALLOW_PATCH
#KVMLIB = -lkvm
# Uncomment this for the alpha patch / BAR_ALPHA_PATCH
XRENDER = -lXrender
# Uncomment this for the mdpcontrol patch / MDPCONTROL_PATCH
#MPDCLIENT = -lmpdclient
# Uncomment for the pango patch / BAR_PANGO_PATCH
#PANGOINC = `pkg-config --cflags xft pango pangoxft`
#PANGOLIB = `pkg-config --libs xft pango pangoxft`
# Uncomment for the ipc patch / IPC_PATCH
YAJLLIBS = -lyajl
YAJLINC = -I/usr/include/yajl
# Uncomment this for the rounded corners patch / ROUNDED_CORNERS_PATCH
#XEXTLIB = -lXext
# Uncomment this for the swallow patch / SWALLOW_PATCH
XCBLIBS = -lX11-xcb -lxcb -lxcb-res
# includes and libs
INCS = -I${X11INC} -I${FREETYPEINC}
LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
INCS = -I${X11INC} -I${FREETYPEINC} ${YAJLINC} ${PANGOINC}
LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XRENDER} ${MPDCLIENT} ${XEXTLIB} ${XCBLIBS} ${KVMLIB} ${PANGOLIB} ${YAJLLIBS}
# flags
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}


+ 259
- 8
suckless/dwm/drw.c View File

@ -5,9 +5,11 @@
#include <X11/Xlib.h>
#include <X11/Xft/Xft.h>
#include "patches.h"
#include "drw.h"
#include "util.h"
#if !BAR_PANGO_PATCH
#define UTF_INVALID 0xFFFD
#define UTF_SIZ 4
@ -15,7 +17,13 @@ static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}
static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000};
static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
#endif // BAR_PANGO_PATCH
#if BAR_POWERLINE_TAGS_PATCH || BAR_POWERLINE_STATUS_PATCH
Clr transcheme[3];
#endif // BAR_POWERLINE_TAGS_PATCH | BAR_POWERLINE_STATUS_PATCH
#if !BAR_PANGO_PATCH
static long
utf8decodebyte(const char c, size_t *i)
{
@ -59,9 +67,14 @@ utf8decode(const char *c, long *u, size_t clen)
return len;
}
#endif // BAR_PANGO_PATCH
Drw *
#if BAR_ALPHA_PATCH
drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h, Visual *visual, unsigned int depth, Colormap cmap)
#else
drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h)
#endif // BAR_ALPHA_PATCH
{
Drw *drw = ecalloc(1, sizeof(Drw));
@ -70,8 +83,17 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h
drw->root = root;
drw->w = w;
drw->h = h;
#if BAR_ALPHA_PATCH
drw->visual = visual;
drw->depth = depth;
drw->cmap = cmap;
drw->drawable = XCreatePixmap(dpy, root, w, h, depth);
drw->gc = XCreateGC(dpy, drw->drawable, 0, NULL);
#else
drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen));
drw->gc = XCreateGC(dpy, root, 0, NULL);
#endif // BAR_ALPHA_PATCH
XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
return drw;
@ -87,7 +109,11 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h)
drw->h = h;
if (drw->drawable)
XFreePixmap(drw->dpy, drw->drawable);
#if BAR_ALPHA_PATCH
drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, drw->depth);
#else
drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen));
#endif // BAR_ALPHA_PATCH
}
void
@ -99,6 +125,41 @@ drw_free(Drw *drw)
free(drw);
}
#if BAR_PANGO_PATCH
/* This function is an implementation detail. Library users should use
* drw_font_create instead.
*/
static Fnt *
xfont_create(Drw *drw, const char *fontname)
{
Fnt *font;
PangoFontMap *fontmap;
PangoContext *context;
PangoFontDescription *desc;
PangoFontMetrics *metrics;
if (!fontname) {
die("no font specified.");
}
font = ecalloc(1, sizeof(Fnt));
font->dpy = drw->dpy;
fontmap = pango_xft_get_font_map(drw->dpy, drw->screen);
context = pango_font_map_create_context(fontmap);
desc = pango_font_description_from_string(fontname);
font->layout = pango_layout_new(context);
pango_layout_set_font_description(font->layout, desc);
metrics = pango_context_get_metrics(context, desc, pango_language_from_string ("en-us"));
font->h = pango_font_metrics_get_height(metrics) / PANGO_SCALE;
pango_font_metrics_unref(metrics);
g_object_unref(context);
return font;
}
#else
/* This function is an implementation detail. Library users should use
* drw_fontset_create instead.
*/
@ -133,6 +194,7 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
die("no font specified.");
}
#if !BAR_COLOR_EMOJI_PATCH
/* Do not allow using color fonts. This is a workaround for a BadLength
* error from Xft with color glyphs. Modelled on the Xterm workaround. See
* https://bugzilla.redhat.com/show_bug.cgi?id=1498269
@ -141,10 +203,11 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
* and lots more all over the internet.
*/
FcBool iscol;
if(FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) {
if (FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) {
XftFontClose(drw->dpy, xfont);
return NULL;
}
#endif // BAR_COLOR_EMOJI_PATCH
font = ecalloc(1, sizeof(Fnt));
font->xfont = xfont;
@ -154,18 +217,38 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
return font;
}
#endif // BAR_PANGO_PATCH
static void
xfont_free(Fnt *font)
{
if (!font)
return;
#if BAR_PANGO_PATCH
if (font->layout)
g_object_unref(font->layout);
#else
if (font->pattern)
FcPatternDestroy(font->pattern);
XftFontClose(font->dpy, font->xfont);
#endif // BAR_PANGO_PATCH
free(font);
}
#if BAR_PANGO_PATCH
Fnt*
drw_font_create(Drw* drw, const char font[])
{
Fnt *fnt = NULL;
if (!drw || !font)
return NULL;
fnt = xfont_create(drw, font);
return (drw->fonts = fnt);
}
#else
Fnt*
drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount)
{
@ -183,35 +266,60 @@ drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount)
}
return (drw->fonts = ret);
}
#endif // BAR_PANGO_PATCH
void
drw_fontset_free(Fnt *font)
{
if (font) {
#if !BAR_PANGO_PATCH
drw_fontset_free(font->next);
#endif // BAR_PANGO_PATCH
xfont_free(font);
}
}
void
drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
{
drw_clr_create(
Drw *drw,
Clr *dest,
const char *clrname
#if BAR_ALPHA_PATCH
, unsigned int alpha
#endif // BAR_ALPHA_PATCH
) {
if (!drw || !dest || !clrname)
return;
#if BAR_ALPHA_PATCH
if (!XftColorAllocName(drw->dpy, drw->visual, drw->cmap,
clrname, dest))
die("error, cannot allocate color '%s'", clrname);
dest->pixel = (dest->pixel & 0x00ffffffU) | (alpha << 24);
#else
if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen),
DefaultColormap(drw->dpy, drw->screen),
clrname, dest))
die("error, cannot allocate color '%s'", clrname);
#if NO_TRANSPARENT_BORDERS_PATCH
dest->pixel |= 0xff << 24;
#endif // NO_TRANSPARENT_BORDERS_PATCH
#endif // BAR_ALPHA_PATCH
}
/* Wrapper to create color schemes. The caller has to call free(3) on the
* returned color scheme when done using it. */
Clr *
drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
{
drw_scm_create(
Drw *drw,
char *clrnames[],
#if BAR_ALPHA_PATCH
const unsigned int alphas[],
#endif // BAR_ALPHA_PATCH
size_t clrcount
) {
size_t i;
Clr *ret;
@ -220,16 +328,22 @@ drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
return NULL;
for (i = 0; i < clrcount; i++)
#if BAR_ALPHA_PATCH
drw_clr_create(drw, &ret[i], clrnames[i], alphas[i]);
#else
drw_clr_create(drw, &ret[i], clrnames[i]);
#endif // BAR_ALPHA_PATCH
return ret;
}
#if !BAR_PANGO_PATCH
void
drw_setfontset(Drw *drw, Fnt *set)
{
if (drw)
drw->fonts = set;
}
#endif // BAR_PANGO_PATCH
void
drw_setscheme(Drw *drw, Clr *scm)
@ -238,6 +352,17 @@ drw_setscheme(Drw *drw, Clr *scm)
drw->scheme = scm;
}
#if BAR_POWERLINE_TAGS_PATCH || BAR_POWERLINE_STATUS_PATCH
void
drw_settrans(Drw *drw, Clr *psc, Clr *nsc)
{
if (drw) {
transcheme[0] = psc[ColBg]; transcheme[1] = nsc[ColBg]; transcheme[2] = psc[ColBorder];
drw->scheme = transcheme;
}
}
#endif // BAR_POWERLINE_TAGS_PATCH | BAR_POWERLINE_STATUS_PATCH
void
drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert)
{
@ -250,8 +375,74 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int
XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1);
}
#if BAR_PANGO_PATCH
int
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, Bool markup)
{
char buf[1024];
int ty;
unsigned int ew;
XftDraw *d = NULL;
size_t i, len;
int render = x || y || w || h;
if (!drw || (render && !drw->scheme) || !text || !drw->fonts)
return 0;
if (!render) {
w = ~w;
} else {
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
#if BAR_ALPHA_PATCH
d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap);
#else
d = XftDrawCreate(drw->dpy, drw->drawable,
DefaultVisual(drw->dpy, drw->screen),
DefaultColormap(drw->dpy, drw->screen));
#endif // BAR_ALPHA_PATCH
x += lpad;
w -= lpad;
}
len = strlen(text);
if (len) {
drw_font_getexts(drw->fonts, text, len, &ew, NULL, markup);
/* shorten text if necessary */
for (len = MIN(len, sizeof(buf) - 1); len && ew > w; len--)
drw_font_getexts(drw->fonts, text, len, &ew, NULL, markup);
if (len) {
memcpy(buf, text, len);
buf[len] = '\0';
if (len < strlen(text))
for (i = len; i && i > len - 3; buf[--i] = '.')
; /* NOP */
if (render) {
ty = y + (h - drw->fonts->h) / 2;
if (markup)
pango_layout_set_markup(drw->fonts->layout, buf, len);
else
pango_layout_set_text(drw->fonts->layout, buf, len);
pango_xft_render_layout(d, &drw->scheme[invert ? ColBg : ColFg],
drw->fonts->layout, x * PANGO_SCALE, ty * PANGO_SCALE);
if (markup) /* clear markup attributes */
pango_layout_set_attributes(drw->fonts->layout, NULL);
}
x += ew;
w -= ew;
}
}
if (d)
XftDrawDestroy(d);
return x + (render ? w : 0);
}
#else
int
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert)
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, Bool ignored)
{
char buf[1024];
int ty;
@ -276,9 +467,13 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
} else {
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
#if BAR_ALPHA_PATCH
d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap);
#else
d = XftDrawCreate(drw->dpy, drw->drawable,
DefaultVisual(drw->dpy, drw->screen),
DefaultColormap(drw->dpy, drw->screen));
#endif // BAR_ALPHA_PATCH
x += lpad;
w -= lpad;
}
@ -380,6 +575,40 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
return x + (render ? w : 0);
}
#endif // BAR_PANGO_PATCH
#if BAR_POWERLINE_TAGS_PATCH || BAR_POWERLINE_STATUS_PATCH
void
drw_arrow(Drw *drw, int x, int y, unsigned int w, unsigned int h, int direction, int slash)
{
if (!drw || !drw->scheme)
return;
/* direction=1 draws right arrow */
x = direction ? x : x + w;
w = direction ? w : -w;
/* slash=1 draws slash instead of arrow */
unsigned int hh = slash ? (direction ? 0 : h) : h/2;
XPoint points[] = {
{x , y },
{x + w, y + hh },
{x , y + h },
};
XPoint bg[] = {
{x , y },
{x + w, y },
{x + w, y + h},
{x , y + h},
};
XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel);
XFillPolygon(drw->dpy, drw->drawable, drw->gc, bg, 4, Convex, CoordModeOrigin);
XSetForeground(drw->dpy, drw->gc, drw->scheme[ColFg].pixel);
XFillPolygon(drw->dpy, drw->drawable, drw->gc, points, 3, Nonconvex, CoordModeOrigin);
}
#endif // BAR_POWERLINE_TAGS_PATCH | BAR_POWERLINE_STATUS_PATCH
void
drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
@ -392,13 +621,34 @@ drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
}
unsigned int
drw_fontset_getwidth(Drw *drw, const char *text)
drw_fontset_getwidth(Drw *drw, const char *text, Bool markup)
{
if (!drw || !drw->fonts || !text)
return 0;
return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
return drw_text(drw, 0, 0, 0, 0, 0, text, 0, markup);
}
#if BAR_PANGO_PATCH
void
drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h, Bool markup)
{
if (!font || !text)
return;
PangoRectangle r;
if (markup)
pango_layout_set_markup(font->layout, text, len);
else
pango_layout_set_text(font->layout, text, len);
pango_layout_get_extents(font->layout, 0, &r);
if (markup) /* clear markup attributes */
pango_layout_set_attributes(font->layout, NULL);
if (w)
*w = r.width / PANGO_SCALE;
if (h)
*h = font->h;
}
#else
void
drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
{
@ -413,6 +663,7 @@ drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w,
if (h)
*h = font->h;
}
#endif // BAR_PANGO_PATCH
Cur *
drw_cur_create(Drw *drw, int shape)


+ 51
- 6
suckless/dwm/drw.h View File

@ -1,5 +1,10 @@
/* See LICENSE file for copyright and license details. */
#if BAR_PANGO_PATCH
#include <pango/pango.h>
#include <pango/pangoxft.h>
#endif // BAR_PANGO_PATCH
typedef struct {
Cursor cursor;
} Cur;
@ -7,12 +12,16 @@ typedef struct {
typedef struct Fnt {
Display *dpy;
unsigned int h;
#if BAR_PANGO_PATCH
PangoLayout *layout;
#else
XftFont *xfont;
FcPattern *pattern;
struct Fnt *next;
#endif // BAR_PANGO_PATCH
} Fnt;
enum { ColFg, ColBg, ColBorder }; /* Clr scheme index */
enum { ColFg, ColBg, ColBorder, ColFloat, ColCount }; /* Clr scheme index */
typedef XftColor Clr;
typedef struct {
@ -20,6 +29,11 @@ typedef struct {
Display *dpy;
int screen;
Window root;
#if BAR_ALPHA_PATCH
Visual *visual;
unsigned int depth;
Colormap cmap;
#endif // BAR_ALPHA_PATCH
Drawable drawable;
GC gc;
Clr *scheme;
@ -27,31 +41,62 @@ typedef struct {
} Drw;
/* Drawable abstraction */
#if BAR_ALPHA_PATCH
Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h, Visual *visual, unsigned int depth, Colormap cmap);
#else
Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h);
#endif // BAR_ALPHA_PATCH
void drw_resize(Drw *drw, unsigned int w, unsigned int h);
void drw_free(Drw *drw);
/* Fnt abstraction */
#if BAR_PANGO_PATCH
Fnt *drw_font_create(Drw* drw, const char font[]);
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h, Bool markup);
#else
Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);
void drw_fontset_free(Fnt* set);
unsigned int drw_fontset_getwidth(Drw *drw, const char *text);
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
#endif // BAR_PANGO_PATCH
void drw_fontset_free(Fnt* set);
unsigned int drw_fontset_getwidth(Drw *drw, const char *text, Bool markup);
/* Colorscheme abstraction */
void drw_clr_create(Drw *drw, Clr *dest, const char *clrname);
Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount);
void drw_clr_create(
Drw *drw,
Clr *dest,
const char *clrname
#if BAR_ALPHA_PATCH
, unsigned int alpha
#endif // BAR_ALPHA_PATCH
);
Clr *drw_scm_create(
Drw *drw,
char *clrnames[],
#if BAR_ALPHA_PATCH
const unsigned int alphas[],
#endif // BAR_ALPHA_PATCH
size_t clrcount
);
/* Cursor abstraction */
Cur *drw_cur_create(Drw *drw, int shape);
void drw_cur_free(Drw *drw, Cur *cursor);
/* Drawing context manipulation */
#if !BAR_PANGO_PATCH
void drw_setfontset(Drw *drw, Fnt *set);
#endif // BAR_PANGO_PATCH
void drw_setscheme(Drw *drw, Clr *scm);
#if BAR_POWERLINE_TAGS_PATCH || BAR_POWERLINE_STATUS_PATCH
void drw_settrans(Drw *drw, Clr *psc, Clr *nsc);
#endif // BAR_POWERLINE_TAGS_PATCH | BAR_POWERLINE_STATUS_PATCH
/* Drawing functions */
void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert);
int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert);
int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, Bool markup);
#if BAR_POWERLINE_TAGS_PATCH || BAR_POWERLINE_STATUS_PATCH
void drw_arrow(Drw *drw, int x, int y, unsigned int w, unsigned int h, int direction, int slash);
#endif // BAR_POWERLINE_TAGS_PATCH | BAR_POWERLINE_STATUS_PATCH
/* Map functions */
void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);

+ 0
- 727
suckless/dwm/dwm-systray-20200914-61bb8b2.diff View File

@ -1,727 +0,0 @@
diff --git a/config.def.h b/config.def.h
index 1c0b587..2d824d1 100644
--- a/config.def.h
+++ b/config.def.h
@@ -3,6 +3,10 @@
/* appearance */
static const unsigned int borderpx = 1; /* border pixel of windows */
static const unsigned int snap = 32; /* snap pixel */
+static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */
+static const unsigned int systrayspacing = 2; /* systray spacing */
+static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/
+static const int showsystray = 1; /* 0 means no systray */
static const int showbar = 1; /* 0 means no bar */
static const int topbar = 1; /* 0 means bottom bar */
static const char *fonts[] = { "monospace:size=10" };
diff --git a/dwm.c b/dwm.c
index 664c527..abce13d 100644
--- a/dwm.c
+++ b/dwm.c
@@ -57,12 +57,30 @@
#define TAGMASK ((1 << LENGTH(tags)) - 1)
#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
+#define SYSTEM_TRAY_REQUEST_DOCK 0
+
+/* XEMBED messages */
+#define XEMBED_EMBEDDED_NOTIFY 0
+#define XEMBED_WINDOW_ACTIVATE 1
+#define XEMBED_FOCUS_IN 4
+#define XEMBED_MODALITY_ON 10
+
+#define XEMBED_MAPPED (1 << 0)
+#define XEMBED_WINDOW_ACTIVATE 1
+#define XEMBED_WINDOW_DEACTIVATE 2
+
+#define VERSION_MAJOR 0
+#define VERSION_MINOR 0
+#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR
+
/* enums */
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
enum { SchemeNorm, SchemeSel }; /* color schemes */
enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
+ NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, NetSystemTrayOrientationHorz,
NetWMFullscreen, NetActiveWindow, NetWMWindowType,
NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
+enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */
enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
@@ -141,6 +159,12 @@ typedef struct {
int monitor;
} Rule;
+typedef struct Systray Systray;
+struct Systray {
+ Window win;
+ Client *icons;
+};
+
/* function declarations */
static void applyrules(Client *c);
static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
@@ -172,6 +196,7 @@ static void focusstack(const Arg *arg);
static Atom getatomprop(Client *c, Atom prop);
static int getrootptr(int *x, int *y);
static long getstate(Window w);
+static unsigned int getsystraywidth();
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
static void grabbuttons(Client *c, int focused);
static void grabkeys(void);
@@ -189,13 +214,16 @@ static void pop(Client *);
static void propertynotify(XEvent *e);
static void quit(const Arg *arg);
static Monitor *recttomon(int x, int y, int w, int h);
+static void removesystrayicon(Client *i);
static void resize(Client *c, int x, int y, int w, int h, int interact);
+static void resizebarwin(Monitor *m);
static void resizeclient(Client *c, int x, int y, int w, int h);
static void resizemouse(const Arg *arg);
+static void resizerequest(XEvent *e);
static void restack(Monitor *m);
static void run(void);
static void scan(void);
-static int sendevent(Client *c, Atom proto);
+static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4);
static void sendmon(Client *c, Monitor *m);
static void setclientstate(Client *c, long state);
static void setfocus(Client *c);
@@ -207,6 +235,7 @@ static void seturgent(Client *c, int urg);
static void showhide(Client *c);
static void sigchld(int unused);
static void spawn(const Arg *arg);
+static Monitor *systraytomon(Monitor *m);
static void tag(const Arg *arg);
static void tagmon(const Arg *arg);
static void tile(Monitor *);
@@ -224,18 +253,23 @@ static int updategeom(void);
static void updatenumlockmask(void);
static void updatesizehints(Client *c);
static void updatestatus(void);
+static void updatesystray(void);
+static void updatesystrayicongeom(Client *i, int w, int h);
+static void updatesystrayiconstate(Client *i, XPropertyEvent *ev);
static void updatetitle(Client *c);
static void updatewindowtype(Client *c);
static void updatewmhints(Client *c);
static void view(const Arg *arg);
static Client *wintoclient(Window w);
static Monitor *wintomon(Window w);
+static Client *wintosystrayicon(Window w);
static int xerror(Display *dpy, XErrorEvent *ee);
static int xerrordummy(Display *dpy, XErrorEvent *ee);
static int xerrorstart(Display *dpy, XErrorEvent *ee);
static void zoom(const Arg *arg);
/* variables */
+static Systray *systray = NULL;
static const char broken[] = "broken";
static char stext[256];
static int screen;
@@ -258,9 +292,10 @@ static void (*handler[LASTEvent]) (XEvent *) = {
[MapRequest] = maprequest,
[MotionNotify] = motionnotify,
[PropertyNotify] = propertynotify,
+ [ResizeRequest] = resizerequest,
[UnmapNotify] = unmapnotify
};
-static Atom wmatom[WMLast], netatom[NetLast];
+static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast];
static int running = 1;
static Cur *cursor[CurLast];
static Clr **scheme;
@@ -440,7 +475,7 @@ buttonpress(XEvent *e)
arg.ui = 1 << i;
} else if (ev->x < x + blw)
click = ClkLtSymbol;
- else if (ev->x > selmon->ww - (int)TEXTW(stext))
+ else if (ev->x > selmon->ww - (int)TEXTW(stext) - getsystraywidth())
click = ClkStatusText;
else
click = ClkWinTitle;
@@ -483,6 +518,11 @@ cleanup(void)
XUngrabKey(dpy, AnyKey, AnyModifier, root);
while (mons)
cleanupmon(mons);
+ if (showsystray) {
+ XUnmapWindow(dpy, systray->win);
+ XDestroyWindow(dpy, systray->win);
+ free(systray);
+ }
for (i = 0; i < CurLast; i++)
drw_cur_free(drw, cursor[i]);
for (i = 0; i < LENGTH(colors); i++)
@@ -513,9 +553,57 @@ cleanupmon(Monitor *mon)
void
clientmessage(XEvent *e)
{
+ XWindowAttributes wa;
+ XSetWindowAttributes swa;
XClientMessageEvent *cme = &e->xclient;
Client *c = wintoclient(cme->window);
+ if (showsystray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) {
+ /* add systray icons */
+ if (cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) {
+ if (!(c = (Client *)calloc(1, sizeof(Client))))
+ die("fatal: could not malloc() %u bytes\n", sizeof(Client));
+ if (!(c->win = cme->data.l[2])) {
+ free(c);
+ return;
+ }
+ c->mon = selmon;
+ c->next = systray->icons;
+ systray->icons = c;
+ if (!XGetWindowAttributes(dpy, c->win, &wa)) {
+ /* use sane defaults */
+ wa.width = bh;
+ wa.height = bh;
+ wa.border_width = 0;
+ }
+ c->x = c->oldx = c->y = c->oldy = 0;
+ c->w = c->oldw = wa.width;
+ c->h = c->oldh = wa.height;
+ c->oldbw = wa.border_width;
+ c->bw = 0;
+ c->isfloating = True;
+ /* reuse tags field as mapped status */
+ c->tags = 1;
+ updatesizehints(c);
+ updatesystrayicongeom(c, wa.width, wa.height);
+ XAddToSaveSet(dpy, c->win);
+ XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask);
+ XReparentWindow(dpy, c->win, systray->win, 0, 0);
+ /* use parents background color */
+ swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
+ XChangeWindowAttributes(dpy, c->win, CWBackPixel, &swa);
+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
+ /* FIXME not sure if I have to send these events, too */
+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_FOCUS_IN, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_MODALITY_ON, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
+ XSync(dpy, False);
+ resizebarwin(selmon);
+ updatesystray();
+ setclientstate(c, NormalState);
+ }
+ return;
+ }
if (!c)
return;
if (cme->message_type == netatom[NetWMState]) {
@@ -568,7 +656,7 @@ configurenotify(XEvent *e)
for (c = m->clients; c; c = c->next)
if (c->isfullscreen)
resizeclient(c, m->mx, m->my, m->mw, m->mh);
- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
+ resizebarwin(m);
}
focus(NULL);
arrange(NULL);
@@ -653,6 +741,11 @@ destroynotify(XEvent *e)
if ((c = wintoclient(ev->window)))
unmanage(c, 1);
+ else if ((c = wintosystrayicon(ev->window))) {
+ removesystrayicon(c);
+ resizebarwin(selmon);
+ updatesystray();
+ }
}
void
@@ -696,19 +789,23 @@ dirtomon(int dir)
void
drawbar(Monitor *m)
{
- int x, w, tw = 0;
+ int x, w, tw = 0, stw = 0;
int boxs = drw->fonts->h / 9;
int boxw = drw->fonts->h / 6 + 2;
unsigned int i, occ = 0, urg = 0;
Client *c;
+ if(showsystray && m == systraytomon(m))
+ stw = getsystraywidth();
+
/* draw status first so it can be overdrawn by tags later */
if (m == selmon) { /* status is only drawn on selected monitor */
drw_setscheme(drw, scheme[SchemeNorm]);
- tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
- drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0);
+ tw = TEXTW(stext) - lrpad / 2 + 2; /* 2px right padding */
+ drw_text(drw, m->ww - tw - stw, 0, tw, bh, lrpad / 2 - 2, stext, 0);
}
+ resizebarwin(m);
for (c = m->clients; c; c = c->next) {
occ |= c->tags;
if (c->isurgent)
@@ -729,7 +826,7 @@ drawbar(Monitor *m)
drw_setscheme(drw, scheme[SchemeNorm]);
x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
- if ((w = m->ww - tw - x) > bh) {
+ if ((w = m->ww - tw - stw - x) > bh) {
if (m->sel) {
drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0);
@@ -740,7 +837,7 @@ drawbar(Monitor *m)
drw_rect(drw, x, 0, w, bh, 1, 1);
}
}
- drw_map(drw, m->barwin, 0, 0, m->ww, bh);
+ drw_map(drw, m->barwin, 0, 0, m->ww - stw, bh);
}
void
@@ -777,8 +874,11 @@ 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);
+ if (m == selmon)
+ updatesystray();
+ }
}
void
@@ -863,10 +963,17 @@ getatomprop(Client *c, Atom prop)
unsigned long dl;
unsigned char *p = NULL;
Atom da, atom = None;
+ /* FIXME getatomprop should return the number of items and a pointer to
+ * the stored data instead of this workaround */
+ Atom req = XA_ATOM;
+ if (prop == xatom[XembedInfo])
+ req = xatom[XembedInfo];
- if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM,
+ if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req,
&da, &di, &dl, &dl, &p) == Success && p) {
atom = *(Atom *)p;
+ if (da == xatom[XembedInfo] && dl == 2)
+ atom = ((Atom *)p)[1];
XFree(p);
}
return atom;
@@ -900,6 +1007,16 @@ getstate(Window w)
return result;
}
+unsigned int
+getsystraywidth()
+{
+ unsigned int w = 0;
+ Client *i;
+ if(showsystray)
+ for(i = systray->icons; i; w += i->w + systrayspacing, i = i->next) ;
+ return w ? w + systrayspacing : 1;
+}
+
int
gettextprop(Window w, Atom atom, char *text, unsigned int size)
{
@@ -1004,7 +1121,7 @@ killclient(const Arg *arg)
{
if (!selmon->sel)
return;
- if (!sendevent(selmon->sel, wmatom[WMDelete])) {
+ if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0 , 0, 0)) {
XGrabServer(dpy);
XSetErrorHandler(xerrordummy);
XSetCloseDownMode(dpy, DestroyAll);
@@ -1092,6 +1209,12 @@ maprequest(XEvent *e)
{
static XWindowAttributes wa;
XMapRequestEvent *ev = &e->xmaprequest;
+ Client *i;
+ if ((i = wintosystrayicon(ev->window))) {
+ sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION);
+ resizebarwin(selmon);
+ updatesystray();
+ }
if (!XGetWindowAttributes(dpy, ev->window, &wa))
return;
@@ -1216,6 +1339,16 @@ propertynotify(XEvent *e)
Window trans;
XPropertyEvent *ev = &e->xproperty;
+ if ((c = wintosystrayicon(ev->window))) {
+ if (ev->atom == XA_WM_NORMAL_HINTS) {
+ updatesizehints(c);
+ updatesystrayicongeom(c, c->w, c->h);
+ }
+ else
+ updatesystrayiconstate(c, ev);
+ resizebarwin(selmon);
+ updatesystray();
+ }
if ((ev->window == root) && (ev->atom == XA_WM_NAME))
updatestatus();
else if (ev->state == PropertyDelete)
@@ -1266,6 +1399,20 @@ recttomon(int x, int y, int w, int h)
return r;
}
+void
+removesystrayicon(Client *i)
+{
+ Client **ii;
+
+ if (!showsystray || !i)
+ return;
+ for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next);
+ if (ii)
+ *ii = i->next;
+ free(i);
+}
+
+
void
resize(Client *c, int x, int y, int w, int h, int interact)
{
@@ -1273,6 +1420,14 @@ resize(Client *c, int x, int y, int w, int h, int interact)
resizeclient(c, x, y, w, h);
}
+void
+resizebarwin(Monitor *m) {
+ unsigned int w = m->ww;
+ if (showsystray && m == systraytomon(m))
+ w -= getsystraywidth();
+ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh);
+}
+
void
resizeclient(Client *c, int x, int y, int w, int h)
{
@@ -1345,6 +1500,19 @@ resizemouse(const Arg *arg)
}
}
+void
+resizerequest(XEvent *e)
+{
+ XResizeRequestEvent *ev = &e->xresizerequest;
+ Client *i;
+
+ if ((i = wintosystrayicon(ev->window))) {
+ updatesystrayicongeom(i, ev->width, ev->height);
+ resizebarwin(selmon);
+ updatesystray();
+ }
+}
+
void
restack(Monitor *m)
{
@@ -1434,26 +1602,36 @@ setclientstate(Client *c, long state)
}
int
-sendevent(Client *c, Atom proto)
+sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4)
{
int n;
- Atom *protocols;
+ Atom *protocols, mt;
int exists = 0;
XEvent ev;
- if (XGetWMProtocols(dpy, c->win, &protocols, &n)) {
- while (!exists && n--)
- exists = protocols[n] == proto;
- XFree(protocols);
+ if (proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) {
+ mt = wmatom[WMProtocols];
+ if (XGetWMProtocols(dpy, w, &protocols, &n)) {
+ while (!exists && n--)
+ exists = protocols[n] == proto;
+ XFree(protocols);
+ }
+ }
+ else {
+ exists = True;
+ mt = proto;
}
if (exists) {
ev.type = ClientMessage;
- ev.xclient.window = c->win;
- ev.xclient.message_type = wmatom[WMProtocols];
+ ev.xclient.window = w;
+ ev.xclient.message_type = mt;
ev.xclient.format = 32;
- ev.xclient.data.l[0] = proto;
- ev.xclient.data.l[1] = CurrentTime;
- XSendEvent(dpy, c->win, False, NoEventMask, &ev);
+ ev.xclient.data.l[0] = d0;
+ ev.xclient.data.l[1] = d1;
+ ev.xclient.data.l[2] = d2;
+ ev.xclient.data.l[3] = d3;
+ ev.xclient.data.l[4] = d4;
+ XSendEvent(dpy, w, False, mask, &ev);
}
return exists;
}
@@ -1467,7 +1645,7 @@ setfocus(Client *c)
XA_WINDOW, 32, PropModeReplace,
(unsigned char *) &(c->win), 1);
}
- sendevent(c, wmatom[WMTakeFocus]);
+ sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0);
}
void
@@ -1556,6 +1734,10 @@ setup(void)
wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
+ netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False);
+ netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False);
+ netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False);
+ netatom[NetSystemTrayOrientationHorz] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION_HORZ", False);
netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False);
@@ -1563,6 +1745,9 @@ setup(void)
netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False);
+ xatom[Manager] = XInternAtom(dpy, "MANAGER", False);
+ xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False);
+ xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False);
/* init cursors */
cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr);
cursor[CurResize] = drw_cur_create(drw, XC_sizing);
@@ -1571,6 +1756,8 @@ setup(void)
scheme = ecalloc(LENGTH(colors), sizeof(Clr *));
for (i = 0; i < LENGTH(colors); i++)
scheme[i] = drw_scm_create(drw, colors[i], 3);
+ /* init system tray */
+ updatesystray();
/* init bars */
updatebars();
updatestatus();
@@ -1704,7 +1891,18 @@ togglebar(const Arg *arg)
{
selmon->showbar = !selmon->showbar;
updatebarpos(selmon);
- XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
+ resizebarwin(selmon);
+ if (showsystray) {
+ XWindowChanges wc;
+ if (!selmon->showbar)
+ wc.y = -bh;
+ else if (selmon->showbar) {
+ wc.y = 0;
+ if (!selmon->topbar)
+ wc.y = selmon->mh - bh;
+ }
+ XConfigureWindow(dpy, systray->win, CWY, &wc);
+ }
arrange(selmon);
}
@@ -1799,11 +1997,18 @@ unmapnotify(XEvent *e)
else
unmanage(c, 0);
}
+ else if ((c = wintosystrayicon(ev->window))) {
+ /* KLUDGE! sometimes icons occasionally unmap their windows, but do
+ * _not_ destroy them. We map those windows back */
+ XMapRaised(dpy, c->win);
+ updatesystray();
+ }
}
void
updatebars(void)
{
+ unsigned int w;
Monitor *m;
XSetWindowAttributes wa = {
.override_redirect = True,
@@ -1814,10 +2019,15 @@ updatebars(void)
for (m = mons; m; m = m->next) {
if (m->barwin)
continue;
- m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
+ w = m->ww;
+ if (showsystray && m == systraytomon(m))
+ w -= getsystraywidth();
+ m->barwin = XCreateWindow(dpy, root, m->wx, m->by, w, bh, 0, DefaultDepth(dpy, screen),
CopyFromParent, DefaultVisual(dpy, screen),
CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor);
+ if (showsystray && m == systraytomon(m))
+ XMapRaised(dpy, systray->win);
XMapRaised(dpy, m->barwin);
XSetClassHint(dpy, m->barwin, &ch);
}
@@ -1993,6 +2203,121 @@ updatestatus(void)
if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
strcpy(stext, "dwm-"VERSION);
drawbar(selmon);
+ updatesystray();
+}
+
+void
+updatesystrayicongeom(Client *i, int w, int h)
+{
+ if (i) {
+ i->h = bh;
+ if (w == h)
+ i->w = bh;
+ else if (h == bh)
+ i->w = w;
+ else
+ i->w = (int) ((float)bh * ((float)w / (float)h));
+ applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False);
+ /* force icons into the systray dimensions if they don't want to */
+ if (i->h > bh) {
+ if (i->w == i->h)
+ i->w = bh;
+ else
+ i->w = (int) ((float)bh * ((float)i->w / (float)i->h));
+ i->h = bh;
+ }
+ }
+}
+
+void
+updatesystrayiconstate(Client *i, XPropertyEvent *ev)
+{
+ long flags;
+ int code = 0;
+
+ if (!showsystray || !i || ev->atom != xatom[XembedInfo] ||
+ !(flags = getatomprop(i, xatom[XembedInfo])))
+ return;
+
+ if (flags & XEMBED_MAPPED && !i->tags) {
+ i->tags = 1;
+ code = XEMBED_WINDOW_ACTIVATE;
+ XMapRaised(dpy, i->win);
+ setclientstate(i, NormalState);
+ }
+ else if (!(flags & XEMBED_MAPPED) && i->tags) {
+ i->tags = 0;
+ code = XEMBED_WINDOW_DEACTIVATE;
+ XUnmapWindow(dpy, i->win);
+ setclientstate(i, WithdrawnState);
+ }
+ else
+ return;
+ sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0,
+ systray->win, XEMBED_EMBEDDED_VERSION);
+}
+
+void
+updatesystray(void)
+{
+ XSetWindowAttributes wa;
+ XWindowChanges wc;
+ Client *i;
+ Monitor *m = systraytomon(NULL);
+ unsigned int x = m->mx + m->mw;
+ unsigned int w = 1;
+
+ if (!showsystray)
+ return;
+ if (!systray) {
+ /* init systray */
+ if (!(systray = (Systray *)calloc(1, sizeof(Systray))))
+ die("fatal: could not malloc() %u bytes\n", sizeof(Systray));
+ systray->win = XCreateSimpleWindow(dpy, root, x, m->by, w, bh, 0, 0, scheme[SchemeSel][ColBg].pixel);
+ wa.event_mask = ButtonPressMask | ExposureMask;
+ wa.override_redirect = True;
+ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
+ XSelectInput(dpy, systray->win, SubstructureNotifyMask);
+ XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char *)&netatom[NetSystemTrayOrientationHorz], 1);
+ XChangeWindowAttributes(dpy, systray->win, CWEventMask|CWOverrideRedirect|CWBackPixel, &wa);
+ XMapRaised(dpy, systray->win);
+ XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime);
+ if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) {
+ sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0);
+ XSync(dpy, False);
+ }
+ else {
+ fprintf(stderr, "dwm: unable to obtain system tray.\n");
+ free(systray);
+ systray = NULL;
+ return;
+ }
+ }
+ for (w = 0, i = systray->icons; i; i = i->next) {
+ /* make sure the background color stays the same */
+ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
+ XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa);
+ XMapRaised(dpy, i->win);
+ w += systrayspacing;
+ i->x = w;
+ XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h);
+ w += i->w;
+ if (i->mon != m)
+ i->mon = m;
+ }
+ w = w ? w + systrayspacing : 1;
+ x -= w;
+ XMoveResizeWindow(dpy, systray->win, x, m->by, w, bh);
+ wc.x = x; wc.y = m->by; wc.width = w; wc.height = bh;
+ wc.stack_mode = Above; wc.sibling = m->barwin;
+ XConfigureWindow(dpy, systray->win, CWX|CWY|CWWidth|CWHeight|CWSibling|CWStackMode, &wc);
+ XMapWindow(dpy, systray->win);
+ XMapSubwindows(dpy, systray->win);
+ /* redraw background */
+ XSetForeground(dpy, drw->gc, scheme[SchemeNorm][ColBg].pixel);
+ XFillRectangle(dpy, systray->win, drw->gc, 0, 0, w, bh);
+ XSync(dpy, False);
}
void
@@ -2060,6 +2385,16 @@ wintoclient(Window w)
return NULL;
}
+Client *
+wintosystrayicon(Window w) {
+ Client *i = NULL;
+
+ if (!showsystray || !w)
+ return i;
+ for (i = systray->icons; i && i->win != w; i = i->next) ;
+ return i;
+}
+
Monitor *
wintomon(Window w)
{
@@ -2113,6 +2448,22 @@ xerrorstart(Display *dpy, XErrorEvent *ee)
return -1;
}
+Monitor *
+systraytomon(Monitor *m) {
+ Monitor *t;
+ int i, n;
+ if(!systraypinning) {
+ if(!m)
+ return selmon;
+ return m == selmon ? m : NULL;
+ }
+ for(n = 1, t = mons; t && t->next; n++, t = t->next) ;
+ for(i = 1, t = mons; t && t->next && i < systraypinning; i++, t = t->next) ;
+ if(systraypinningfailfirst && n < systraypinning)
+ return mons;
+ return t;
+}
+
void
zoom(const Arg *arg)
{

+ 0
- 9
suckless/dwm/dwm.1 View File

@ -92,12 +92,6 @@ Sets monocle layout.
.B Mod1\-space
Toggles between current and previous layout.
.TP
.B Mod1\-Control\-,
Cycles backwards in layout list.
.TP
.B Mod1\-Control\-.
Cycles forwards in layout list.
.TP
.B Mod1\-j
Focus next window.
.TP
@ -116,9 +110,6 @@ 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


+ 2712
- 803
suckless/dwm/dwm.c
File diff suppressed because it is too large
View File


+ 0
- 28
suckless/dwm/dwm_config_pulseaudio.h View File

@ -1,28 +0,0 @@
/**
* dwmconfig.h
* Hardware multimedia keys
*/
/* Somewhere at the beginning of config.h include:
#include <X11/XF86keysym.h>
/* Add somewhere in your constants definition section */
static const char *upvol[] = { "/usr/bin/pactl", "set-sink-volume", "0", "+5%", NULL };
static const char *downvol[] = { "/usr/bin/pactl", "set-sink-volume", "0", "-5%", NULL };
static const char *mutevol[] = { "/usr/bin/pactl", "set-sink-mute", "0", "toggle", NULL };
/* Add to keys[] array. With 0 as modifier, you are able to use the keys directly. */
static Key keys[] = {
{ 0, XF86XK_AudioLowerVolume, spawn, {.v = downvol } },
{ 0, XF86XK_AudioMute, spawn, {.v = mutevol } },
{ 0, XF86XK_AudioRaiseVolume, spawn, {.v = upvol } },
};
/* If you have a small laptop keyboard or don't want to spring your fingers too far away. */
static Key keys[] = {
{ MODKEY, XK_F11, spawn, {.v = downvol } },
{ MODKEY, XK_F9, spawn, {.v = mutevol } },
{ MODKEY, XK_F12, spawn, {.v = upvol } },
};

+ 0
- 66
suckless/dwm/fibonacci.c View File

@ -1,66 +0,0 @@
void
fibonacci(Monitor *mon, int s) {
unsigned int i, n, nx, ny, nw, nh;
Client *c;
for(n = 0, c = nexttiled(mon->clients); c; c = nexttiled(c->next), n++);
if(n == 0)
return;
nx = mon->wx;
ny = 0;
nw = mon->ww;
nh = mon->wh;
for(i = 0, c = nexttiled(mon->clients); c; c = nexttiled(c->next)) {
if((i % 2 && nh / 2 > 2 * c->bw)
|| (!(i % 2) && nw / 2 > 2 * c->bw)) {
if(i < n - 1) {
if(i % 2)
nh /= 2;
else
nw /= 2;
if((i % 4) == 2 && !s)
nx += nw;
else if((i % 4) == 3 && !s)
ny += nh;
}
if((i % 4) == 0) {
if(s)
ny += nh;
else
ny -= nh;
}
else if((i % 4) == 1)
nx += nw;
else if((i % 4) == 2)
ny += nh;
else if((i % 4) == 3) {
if(s)
nx += nw;
else
nx -= nw;
}
if(i == 0)
{
if(n != 1)
nw = mon->ww * mon->mfact;
ny = mon->wy;
}
else if(i == 1)
nw = mon->ww - nw;
i++;
}
resize(c, nx, ny, nw - 2 * c->bw, nh - 2 * c->bw, False);
}
}
void
dwindle(Monitor *mon) {
fibonacci(mon, 1);
}
void
spiral(Monitor *mon) {
fibonacci(mon, 0);
}

+ 345
- 0
suckless/dwm/flexipatch-finalizer.sh View File

@ -0,0 +1,345 @@
#!/bin/bash
KEEP_FILES=0
ECHO_COMMANDS=0
RUN_SCRIPT=0
DIRECTORY=.
OUTPUT_DIRECTORY=
KEEP_GITFILES=0
DEBUG=0
if [[ $# = 0 ]]; then
set -- '-h'
fi
while (( $# )); do
case "$1" in
-d|--directory)
shift
DIRECTORY=$1 # source directory
shift
;;
-o|--output)
shift
OUTPUT_DIRECTORY=$1
shift
;;
--debug)
shift
DEBUG=1
;;
-r|--run)
shift
RUN_SCRIPT=1
;;
-e|--echo)
shift
ECHO_COMMANDS=1
;;
-k|--keep)
shift
KEEP_FILES=1
;;
-g|--git)
shift
KEEP_GITFILES=1
;;
-h|--help)
shift
fmt=" %-31s%s\n"
printf "%s" "Usage: $(basename ${BASH_SOURCE[0]}) [OPTION?]"
printf "\n"
printf "\nThis is a custom pre-processor designed to remove unused flexipatch patches and create a final build."
printf "\n\n"
printf "$fmt" "-r, --run" "include this flag to confirm that you really do want to run this script"
printf "\n"
printf "$fmt" "-d, --directory <dir>" "the flexipatch source directory to process (defaults to current directory)"
printf "$fmt" "-o, --output <dir>" "the output directory to store the processed files"
printf "$fmt" "-h, --help" "display this help section"
printf "$fmt" "-k, --keep" "keep temporary files and do not replace the original ones"
printf "$fmt" "-g, --git" "keep .git files"
printf "$fmt" "-e, --echo" "echo commands that will be run rather than running them"
printf "$fmt" " --debug" "prints additional debug information to stderr"
printf "\nWarning! This script alters and removes files within the source directory."
printf "\nWarning! This process is irreversible! Use with care. Do make a backup before running this."
printf "\n\n"
exit
;;
*)
echo "Ignoring unknown argument ($1)"
shift
;;
esac
done
if [[ $RUN_SCRIPT = 0 ]]; then
echo "Re-run this command with the --run option to confirm that you really want to run this script."
echo "The changes this script makes are irreversible."
exit 1
fi
if [[ -z ${OUTPUT_DIRECTORY} ]]; then
echo "Output directory not specified, see -o"
exit 1
fi
DIRECTORY=$(readlink -f "${DIRECTORY}")
OUTPUT_DIRECTORY=$(readlink -f "${OUTPUT_DIRECTORY}")
if [[ $DIRECTORY != $OUTPUT_DIRECTORY ]]; then
mkdir -p "${OUTPUT_DIRECTORY}"
cp -r -f "${DIRECTORY}/." -t "${OUTPUT_DIRECTORY}"
DIRECTORY=${OUTPUT_DIRECTORY}
fi
if [[ ! -e ${DIRECTORY}/patches.h ]]; then
printf "No patches.h file found. Make sure you run this script within a flexipatch source directory."
exit 1
fi
FILES_TO_DELETE=$(find $DIRECTORY -name "*.c" -o -name "*.h" | awk -v DEBUG="$DEBUG" -v DIRECTORY="$DIRECTORY" '
function istrue(f) {
ret = 0
for ( i = 2; i in f; i++ ) {
if ( f[i] == "||" ) {
if ( ret == -1 ) {
ret = 0
} else if ( ret == 1 ) {
break
}
continue
} else if ( f[i] == "&&" ) {
if ( ret == 0 ) {
ret = -1
}
continue
} else if ( ret == -1 ) {
continue
} else if ( f[i] !~ /_(PATCH|LAYOUT)$/ ) {
ret = 1
} else if ( f[i] ~ /^!/ ) {
ret = !patches[substr(f[i],2)]
} else {
ret = patches[f[i]]
}
}
if ( ret == -1 ) {
ret = 0
}
return ret
}
function schedule_delete(file) {
# Skip duplicates
for ( i = 1; i in files_to_delete; i++ ) {
if ( files_to_delete[i] == file) {
return
}
}
if (DEBUG) {
print "Scheduling file " file " for deletion." > "/dev/stderr"
}
files_to_delete[i] = file
}
function is_flexipatch(patch) {
return patch ~ /_(PATCH|LAYOUT)$/
}
BEGIN {
# Read patches.h and store patch settings in the patches associative array
if (DEBUG) {
print "Reading file " DIRECTORY "/patches.h" > "/dev/stderr"
}
while (( getline line < (DIRECTORY"/patches.h") ) > 0 ) {
split(line,f)
if ( f[1] ~ /^#define$/ ) {
if ( f[3] == 0 || f[3] == 1 ) {
patches[f[2]] = f[3]
} else {
patches[f[2]] = istrue(f)
}
if (DEBUG) {
print "Found " f[2] " = " patches[f[2]] > "/dev/stderr"
}
}
}
files_to_delete[0] = ""
}
{
level = 0
do_print[level] = 1
has_printed[level] = 0
condition[level] = ""
while (( getline line < $0) > 0 ) {
split(line,f)
if ( f[1] ~ /^#if$/ ) {
level++;
do_print[level] = do_print[level-1]
has_printed[level] = 0
condition[level] = f[2]
if ( do_print[level] ) {
if ( istrue(f) ) {
has_printed[level] = 1
do_print[level] = 1
} else {
do_print[level] = 0
}
}
if ( is_flexipatch(condition[level]) ) {
continue
}
} else if ( f[1] ~ /^#ifdef$/ || f[1] ~ /^#ifndef$/ ) {
level++;
do_print[level] = do_print[level-1]
has_printed[level] = 0
condition[level] = f[2]
if ( do_print[level] ) {
has_printed[level] = 1
do_print[level] = 1
}
if ( is_flexipatch(condition[level]) ) {
continue
}
} else if ( f[1] ~ /^#elif$/ ) {
if ( (!is_flexipatch(condition[level]) || has_printed[level] == 0) && do_print[level-1] == 1 ) {
if ( istrue(f) ) {
has_printed[level] = 1
do_print[level] = 1
} else {
do_print[level] = 0
}
} else {
do_print[level] = 0
}
if ( is_flexipatch(f[2]) ) {
continue
}
} else if ( f[1] ~ /^#else$/ ) {
if ( (!is_flexipatch(condition[level]) || has_printed[level] == 0) && do_print[level-1] == 1 ) {
has_printed[level] = 1
do_print[level] = 1
} else {
do_print[level] = 0
}
if ( is_flexipatch(condition[level]) ) {
continue
}
} else if ( f[1] ~ /^#include$/ && f[2] ~ /^"/ && (do_print[level] == 0 || f[2] == "\"patches.h\"") ) {
dir = ""
if ( $0 ~ /\// ) {
dir = $0
sub("/[^/]+$", "/", dir)
}
schedule_delete(dir substr(f[2], 2, length(f[2]) - 2))
continue
} else if ( f[1] ~ /^#endif$/ ) {
if ( is_flexipatch(condition[level]) ) {
level--
continue
}
level--
}
if ( do_print[level] ) {
print line > $0 ".~"
}
}
}
END {
for ( i = 1; i in files_to_delete; i++ ) {
print files_to_delete[i]
}
}
')
# Chmod and replace files
for FILE in $(find $DIRECTORY -name "*.~"); do
chmod --reference=${FILE%%.~} ${FILE}
if [[ $KEEP_FILES = 0 ]] || [[ $ECHO_COMMANDS = 1 ]]; then
if [[ $ECHO_COMMANDS = 1 ]]; then
echo "mv ${FILE} ${FILE%%.~}"
else
mv ${FILE} ${FILE%%.~}
fi
fi
done
# Delete unnecessary files
if [[ $KEEP_FILES = 0 ]] || [[ $ECHO_COMMANDS = 1 ]]; then
# Remove dwmc shell script if patch not enabled
if [[ -f ${DIRECTORY}/patch/dwmc ]] && [[ $(grep -cE '^#define DWMC_PATCH +0 *$' ${DIRECTORY}/patches.h) > 0 ]]; then
if [[ $ECHO_COMMANDS = 1 ]]; then
echo "rm ${DIRECTORY}/patch/dwmc"
echo "sed -r -i -e '/cp -f patch\/dwmc/d' \"${DIRECTORY}/Makefile\""
else
rm "${DIRECTORY}/patch/dwmc"
sed -r -i -e '/cp -f patch\/dwmc/d' "${DIRECTORY}/Makefile"
fi
fi
# Remove layoutmenu.sh shell script if patch not enabled
if [[ -f ${DIRECTORY}/patch/layoutmenu.sh ]] && [[ $(grep -cE '^#define BAR_LAYOUTMENU_PATCH +0 *$' ${DIRECTORY}/patches.h) > 0 ]]; then
if [[ $ECHO_COMMANDS = 1 ]]; then
echo "rm ${DIRECTORY}/patch/layoutmenu.sh"
else
rm "${DIRECTORY}/patch/layoutmenu.sh"
fi
fi
for FILE in $FILES_TO_DELETE ${DIRECTORY}/patches.def.h; do
if [[ $ECHO_COMMANDS = 1 ]]; then
echo "rm $FILE"
else
rm "$FILE"
fi
done
if [[ -f $DIRECTORY/README.md ]]; then
if [[ $ECHO_COMMANDS = 1 ]]; then
echo "rm $DIRECTORY/README.md"
else
rm $DIRECTORY/README.md
fi
fi
if [[ $KEEP_GITFILES = 0 ]]; then
rm -rf $DIRECTORY/.git*
fi
# Remove empty include files
INCLUDE_RE='*patch/*include.[hc]'
if [[ $ECHO_COMMANDS = 1 ]]; then
INCLUDE_RE='*patch/*include.[hc][.]~'
fi
for FILE in $(find $DIRECTORY -path "$INCLUDE_RE"); do
if [[ $(grep -c "#include " $FILE) = 0 ]]; then
if [[ $ECHO_COMMANDS = 1 ]]; then
echo "rm ${FILE%%.~}"
else
rm "$FILE"
fi
for LINE in $(grep -Ern "#include \"patch/$(basename ${FILE%%.~})\"" $DIRECTORY | grep -v '.~:' | awk -F":" '{print $1 ":" $2 }'); do
INCFILE=$(echo $LINE | cut -d":" -f1)
LINE_NO=$(echo $LINE | cut -d":" -f2)
if [[ $ECHO_COMMANDS = 1 ]]; then
echo "sed -i \"${LINE_NO}d\" ${INCFILE}"
else
sed -i "${LINE_NO}d" ${INCFILE}
fi
done
fi
done
fi
# Clean up the Makefile
sed -r -i -e 's/ patches.h$//' -e '/^patches.h:$/{N;N;d;}' "${DIRECTORY}/Makefile"

+ 132
- 0
suckless/dwm/keybind.h View File

@ -0,0 +1,132 @@
#include <X11/XF86keysym.h>
/* key definitions */
#define MODKEY Mod4Mask
#define TAGKEYS(KEY,TAG) \
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
{ MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
{ MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
{ MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
static char dmenumon[2] = "0";
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-z", "1900", "-x", "10", "-y", "10"};
static const char *termcmd[] = { "/usr/local/bin/st", NULL };
static const char *upvol[] = { "/home/yigit/.scripts/pacontrol.sh", "up", NULL };
static const char *downvol[] = { "/home/yigit/.scripts/pacontrol.sh", "down", NULL };
static const char *mutevol[] = { "/home/yigit/.scripts/pacontrol.sh", "togglemute", NULL };
static const char *upbright[] = {"/usr/bin/xbacklight","-inc","10",NULL};
static const char *downbright[] = {"/usr/bin/xbacklight","-dec","10",NULL};
static const char *lock[] = {"/usr/bin/betterlockscreen","-l","-t","Stay the fuck out!",NULL};
static const char *clipmenu[] = {"/usr/bin/clipmenu","-i",NULL};
static const char *play[] = {"/usr/bin/playerctl","play-pause",NULL};
static const char *prev[] = {"/usr/bin/playerctl","previous",NULL};
static const char *next[] = {"/usr/bin/playerctl","next",NULL};
static const char *outmenu[] = {"/home/yigit/.scripts/dmenu-logout"};
static const char *notification_off[] = {"/home/yigit/.scripts/dunst_toggle.sh","-s",NULL};
static const char *notification_on[] = {"/home/yigit/.scripts/dunst_toggle.sh", "-e",NULL};
static const char *bwmenu[] = {"/usr/bin/bwmenu", "--auto-lock", "-1", NULL};
static const char *network_manager[] = {"/home/yigit/.scripts/networkmanager_dmenu"};
static const char *trackpad[] = {"/home/yigit/.scripts/toggle_touchpad.sh"};
static const char *kdeconnect[] = {"/home/yigit/.local/bin/dmenu_kdeconnect.sh", NULL};
static const char *bluetooth[] = {"/home/yigit/.scripts/dmenu-bluetooth", NULL};
static const char *screenshot[] = { "scrot","-d","3", "%Y-%m-%d-%s_$wx$h.jpg", "-e","xclip -selection clipboard -t image/jpg < $f; mv $f ~/Pictures/Screenshots/;dunstify --icon='/home/yigit/.icons/Numix-Circle/48/apps/camera.svg' -a 'SNAP' 'Screenshot taken'", NULL };
static const char *windowshot[] = { "scrot", "-u", "-d","3", "%Y-%m-%d-%s_$wx$h.jpg", "-e","xclip -selection clipboard -t image/jpg < $f; mv $f ~/Pictures/Screenshots/;dunstify --icon='/home/yigit/.icons/Numix-Circle/48/apps/camera.svg' -a 'SNAP' 'Screenshot taken'", NULL };
/* commands */
static Key keys[] = {
/* modifier key function argument */
{ MODKEY, XK_d, spawn, {.v = dmenucmd } },
{ MODKEY, XK_p, spawn, {.v = bwmenu } },
{ MODKEY, XK_Return, spawn, {.v = termcmd } },
{ MODKEY, XK_b, togglebar, {0} },
{ MODKEY, XK_j, focusstack, {.i = +1 } },
{ MODKEY, XK_n, spawn, {.v = notification_off} },
{ MODKEY|ShiftMask, XK_n, spawn, {.v = notification_on } },
{ MODKEY, XK_k, focusstack, {.i = -1 } },
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
{ MODKEY, XK_s, incnmaster, {.i = -1 } },
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
{ MODKEY|ShiftMask, XK_Return, zoom, {0} },
{ MODKEY, XK_Tab, view, {0} },
{ MODKEY, XK_q, killclient, {0} },
{ MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } },
{ MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } },
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, /*tiled*/
{ MODKEY|Mod1Mask, XK_f, setlayout, {.v = &layouts[1]} }, /*Spiral*/
{ MODKEY|Mod1Mask, XK_g, setlayout, {.v = &layouts[2]} }, /*Grid*/
{ MODKEY|Mod1Mask, XK_c, setlayout, {.v = &layouts[3]} }, /*center*/
{ MODKEY, XK_m, setlayout, {.v = &layouts[5]} }, /*monocle*/
{ MODKEY|ShiftMask, XK_m, setlayout, {.v = &layouts[6]} }, /*Deck*/
// { MODKEY, XK_s, togglefloating, {0} }, [>float<]
// { MODKEY, XK_f, togglefullscr, {0} }, [>Fullscreen<]
{ MODKEY|Mod1Mask, XK_comma, cyclelayout, {.i = -1 } }, /*Ciclar layouts*/
{ MODKEY|Mod1Mask, XK_period, cyclelayout, {.i = +1 } }, /*Ciclar layouts*/
{ MODKEY, XK_a, view, {.ui = ~0 } },
{ MODKEY|ShiftMask, XK_a, tag, {.ui = ~0 } },
{ MODKEY, XK_comma, focusmon, {.i = -1 } },
{ MODKEY, XK_period, focusmon, {.i = +1 } },
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
TAGKEYS( XK_1, 0)
TAGKEYS( XK_2, 1)
TAGKEYS( XK_3, 2)
TAGKEYS( XK_4, 3)
TAGKEYS( XK_5, 4)
TAGKEYS( XK_6, 5)
TAGKEYS( XK_7, 6)
TAGKEYS( XK_8, 7)
TAGKEYS( XK_9, 8)
TAGKEYS( XK_0, 9)
{ MODKEY|ShiftMask, XK_q, spawn, {.v = outmenu} },
{ MODKEY|ShiftMask, XK_t, spawn, {.v = trackpad} },
{ MODKEY, XK_x, spawn, {.v = lock } },
{ MODKEY, XK_c, spawn, {.v = clipmenu } },
{ MODKEY|ShiftMask, XK_p, spawn, {.v = kdeconnect } },
{ MODKEY|ShiftMask, XK_b, spawn, {.v = bluetooth } },
{ MODKEY|Mod1Mask, XK_n, spawn, {.v = network_manager} }, /*Spiral*/
{ 0, XF86XK_AudioLowerVolume, spawn, {.v = downvol } },
{ 0, XF86XK_MonBrightnessUp, spawn, {.v = upbright } },
{ 0, XF86XK_MonBrightnessDown, spawn, {.v = downbright } },
{ 0, XF86XK_AudioMute, spawn, {.v = mutevol } },
{ 0, XF86XK_AudioRaiseVolume, spawn, {.v = upvol } },
{ 0, XF86XK_AudioPrev, spawn, {.v = prev } },
{ 0, XF86XK_AudioPlay, spawn, {.v = play } },
{ 0, XF86XK_AudioNext, spawn, {.v = next } },
{ 0, XK_Print, spawn, {.v = screenshot } },
{ MODKEY, XK_Print, spawn, {.v = windowshot } },
};
/* button definitions */
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
static Button buttons[] = {
/* click event mask button function argument */
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
{ ClkTagBar, 0, Button1, view, {0} },
{ ClkTagBar, 0, Button3, toggleview, {0} },
{ ClkTagBar, MODKEY, Button1, tag, {0} },
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
{ ClkStatusText, 0, Button1, sigdwmblocks, {.i = 1 } },
{ ClkStatusText, 0, Button2, sigdwmblocks, {.i = 2 } },
{ ClkStatusText, 0, Button3, sigdwmblocks, {.i = 3 } },
{ ClkLtSymbol, 0, Button3, layoutmenu, {0} },
};

+ 0
- 27
suckless/dwm/layouts.c View File

@ -1,27 +0,0 @@
void
grid(Monitor *m) {
unsigned int i, n, cx, cy, cw, ch, aw, ah, cols, rows;
Client *c;
for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next))
n++;
/* grid dimensions */
for(rows = 0; rows <= n/2; rows++)
if(rows*rows >= n)
break;
cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows;
/* window geoms (cell height/width) */
ch = m->wh / (rows ? rows : 1);
cw = m->ww / (cols ? cols : 1);
for(i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) {
cx = m->wx + (i / rows) * cw;
cy = m->wy + (i % rows) * ch;
/* adjust height/width of last row/column's windows */
ah = ((i + 1) % rows == 0) ? m->wh - ch * rows : 0;
aw = (i >= rows * (cols - 1)) ? m->ww - cw * cols : 0;
resize(c, cx, cy, cw - 2 * c->bw + aw, ch - 2 * c->bw + ah, False);
i++;
}
}

+ 24
- 0
suckless/dwm/patch/aspectresize.c View File

@ -0,0 +1,24 @@
void
aspectresize(const Arg *arg)
{
/* only floating windows can be moved */
Client *c;
c = selmon->sel;
float ratio;
int w, h,nw, nh;
if (!c || !arg)
return;
if (selmon->lt[selmon->sellt]->arrange && !c->isfloating)
return;
ratio = (float)c->w / (float)c->h;
h = arg->i;
w = (int)(ratio * h);
nw = c->w + w;
nh = c->h + h;
XRaiseWindow(dpy, c->win);
resize(c, c->x, c->y, nw, nh, True);
}

+ 1
- 0
suckless/dwm/patch/aspectresize.h View File

@ -0,0 +1 @@
static void aspectresize(const Arg *arg);

+ 42
- 0
suckless/dwm/patch/attachx.c View File

@ -0,0 +1,42 @@
void
attachx(Client *c)
{
#if ATTACHABOVE_PATCH
Client *at;
if (!(c->mon->sel == NULL || c->mon->sel == c->mon->clients || c->mon->sel->isfloating)) {
for (at = c->mon->clients; at->next != c->mon->sel; at = at->next);
c->next = at->next;
at->next = c;
return;
}
#elif ATTACHASIDE_PATCH
Client *at;
unsigned int n;
for (at = c->mon->clients, n = 0; at; at = at->next)
if (!at->isfloating && ISVISIBLEONTAG(at, c->tags))
if (++n >= c->mon->nmaster)
break;
if (at && c->mon->nmaster) {
c->next = at->next;
at->next = c;
return;
}
#elif ATTACHBELOW_PATCH
if (!(c->mon->sel == NULL || c->mon->sel == c || c->mon->sel->isfloating)) {
c->next = c->mon->sel->next;
c->mon->sel->next = c;
return;
}
#elif ATTACHBOTTOM_PATCH
Client *at;
for (at = c->mon->clients; at && at->next; at = at->next);
if (at) {
at->next = c;
c->next = NULL;
return;
}
#endif
attach(c); // master (default)
}

+ 1
- 0
suckless/dwm/patch/attachx.h View File

@ -0,0 +1 @@
static void attachx(Client *c);

+ 83
- 0
suckless/dwm/patch/autostart.c View File

@ -0,0 +1,83 @@
void
runautostart(void)
{
char *pathpfx;
char *path;
char *xdgdatahome;
char *home;
if ((home = getenv("HOME")) == NULL)
/* this is almost impossible */
return;
/* if $XDG_DATA_HOME is defined, use $XDG_DATA_HOME/dwm,
* otherwise use ~/.local/share/dwm as autostart script directory
*/
if ((xdgdatahome = getenv("XDG_DATA_HOME")) != NULL) {
/* space for path segments, separators and nul */
if ((pathpfx = malloc(strlen(xdgdatahome) + strlen(dwmdir) + 2)) == NULL)
return;
if (sprintf(pathpfx, "%s/%s", xdgdatahome, dwmdir) <= 0) {
free(pathpfx);
return;
}
} else {
/* space for path segments, separators and nul */
if ((pathpfx = malloc(strlen(home) + strlen(localshare) + strlen(dwmdir) + 3)) == NULL)
return;
if (sprintf(pathpfx, "%s/%s/%s", home, localshare, dwmdir) < 0) {
free(pathpfx);
return;
}
}
/* check if the autostart script directory exists */
struct stat sb;
if (! (stat(pathpfx, &sb) == 0 && S_ISDIR(sb.st_mode))) {
/* the XDG conformant path does not exist or are not directories
* so we try ~/.dwm instead
*/
if (realloc(pathpfx, strlen(home) + strlen(dwmdir) + 3) == NULL) {
free(pathpfx);
return;
}
if (sprintf(pathpfx, "%s/.%s", home, dwmdir) <= 0) {
free(pathpfx);
return;
}
}
/* try the blocking script first */
if ((path = malloc(strlen(pathpfx) + strlen(autostartblocksh) + 2)) == NULL) {
free(pathpfx);
return;
} else
if (sprintf(path, "%s/%s", pathpfx, autostartblocksh) <= 0) {
free(path);
free(pathpfx);
}
if (access(path, X_OK) == 0)
system(path);
/* now the non-blocking script */
if ((path = realloc(path, strlen(pathpfx) + strlen(autostartsh) + 4)) == NULL) {
free(pathpfx);
free(path);
return;
} else
if (sprintf(path, "%s/%s", pathpfx, autostartsh) <= 0) {
free(path);
free(pathpfx);
}
if (access(path, X_OK) == 0) {
system(strcat(path, " &"));
free(pathpfx);
free(path);
}
}

+ 1
- 0
suckless/dwm/patch/autostart.h View File

@ -0,0 +1 @@
static void runautostart(void);

+ 42
- 0
suckless/dwm/patch/bar_alpha.c View File

@ -0,0 +1,42 @@
static int useargb = 0;
static Visual *visual;
static int depth;
static Colormap cmap;
void
xinitvisual()
{
XVisualInfo *infos;
XRenderPictFormat *fmt;
int nitems;
int i;
XVisualInfo tpl = {
.screen = screen,
.depth = 32,
.class = TrueColor
};
long masks = VisualScreenMask | VisualDepthMask | VisualClassMask;
infos = XGetVisualInfo(dpy, masks, &tpl, &nitems);
visual = NULL;
for (i = 0; i < nitems; i ++) {
fmt = XRenderFindVisualFormat(dpy, infos[i].visual);
if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) {
visual = infos[i].visual;
depth = infos[i].depth;
cmap = XCreateColormap(dpy, root, visual, AllocNone);
useargb = 1;
break;
}
}
XFree(infos);
if (!visual) {
visual = DefaultVisual(dpy, screen);
depth = DefaultDepth(dpy, screen);
cmap = DefaultColormap(dpy, screen);
}
}

+ 3
- 0
suckless/dwm/patch/bar_alpha.h View File

@ -0,0 +1,3 @@
#define OPAQUE 0xffU
static void xinitvisual();

+ 6
- 0
suckless/dwm/patch/bar_alternativetags.c View File

@ -0,0 +1,6 @@
void
togglealttag()
{
selmon->alttag = !selmon->alttag;
drawbar(selmon);
}

+ 1
- 0
suckless/dwm/patch/bar_alternativetags.h View File

@ -0,0 +1 @@
static void togglealttag();

+ 82
- 0
suckless/dwm/patch/bar_anybar.c View File

@ -0,0 +1,82 @@
void
managealtbar(Window win, XWindowAttributes *wa)
{
Monitor *m;
Bar *bar;
int i;
if (!(m = recttomon(wa->x, wa->y, wa->width, wa->height)))
return;
for (i = 0, bar = m->bar; bar && bar->win && bar->next; bar = bar->next, ++i); // find last bar
if (!bar) {
bar = m->bar = ecalloc(1, sizeof(Bar));
bar->topbar = topbar;
} else if (bar && bar->win) {
bar->next = ecalloc(1, sizeof(Bar));
bar->next->topbar = !bar->topbar;
bar = bar->next;
}
bar->external = 1;
bar->showbar = 1;
bar->mon = m;
bar->idx = i;
bar->borderpx = 0;
bar->win = win;
bar->bh = wa->height;
updatebarpos(m);
arrange(m);
XSelectInput(dpy, win, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
XMapWindow(dpy, win);
XMoveResizeWindow(dpy, bar->win, bar->bx, -bar->by, wa->width, bar->bh);
arrange(selmon);
XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
(unsigned char *) &win, 1);
}
void
spawnbar()
{
if (*altbarcmd)
system(altbarcmd);
}
void
unmanagealtbar(Window w)
{
Monitor *m = wintomon(w);
Bar *bar;
if (!m)
return;
for (bar = m->bar; bar && bar->win; bar = bar->next)
if (bar->win == w) {
bar->win = 0;
bar->by = 0;
bar->bh = 0;
break;
}
updatebarpos(m);
arrange(m);
}
int
wmclasscontains(Window win, const char *class, const char *name)
{
XClassHint ch = { NULL, NULL };
int res = 1;
if (XGetClassHint(dpy, win, &ch)) {
if (ch.res_name && strstr(ch.res_name, name) == NULL)
res = 0;
if (ch.res_class && strstr(ch.res_class, class) == NULL)
res = 0;
} else
res = 0;
if (ch.res_class)
XFree(ch.res_class);
if (ch.res_name)
XFree(ch.res_name);
return res;
}

+ 4
- 0
suckless/dwm/patch/bar_anybar.h View File

@ -0,0 +1,4 @@
static void managealtbar(Window win, XWindowAttributes *wa);
static void spawnbar();
static void unmanagealtbar(Window w);
static int wmclasscontains(Window win, const char *class, const char *name);

+ 79
- 0
suckless/dwm/patch/bar_awesomebar.c View File

@ -0,0 +1,79 @@
int
width_awesomebar(Bar *bar, BarArg *a)
{
return a->w;
}
int
draw_awesomebar(Bar *bar, BarArg *a)
{
int n = 0, scm, remainder = 0, tabw, pad;
unsigned int i;
#if BAR_TITLE_LEFT_PAD_PATCH && BAR_TITLE_RIGHT_PAD_PATCH
int x = a->x + lrpad / 2, w = a->w - lrpad;
#elif BAR_TITLE_LEFT_PAD_PATCH
int x = a->x + lrpad / 2, w = a->w - lrpad / 2;
#elif BAR_TITLE_RIGHT_PAD_PATCH
int x = a->x, w = a->w - lrpad / 2;
#else
int x = a->x, w = a->w;
#endif // BAR_TITLE_LEFT_PAD_PATCH | BAR_TITLE_RIGHT_PAD_PATCH
Client *c;
for (c = bar->mon->clients; c; c = c->next)
if (ISVISIBLE(c))
n++;
if (n > 0) {
remainder = w % n;
tabw = w / n;
for (i = 0, c = bar->mon->clients; c; c = c->next, i++) {
if (!ISVISIBLE(c))
continue;
if (bar->mon->sel == c)
scm = SchemeTitleSel;
else if (HIDDEN(c))
scm = SchemeHid;
else
scm = SchemeTitleNorm;
pad = lrpad / 2;
#if BAR_CENTEREDWINDOWNAME_PATCH
if (TEXTW(c->name) < tabw)
pad = (tabw - TEXTW(c->name) + lrpad) / 2;
#endif // BAR_CENTEREDWINDOWNAME_PATCH
drw_setscheme(drw, scheme[scm]);
drw_text(drw, x, a->y, tabw + (i < remainder ? 1 : 0), a->h, pad, c->name, 0, False);
drawstateindicator(c->mon, c, 1, x, a->y, tabw + (i < remainder ? 1 : 0), a->h, 0, 0, c->isfixed);
x += tabw + (i < remainder ? 1 : 0);
}
}
return n;
}
int
click_awesomebar(Bar *bar, Arg *arg, BarArg *a)
{
int x = 0, n = 0;
Client *c;
for (c = bar->mon->clients; c; c = c->next)
if (ISVISIBLE(c))
n++;
c = bar->mon->clients;
do {
if (!c || !ISVISIBLE(c))
continue;
else
x += (1.0 / (double)n) * a->w;
} while (c && a->x > x && (c = c->next));
if (c) {
arg->v = c;
return ClkWinTitle;
}
return -1;
}

+ 3
- 0
suckless/dwm/patch/bar_awesomebar.h View File

@ -0,0 +1,3 @@
static int width_awesomebar(Bar *bar, BarArg *a);
static int draw_awesomebar(Bar *bar, BarArg *a);
static int click_awesomebar(Bar *bar, Arg *arg, BarArg *a);

+ 31
- 0
suckless/dwm/patch/bar_dwmblocks.c View File

@ -0,0 +1,31 @@
static int dwmblockssig;
pid_t dwmblockspid = 0;
int
getdwmblockspid()
{
char buf[16];
FILE *fp = popen("pidof -s dwmblocks", "r");
if (fgets(buf, sizeof(buf), fp));
pid_t pid = strtoul(buf, NULL, 10);
pclose(fp);
dwmblockspid = pid;
return pid != 0 ? 0 : -1;
}
void
sigdwmblocks(const Arg *arg)
{
union sigval sv;
sv.sival_int = (dwmblockssig << 8) | arg->i;
if (!dwmblockspid)
if (getdwmblockspid() == -1)
return;
if (sigqueue(dwmblockspid, SIGUSR1, sv) == -1) {
if (errno == ESRCH) {
if (!getdwmblockspid())
sigqueue(dwmblockspid, SIGUSR1, sv);
}
}
}

+ 2
- 0
suckless/dwm/patch/bar_dwmblocks.h View File

@ -0,0 +1,2 @@
static int getdwmblockspid();
static void sigdwmblocks(const Arg *arg);

+ 52
- 0
suckless/dwm/patch/bar_ewmhtags.c View File

@ -0,0 +1,52 @@
void
setcurrentdesktop(void)
{
long data[] = { 0 };
XChangeProperty(dpy, root, netatom[NetCurrentDesktop], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1);
}
void
setdesktopnames(void)
{
int i;
XTextProperty text;
char *tags[NUMTAGS];
for (i = 0; i < NUMTAGS; i++)
tags[i] = tagicon(selmon, i);
Xutf8TextListToTextProperty(dpy, tags, NUMTAGS, XUTF8StringStyle, &text);
XSetTextProperty(dpy, root, &text, netatom[NetDesktopNames]);
}
void
setfloatinghint(Client *c)
{
Atom target = XInternAtom(dpy, "_IS_FLOATING", 0);
unsigned int floating[1] = {c->isfloating};
XChangeProperty(dpy, c->win, target, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)floating, 1);
}
void
setnumdesktops(void)
{
long data[] = { NUMTAGS };
XChangeProperty(dpy, root, netatom[NetNumberOfDesktops], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1);
}
void
setviewport(void)
{
long data[] = { 0, 0 };
XChangeProperty(dpy, root, netatom[NetDesktopViewport], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 2);
}
void
updatecurrentdesktop(void)
{
long rawdata[] = { selmon->tagset[selmon->seltags] };
int i = 0;
while (*rawdata >> (i + 1)) {
i++;
}
long data[] = { i };
XChangeProperty(dpy, root, netatom[NetCurrentDesktop], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1);
}

+ 6
- 0
suckless/dwm/patch/bar_ewmhtags.h View File

@ -0,0 +1,6 @@
static void setcurrentdesktop(void);
static void setdesktopnames(void);
static void setfloatinghint(Client *c);
static void setnumdesktops(void);
static void setviewport(void);
static void updatecurrentdesktop(void);

+ 70
- 0
suckless/dwm/patch/bar_fancybar.c View File

@ -0,0 +1,70 @@
int
width_fancybar(Bar *bar, BarArg *a)
{
return a->w;
}
int
draw_fancybar(Bar *bar, BarArg *a)
{
int ftw, mw, ew = 0, n = 0;
unsigned int i;
Client *c;
Monitor *m = bar->mon;
#if BAR_TITLE_LEFT_PAD_PATCH && BAR_TITLE_RIGHT_PAD_PATCH
int x = a->x + lrpad / 2, w = a->w - lrpad;
#elif BAR_TITLE_LEFT_PAD_PATCH
int x = a->x + lrpad / 2, w = a->w - lrpad / 2;
#elif BAR_TITLE_RIGHT_PAD_PATCH
int x = a->x, w = a->w - lrpad / 2;
#else
int x = a->x, w = a->w;
#endif // BAR_TITLE_LEFT_PAD_PATCH | BAR_TITLE_RIGHT_PAD_PATCH
for (c = m->clients; c; c = c->next) {
if (ISVISIBLE(c))
n++;
}
if (n > 0) {
ftw = TEXTW(m->sel->name);
mw = (ftw >= w || n == 1) ? 0 : (w - ftw) / (n - 1);
i = 0;
for (c = m->clients; c; c = c->next) {
if (!ISVISIBLE(c) || c == m->sel)
continue;
ftw = TEXTW(c->name);
if (ftw < mw)
ew += (mw - ftw);
else
i++;
}
if (i > 0)
mw += ew / i;
for (c = m->clients; c; c = c->next) {
if (!ISVISIBLE(c))
continue;
ftw = MIN(m->sel == c ? w : mw, TEXTW(c->name));
drw_setscheme(drw, scheme[m->sel == c ? SchemeTitleSel : SchemeTitleNorm]);
if (ftw > 0) /* trap special handling of 0 in drw_text */
drw_text(drw, x, a->y, ftw, a->h, lrpad / 2, c->name, 0, False);
drawstateindicator(c->mon, c, 1, x, a->y, ftw, a->h, 0, 0, c->isfixed);
x += ftw;
w -= ftw;
}
}
return n;
}
int
click_fancybar(Bar *bar, Arg *arg, BarArg *a)
{
return ClkWinTitle;
}

+ 3
- 0
suckless/dwm/patch/bar_fancybar.h View File

@ -0,0 +1,3 @@
static int width_fancybar(Bar *bar, BarArg *a);
static int draw_fancybar(Bar *bar, BarArg *a);
static int click_fancybar(Bar *bar, Arg *arg, BarArg *a);

+ 436
- 0
suckless/dwm/patch/bar_flexwintitle.c View File

@ -0,0 +1,436 @@
/* Flexwintitle properties, you can override these in your config.h if you want. */
#ifndef FLEXWINTITLE_BORDERS
#define FLEXWINTITLE_BORDERS 1 // 0 = off, 1 = on
#endif
#ifndef FLEXWINTITLE_SHOWFLOATING
#define FLEXWINTITLE_SHOWFLOATING 0 // whether to show titles for floating windows, hidden clients are always shown
#endif
#ifndef FLEXWINTITLE_MASTERWEIGHT
#define FLEXWINTITLE_MASTERWEIGHT 9 // master weight compared to stack, hidden and floating window titles
#endif
#ifndef FLEXWINTITLE_STACKWEIGHT
#define FLEXWINTITLE_STACKWEIGHT 3 // stack weight compared to master, hidden and floating window titles
#endif
#ifndef FLEXWINTITLE_HIDDENWEIGHT
#define FLEXWINTITLE_HIDDENWEIGHT 1 // hidden window title weight
#endif
#ifndef FLEXWINTITLE_FLOATWEIGHT
#define FLEXWINTITLE_FLOATWEIGHT 1 // floating window title weight, set to 0 to not show floating windows
#endif
#define SCHEMEFOR(c) getschemefor(m, c, groupactive == c)
enum { GRP_NOSELECTION, GRP_MASTER, GRP_STACK1, GRP_STACK2, GRP_FLOAT, GRP_HIDDEN };
int
width_flexwintitle(Bar *bar, BarArg *a)
{
return a->w;
}
int
draw_flexwintitle(Bar *bar, BarArg *a)
{
drw_rect(drw, a->x, a->y, a->w, a->h, 1, 1);
return flextitlecalculate(bar->mon, a->x, a->w, -1, flextitledraw, NULL, a);
}
int
click_flexwintitle(Bar *bar, Arg *arg, BarArg *a)
{
flextitlecalculate(bar->mon, 0, a->w, a->x, flextitleclick, arg, a);
return ClkWinTitle;
}
Client *
flextitledrawarea(Monitor *m, Client *c, int x, int r, int w, int max_clients, int scheme, int draw_tiled, int draw_hidden, int draw_floating,
int passx, void(*tabfn)(Monitor *, Client *, int, int, int, int, Arg *arg, BarArg *barg), Arg *arg, BarArg *barg)
{
int i;
for (i = 0; c && i < max_clients; c = c->next) {
if (
ISVISIBLE(c) &&
(
(draw_tiled && !c->isfloating && !HIDDEN(c)) ||
(draw_floating && c->isfloating && !HIDDEN(c)) ||
(draw_hidden && HIDDEN(c))
)
) {
tabfn(m, c, passx, x, w + (i < r ? 1 : 0), scheme, arg, barg);
x += w + (i < r ? 1 : 0);
i++;
}
}
return c;
}
int
getschemefor(Monitor *m, int group, int activegroup)
{
switch (group) {
case GRP_NOSELECTION:
case GRP_MASTER:
case GRP_STACK1:
case GRP_STACK2:
#if BSTACK_LAYOUT
if (m->lt[m->sellt]->arrange == &bstack)
return (activegroup ? SchemeFlexActLTR : SchemeFlexInaLTR);
#endif // BSTACK_LAYOUT
#if BSTACKHORIZ_LAYOUT
if (m->lt[m->sellt]->arrange == &bstackhoriz) {
if (group == GRP_MASTER)
return (activegroup ? SchemeFlexActLTR : SchemeFlexInaLTR);
else
return (activegroup ? SchemeFlexActTTB : SchemeFlexInaTTB);
}
#endif // BSTACKHORIZ_LAYOUT
#if CENTEREDMASTER_LAYOUT
if (m->lt[m->sellt]->arrange == &centeredmaster)
return (activegroup ? SchemeFlexActTTB : SchemeFlexInaTTB);
#endif // CENTEREDMASTER_LAYOUT
#if CENTEREDFLOATINGMASTER_LAYOUT
if (m->lt[m->sellt]->arrange == &centeredfloatingmaster)
return (activegroup ? SchemeFlexActLTR : SchemeFlexInaLTR);
#endif // CENTEREDFLOATINGMASTER_LAYOUT
#if COLUMNS_LAYOUT
if (m->lt[m->sellt]->arrange == &col) {
if (group == GRP_MASTER)
return (activegroup ? SchemeFlexActLTR : SchemeFlexInaLTR);
else
return (activegroup ? SchemeFlexActTTB : SchemeFlexInaTTB);
}
#endif // COLUMNS_LAYOUT
#if DECK_LAYOUT
if (m->lt[m->sellt]->arrange == &deck) {
if (group == GRP_MASTER)
return (activegroup ? SchemeFlexActTTB : SchemeFlexInaTTB);
else
return (activegroup ? SchemeFlexActMONO : SchemeFlexInaMONO);
}
#endif // DECK_LAYOUT
#if FIBONACCI_DWINDLE_LAYOUT
if (m->lt[m->sellt]->arrange == &dwindle)
return (activegroup ? SchemeFlexActDWDL : SchemeFlexInaDWDL);
#endif // FIBONACCI_DWINDLE_LAYOUT
#if FIBONACCI_SPIRAL_LAYOUT
if (m->lt[m->sellt]->arrange == &spiral)
return (activegroup ? SchemeFlexActSPRL : SchemeFlexInaSPRL);
#endif // FIBONACCI_SPIRAL_LAYOUT
#if FLEXTILE_DELUXE_LAYOUT
if (m->lt[m->sellt]->arrange == &flextile)
return (activegroup ? SchemeFlexActTTB + m->ltaxis[group] : SchemeFlexInaTTB + m->ltaxis[group]);
#endif // FLEXTILE_DELUXE_LAYOUT
#if GAPPLESSGRID_LAYOUT
if (m->lt[m->sellt]->arrange == &gaplessgrid)
return (activegroup ? SchemeFlexActGRID : SchemeFlexInaGRID);
#endif // GAPPLESSGRID_LAYOUT
#if GRIDMODE_LAYOUT
if (m->lt[m->sellt]->arrange == &grid)
return (activegroup ? SchemeFlexActGRDM : SchemeFlexInaGRDM);
#endif // GRIDMODE_LAYOUT
#if HORIZGRID_LAYOUT
if (m->lt[m->sellt]->arrange == &horizgrid)
return (activegroup ? SchemeFlexActHGRD : SchemeFlexInaHGRD);
#endif // HORIZGRID_LAYOUT
#if NROWGRID_LAYOUT
if (m->lt[m->sellt]->arrange == &nrowgrid)
return (activegroup ? SchemeFlexActGRD1 : SchemeFlexInaGRD1);
#endif // NROWGRID_LAYOUT
#if TILE_LAYOUT
if (m->lt[m->sellt]->arrange == &tile)
return (activegroup ? SchemeFlexActTTB : SchemeFlexInaTTB);
#endif // TILE_LAYOUT
#if MONOCLE_LAYOUT
if (m->lt[m->sellt]->arrange == &monocle)
return (activegroup ? SchemeFlexActMONO : SchemeFlexInaMONO);
#endif // MONOCLE_LAYOUT
return SchemeTitleNorm;
case GRP_HIDDEN:
return SchemeHid;
case GRP_FLOAT:
return (activegroup ? SchemeFlexActFloat : SchemeFlexInaFloat);
}
return SchemeTitleNorm;
}
int
getselschemefor(int scheme)
{
if (scheme == SchemeFlexActFloat || scheme == SchemeFlexInaFloat)
return SchemeFlexSelFloat;
if (scheme >= SchemeFlexInaTTB)
return scheme + SchemeFlexInaTTB - SchemeFlexActTTB;
if (scheme >= SchemeFlexActTTB)
return scheme + SchemeFlexSelTTB - SchemeFlexActTTB;
return SchemeTitleSel;
}
void
flextitledraw(Monitor *m, Client *c, int unused, int x, int w, int tabscheme, Arg *arg, BarArg *barg)
{
if (!c)
return;
int i, nclienttags = 0, nviewtags = 0, pad = lrpad / 2;
int clientscheme = (
c == selmon->sel
? getselschemefor(tabscheme)
: HIDDEN(c)
? SchemeHid
: c->isurgent
? SchemeUrg
: tabscheme
);
drw_setscheme(drw, scheme[clientscheme]);
XSetWindowBorder(dpy, c->win, scheme[clientscheme][ColBorder].pixel);
if (w <= TEXTW("A") - lrpad + pad) // reduce text padding if wintitle is too small
pad = (w - TEXTW("A") + lrpad < 0 ? 0 : (w - TEXTW("A") + lrpad) / 2);
#if BAR_CENTEREDWINDOWNAME_PATCH
else if (TEXTW(c->name) < w)
pad = (w - TEXTW(c->name) + lrpad) / 2;
#endif // BAR_CENTEREDWINDOWNAME_PATCH
drw_text(drw, x, barg->y, w, barg->h, pad, c->name, 0, False);
drawstateindicator(m, c, 1, x + 2, barg->y, w, barg->h, 0, 0, 0);
if (FLEXWINTITLE_BORDERS) {
XSetForeground(drw->dpy, drw->gc, scheme[SchemeSel][ColBorder].pixel);
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, barg->y, 1, barg->h);
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x + w - (x + w >= barg->w ? 1 : 0), barg->y, 1, barg->h);
}
/* Optional tags icons */
for (i = 0; i < NUMTAGS; i++) {
if ((m->tagset[m->seltags] >> i) & 1)
nviewtags++;
if ((c->tags >> i) & 1)
nclienttags++;
}
if (TAGSINDICATOR == 2 || nclienttags > 1 || nviewtags > 1)
drawindicator(m, c, 1, x, barg->y, w, barg->h, 0, 0, 0, INDICATOR_RIGHT_TAGS);
}
#ifndef HIDDEN
#define HIDDEN(C) 0
#endif
void
flextitleclick(Monitor *m, Client *c, int passx, int x, int w, int unused, Arg *arg, BarArg *barg)
{
if (passx >= x && passx <= x + w)
arg->v = c;
}
int
flextitlecalculate(
Monitor *m, int offx, int tabw, int passx,
void(*tabfn)(Monitor *, Client *, int, int, int, int, Arg *arg, BarArg *barg),
Arg *arg, BarArg *barg
) {
Client *c;
int n, center = 0, mirror = 0, fixed = 0; // layout configuration
int clientsnmaster = 0, clientsnstack = 0, clientsnfloating = 0, clientsnhidden = 0;
int i, w, r, num = 0, den, fulllayout = 0;
int clientsnstack2 = 0;
int groupactive = 0;
int selidx = 0;
int dualstack = 0;
int rw, rr;
int mas_x = offx, st1_x = offx, st2_x = offx, hid_x = offx, flt_x = offx;
int mas_w, st1_w, st2_w, hid_w;
for (i = 0, c = m->clients; c; c = c->next) {
if (!ISVISIBLE(c))
continue;
if (HIDDEN(c)) {
if (FLEXWINTITLE_HIDDENWEIGHT)
clientsnhidden++;
continue;
}
if (c->isfloating) {
if (FLEXWINTITLE_FLOATWEIGHT)
clientsnfloating++;
continue;
}
if (m->sel == c)
selidx = i;
if (i < m->nmaster)
clientsnmaster++;
#if FLEXTILE_DELUXE_LAYOUT
else if (m->nstack) {
if (clientsnstack < m->nstack)
clientsnstack++;
else
clientsnstack2++;
}
#endif // FLEXTILE_DELUXE_LAYOUT
else if ((i - m->nmaster) % 2)
clientsnstack2++;
else
clientsnstack++;
i++;
}
if (!m->sel)
groupactive = GRP_NOSELECTION;
else if (HIDDEN(m->sel))
groupactive = GRP_HIDDEN;
else if (m->sel->isfloating)
groupactive = GRP_FLOAT;
else if (selidx < clientsnmaster)
groupactive = GRP_MASTER;
else if (selidx < clientsnmaster + clientsnstack)
groupactive = GRP_STACK1;
else if (selidx < clientsnmaster + clientsnstack + clientsnstack2)
groupactive = GRP_STACK2;
n = clientsnmaster + clientsnstack + clientsnstack2 + clientsnfloating + clientsnhidden;
if (n == 0)
return 0;
#if FLEXTILE_DELUXE_LAYOUT
else if (m->lt[m->sellt]->arrange == &flextile) {
int layout = m->ltaxis[LAYOUT];
if (layout < 0) {
mirror = 1;
layout *= -1;
}
if (layout > FLOATING_MASTER) {
layout -= FLOATING_MASTER;
fixed = 1;
}
if (layout == SPLIT_HORIZONTAL_DUAL_STACK || layout == SPLIT_HORIZONTAL_DUAL_STACK_FIXED)
dualstack = 1;
else if (layout == SPLIT_CENTERED_VERTICAL && (fixed || n - m->nmaster > 1))
center = 1;
else if (layout == FLOATING_MASTER)
center = 1;
else if (layout == SPLIT_CENTERED_HORIZONTAL) {
if (fixed || n - m->nmaster > 1)
center = 1;
}
}
#endif // FLEXTILE_DELUXE_LAYOUT
#if CENTEREDMASTER_LAYOUT
else if (m->lt[m->sellt]->arrange == &centeredmaster && (fixed || n - m->nmaster > 1))
center = 1;
#endif // CENTEREDMASTER_LAYOUT
#if CENTEREDFLOATINGMASTER_LAYOUT
else if (m->lt[m->sellt]->arrange == &centeredfloatingmaster)
center = 1;
#endif // CENTEREDFLOATINGMASTER_LAYOUT
/* Certain layouts have no master / stack areas */
if (!m->lt[m->sellt]->arrange // floating layout
|| (!n || (!fixed && m->nmaster && n <= m->nmaster)) // no master
#if MONOCLE_LAYOUT
|| m->lt[m->sellt]->arrange == &monocle
#endif // MONOCLE_LAYOUT
#if GRIDMODE_LAYOUT
|| m->lt[m->sellt]->arrange == &grid
#endif // GRIDMODE_LAYOUT
#if HORIZGRID_LAYOUT
|| m->lt[m->sellt]->arrange == &horizgrid
#endif // HORIZGRID_LAYOUT
#if GAPPLESSGRID_LAYOUT
|| m->lt[m->sellt]->arrange == &gaplessgrid
#endif // GAPPLESSGRID_LAYOUT
#if NROWGRID_LAYOUT
|| m->lt[m->sellt]->arrange == &nrowgrid
#endif // NROWGRID_LAYOUT
#if FLEXTILE_DELUXE_LAYOUT
|| (m->lt[m->sellt]->arrange == &flextile && m->ltaxis[LAYOUT] == NO_SPLIT)
#endif // FLEXTILE_DELUXE_LAYOUT
)
fulllayout = 1;
num = tabw;
c = m->clients;
/* floating mode */
if ((fulllayout && FLEXWINTITLE_FLOATWEIGHT > 0) || clientsnmaster + clientsnstack == 0 || !m->lt[m->sellt]->arrange) {
den = clientsnmaster + clientsnstack + clientsnstack2 + clientsnfloating + clientsnhidden;
w = num / den;
r = num % den; // rest
c = flextitledrawarea(m, c, mas_x, r, w, den, !m->lt[m->sellt]->arrange ? SchemeFlexActFloat : SCHEMEFOR(GRP_MASTER), 1, FLEXWINTITLE_HIDDENWEIGHT, FLEXWINTITLE_FLOATWEIGHT, passx, tabfn, arg, barg); // floating
/* no master and stack mode, e.g. monocole, grid layouts, fibonacci */
} else if (fulllayout) {
den = clientsnmaster + clientsnstack + clientsnstack2 + clientsnhidden;
w = num / den;
r = num % den; // rest
c = flextitledrawarea(m, c, mas_x, r, w, den, SCHEMEFOR(GRP_MASTER), 1, FLEXWINTITLE_HIDDENWEIGHT, 0, passx, tabfn, arg, barg); // full
/* tiled mode */
} else {
den = clientsnmaster * FLEXWINTITLE_MASTERWEIGHT + (clientsnstack + clientsnstack2) * FLEXWINTITLE_STACKWEIGHT + clientsnfloating * FLEXWINTITLE_FLOATWEIGHT + clientsnhidden * FLEXWINTITLE_HIDDENWEIGHT;
w = num / den; // weight width per client
r = num % den; // weight rest width
rw = r / n; // rest incr per client
rr = r % n; // rest rest
#if FLEXTILE_DELUXE_LAYOUT
if ((!center && !dualstack) || (center && n <= m->nmaster + (m->nstack ? m->nstack : 1)))
#else
if ((!center && !dualstack) || (center && n <= m->nmaster + 1))
#endif // FLEXTILE_DELUXE_LAYOUT
{
clientsnstack += clientsnstack2;
clientsnstack2 = 0;
if (groupactive == GRP_STACK2)
groupactive = GRP_STACK1;
}
mas_w = clientsnmaster * rw + w * clientsnmaster * FLEXWINTITLE_MASTERWEIGHT + (rr > 0 ? MIN(rr, clientsnmaster) : 0);
rr -= clientsnmaster;
st1_w = clientsnstack * (rw + w * FLEXWINTITLE_STACKWEIGHT) + (rr > 0 ? MIN(rr, clientsnstack) : 0);
rr -= clientsnstack;
st2_w = clientsnstack2 * (rw + w * FLEXWINTITLE_STACKWEIGHT) + (rr > 0 ? MIN(rr, clientsnstack2) : 0);
rr -= clientsnstack2;
hid_w = clientsnhidden * (rw + w * FLEXWINTITLE_HIDDENWEIGHT) + (rr > 0 ? MIN(rr, clientsnhidden) : 0);
rr -= clientsnhidden;
rr = r % n;
if (mirror) {
if (center && clientsnstack2) {
mas_x = st1_x + st1_w;
st2_x = mas_x + mas_w;
hid_x = st2_x + st2_w;
} else {
if (clientsnstack2) {
st2_x = st1_x + st1_w;
mas_x = st2_x + st2_w;
} else
mas_x = st1_x + st1_w;
hid_x = mas_x + mas_w;
}
} else {
if (center && clientsnstack2) {
mas_x = st2_x + st2_w;
st1_x = mas_x + mas_w;
hid_x = st1_x + st1_w;
} else {
st1_x = mas_x + mas_w;
if (clientsnstack2) {
st2_x = st1_x + st1_w;
hid_x = st2_x + st2_w;
} else
hid_x = st1_x + st1_w;
}
}
flt_x = hid_x + hid_w;
c = flextitledrawarea(m, c, mas_x, rr, w * FLEXWINTITLE_MASTERWEIGHT + rw, clientsnmaster, SCHEMEFOR(GRP_MASTER), 1, 0, 0, passx, tabfn, arg, barg); // master
rr -= clientsnmaster;
c = flextitledrawarea(m, c, st1_x, rr, w * FLEXWINTITLE_STACKWEIGHT + rw, clientsnstack, SCHEMEFOR(GRP_STACK1), 1, 0, 0, passx, tabfn, arg, barg); // stack1
rr -= clientsnstack;
if (clientsnstack2) {
c = flextitledrawarea(m, c, st2_x, rr, w * FLEXWINTITLE_STACKWEIGHT + rw, clientsnstack2, SCHEMEFOR(GRP_STACK2), 1, 0, 0, passx, tabfn, arg, barg); // stack2
rr -= clientsnstack2;
}
c = flextitledrawarea(m, m->clients, hid_x, rr, w * FLEXWINTITLE_HIDDENWEIGHT + rw, clientsnhidden, SCHEMEFOR(GRP_HIDDEN), 0, 1, 0, passx, tabfn, arg, barg); // hidden
rr -= clientsnhidden;
c = flextitledrawarea(m, m->clients, flt_x, rr, w * FLEXWINTITLE_FLOATWEIGHT + rw, clientsnfloating, SCHEMEFOR(GRP_FLOAT), 0, 0, 1, passx, tabfn, arg, barg); // floating
}
return 1;
}

+ 10
- 0
suckless/dwm/patch/bar_flexwintitle.h View File

@ -0,0 +1,10 @@
static int width_flexwintitle(Bar *bar, BarArg *a);
static int draw_flexwintitle(Bar *bar, BarArg *a);
static int click_flexwintitle(Bar *bar, Arg *arg, BarArg *a);
static void flextitledraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive, Arg *arg, BarArg *barg);
static void flextitleclick(Monitor *m, Client *c, int passx, int x, int w, int unused, Arg *arg, BarArg *barg);
static int flextitlecalculate(Monitor *m, int offx, int w, int passx, void(*tabfn)(Monitor *, Client *, int, int, int, int, Arg *arg, BarArg *barg), Arg *arg, BarArg *barg);
static int getschemefor(Monitor *m, int group, int activegroup);
static int getselschemefor(int scheme);
static Client *flextitledrawarea(Monitor *m, Client *c, int x, int r, int w, int max_clients, int tabscheme, int draw_tiled, int draw_hidden, int draw_floating, int passx, void(*tabfn)(Monitor *, Client *, int, int, int, int, Arg *arg, BarArg *barg), Arg *arg, BarArg *barg);

+ 37
- 0
suckless/dwm/patch/bar_holdbar.c View File

@ -0,0 +1,37 @@
void
holdbar(const Arg *arg)
{
if (selmon->showbar)
return;
Bar *bar;
selmon->showbar = 2;
updatebarpos(selmon);
for (bar = selmon->bar; bar; bar = bar->next)
XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh);
}
void
keyrelease(XEvent *e)
{
Bar *bar;
if (XEventsQueued(dpy, QueuedAfterReading)) {
XEvent ne;
XPeekEvent(dpy, &ne);
if (ne.type == KeyPress && ne.xkey.time == e->xkey.time &&
ne.xkey.keycode == e->xkey.keycode) {
XNextEvent(dpy, &ne);
return;
}
}
if (e->xkey.keycode == XKeysymToKeycode(dpy, HOLDKEY) && selmon->showbar == 2) {
selmon->showbar = 0;
updatebarpos(selmon);
for (bar = selmon->bar; bar; bar = bar->next)
XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh);
arrange(selmon);
}
#if COMBO_PATCH
combo = 0;
#endif // COMBO_PATCH
}

+ 2
- 0
suckless/dwm/patch/bar_holdbar.h View File

@ -0,0 +1,2 @@
static void keyrelease(XEvent *e);
static void holdbar(const Arg *arg);

+ 110
- 0
suckless/dwm/patch/bar_indicators.c View File

@ -0,0 +1,110 @@
/* Indicator properties, you can override these in your config.h if you want. */
#ifndef TAGSINDICATOR
#define TAGSINDICATOR 1 // 0 = off, 1 = on if >1 client/view tag, 2 = always on
#endif
#ifndef TAGSPX
#define TAGSPX 5 // # pixels for tag grid boxes
#endif
#ifndef TAGSROWS
#define TAGSROWS 3 // # rows in tag grid (9 tags, e.g. 3x3)
#endif
void
drawindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert, int type)
{
int i, boxw, boxs, indn = 0;
if (!(occ & 1 << tag) || type == INDICATOR_NONE)
return;
boxs = drw->fonts->h / 9;
boxw = drw->fonts->h / 6 + 2;
if (filled == -1)
filled = m == selmon && m->sel && m->sel->tags & 1 << tag;
switch (type) {
default:
case INDICATOR_TOP_LEFT_SQUARE:
drw_rect(drw, x + boxs, y + boxs, boxw, boxw, filled, invert);
break;
case INDICATOR_TOP_LEFT_LARGER_SQUARE:
drw_rect(drw, x + boxs + 2, y + boxs+1, boxw+1, boxw+1, filled, invert);
break;
case INDICATOR_TOP_BAR:
drw_rect(drw, x + boxw, y, w - ( 2 * boxw + 1), boxw/2, filled, invert);
break;
case INDICATOR_TOP_BAR_SLIM:
drw_rect(drw, x + boxw, y, w - ( 2 * boxw + 1), 1, 0, invert);
break;
case INDICATOR_BOTTOM_BAR:
drw_rect(drw, x + boxw, y + h - boxw/2, w - ( 2 * boxw + 1), boxw/2, filled, invert);
break;
case INDICATOR_BOTTOM_BAR_SLIM:
drw_rect(drw, x + boxw, y + h - 1, w - ( 2 * boxw + 1), 1, 0, invert);
break;
case INDICATOR_BOX:
drw_rect(drw, x + boxw, y, w - 2 * boxw, h, 0, invert);
break;
case INDICATOR_BOX_WIDER:
drw_rect(drw, x + boxw/2, y, w - boxw, h, 0, invert);
break;
case INDICATOR_BOX_FULL:
drw_rect(drw, x, y, w - 2, h, 0, invert);
break;
case INDICATOR_CLIENT_DOTS:
for (c = m->clients; c; c = c->next) {
if (c->tags & (1 << tag)) {
drw_rect(drw, x, 1 + (indn * 2), m->sel == c ? 6 : 1, 1, 1, invert);
indn++;
}
if (h <= 1 + (indn * 2)) {
indn = 0;
x += 2;
}
}
break;
case INDICATOR_RIGHT_TAGS:
if (!c)
break;
for (i = 0; i < NUMTAGS; i++) {
drw_rect(drw,
( x + w - 2 - ((NUMTAGS / TAGSROWS) * TAGSPX)
- (i % (NUMTAGS/TAGSROWS)) + ((i % (NUMTAGS / TAGSROWS)) * TAGSPX)
),
( y + 2 + ((i / (NUMTAGS/TAGSROWS)) * TAGSPX)
- ((i / (NUMTAGS/TAGSROWS)))
),
TAGSPX, TAGSPX, (c->tags >> i) & 1, 0
);
}
break;
case INDICATOR_PLUS_AND_LARGER_SQUARE:
boxs += 2;
boxw += 2;
/* falls through */
case INDICATOR_PLUS_AND_SQUARE:
drw_rect(drw, x + boxs, y + boxs, boxw % 2 ? boxw : boxw + 1, boxw % 2 ? boxw : boxw + 1, filled, invert);
/* falls through */
case INDICATOR_PLUS:
if (!(boxw % 2))
boxw += 1;
drw_rect(drw, x + boxs + boxw / 2, y + boxs, 1, boxw, filled, invert); // |
drw_rect(drw, x + boxs, y + boxs + boxw / 2, boxw + 1, 1, filled, invert); //
break;
}
}
void
drawstateindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert)
{
#if FAKEFULLSCREEN_CLIENT_PATCH
if (c->fakefullscreen && c->isfloating)
drawindicator(m, c, occ, x, y, w, h, tag, filled, invert, floatfakefsindicatortype);
else if (c->fakefullscreen)
drawindicator(m, c, occ, x, y, w, h, tag, filled, invert, fakefsindicatortype);
else
#endif // FAKEFULLSCREEN_CLIENT_PATCH
if (c->isfloating)
drawindicator(m, c, occ, x, y, w, h, tag, filled, invert, floatindicatortype);
else
drawindicator(m, c, occ, x, y, w, h, tag, filled, invert, tiledindicatortype);
}

+ 20
- 0
suckless/dwm/patch/bar_indicators.h View File

@ -0,0 +1,20 @@
enum {
INDICATOR_NONE,
INDICATOR_TOP_LEFT_SQUARE,
INDICATOR_TOP_LEFT_LARGER_SQUARE,
INDICATOR_TOP_BAR,
INDICATOR_TOP_BAR_SLIM,
INDICATOR_BOTTOM_BAR,
INDICATOR_BOTTOM_BAR_SLIM,
INDICATOR_BOX,
INDICATOR_BOX_WIDER,
INDICATOR_BOX_FULL,
INDICATOR_CLIENT_DOTS,
INDICATOR_RIGHT_TAGS,
INDICATOR_PLUS,
INDICATOR_PLUS_AND_SQUARE,
INDICATOR_PLUS_AND_LARGER_SQUARE,
};
static void drawindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert, int type);
static void drawstateindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert);

+ 18
- 0
suckless/dwm/patch/bar_layoutmenu.c View File

@ -0,0 +1,18 @@
void
layoutmenu(const Arg *arg) {
FILE *p;
char c[3], *s;
int i;
if (!(p = popen(layoutmenu_cmd, "r")))
return;
s = fgets(c, sizeof(c), p);
pclose(p);
if (!s || *s == '\0' || c == '\0')
return;
i = atoi(c);
setlayout(&((Arg) { .v = &layouts[i] }));
}

+ 1
- 0
suckless/dwm/patch/bar_layoutmenu.h View File

@ -0,0 +1 @@
static void layoutmenu(const Arg *arg);

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save