dotfiles

Mahdi's dotfiles
git clone git://mahdi.pw/dotfiles.git
Log | Files | Refs | Submodules | README | LICENSE

commit fffd5c7f5109234c4d0bf0c58dc648fc068dcd87
parent 6231aedafd862b047ac670eca32d91ff0b00f83b
Author: Mahdi Mirzade <me@mahdi.pw>
Date:   Sat,  8 Oct 2022 22:07:50 +0330

Remove builds

Diffstat:
M.config/mbsync/mbsyncrc | 26+++++++++++++-------------
M.config/mpv/input.conf | 6++++++
M.config/mutt/mailcap | 2+-
M.config/mutt/muttrc | 6++++--
D.config/shell/aliasrc | 36------------------------------------
D.config/shell/inputrc | 15---------------
D.config/shell/profile | 57---------------------------------------------------------
M.config/surf/styles/default.css | 32++++++++++++++++++--------------
M.config/surf/styles/default.css.in | 10+++++++---
M.config/vis/visrc.lua | 67+++++++++++++++++++++++++++++++++++--------------------------------
M.config/x11/colors | 51++++++++++++++++++++-------------------------------
M.config/x11/themes/solarized-dark | 87+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
M.config/x11/xinitrc | 20+++++++-------------
M.config/yt-dlp/config | 2+-
M.config/zathura/zathurarc | 56++++++++++++++++++++++++++++----------------------------
M.local/bin/bg-gen | 1-
M.local/bin/bg-set | 10++++++----
M.local/bin/bright | 135+++++++++++++++++++++++++++++++++++++++++++------------------------------------
M.local/bin/dmenu-archwiki | 6+++---
M.local/bin/dmenu-emoji | 18+++++++++---------
M.local/bin/dmenu-fix-sheet | 36++++++++++++++++++------------------
M.local/bin/dmenu-man | 4++--
M.local/bin/dmenu-power | 9+++++----
M.local/bin/doas-askpass | 2+-
M.local/bin/dwm-bar | 416++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
M.local/bin/email | 86+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
M.local/bin/pacman-up | 6+++---
M.local/bin/screenshot | 34+++++++++++++++++-----------------
M.local/bin/theme-sel | 140+++++++++++++++++++++++++++++++++++++++++--------------------------------------
D.local/bin/volume | 152-------------------------------------------------------------------------------
M.local/bin/vpn | 50+++++++++++++++++++++++++++++++++++++++++++-------
M.local/bin/webcam | 12++++++------
D.local/src/dmenu/LICENSE | 30------------------------------
D.local/src/dmenu/Makefile | 64----------------------------------------------------------------
D.local/src/dmenu/README | 24------------------------
D.local/src/dmenu/arg.h | 49-------------------------------------------------
D.local/src/dmenu/config.h | 60------------------------------------------------------------
D.local/src/dmenu/config.mk | 35-----------------------------------
D.local/src/dmenu/dmenu.1 | 202-------------------------------------------------------------------------------
D.local/src/dmenu/dmenu.c | 1011-------------------------------------------------------------------------------
D.local/src/dmenu/dmenu_path | 13-------------
D.local/src/dmenu/dmenu_run | 2--
D.local/src/dmenu/dmenu_run.hist | 50--------------------------------------------------
D.local/src/dmenu/drw.c | 467-------------------------------------------------------------------------------
D.local/src/dmenu/drw.h | 62--------------------------------------------------------------
D.local/src/dmenu/patches/dmenu-alpha-20210605-1a13d04.diff | 267-------------------------------------------------------------------------------
D.local/src/dmenu/patches/dmenu-bidi-20210723-b34d318.diff | 109-------------------------------------------------------------------------------
D.local/src/dmenu/patches/dmenu-highlight-20201211-fcdc159.diff | 97-------------------------------------------------------------------------------
D.local/src/dmenu/patches/dmenu-linesbelowprompt-and-fullwidth-20211014.diff | 25-------------------------
D.local/src/dmenu/patches/dmenu-password-5.0.diff | 103-------------------------------------------------------------------------------
D.local/src/dmenu/patches/dmenu-preselect-20200513-db6093f.diff | 90-------------------------------------------------------------------------------
D.local/src/dmenu/patches/dmenu-xresources-alt-5.0.diff | 182-------------------------------------------------------------------------------
D.local/src/dmenu/stest.1 | 90-------------------------------------------------------------------------------
D.local/src/dmenu/stest.c | 109-------------------------------------------------------------------------------
D.local/src/dmenu/util.c | 35-----------------------------------
D.local/src/dmenu/util.h | 8--------
D.local/src/dwm/LICENSE | 37-------------------------------------
D.local/src/dwm/Makefile | 51---------------------------------------------------
D.local/src/dwm/README | 48------------------------------------------------
D.local/src/dwm/config.h | 303-------------------------------------------------------------------------------
D.local/src/dwm/config.mk | 42------------------------------------------
D.local/src/dwm/drw.c | 437-------------------------------------------------------------------------------
D.local/src/dwm/drw.h | 57---------------------------------------------------------
D.local/src/dwm/dwm.1 | 205-------------------------------------------------------------------------------
D.local/src/dwm/dwm.c | 3243-------------------------------------------------------------------------------
D.local/src/dwm/dwm.png | 0
D.local/src/dwm/patches/accessnthmon.diff | 100-------------------------------------------------------------------------------
D.local/src/dwm/patches/dwm-actualfullscreen-20211013-cb3f58a.diff | 68--------------------------------------------------------------------
D.local/src/dwm/patches/dwm-attachbottom-20201227-61bb8b2.diff | 67-------------------------------------------------------------------
D.local/src/dwm/patches/dwm-bidi-20220309-0386419.diff | 132-------------------------------------------------------------------------------
D.local/src/dwm/patches/dwm-centeredwindowname-20200723-f035e1e.diff | 30------------------------------
D.local/src/dwm/patches/dwm-cyclelayouts-20180524-6.2.diff | 93-------------------------------------------------------------------------------
D.local/src/dwm/patches/dwm-fullgaps-20200508-7b77734.diff | 138-------------------------------------------------------------------------------
D.local/src/dwm/patches/dwm-hide_vacant_tags-6.3.diff | 39---------------------------------------
D.local/src/dwm/patches/dwm-movestack-20211115-a786211.diff | 95-------------------------------------------------------------------------------
D.local/src/dwm/patches/dwm-noborderfloatingfix-6.2.diff | 31-------------------------------
D.local/src/dwm/patches/dwm-placemouse-6.3.diff | 259-------------------------------------------------------------------------------
D.local/src/dwm/patches/dwm-rainbowtags-6.2.diff | 59-----------------------------------------------------------
D.local/src/dwm/patches/dwm-restartsig-20180523-6.2.diff | 139-------------------------------------------------------------------------------
D.local/src/dwm/patches/dwm-setstatus-6.2.diff | 49-------------------------------------------------
D.local/src/dwm/patches/dwm-status2d-systray-6.3.diff | 888-------------------------------------------------------------------------------
D.local/src/dwm/patches/dwm-statusallmons-6.2.diff | 25-------------------------
D.local/src/dwm/patches/dwm-sticky-6.1.diff | 58----------------------------------------------------------
D.local/src/dwm/patches/dwm-warp-6.2.diff | 58----------------------------------------------------------
D.local/src/dwm/patches/dwm-xrdb-6.2.diff | 188-------------------------------------------------------------------------------
D.local/src/dwm/patches/shiftview.c | 19-------------------
D.local/src/dwm/transient.c | 42------------------------------------------
D.local/src/dwm/util.c | 35-----------------------------------
D.local/src/dwm/util.h | 8--------
D.local/src/merbe/.gitignore | 3---
D.local/src/merbe/LICENSE | 22----------------------
D.local/src/merbe/Makefile | 33---------------------------------
D.local/src/merbe/README | 73-------------------------------------------------------------------------
D.local/src/merbe/config.def.h | 19-------------------
D.local/src/merbe/merbe.c | 246-------------------------------------------------------------------------------
D.local/src/slock/LICENSE | 24------------------------
D.local/src/slock/Makefile | 61-------------------------------------------------------------
D.local/src/slock/README | 24------------------------
D.local/src/slock/arg.h | 65-----------------------------------------------------------------
D.local/src/slock/config.h | 72------------------------------------------------------------------------
D.local/src/slock/config.mk | 40----------------------------------------
D.local/src/slock/explicit_bzero.c | 19-------------------
D.local/src/slock/patches/slock-dpms-1.4.diff | 62--------------------------------------------------------------
D.local/src/slock/patches/slock-failure-command-1.4.diff | 39---------------------------------------
D.local/src/slock/patches/slock-foreground-and-background-20210611-35633d4.diff | 340-------------------------------------------------------------------------------
D.local/src/slock/patches/slock-message-xft-20210315-ae681c5.patch | 237-------------------------------------------------------------------------------
D.local/src/slock/patches/slock-xresources-20191126-53e56c7.diff | 159-------------------------------------------------------------------------------
D.local/src/slock/slock.1 | 39---------------------------------------
D.local/src/slock/slock.c | 627-------------------------------------------------------------------------------
D.local/src/slock/util.h | 5-----
D.local/src/st/FAQ | 250-------------------------------------------------------------------------------
D.local/src/st/LEGACY | 17-----------------
D.local/src/st/LICENSE | 34----------------------------------
D.local/src/st/Makefile | 61-------------------------------------------------------------
D.local/src/st/README | 34----------------------------------
D.local/src/st/TODO | 28----------------------------
D.local/src/st/arg.h | 50--------------------------------------------------
D.local/src/st/config.h | 498-------------------------------------------------------------------------------
D.local/src/st/config.mk | 35-----------------------------------
D.local/src/st/patches/st-anysize-0.8.4.diff | 152-------------------------------------------------------------------------------
D.local/src/st/patches/st-blinking_cursor-20211116-2f6e597.diff | 153-------------------------------------------------------------------------------
D.local/src/st/patches/st-columns-rows-reflow-st-unpatched-new.diff | 1529-------------------------------------------------------------------------------
D.local/src/st/patches/st-dynamic-cursor-color-0.8.4.diff | 52----------------------------------------------------
D.local/src/st/patches/st-externalpipe-0.8.4.diff | 92-------------------------------------------------------------------------------
D.local/src/st/patches/st-externalpipe-eternal-0.8.3.diff | 74--------------------------------------------------------------------------
D.local/src/st/patches/st-font2-20190416-ba72400.diff | 167-------------------------------------------------------------------------------
D.local/src/st/patches/st-hidecursor-0.8.3.diff | 88-------------------------------------------------------------------------------
D.local/src/st/patches/st-xresources-signal-reloading-20220312-6685098.diff | 165-------------------------------------------------------------------------------
D.local/src/st/st-copyout | 13-------------
D.local/src/st/st-urlhandler | 19-------------------
D.local/src/st/st.1 | 177-------------------------------------------------------------------------------
D.local/src/st/st.c | 3183-------------------------------------------------------------------------------
D.local/src/st/st.h | 134-------------------------------------------------------------------------------
D.local/src/st/st.info | 239-------------------------------------------------------------------------------
D.local/src/st/win.h | 40----------------------------------------
D.local/src/st/x.c | 2400-------------------------------------------------------------------------------
D.local/src/surf/FAQ.md | 10----------
D.local/src/surf/LICENSE | 58----------------------------------------------------------
D.local/src/surf/Makefile | 82-------------------------------------------------------------------------------
D.local/src/surf/README | 40----------------------------------------
D.local/src/surf/TODO.md | 10----------
D.local/src/surf/arg.h | 48------------------------------------------------
D.local/src/surf/common.h | 1-
D.local/src/surf/config.h | 281-------------------------------------------------------------------------------
D.local/src/surf/config.mk | 32--------------------------------
D.local/src/surf/patches/surf-2.0-externalpipe.diff | 93-------------------------------------------------------------------------------
D.local/src/surf/patches/surf-2.0-homepage.diff | 24------------------------
D.local/src/surf/patches/surf-2.1-history.diff | 68--------------------------------------------------------------------
D.local/src/surf/patches/surf-bookmarks-20170722-723ff26.diff | 42------------------------------------------
D.local/src/surf/patches/surf-clipboard-20200112-a6a8878.diff | 67-------------------------------------------------------------------
D.local/src/surf/patches/surf-git-20170323-webkit2-searchengines.diff | 56--------------------------------------------------------
D.local/src/surf/patches/surf-playexternal-20190724-b814567.diff | 54------------------------------------------------------
D.local/src/surf/surf-edit-source | 5-----
D.local/src/surf/surf-link-select | 76----------------------------------------------------------------------------
D.local/src/surf/surf-open | 19-------------------
D.local/src/surf/surf.1 | 308-------------------------------------------------------------------------------
D.local/src/surf/surf.c | 2288-------------------------------------------------------------------------------
D.local/src/surf/surf.png | 0
D.local/src/surf/webext-surf.c | 106-------------------------------------------------------------------------------
D.local/src/tabbed/LICENSE | 23-----------------------
D.local/src/tabbed/Makefile | 65-----------------------------------------------------------------
D.local/src/tabbed/README | 22----------------------
D.local/src/tabbed/TODO | 4----
D.local/src/tabbed/arg.h | 48------------------------------------------------
D.local/src/tabbed/config.h | 87-------------------------------------------------------------------------------
D.local/src/tabbed/config.mk | 33---------------------------------
D.local/src/tabbed/patches/tabbed-bar-height-0.6.diff | 24------------------------
D.local/src/tabbed/patches/tabbed-clientnumber-20160702-bc23614.diff | 23-----------------------
D.local/src/tabbed/patches/tabbed-hidetabs-20191216-b5f9ec6.diff | 105-------------------------------------------------------------------------------
D.local/src/tabbed/patches/tabbed-keyrelease-20191216-b5f9ec6.diff | 96-------------------------------------------------------------------------------
D.local/src/tabbed/patches/tabbed-xresources-20210317-dabf6a2.diff | 178-------------------------------------------------------------------------------
D.local/src/tabbed/tabbed.1 | 171-------------------------------------------------------------------------------
D.local/src/tabbed/tabbed.c | 1512-------------------------------------------------------------------------------
D.local/src/tabbed/xembed.1 | 35-----------------------------------
D.local/src/tabbed/xembed.c | 45---------------------------------------------
D.local/src/xwallpaper/.deps/xwallpaper-debug.Po | 28----------------------------
D.local/src/xwallpaper/.deps/xwallpaper-load_jpeg.Po | 139-------------------------------------------------------------------------------
D.local/src/xwallpaper/.deps/xwallpaper-load_png.Po | 141-------------------------------------------------------------------------------
D.local/src/xwallpaper/.deps/xwallpaper-load_xpm.Po | 152-------------------------------------------------------------------------------
D.local/src/xwallpaper/.deps/xwallpaper-main.Po | 136-------------------------------------------------------------------------------
D.local/src/xwallpaper/.deps/xwallpaper-options.Po | 134-------------------------------------------------------------------------------
D.local/src/xwallpaper/.deps/xwallpaper-outputs.Po | 131-------------------------------------------------------------------------------
D.local/src/xwallpaper/.deps/xwallpaper-seccomp.Po | 1-
D.local/src/xwallpaper/.deps/xwallpaper-util.Po | 23-----------------------
D.local/src/xwallpaper/LICENSE | 15---------------
D.local/src/xwallpaper/Makefile | 1092-------------------------------------------------------------------------------
D.local/src/xwallpaper/Makefile.am | 52----------------------------------------------------
D.local/src/xwallpaper/Makefile.in | 1092-------------------------------------------------------------------------------
D.local/src/xwallpaper/README.md | 54------------------------------------------------------
D.local/src/xwallpaper/_xwallpaper | 26--------------------------
D.local/src/xwallpaper/aclocal.m4 | 1494-------------------------------------------------------------------------------
D.local/src/xwallpaper/autogen.sh | 11-----------
D.local/src/xwallpaper/autom4te.cache/output.0 | 6843-------------------------------------------------------------------------------
D.local/src/xwallpaper/autom4te.cache/output.1 | 6843-------------------------------------------------------------------------------
D.local/src/xwallpaper/autom4te.cache/output.2 | 6845-------------------------------------------------------------------------------
D.local/src/xwallpaper/autom4te.cache/requests | 247-------------------------------------------------------------------------------
D.local/src/xwallpaper/autom4te.cache/traces.0 | 1229-------------------------------------------------------------------------------
D.local/src/xwallpaper/autom4te.cache/traces.1 | 524-------------------------------------------------------------------------------
D.local/src/xwallpaper/autom4te.cache/traces.2 | 524-------------------------------------------------------------------------------
D.local/src/xwallpaper/compile | 348-------------------------------------------------------------------------------
D.local/src/xwallpaper/config.h | 76----------------------------------------------------------------------------
D.local/src/xwallpaper/config.h.in | 75---------------------------------------------------------------------------
D.local/src/xwallpaper/config.log | 505-------------------------------------------------------------------------------
D.local/src/xwallpaper/config.status | 1206-------------------------------------------------------------------------------
D.local/src/xwallpaper/configure | 6844-------------------------------------------------------------------------------
D.local/src/xwallpaper/configure.ac | 159-------------------------------------------------------------------------------
D.local/src/xwallpaper/debug.c | 33---------------------------------
D.local/src/xwallpaper/depcomp | 791-------------------------------------------------------------------------------
D.local/src/xwallpaper/functions.h | 102-------------------------------------------------------------------------------
D.local/src/xwallpaper/install-sh | 541-------------------------------------------------------------------------------
D.local/src/xwallpaper/load_jpeg.c | 106-------------------------------------------------------------------------------
D.local/src/xwallpaper/load_png.c | 144-------------------------------------------------------------------------------
D.local/src/xwallpaper/load_xpm.c | 130-------------------------------------------------------------------------------
D.local/src/xwallpaper/main.c | 825-------------------------------------------------------------------------------
D.local/src/xwallpaper/missing | 215-------------------------------------------------------------------------------
D.local/src/xwallpaper/options.c | 281-------------------------------------------------------------------------------
D.local/src/xwallpaper/outputs.c | 173-------------------------------------------------------------------------------
D.local/src/xwallpaper/seccomp.c | 194-------------------------------------------------------------------------------
D.local/src/xwallpaper/stamp-h1 | 1-
D.local/src/xwallpaper/util.c | 31-------------------------------
D.local/src/xwallpaper/xwallpaper | 0
D.local/src/xwallpaper/xwallpaper-debug.o | 0
D.local/src/xwallpaper/xwallpaper-load_jpeg.o | 0
D.local/src/xwallpaper/xwallpaper-load_png.o | 0
D.local/src/xwallpaper/xwallpaper-load_xpm.o | 0
D.local/src/xwallpaper/xwallpaper-main.o | 0
D.local/src/xwallpaper/xwallpaper-options.o | 0
D.local/src/xwallpaper/xwallpaper-outputs.o | 0
D.local/src/xwallpaper/xwallpaper-util.o | 0
D.local/src/xwallpaper/xwallpaper.1 | 171-------------------------------------------------------------------------------
D.mkshrc | 32--------------------------------
MMakefile | 26++++++++++++++++++++++++--
Mconfig.mk | 2+-
Minc/configs-dirs.mk | 3+--
Minc/configs-files.mk | 16+++++++++-------
Minc/pkgs-alpine.mk | 36+++++++++++++++++++++---------------
236 files changed, 794 insertions(+), 69997 deletions(-)

diff --git a/.config/mbsync/mbsyncrc b/.config/mbsync/mbsyncrc @@ -1,9 +1,18 @@ +# Automatically create missing mailboxes, both locally and on the server. +Create Both + +# Sync the movement of messages between folders and deletions, +# add after making sure the sync works. +Expunge Both + +# Save the synchronization state files in the relevant directory. +SyncState * + IMAPAccount acct0 Host mail.mahdi.pw User me -# Pass "This is my secure password" -PassCmd "pass email" -# Use SSL +#Pass "This is my secure password" +PassCmd "pash s email" SSLType IMAPS SSLVersions TLSv1.2 AuthMechs LOGIN @@ -14,18 +23,9 @@ Account acct0 MaildirStore acct0-local Subfolders Verbatim -# The trailing "/" is important -Path ~/.local/share/mail/acct0/ +Path ~/.local/share/mail/acct0/ # The trailing "/" is important Inbox ~/.local/share/mail/acct0/Inbox Channel acct0 Far :acct0-remote: Near :acct0-local: -# Include everything -Patterns * -# Automatically create missing mailboxes, both locally and on the server -Create Both -# Sync the movement of messages between folders and deletions, add after making sure the sync works -Expunge Both -# Save the synchronization state files in the relevant directory -SyncState * diff --git a/.config/mpv/input.conf b/.config/mpv/input.conf @@ -53,6 +53,12 @@ Ctrl+d run "/bin/sh" "-c" "(choice=`printf 'Yes\nNo' | dmenu -p \"Delete \\\"${p # - Copy the name of the file to clipboard Ctrl+y run "/bin/sh" "-c" "printf '%s' \"${path}\" | xclip -selection c"; show-text "Copied ${path} to Clipboard" +# - Copy subtitle-text to clipboard +ctrl+s run "/bin/sh" "-c" "echo \"${sub-text}\" | tr '\n' ' ' | xclip -selection c" ; show-text "Copied subtitle to clipboard." + +# - Copy a word from subtitle-text to clipboard (dmenu) +ctrl+shift+s run "/bin/sh" "-c" "echo \"${sub-text}\" | tr ' ' '\n' | dmenu -i -l 20 | xclip -selection c" ; show-text "Copied word to clipboard." + # TODO: Figure this out # - Paste from clipboard to playlist Ctrl+p run "/bin/sh" "-c" "xclip -selection c -o" diff --git a/.config/mutt/mailcap b/.config/mutt/mailcap @@ -1,6 +1,6 @@ text/plain; $EDITOR %s ; text/html; openfile %s ; nametemplate=%s.html -text/html; lynx -assume_charset=%{charset} -display_charset=utf-8 -dump -width=1024 %s; nametemplate=%s.html; copiousoutput; +text/html; lynx -dump %s; nametemplate=%s.html; copiousoutput; image/*; openfile %s ; video/*; mpv --quiet %s &; copiousoutput audio/*; mpv %s ; diff --git a/.config/mutt/muttrc b/.config/mutt/muttrc @@ -6,6 +6,7 @@ macro index,pager <f3> '<sync-mailbox><enter-command>source ~/.config/mutt/work< # Personal Details set realname="Mahdi Mirzade" set from="me@mahdi.pw" +set signature="~/.config/mutt/signature" set use_from=yes set use_envelope_from=yes set reverse_name=yes @@ -16,12 +17,12 @@ set ssl_force_tls = yes # Syntax: imaps://user@domain@imap_domain:port #set folder="imaps://me@mahdi.pw@mail.mahdi.pw:993" -#set imap_pass = `pass email` +#set imap_pass = `pash s email` set folder="~/.local/share/mail/acct0" # Syntax: smtps://user@domain@smtp_domain:port set smtp_url = "smtps://me@mahdi.pw@mail.mahdi.pw:465" -set smtp_pass = `pass email` +set smtp_pass = `pash s email` # Mailboxes set spoolfile="+Inbox" @@ -34,6 +35,7 @@ mailboxes =Inbox =Drafts =Sent =Junk =Trash # Settings set mailcap_path="~/.config/mutt/mailcap" macro attach s <save-entry><bol>~/Downloads/<eol> +macro index V "!email -sn^M" "Update through mbsync" set date_format="%y/%m/%d %I:%M%p" set index_format="%2C %Z %?X?A& ? %D %-15.15F %s (%-4.4c)" set sort = 'reverse-date' diff --git a/.config/shell/aliasrc b/.config/shell/aliasrc @@ -1,36 +0,0 @@ -#!/bin/sh - -# Run some programs in sudo. -for command in mount umount sv pacman pkg updatedb su; do - alias $command="doas $command" -done; unset command - -alias startx="startx \"$XINITRC\"" -alias vim="vim -i ${XDG_DATA_HOME:-$HOME/.local/share}/viminfo" - -alias \ - ..='cd ..' \ - ...='cd ../..' \ - ....='cd ../../..' - -# Fix colorizing commands. -alias \ - ls="ls -h --color=always" \ - ip="ip --color=auto" \ - grep="grep --color=auto" - -# Lazy Aliases. -alias \ - c="clear -x" \ - e="$EDITOR" \ - g="git" \ - h="htop" \ - l="ls" \ - p="pacman" \ - v="$EDITOR" \ - x="exit" - -# Suckless now with tabbed. -#alias \ -# surf="surf-open" \ -# st="tabbed -c -r 2 st -w ''" diff --git a/.config/shell/inputrc b/.config/shell/inputrc @@ -1,15 +0,0 @@ -set editing-mode vi - -set show-mode-in-prompt on -set vi-ins-mode-string \1\e[6 q\2 -set vi-cmd-mode-string \1\e[2 q\2 - -set keymap vi-command -# these are for vi-command mode -Control-l: clear-screen -Control-a: beginning-of-line - -set keymap vi-insert -# these are for vi-insert mode -Control-l: clear-screen -Control-a: beginning-of-line diff --git a/.config/shell/profile b/.config/shell/profile @@ -1,57 +0,0 @@ -#!/bin/sh -# Environmental variables are set here. (Runs on login) - -# Adds `~/.local/bin/*` to $PATH -#export PATH="$PATH:${$(find ~/.local/bin -type d -printf %p:)%%:}" -# Adds `~/.local/bin` to $PATH -export PATH="$PATH:$HOME/.local/bin" - -# Default Programs -export BROWSER="surf-open" -export EDITOR="vi" -export TERMINAL="st" - -# XDG_CONFIG -export XDG_CACHE_HOME="$HOME/.cache" -export XDG_CONFIG_HOME="$HOME/.config" -export XDG_DATA_HOME="$HOME/.local/share" -export XDG_STATE_HOME="$HOME/.local/state" -export XDG_RUNTIME_DIR="$HOME/.local/run" - -[ -d "$XDG_CACHE_HOME" ] || mkdir -p "$XDG_CACHE_HOME" -[ -d "$XDG_CONFIG_HOME" ] || mkdir -p "$XDG_CONFIG_HOME" -[ -d "$XDG_DATA_HOME" ] || mkdir -p "$XDG_DATA_HOME" -[ -d "$XDG_STATE_HOME" ] || mkdir -p "$XDG_STATE_HOME" -[ -d "$XDG_RUNTIME_DIR" ] || mkdir -p "$XDG_RUNTIME_DIR" - -# Use $XDG_CONFIG_HOME for disrespectful programs -export GNUPGHOME="${XDG_DATA_HOME:-$HOME/.local/share}/gnupg" -export GTK2_RC_FILES="${XDG_CONFIG_HOME:-$HOME/.config}/gtk-2.0/gtkrc-2.0" -export HISTFILE="${XDG_DATA_HOME:-$HOME/.local/share}/history.$(basename "$(echo "${0:-$SHELL}" | sed 's|-||')")" -export INPUTRC="${XDG_CONFIG_HOME:-$HOME/.config}/shell/inputrc" -export MBSYNCRC="${XDG_CONFIG_HOME:-$HOME/.config}/mbsync/mbsyncrc" -export PASSWORD_STORE_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/password-store" -export WGETRC="${XDG_CONFIG_HOME:-$HOME/.config}/wget/wgetrc" -export LESSHISTFILE="${XDG_DATA_HOME:-$HOME/.local/share}/lesshst" -export XAUTHORITY="${XDG_RUNTIME_DIR}/Xauthority" -export XINITRC="${XDG_CONFIG_HOME:-$HOME/.config}/x11/xinitrc" - -export DOAS_ASKPASS="dmenu -P -p Password:" -export QT_STYLE_OVERRIDE="kvantum" - -if [ "$(tty)" = "/dev/tty1" ] || [ "$(tty)" = "/dev/ttyv0" ]; then - pidof -s Xorg >/dev/null 2>&1 || exec startx "$XINITRC" -fi - -## Start graphics if 'libxft-bgra' was installed and already not running. -#if pacman -Q libxft-bgra >/dev/null 2>&1; then -# [ "$(tty)" = "/dev/tty1" ] && ! pidof -s Xorg >/dev/null 2>&1 && exec startx "$XINITRC" -#else -# printf "\033[31mIMPORTANT\033[0m: Note that \033[32m\`libxft-bgra\`\033[0m must be installed for my build of dwm, st, ...\n" -# printf "Please run:\n" -# printf "\033[32m\tgit clone https://mahdi.pw/git/libxft.git\n\033[0m" -# printf "\033[32m\tcd libxft\n\033[0m" -# printf "\033[32m\tmakepkg -si\n\033[0m" -# printf "and replace 'libxft' (if not replaced by pacman).\n" -# printf "Afterwards enter the graphical server using: \033[34mstartx \"$XINITRC\"\033[0m\n" -#fi diff --git a/.config/surf/styles/default.css b/.config/surf/styles/default.css @@ -1,25 +1,29 @@ /*html, img { -webkit-filter: invert(1) hue-rotate(180deg); }*/ *, *::before, *::after { background-image: none !important; } -/*a,button,col,div,textarea,body,input,form,td,tr,th,p,span,article,svg,header,footer,details,summary { */ -html,head,body,header,footer,a,p,h1,h2,h3,h4,h5,h6,h7,div,ul,li,dl,dt,q,pre,code,blockquote,i,u,input,button,tag,table,thead,tbody,tfoot,td,tr,th,span,article,details,summary,textarea,div,a,svg,label,aside,main { -/*,*, *::before, *::after { */ - background-color: #1E2127 !important; - border-color: #5C6370 !important; - color: #ABB2BF !important; +/*a,button,col,div,textarea,body,input,form,td,tr,th,p,span, +article,svg,header,footer,details,summary { */ +/*html,head,body,header,footer,a,p,h1,h2,h3,h4,h5,h6,h7,div, +ul,li,dl,dt,q,pre,code,blockquote,i,u,input,button,tag,table, +thead,tbody,tfoot,td,tr,th,span,article,details,summary,textarea, +div,a,svg,label,aside,main {*/ +*, *::before, *::after { + background-color: #282a36 !important; + border-color: #4D4D4D !important; + color: #BFBFBF !important; } blockquote, pre, code, code>* { - background-color: #1E2127 !important; - border-color: #5C6370 !important; - color: #ABB2BF !important; + background-color: #282a36 !important; + border-color: #4D4D4D !important; + color: #BFBFBF !important; padding: 5px; font-family: monospace; } -a:link { color: #56B6C2 !important; } -a:hover { color: #C678DD !important; } -a:visited { color: #C678DD !important; } -input:hover { color: #56B6C2 !important; } -button:hover { color: #56B6C2 !important; } +a:link { color: #8BE9FD !important; } +a:hover { color: #FF79C6 !important; } +a:visited { color: #FF92D0 !important; } +input:hover { color: #9AEDFE !important; } +button:hover { color: #9AEDFE !important; } img { opacity: .75; } img:hover { opacity: 1; } diff --git a/.config/surf/styles/default.css.in b/.config/surf/styles/default.css.in @@ -1,8 +1,12 @@ /*html, img { -webkit-filter: invert(1) hue-rotate(180deg); }*/ *, *::before, *::after { background-image: none !important; } -/*a,button,col,div,textarea,body,input,form,td,tr,th,p,span,article,svg,header,footer,details,summary { */ -html,head,body,header,footer,a,p,h1,h2,h3,h4,h5,h6,h7,div,ul,li,dl,dt,q,pre,code,blockquote,i,u,input,button,tag,table,thead,tbody,tfoot,td,tr,th,span,article,details,summary,textarea,div,a,svg,label,aside,main { -/*,*, *::before, *::after { */ +/*a,button,col,div,textarea,body,input,form,td,tr,th,p,span, +article,svg,header,footer,details,summary { */ +/*html,head,body,header,footer,a,p,h1,h2,h3,h4,h5,h6,h7,div, +ul,li,dl,dt,q,pre,code,blockquote,i,u,input,button,tag,table, +thead,tbody,tfoot,td,tr,th,span,article,details,summary,textarea, +div,a,svg,label,aside,main {*/ +*, *::before, *::after { background-color: %cl0% !important; border-color: %cl8% !important; color: %cl7% !important; diff --git a/.config/vis/visrc.lua b/.config/vis/visrc.lua @@ -1,50 +1,53 @@ require('vis') vis.events.subscribe(vis.events.INIT, function() - -- Your global configuration options + -- Your global configuration options end) vis.events.subscribe(vis.events.WIN_OPEN, function(win) - -- Your per window configuration options e.g. - vis:command('set number') - --vis:command('set relativenumbers') + -- Your per window configuration options e.g. + vis:command('set number') + vis:command('set colorcolumn 80') + --vis:command('set relativenumbers') --vis:command('set expandtab') vis:command('set tabwidth 4') vis:command('set escdelay 0') vis:command('set show-eof off') - vis:command('set theme dark-16') - vis:command('set autoindent on') + vis:command('set theme my-theme') + vis:command('set autoindent on') end) -- Backspace removes 4 spaces if need be vis:map(vis.modes.INSERT, '<Backspace>', function() - local tabwidth = 4 - local single_selection = false - for selection in vis.win:selections_iterator() do - if single_selection then - single_selection = false - break - end - single_selection = true - end - - local to_stop = (vis.win.selection.col - 1) % tabwidth - if to_stop == 0 then - to_stop = tabwidth - end - - if single_selection and to_stop > 1 and vis.win.file:content(vis.win.selection.pos - to_stop, to_stop) == string.rep(' ', to_stop) then - vis:feedkeys(string.rep('<vis-delete-char-prev>', to_stop)) - else - vis:feedkeys('<vis-delete-char-prev>') - end -end) + local tabwidth = 4 + local single_selection = false + for selection in vis.win:selections_iterator() do + if single_selection then + single_selection = false + break + end + single_selection = true + end + + local to_stop = (vis.win.selection.col - 1) % tabwidth + if to_stop == 0 then + to_stop = tabwidth + end + + if single_selection and to_stop > 1 and + vis.win.file:content(vis.win.selection.pos - to_stop, to_stop) == + string.rep(' ', to_stop) then + vis:feedkeys(string.rep('<vis-delete-char-prev>', to_stop)) + else + vis:feedkeys('<vis-delete-char-prev>') + end +end, "Backspace removes 4 spaces if need be") -- Strip trailing spaces vis:command_register("sts", function(argv, force, win, selection, range) - local lines = win.file.lines - for index=1, #lines do - lines[index] = lines[index]:gsub("%s+$", "") - end - return true + local lines = win.file.lines + for index=1, #lines do + lines[index] = lines[index]:gsub("%s+$", "") + end + return true end, "Strip line trailing spaces") diff --git a/.config/x11/colors b/.config/x11/colors @@ -1,31 +1,20 @@ -! Custom -! Original theme https://github.com/nathanbuchar/atom-one-dark-terminal -*.foreground: #ABB2BF -*.background: #1E2127 -*.cursorColor: #5C6370 -*.highlightColor:#3A3F4B - -! Negro y gris -*.color0: #1E2127 -*.color8: #5C6370 -! Rojos -*.color1: #E06C75 -*.color9: #E06C75 -! Verde -*.color2: #98C379 -*.color10: #98C379 -! Amarillo -*.color3: #D19A66 -*.color11: #D19A66 -! Azul -*.color4: #61AFEF -*.color12: #61AFEF -! Magenta -*.color5: #C678DD -*.color13: #C678DD -! Cyan -*.color6: #56B6C2 -*.color14: #56B6C2 -! Blanco -*.color7: #ABB2BF -*.color15: #FFFFFF +! Dracula Xresources palette +*.foreground: #f8f8f2 +*.background: #282a36 +*.cursorColor: #6272a4 +*.color0: #282a36 +*.color8: #4D4D4D +*.color1: #FF5555 +*.color9: #FF6E67 +*.color2: #50FA7B +*.color10: #5AF78E +*.color3: #F1FA8C +*.color11: #F4F99D +*.color4: #BD93F9 +*.color12: #CAA9FA +*.color5: #FF79C6 +*.color13: #FF92D0 +*.color6: #8BE9FD +*.color14: #9AEDFE +*.color7: #BFBFBF +*.color15: #E6E6E6 diff --git a/.config/x11/themes/solarized-dark b/.config/x11/themes/solarized-dark @@ -1,36 +1,53 @@ -*.foreground: #708284 -*.background: #001e27 -*.cursorColor: #708284 -! -! Black -*.color0: #002831 -*.color8: #001e27 -! -! Red -*.color1: #d11c24 -*.color9: #bd3613 -! -! Green -*.color2: #738a05 -*.color10: #475b62 -! -! Yellow -*.color3: #a57706 -*.color11: #536870 -! -! Blue -*.color4: #2176c7 -*.color12: #708284 -! -! Magenta -*.color5: #c61c6f -*.color13: #5956ba -! -! Cyan -*.color6: #259286 -*.color14: #819090 -! -! White -*.color7: #eae3cb -*.color15: #fcf4dc +#define S_base03 #002b36 +#define S_base02 #073642 +#define S_base01 #586e75 +#define S_base00 #657b83 +#define S_base0 #839496 +#define S_base1 #93a1a1 +#define S_base2 #eee8d5 +#define S_base3 #fdf6e3 +*.background: S_base03 +*.foreground: S_base0 +*.cursorColor: S_base1 + +#define S_yellow #b58900 +#define S_orange #cb4b16 +#define S_red #dc322f +#define S_magenta #d33682 +#define S_violet #6c71c4 +#define S_blue #268bd2 +#define S_cyan #2aa198 +#define S_green #859900 + +! black dark/light +*.color0: S_base03 +*.color8: S_base02 + +! red dark/light +*.color1: S_red +*.color9: S_orange + +! green dark/light +*.color2: S_green +*.color10: S_base01 + +! yellow dark/light +*.color3: S_yellow +*.color11: S_base00 + +! blue dark/light +*.color4: S_blue +*.color12: S_base0 + +! magenta dark/light +*.color5: S_magenta +*.color13: S_violet + +! cyan dark/light +*.color6: S_cyan +*.color14: S_base1 + +! white dark/light +*.color7: S_base2 +*.color15: S_base3 diff --git a/.config/x11/xinitrc b/.config/x11/xinitrc @@ -6,17 +6,12 @@ UMM="${XDG_CONFIG_HOME:-$HOME/.config}"/x11/xmodmap [ -f "$UMM" ] && xmodmap "$UMM" # Autostart: -#setsid xsetroot -cursor_name left_ptr -#setsid xautolock -time 10 -locker slock -[ -f "$HOME/.cache/theme" ] || theme-sel -#pidof "dunst" || setsid "dunst" -pidof "bg-gen" || setsid "bg-gen" -pidof "dwm-bar" || setsid "dwm-bar" -pidof "pipewire" || setsid "pipewire" -pidof "pipewire-alsa" || setsid "pipewire-alsa" -pidof "pipewire-jack" || setsid "pipewire-jack" -pidof "pipewire-pulse" || setsid "pipewire-pulse" -pidof "pipewire-media-session" || setsid "pipewire-media-session" +pidof "theme-sel" || theme-sel -x +pidof "bg-gen" || bg-gen & +pidof "dwm-bar" || dwm-bar & +pidof "pipewire" || pipewire & +xset -dpms # Disables Energy Star features +xset s off # Disables screen saver # Monitors: i=0 @@ -36,11 +31,10 @@ done setxkbmap -layout us,ir setxkbmap -option 'grp:caps_toggle' -# Keyboard - Fix for my laptop's broken keyboard: +# Keyboard - Bind `Alt_L` to `p` for my laptop's broken keyboard: xmodmap -e "clear mod1" xmodmap -e "keycode 108 = p P Arabic_hah bracketleft" xmodmap -e "add mod1 = Alt_L Meta_L" # Add -f after startx to experience dwm in floating mode. ssh-agent dwm "$@" -#exec dwm "$@" diff --git a/.config/yt-dlp/config b/.config/yt-dlp/config @@ -14,4 +14,4 @@ --embed-subs # Cookies are good ---cookies ~/.local/share/yt-cookies.txt +#--cookies ~/.local/share/yt-cookies.txt diff --git a/.config/zathura/zathurarc b/.config/zathura/zathurarc @@ -11,31 +11,31 @@ set adjust-open width # Adjust to when opening file map b toggle_statusbar # Theme -set default-bg "#1E2127" -set default-fg "#ABB2BF" -set statusbar-bg "#1E2127" -set statusbar-fg "#ABB2BF" -set inputbar-bg "#1E2127" -set inputbar-fg "#56B6C2" -set completion-bg "#1E2127" -set completion-fg "#ABB2BF" -set completion-group-bg "#1E2127" -set completion-group-fg "#ABB2BF" -set completion-highlight-bg "#5C6370" -set completion-highlight-fg "#ABB2BF" -set notification-bg "#5C6370" -set notification-fg "#FFFFFF" -set notification-error-bg "#E06C75" -set notification-error-fg "#FFFFFF" -set notification-warning-bg "#D19A66" -set notification-warning-fg "#1E2127" -set highlight-color "#56B6C2" -set highlight-active-color "#56B6C2" -set index-bg "#1E2127" -set index-fg "#ABB2BF" -set index-active-bg "#5C6370" -set index-active-fg "#ABB2BF" -set recolor-darkcolor "#ABB2BF" -set recolor-lightcolor "#1E2127" -set render-loading-bg "#1E2127" -set render-loading-fg "#ABB2BF" +set default-bg "#282a36" +set default-fg "#f8f8f2" +set statusbar-bg "#282a36" +set statusbar-fg "#f8f8f2" +set inputbar-bg "#282a36" +set inputbar-fg "#8BE9FD" +set completion-bg "#282a36" +set completion-fg "#f8f8f2" +set completion-group-bg "#282a36" +set completion-group-fg "#f8f8f2" +set completion-highlight-bg "#4D4D4D" +set completion-highlight-fg "#f8f8f2" +set notification-bg "#4D4D4D" +set notification-fg "#E6E6E6" +set notification-error-bg "#FF6E67" +set notification-error-fg "#E6E6E6" +set notification-warning-bg "#F4F99D" +set notification-warning-fg "#282a36" +set highlight-color "#9AEDFE" +set highlight-active-color "#8BE9FD" +set index-bg "#282a36" +set index-fg "#f8f8f2" +set index-active-bg "#4D4D4D" +set index-active-fg "#f8f8f2" +set recolor-darkcolor "#f8f8f2" +set recolor-lightcolor "#282a36" +set render-loading-bg "#282a36" +set render-loading-fg "#f8f8f2" diff --git a/.local/bin/bg-gen b/.local/bin/bg-gen @@ -11,7 +11,6 @@ if [ ! -f "$IMG" ]; then RES="683x384" #RES="1366x768" #TAGS="xc: -attenuate 0.3 +noise Random" - #TAGS="xc: -attenuate 0.3 +noise Random" #TAGS="xc: -attenuate 0.3 +noise Random -paint 10" TAGS="plasma:" magick -size "$RES" $TAGS \ diff --git a/.local/bin/bg-set b/.local/bin/bg-set @@ -41,13 +41,15 @@ image_preview() { } if [ "$SET_BG_SELECT" ]; then - cd "$WLPS" + cd "$WLPS" || exit if [ "$#" = 0 ]; then trap stop_ueberzug EXIT QUIT INT TERM start_ueberzug - OUTPUT="$(find -type f -printf '%P\n' | sort | fzf -i -e \ - --layout=reverse --border=sharp --info=inline --preview "sh $0 {}" \ - --preview-window "right:50%:noborder:wrap" --bind "µ:toggle-preview+toggle-preview")" + OUTPUT=$(find . -type f -printf '%P\n' | sort \ + | fzf -i -e --layout=reverse --border=sharp \ + --info=inline --preview "sh $0 {}" \ + --preview-window "right:50%:noborder:wrap" \ + --bind "µ:toggle-preview+toggle-preview") if [ "$OUTPUT" ]; then stop_ueberzug bg_set "$WLPS/$OUTPUT" diff --git a/.local/bin/bright b/.local/bin/bright @@ -1,36 +1,19 @@ #!/bin/sh # Notes for linux users: -# Add backlight rules to change your card's file permissions to the group `video` +# Add backlight rule to change your card's file permissions +# to your user, replace [USER] with your user & [CARD] with +# your brightness card. # /etc/udev/rules.d/backlight.rules: # ---------------------------------- -# RUN+="/bin/chgrp video /sys/class/backlight/amdgpu_bl0/brightness" +# RUN+="/bin/chown [USER] /sys/class/backlight/[CARD]/brightness" BRIGHTNESS_ACT="get" -BRIGHTNESS_STEPS="10" +BRIGHTNESS_STEPS="5" +BRIGHTNESS_NOTIF=0 -KERNEL=$(uname) - -case "$KERNEL" in - Linux*) - BRIGHTNESS_CARD=$(ls /sys/class/backlight | head -n 1) - BRIGHTNESS_CARD=/sys/class/backlight/$BRIGHTNESS_CARD - BRIGHTNESS_MAX=$(cat "${BRIGHTNESS_CARD}/max_brightness") - BRIGHTNESS=$(cat "${BRIGHTNESS_CARD}/brightness") - BRIGHTNESS=$((BRIGHTNESS*100/BRIGHTNESS_MAX)) - BRIGHTNESS=${BRIGHTNESS%.*} - ;; - FreeBSD*) - BRIGHTNESS_MAX=100 - BRIGHTNESS=$(backlight | cut -d ' ' -f 2) - ;; - OpenBSD*) - BRIGHTNESS_MAX=100 - BRIGHTNESS=$(apm -l) - ;; -esac - -while getopts ':gidos:c:' flag; do +while getopts ':ngidos:c:' flag; do case "${flag}" in + n) BRIGHTNESS_NOTIF=1 ;; g) BRIGHTNESS_ACT="get" ;; i) BRIGHTNESS_ACT="inc" ;; d) BRIGHTNESS_ACT="dec" ;; @@ -48,50 +31,78 @@ while getopts ':gidos:c:' flag; do esac done -case "$BRIGHTNESS_ACT" in - get) - pkill -SIGUSR1 merbe - merbe "$BRIGHTNESS_ICON $BRIGHTNESS" & - exit - ;; - inc) - BRIGHTNESS_NEW="$((BRIGHTNESS+BRIGHTNESS_STEPS))" - ;; - dec) - BRIGHTNESS_NEW="$((BRIGHTNESS-BRIGHTNESS_STEPS))" - ;; - opt) - TMPFILE=$(mktemp /tmp/backlight-optimal-XXXXXXX.jpg) - ffmpeg -y -loglevel quiet -f v4l2 -i /dev/video0 -frames:v 1 -f image2 "$TMPFILE" - AVG=$(convert "$TMPFILE" -format "%[mean]" info:) - rm "$TMPFILE" - BRIGHTNESS_NEW=$(printf '%s' "$AVG" | awk '{print int($1/65535*100+30)}') - ;; -esac - -BRIGHTNESS_NEW=$((BRIGHTNESS_NEW * BRIGHTNESS_MAX / 100)) -[ "$BRIGHTNESS_NEW" -gt "$BRIGHTNESS_MAX" ] && BRIGHTNESS_NEW=$BRIGHTNESS_MAX -[ "$BRIGHTNESS_NEW" -lt "1" ] && BRIGHTNESS_NEW=1 +KERNEL=$(uname) case "$KERNEL" in Linux*) - echo "$BRIGHTNESS_NEW" > "${BRIGHTNESS_CARD}/brightness" + BRIGHTNESS_CARD=$(find /sys/class/backlight -depth | head -n 1) + BRIGHTNESS_MAX=$(cat "${BRIGHTNESS_CARD}/max_brightness") + BRIGHTNESS=$(cat "${BRIGHTNESS_CARD}/brightness") + BRIGHTNESS=$((BRIGHTNESS*100/BRIGHTNESS_MAX)) + BRIGHTNESS=${BRIGHTNESS%.*} ;; FreeBSD*) - backlight "$BRIGHTNESS_NEW" + BRIGHTNESS_MAX=100 + BRIGHTNESS=$(backlight | cut -d ' ' -f 2) ;; OpenBSD*) - apm -s "$BRIGHTNESS_NEW" + BRIGHTNESS_MAX=100 + BRIGHTNESS=$(apm -l) ;; esac -BRIGHTNESS="$((BRIGHTNESS_NEW*100/BRIGHTNESS_MAX))" -if [ "$BRIGHTNESS" -le 25 ]; then - BRIGHTNESS_ICON="" -elif [ "$BRIGHTNESS" -le 60 ]; then - BRIGHTNESS_ICON="" -else - BRIGHTNESS_ICON="" -fi -pkill -SIGUSR1 merbe -merbe "$BRIGHTNESS_ICON $BRIGHTNESS" & +change_bright() { + BRIGHTNESS_NEW=$1 + BRIGHTNESS_NEW=$((BRIGHTNESS_NEW * BRIGHTNESS_MAX / 100)) + [ "$BRIGHTNESS_NEW" -gt "$BRIGHTNESS_MAX" ] && BRIGHTNESS_NEW=$BRIGHTNESS_MAX + [ "$BRIGHTNESS_NEW" -lt "1" ] && BRIGHTNESS_NEW=1 + + case "$KERNEL" in + Linux*) + echo "$BRIGHTNESS_NEW" > "${BRIGHTNESS_CARD}/brightness" + ;; + FreeBSD*) + backlight "$BRIGHTNESS_NEW" + ;; + OpenBSD*) + apm -s "$BRIGHTNESS_NEW" + ;; + esac +} + +main() { + case "$BRIGHTNESS_ACT" in + get) + echo "$BRIGHTNESS" + ;; + inc) + BRIGHTNESS_NEW=$((BRIGHTNESS+BRIGHTNESS_STEPS)) + ;; + dec) + BRIGHTNESS_NEW=$((BRIGHTNESS-BRIGHTNESS_STEPS)) + ;; + opt) + TMPFILE=$(mktemp /tmp/backlight-optimal-XXXXXXX.jpg) + ffmpeg -y -loglevel quiet -f v4l2 -i /dev/video0 -frames:v 1 -f image2 "$TMPFILE" + AVG=$(convert "$TMPFILE" -format "%[mean]" info:) + rm "$TMPFILE" + BRIGHTNESS_NEW=$(printf '%s' "$AVG" | awk '{print int($1/65535*100+30)}') + ;; + esac + + [ "$BRIGHTNESS_ACT" = "get" ] || change_bright "$BRIGHTNESS_NEW" + + if [ "$BRIGHTNESS_NOTIF" -eq 1 ]; then + BRIGHTNESS=$((BRIGHTNESS_NEW*100/BRIGHTNESS_MAX)) + if [ "$BRIGHTNESS" -le 25 ]; then + BRIGHTNESS_ICON="" + elif [ "$BRIGHTNESS" -le 60 ]; then + BRIGHTNESS_ICON="" + else + BRIGHTNESS_ICON="" + fi + notify "$BRIGHTNESS_ICON $BRIGHTNESS" + fi +} + +main diff --git a/.local/bin/dmenu-archwiki b/.local/bin/dmenu-archwiki @@ -2,9 +2,9 @@ # Install: arch-wiki-doc wikipath="/usr/share/doc/arch-wiki/html/en" wikimenu () { - for file in $wikipath/*; do - [ -f $file ] && printf '%s\n' "${file##*/}" - done + for file in "$wikipath"/*; do + [ -f "$file" ] && printf '%s\n' "${file##*/}" + done } wikipage="$(wikimenu | dmenu -i -l 20 -p "Choose Wiki:")" [ -z "$wikipage" ] || "${BROWSER:-xdg-open}" "$wikipath/$wikipage" diff --git a/.local/bin/dmenu-emoji b/.local/bin/dmenu-emoji @@ -1,17 +1,17 @@ #!/bin/sh active_window="$(xdotool getactivewindow)" -emoji=$(sed '0,/^__DATA__$/d' "$(which "$0")" | sed -e 's/\ufe0f//g' | dmenu -i -l 20 | sed 's/ .*//') -xdotool windowactivate "$active_window" +emoji=$(sed '/^__DATA__$/,$!d;/^__DATA__$/d;s/\ufe0f//g' "$(which "$0")" | dmenu -i -l 20 | sed 's/ .*//') [ "$emoji" ] || exit +xdotool windowactivate "$active_window" case "$1" in - [Cc]|[Cc][Ll][Ii][Pp][Bb][Oo][Aa][Rr][Dd]) - echo "$emoji" | xclip -selection clipboard - merbe "Emoji" "Copied $emoji to clipboard!" - ;; - *) - xdotool type -delay 100 "$emoji" - ;; + [Cc]|[Cc][Ll][Ii][Pp][Bb][Oo][Aa][Rr][Dd]) + echo "$emoji" | xclip -selection clipboard + notify "Emoji" "Copied $emoji to clipboard!" + ;; + *) + xdotool type -delay 100 "$emoji" + ;; esac exit $? diff --git a/.local/bin/dmenu-fix-sheet b/.local/bin/dmenu-fix-sheet @@ -1,21 +1,21 @@ #!/bin/sh -# Some cheatsheet for some fast fixes wouldn't be bad. -CHOICE="$(printf '%s\n' "background noise in pulse" \ - | dmenu -p "Get Help For Some Quick Fix:" -l 20)" +# Some cheatsheet for some fast fixes wouldn't be bad. +CHOICE="$(printf '%s\n' "background noise in pulse" \ + | dmenu -p "Get Help For Some Quick Fix:" -l 20)" case "$CHOICE" in - "background noise in pulse") - printf '# My fix for background noise in pulse.\n' - printf '#\n' - printf '# 1. Run privilaged:\n' - printf '# doas ./fix.mic.sh\n' - printf '# 2. Restart Audio Server:\n' - printf '# pulseaudio -k\n' - printf '#\n' - printf 'doas cp /etc/pulse/default.pa /etc/pulse/default.pa.bak\n' - printf 'doas cat << EOT >> /etc/pulse/default.pa\n' - printf 'load-module module-echo-cancel source_name=noechosource sink_name=noechosink\n' - printf 'set-default-source noechosource\n' - printf 'set-default-sink noechosink\n' - printf 'EOT\n' - ;; + "background noise in pulse") + printf '# My fix for background noise in pulse.\n' + printf '#\n' + printf '# 1. Run privilaged:\n' + printf '# doas ./fix.mic.sh\n' + printf '# 2. Restart Audio Server:\n' + printf '# pulseaudio -k\n' + printf '#\n' + printf 'doas cp /etc/pulse/default.pa /etc/pulse/default.pa.bak\n' + printf 'doas cat << EOT >> /etc/pulse/default.pa\n' + printf 'load-module module-echo-cancel source_name=noechosource sink_name=noechosink\n' + printf 'set-default-source noechosource\n' + printf 'set-default-sink noechosink\n' + printf 'EOT\n' + ;; esac diff --git a/.local/bin/dmenu-man b/.local/bin/dmenu-man @@ -1,3 +1,3 @@ #!/bin/sh -CHOICE="$(man -k . | dmenu -p 'Choose Manual:' -l 20 | awk '{print $1"."$2}' | sed 's/(//;s/)//')" -[ "$CHOICE" ] && man -Tpdf "$CHOICE" | zathura - +CHOICE=${1:-$(man -k . | dmenu -p 'Choose Manual:' -l 20 | awk '{print $1"."$2}' | sed 's/(//;s/)//')} +[ "$CHOICE" ] && "$TERMINAL" -e man "$CHOICE" diff --git a/.local/bin/dmenu-power b/.local/bin/dmenu-power @@ -1,8 +1,9 @@ #!/bin/sh ask() { - prompt="Do you really want to $1?" - answer="$(printf 'Yes\nNo' | dmenu -i -p "$prompt")" - [ "$answer" = "Yes" ] && doas-askpass "$2" + doas-askpass "$2" + #prompt="Do you really want to $1?" + #answer="$(printf 'Yes\nNo' | dmenu -i -p "$prompt")" + #[ "$answer" = "Yes" ] && doas-askpass "$2" } btn_power="📴 Poweroff" @@ -16,5 +17,5 @@ case "$CHOICE" in #"$btn_logout") ask "logout from \"$(logname)\"" "pkill -KILL -u \"$(logname)\"" ;; "$btn_logout") ask "logout from \"$(logname)\"" "kill -9 -1" ;; "$btn_reboot") ask "reboot this machine" "reboot" ;; - "$btn_power") ask "this computer to shutdown" "shutdown now";; + "$btn_power") ask "this computer to shutdown" "poweroff";; esac diff --git a/.local/bin/doas-askpass b/.local/bin/doas-askpass @@ -1,4 +1,4 @@ -#!/usr/local/bin/expect -- +#!/usr/bin/expect -- # askpass implementation for doas # /home/mahdi/.local/bin/doas-askpass diff --git a/.local/bin/dwm-bar b/.local/bin/dwm-bar @@ -4,48 +4,129 @@ # ------------------ # # ----- Config ----- # # ------------------ # - -# Colorful status: change to 1 if you want your modules colored. (Xresources) -COLORFUL=0 - -# Colorful background: Change to 1 if you want your modules' -# backgrounds to be set to your Xresources background colors, -# But darkened for each module to a certain number from left to right. -# Note: *REQUIRES COLORFUL=1* -COLORFUL_BACKGROUND=0 +# Cache directory +CACHE_DIR=${XDG_CACHE_HOME:-$HOME/.cache}/dwm-bar +[ -d "$CACHE_DIR" ] || mkdir -p "$CACHE_DIR" # The location for weather module, the necessary information is parsed from: # v2d.wttr.in/${WEATHER_LOC} WEATHER_LOC="Babol" -# The keyboard layouts you want to use in "Keyboard" module. -# You can modify your own layouts, -# *:%; -# Where: -# * -> The order of the layout you've set from setxkbmap (starting from 0) -# % -> The name you want the module to return for the layout. -KBD_LAYOUTS="0:English;1:Persian;" +# List of modules +full_mods="Weather PublicIP PrivateIP Keyboard Battery Brightness Volume CPUtemp Memory Uptime DTime" +opts_mods=" +Volume Memory DTime +Volume CPUtemp Uptime DTime +Keyboard Battery Brightness DTime +Weather Battery Brightness DTime +Weather Keyboard Battery Brightness DTime +Weather PublicIP PrivateIP Uptime DTime +" + +# Store Kernel's Name (Linux/FreeBSD/OpenBSD) +KERNEL=$(uname -s) + +case "$KERNEL" in + Linux*) + TEMPERATURE_FILES=" + /sys/class/thermal/thermal_zone0/temp + /sys/class/thermal/thermal_zone1/temp + /sys/class/thermal/thermal_zone2/temp + /sys/class/hwmon/hwmon0/temp1_input + /sys/class/hwmon/hwmon1/temp1_input + /sys/class/hwmon/hwmon2/temp1_input + /sys/class/hwmon/hwmon0/device/temp1_input + /sys/class/hwmon/hwmon1/device/temp1_input + /sys/class/hwmon/hwmon2/device/temp1_input + null + " + + for file in $TEMPERATURE_FILES; do + TEMP_FILE=$file + [ -f "$TEMP_FILE" ] && break + done + + [ "$TEMP_FILE" = "null" ] && unset TEMP_FILE + ;; +esac -KERNEL=$(uname) # ------------------ # # ---- Modules ----- # # ------------------ # Weather(){ - find "$HOME/.cache/weather" -mmin +59 -delete - if [ ! -f "$HOME/.cache/weather" ] || [ -z "$(cat "$HOME/.cache/weather" >/dev/null 2>&1)" ] ; then - weather=$(curl -s "v2d.wttr.in/${WEATHER_LOC}" \ - | sed "/Weather:/!d;s/Weather://;s/,//g;s/+//g;s/°C.*//;s/.*m//;s/ //;s/ //;s/ //") - [ "$weather" ] && echo "${weather}°C" > "$HOME/.cache/weather" + weather_file="$CACHE_DIR/.weather" + weather_file_last=$(stat -c%Y "$weather_file") + if [ "$(date +%s)" -ge $((weather_file_last+3600)) ]; then + for interface in $(find /sys/class/net -depth | \ + sed '/\/lo$/d;/\/net$/d'); do + if [ "$(cat "$interface" 2>/dev/null)" -eq 1 ]; then + rm "$weather_file" + break + fi + done fi - weather=$(cat "$HOME/.cache/weather") - printf "%s" "$weather" + weather=$(cat "$weather_file" 2>/dev/null) + + if [ ! "$weather" ]; then + weather=$(curl -s "v2d.wttr.in/${WEATHER_LOC}" | \ + sed "/Weather:/!d;s/Weather://;s/,//g; + s/+//g;s/°C.*//;s/.*m//;s/ //;s/ //;s/ //") + weather="${weather}°C" + echo "$weather" > "$weather_file" + fi + + [ "$weather" ] && printf "%s" "${weather}" +} + +PublicIP(){ + publicip_file="$CACHE_DIR/.publicip" + publicip_last=$(stat -c%Y "$publicip_file") + if [ "$(date +%s)" -ge $((publicip_last+300)) ]; then + for interface in $(find /sys/class/net -depth | \ + sed '/\/lo$/d;/\/net$/d'); do + if [ "$(cat "$interface" 2>/dev/null)" -eq 1 ]; then + rm "$publicip_file" + break + fi + done + fi + PUBLIC_IP=$(cat "$publicip_file" 2>/dev/null) + + if [ ! "$PUBLIC_IP" ]; then + RESOLVERS='resolver1.opendns.com resolver2.opendns.com resolver3.opendns.com resolver4.opendns.com' + for resolver in $RESOLVERS ; do + PUBLIC_IP=$(host myip.opendns.com "$resolver" | \ + grep "myip.opendns.com has" | awk '{print $4}') + [ -n "$PUBLIC_IP" ] && break + done + echo "$PUBLIC_IP" > "$publicip_file" + fi + + [ "$PUBLIC_IP" ] && printf " %s" "$PUBLIC_IP" +} + +PrivateIP(){ + case "$KERNEL" in + Darwin*|FreeBSD*|OpenBSD*) + PRIVATE_IP=$(ifconfig | grep "inet " | \ + grep -Fv 127.0.0.1 | awk '{print $2}') + ;; + Linux*) + PRIVATE_IP=$(ip a | sed '/inet.*scope global/!d' | \ + grep -o '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*' | sed -n '1p') + ;; + esac + + [ "$PRIVATE_IP" ] && printf " %s" "$PRIVATE_IP" } Keyboard(){ + KBD_LAYOUTS=$(setxkbmap -query | awk '/layout/{print $2}' | \ + tr ',' '\n' | awk '{print NR-1":"$1}') KBD=$(xset -q | grep LED | awk '{ print substr($10,5,1) }') - KBD=$(echo "$KBD_LAYOUTS" | sed "s/;/\n/g" | sed "/$KBD:/!d;s/.*://") - printf " %s" "${KBD}" + KBD=$(echo "$KBD_LAYOUTS" | sed "/^$KBD:/!d;s/.*://") + [ "$KBD" ] && printf " %s" "$KBD" } Battery() { @@ -57,6 +138,7 @@ Battery() { BATTERY_4_ICON='' FULL_AT=98 + WARNING_AT=15 BAT_ICON="" ICON="" @@ -68,16 +150,16 @@ Battery() { CAPACITY=$(cat "${BAT}/capacity") CHARGING=$(cat "${BAT}/status") fi - [ "$CHARGING" = "Charging" ] && ICON=$CHARGING_ICON + [ "$CHARGING" = "Charging" ] && ICON=$CHARGING_ICON ;; FreeBSD*) CAPACITY=$(sysctl -n hw.acpi.battery.life) CHARGING=$(sysctl -n hw.acpi.battery.state) - [ $CHARGING -eq 2 ] && ICON=$CHARGING_ICON + [ "$CHARGING" -eq 2 ] && ICON=$CHARGING_ICON ;; esac - [ -z "$ICON" ] && [ $CAPACITY -le 25 ] && ICON=$WARNING_ICON + [ -z "$ICON" ] && [ "$CAPACITY" -le "$WARNING_AT" ] && ICON=$WARNING_ICON if [ "$CAPACITY" -ge "$FULL_AT" ]; then BAT_ICON=$BATTERY_FULL_ICON @@ -93,13 +175,32 @@ Battery() { [ "$ICON" ] && printf "%s " "$ICON" [ "$BAT_ICON" ] && printf "%s " "$BAT_ICON" [ "$CAPACITY" ] && printf "%s%%" "$CAPACITY" + + CHARG_BAT="$CACHE_DIR/.battery-charge" + if [ "$CHARGING" = "Charging" ] || [ "$CHARGING" -eq 2 ]; then + [ -e "$CHARG_BAT" ] && return; + touch "$CHARG_BAT" + notify "Charging - ${ICON} ${BAT_ICON} ${CAPACITY}%" + rm "$LOW_BAT" + else + [ -e "$CHARG_BAT" ] || return; + notify "Discharging - ${BAT_ICON} ${CAPACITY}%" + rm "$CHARG_BAT" + fi + + LOW_BAT="$CACHE_DIR/.battery-low" + if [ "$CAPACITY" -le "$WARNING_AT" ] && \ + [ ! -e "$LOW_BAT" ] && [ ! -e "$CHARG_BAT" ]; then + touch "$LOW_BAT" + notify "${WARNING_ICON} Low Battery +${BAT_ICON} ${CAPACITY}% Remains" + fi } Brightness() { case "$KERNEL" in - Linux*) - BRIGHTNESS_CARD=$(ls /sys/class/backlight | head -n 1) - BRIGHTNESS_CARD=/sys/class/backlight/$BRIGHTNESS_CARD + *Linux*) + BRIGHTNESS_CARD=$(find /sys/class/backlight -depth | head -n 1) BRIGHTNESS_MAX=$(cat "${BRIGHTNESS_CARD}/max_brightness") BRIGHTNESS=$(cat "${BRIGHTNESS_CARD}/brightness") BRIGHTNESS=$((BRIGHTNESS*100/BRIGHTNESS_MAX)) @@ -112,21 +213,20 @@ Brightness() { BRIGHTNESS=$(apm -l) ;; esac - if [ "$BRIGHTNESS" -le 25 ]; then - ICON="" - elif [ "$BRIGHTNESS" -le 60 ]; then - ICON="" - else - ICON="" - fi - [ "$BRIGHTNESS" ] && printf "%s %s%%" "$ICON" "$BRIGHTNESS" + if [ "$BRIGHTNESS" -le 25 ]; then + ICON="" + elif [ "$BRIGHTNESS" -le 60 ]; then + ICON="" + else + ICON="" + fi + [ "$BRIGHTNESS" ] && printf "%s %s%%" "$ICON" "$BRIGHTNESS" } Volume() { - VOLUME=$(mixer vol | cut -d':' -f2) case "$KERNEL" in Linux*) - if pactl stat >/dev/null 2>&1; then + if pactl stat 2>/dev/null; then VOLUME=$(pactl get-sink-volume @DEFAULT_SOURCE@ | \ awk '/%/{sub(/%/, "", $5);print $5}') else @@ -138,30 +238,21 @@ Volume() { VOLUME=$(mixer -s vol | cut -d ':' -f 2) ;; esac - if [ "$VOLUME" -le 25 ]; then - ICON="" - elif [ "$VOLUME" -le 60 ]; then - ICON="" - else - ICON="" + if [ "$VOLUME" -le 25 ]; then + ICON="" + elif [ "$VOLUME" -le 60 ]; then + ICON="" + else + ICON="" fi - [ "$VOLUME" ] && printf "%s %s%%" "$ICON" "$VOLUME" -} - -CPU() { - USAGE=$(ps aux | awk 'BEGIN {sum=0} {sum+=$3}; END {print sum}' | sed 's/\..*//') - case "$KERNEL" in - Linux) - USAGE=$((USAGE/$(grep -c "^processor" /proc/cpuinfo))) - ;; - esac - printf " %s%%" "$USAGE" + [ "$VOLUME" ] && printf "%s %s%%" "$ICON" "$VOLUME" } CPUtemp() { case "$KERNEL" in Linux*) - TEMP=$(sensors | awk '/temp1/ {sub(/^\+/, "", $2);print $2}' | sed 's/\..*//') + [ -z "$TEMP_FILE" ] || \ + TEMP=$(sed 's/...$//' "$TEMP_FILE" 2>/dev/null) ;; FreeBSD*) TEMP=$(sysctl -n dev.cpu.0.temperature | sed 's/\..*//') @@ -172,38 +263,12 @@ CPUtemp() { sed 's/00/0/') ;; esac - printf " %s°C" "$TEMP" -} - -Uptime() { - case "$KERNEL" in - Linux) - SECS=$(cat /proc/uptime | sed 's/\..*//g') - ;; - *BSD*) - SECS=$(($(date +%s)-$(sysctl -n kern.boottime | \ - cut -d ',' -f 1 | cut -d '=' -f 2))) - ;; - esac - D=$((SECS / 60 / 60 / 24)) - H=$((SECS / 60/ 60 % 24)) - M=$((SECS / 60 % 60)) - S=$((SECS % 60)) - if [ "$D" != 0 ]; then - UPTIME="${D}d ${H:-0}h ${M:-0}m" - elif [ "$H" != 0 ]; then - UPTIME="${H}h ${M:-0}m" - elif [ "$M" != 0 ]; then - UPTIME="${M}m" - else - UPTIME="${S}s" - fi - printf " %s" "$UPTIME" + [ "$TEMP" ] && printf " %s°C" "$TEMP" } Memory() { case "$KERNEL" in - Linux) + Linux*) free=$(awk '/^MemFree/{free=$2} /^Buffers/{buff=$2} /^Cached/{cached=$2} @@ -226,7 +291,35 @@ Memory() { ;; esac USAGE=$(((total-free)*100/total)) - printf " %s%%" "${USAGE%.*}" + [ "$USAGE" ] && printf " %s%%" "${USAGE%.*}" +} + +Uptime() { + case "$KERNEL" in + Linux*) + SECS=$(sed 's/\..*//g' /proc/uptime) + ;; + *BSD*) + SECS=$(($(date +%s)-$(sysctl -n kern.boottime | \ + cut -d ',' -f 1 | cut -d '=' -f 2))) + ;; + esac + if [ "$SECS" -ge 86400 ]; then + D=$((SECS / 60 / 60 / 24)) + H=$((SECS / 60/ 60 % 24)) + M=$((SECS / 60 % 60)) + UPTIME="${D}d ${H:-0}h ${M:-0}m" + elif [ "$SECS" -ge 3600 ]; then + H=$((SECS / 60/ 60 % 24)) + M=$((SECS / 60 % 60)) + UPTIME="${H}h ${M:-0}m" + elif [ "$SECS" -ge 60 ]; then + M=$((SECS / 60 % 60)) + UPTIME="${M}m" + else + UPTIME="${SECS}s" + fi + [ "$UPTIME" ] && printf " %s" "$UPTIME" } DTime() { @@ -239,95 +332,42 @@ DTime() { *) echo "th";; esac } - printf " %s" "$(date "+$DAY$(day_suffix) %b %I:%M %p")" + DATE=$(date "+$DAY$(day_suffix) %b %I:%M %p") + [ "$DATE" ] && printf " %s" "$DATE" } # ------------------ # # --- Functions ---- # # ------------------ # -darken_hex(){ - C=${1:-FFFFFF} - V=${2:-10} - if [ "$(printf '%s' "$C" | cut -c1-1)" = "#" ]; then - C=$(printf '%s' "$C" | cut -c2-8) - else - C=$1 - fi - R=$(printf '%s' "$C" | awk '{print substr($0, 0, 2)}') - G=$(printf '%s' "$C" | awk '{print substr($0, 3, 2)}') - B=$(printf '%s' "$C" | awk '{print substr($0, 5, 2)}') - R=$(printf '%d' 0x"$R") - G=$(printf '%d' 0x"$G") - B=$(printf '%d' 0x"$B") - R=$((R+V)) - G=$((G+V)) - B=$((B+V)) - if [ "$R" -lt 0 ]; then - R=0 - elif [ "$R" -gt 255 ]; then - R=255 - fi - if [ "$G" -lt 0 ]; then - G=0 - elif [ "$G" -gt 255 ]; then - G=255 - fi - if [ "$B" -lt 0 ]; then - B=0 - elif [ "$B" -gt 255 ]; then - B=255 - fi - printf "#%02X%02X%02X\n" "$R" "$G" "$B" -} usage() { - printf "$0 [-m modules] [-M] [-h]\n" + printf "%s [-m modules] [-M] [-h]\n" "$0" exit 2 } stopbar() { for pid in $(ps ax | grep "/bin/sh.*dwm-bar" | awk '{print $1}'); do [ "$pid" = "$$" ] && continue - kill -9 "$pid" > /dev/null 2>&1 + kill -9 "$pid" 2>/dev/null wait done } startbar() { c=1 - while ! pgrep -x dwm >/dev/null; do + while ! pgrep -x dwm 2>/dev/null; do sleep 1; c=$((c+1)) [ "$c" = 10 ] && exit 2 done - [ -r "$HOME/.cache/bar_modules" ] && mods_list=$(cat "$HOME/.cache/bar_modules") - mods_list=${mods_list:-Weather Keyboard Battery Brightness Volume CPU CPUtemp Uptime Memory DTime} - mods=${1:-$mods_list} - mods_count=$(echo "$mods" | wc -w) + mods_list=$(cat "$CACHE_DIR/Modules" 2>/dev/null) + mods_list=${mods_list:-$full_mods} + mods=${mods:-$mods_list} c=1 for mod in $mods; do - if [ "$COLORFUL" -eq 1 ]; then - XRDB=$(xrdb -query) - fgColor=$(printf "$XRDB" | awk "/color$c/ {print \$2;exit}") - bgcolor=$(printf "$XRDB" | awk "/background/ {print \$2;exit}") - bgcolor_off=$(((c-1)*$((40/$mods_count)))) - bgColor=$(darken_hex "$bgcolor" "-$bgcolor_off") - [ "$c" -eq 1 ] && bgColor=$bgcolor - [ "$c" -ge 8 ] && fgColor=$(echo "$XRDB" | awk "/color$((c+1))/ {print \$2;exit}") - if [ "$COLORFUL_BACKGROUND" -eq 1 ]; then - mod_prefix="^c$fgColor^^b$bgColor^ " - mod_suffix="" - mod_sep=" " - else - mod_prefix="^c$fgColor^ " - mod_suffix="" - mod_sep=" " - fi - else - mod_prefix=" " - mod_suffix="" - mod_sep=" |" - #mod_prefix=" [ " - #mod_suffix=" ]" - #mod_sep="" - fi + mod_prefix="" + mod_suffix="" + mod_sep=" | " + #mod_prefix=" [ " + #mod_suffix=" ] " + #mod_sep="" if [ "$c" = 1 ]; then output="$mod_prefix%$mod%$mod_suffix" else @@ -335,14 +375,19 @@ startbar() { fi c=$((c+1)) done - output="$output " + # Add padding + output=" $output " while true; do - unset out out=$output for mod in $mods; do unset mod_output - mod_output=$($mod) - [ -z "$mod_output" ] && continue + #mod_output=$($mod) + mod_output=$(cat "$CACHE_DIR/mod-$mod") + if [ -z "$mod_output" ]; then + out=$(printf "%s" "${out}" | \ + sed "s/$mod_sep$mod_prefix%$mod%$mod_suffix//") + continue + fi out=$(printf "%s" "${out}" | sed "s/%$mod%/$mod_output/g") done dwm -s "$out" @@ -350,56 +395,63 @@ startbar() { done } +updatebar() { + mods_list=$(cat "$CACHE_DIR/Modules") + mods_list=${mods_list:-$full_mods} + while true; do + for mod in ${mods:-$mods_list}; do + printf '%s' "$($mod)" > "$CACHE_DIR/mod-$mod" + done + done +} + main() { while getopts "m:M" flag; do case "${flag}" in M) full_text="[All Modules]" - full="Weather Keyboard Battery Brightness Volume CPU CPUtemp Uptime Memory DTime" rest="[Restart Modules]" cust="[Custom Modules]" - opts=" - Volume CPU Memory DTime - Volume CPU CPUtemp Uptime DTime - Keyboard Battery Brightness DTime - Weather Battery Brightness DTime - Weather Keyboard Battery Brightness DTime - " - opts=$(printf "%s" "${opts}" | sed 's/^[ \t]*//g;/^ *$/d') - choice=$(printf "%s\n" "${full_text}" "${rest}" "${cust}" "${opts}" | dmenu -i -l 20) - [ -z "$choice" ] && choice=$(cat $HOME/.cache/bar_modules) + opts=$(printf "%s" "${opts_mods}" | sed 's/^[ \t]*//g;/^ *$/d') + choice=$(printf "%s\n" \ + "${full_text}" "${rest}" "${cust}" "${opts}" | dmenu -i -l 20) + [ -z "$choice" ] && choice=$(cat "$CACHE_DIR/Modules") case "$choice" in "$cust") - HEIGHT=$(($(echo "$full" | wc -w)+2)) - WIDTH=$(($(echo "$full" | tr ' ' '\n' | wc -L)*2)) + HEIGHT=$(($(echo "$full_mods" | wc -w)+2)) + WIDTH=$(($(echo "$full_mods" | tr ' ' '\n' | wc -L)*2)) [ "$WIDTH" -lt 30 ] && WIDTH="30" "$TERMINAL" -c "st-float" -g "${WIDTH}x${HEIGHT}+400+150" \ - -e sh -c "echo \"$full\" | tr ' ' '\n' | smenu -m \"Select Modules:\" -l -P -n 100 -q | tr '\n' ' ' > $HOME/.cache/bar_modules.tmp" - mods=$(cat "$HOME/.cache/bar_modules.tmp") - [ -z "$mods" ] && mods=$(cat "$HOME/.cache/bar_modules") - rm "$HOME/.cache/bar_modules.tmp" + -e sh -c "echo \"$full_mods\" | tr ' ' '\n' | \ + smenu -m \"Select Modules:\" -l -P -n 100 -q | \ + tr '\n' ' ' > \"$CACHE_DIR/Modules.tmp\"" + mods=$(cat "$CACHE_DIR/Modules.tmp") + [ -z "$mods" ] && mods=$(cat "$CACHE_DIR/Modules") + rm "$CACHE_DIR/Modules.tmp" ;; "$rest") - mods=$(cat $HOME/.cache/bar_modules) + mods=$(cat "$CACHE_DIR/Modules") ;; "$full_text") - mods=$full + mods=$full_mods ;; *) mods=$choice ;; esac - echo "$mods" > "$HOME/.cache/bar_modules" + echo "$mods" > "$CACHE_DIR/Modules" ;; m) mods=${OPTARG} - echo "$mods" > "$HOME/.cache/bar_modules" + echo "$mods" > "$CACHE_DIR/Modules" ;; *) usage ;; esac done + stopbar - startbar "$mods" & + updatebar & + startbar & } main "$@" diff --git a/.local/bin/email b/.local/bin/email @@ -1,38 +1,60 @@ #!/bin/sh -# Easy Mail +NO_CLIENT=0 +SYNC_MAIL=0 +SYNC_MAIL_FREQ=0 +SYNC_MAIL_FREQ_SECS=1800 + MBSYNCRC="${MBSYNCRC:-${XDG_CONFIG_HOME:-$HOME/.config}/mbsync/mbsyncrc}" MBSYNC_ACCS="${XDG_DATA_HOME:-$HOME/.local/share}/mail" sync_mail() { - mbsync -c "$MBSYNCRC" -a - for ACC in $MBSYNC_ACCS/*; do - LAST_RUN="$ACC/.sync_mail.lastrun" - NEW_MAILS="$(find \ - "$ACC/INBOX/new" \ - "$ACC/Inbox/new" \ - "$ACC/inbox/new" \ - -type f -newer "$LAST_RUN" 2>/dev/null | wc -l | sed 's/ //g')" - if [ "$NEW_MAILS" -ge 1 ]; then - [ "$NEW_MAILS" -gt 1 ] && SUF="s" || SUF="" - ACC_SHOW="${ACC##*/}" - merbe " New Mail" "You have ${NEW_MAILS} new mail${SUF} in '${ACC_SHOW}'." & - fi - touch "$LAST_RUN" - done + mbsync -c "$MBSYNCRC" -a + for ACC in "$MBSYNC_ACCS"/*; do + LAST_RUN="$ACC/.sync_mail.lastrun" + NEW_MAILS=$(find \ + "$ACC/INBOX/new" \ + "$ACC/Inbox/new" \ + "$ACC/inbox/new" \ + -type f -newer "$LAST_RUN" 2>/dev/null | wc -l | sed 's/ //g') + if [ "$NEW_MAILS" -ge 1 ]; then + [ "$NEW_MAILS" -gt 1 ] && SUF="s" || SUF="" + ACC_SHOW="${ACC##*/}" + notify " New Mail +You have ${NEW_MAILS} new mail${SUF} in '${ACC_SHOW}'." + fi + touch "$LAST_RUN" + done } -case "$1" in - -n) - sync_mail - ;; - -s) - while :; do - sync_mail - sleep 3600 - done - ;; - *) - sync_mail - mutt - sync_mail - ;; -esac +while getopts ':nosS:' flag; do + case "$flag" in + n) NO_CLIENT=1 ;; + o) SYNC_MAIL=1 ;; + s) SYNC_MAIL_FREQ=1 ;; + S) + echo "${OPTARG}" | grep "^-\?[0-9]+$" && \ + SYNC_MAIL_FREQ_SECS=${OPTARG} + ;; + *) + printf 'Usage: %s [-n] [-s]\n\n' "$0" + printf ' -n: Do not open client\n' + printf ' -o: Sync email before opening client\n' + printf ' -s: Sync email every X seconds (default: %s)\n' \ + "$SYNC_MAIL_FREQ_SECS" + printf ' -S: Frequency of syncing emails (-s option)\n' + exit 2 + ;; + esac +done + +if [ $SYNC_MAIL_FREQ -eq 1 ]; then + while true; do + sync_mail + sleep "$SYNC_MAIL_FREQ_SECS" + done & +elif [ $SYNC_MAIL -eq 1 ]; then + sync_mail +fi + +[ $NO_CLIENT -eq 1 ] || mutt + +exit diff --git a/.local/bin/pacman-up b/.local/bin/pacman-up @@ -1,6 +1,6 @@ #!/bin/sh notif() { - merbe " Updater" "$1" & + notify " Updater" "$1" } notifnq() { TEXT="${1}" @@ -19,12 +19,12 @@ PKG_COUNT="$(printf '%s\n' "$PKG_LIST" | wc -l)" PKG_SIZE="$(printf '%s\n' "$PKG_LIST" | awk '{SUM+=$2} END {printf("%.1fMiB",SUM/1024/1024)}')" [ "$PKG_COUNT" -gt 1 ] && SUFFIX="s" -merbe "$(printf "Packages:\n$PKG_LIST_H" | head)" & +notify "$(printf "Packages:\n$PKG_LIST_H" | head)" CHOICE="$(printf '%s\n' "Yes" "No" | dmenu -p "Update $PKG_COUNT Package$SUFFIX ($PKG_SIZE)?")" case "$CHOICE" in [Yy][Ee][Ss]|[Yy]) notif "Updating $PKG_COUNT Package$SUFFIX..." - "$TERMINAL" -c "st-float" -g "120x26" -e sh -c "doas pacman -Syu --noconfirm || (merbe \" Updater\" \"Didn't update anything.\" && exit 2)" + "$TERMINAL" -c "st-float" -g "120x26" -e sh -c "doas pacman -Syu --noconfirm || (notify \" Updater\" \"Didn't update anything.\" && exit 2)" rm ~/.cache/pkg_updates notifnq "Updated $PKG_COUNT Package$SUFFIX." ;; diff --git a/.local/bin/screenshot b/.local/bin/screenshot @@ -9,17 +9,17 @@ NAME_SS="$(date '+%Y%m%d-%H%M%S').png" SAVE_SS_DIR="$HOME/pics" while getopts :wscxt:q:n:p: flag; do - case "${flag}" in - w) ACTIVE=1;; - s) SELECT=1;; - c) COPY_SS=1;; - x) SAVE_SS=1;; - t) TIMER=${OPTARG};; - q) QUALITY=${OPTARG};; - n) NAME_SS=${OPTARG};; - p) SAVE_SS_DIR=${OPTARG};; - *) echo "usage: $0 [-wxsc] [-t time(s)] [-q quality(1-10)] [-n name.png] [-p path/to/picture]"; exit 2 ;; - esac + case "${flag}" in + w) ACTIVE=1;; + s) SELECT=1;; + c) COPY_SS=1;; + x) SAVE_SS=1;; + t) TIMER=${OPTARG};; + q) QUALITY=${OPTARG};; + n) NAME_SS=${OPTARG};; + p) SAVE_SS_DIR=${OPTARG};; + *) echo "usage: $0 [-wxsc] [-t time(s)] [-q quality(1-10)] [-n name.png] [-p path/to/picture]"; exit 2 ;; + esac done [ $SAVE_SS -eq 0 ] && [ $COPY_SS -eq 0 ] && COPY_SS=1 @@ -35,13 +35,13 @@ sleep "$TIMER" maim $TAGS -m "$QUALITY" "${SAVE_SS_DIR}/${NAME_SS}" || exit 2 if [ $SAVE_SS -eq 1 ] && [ $COPY_SS -eq 1 ]; then - xclip -selection clipboard -target image/png -i "${SAVE_SS_DIR}/${NAME_SS}" - SHOW="$(echo "${SAVE_SS_DIR}" | sed -e "s|${HOME}|~|g")/${NAME_SS} (+CLIPBOARD)" + xclip -selection clipboard -target image/png -i "${SAVE_SS_DIR}/${NAME_SS}" + SHOW="$(echo "${SAVE_SS_DIR}" | sed -e "s|${HOME}|~|g")/${NAME_SS} (+CLIPBOARD)" elif [ $SAVE_SS -eq 0 ] && [ $COPY_SS -eq 1 ]; then - rm "${SAVE_SS_DIR}/${NAME_SS}" - SHOW="CLIPBOARD" + rm "${SAVE_SS_DIR}/${NAME_SS}" + SHOW="CLIPBOARD" elif [ $SAVE_SS -eq 1 ] && [ $COPY_SS -eq 0 ]; then - SHOW="$(echo "${SAVE_SS_DIR}" | sed -e "s|${HOME}|~|g")/${NAME_SS}" + SHOW="$(echo "${SAVE_SS_DIR}" | sed -e "s|${HOME}|~|g")/${NAME_SS}" fi -merbe " Picture acquired!" "${SHOW}" +notify " Picture acquired!" "${SHOW}" diff --git a/.local/bin/theme-sel b/.local/bin/theme-sel @@ -6,88 +6,92 @@ XRES_COLORS_DST="${XRES}/colors" XRES_COLORS_SRC="${XRES}/themes" find_themes() { - find "${XRES_COLORS_SRC}" -type f -exec basename {} \; | sort + find "${XRES_COLORS_SRC}" -type f -exec basename {} \; | sort } generate_theme() { - SRC="$1" - DST="$2" - [ -f "${DST}.tmp" ] && rm "${DST}.tmp" - cp "${SRC}" "${DST}.tmp" - - XRDB="$(xrdb -query)" - background="$(printf '%s\n' "$XRDB" | awk '/background/ {print $2;exit}')" - foreground="$(printf '%s\n' "$XRDB" | awk '/foreground/ {print $2;exit}')" - cursorColor="$(printf '%s\n' "$XRDB" | awk '/cursorColor/ {print $2;exit}')" - - sed -i "s|%clfg%|$foreground|g" "${DST}.tmp" - sed -i "s|%clbg%|$background|g" "${DST}.tmp" - sed -i "s|%clcr%|$cursorcolor|g" "${DST}.tmp" - sed -i "s|%HOME%|$HOME|g" "${DST}.tmp" - - for i in $(seq 0 15); do - v="$(echo "$XRDB" | awk "/color$i/ {print \$2;exit}")" - sed -i "s|%cl${i}%|$v|g" "${DST}.tmp" - done - - [ -f "${DST}" ] && rm "${DST}" - mv "${DST}.tmp" "${DST}" + SRC="$1" + DST="$2" + [ -f "${DST}.tmp" ] && rm "${DST}.tmp" + cp "${SRC}" "${DST}.tmp" + + XRDB="$(xrdb -query)" + background="$(printf '%s\n' "$XRDB" | awk '/background/ {print $2;exit}')" + foreground="$(printf '%s\n' "$XRDB" | awk '/foreground/ {print $2;exit}')" + cursorcolor="$(printf '%s\n' "$XRDB" | awk '/cursorColor/ {print $2;exit}')" + + sed "s|%clfg%|$foreground|g;s|%clbg%|$background|g;s|%clcr%|$cursorcolor|g;s|%HOME%|$HOME|g" "${DST}.tmp" > "${DST}.tmp2" + mv "${DST}.tmp2" "${DST}.tmp" + + for i in $(seq 0 15); do + v="$(echo "$XRDB" | awk "/color$i/ {print \$2;exit}")" + sed "s|%cl${i}%|$v|g" "${DST}.tmp" > "${DST}.tmp2" + mv "${DST}.tmp2" "${DST}.tmp" + done + + [ -f "${DST}" ] && rm "${DST}" + mv "${DST}.tmp" "${DST}" } apply_theme() { - THEME="$1" - XRES_COLORS_SRC="${XRES}/themes/$THEME" - cp -f "${XRES_COLORS_SRC}" "${XRES_COLORS_DST}" - xrdb "${XRES_SRC}" - generate_theme "${HOME}/.config/surf/styles/default.css.in" "${HOME}/.config/surf/styles/default.css" - generate_theme "${HOME}/.config/zathura/zathurarc.in" "${HOME}/.config/zathura/zathurarc" - echo "$THEME" > "$HOME"/.cache/theme + THEME="$1" + XRES_COLORS_SRC="${XRES}/themes/$THEME" + cp -f "${XRES_COLORS_SRC}" "${XRES_COLORS_DST}" + xrdb "${XRES_SRC}" + generate_theme "${HOME}/.config/surf/styles/default.css.in" "${HOME}/.config/surf/styles/default.css" + generate_theme "${HOME}/.config/zathura/zathurarc.in" "${HOME}/.config/zathura/zathurarc" + echo "$THEME" > "$HOME"/.cache/theme } reload_theme() { - pidof tabbed >/dev/null 2>&1 && for PID in $(pidof tabbed); do kill -s USR1 "$PID"; done - pidof st >/dev/null 2>&1 && for PID in $(pidof st); do kill -s USR1 "$PID"; done - # Remove urgency mark for st, tabbed instances: - xdotool search --class st set_window --urgency 0 "%@" - xdotool search --class tabbed set_window --urgency 0 "%@" - pidof dwm >/dev/null 2>&1 && xdotool key "Super+F5" - #pidof bspwm && bspc wm -r - #pidof openbox && openbox --restart - setsid dwm-bar - - case "$OLDTHEME" in - "${THEME}") NOTIF_TEXT="Reloaded ${THEME} theme." ;; - *) NOTIF_TEXT="Set the theme from ${OLDTHEME} to ${THEME}!" ;; - esac - pkill -SIGUSR1 merbe - merbe " Theme Selector" "$NOTIF_TEXT" & - #dunstify -t 10000 -h string:x-dunst-stack-tag:theme "Set Theme" "$NOTIF_TEXT" + pidof tabbed >/dev/null 2>&1 && for PID in $(pidof tabbed); do kill -s USR1 "$PID" >/dev/null 2>&1; done + pidof st >/dev/null 2>&1 && for PID in $(pidof st); do kill -s USR1 "$PID" >/dev/null 2>&1; done + # Remove urgency mark for st, tabbed instances: + xdotool search --class st set_window --urgency 0 "%@" + xdotool search --class tabbed set_window --urgency 0 "%@" + pidof dwm >/dev/null 2>&1 && xdotool key "Super+F5" + #pidof bspwm && bspc wm -r + #pidof openbox && openbox --restart + + # If you have colorful bar, consider restarting the bar + #dwm-bar & + + case "$OLDTHEME" in + "${THEME}") NOTIF_TEXT="Reloaded ${THEME} theme." ;; + *) NOTIF_TEXT="Set the theme from ${OLDTHEME} to ${THEME}!" ;; + esac + notify "$(printf '%s\n' " Theme Selector" "$NOTIF_TEXT")" } case "$1" in - -l) - find_themes - exit - ;; - -x) - THEME="$(find_themes | shuf -n 1)" - THEME="${THEME%% *}" - [ "$THEME" ] || exit - ;; - -s) - THEME="$(find_themes | sed "s/$OLDTHEME/$OLDTHEME */g" | dmenu -i -p "Set Theme:")" - THEME="${THEME%% *}" - [ "$THEME" ] || exit - ;; - *) - THEME="${1:-$(cat "$HOME"/.cache/theme || echo "nord")}" - ;; + -l) + find_themes + exit + ;; + -x) + TODAY=$(date +%d) + COUNT=$(find_themes | wc -l) + THEME=$((TODAY%COUNT)) + [ "$THEME" -eq 0 ] && THEME=$COUNT + THEME=$(find_themes | sed -n "${THEME}p") + ;; + -s) + NUM=$(find_themes -l | awk "/$OLDTHEME/{print NR-1}") + THEME=$(find_themes | sed "s/$OLDTHEME/$OLDTHEME */g" | dmenu -i -n "$NUM" -p "Set Theme:") + THEME=${THEME%% *} + [ "$THEME" ] || exit + ;; + *) + THEME="${1:-$(cat "$HOME"/.cache/theme || echo "nord")}" + ;; esac + apply_theme "$THEME" -if [ "$DISPLAY" ]; then - #bg-set - bg-gen - reload_theme + +if [ "$DISPLAY" ]; then + #bg-set + bg-gen + reload_theme fi # Old: diff --git a/.local/bin/volume b/.local/bin/volume @@ -1,152 +0,0 @@ -#!/bin/sh -AUDIO_STEPS="5" -AUDIO_ACT="get" - -while getopts ':gidmGIDMs:' flag; do - case "${flag}" in - g) AUDIO_ACT="get" ;; - i) AUDIO_ACT="inc" ;; - d) AUDIO_ACT="dec" ;; - m) AUDIO_ACT="mute" ;; - G) AUDIO_ACT="mic-get" ;; - I) AUDIO_ACT="mic-inc" ;; - D) AUDIO_ACT="mic-dec" ;; - M) AUDIO_ACT="mic-mute" ;; - s) AUDIO_STEPS="${OPTARG}" ;; - *) - printf 'Usage: %s [-g] [-d] [-i] [-m] [-G] [-D] [-I] [-M] [-s audio steps (in %%)]\n' "$0" - printf ' -g: get volume\n' - printf ' -i: increase volume\n' - printf ' -d: decrease volume\n' - printf ' -m: mute volume\n' - printf ' -G: get mic volume\n' - printf ' -I: increase mic volume\n' - printf ' -D: decrease mic volume\n' - printf ' -M: mute mic volume\n' - exit 2 - ;; - esac -done - -vol() { - case "$(uname)" in - "Linux"*) - if pactl stat >/dev/null 2>&1; then - case "$1" in - get) pactl get-sink-volume @DEFAULT_SOURCE@ | awk '/%/{sub(/%/, "", $5);print $5}' ;; - inc) pactl set-sink-volume @DEFAULT_SINK@ "+$2%" ;; - dec) pactl set-sink-volume @DEFAULT_SINK@ "-$2%" ;; - mute) pactl set-sink-mute @DEFAULT_SINK@ toggle ;; - ismuted) pactl get-sink-mute @DEFAULT_SOURCE@ | grep -o 'yes' ;; - mic-get) pactl get-source-volume @DEFAULT_SOURCE@ | awk '/%/{sub(/%/, "", $5);print $5}' ;; - mic-inc) pactl set-source-volume @DEFAULT_SINK@ "+$2%" ;; - mic-dec) pactl set-source-volume @DEFAULT_SINK@ "-$2%" ;; - mic-mute) pactl set-source-mute @DEFAULT_SINK@ toggle ;; - mic-ismuted) pactl get-source-mute @DEFAULT_SOURCE@ | grep -o 'yes' ;; - esac - else - case "$1" in - get) amixer sget Master on | grep -o '[0-9]*%' | sed 's/%//' ;; - inc) amixer sset Master "$2%+" on -q ;; - dec) amixer sset Master "$2%-" on -q ;; - mute) amixer sset Master 1+ toggle -q ;; - ismuted) amixer sget Master on | grep -o '\[off\]' ;; - mic-get) pactl get-source-volume @DEFAULT_SOURCE@ | awk '/%/{sub(/%/, "", $5);print $5}' ;; - mic-inc) pactl set-source-volume @DEFAULT_SINK@ "+$2%" ;; - mic-dec) pactl set-source-volume @DEFAULT_SINK@ "-$2%" ;; - mic-mute) pactl set-source-mute @DEFAULT_SINK@ toggle ;; - mic-ismuted) pactl get-source-mute @DEFAULT_SOURCE@ | grep -o 'yes' ;; - esac - fi - ;; - "FreeBSD"*) - case "$1" in - get) mixer -s vol | cut -d ':' -f 2 ;; - inc) mixer -s vol "+$2%" ;; - dec) mixer -s vol "-$2%" ;; - mute) [ "$(vol get)" -eq 0 ] && mixer -s vol 75 || mixer -s vol 0 ;; - ismuted) [ "$(vol get)" -eq 0 ] && echo yes ;; - mic-get) mixer -s mic | cut -d ':' -f 2 ;; - mic-inc) mixer -s mic "+$2%" ;; - mic-dec) mixer -s mic "-$2%" ;; - mic-mute) [ "$(vol mic-get)" -eq 0 ] && mixer -s mic 35 || mixer -s mic 0 ;; - mic-ismuted) [ "$(vol mic-get)" -eq 0 ] && echo yes ;; - esac - ;; - esac -} - -notify() { - case "$1" in - mic) VOLUME=$(vol mic-get) ; IS_MUTED=$(vol mic-ismuted) ;; - *) VOLUME=$(vol get) ; IS_MUTED=$(vol ismuted) ;; - esac - if [ "$IS_MUTED" ] || [ "$VOLUME" -eq 0 ]; then - VOLUME="Muted" - VOLUME_ICON="ﱝ" - elif [ "$VOLUME" -lt 30 ]; then - VOLUME_ICON="" - elif [ "$VOLUME" -lt 70 ]; then - VOLUME_ICON="" - else - VOLUME_ICON="" - fi - pkill -SIGUSR1 merbe - merbe "$VOLUME_ICON $VOLUME" & -} - -case "$AUDIO_ACT" in - inc) - CURRENT_VOLUME=$(vol get) - REMAINDER=$((CURRENT_VOLUME%AUDIO_STEPS)) - AUDIO_STEPS=$((AUDIO_STEPS-REMAINDER)) - ;; - dec) - CURRENT_VOLUME=$(vol get) - REMAINDER=$((CURRENT_VOLUME%AUDIO_STEPS)) - AUDIO_STEPS=$((AUDIO_STEPS+REMAINDER)) - ;; - mic-inc) - CURRENT_VOLUME=$(vol mic-get) - REMAINDER=$((CURRENT_VOLUME%AUDIO_STEPS)) - AUDIO_STEPS=$((AUDIO_STEPS-REMAINDER)) - ;; - mic-dec) - CURRENT_VOLUME=$(vol mic-get) - REMAINDER=$((CURRENT_VOLUME%AUDIO_STEPS)) - AUDIO_STEPS=$((AUDIO_STEPS+REMAINDER)) - ;; -esac - -case "$AUDIO_ACT" in - get) - notify - ;; - inc) - vol inc "$AUDIO_STEPS" - notify - ;; - dec) - vol dec "$AUDIO_STEPS" - notify - ;; - mute) - vol mute - notify - ;; - mic-get) - notify "mic" - ;; - mic-inc) - vol mic-inc "$AUDIO_STEPS" - notify "mic" - ;; - mic-dec) - vol mic-dec "$AUDIO_STEPS" - notify "mic" - ;; - mic-mute) - vol mic-mute - notify "mic" - ;; -esac diff --git a/.local/bin/vpn b/.local/bin/vpn @@ -1,14 +1,50 @@ #!/bin/sh -echo "nameserver 1.1.1.1" > /etc/resolv.conf -cd /dev -mkdir net -mknod net/tun c 10 200 -chmod 0666 net/tun -while :; do +prepare() { + (echo "nameserver 1.1.1.1"; + echo "nameserver 1.0.0.1"; + echo "nameserver 208.67.222.222"; + echo "nameserver 208.67.220.220") > /etc/resolv.conf + + cd /dev || exit + mkdir net + mknod net/tun c 10 200 + chmod 0666 net/tun +} + +stopvpn() { for pid in $(ps ax | grep openvpn | awk '{print $1}'); do [ "$pid" = "$$" ] && continue kill -9 "$pid" > /dev/null 2>&1 wait done +} + +startvpn() { + printf "\033[90m" openvpn /home/mahdi/.local/share/Mahdi.ovpn -done + printf "\033[0m" +} + +loopvpn() { + while :; do + stopvpn + startvpn + done +} + +prepare +clear + +case "$1" in + start) + startvpn + ;; + stop) + stopvpn + ;; + *) + loopvpn & + trap loop INT + trap loop EXIT + ;; +esac diff --git a/.local/bin/webcam b/.local/bin/webcam @@ -1,9 +1,9 @@ #!/bin/sh -WEBCAM_DRIVER="v4l2" -WEBCAM_DEVICE="$(ls /dev/video* | head -n 1)" +WEBCAM_DRIVER=v4l2 +WEBCAM_DEVICE=$(find /dev -name "video*" | sort | sed -n '1p') if [ ! -e "${WEBCAM_DEVICE}" ]; then - merbe "Webcam" "Install a webcam first!" & + notify "Webcam" "Install a webcam first!" exit 2 fi @@ -14,10 +14,10 @@ case "$1" in ;; *) ps ax | grep "mpv*av://$WEBCAM_DRIVER:$WEBCAM_DEVICE*" | \ - awk '{print $1}' | while read PID; do kill -9 "$PID"; wait; done - merbe " Webcam" "$WEBCAM_DEVICE is open now." & + awk '{print $1}' | while read -r PID; do kill -9 "$PID"; wait; done + notify " Webcam" "$WEBCAM_DEVICE is open now." mpv "av://$WEBCAM_DRIVER:$WEBCAM_DEVICE" --title=webcam \ --profile=low-latency --untimed --load-scripts=no --no-osc - merbe "﫞 Webcam" "$WEBCAM_DEVICE has been closed." & + notify "﫞 Webcam" "$WEBCAM_DEVICE has been closed." ;; esac diff --git a/.local/src/dmenu/LICENSE b/.local/src/dmenu/LICENSE @@ -1,30 +0,0 @@ -MIT/X Consortium License - -© 2006-2019 Anselm R Garbe <anselm@garbe.ca> -© 2006-2008 Sander van Dijk <a.h.vandijk@gmail.com> -© 2006-2007 Michał Janeczek <janeczek@gmail.com> -© 2007 Kris Maglione <jg@suckless.org> -© 2009 Gottox <gottox@s01.de> -© 2009 Markus Schnalke <meillo@marmaro.de> -© 2009 Evan Gates <evan.gates@gmail.com> -© 2010-2012 Connor Lane Smith <cls@lubutu.com> -© 2014-2022 Hiltjo Posthuma <hiltjo@codemadness.org> -© 2015-2019 Quentin Rameau <quinq@fifth.space> - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/.local/src/dmenu/Makefile b/.local/src/dmenu/Makefile @@ -1,64 +0,0 @@ -# dmenu - dynamic menu -# See LICENSE file for copyright and license details. - -include config.mk - -SRC = drw.c dmenu.c stest.c util.c -OBJ = $(SRC:.c=.o) - -all: options dmenu stest - -options: - @echo dmenu build options: - @echo "CFLAGS = $(CFLAGS)" - @echo "LDFLAGS = $(LDFLAGS)" - @echo "CC = $(CC)" - -.c.o: - $(CC) -c $(CFLAGS) $< - -config.h: - cp config.def.h $@ - -$(OBJ): arg.h config.h config.mk drw.h - -dmenu: dmenu.o drw.o util.o - $(CC) -o $@ dmenu.o drw.o util.o $(LDFLAGS) - -stest: stest.o - $(CC) -o $@ stest.o $(LDFLAGS) - -clean: - rm -f dmenu stest $(OBJ) dmenu-$(VERSION).tar.gz - -dist: clean - mkdir -p dmenu-$(VERSION) - cp LICENSE Makefile README arg.h config.def.h config.mk dmenu.1\ - drw.h util.h dmenu_path dmenu_run stest.1 $(SRC)\ - dmenu-$(VERSION) - tar -cf dmenu-$(VERSION).tar dmenu-$(VERSION) - gzip dmenu-$(VERSION).tar - rm -rf dmenu-$(VERSION) - -install: all - mkdir -p $(DESTDIR)$(PREFIX)/bin - cp -f dmenu dmenu_path dmenu_run stest $(DESTDIR)$(PREFIX)/bin - chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu - chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_path - chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_run - chmod 755 $(DESTDIR)$(PREFIX)/bin/stest - mkdir -p $(DESTDIR)$(MANPREFIX)/man1 - sed "s/VERSION/$(VERSION)/g" < dmenu.1 > $(DESTDIR)$(MANPREFIX)/man1/dmenu.1 - sed "s/VERSION/$(VERSION)/g" < stest.1 > $(DESTDIR)$(MANPREFIX)/man1/stest.1 - chmod 644 $(DESTDIR)$(MANPREFIX)/man1/dmenu.1 - chmod 644 $(DESTDIR)$(MANPREFIX)/man1/stest.1 - -uninstall: - rm -f $(DESTDIR)$(PREFIX)/bin/dmenu\ - $(DESTDIR)$(PREFIX)/bin/dmenu_path\ - $(DESTDIR)$(PREFIX)/bin/dmenu_run\ - $(DESTDIR)$(PREFIX)/bin/stest\ - $(DESTDIR)$(MANPREFIX)/man1/dmenu.1\ - $(DESTDIR)$(MANPREFIX)/man1/stest.1 - -.PHONY: all options clean dist install uninstall diff --git a/.local/src/dmenu/README b/.local/src/dmenu/README @@ -1,24 +0,0 @@ -dmenu - dynamic menu -==================== -dmenu is an efficient dynamic menu for X. - - -Requirements ------------- -In order to build dmenu you need the Xlib header files. - - -Installation ------------- -Edit config.mk to match your local setup (dmenu is installed into -the /usr/local namespace by default). - -Afterwards enter the following command to build and install dmenu -(if necessary as root): - - make clean install - - -Running dmenu -------------- -See the man page for details. diff --git a/.local/src/dmenu/arg.h b/.local/src/dmenu/arg.h @@ -1,49 +0,0 @@ -/* - * Copy me if you can. - * by 20h - */ - -#ifndef ARG_H__ -#define ARG_H__ - -extern char *argv0; - -/* use main(int argc, char *argv[]) */ -#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ - argv[0] && argv[0][0] == '-'\ - && argv[0][1];\ - argc--, argv++) {\ - char argc_;\ - char **argv_;\ - int brk_;\ - if (argv[0][1] == '-' && argv[0][2] == '\0') {\ - argv++;\ - argc--;\ - break;\ - }\ - for (brk_ = 0, argv[0]++, argv_ = argv;\ - argv[0][0] && !brk_;\ - argv[0]++) {\ - if (argv_ != argv)\ - break;\ - argc_ = argv[0][0];\ - switch (argc_) - -#define ARGEND }\ - } - -#define ARGC() argc_ - -#define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\ - ((x), abort(), (char *)0) :\ - (brk_ = 1, (argv[0][1] != '\0')?\ - (&argv[0][1]) :\ - (argc--, argv++, argv[0]))) - -#define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\ - (char *)0 :\ - (brk_ = 1, (argv[0][1] != '\0')?\ - (&argv[0][1]) :\ - (argc--, argv++, argv[0]))) - -#endif diff --git a/.local/src/dmenu/config.h b/.local/src/dmenu/config.h @@ -1,60 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -static char font[] = "monospace:size=10"; /* -fn option overrides fonts[0]; default font */ -static const char *fonts[] = { - font, - "Vazir:size=10", - "emoji:size=10", -}; - -static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ -static unsigned int border_width= 2; /* -bw option; size of the window border */ -static char *prompt = NULL; /* -p option; prompt to the left of input field */ -static unsigned int preselected = 0; /* -n option; preselected item starting from 0 */ -static unsigned int lines = 0; /* -l option; if nonzero dmenu draws vertical list */ -static const unsigned int alpha = 0xf0; - -/* - * Characters not considered part of a word while deleting words - * for example: " /?\"&[]" - */ -static const char worddelimiters[] = " "; - -static char normfgcolor[] = "#ECEFF4"; -static char normbgcolor[] = "#3B4252"; -static char normhlcolor[] = "#EBCB8B"; -static char selfgcolor[] = "#EBCB8B"; -static char selbgcolor[] = "#4C566A"; -static char selhlcolor[] = "#E5E9F0"; -static char *colors[SchemeLast][2] = { - /* fg bg */ - [SchemeNorm] = { normfgcolor, normbgcolor }, - [SchemeSel] = { selfgcolor, selbgcolor }, - [SchemeNormHighlight] = { normhlcolor, normbgcolor }, - [SchemeSelHighlight] = { selhlcolor, selbgcolor }, - [SchemeOut] = { "#000000", "#00ffff" }, - [SchemeOutHighlight] = { normhlcolor, "#00ffff" }, -}; - -static const unsigned int alphas[SchemeLast][2] = { - [SchemeNorm] = { OPAQUE, alpha }, - [SchemeSel] = { OPAQUE, alpha }, - [SchemeOut] = { OPAQUE, alpha }, - [SchemeNormHighlight] = { OPAQUE, alpha }, - [SchemeSelHighlight] = { OPAQUE, alpha }, - [SchemeOutHighlight] = { OPAQUE, alpha }, -}; - -/* - * Xresources preferences to load at startup - */ -ResourcePref resources[] = { - { "font", STRING, &font }, - { "color12", STRING, &normfgcolor }, - { "color0", STRING, &normbgcolor }, - { "color11", STRING, &normhlcolor }, - { "color0", STRING, &selfgcolor }, - { "color12", STRING, &selbgcolor }, - { "color8", STRING, &selhlcolor }, - { "prompt", STRING, &prompt }, -}; - diff --git a/.local/src/dmenu/config.mk b/.local/src/dmenu/config.mk @@ -1,35 +0,0 @@ -# dmenu version -VERSION = 5.1 - -# paths -PREFIX = /usr/local -MANPREFIX = $(PREFIX)/share/man - -X11INC = /usr/include -X11LIB = /usr/lib - -BDINC = /usr/include/fribidi - -# Xinerama, comment if you don't want it -XINERAMALIBS = -lXinerama -XINERAMAFLAGS = -DXINERAMA - -# freetype -FREETYPELIBS = -lfontconfig -lXft -FREETYPEINC = /usr/include/freetype2 -# OpenBSD (uncomment) -#FREETYPEINC = $(X11INC)/freetype2 - -BDLIBS = -lfribidi - -# includes and libs -INCS = -I$(X11INC) -I$(FREETYPEINC) -I$(BDINC) -LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) $(BDLIBS) -lXrender - -# flags -CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS) -CFLAGS = -std=c99 -pedantic -Wall -Os $(INCS) $(CPPFLAGS) -LDFLAGS = $(LIBS) - -# compiler and linker -CC = cc diff --git a/.local/src/dmenu/dmenu.1 b/.local/src/dmenu/dmenu.1 @@ -1,202 +0,0 @@ -.TH DMENU 1 dmenu\-VERSION -.SH NAME -dmenu \- dynamic menu -.SH SYNOPSIS -.B dmenu -.RB [ \-bfivP ] -.RB [ \-l -.IR lines ] -.RB [ \-m -.IR monitor ] -.RB [ \-p -.IR prompt ] -.RB [ \-fn -.IR font ] -.RB [ \-nb -.IR color ] -.RB [ \-nf -.IR color ] -.RB [ \-sb -.IR color ] -.RB [ \-sf -.IR color ] -.RB [ \-w -.IR windowid ] -.RB [ \-n -.IR number ] -.P -.BR dmenu_run " ..." -.SH DESCRIPTION -.B dmenu -is a dynamic menu for X, which reads a list of newline\-separated items from -stdin. When the user selects an item and presses Return, their choice is printed -to stdout and dmenu terminates. Entering text will narrow the items to those -matching the tokens in the input. -.P -.B dmenu_run -is a script used by -.IR dwm (1) -which lists programs in the user's $PATH and runs the result in their $SHELL. -.SH OPTIONS -.TP -.B \-b -dmenu appears at the bottom of the screen. -.TP -.B \-f -dmenu grabs the keyboard before reading stdin if not reading from a tty. This -is faster, but will lock up X until stdin reaches end\-of\-file. -.TP -.B \-i -dmenu matches menu items case insensitively. -.TP -.B \-P -dmenu will not directly display the keyboard input, but instead replace it with dots. All data from stdin will be ignored. -.TP -.BI \-l " lines" -dmenu lists items vertically, with the given number of lines. -.TP -.BI \-m " monitor" -dmenu is displayed on the monitor number supplied. Monitor numbers are starting -from 0. -.TP -.BI \-p " prompt" -defines the prompt to be displayed to the left of the input field. -.TP -.BI \-fn " font" -defines the font or font set used. -.TP -.BI \-nb " color" -defines the normal background color. -.IR #RGB , -.IR #RRGGBB , -and X color names are supported. -.TP -.BI \-nf " color" -defines the normal foreground color. -.TP -.BI \-sb " color" -defines the selected background color. -.TP -.BI \-sf " color" -defines the selected foreground color. -.TP -.B \-v -prints version information to stdout, then exits. -.TP -.BI \-w " windowid" -embed into windowid. -.TP -.BI \-n " number" -preseslected item starting from 0. -.SH USAGE -dmenu is completely controlled by the keyboard. Items are selected using the -arrow keys, page up, page down, home, and end. -.TP -.B Tab -Copy the selected item to the input field. -.TP -.B Return -Confirm selection. Prints the selected item to stdout and exits, returning -success. -.TP -.B Ctrl-Return -Confirm selection. Prints the selected item to stdout and continues. -.TP -.B Shift\-Return -Confirm input. Prints the input text to stdout and exits, returning success. -.TP -.B Escape -Exit without selecting an item, returning failure. -.TP -.B Ctrl-Left -Move cursor to the start of the current word -.TP -.B Ctrl-Right -Move cursor to the end of the current word -.TP -.B C\-a -Home -.TP -.B C\-b -Left -.TP -.B C\-c -Escape -.TP -.B C\-d -Delete -.TP -.B C\-e -End -.TP -.B C\-f -Right -.TP -.B C\-g -Escape -.TP -.B C\-h -Backspace -.TP -.B C\-i -Tab -.TP -.B C\-j -Return -.TP -.B C\-J -Shift-Return -.TP -.B C\-k -Delete line right -.TP -.B C\-m -Return -.TP -.B C\-M -Shift-Return -.TP -.B C\-n -Down -.TP -.B C\-p -Up -.TP -.B C\-u -Delete line left -.TP -.B C\-w -Delete word left -.TP -.B C\-y -Paste from primary X selection -.TP -.B C\-Y -Paste from X clipboard -.TP -.B M\-b -Move cursor to the start of the current word -.TP -.B M\-f -Move cursor to the end of the current word -.TP -.B M\-g -Home -.TP -.B M\-G -End -.TP -.B M\-h -Up -.TP -.B M\-j -Page down -.TP -.B M\-k -Page up -.TP -.B M\-l -Down -.SH SEE ALSO -.IR dwm (1), -.IR stest (1) diff --git a/.local/src/dmenu/dmenu.c b/.local/src/dmenu/dmenu.c @@ -1,1011 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <ctype.h> -#include <locale.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <strings.h> -#include <time.h> -#include <unistd.h> - -#include <X11/Xlib.h> -#include <X11/Xatom.h> -#include <X11/Xproto.h> -#include <X11/Xutil.h> -#include <X11/Xresource.h> -#ifdef XINERAMA -#include <X11/extensions/Xinerama.h> -#endif -#include <X11/Xft/Xft.h> - -#include <fribidi.h> - -#include "drw.h" -#include "util.h" - -/* macros */ -#define INTERSECT(x,y,w,h,r) (MAX(0, MIN((x)+(w),(r).x_org+(r).width) - MAX((x),(r).x_org)) \ - * MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org))) -#define LENGTH(X) (sizeof X / sizeof X[0]) -#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) - -#define OPAQUE 0xffU - -/* enums */ -enum { SchemeNorm, SchemeSel, SchemeOut, SchemeNormHighlight, SchemeSelHighlight, SchemeOutHighlight, SchemeLast }; /* color schemes */ -struct item { - char *text; - struct item *left, *right; - int out; -}; - -static char text[BUFSIZ] = ""; -static char fribidi_text[BUFSIZ] = ""; -static char *embed; -static int bh, mw, mh; -static int inputw = 0, promptw, passwd = 0; -static int lrpad; /* sum of left and right padding */ -static size_t cursor; -static struct item *items = NULL; -static struct item *matches, *matchend; -static struct item *prev, *curr, *next, *sel; -static int mon = -1, screen; - -static Atom clip, utf8; -static Display *dpy; -static Window root, parentwin, win; -static XIC xic; - -static Drw *drw; -static Clr *scheme[SchemeLast]; - -/* Xresources preferences */ -enum resource_type { - STRING = 0, - INTEGER = 1, - FLOAT = 2 -}; -typedef struct { - char *name; - enum resource_type type; - void *dst; -} ResourcePref; - -static void load_xresources(void); -static void resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst); - -static int useargb = 0; -static Visual *visual; -static int depth; -static Colormap cmap; - -#include "config.h" - -static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; -static char *(*fstrstr)(const char *, const char *) = strstr; -static void xinitvisual(); - -static unsigned int -textw_clamp(const char *str, unsigned int n) -{ - unsigned int w = drw_fontset_getwidth_clamp(drw, str, n) + lrpad; - return MIN(w, n); -} - -static void -appenditem(struct item *item, struct item **list, struct item **last) -{ - if (*last) - (*last)->right = item; - else - *list = item; - - item->left = *last; - item->right = NULL; - *last = item; -} - -static void -calcoffsets(void) -{ - int i, n; - - if (lines > 0) - n = lines * bh; - else - n = mw - (promptw + inputw + TEXTW("<") + TEXTW(">")); - /* calculate which items will begin the next page and previous page */ - for (i = 0, next = curr; next; next = next->right) - if ((i += (lines > 0) ? bh : textw_clamp(next->text, n)) > n) - break; - for (i = 0, prev = curr; prev && prev->left; prev = prev->left) - if ((i += (lines > 0) ? bh : textw_clamp(prev->left->text, n)) > n) - break; -} - -static void -cleanup(void) -{ - size_t i; - - XUngrabKey(dpy, AnyKey, AnyModifier, root); - for (i = 0; i < SchemeLast; i++) - free(scheme[i]); - for (i = 0; items && items[i].text; ++i) - free(items[i].text); - free(items); - drw_free(drw); - XSync(dpy, False); - XCloseDisplay(dpy); -} - -static char * -cistrstr(const char *h, const char *n) -{ - size_t i; - - if (!n[0]) - return (char *)h; - - for (; *h; ++h) { - for (i = 0; n[i] && tolower((unsigned char)n[i]) == - tolower((unsigned char)h[i]); ++i) - ; - if (n[i] == '\0') - return (char *)h; - } - return NULL; -} - -static void -drawhighlights(struct item *item, int x, int y, int maxw) -{ - char restorechar, tokens[sizeof text], *highlight, *token; - int indentx, highlightlen; - - drw_setscheme(drw, scheme[item == sel ? SchemeSelHighlight : item->out ? SchemeOutHighlight : SchemeNormHighlight]); - strcpy(tokens, text); - for (token = strtok(tokens, " "); token; token = strtok(NULL, " ")) { - highlight = fstrstr(item->text, token); - while (highlight) { - // Move item str end, calc width for highlight indent, & restore - highlightlen = highlight - item->text; - restorechar = *highlight; - item->text[highlightlen] = '\0'; - indentx = TEXTW(item->text); - item->text[highlightlen] = restorechar; - - // Move highlight str end, draw highlight, & restore - restorechar = highlight[strlen(token)]; - highlight[strlen(token)] = '\0'; - if (indentx - (lrpad / 2) - 1 < maxw) - drw_text( - drw, - x + indentx - (lrpad / 2) - 1, - y, - MIN(maxw - indentx, TEXTW(highlight) - lrpad), - bh, 0, highlight, 0 - ); - highlight[strlen(token)] = restorechar; - - if (strlen(highlight) - strlen(token) < strlen(token)) break; - highlight = fstrstr(highlight + strlen(token), token); - } - } -} - -static void -apply_fribidi(char *str) -{ - FriBidiStrIndex len = strlen(str); - FriBidiChar logical[BUFSIZ]; - FriBidiChar visual[BUFSIZ]; - FriBidiParType base = FRIBIDI_PAR_ON; - FriBidiCharSet charset; - fribidi_boolean result; - - fribidi_text[0] = 0; - if (len > 0) { - charset = fribidi_parse_charset("UTF-8"); - len = fribidi_charset_to_unicode(charset, str, len, logical); - result = fribidi_log2vis(logical, len, &base, visual, NULL, NULL, NULL); - len = fribidi_unicode_to_charset(charset, visual, len, fribidi_text); - } -} - -static int -drawitem(struct item *item, int x, int y, int w) -{ - if (item == sel) - drw_setscheme(drw, scheme[SchemeSel]); - else if (item->out) - drw_setscheme(drw, scheme[SchemeOut]); - else - drw_setscheme(drw, scheme[SchemeNorm]); - - apply_fribidi(item->text); - int r = drw_text(drw, x, y, w, bh, lrpad / 2, fribidi_text, 0); - drawhighlights(item, x, y, w); - return r; -} - -static void -drawmenu(void) -{ - unsigned int curpos; - struct item *item; - int x = 0, y = 0, w; - char *censort; - - drw_setscheme(drw, scheme[SchemeNorm]); - drw_rect(drw, 0, 0, mw, mh, 1, 1); - - if (prompt && *prompt) { - drw_setscheme(drw, scheme[SchemeSel]); - x = drw_text(drw, x, 0, promptw, bh, lrpad / 2, prompt, 0); - } - /* draw input field */ - w = (lines > 0 || !matches) ? mw - x : inputw; - drw_setscheme(drw, scheme[SchemeNorm]); - if (passwd) { - censort = ecalloc(1, sizeof(text)); - memset(censort, '.', strlen(text)); - drw_text(drw, x, 0, w, bh, lrpad / 2, censort, 0); - free(censort); - } else { - apply_fribidi(text); - drw_text(drw, x, 0, w, bh, lrpad / 2, fribidi_text, 0); - } - - curpos = TEXTW(text) - TEXTW(&text[cursor]); - if ((curpos += lrpad / 2 - 1) < w) { - drw_setscheme(drw, scheme[SchemeNorm]); - drw_rect(drw, x + curpos, 2, 2, bh - 4, 1, 0); - } - - if (lines > 0) { - /* draw vertical list */ - for (item = curr; item != next; item = item->right) - drawitem(item, x - promptw, y += bh, mw); - } else if (matches) { - /* draw horizontal list */ - x += inputw; - w = TEXTW("<"); - if (curr->left) { - drw_setscheme(drw, scheme[SchemeNorm]); - drw_text(drw, x, 0, w, bh, lrpad / 2, "<", 0); - } - x += w; - for (item = curr; item != next; item = item->right) - x = drawitem(item, x, 0, textw_clamp(item->text, mw - x - TEXTW(">"))); - if (next) { - w = TEXTW(">"); - drw_setscheme(drw, scheme[SchemeNorm]); - drw_text(drw, mw - w, 0, w, bh, lrpad / 2, ">", 0); - } - } - drw_map(drw, win, 0, 0, mw, mh); -} - -static void -grabfocus(void) -{ - struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 }; - Window focuswin; - int i, revertwin; - - for (i = 0; i < 100; ++i) { - XGetInputFocus(dpy, &focuswin, &revertwin); - if (focuswin == win) - return; - XSetInputFocus(dpy, win, RevertToParent, CurrentTime); - nanosleep(&ts, NULL); - } - die("cannot grab focus"); -} - -static void -grabkeyboard(void) -{ - struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 }; - int i; - - if (embed) - return; - /* try to grab keyboard, we may have to wait for another process to ungrab */ - for (i = 0; i < 1000; i++) { - if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabModeAsync, - GrabModeAsync, CurrentTime) == GrabSuccess) - return; - nanosleep(&ts, NULL); - } - die("cannot grab keyboard"); -} - -static void -match(void) -{ - static char **tokv = NULL; - static int tokn = 0; - - char buf[sizeof text], *s; - int i, tokc = 0; - size_t len, textsize; - struct item *item, *lprefix, *lsubstr, *prefixend, *substrend; - - strcpy(buf, text); - /* separate input text into tokens to be matched individually */ - for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NULL, " ")) - if (++tokc > tokn && !(tokv = realloc(tokv, ++tokn * sizeof *tokv))) - die("cannot realloc %zu bytes:", tokn * sizeof *tokv); - len = tokc ? strlen(tokv[0]) : 0; - - matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL; - textsize = strlen(text) + 1; - for (item = items; item && item->text; item++) { - for (i = 0; i < tokc; i++) - if (!fstrstr(item->text, tokv[i])) - break; - if (i != tokc) /* not all tokens match */ - continue; - /* exact matches go first, then prefixes, then substrings */ - if (!tokc || !fstrncmp(text, item->text, textsize)) - appenditem(item, &matches, &matchend); - else if (!fstrncmp(tokv[0], item->text, len)) - appenditem(item, &lprefix, &prefixend); - else - appenditem(item, &lsubstr, &substrend); - } - if (lprefix) { - if (matches) { - matchend->right = lprefix; - lprefix->left = matchend; - } else - matches = lprefix; - matchend = prefixend; - } - if (lsubstr) { - if (matches) { - matchend->right = lsubstr; - lsubstr->left = matchend; - } else - matches = lsubstr; - matchend = substrend; - } - curr = sel = matches; - calcoffsets(); -} - -static void -insert(const char *str, ssize_t n) -{ - if (strlen(text) + n > sizeof text - 1) - return; - /* move existing text out of the way, insert new text, and update cursor */ - memmove(&text[cursor + n], &text[cursor], sizeof text - cursor - MAX(n, 0)); - if (n > 0) - memcpy(&text[cursor], str, n); - cursor += n; - match(); -} - -static size_t -nextrune(int inc) -{ - ssize_t n; - - /* return location of next utf8 rune in the given direction (+1 or -1) */ - for (n = cursor + inc; n + inc >= 0 && (text[n] & 0xc0) == 0x80; n += inc) - ; - return n; -} - -static void -movewordedge(int dir) -{ - if (dir < 0) { /* move cursor to the start of the word*/ - while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)])) - cursor = nextrune(-1); - while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)])) - cursor = nextrune(-1); - } else { /* move cursor to the end of the word */ - while (text[cursor] && strchr(worddelimiters, text[cursor])) - cursor = nextrune(+1); - while (text[cursor] && !strchr(worddelimiters, text[cursor])) - cursor = nextrune(+1); - } -} - -static void -keypress(XKeyEvent *ev) -{ - char buf[32]; - int len; - KeySym ksym; - Status status; - - len = XmbLookupString(xic, ev, buf, sizeof buf, &ksym, &status); - switch (status) { - default: /* XLookupNone, XBufferOverflow */ - return; - case XLookupChars: - goto insert; - case XLookupKeySym: - case XLookupBoth: - break; - } - - if (ev->state & ControlMask) { - switch(ksym) { - case XK_a: ksym = XK_Home; break; - case XK_b: ksym = XK_Left; break; - case XK_c: ksym = XK_Escape; break; - case XK_d: ksym = XK_Delete; break; - case XK_e: ksym = XK_End; break; - case XK_f: ksym = XK_Right; break; - case XK_g: ksym = XK_Escape; break; - case XK_h: ksym = XK_BackSpace; break; - case XK_i: ksym = XK_Tab; break; - case XK_j: /* fallthrough */ - case XK_J: /* fallthrough */ - case XK_m: /* fallthrough */ - case XK_M: ksym = XK_Return; ev->state &= ~ControlMask; break; - case XK_n: ksym = XK_Down; break; - case XK_p: ksym = XK_Up; break; - - case XK_k: /* delete right */ - text[cursor] = '\0'; - match(); - break; - case XK_u: /* delete left */ - insert(NULL, 0 - cursor); - break; - case XK_w: /* delete word */ - while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)])) - insert(NULL, nextrune(-1) - cursor); - while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)])) - insert(NULL, nextrune(-1) - cursor); - break; - case XK_y: /* paste selection */ - XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY, - utf8, utf8, win, CurrentTime); - return; - case XK_Y: /* paste selection from clipboard */ - XConvertSelection(dpy, clip, utf8, utf8, win, CurrentTime); - return; - case XK_Left: - case XK_KP_Left: - movewordedge(-1); - goto draw; - case XK_Right: - case XK_KP_Right: - movewordedge(+1); - goto draw; - case XK_Return: - case XK_KP_Enter: - break; - case XK_bracketleft: - cleanup(); - exit(1); - default: - return; - } - } else if (ev->state & Mod1Mask) { - switch(ksym) { - case XK_b: - movewordedge(-1); - goto draw; - case XK_f: - movewordedge(+1); - goto draw; - case XK_g: ksym = XK_Home; break; - case XK_G: ksym = XK_End; break; - case XK_h: ksym = XK_Up; break; - case XK_j: ksym = XK_Next; break; - case XK_k: ksym = XK_Prior; break; - case XK_l: ksym = XK_Down; break; - default: - return; - } - } - - switch(ksym) { - default: - insert: - if (!iscntrl((unsigned char)*buf)) - insert(buf, len); - break; - case XK_Delete: - case XK_KP_Delete: - if (text[cursor] == '\0') - return; - cursor = nextrune(+1); - /* fallthrough */ - case XK_BackSpace: - if (cursor == 0) - return; - insert(NULL, nextrune(-1) - cursor); - break; - case XK_End: - case XK_KP_End: - if (text[cursor] != '\0') { - cursor = strlen(text); - break; - } - if (next) { - /* jump to end of list and position items in reverse */ - curr = matchend; - calcoffsets(); - curr = prev; - calcoffsets(); - while (next && (curr = curr->right)) - calcoffsets(); - } - sel = matchend; - break; - case XK_Escape: - cleanup(); - exit(1); - case XK_Home: - case XK_KP_Home: - if (sel == matches) { - cursor = 0; - break; - } - sel = curr = matches; - calcoffsets(); - break; - case XK_Left: - case XK_KP_Left: - if (cursor > 0 && (!sel || !sel->left || lines > 0)) { - cursor = nextrune(-1); - break; - } - if (lines > 0) - return; - /* fallthrough */ - case XK_Up: - case XK_KP_Up: - if (sel && sel->left && (sel = sel->left)->right == curr) { - curr = prev; - calcoffsets(); - } - break; - case XK_Next: - case XK_KP_Next: - if (!next) - return; - sel = curr = next; - calcoffsets(); - break; - case XK_Prior: - case XK_KP_Prior: - if (!prev) - return; - sel = curr = prev; - calcoffsets(); - break; - case XK_Return: - case XK_KP_Enter: - puts((sel && !(ev->state & ShiftMask)) ? sel->text : text); - if (!(ev->state & ControlMask)) { - cleanup(); - exit(0); - } - if (sel) - sel->out = 1; - break; - case XK_Right: - case XK_KP_Right: - if (text[cursor] != '\0') { - cursor = nextrune(+1); - break; - } - if (lines > 0) - return; - /* fallthrough */ - case XK_Down: - case XK_KP_Down: - if (sel && sel->right && (sel = sel->right) == next) { - curr = next; - calcoffsets(); - } - break; - case XK_Tab: - if (!sel) - return; - strncpy(text, sel->text, sizeof text - 1); - text[sizeof text - 1] = '\0'; - cursor = strlen(text); - match(); - break; - } - -draw: - drawmenu(); -} - -static void -paste(void) -{ - char *p, *q; - int di; - unsigned long dl; - Atom da; - - /* we have been given the current selection, now insert it into input */ - if (XGetWindowProperty(dpy, win, utf8, 0, (sizeof text / 4) + 1, False, - utf8, &da, &di, &dl, &dl, (unsigned char **)&p) - == Success && p) { - insert(p, (q = strchr(p, '\n')) ? q - p : (ssize_t)strlen(p)); - XFree(p); - } - drawmenu(); -} - -static void -readstdin(void) -{ - char buf[sizeof text], *p; - size_t i, size = 0; - if (passwd) { - inputw = lines = 0; - return; - } - - /* read each line from stdin and add it to the item list */ - for (i = 0; fgets(buf, sizeof buf, stdin); i++) { - if (i + 1 >= size / sizeof *items) - if (!(items = realloc(items, (size += BUFSIZ)))) - die("cannot realloc %zu bytes:", size); - if ((p = strchr(buf, '\n'))) - *p = '\0'; - if (!(items[i].text = strdup(buf))) - die("cannot strdup %zu bytes:", strlen(buf) + 1); - items[i].out = 0; - } - if (items) - items[i].text = NULL; - lines = MIN(lines, i); -} - -void -resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst) -{ - char *sdst = NULL; - int *idst = NULL; - float *fdst = NULL; - sdst = dst; - idst = dst; - fdst = dst; - char fullname[256]; - char *type; - XrmValue ret; - snprintf(fullname, sizeof(fullname), "%s.%s", "dmenu", name); - fullname[sizeof(fullname) - 1] = '\0'; - XrmGetResource(db, fullname, "*", &type, &ret); - if (!(ret.addr == NULL || strncmp("String", type, 64))) - { - switch (rtype) { - case STRING: - strcpy(sdst, ret.addr); - break; - case INTEGER: - *idst = strtoul(ret.addr, NULL, 10); - break; - case FLOAT: - *fdst = strtof(ret.addr, NULL); - break; - } - } -} - -void -load_xresources(void) -{ - Display *display; - char *resm; - XrmDatabase db; - ResourcePref *p; - display = XOpenDisplay(NULL); - resm = XResourceManagerString(display); - if (!resm) - return; - db = XrmGetStringDatabase(resm); - for (p = resources; p < resources + LENGTH(resources); p++) - resource_load(db, p->name, p->type, p->dst); - XCloseDisplay(display); -} - -static void -run(void) -{ - XEvent ev; - int i; - - while (!XNextEvent(dpy, &ev)) { - if (preselected) { - for (i = 0; i < preselected; i++) { - if (sel && sel->right && (sel = sel->right) == next) { - curr = next; - calcoffsets(); - } - } - drawmenu(); - preselected = 0; - } - if (XFilterEvent(&ev, win)) - continue; - switch(ev.type) { - case DestroyNotify: - if (ev.xdestroywindow.window != win) - break; - cleanup(); - exit(1); - case Expose: - if (ev.xexpose.count == 0) - drw_map(drw, win, 0, 0, mw, mh); - break; - case FocusIn: - /* regrab focus from parent window */ - if (ev.xfocus.window != win) - grabfocus(); - break; - case KeyPress: - keypress(&ev.xkey); - break; - case SelectionNotify: - if (ev.xselection.property == utf8) - paste(); - break; - case VisibilityNotify: - if (ev.xvisibility.state != VisibilityUnobscured) - XRaiseWindow(dpy, win); - break; - } - } -} - -static void -setup(void) -{ - int x, y, i, j; - unsigned int du, tmp; - XSetWindowAttributes swa; - XIM xim; - Window w, dw, *dws; - XWindowAttributes wa; - XClassHint ch = {"dmenu", "dmenu"}; - struct item *item; -#ifdef XINERAMA - XineramaScreenInfo *info; - Window pw; - int a, di, n, area = 0; -#endif - /* init appearance */ - for (j = 0; j < SchemeLast; j++) - scheme[j] = drw_scm_create(drw, colors[j], alphas[j], 2); - - clip = XInternAtom(dpy, "CLIPBOARD", False); - utf8 = XInternAtom(dpy, "UTF8_STRING", False); - - /* calculate menu geometry */ - bh = drw->fonts->h + 2; - lines = MAX(lines, 0); - mh = (lines + 1) * bh; -#ifdef XINERAMA - i = 0; - if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) { - XGetInputFocus(dpy, &w, &di); - if (mon >= 0 && mon < n) - i = mon; - else if (w != root && w != PointerRoot && w != None) { - /* find top-level window containing current input focus */ - do { - if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws) - XFree(dws); - } while (w != root && w != pw); - /* find xinerama screen with which the window intersects most */ - if (XGetWindowAttributes(dpy, pw, &wa)) - for (j = 0; j < n; j++) - if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) { - area = a; - i = j; - } - } - /* no focused window is on screen, so use pointer location instead */ - if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du)) - for (i = 0; i < n; i++) - if (INTERSECT(x, y, 1, 1, info[i]) != 0) - break; - - x = info[i].x_org; - y = info[i].y_org + (topbar ? 0 : info[i].height - mh); - mw = info[i].width; - - XFree(info); - } else -#endif - { - if (!XGetWindowAttributes(dpy, parentwin, &wa)) - die("could not get embedding window attributes: 0x%lx", - parentwin); - x = 0; - y = topbar ? 0 : wa.height - mh; - mw = wa.width; - } - promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; - for (item = items; item && item->text; ++item) { - if ((tmp = textw_clamp(item->text, mw/3)) > inputw) { - if ((inputw = tmp) == mw/3) - break; - } - } - match(); - - /* create menu window */ - swa.override_redirect = True; - swa.background_pixel = 0; - swa.border_pixel = 0; - swa.colormap = cmap; - swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; - win = XCreateWindow(dpy, parentwin, x, y, mw - border_width * 2, mh, border_width, - depth, CopyFromParent, visual, - CWOverrideRedirect | CWBackPixel | CWBorderPixel | CWColormap | CWEventMask, &swa); - if (border_width) - XSetWindowBorder(dpy, win, scheme[SchemeSel][ColBg].pixel); - XSetClassHint(dpy, win, &ch); - - - /* input methods */ - if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL) - die("XOpenIM failed: could not open input device"); - - xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, - XNClientWindow, win, XNFocusWindow, win, NULL); - - XMapRaised(dpy, win); - if (embed) { - XSelectInput(dpy, parentwin, FocusChangeMask | SubstructureNotifyMask); - if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) { - for (i = 0; i < du && dws[i] != win; ++i) - XSelectInput(dpy, dws[i], FocusChangeMask); - XFree(dws); - } - grabfocus(); - } - drw_resize(drw, mw, mh); - drawmenu(); -} - -static void -usage(void) -{ - fputs("usage: dmenu [-bfivP] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" - " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid] [-n number] [-bw number]\n", stderr); - exit(1); -} - -int -main(int argc, char *argv[]) -{ - XWindowAttributes wa; - int i, fast = 0; - - XrmInitialize(); - load_xresources(); - - for (i = 1; i < argc; i++) - /* these options take no arguments */ - if (!strcmp(argv[i], "-v")) { /* prints version information */ - puts("dmenu-"VERSION); - exit(0); - } else if (!strcmp(argv[i], "-b")) /* appears at the bottom of the screen */ - topbar = 0; - else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */ - fast = 1; - else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */ - fstrncmp = strncasecmp; - fstrstr = cistrstr; - } else if (!strcmp(argv[i], "-P")) /* is the input a password */ - passwd = 1; - else if (i + 1 == argc) - usage(); - /* these options take one argument */ - else if (!strcmp(argv[i], "-l")) /* number of lines in vertical list */ - lines = atoi(argv[++i]); - else if (!strcmp(argv[i], "-m")) - mon = atoi(argv[++i]); - else if (!strcmp(argv[i], "-p")) /* adds prompt to left of input field */ - prompt = argv[++i]; - else if (!strcmp(argv[i], "-fn")) /* font or font set */ - fonts[0] = argv[++i]; - else if (!strcmp(argv[i], "-nb")) /* normal background color */ - colors[SchemeNorm][ColBg] = argv[++i]; - else if (!strcmp(argv[i], "-nf")) /* normal foreground color */ - colors[SchemeNorm][ColFg] = argv[++i]; - else if (!strcmp(argv[i], "-sb")) /* selected background color */ - colors[SchemeSel][ColBg] = argv[++i]; - else if (!strcmp(argv[i], "-sf")) /* selected foreground color */ - colors[SchemeSel][ColFg] = argv[++i]; - else if (!strcmp(argv[i], "-w")) /* embedding window id */ - embed = argv[++i]; - else if (!strcmp(argv[i], "-n")) /* preselected item */ - preselected = atoi(argv[++i]); - else if (!strcmp(argv[i], "-bw")) - border_width = atoi(argv[++i]); /* border width */ - else - usage(); - - if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) - fputs("warning: no locale support\n", stderr); - if (!(dpy = XOpenDisplay(NULL))) - die("cannot open display"); - screen = DefaultScreen(dpy); - root = RootWindow(dpy, screen); - if (!embed || !(parentwin = strtol(embed, NULL, 0))) - parentwin = root; - if (!XGetWindowAttributes(dpy, parentwin, &wa)) - die("could not get embedding window attributes: 0x%lx", - parentwin); - xinitvisual(); - drw = drw_create(dpy, screen, root, wa.width, wa.height, visual, depth, cmap); - if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) - die("no fonts could be loaded."); - lrpad = drw->fonts->h; - -#ifdef __OpenBSD__ - if (pledge("stdio rpath", NULL) == -1) - die("pledge"); -#endif - - if (fast && !isatty(0)) { - grabkeyboard(); - readstdin(); - } else { - readstdin(); - grabkeyboard(); - } - setup(); - run(); - - return 1; /* unreachable */ -} - -void -xinitvisual() -{ - XVisualInfo *infos; - XRenderPictFormat *fmt; - int nitems; - int i; - - XVisualInfo tpl = { - .screen = screen, - .depth = 32, - .class = TrueColor - }; - long masks = VisualScreenMask | VisualDepthMask | VisualClassMask; - - infos = XGetVisualInfo(dpy, masks, &tpl, &nitems); - visual = NULL; - for(i = 0; i < nitems; i ++) { - fmt = XRenderFindVisualFormat(dpy, infos[i].visual); - if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) { - visual = infos[i].visual; - depth = infos[i].depth; - cmap = XCreateColormap(dpy, root, visual, AllocNone); - useargb = 1; - break; - } - } - - XFree(infos); - - if (! visual) { - visual = DefaultVisual(dpy, screen); - depth = DefaultDepth(dpy, screen); - cmap = DefaultColormap(dpy, screen); - } -} - diff --git a/.local/src/dmenu/dmenu_path b/.local/src/dmenu/dmenu_path @@ -1,13 +0,0 @@ -#!/bin/sh - -cachedir="${XDG_CACHE_HOME:-"$HOME/.cache"}" -cache="$cachedir/dmenu_run" - -[ ! -e "$cachedir" ] && mkdir -p "$cachedir" - -IFS=: -if stest -dqr -n "$cache" $PATH; then - stest -flx $PATH | sort -u | tee "$cache" -else - cat "$cache" -fi diff --git a/.local/src/dmenu/dmenu_run b/.local/src/dmenu/dmenu_run @@ -1,2 +0,0 @@ -#!/bin/sh -dmenu_path | dmenu "$@" | ${SHELL:-"/bin/sh"} & diff --git a/.local/src/dmenu/dmenu_run.hist b/.local/src/dmenu/dmenu_run.hist @@ -1,50 +0,0 @@ -#!/bin/sh - -cachedir=${XDG_CACHE_HOME:-"$HOME/.cache"} -if [ -d "$cachedir" ]; then - cache=$cachedir/dmenu_run - historyfile=$cachedir/dmenu_history -else # if no xdg dir, fall back to dotfiles in ~ - cache=$HOME/.dmenu_cache - historyfile=$HOME/.dmenu_history -fi - -IFS=: -if stest -dqr -n "$cache" $PATH; then - stest -flx $PATH | sort -u > "$cache" -fi -unset IFS - -awk -v histfile=$historyfile ' - BEGIN { - while( (getline < histfile) > 0 ) { - sub("^[0-9]+\t","") - print - x[$0]=1 - } - } !x[$0]++ ' "$cache" \ - | dmenu -i "$@" \ - | awk -v histfile=$historyfile ' - BEGIN { - FS=OFS="\t" - while ( (getline < histfile) > 0 ) { - count=$1 - sub("^[0-9]+\t","") - fname=$0 - history[fname]=count - } - close(histfile) - } - - { - history[$0]++ - print - } - - END { - if(!NR) exit - for (f in history) - print history[f],f | "sort -t '\t' -k1rn >" histfile - } - ' \ - | while read cmd; do ${SHELL:-"/bin/sh"} -c "$cmd" & done diff --git a/.local/src/dmenu/drw.c b/.local/src/dmenu/drw.c @@ -1,467 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <X11/Xlib.h> -#include <X11/Xft/Xft.h> - -#include "drw.h" -#include "util.h" - -#define UTF_INVALID 0xFFFD -#define UTF_SIZ 4 - -static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; -static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; -static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; -static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; - -static long -utf8decodebyte(const char c, size_t *i) -{ - for (*i = 0; *i < (UTF_SIZ + 1); ++(*i)) - if (((unsigned char)c & utfmask[*i]) == utfbyte[*i]) - return (unsigned char)c & ~utfmask[*i]; - return 0; -} - -static size_t -utf8validate(long *u, size_t i) -{ - if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) - *u = UTF_INVALID; - for (i = 1; *u > utfmax[i]; ++i) - ; - return i; -} - -static size_t -utf8decode(const char *c, long *u, size_t clen) -{ - size_t i, j, len, type; - long udecoded; - - *u = UTF_INVALID; - if (!clen) - return 0; - udecoded = utf8decodebyte(c[0], &len); - if (!BETWEEN(len, 1, UTF_SIZ)) - return 1; - for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { - udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); - if (type) - return j; - } - if (j < len) - return 0; - *u = udecoded; - utf8validate(u, len); - - return len; -} - -Drw * -drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h, Visual *visual, unsigned int depth, Colormap cmap) -{ - Drw *drw = ecalloc(1, sizeof(Drw)); - - drw->dpy = dpy; - drw->screen = screen; - drw->root = root; - drw->w = w; - drw->h = h; - drw->visual = visual; - drw->depth = depth; - drw->cmap = cmap; - drw->drawable = XCreatePixmap(dpy, root, w, h, depth); - drw->gc = XCreateGC(dpy, drw->drawable, 0, NULL); - XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); - - return drw; -} - -void -drw_resize(Drw *drw, unsigned int w, unsigned int h) -{ - if (!drw) - return; - - drw->w = w; - drw->h = h; - if (drw->drawable) - XFreePixmap(drw->dpy, drw->drawable); - drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, drw->depth); -} - -void -drw_free(Drw *drw) -{ - XFreePixmap(drw->dpy, drw->drawable); - XFreeGC(drw->dpy, drw->gc); - drw_fontset_free(drw->fonts); - free(drw); -} - -/* This function is an implementation detail. Library users should use - * drw_fontset_create instead. - */ -static Fnt * -xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) -{ - Fnt *font; - XftFont *xfont = NULL; - FcPattern *pattern = NULL; - - if (fontname) { - /* Using the pattern found at font->xfont->pattern does not yield the - * same substitution results as using the pattern returned by - * FcNameParse; using the latter results in the desired fallback - * behaviour whereas the former just results in missing-character - * rectangles being drawn, at least with some fonts. */ - if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) { - fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname); - return NULL; - } - if (!(pattern = FcNameParse((FcChar8 *) fontname))) { - fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname); - XftFontClose(drw->dpy, xfont); - return NULL; - } - } else if (fontpattern) { - if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { - fprintf(stderr, "error, cannot load font from pattern.\n"); - return NULL; - } - } else { - die("no font specified."); - } - - /* Do not allow using color fonts. This is a workaround for a BadLength - * error from Xft with color glyphs. Modelled on the Xterm workaround. See - * https://bugzilla.redhat.com/show_bug.cgi?id=1498269 - * https://lists.suckless.org/dev/1701/30932.html - * https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=916349 - * and lots more all over the internet. - */ - FcBool iscol; - if(FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) { - XftFontClose(drw->dpy, xfont); - return NULL; - } - - font = ecalloc(1, sizeof(Fnt)); - font->xfont = xfont; - font->pattern = pattern; - font->h = xfont->ascent + xfont->descent; - font->dpy = drw->dpy; - - return font; -} - -static void -xfont_free(Fnt *font) -{ - if (!font) - return; - if (font->pattern) - FcPatternDestroy(font->pattern); - XftFontClose(font->dpy, font->xfont); - free(font); -} - -Fnt* -drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) -{ - Fnt *cur, *ret = NULL; - size_t i; - - if (!drw || !fonts) - return NULL; - - for (i = 1; i <= fontcount; i++) { - if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) { - cur->next = ret; - ret = cur; - } - } - return (drw->fonts = ret); -} - -void -drw_fontset_free(Fnt *font) -{ - if (font) { - drw_fontset_free(font->next); - xfont_free(font); - } -} - -void -drw_clr_create(Drw *drw, Clr *dest, const char *clrname, unsigned int alpha) -{ - if (!drw || !dest || !clrname) - return; - - if (!XftColorAllocName(drw->dpy, drw->visual, drw->cmap, - clrname, dest)) - die("error, cannot allocate color '%s'", clrname); - - dest->pixel = (dest->pixel & 0x00ffffffU) | (alpha << 24); -} - -/* Wrapper to create color schemes. The caller has to call free(3) on the - * returned color scheme when done using it. */ -Clr * -drw_scm_create(Drw *drw, char *clrnames[], const unsigned int alphas[], size_t clrcount) -{ - size_t i; - Clr *ret; - - /* need at least two colors for a scheme */ - if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor)))) - return NULL; - - for (i = 0; i < clrcount; i++) - drw_clr_create(drw, &ret[i], clrnames[i], alphas[i]); - return ret; -} - -void -drw_setfontset(Drw *drw, Fnt *set) -{ - if (drw) - drw->fonts = set; -} - -void -drw_setscheme(Drw *drw, Clr *scm) -{ - if (drw) - drw->scheme = scm; -} - -void -drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) -{ - if (!drw || !drw->scheme) - return; - XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel); - if (filled) - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); - else - XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1); -} - -int -drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) -{ - int i, ty, ellipsis_x = 0; - unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len; - XftDraw *d = NULL; - Fnt *usedfont, *curfont, *nextfont; - int utf8strlen, utf8charlen, render = x || y || w || h; - long utf8codepoint = 0; - const char *utf8str; - FcCharSet *fccharset; - FcPattern *fcpattern; - FcPattern *match; - XftResult result; - int charexists = 0, overflow = 0; - /* keep track of a couple codepoints for which we have no match. */ - enum { nomatches_len = 64 }; - static struct { long codepoint[nomatches_len]; unsigned int idx; } nomatches; - static unsigned int ellipsis_width = 0; - - if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts) - return 0; - - if (!render) { - w = invert ? invert : ~invert; - } else { - XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); - d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap); - x += lpad; - w -= lpad; - } - - usedfont = drw->fonts; - if (!ellipsis_width && render) - ellipsis_width = drw_fontset_getwidth(drw, "..."); - while (1) { - ew = ellipsis_len = utf8strlen = 0; - utf8str = text; - nextfont = NULL; - while (*text) { - utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ); - for (curfont = drw->fonts; curfont; curfont = curfont->next) { - charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); - if (charexists) { - drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL); - if (ew + ellipsis_width <= w) { - /* keep track where the ellipsis still fits */ - ellipsis_x = x + ew; - ellipsis_w = w - ew; - ellipsis_len = utf8strlen; - } - - if (ew + tmpw > w) { - overflow = 1; - /* called from drw_fontset_getwidth_clamp(): - * it wants the width AFTER the overflow - */ - if (!render) - x += tmpw; - else - utf8strlen = ellipsis_len; - } else if (curfont == usedfont) { - utf8strlen += utf8charlen; - text += utf8charlen; - ew += tmpw; - } else { - nextfont = curfont; - } - break; - } - } - - if (overflow || !charexists || nextfont) - break; - else - charexists = 0; - } - - if (utf8strlen) { - if (render) { - ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; - XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], - usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen); - } - x += ew; - w -= ew; - } - if (render && overflow) - drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert); - - if (!*text || overflow) { - break; - } else if (nextfont) { - charexists = 0; - usedfont = nextfont; - } else { - /* Regardless of whether or not a fallback font is found, the - * character must be drawn. */ - charexists = 1; - - for (i = 0; i < nomatches_len; ++i) { - /* avoid calling XftFontMatch if we know we won't find a match */ - if (utf8codepoint == nomatches.codepoint[i]) - goto no_match; - } - - fccharset = FcCharSetCreate(); - FcCharSetAddChar(fccharset, utf8codepoint); - - if (!drw->fonts->pattern) { - /* Refer to the comment in xfont_create for more information. */ - die("the first font in the cache must be loaded from a font string."); - } - - fcpattern = FcPatternDuplicate(drw->fonts->pattern); - FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); - FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); - //FcPatternAddBool(fcpattern, FC_COLOR, FcFalse); - - FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); - FcDefaultSubstitute(fcpattern); - match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result); - - FcCharSetDestroy(fccharset); - FcPatternDestroy(fcpattern); - - if (match) { - usedfont = xfont_create(drw, NULL, match); - if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) { - for (curfont = drw->fonts; curfont->next; curfont = curfont->next) - ; /* NOP */ - curfont->next = usedfont; - } else { - xfont_free(usedfont); - nomatches.codepoint[++nomatches.idx % nomatches_len] = utf8codepoint; -no_match: - usedfont = drw->fonts; - } - } - } - } - if (d) - XftDrawDestroy(d); - - return x + (render ? w : 0); -} - -void -drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) -{ - if (!drw) - return; - - XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); - XSync(drw->dpy, False); -} - -unsigned int -drw_fontset_getwidth(Drw *drw, const char *text) -{ - if (!drw || !drw->fonts || !text) - return 0; - return drw_text(drw, 0, 0, 0, 0, 0, text, 0); -} - -unsigned int -drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n) -{ - unsigned int tmp = 0; - if (drw && drw->fonts && text && n) - tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n); - return MIN(n, tmp); -} - -void -drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) -{ - XGlyphInfo ext; - - if (!font || !text) - return; - - XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); - if (w) - *w = ext.xOff; - if (h) - *h = font->h; -} - -Cur * -drw_cur_create(Drw *drw, int shape) -{ - Cur *cur; - - if (!drw || !(cur = ecalloc(1, sizeof(Cur)))) - return NULL; - - cur->cursor = XCreateFontCursor(drw->dpy, shape); - - return cur; -} - -void -drw_cur_free(Drw *drw, Cur *cursor) -{ - if (!cursor) - return; - - XFreeCursor(drw->dpy, cursor->cursor); - free(cursor); -} - diff --git a/.local/src/dmenu/drw.h b/.local/src/dmenu/drw.h @@ -1,62 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -typedef struct { - Cursor cursor; -} Cur; - -typedef struct Fnt { - Display *dpy; - unsigned int h; - XftFont *xfont; - FcPattern *pattern; - struct Fnt *next; -} Fnt; - -enum { ColFg, ColBg }; /* Clr scheme index */ -typedef XftColor Clr; - -typedef struct { - unsigned int w, h; - Display *dpy; - int screen; - Window root; - Visual *visual; - unsigned int depth; - Colormap cmap; - Drawable drawable; - GC gc; - Clr *scheme; - Fnt *fonts; -} Drw; - -/* Drawable abstraction */ -Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h, Visual*, unsigned int, Colormap); -void drw_resize(Drw *drw, unsigned int w, unsigned int h); -void drw_free(Drw *drw); - -/* Fnt abstraction */ -Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); -void drw_fontset_free(Fnt* set); -unsigned int drw_fontset_getwidth(Drw *drw, const char *text); -unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n); -void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); - -/* Colorscheme abstraction */ -void drw_clr_create(Drw *drw, Clr *dest, const char *clrname, unsigned int alpha); -Clr *drw_scm_create(Drw *drw, char *clrnames[], const unsigned int alphas[], size_t clrcount); - -/* Cursor abstraction */ -Cur *drw_cur_create(Drw *drw, int shape); -void drw_cur_free(Drw *drw, Cur *cursor); - -/* Drawing context manipulation */ -void drw_setfontset(Drw *drw, Fnt *set); -void drw_setscheme(Drw *drw, Clr *scm); - -/* Drawing functions */ -void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); -int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); - -/* Map functions */ -void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); - diff --git a/.local/src/dmenu/patches/dmenu-alpha-20210605-1a13d04.diff b/.local/src/dmenu/patches/dmenu-alpha-20210605-1a13d04.diff @@ -1,267 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 1edb647..697d511 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -2,6 +2,7 @@ - /* Default settings; can be overriden by command line. */ - - static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ -+static const unsigned int alpha = 0xf0; - /* -fn option overrides fonts[0]; default X11 font or font set */ - static const char *fonts[] = { - "monospace:size=10" -@@ -13,6 +14,13 @@ static const char *colors[SchemeLast][2] = { - [SchemeSel] = { "#eeeeee", "#005577" }, - [SchemeOut] = { "#000000", "#00ffff" }, - }; -+ -+static const unsigned int alphas[SchemeLast][2] = { -+ [SchemeNorm] = { OPAQUE, alpha }, -+ [SchemeSel] = { OPAQUE, alpha }, -+ [SchemeOut] = { OPAQUE, alpha }, -+}; -+ - /* -l option; if nonzero, dmenu uses vertical list with given number of lines */ - static unsigned int lines = 0; - -diff --git a/dmenu.c b/dmenu.c -index 65f25ce..3e56e1a 100644 ---- a/dmenu.c -+++ b/dmenu.c -@@ -10,6 +10,7 @@ - - #include <X11/Xlib.h> - #include <X11/Xatom.h> -+#include <X11/Xproto.h> - #include <X11/Xutil.h> - #ifdef XINERAMA - #include <X11/extensions/Xinerama.h> -@@ -25,6 +26,8 @@ - #define LENGTH(X) (sizeof X / sizeof X[0]) - #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) - -+#define OPAQUE 0xffU -+ - /* enums */ - enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */ - -@@ -53,10 +56,16 @@ static XIC xic; - static Drw *drw; - static Clr *scheme[SchemeLast]; - -+static int useargb = 0; -+static Visual *visual; -+static int depth; -+static Colormap cmap; -+ - #include "config.h" - - static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; - static char *(*fstrstr)(const char *, const char *) = strstr; -+static void xinitvisual(); - - static void - appenditem(struct item *item, struct item **list, struct item **last) -@@ -602,7 +611,7 @@ setup(void) - #endif - /* init appearance */ - for (j = 0; j < SchemeLast; j++) -- scheme[j] = drw_scm_create(drw, colors[j], 2); -+ scheme[j] = drw_scm_create(drw, colors[j], alphas[i], 2); - - clip = XInternAtom(dpy, "CLIPBOARD", False); - utf8 = XInternAtom(dpy, "UTF8_STRING", False); -@@ -640,6 +649,7 @@ setup(void) - x = info[i].x_org; - y = info[i].y_org + (topbar ? 0 : info[i].height - mh); - mw = info[i].width; -+ - XFree(info); - } else - #endif -@@ -657,11 +667,13 @@ setup(void) - - /* create menu window */ - swa.override_redirect = True; -- swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; -+ swa.background_pixel = 0; -+ swa.border_pixel = 0; -+ swa.colormap = cmap; - swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; -- win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0, -- CopyFromParent, CopyFromParent, CopyFromParent, -- CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); -+ win = XCreateWindow(dpy, parentwin, x, y, mw, mh, border_width, -+ depth, CopyFromParent, visual, -+ CWOverrideRedirect | CWBackPixel | CWBorderPixel | CWColormap | CWEventMask, &swa); - XSetClassHint(dpy, win, &ch); - - -@@ -747,7 +759,8 @@ main(int argc, char *argv[]) - if (!XGetWindowAttributes(dpy, parentwin, &wa)) - die("could not get embedding window attributes: 0x%lx", - parentwin); -- drw = drw_create(dpy, screen, root, wa.width, wa.height); -+ xinitvisual(); -+ drw = drw_create(dpy, screen, root, wa.width, wa.height, visual, depth, cmap); - if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) - die("no fonts could be loaded."); - lrpad = drw->fonts->h; -@@ -769,3 +782,40 @@ main(int argc, char *argv[]) - - return 1; /* unreachable */ - } -+ -+ void -+xinitvisual() -+{ -+ XVisualInfo *infos; -+ XRenderPictFormat *fmt; -+ int nitems; -+ int i; -+ -+ XVisualInfo tpl = { -+ .screen = screen, -+ .depth = 32, -+ .class = TrueColor -+ }; -+ long masks = VisualScreenMask | VisualDepthMask | VisualClassMask; -+ -+ infos = XGetVisualInfo(dpy, masks, &tpl, &nitems); -+ visual = NULL; -+ for(i = 0; i < nitems; i ++) { -+ fmt = XRenderFindVisualFormat(dpy, infos[i].visual); -+ if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) { -+ visual = infos[i].visual; -+ depth = infos[i].depth; -+ cmap = XCreateColormap(dpy, root, visual, AllocNone); -+ useargb = 1; -+ break; -+ } -+ } -+ -+ XFree(infos); -+ -+ if (! visual) { -+ visual = DefaultVisual(dpy, screen); -+ depth = DefaultDepth(dpy, screen); -+ cmap = DefaultColormap(dpy, screen); -+ } -+} -diff --git a/drw.c b/drw.c -index 4cdbcbe..fe3aadd 100644 ---- a/drw.c -+++ b/drw.c -@@ -61,7 +61,7 @@ utf8decode(const char *c, long *u, size_t clen) - } - - Drw * --drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) -+drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h, Visual *visual, unsigned int depth, Colormap cmap) - { - Drw *drw = ecalloc(1, sizeof(Drw)); - -@@ -70,8 +70,11 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h - drw->root = root; - drw->w = w; - drw->h = h; -- drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); -- drw->gc = XCreateGC(dpy, root, 0, NULL); -+ drw->visual = visual; -+ drw->depth = depth; -+ drw->cmap = cmap; -+ drw->drawable = XCreatePixmap(dpy, root, w, h, depth); -+ drw->gc = XCreateGC(dpy, drw->drawable, 0, NULL); - XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); - - return drw; -@@ -87,7 +90,7 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h) - drw->h = h; - if (drw->drawable) - XFreePixmap(drw->dpy, drw->drawable); -- drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); -+ drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, drw->depth); - } - - void -@@ -194,21 +197,22 @@ drw_fontset_free(Fnt *font) - } - - void --drw_clr_create(Drw *drw, Clr *dest, const char *clrname) -+drw_clr_create(Drw *drw, Clr *dest, const char *clrname, unsigned int alpha) - { - if (!drw || !dest || !clrname) - return; - -- if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), -- DefaultColormap(drw->dpy, drw->screen), -+ if (!XftColorAllocName(drw->dpy, drw->visual, drw->cmap, - clrname, dest)) - die("error, cannot allocate color '%s'", clrname); -+ -+ dest->pixel = (dest->pixel & 0x00ffffffU) | (alpha << 24); - } - - /* Wrapper to create color schemes. The caller has to call free(3) on the - * returned color scheme when done using it. */ - Clr * --drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) -+drw_scm_create(Drw *drw, const char *clrnames[], const unsigned int alphas[], size_t clrcount) - { - size_t i; - Clr *ret; -@@ -218,7 +222,7 @@ drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) - return NULL; - - for (i = 0; i < clrcount; i++) -- drw_clr_create(drw, &ret[i], clrnames[i]); -+ drw_clr_create(drw, &ret[i], clrnames[i], alphas[i]); - return ret; - } - -@@ -274,9 +278,7 @@ 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); -- d = XftDrawCreate(drw->dpy, drw->drawable, -- DefaultVisual(drw->dpy, drw->screen), -- DefaultColormap(drw->dpy, drw->screen)); -+ d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap); - x += lpad; - w -= lpad; - } -diff --git a/drw.h b/drw.h -index 4c67419..f6fa5cd 100644 ---- a/drw.h -+++ b/drw.h -@@ -20,6 +20,9 @@ typedef struct { - Display *dpy; - int screen; - Window root; -+ Visual *visual; -+ unsigned int depth; -+ Colormap cmap; - Drawable drawable; - GC gc; - Clr *scheme; -@@ -27,7 +30,7 @@ typedef struct { - } Drw; - - /* Drawable abstraction */ --Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); -+Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h, Visual*, unsigned int, Colormap); - void drw_resize(Drw *drw, unsigned int w, unsigned int h); - void drw_free(Drw *drw); - -@@ -38,8 +41,8 @@ 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); - - /* 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, unsigned int alpha); -+Clr *drw_scm_create(Drw *drw, const char *clrnames[], const unsigned int alphas[], size_t clrcount); - - /* Cursor abstraction */ - Cur *drw_cur_create(Drw *drw, int shape); diff --git a/.local/src/dmenu/patches/dmenu-bidi-20210723-b34d318.diff b/.local/src/dmenu/patches/dmenu-bidi-20210723-b34d318.diff @@ -1,109 +0,0 @@ -From b34d318bfed8557f2a1e53fc523b8ecff7c79374 Mon Sep 17 00:00:00 2001 -From: Eyal Seelig <eyal.seelig@gmail.com> -Date: Fri, 23 Jul 2021 18:31:11 +0300 -Subject: [PATCH] Added support for RTL languages, such as Hebrew, Arabic, and - Farsi, using the FriBiDi library - ---- - config.mk | 8 ++++++-- - dmenu.c | 29 +++++++++++++++++++++++++++-- - 2 files changed, 33 insertions(+), 4 deletions(-) - -diff --git a/config.mk b/config.mk -index 05d5a3e..eefd0ae 100644 ---- a/config.mk -+++ b/config.mk -@@ -8,6 +8,8 @@ MANPREFIX = $(PREFIX)/share/man - X11INC = /usr/X11R6/include - X11LIB = /usr/X11R6/lib - -+BDINC = /usr/include/fribidi -+ - # Xinerama, comment if you don't want it - XINERAMALIBS = -lXinerama - XINERAMAFLAGS = -DXINERAMA -@@ -18,9 +20,11 @@ FREETYPEINC = /usr/include/freetype2 - # OpenBSD (uncomment) - #FREETYPEINC = $(X11INC)/freetype2 - -+BDLIBS = -lfribidi -+ - # includes and libs --INCS = -I$(X11INC) -I$(FREETYPEINC) --LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) -+INCS = -I$(X11INC) -I$(FREETYPEINC) -I$(BDINC) -+LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) $(BDLIBS) - - # flags - CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS) -diff --git a/dmenu.c b/dmenu.c -index 65f25ce..389916b 100644 ---- a/dmenu.c -+++ b/dmenu.c -@@ -16,6 +16,8 @@ - #endif - #include <X11/Xft/Xft.h> - -+#include <fribidi.h> -+ - #include "drw.h" - #include "util.h" - -@@ -35,6 +37,7 @@ struct item { - }; - - static char text[BUFSIZ] = ""; -+static char fribidi_text[BUFSIZ] = ""; - static char *embed; - static int bh, mw, mh; - static int inputw = 0, promptw; -@@ -113,6 +116,26 @@ cistrstr(const char *s, const char *sub) - return NULL; - } - -+static void -+apply_fribidi(char *str) -+{ -+ FriBidiStrIndex len = strlen(str); -+ FriBidiChar logical[BUFSIZ]; -+ FriBidiChar visual[BUFSIZ]; -+ FriBidiParType base = FRIBIDI_PAR_ON; -+ FriBidiCharSet charset; -+ fribidi_boolean result; -+ -+ fribidi_text[0] = 0; -+ if (len>0) -+ { -+ charset = fribidi_parse_charset("UTF-8"); -+ len = fribidi_charset_to_unicode(charset, str, len, logical); -+ result = fribidi_log2vis(logical, len, &base, visual, NULL, NULL, NULL); -+ len = fribidi_unicode_to_charset(charset, visual, len, fribidi_text); -+ } -+} -+ - static int - drawitem(struct item *item, int x, int y, int w) - { -@@ -123,7 +146,8 @@ drawitem(struct item *item, int x, int y, int w) - else - drw_setscheme(drw, scheme[SchemeNorm]); - -- return drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0); -+ apply_fribidi(item->text); -+ return drw_text(drw, x, y, w, bh, lrpad / 2, fribidi_text, 0); - } - - static void -@@ -143,7 +167,8 @@ drawmenu(void) - /* draw input field */ - w = (lines > 0 || !matches) ? mw - x : inputw; - drw_setscheme(drw, scheme[SchemeNorm]); -- drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0); -+ apply_fribidi(text); -+ drw_text(drw, x, 0, w, bh, lrpad / 2, fribidi_text, 0); - - curpos = TEXTW(text) - TEXTW(&text[cursor]); - if ((curpos += lrpad / 2 - 1) < w) { --- -2.32.0 - diff --git a/.local/src/dmenu/patches/dmenu-highlight-20201211-fcdc159.diff b/.local/src/dmenu/patches/dmenu-highlight-20201211-fcdc159.diff @@ -1,97 +0,0 @@ -From fcdc1593ed418166f20b7e691a49b1e6eefc116e Mon Sep 17 00:00:00 2001 -From: Nathaniel Evan <nathanielevan@zohomail.com> -Date: Fri, 11 Dec 2020 11:08:12 +0700 -Subject: [PATCH] Highlight matched text in a different color scheme - ---- - config.def.h | 3 +++ - dmenu.c | 44 +++++++++++++++++++++++++++++++++++++++++--- - 2 files changed, 44 insertions(+), 3 deletions(-) - -diff --git a/config.def.h b/config.def.h -index 1edb647..79be73a 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -11,7 +11,10 @@ static const char *colors[SchemeLast][2] = { - /* fg bg */ - [SchemeNorm] = { "#bbbbbb", "#222222" }, - [SchemeSel] = { "#eeeeee", "#005577" }, -+ [SchemeSelHighlight] = { "#ffc978", "#005577" }, -+ [SchemeNormHighlight] = { "#ffc978", "#222222" }, - [SchemeOut] = { "#000000", "#00ffff" }, -+ [SchemeOutHighlight] = { "#ffc978", "#00ffff" }, - }; - /* -l option; if nonzero, dmenu uses vertical list with given number of lines */ - static unsigned int lines = 0; -diff --git a/dmenu.c b/dmenu.c -index 65f25ce..cce1ad1 100644 ---- a/dmenu.c -+++ b/dmenu.c -@@ -26,8 +26,7 @@ - #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) - - /* enums */ --enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */ -- -+enum { SchemeNorm, SchemeSel, SchemeOut, SchemeNormHighlight, SchemeSelHighlight, SchemeOutHighlight, SchemeLast }; /* color schemes */ - struct item { - char *text; - struct item *left, *right; -@@ -113,6 +112,43 @@ cistrstr(const char *s, const char *sub) - return NULL; - } - -+static void -+drawhighlights(struct item *item, int x, int y, int maxw) -+{ -+ char restorechar, tokens[sizeof text], *highlight, *token; -+ int indentx, highlightlen; -+ -+ drw_setscheme(drw, scheme[item == sel ? SchemeSelHighlight : item->out ? SchemeOutHighlight : SchemeNormHighlight]); -+ strcpy(tokens, text); -+ for (token = strtok(tokens, " "); token; token = strtok(NULL, " ")) { -+ highlight = fstrstr(item->text, token); -+ while (highlight) { -+ // Move item str end, calc width for highlight indent, & restore -+ highlightlen = highlight - item->text; -+ restorechar = *highlight; -+ item->text[highlightlen] = '\0'; -+ indentx = TEXTW(item->text); -+ item->text[highlightlen] = restorechar; -+ -+ // Move highlight str end, draw highlight, & restore -+ restorechar = highlight[strlen(token)]; -+ highlight[strlen(token)] = '\0'; -+ if (indentx - (lrpad / 2) - 1 < maxw) -+ drw_text( -+ drw, -+ x + indentx - (lrpad / 2) - 1, -+ y, -+ MIN(maxw - indentx, TEXTW(highlight) - lrpad), -+ bh, 0, highlight, 0 -+ ); -+ highlight[strlen(token)] = restorechar; -+ -+ if (strlen(highlight) - strlen(token) < strlen(token)) break; -+ highlight = fstrstr(highlight + strlen(token), token); -+ } -+ } -+} -+ - static int - drawitem(struct item *item, int x, int y, int w) - { -@@ -123,7 +159,9 @@ drawitem(struct item *item, int x, int y, int w) - else - drw_setscheme(drw, scheme[SchemeNorm]); - -- return drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0); -+ int r = drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0); -+ drawhighlights(item, x, y, w); -+ return r; - } - - static void --- -2.29.2 - diff --git a/.local/src/dmenu/patches/dmenu-linesbelowprompt-and-fullwidth-20211014.diff b/.local/src/dmenu/patches/dmenu-linesbelowprompt-and-fullwidth-20211014.diff @@ -1,25 +0,0 @@ -From 98e63311c4816fb3c7f5c5d00232fec3232465f3 Mon Sep 17 00:00:00 2001 -From: Sebastian LaVine <mail@smlavine.com> -Date: Sat, 3 Jul 2021 17:35:50 -0400 -Subject: [PATCH] Draw lines immediately below prompt - ---- - dmenu.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/dmenu.c b/dmenu.c -index 65f25ce..5a041a6 100644 ---- a/dmenu.c -+++ b/dmenu.c -@@ -154,7 +154,7 @@ drawmenu(void) - if (lines > 0) { - /* draw vertical list */ - for (item = curr; item != next; item = item->right) -- drawitem(item, x, y += bh, mw - x); -+ drawitem(item, x - promptw, y += bh, mw); - } else if (matches) { - /* draw horizontal list */ - x += inputw; --- -2.32.0 - diff --git a/.local/src/dmenu/patches/dmenu-password-5.0.diff b/.local/src/dmenu/patches/dmenu-password-5.0.diff @@ -1,103 +0,0 @@ -From c4de1032bd4c247bc20b6ab92a10a8d778966679 Mon Sep 17 00:00:00 2001 -From: Mehrad Mahmoudian <m.mahmoudian@gmail.com> -Date: Tue, 4 May 2021 12:05:09 +0300 -Subject: [PATCH] patched with password patch - ---- - dmenu.1 | 5 ++++- - dmenu.c | 21 +++++++++++++++++---- - 2 files changed, 21 insertions(+), 5 deletions(-) - -diff --git a/dmenu.1 b/dmenu.1 -index 323f93c..762f707 100644 ---- a/dmenu.1 -+++ b/dmenu.1 -@@ -3,7 +3,7 @@ - dmenu \- dynamic menu - .SH SYNOPSIS - .B dmenu --.RB [ \-bfiv ] -+.RB [ \-bfivP ] - .RB [ \-l - .IR lines ] - .RB [ \-m -@@ -47,6 +47,9 @@ is faster, but will lock up X until stdin reaches end\-of\-file. - .B \-i - dmenu matches menu items case insensitively. - .TP -+.B \-P -+dmenu will not directly display the keyboard input, but instead replace it with dots. All data from stdin will be ignored. -+.TP - .BI \-l " lines" - dmenu lists items vertically, with the given number of lines. - .TP -diff --git a/dmenu.c b/dmenu.c -index 65f25ce..ad8f63b 100644 ---- a/dmenu.c -+++ b/dmenu.c -@@ -37,7 +37,7 @@ struct item { - static char text[BUFSIZ] = ""; - static char *embed; - static int bh, mw, mh; --static int inputw = 0, promptw; -+static int inputw = 0, promptw, passwd = 0; - static int lrpad; /* sum of left and right padding */ - static size_t cursor; - static struct item *items = NULL; -@@ -132,6 +132,7 @@ drawmenu(void) - unsigned int curpos; - struct item *item; - int x = 0, y = 0, w; -+ char *censort; - - drw_setscheme(drw, scheme[SchemeNorm]); - drw_rect(drw, 0, 0, mw, mh, 1, 1); -@@ -143,7 +144,12 @@ drawmenu(void) - /* draw input field */ - w = (lines > 0 || !matches) ? mw - x : inputw; - drw_setscheme(drw, scheme[SchemeNorm]); -- drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0); -+ if (passwd) { -+ censort = ecalloc(1, sizeof(text)); -+ memset(censort, '.', strlen(text)); -+ drw_text(drw, x, 0, w, bh, lrpad / 2, censort, 0); -+ free(censort); -+ } else drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0); - - curpos = TEXTW(text) - TEXTW(&text[cursor]); - if ((curpos += lrpad / 2 - 1) < w) { -@@ -524,6 +530,11 @@ readstdin(void) - char buf[sizeof text], *p; - size_t i, imax = 0, size = 0; - unsigned int tmpmax = 0; -+ if(passwd){ -+ inputw = lines = 0; -+ return; -+ } -+ - - /* read each line from stdin and add it to the item list */ - for (i = 0; fgets(buf, sizeof buf, stdin); i++) { -@@ -689,7 +700,7 @@ setup(void) - static void - usage(void) - { -- fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" -+ fputs("usage: dmenu [-bfivP] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" - " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr); - exit(1); - } -@@ -712,7 +723,9 @@ main(int argc, char *argv[]) - else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */ - fstrncmp = strncasecmp; - fstrstr = cistrstr; -- } else if (i + 1 == argc) -+ } else if (!strcmp(argv[i], "-P")) /* is the input a password */ -+ passwd = 1; -+ else if (i + 1 == argc) - usage(); - /* these options take one argument */ - else if (!strcmp(argv[i], "-l")) /* number of lines in vertical list */ --- -2.31.1 - diff --git a/.local/src/dmenu/patches/dmenu-preselect-20200513-db6093f.diff b/.local/src/dmenu/patches/dmenu-preselect-20200513-db6093f.diff @@ -1,90 +0,0 @@ -From 055e86dee88c5135b3d3a691942a915334d1b3a2 Mon Sep 17 00:00:00 2001 -From: Mathieu Moneyron <mathieu.moneyron@gmail.com> -Date: Wed, 13 May 2020 17:28:37 +0200 -Subject: [PATCH] Added option to preselect an item by providing a number - ---- - config.def.h | 3 +++ - dmenu.1 | 5 +++++ - dmenu.c | 15 ++++++++++++++- - 3 files changed, 22 insertions(+), 1 deletion(-) - -diff --git a/config.def.h b/config.def.h -index 1edb647..95bee59 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -21,3 +21,6 @@ static unsigned int lines = 0; - * for example: " /?\"&[]" - */ - static const char worddelimiters[] = " "; -+ -+/* -n option; preselected item starting from 0 */ -+static unsigned int preselected = 0; -diff --git a/dmenu.1 b/dmenu.1 -index 323f93c..6e1ee7f 100644 ---- a/dmenu.1 -+++ b/dmenu.1 -@@ -22,6 +22,8 @@ dmenu \- dynamic menu - .IR color ] - .RB [ \-w - .IR windowid ] -+.RB [ \-n -+.IR number ] - .P - .BR dmenu_run " ..." - .SH DESCRIPTION -@@ -80,6 +82,9 @@ prints version information to stdout, then exits. - .TP - .BI \-w " windowid" - embed into windowid. -+.TP -+.BI \-n " number" -+preseslected item starting from 0. - .SH USAGE - dmenu is completely controlled by the keyboard. Items are selected using the - arrow keys, page up, page down, home, and end. -diff --git a/dmenu.c b/dmenu.c -index 65f25ce..0a02609 100644 ---- a/dmenu.c -+++ b/dmenu.c -@@ -551,8 +551,19 @@ static void - run(void) - { - XEvent ev; -+ int i; - - while (!XNextEvent(dpy, &ev)) { -+ if (preselected) { -+ for (i = 0; i < preselected; i++) { -+ if (sel && sel->right && (sel = sel->right) == next) { -+ curr = next; -+ calcoffsets(); -+ } -+ } -+ drawmenu(); -+ preselected = 0; -+ } - if (XFilterEvent(&ev, win)) - continue; - switch(ev.type) { -@@ -690,7 +701,7 @@ static void - usage(void) - { - fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" -- " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr); -+ " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid] [-n number]\n", stderr); - exit(1); - } - -@@ -733,6 +744,8 @@ main(int argc, char *argv[]) - colors[SchemeSel][ColFg] = argv[++i]; - else if (!strcmp(argv[i], "-w")) /* embedding window id */ - embed = argv[++i]; -+ else if (!strcmp(argv[i], "-n")) /* preselected item */ -+ preselected = atoi(argv[++i]); - else - usage(); - --- -2.26.2 - diff --git a/.local/src/dmenu/patches/dmenu-xresources-alt-5.0.diff b/.local/src/dmenu/patches/dmenu-xresources-alt-5.0.diff @@ -1,182 +0,0 @@ -diff -rupN orig/config.def.h patched/config.def.h ---- orig/config.def.h 2021-04-16 06:30:47.713924755 +0300 -+++ patched/config.def.h 2021-04-16 06:34:14.956933252 +0300 -@@ -2,16 +2,25 @@ - /* Default settings; can be overriden by command line. */ - - static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ -+ - /* -fn option overrides fonts[0]; default X11 font or font set */ -+static char font[] = "monospace:size=10"; - static const char *fonts[] = { -- "monospace:size=10" -+ font, -+ "monospace:size=10", - }; --static const char *prompt = NULL; /* -p option; prompt to the left of input field */ --static const char *colors[SchemeLast][2] = { -+ -+static char *prompt = NULL; /* -p option; prompt to the left of input field */ -+ -+static char normfgcolor[] = "#bbbbbb"; -+static char normbgcolor[] = "#222222"; -+static char selfgcolor[] = "#eeeeee"; -+static char selbgcolor[] = "#005577"; -+static char *colors[SchemeLast][2] = { - /* fg bg */ -- [SchemeNorm] = { "#bbbbbb", "#222222" }, -- [SchemeSel] = { "#eeeeee", "#005577" }, -- [SchemeOut] = { "#000000", "#00ffff" }, -+ [SchemeNorm] = { normfgcolor, normbgcolor }, -+ [SchemeSel] = { selfgcolor, selbgcolor }, -+ [SchemeOut] = { "#000000", "#00ffff" }, - }; - /* -l option; if nonzero, dmenu uses vertical list with given number of lines */ - static unsigned int lines = 0; -@@ -21,3 +30,15 @@ static unsigned int lines = 0; - * for example: " /?\"&[]" - */ - static const char worddelimiters[] = " "; -+ -+/* -+ * Xresources preferences to load at startup -+ */ -+ResourcePref resources[] = { -+ { "font", STRING, &font }, -+ { "normfgcolor", STRING, &normfgcolor }, -+ { "normbgcolor", STRING, &normbgcolor }, -+ { "selfgcolor", STRING, &selfgcolor }, -+ { "selbgcolor", STRING, &selbgcolor }, -+ { "prompt", STRING, &prompt }, -+}; -diff -rupN orig/dmenu.c patched/dmenu.c ---- orig/dmenu.c 2021-04-16 06:30:47.715924755 +0300 -+++ patched/dmenu.c 2021-04-16 06:30:59.668925245 +0300 -@@ -11,6 +11,7 @@ - #include <X11/Xlib.h> - #include <X11/Xatom.h> - #include <X11/Xutil.h> -+#include <X11/Xresource.h> - #ifdef XINERAMA - #include <X11/extensions/Xinerama.h> - #endif -@@ -53,6 +54,21 @@ static XIC xic; - static Drw *drw; - static Clr *scheme[SchemeLast]; - -+/* Xresources preferences */ -+enum resource_type { -+ STRING = 0, -+ INTEGER = 1, -+ FLOAT = 2 -+}; -+typedef struct { -+ char *name; -+ enum resource_type type; -+ void *dst; -+} ResourcePref; -+ -+static void load_xresources(void); -+static void resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst); -+ - #include "config.h" - - static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; -@@ -395,7 +411,7 @@ keypress(XKeyEvent *ev) - - switch(ksym) { - default: --insert: -+ insert: - if (!iscntrl(*buf)) - insert(buf, len); - break; -@@ -547,6 +563,54 @@ readstdin(void) - lines = MIN(lines, i); - } - -+void -+resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst) -+{ -+ char *sdst = NULL; -+ int *idst = NULL; -+ float *fdst = NULL; -+ sdst = dst; -+ idst = dst; -+ fdst = dst; -+ char fullname[256]; -+ char *type; -+ XrmValue ret; -+ snprintf(fullname, sizeof(fullname), "%s.%s", "dmenu", name); -+ fullname[sizeof(fullname) - 1] = '\0'; -+ XrmGetResource(db, fullname, "*", &type, &ret); -+ if (!(ret.addr == NULL || strncmp("String", type, 64))) -+ { -+ switch (rtype) { -+ case STRING: -+ strcpy(sdst, ret.addr); -+ break; -+ case INTEGER: -+ *idst = strtoul(ret.addr, NULL, 10); -+ break; -+ case FLOAT: -+ *fdst = strtof(ret.addr, NULL); -+ break; -+ } -+ } -+} -+ -+void -+load_xresources(void) -+{ -+ Display *display; -+ char *resm; -+ XrmDatabase db; -+ ResourcePref *p; -+ display = XOpenDisplay(NULL); -+ resm = XResourceManagerString(display); -+ if (!resm) -+ return; -+ db = XrmGetStringDatabase(resm); -+ for (p = resources; p < resources + LENGTH(resources); p++) -+ resource_load(db, p->name, p->type, p->dst); -+ XCloseDisplay(display); -+} -+ - static void - run(void) - { -@@ -700,6 +764,9 @@ main(int argc, char *argv[]) - XWindowAttributes wa; - int i, fast = 0; - -+ XrmInitialize(); -+ load_xresources(); -+ - for (i = 1; i < argc; i++) - /* these options take no arguments */ - if (!strcmp(argv[i], "-v")) { /* prints version information */ -diff -rupN orig/drw.c patched/drw.c ---- orig/drw.c 2021-04-16 06:30:47.718924755 +0300 -+++ patched/drw.c 2021-04-16 06:30:59.670925245 +0300 -@@ -208,7 +208,7 @@ drw_clr_create(Drw *drw, Clr *dest, cons - /* 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[], size_t clrcount) - { - size_t i; - Clr *ret; -diff -rupN orig/drw.h patched/drw.h ---- orig/drw.h 2021-04-16 06:30:47.718924755 +0300 -+++ patched/drw.h 2021-04-16 06:30:59.671925245 +0300 -@@ -39,7 +39,7 @@ void drw_font_getexts(Fnt *font, const c - - /* 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); -+Clr *drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount); - - /* Cursor abstraction */ - Cur *drw_cur_create(Drw *drw, int shape); diff --git a/.local/src/dmenu/stest.1 b/.local/src/dmenu/stest.1 @@ -1,90 +0,0 @@ -.TH STEST 1 dmenu\-VERSION -.SH NAME -stest \- filter a list of files by properties -.SH SYNOPSIS -.B stest -.RB [ -abcdefghlpqrsuwx ] -.RB [ -n -.IR file ] -.RB [ -o -.IR file ] -.RI [ file ...] -.SH DESCRIPTION -.B stest -takes a list of files and filters by the files' properties, analogous to -.IR test (1). -Files which pass all tests are printed to stdout. If no files are given, stest -reads files from stdin. -.SH OPTIONS -.TP -.B \-a -Test hidden files. -.TP -.B \-b -Test that files are block specials. -.TP -.B \-c -Test that files are character specials. -.TP -.B \-d -Test that files are directories. -.TP -.B \-e -Test that files exist. -.TP -.B \-f -Test that files are regular files. -.TP -.B \-g -Test that files have their set-group-ID flag set. -.TP -.B \-h -Test that files are symbolic links. -.TP -.B \-l -Test the contents of a directory given as an argument. -.TP -.BI \-n " file" -Test that files are newer than -.IR file . -.TP -.BI \-o " file" -Test that files are older than -.IR file . -.TP -.B \-p -Test that files are named pipes. -.TP -.B \-q -No files are printed, only the exit status is returned. -.TP -.B \-r -Test that files are readable. -.TP -.B \-s -Test that files are not empty. -.TP -.B \-u -Test that files have their set-user-ID flag set. -.TP -.B \-v -Invert the sense of tests, only failing files pass. -.TP -.B \-w -Test that files are writable. -.TP -.B \-x -Test that files are executable. -.SH EXIT STATUS -.TP -.B 0 -At least one file passed all tests. -.TP -.B 1 -No files passed all tests. -.TP -.B 2 -An error occurred. -.SH SEE ALSO -.IR dmenu (1), -.IR test (1) diff --git a/.local/src/dmenu/stest.c b/.local/src/dmenu/stest.c @@ -1,109 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <sys/stat.h> - -#include <dirent.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "arg.h" -char *argv0; - -#define FLAG(x) (flag[(x)-'a']) - -static void test(const char *, const char *); -static void usage(void); - -static int match = 0; -static int flag[26]; -static struct stat old, new; - -static void -test(const char *path, const char *name) -{ - struct stat st, ln; - - if ((!stat(path, &st) && (FLAG('a') || name[0] != '.') /* hidden files */ - && (!FLAG('b') || S_ISBLK(st.st_mode)) /* block special */ - && (!FLAG('c') || S_ISCHR(st.st_mode)) /* character special */ - && (!FLAG('d') || S_ISDIR(st.st_mode)) /* directory */ - && (!FLAG('e') || access(path, F_OK) == 0) /* exists */ - && (!FLAG('f') || S_ISREG(st.st_mode)) /* regular file */ - && (!FLAG('g') || st.st_mode & S_ISGID) /* set-group-id flag */ - && (!FLAG('h') || (!lstat(path, &ln) && S_ISLNK(ln.st_mode))) /* symbolic link */ - && (!FLAG('n') || st.st_mtime > new.st_mtime) /* newer than file */ - && (!FLAG('o') || st.st_mtime < old.st_mtime) /* older than file */ - && (!FLAG('p') || S_ISFIFO(st.st_mode)) /* named pipe */ - && (!FLAG('r') || access(path, R_OK) == 0) /* readable */ - && (!FLAG('s') || st.st_size > 0) /* not empty */ - && (!FLAG('u') || st.st_mode & S_ISUID) /* set-user-id flag */ - && (!FLAG('w') || access(path, W_OK) == 0) /* writable */ - && (!FLAG('x') || access(path, X_OK) == 0)) != FLAG('v')) { /* executable */ - if (FLAG('q')) - exit(0); - match = 1; - puts(name); - } -} - -static void -usage(void) -{ - fprintf(stderr, "usage: %s [-abcdefghlpqrsuvwx] " - "[-n file] [-o file] [file...]\n", argv0); - exit(2); /* like test(1) return > 1 on error */ -} - -int -main(int argc, char *argv[]) -{ - struct dirent *d; - char path[PATH_MAX], *line = NULL, *file; - size_t linesiz = 0; - ssize_t n; - DIR *dir; - int r; - - ARGBEGIN { - case 'n': /* newer than file */ - case 'o': /* older than file */ - file = EARGF(usage()); - if (!(FLAG(ARGC()) = !stat(file, (ARGC() == 'n' ? &new : &old)))) - perror(file); - break; - default: - /* miscellaneous operators */ - if (strchr("abcdefghlpqrsuvwx", ARGC())) - FLAG(ARGC()) = 1; - else - usage(); /* unknown flag */ - } ARGEND; - - if (!argc) { - /* read list from stdin */ - while ((n = getline(&line, &linesiz, stdin)) > 0) { - if (line[n - 1] == '\n') - line[n - 1] = '\0'; - test(line, line); - } - free(line); - } else { - for (; argc; argc--, argv++) { - if (FLAG('l') && (dir = opendir(*argv))) { - /* test directory contents */ - while ((d = readdir(dir))) { - r = snprintf(path, sizeof path, "%s/%s", - *argv, d->d_name); - if (r >= 0 && (size_t)r < sizeof path) - test(path, d->d_name); - } - closedir(dir); - } else { - test(*argv, *argv); - } - } - } - return match ? 0 : 1; -} diff --git a/.local/src/dmenu/util.c b/.local/src/dmenu/util.c @@ -1,35 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "util.h" - -void * -ecalloc(size_t nmemb, size_t size) -{ - void *p; - - if (!(p = calloc(nmemb, size))) - die("calloc:"); - return p; -} - -void -die(const char *fmt, ...) { - va_list ap; - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - - if (fmt[0] && fmt[strlen(fmt)-1] == ':') { - fputc(' ', stderr); - perror(NULL); - } else { - fputc('\n', stderr); - } - - exit(1); -} diff --git a/.local/src/dmenu/util.h b/.local/src/dmenu/util.h @@ -1,8 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -#define MAX(A, B) ((A) > (B) ? (A) : (B)) -#define MIN(A, B) ((A) < (B) ? (A) : (B)) -#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) - -void die(const char *fmt, ...); -void *ecalloc(size_t nmemb, size_t size); diff --git a/.local/src/dwm/LICENSE b/.local/src/dwm/LICENSE @@ -1,37 +0,0 @@ -MIT/X Consortium License - -© 2006-2019 Anselm R Garbe <anselm@garbe.ca> -© 2006-2009 Jukka Salmi <jukka at salmi dot ch> -© 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com> -© 2007-2011 Peter Hartlich <sgkkr at hartlich dot com> -© 2007-2009 Szabolcs Nagy <nszabolcs at gmail dot com> -© 2007-2009 Christof Musik <christof at sendfax dot de> -© 2007-2009 Premysl Hruby <dfenze at gmail dot com> -© 2007-2008 Enno Gottox Boland <gottox at s01 dot de> -© 2008 Martin Hurton <martin dot hurton at gmail dot com> -© 2008 Neale Pickett <neale dot woozle dot org> -© 2009 Mate Nagy <mnagy at port70 dot net> -© 2010-2016 Hiltjo Posthuma <hiltjo@codemadness.org> -© 2010-2012 Connor Lane Smith <cls@lubutu.com> -© 2011 Christoph Lohmann <20h@r-36.net> -© 2015-2016 Quentin Rameau <quinq@fifth.space> -© 2015-2016 Eric Pruitt <eric.pruitt@gmail.com> -© 2016-2017 Markus Teich <markus.teich@stusta.mhn.de> - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/.local/src/dwm/Makefile b/.local/src/dwm/Makefile @@ -1,51 +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.h config.mk\ - dwm.1 drw.h util.h ${SRC} dwm.png transient.c dwm-${VERSION} - tar -cf dwm-${VERSION}.tar dwm-${VERSION} - gzip dwm-${VERSION}.tar - rm -rf dwm-${VERSION} - -install: all - mkdir -p ${DESTDIR}${PREFIX}/bin - cp -f dwm ${DESTDIR}${PREFIX}/bin - chmod 755 ${DESTDIR}${PREFIX}/bin/dwm - mkdir -p ${DESTDIR}${MANPREFIX}/man1 - sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1 - chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1 - -uninstall: - rm -f ${DESTDIR}${PREFIX}/bin/dwm\ - ${DESTDIR}${MANPREFIX}/man1/dwm.1 - -.PHONY: all options clean dist install uninstall diff --git a/.local/src/dwm/README b/.local/src/dwm/README @@ -1,48 +0,0 @@ -dwm - dynamic window manager -============================ -dwm is an extremely fast, small, and dynamic window manager for X. - - -Requirements ------------- -In order to build dwm you need the Xlib header files. - - -Installation ------------- -Edit config.mk to match your local setup (dwm is installed into -the /usr/local namespace by default). - -Afterwards enter the following command to build and install dwm (if -necessary as root): - - make clean install - - -Running dwm ------------ -Add the following line to your .xinitrc to start dwm using startx: - - exec dwm - -In order to connect dwm to a specific display, make sure that -the DISPLAY environment variable is set correctly, e.g.: - - DISPLAY=foo.bar:1 exec dwm - -(This will start dwm on display :1 of the host foo.bar.) - -In order to display status info in the bar, you can do something -like this in your .xinitrc: - - while xsetroot -name "`date` `uptime | sed 's/.*,//'`" - do - sleep 1 - done & - exec dwm - - -Configuration -------------- -The configuration of dwm is done by creating a custom config.h -and (re)compiling the source code. diff --git a/.local/src/dwm/config.h b/.local/src/dwm/config.h @@ -1,303 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* Load essentials */ -#include <X11/XF86keysym.h> /* For XF86 multimedia binds */ - -/* System Tray */ -static const int showsystray = 0; /* 0 means no systray */ -static const unsigned int systraypadding= 1; /* systray vertical padding */ -static const unsigned int systrayspacing= 2; /* systray spacing */ -static const unsigned int systrayonleft = 0; /* 0: systray in the right corner, 1: systray on left of status text */ - -static const unsigned int systraypinning= 1; /* 0: sloppy systray follows selected monitor, 1: pin systray to monitor X */ -static const int systraypinningfailfirst= 1; /* 1: if pinning fails, display systray on the first monitor, 0: display systray on the last monitor*/ - -/* appearance */ -static const char *fonts[] = { "monospace:size=9", "Vazirmatn:size=9" }; -static const unsigned int borderpx = 0; /* border pixel of windows */ -static const unsigned int gappx = 10; /* gaps between windows */ -static const unsigned int snap = 32; /* snap pixel */ -static const int showbar = 1; /* 0 means no bar */ -static const int topbar = 1; /* 0 means bottom bar */ -static const int barheight = 3; /* Spacing around the bar's font */ -static const int hidevacanttags = 1; /* 1 means hide empty tags / 0: show every tag */ -static const int hidetagindicator = 1; /* 1 means hide default top-left square-shaped tag indicator */ -static const int showtitle = 0; /* 1 means show WM_NAME of the currently selected window */ -static const int truecenteredtitle = 0; /* 1 means center the WM_NAME on the status bar */ -static const unsigned int colorfultag = 0; /* 0 means use SchemeSel for selected tag */ -static char fgcolor[] = "#D8DEE9"; -static char bgcolor[] = "#2E3440"; -static char color0[] = "#3B4252"; -static char color1[] = "#BF616A"; -static char color2[] = "#A3BE8C"; -static char color3[] = "#EBCB8B"; -static char color4[] = "#81A1C1"; -static char color5[] = "#B48EAD"; -static char color6[] = "#88C0D0"; -static char color7[] = "#E5E9F0"; -static char color8[] = "#4C566A"; -static char color9[] = "#BF616A"; -static char color10[] = "#A3BE8C"; -static char color11[] = "#EBCB8B"; -static char color12[] = "#81A1C1"; -static char color13[] = "#B48EAD"; -static char color14[] = "#8FBCBB"; -static char color15[] = "#ECEFF4"; - -/* - * Xresources preferences to load at startup - */ -ResourcePref resources[] = { - { "foreground", STRING, &fgcolor}, - { "background", STRING, &bgcolor}, - { "color0", STRING, &color0}, - { "color1", STRING, &color1}, - { "color2", STRING, &color2}, - { "color3", STRING, &color3}, - { "color4", STRING, &color4}, - { "color5", STRING, &color5}, - { "color6", STRING, &color6}, - { "color7", STRING, &color7}, - { "color8", STRING, &color8}, - { "color9", STRING, &color9}, - { "color10", STRING, &color10}, - { "color11", STRING, &color11}, - { "color12", STRING, &color12}, - { "color13", STRING, &color13}, - { "color14", STRING, &color14}, - { "color15", STRING, &color15}, -}; - -static const char *colors[][3] = { - /* fg bg border */ - [SchemeNorm] = { color12, color0, color8 }, - [SchemeSel] = { color0, color12, color12 }, - [SchemeLayout] = { color12, color0, color8 }, -}; - -/* if colorfultag == 1: */ -static const char *colortags[][2] = { - { color1, color0 }, - { color2, color0 }, - { color3, color0 }, - { color4, color0 }, - { color5, color0 }, - { color6, color0 }, - { color9, color0 }, - { color10, color0 }, - { color11, color0 }, -}; -//static const char *colortags_sel[][2] = { -// { color1, color8 }, -// { color2, color8 }, -// { color3, color8 }, -// { color4, color8 }, -// { color5, color8 }, -// { color6, color8 }, -// { color9, color8 }, -// { color10, color8 }, -// { color11, color8 }, -//}; -static const char *colortags_sel[][2] = { - { color0, color1 }, - { color0, color2 }, - { color0, color3 }, - { color0, color4 }, - { color0, color5 }, - { color0, color6 }, - { color0, color9 }, - { color0, color10 }, - { color0, color11 }, -}; - -/* tagging */ -//static const char *tags[] = { "𐎠", "𐎡", "𐎢", "𐎣", "𐎤", "𐎥", "𐎦", "𐎧", "𐎨" }; -static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; - -static const Rule rules[] = { - /* xprop(1): - * WM_CLASS(STRING) = instance, class - * WM_NAME(STRING) = title - */ - /* class instance title tags mask isfloating monitor */ - //{ "mpv", NULL, NULL, 0, 1, -1 }, - //{ "Gimp", NULL, NULL, 0, 1, -1 }, - //{ "Firefox", NULL, NULL, 1 << 8, 0, -1 }, - { "st-float", NULL, NULL, 0, 1, -1 }, - { NULL, "st-float", NULL, 0, 1, -1 }, - { NULL, NULL, "Event Tester", 0, 0, -1 }, /* xev */ -}; - -/* 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 = 1; /* 1 means respect size hints in tiled resizals */ -static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ -static int layouts_default = 0; /* Default layout */ -static const int layouts_floating = 2;/* Layout number for floating mode */ - -//static const Layout layouts[] = { -// /* symbol arrange function */ -// { "Tile", tile }, /* first entry is default */ -// { "Monocle", monocle }, -// { "Float", NULL }, /* no layout function means floating behavior */ -// { NULL, NULL }, -//}; - -static const Layout layouts[] = { - /* symbol arrange function */ - { "[]=", tile }, /* first entry is default */ - { "[M]", monocle }, - { "><>", NULL }, /* no layout function means floating behavior */ - { NULL, NULL }, -}; - -/* key definitions */ -#define MODKEY Mod4Mask -#define ALTMOD Mod1Mask -#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} }, \ - { ALTMOD, KEY, focusnthmon, {.i = TAG } }, \ - { ALTMOD|ShiftMask, KEY, tagnthmon, {.i = TAG } }, - -/* helper for spawning shell commands in the pre dwm-5.0 fashion */ -#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } - -/* commands */ -static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ -static const char *dmenucmd[] = { "dmenu_run", "-i", "-p", "Run:", NULL }; -//static const char *termcmd[] = { "st", NULL }; -//static const char *termcmdfloat[] = { "st", "-c", "st-float", NULL }; -static const char *termcmd[] = { "tabbed", "-cd", "-r", "2", "st", "-w", "''", NULL }; -static const char *termcmdfloat[] = { "tabbed", "-cd", "-n", "st-float", "-r", "2", "st", "-w", "''", NULL }; - -static Key keys[] = { - /* modifier key function argument */ - { MODKEY, XK_a, spawn, SHCMD("dmenu_drun") }, - { MODKEY, XK_c, spawn, {.v = dmenucmd } }, - { MODKEY, XK_Return, spawn, {.v = termcmd } }, - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmdfloat } }, - { 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_d, incnmaster, {.i = -1 } }, - { MODKEY, XK_h, setmfact, {.f = -0.05} }, - { MODKEY, XK_l, setmfact, {.f = +0.05} }, - { MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } }, - { MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } }, - { MODKEY, XK_space, zoom, {0} }, - { MODKEY, XK_Tab, view, {0} }, - { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, - { MODKEY, XK_m, setlayout, {.v = &layouts[1]} }, - { MODKEY, XK_f, setlayout, {.v = &layouts[2]} }, - { MODKEY|ControlMask, XK_comma, cyclelayout, {.i = -1 } }, - { MODKEY|ControlMask, XK_period, cyclelayout, {.i = +1 } }, - { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, - { MODKEY|ShiftMask, XK_f, togglefullscr, {0} }, - { MODKEY, XK_s, togglesticky, {0} }, - { MODKEY, XK_0, view, {.ui = ~0 } }, - { MODKEY|ShiftMask, XK_0, 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, XK_minus, setgaps, {.i = -1 } }, - { MODKEY, XK_equal, setgaps, {.i = +1 } }, - { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } }, - { MODKEY|ControlMask, XK_minus, shiftview, {.i = -1 } }, - { MODKEY|ControlMask, XK_equal, shiftview, {.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) - { MODKEY, XK_F5, live_reload_xresources,{0} }, - { MODKEY|ShiftMask, XK_r, restart, {0} }, - { MODKEY, XK_q, killclient, {0} }, - { MODKEY|ControlMask, XK_q, quit, {0} }, - { MODKEY|ShiftMask, XK_b, spawn, SHCMD("dwm-bar -M") }, - { MODKEY|ShiftMask, XK_q, spawn, SHCMD("dmenu-power") }, - { MODKEY, XK_r, spawn, SHCMD("dmenu-record") }, - { MODKEY, XK_w, spawn, SHCMD("surf-open") }, - { MODKEY|ControlMask, XK_w, spawn, SHCMD("surf") }, - { MODKEY|ShiftMask, XK_e, spawn, SHCMD("st -e sh -c \"mutt\"") }, - { MODKEY|ShiftMask, XK_m, spawn, SHCMD("dmenu-man") }, - { MODKEY|ShiftMask, XK_w, spawn, SHCMD("st -c \"st-float\" -g \"100x20\" -e sh -c \"SET_BG_SELECT=1 bg-set\"") }, - { MODKEY|ShiftMask, XK_u, spawn, SHCMD("st -c \"st-float\" -g \"100x28\" -e sh -c \"doas pacman -Syu --noconfirm && rm ~/.cache/pkg_updates\"") }, - { MODKEY|ShiftMask, XK_t, spawn, SHCMD("theme-sel -s") }, - { MODKEY|ShiftMask, XK_g, spawn, SHCMD("gtt") }, - { MODKEY|ShiftMask, XK_y, spawn, SHCMD("myt -d") }, - { MODKEY|ControlMask, XK_l, spawn, SHCMD("slock") }, - { MODKEY, XK_grave, spawn, SHCMD("dmenu-emoji insert") }, - { ControlMask, XK_grave, spawn, SHCMD("dmenu-emoji clipboard") }, - { 0, XK_Print, spawn, SHCMD("screenshot -xc") }, - { ShiftMask, XK_Print, spawn, SHCMD("screenshot -xc -t 5") }, - { ControlMask, XK_Print, spawn, SHCMD("screenshot -xc -s yes") }, - { ControlMask|ShiftMask, XK_Print, spawn, SHCMD("screenshot -xc -s yes -t 5") }, - - { MODKEY, XK_F11, spawn, SHCMD("bright -d") }, - { MODKEY, XK_F12, spawn, SHCMD("bright -i") }, - - { 0, XF86XK_WebCam, spawn, SHCMD("webcam") }, - { 0, XF86XK_TouchpadToggle, spawn, SHCMD("toggle-touch") }, - { 0, XF86XK_TouchpadOn, spawn, SHCMD("toggle-touch") }, - { 0, XF86XK_TouchpadOff, spawn, SHCMD("toggle-touch") }, - { 0, XF86XK_AudioPlay, spawn, SHCMD("media-controller toggle") }, - { 0, XF86XK_AudioPause, spawn, SHCMD("media-controller toggle") }, - { 0, XF86XK_AudioNext, spawn, SHCMD("media-controller next") }, - { 0, XF86XK_AudioPrev, spawn, SHCMD("media-controller prev") }, - { ShiftMask, XF86XK_AudioPlay, spawn, SHCMD("media-controller pause-all") }, - { ShiftMask, XF86XK_AudioPause, spawn, SHCMD("media-controller pause-all") }, - { ShiftMask, XF86XK_AudioNext, spawn, SHCMD("media-controller seek-fwd") }, - { ShiftMask, XF86XK_AudioPrev, spawn, SHCMD("media-controller seek-bwd") }, - { 0, XF86XK_MonBrightnessUp, spawn, SHCMD("bright -i") }, - { 0, XF86XK_MonBrightnessDown, spawn, SHCMD("bright -d") }, - { 0, XF86XK_AudioRaiseVolume, spawn, SHCMD("volume -i") }, - { 0, XF86XK_AudioLowerVolume, spawn, SHCMD("volume -d") }, - { 0, XF86XK_AudioMute, spawn, SHCMD("volume -m") }, - { ShiftMask, XF86XK_AudioRaiseVolume, spawn, SHCMD("volume -I") }, - { ShiftMask, XF86XK_AudioLowerVolume, spawn, SHCMD("volume -D") }, - { ShiftMask, XF86XK_AudioMute, spawn, SHCMD("volume -M") }, - { 0, XF86XK_AudioMicMute, spawn, SHCMD("volume -M") }, -}; - -/* button definitions */ -/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ -static Button buttons[] = { - /* click event mask button function argument */ - /* placemouse options, choose which feels more natural: - * 0 - tiled position is relative to mouse cursor - * 1 - tiled postiion is relative to window center - * 2 - mouse pointer warps to window center - * - * The moveorplace uses movemouse or placemouse depending on the floating state - * of the selected client. Set up individual keybindings for the two if you want - * to control these separately (i.e. to retain the feature to move a tiled window - * into a floating position). - */ - { ClkClientWin, MODKEY, Button1, moveorplace, {.i = 1} }, - { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, - { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, - { ClkTagBar, 0, Button1, view, {0} }, - { ClkTagBar, 0, Button3, toggleview, {0} }, - { ClkTagBar, MODKEY, Button1, tag, {0} }, - { ClkTagBar, MODKEY, Button3, toggletag, {0} }, - { ClkTagBar, 0, Button4, shiftview, {.i = -1} }, - { ClkTagBar, 0, Button5, shiftview, {.i = +1} }, - { ClkLtSymbol, 0, Button1, cyclelayout, {.i = +1} }, - { ClkLtSymbol, 0, Button3, cyclelayout, {.i = -1} }, - { ClkLtSymbol, 0, Button2, setlayout, {.v = &layouts[0]} }, - { ClkLtSymbol, 0, Button4, cyclelayout, {.i = -1} }, - { ClkLtSymbol, 0, Button5, cyclelayout, {.i = +1} }, - { ClkWinTitle, 0, Button2, togglesticky, {0} }, - { ClkStatusText, 0, Button3, spawn, SHCMD("dwm-bar -M") }, -}; - diff --git a/.local/src/dwm/config.mk b/.local/src/dwm/config.mk @@ -1,42 +0,0 @@ -# dwm version -VERSION = 6.3 - -# Customize below to fit your system - -# paths -PREFIX = /usr/local -MANPREFIX = ${PREFIX}/share/man - -X11INC = /usr/X11R6/include -X11LIB = /usr/X11R6/lib - -BDINC = /usr/include/fribidi - -# Xinerama, comment if you don't want it -XINERAMALIBS = -lXinerama -XINERAMAFLAGS = -DXINERAMA - -# freetype -FREETYPELIBS = -lfontconfig -lXft -FREETYPEINC = /usr/include/freetype2 -# OpenBSD (uncomment) -#FREETYPEINC = ${X11INC}/freetype2 - -BDLIBS = -lfribidi - -# includes and libs -INCS = -I${X11INC} -I${FREETYPEINC} -I$(BDINC) -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} $(BDLIBS) - -# flags -CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} -CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} -LDFLAGS = ${LIBS} - -# Solaris -#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" -#LDFLAGS = ${LIBS} - -# compiler and linker -CC = cc diff --git a/.local/src/dwm/drw.c b/.local/src/dwm/drw.c @@ -1,437 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <X11/Xlib.h> -#include <X11/Xft/Xft.h> - -#include "drw.h" -#include "util.h" - -#define UTF_INVALID 0xFFFD -#define UTF_SIZ 4 - -static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; -static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; -static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; -static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; - -static long -utf8decodebyte(const char c, size_t *i) -{ - for (*i = 0; *i < (UTF_SIZ + 1); ++(*i)) - if (((unsigned char)c & utfmask[*i]) == utfbyte[*i]) - return (unsigned char)c & ~utfmask[*i]; - return 0; -} - -static size_t -utf8validate(long *u, size_t i) -{ - if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) - *u = UTF_INVALID; - for (i = 1; *u > utfmax[i]; ++i) - ; - return i; -} - -static size_t -utf8decode(const char *c, long *u, size_t clen) -{ - size_t i, j, len, type; - long udecoded; - - *u = UTF_INVALID; - if (!clen) - return 0; - udecoded = utf8decodebyte(c[0], &len); - if (!BETWEEN(len, 1, UTF_SIZ)) - return 1; - for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { - udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); - if (type) - return j; - } - if (j < len) - return 0; - *u = udecoded; - utf8validate(u, len); - - return len; -} - -Drw * -drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) -{ - Drw *drw = ecalloc(1, sizeof(Drw)); - - drw->dpy = dpy; - drw->screen = screen; - drw->root = root; - drw->w = w; - drw->h = h; - drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); - drw->gc = XCreateGC(dpy, root, 0, NULL); - XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); - - return drw; -} - -void -drw_resize(Drw *drw, unsigned int w, unsigned int h) -{ - if (!drw) - return; - - drw->w = w; - drw->h = h; - if (drw->drawable) - XFreePixmap(drw->dpy, drw->drawable); - drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); -} - -void -drw_free(Drw *drw) -{ - XFreePixmap(drw->dpy, drw->drawable); - XFreeGC(drw->dpy, drw->gc); - drw_fontset_free(drw->fonts); - free(drw); -} - -/* This function is an implementation detail. Library users should use - * drw_fontset_create instead. - */ -static Fnt * -xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) -{ - Fnt *font; - XftFont *xfont = NULL; - FcPattern *pattern = NULL; - - if (fontname) { - /* Using the pattern found at font->xfont->pattern does not yield the - * same substitution results as using the pattern returned by - * FcNameParse; using the latter results in the desired fallback - * behaviour whereas the former just results in missing-character - * rectangles being drawn, at least with some fonts. */ - if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) { - fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname); - return NULL; - } - if (!(pattern = FcNameParse((FcChar8 *) fontname))) { - fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname); - XftFontClose(drw->dpy, xfont); - return NULL; - } - } else if (fontpattern) { - if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { - fprintf(stderr, "error, cannot load font from pattern.\n"); - return NULL; - } - } else { - die("no font specified."); - } - - /* Do not allow using color fonts. This is a workaround for a BadLength - * error from Xft with color glyphs. Modelled on the Xterm workaround. See - * https://bugzilla.redhat.com/show_bug.cgi?id=1498269 - * https://lists.suckless.org/dev/1701/30932.html - * https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=916349 - * and lots more all over the internet. - */ - FcBool iscol; - if(FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) { - XftFontClose(drw->dpy, xfont); - return NULL; - } - - font = ecalloc(1, sizeof(Fnt)); - font->xfont = xfont; - font->pattern = pattern; - font->h = xfont->ascent + xfont->descent; - font->dpy = drw->dpy; - - return font; -} - -static void -xfont_free(Fnt *font) -{ - if (!font) - return; - if (font->pattern) - FcPatternDestroy(font->pattern); - XftFontClose(font->dpy, font->xfont); - free(font); -} - -Fnt* -drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) -{ - Fnt *cur, *ret = NULL; - size_t i; - - if (!drw || !fonts) - return NULL; - - for (i = 1; i <= fontcount; i++) { - if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) { - cur->next = ret; - ret = cur; - } - } - return (drw->fonts = ret); -} - -void -drw_fontset_free(Fnt *font) -{ - if (font) { - drw_fontset_free(font->next); - xfont_free(font); - } -} - -void -drw_clr_create(Drw *drw, Clr *dest, const char *clrname) -{ - if (!drw || !dest || !clrname) - return; - - if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), - DefaultColormap(drw->dpy, drw->screen), - clrname, dest)) - die("error, cannot allocate color '%s'", clrname); -} - -/* 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) -{ - size_t i; - Clr *ret; - - /* need at least two colors for a scheme */ - if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor)))) - return NULL; - - for (i = 0; i < clrcount; i++) - drw_clr_create(drw, &ret[i], clrnames[i]); - return ret; -} - -void -drw_setfontset(Drw *drw, Fnt *set) -{ - if (drw) - drw->fonts = set; -} - -void -drw_setscheme(Drw *drw, Clr *scm) -{ - if (drw) - drw->scheme = scm; -} - -void -drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) -{ - if (!drw || !drw->scheme) - return; - XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel); - if (filled) - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); - else - XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1); -} - -int -drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) -{ - char buf[1024]; - int ty; - unsigned int ew; - XftDraw *d = NULL; - Fnt *usedfont, *curfont, *nextfont; - size_t i, len; - int utf8strlen, utf8charlen, render = x || y || w || h; - long utf8codepoint = 0; - const char *utf8str; - FcCharSet *fccharset; - FcPattern *fcpattern; - FcPattern *match; - XftResult result; - int charexists = 0; - - if (!drw || (render && !drw->scheme) || !text || !drw->fonts) - return 0; - - if (!render) { - w = ~w; - } else { - XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); - d = XftDrawCreate(drw->dpy, drw->drawable, - DefaultVisual(drw->dpy, drw->screen), - DefaultColormap(drw->dpy, drw->screen)); - x += lpad; - w -= lpad; - } - - usedfont = drw->fonts; - while (1) { - utf8strlen = 0; - utf8str = text; - nextfont = NULL; - while (*text) { - utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ); - for (curfont = drw->fonts; curfont; curfont = curfont->next) { - charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); - if (charexists) { - if (curfont == usedfont) { - utf8strlen += utf8charlen; - text += utf8charlen; - } else { - nextfont = curfont; - } - break; - } - } - - if (!charexists || nextfont) - break; - else - charexists = 0; - } - - if (utf8strlen) { - drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL); - /* shorten text if necessary */ - for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--) - drw_font_getexts(usedfont, utf8str, len, &ew, NULL); - - if (len) { - memcpy(buf, utf8str, len); - buf[len] = '\0'; - if (len < utf8strlen) - for (i = len; i && i > len - 3; buf[--i] = '.') - ; /* NOP */ - - if (render) { - ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; - XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], - usedfont->xfont, x, ty, (XftChar8 *)buf, len); - } - x += ew; - w -= ew; - } - } - - if (!*text) { - break; - } else if (nextfont) { - charexists = 0; - usedfont = nextfont; - } else { - /* Regardless of whether or not a fallback font is found, the - * character must be drawn. */ - charexists = 1; - - fccharset = FcCharSetCreate(); - FcCharSetAddChar(fccharset, utf8codepoint); - - if (!drw->fonts->pattern) { - /* Refer to the comment in xfont_create for more information. */ - die("the first font in the cache must be loaded from a font string."); - } - - fcpattern = FcPatternDuplicate(drw->fonts->pattern); - FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); - FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); - FcPatternAddBool(fcpattern, FC_COLOR, FcFalse); - - FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); - FcDefaultSubstitute(fcpattern); - match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result); - - FcCharSetDestroy(fccharset); - FcPatternDestroy(fcpattern); - - if (match) { - usedfont = xfont_create(drw, NULL, match); - if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) { - for (curfont = drw->fonts; curfont->next; curfont = curfont->next) - ; /* NOP */ - curfont->next = usedfont; - } else { - xfont_free(usedfont); - usedfont = drw->fonts; - } - } - } - } - if (d) - XftDrawDestroy(d); - - return x + (render ? w : 0); -} - -void -drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) -{ - if (!drw) - return; - - XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); - XSync(drw->dpy, False); -} - -unsigned int -drw_fontset_getwidth(Drw *drw, const char *text) -{ - if (!drw || !drw->fonts || !text) - return 0; - return drw_text(drw, 0, 0, 0, 0, 0, text, 0); -} - -void -drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) -{ - XGlyphInfo ext; - - if (!font || !text) - return; - - XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); - if (w) - *w = ext.xOff; - if (h) - *h = font->h; -} - -Cur * -drw_cur_create(Drw *drw, int shape) -{ - Cur *cur; - - if (!drw || !(cur = ecalloc(1, sizeof(Cur)))) - return NULL; - - cur->cursor = XCreateFontCursor(drw->dpy, shape); - - return cur; -} - -void -drw_cur_free(Drw *drw, Cur *cursor) -{ - if (!cursor) - return; - - XFreeCursor(drw->dpy, cursor->cursor); - free(cursor); -} - diff --git a/.local/src/dwm/drw.h b/.local/src/dwm/drw.h @@ -1,57 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -typedef struct { - Cursor cursor; -} Cur; - -typedef struct Fnt { - Display *dpy; - unsigned int h; - XftFont *xfont; - FcPattern *pattern; - struct Fnt *next; -} Fnt; - -enum { ColFg, ColBg, ColBorder }; /* Clr scheme index */ -typedef XftColor Clr; - -typedef struct { - unsigned int w, h; - Display *dpy; - int screen; - Window root; - Drawable drawable; - GC gc; - Clr *scheme; - Fnt *fonts; -} Drw; - -/* Drawable abstraction */ -Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); -void drw_resize(Drw *drw, unsigned int w, unsigned int h); -void drw_free(Drw *drw); - -/* Fnt abstraction */ -Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); -void drw_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); - -/* 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); - -/* Cursor abstraction */ -Cur *drw_cur_create(Drw *drw, int shape); -void drw_cur_free(Drw *drw, Cur *cursor); - -/* Drawing context manipulation */ -void drw_setfontset(Drw *drw, Fnt *set); -void drw_setscheme(Drw *drw, Clr *scm); - -/* Drawing functions */ -void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); -int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); - -/* Map functions */ -void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); diff --git a/.local/src/dwm/dwm.1 b/.local/src/dwm/dwm.1 @@ -1,205 +0,0 @@ -.TH DWM 1 dwm\-VERSION -.SH NAME -dwm \- dynamic window manager -.SH SYNOPSIS -.B dwm -.RB [ \-v ] -.SH DESCRIPTION -dwm is a dynamic window manager for X. It manages windows in tiled, monocle -and floating layouts. Either layout can be applied dynamically, optimising the -environment for the application in use and the task performed. -.P -In tiled layouts windows are managed in a master and stacking area. The master -area on the left contains one window by default, and the stacking area on the -right contains all other windows. The number of master area windows can be -adjusted from zero to an arbitrary number. In monocle layout all windows are -maximised to the screen size. In floating layout windows can be resized and -moved freely. Dialog windows are always managed floating, regardless of the -layout applied. -.P -Windows are grouped by tags. Each window can be tagged with one or multiple -tags. Selecting certain tags displays all windows with these tags. -.P -Each screen contains a small status bar which displays all available tags, the -layout, the title of the focused window, and the text read from the root window -name property, if the screen is focused. A floating window is indicated with an -empty square and a maximised floating window is indicated with a filled square -before the windows title. The selected tags are indicated with a different -color. The tags of the focused window are indicated with a filled square in the -top left corner. The tags which are applied to one or more windows are -indicated with an empty square in the top left corner. -.P -dwm draws a small border around windows to indicate the focus state. -.SH OPTIONS -.TP -.B \-v -prints version information to stderr, then exits. -.SH USAGE -.SS Status bar -.TP -.B X root window name -is read and displayed in the status text area. It can be set with the -.BR xsetroot (1) -command. -.TP -.B Button1 -click on a tag label to display all windows with that tag, click on the layout -label toggles between tiled and floating layout. -.TP -.B Button3 -click on a tag label adds/removes all windows with that tag to/from the view. -.TP -.B Mod4\-Button1 -click on a tag label applies that tag to the focused window. -.TP -.B Mod4\-Button3 -click on a tag label adds/removes that tag to/from the focused window. -.SS Keyboard commands -.TP -.B Mod4\-Shift\-Return -Start -.BR st(1). -.TP -.B Mod4\-p -Spawn -.BR dmenu(1) -for launching other programs. -.TP -.B Mod4\-, -Focus previous screen, if any. -.TP -.B Mod4\-. -Focus next screen, if any. -.TP -.B Mod4\-Shift\-, -Send focused window to previous screen, if any. -.TP -.B Mod4\-Shift\-. -Send focused window to next screen, if any. -.TP -.B Mod4\-b -Toggles bar on and off. -.TP -.B Mod4\-t -Sets tiled layout. -.TP -.B Mod4\-f -Sets floating layout. -.TP -.B Mod4\-m -Sets monocle layout. -.TP -.B Mod4\-space -Toggles between current and previous layout. -.TP -.B Mod4\-Control\-, -Cycles backwards in layout list. -.TP -.B Mod4\-Control\-. -Cycles forwards in layout list. -.TP -.B Mod4\-j -Focus next window. -.TP -.B Mod4\-k -Focus previous window. -.TP -.B Mod4\-i -Increase number of windows in master area. -.TP -.B Mod4\-d -Decrease number of windows in master area. -.TP -.B Mod4\-l -Increase master area size. -.TP -.B Mod4\-h -Decrease master area size. -.TP -.B Mod4\-Return -Zooms/cycles focused window to/from master area (tiled layouts only). -.TP -.B Mod4\-Shift\-c -Close focused window. -.TP -.B Mod4\-Shift\-f -Toggle fullscreen for focused window. -.TP -.B Mod4\-Shift\-space -Toggle focused window between tiled and floating state. -.TP -.B Mod4\-Tab -Toggles to the previously selected tags. -.TP -.B Mod4\-Shift\-[1..n] -Apply nth tag to focused window. -.TP -.B Mod4\-Shift\-0 -Apply all tags to focused window. -.TP -.B Mod4\-Control\-Shift\-[1..n] -Add/remove nth tag to/from focused window. -.TP -.B Mod4\-[1..n] -View all windows with nth tag. -.TP -.B Mod4\-0 -View all windows with any tag. -.TP -.B Mod4\-Control\-[1..n] -Add/remove all windows with nth tag to/from the view. -.TP -.B Mod4\-- -Decrease the gaps around windows. -.TP -.B Mod4\-= -Increase the gaps around windows. -.TP -.B Mod4\-Shift-= -Reset the gaps around windows to -.BR 0 . -.TP -.B Mod4\-Shift\-q -Quit dwm. -.TP -.B Mod4\-Control\-Shift\-q -Restart dwm. -.SS Mouse commands -.TP -.B Mod4\-Button1 -Move focused window while dragging. Tiled windows will be toggled to the floating state. -.TP -.B Mod4\-Button2 -Toggles focused window between floating and tiled state. -.TP -.B Mod4\-Button3 -Resize focused window while dragging. Tiled windows will be toggled to the floating state. -.SH CUSTOMIZATION -dwm is customized by creating a custom config.h and (re)compiling the source -code. This keeps it fast, secure and simple. -.SH SIGNALS -.TP -.B SIGHUP - 1 -Restart the dwm process. -.TP -.B SIGTERM - 15 -Cleanly terminate the dwm process. -.SH SEE ALSO -.BR dmenu (1), -.BR st (1) -.SH ISSUES -Java applications which use the XToolkit/XAWT backend may draw grey windows -only. The XToolkit/XAWT backend breaks ICCCM-compliance in recent JDK 1.5 and early -JDK 1.6 versions, because it assumes a reparenting window manager. Possible workarounds -are using JDK 1.4 (which doesn't contain the XToolkit/XAWT backend) or setting the -environment variable -.BR AWT_TOOLKIT=MToolkit -(to use the older Motif backend instead) or running -.B xprop -root -f _NET_WM_NAME 32a -set _NET_WM_NAME LG3D -or -.B wmname LG3D -(to pretend that a non-reparenting window manager is running that the -XToolkit/XAWT backend can recognize) or when using OpenJDK setting the environment variable -.BR _JAVA_AWT_WM_NONREPARENTING=1 . -.SH BUGS -Send all bug reports with a patch to hackers@suckless.org. diff --git a/.local/src/dwm/dwm.c b/.local/src/dwm/dwm.c @@ -1,3243 +0,0 @@ -/* See LICENSE file for copyright and license details. - * - * dynamic window manager is designed like any other X client as well. It is - * driven through handling X events. In contrast to other X clients, a window - * manager selects for SubstructureRedirectMask on the root window, to receive - * events about window (dis-)appearance. Only one X connection at a time is - * allowed to select for this event mask. - * - * The event handlers of dwm are organized in an array which is accessed - * whenever a new event has been fetched. This allows event dispatching - * in O(1) time. - * - * Each child of the root window is called a client, except windows which have - * set the override_redirect flag. Clients are organized in a linked client - * list on each monitor, the focus history is remembered through a stack list - * on each monitor. Each client contains a bit array to indicate the tags of a - * client. - * - * Keys and tagging rules are organized as arrays and defined in config.h. - * - * To understand everything else, start reading main(). - */ -#include <errno.h> -#include <locale.h> -#include <signal.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <X11/cursorfont.h> -#include <X11/keysym.h> -#include <X11/Xatom.h> -#include <X11/Xlib.h> -#include <X11/Xproto.h> -#include <X11/Xresource.h> -#include <X11/Xutil.h> -#ifdef XINERAMA -#include <X11/extensions/Xinerama.h> -#endif /* XINERAMA */ -#include <X11/Xft/Xft.h> -#include <fribidi.h> - -#include "drw.h" -#include "util.h" - -/* macros */ -#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) -#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) -#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ - * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) -#define INTERSECTC(x,y,w,h,z) (MAX(0, MIN((x)+(w),(z)->x+(z)->w) - MAX((x),(z)->x)) \ - * MAX(0, MIN((y)+(h),(z)->y+(z)->h) - MAX((y),(z)->y))) -#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]) || C->issticky) -#define LENGTH(X) (sizeof X / sizeof X[0]) -#define MOUSEMASK (BUTTONMASK|PointerMotionMask) -#define WIDTH(X) ((X)->w + 2 * (X)->bw) -#define HEIGHT(X) ((X)->h + 2 * (X)->bw) -#define 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, SchemeLayout }; /* color schemes */ -enum { NetSupported, NetWMName, NetWMState, NetWMCheck, - NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, NetSystemTrayOrientationHorz, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetClientList, NetClientInfo, 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 */ - -typedef union { - int i; - unsigned int ui; - float f; - const void *v; -} Arg; - -typedef struct { - unsigned int click; - unsigned int mask; - unsigned int button; - void (*func)(const Arg *arg); - const Arg arg; -} Button; - -typedef struct Monitor Monitor; -typedef struct Client Client; -struct Client { - char name[256]; - float mina, maxa; - int x, y, w, h; - int oldx, oldy, oldw, oldh; - int basew, baseh, incw, inch, maxw, maxh, minw, minh; - int bw, oldbw; - unsigned int tags; - int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, issticky, beingmoved; - pid_t pid; - Client *next; - Client *snext; - Monitor *mon; - Window win; -}; - -typedef struct { - unsigned int mod; - KeySym keysym; - void (*func)(const Arg *); - const Arg arg; -} Key; - -typedef struct { - const char *symbol; - void (*arrange)(Monitor *); -} Layout; - -struct Monitor { - char ltsymbol[16]; - float mfact; - int nmaster; - int num; - int by; /* bar geometry */ - int mx, my, mw, mh; /* screen size */ - int wx, wy, ww, wh; /* window area */ - int gappx; /* gaps between windows */ - unsigned int seltags; - unsigned int sellt; - unsigned int tagset[2]; - unsigned int colorfultag; - int showbar; - int topbar; - Client *clients; - Client *sel; - Client *stack; - Monitor *next; - Window barwin; - const Layout *lt[2]; -}; - -typedef struct { - const char *class; - const char *instance; - const char *title; - unsigned int tags; - int isfloating; - int monitor; -} Rule; - -typedef struct Systray Systray; -struct Systray { - Window win; - Client *icons; -}; - -/* Xresources preferences */ -enum resource_type { - STRING = 0, - INTEGER = 1, - FLOAT = 2 -}; - -typedef struct { - char *name; - enum resource_type type; - void *dst; -} ResourcePref; - -/* function declarations */ -static Atom getatomprop(Client *c, Atom prop); -static Client *nexttiled(Client *c); -static Client *recttoclient(int x, int y, int w, int h); -static Client *wintoclient(Window w); -static Client *wintosystrayicon(Window w); -static Monitor *createmon(void); -static Monitor *dirtomon(int dir); -static Monitor *numtomon(int num); -static Monitor *recttomon(int x, int y, int w, int h); -static Monitor *systraytomon(Monitor *m); -static Monitor *wintomon(Window w); -static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); -static int drawstatusbar(Monitor *m, int bh, char* text); -static int getrootptr(int *x, int *y); -static int gettextprop(Window w, Atom atom, char *text, unsigned int size); -static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4); -static int updategeom(void); -static int xerror(Display *dpy, XErrorEvent *ee); -static int xerrordummy(Display *dpy, XErrorEvent *ee); -static int xerrorstart(Display *dpy, XErrorEvent *ee); -static long getstate(Window w); -static unsigned int getsystraywidth(); -static void applyrules(Client *c); -static void arrange(Monitor *m); -static void arrangemon(Monitor *m); -static void attach(Client *c); -static void attachbottom(Client *c); -static void attachstack(Client *c); -static void buttonpress(XEvent *e); -static void checkotherwm(void); -static void cleanup(void); -static void cleanupmon(Monitor *mon); -static void clientmessage(XEvent *e); -static void configure(Client *c); -static void configurenotify(XEvent *e); -static void configurerequest(XEvent *e); -static void cyclelayout(const Arg *arg); -static void destroynotify(XEvent *e); -static void detach(Client *c); -static void detachstack(Client *c); -static void drawbar(Monitor *m); -static void drawbars(void); -static int drawstatusbar(Monitor *m, int bh, char* text); -static void enternotify(XEvent *e); -static void expose(XEvent *e); -static void focus(Client *c); -static void focusin(XEvent *e); -static void focusmon(const Arg *arg); -static void focusnthmon(const Arg *arg); -static void focusstack(const Arg *arg); -static void grabbuttons(Client *c, int focused); -static void grabkeys(void); -static void incnmaster(const Arg *arg); -static void keypress(XEvent *e); -static void killclient(const Arg *arg); -static void manage(Window w, XWindowAttributes *wa); -static void mappingnotify(XEvent *e); -static void maprequest(XEvent *e); -static void monocle(Monitor *m); -static void motionnotify(XEvent *e); -static void movemouse(const Arg *arg); -static void moveorplace(const Arg *arg); -static void movestack(const Arg *arg); -static void placemouse(const Arg *arg); -static void pop(Client *); -static void propertynotify(XEvent *e); -static void restart(const Arg *arg); -static void quit(const Arg *arg); -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 void sendmon(Client *c, Monitor *m); -static void setclientstate(Client *c, long state); -static void setclienttagprop(Client *c); -static void setfocus(Client *c); -static void setfullscreen(Client *c, int fullscreen); -static void setgaps(const Arg *arg); -static void setlayout(const Arg *arg); -static void setmfact(const Arg *arg); -static void setup(void); -static void seturgent(Client *c, int urg); -static void shiftview(const Arg *arg); -static void showhide(Client *c); -static void sigchld(int unused); -static void sighup(int unused); -static void sigterm(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 tagnthmon(const Arg *arg); -static void tile(Monitor *); -static void togglebar(const Arg *arg); -static void togglefloating(const Arg *arg); -static void togglefullscr(const Arg *arg); -static void togglesticky(const Arg *arg); -static void toggletag(const Arg *arg); -static void toggleview(const Arg *arg); -static void unfocus(Client *c, int setfocus); -static void unmanage(Client *c, int destroyed); -static void unmapnotify(XEvent *e); -static void updatebarpos(Monitor *m); -static void updatebars(void); -static void updateclientlist(void); -static 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 void warp(const Client *c); -static void zoom(const Arg *arg); - -static void live_reload_xresources(const Arg *arg); -static void load_xresources(void); -static void resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst); - -/* variables */ -static Systray *systray = NULL; -static const char broken[] = "broken"; -static char stext[1024]; -static char fribidi_text[BUFSIZ] = ""; -static int screen; -static int sw, sh; /* X display screen geometry width, height */ -static int bh, blw = 0; /* bar geometry */ -static int lrpad; /* sum of left and right padding for text */ -static int (*xerrorxlib)(Display *, XErrorEvent *); -static unsigned int numlockmask = 0; -static void (*handler[LASTEvent]) (XEvent *) = { - [ButtonPress] = buttonpress, - [ClientMessage] = clientmessage, - [ConfigureRequest] = configurerequest, - [ConfigureNotify] = configurenotify, - [DestroyNotify] = destroynotify, - [EnterNotify] = enternotify, - [Expose] = expose, - [FocusIn] = focusin, - [KeyPress] = keypress, - [MappingNotify] = mappingnotify, - [MapRequest] = maprequest, - [MotionNotify] = motionnotify, - [PropertyNotify] = propertynotify, - [ResizeRequest] = resizerequest, - [UnmapNotify] = unmapnotify -}; -static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast]; -static int restartsig = 0; -static int running = 1; -static Cur *cursor[CurLast]; -static Clr **scheme; -static Clr **tagscheme; -static Clr **tagscheme_sel; -static Display *dpy; -static Drw *drw; -static Monitor *mons, *selmon; -static Window root, wmcheckwin; - -/* configuration, allows nested code to access above variables */ -#include "config.h" - -/* compile-time check if all tags fit into an unsigned int bit array. */ -struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; - -/* function implementations */ -static void -apply_fribidi(const char *str) -{ - FriBidiStrIndex len = strlen(str); - FriBidiChar logical[BUFSIZ]; - FriBidiChar visual[BUFSIZ]; - FriBidiParType base = FRIBIDI_PAR_ON; - FriBidiCharSet charset; - fribidi_boolean result; - - fribidi_text[0] = 0; - if (len>0) - { - charset = fribidi_parse_charset("UTF-8"); - len = fribidi_charset_to_unicode(charset, str, len, logical); - result = fribidi_log2vis(logical, len, &base, visual, NULL, NULL, NULL); - len = fribidi_unicode_to_charset(charset, visual, len, fribidi_text); - } -} - -void -applyrules(Client *c) -{ - const char *class, *instance; - unsigned int i; - const Rule *r; - Monitor *m; - XClassHint ch = { NULL, NULL }; - - /* rule matching */ - c->isfloating = 0; - c->tags = 0; - XGetClassHint(dpy, c->win, &ch); - class = ch.res_class ? ch.res_class : broken; - instance = ch.res_name ? ch.res_name : broken; - - for (i = 0; i < LENGTH(rules); i++) { - r = &rules[i]; - if ((!r->title || strstr(c->name, r->title)) - && (!r->class || strstr(class, r->class)) - && (!r->instance || strstr(instance, r->instance))) - { - c->isfloating = r->isfloating; - c->tags |= r->tags; - for (m = mons; m && m->num != r->monitor; m = m->next); - if (m) - c->mon = m; - } - } - if (ch.res_class) - XFree(ch.res_class); - if (ch.res_name) - XFree(ch.res_name); - c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; -} - -int -applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) -{ - int baseismin; - Monitor *m = c->mon; - - /* set minimum possible */ - *w = MAX(1, *w); - *h = MAX(1, *h); - if (interact) { - if (*x > sw) - *x = sw - WIDTH(c); - if (*y > sh) - *y = sh - HEIGHT(c); - if (*x + *w + 2 * c->bw < 0) - *x = 0; - if (*y + *h + 2 * c->bw < 0) - *y = 0; - } else { - if (*x >= m->wx + m->ww) - *x = m->wx + m->ww - WIDTH(c); - if (*y >= m->wy + m->wh) - *y = m->wy + m->wh - HEIGHT(c); - if (*x + *w + 2 * c->bw <= m->wx) - *x = m->wx; - if (*y + *h + 2 * c->bw <= m->wy) - *y = m->wy; - } - if (*h < bh) - *h = bh; - if (*w < bh) - *w = bh; - if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) { - /* see last two sentences in ICCCM 4.1.2.3 */ - baseismin = c->basew == c->minw && c->baseh == c->minh; - if (!baseismin) { /* temporarily remove base dimensions */ - *w -= c->basew; - *h -= c->baseh; - } - /* adjust for aspect limits */ - if (c->mina > 0 && c->maxa > 0) { - if (c->maxa < (float)*w / *h) - *w = *h * c->maxa + 0.5; - else if (c->mina < (float)*h / *w) - *h = *w * c->mina + 0.5; - } - if (baseismin) { /* increment calculation requires this */ - *w -= c->basew; - *h -= c->baseh; - } - /* adjust for increment value */ - if (c->incw) - *w -= *w % c->incw; - if (c->inch) - *h -= *h % c->inch; - /* restore base dimensions */ - *w = MAX(*w + c->basew, c->minw); - *h = MAX(*h + c->baseh, c->minh); - if (c->maxw) - *w = MIN(*w, c->maxw); - if (c->maxh) - *h = MIN(*h, c->maxh); - } - return *x != c->x || *y != c->y || *w != c->w || *h != c->h; -} - -void -arrange(Monitor *m) -{ - if (m) - showhide(m->stack); - else for (m = mons; m; m = m->next) - showhide(m->stack); - if (m) { - arrangemon(m); - restack(m); - } else for (m = mons; m; m = m->next) - arrangemon(m); -} - -void -arrangemon(Monitor *m) -{ - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); - if (m->lt[m->sellt]->arrange) - m->lt[m->sellt]->arrange(m); -} - -void -attach(Client *c) -{ - c->next = c->mon->clients; - c->mon->clients = c; -} - -void -attachbottom(Client *c) -{ - Client **tc; - c->next = NULL; - for (tc = &c->mon->clients; *tc; tc = &(*tc)->next); - *tc = c; -} - -void -attachstack(Client *c) -{ - c->snext = c->mon->stack; - c->mon->stack = c; -} - -void -buttonpress(XEvent *e) -{ - unsigned int i, x, click; - Arg arg = {0}; - Client *c; - Monitor *m; - XButtonPressedEvent *ev = &e->xbutton; - - click = ClkRootWin; - /* focus monitor if necessary */ - if ((m = wintomon(ev->window)) && m != selmon) { - unfocus(selmon->sel, 1); - selmon = m; - focus(NULL); - } - if (ev->window == selmon->barwin) { - i = x = 0; - unsigned int occ = 0; - for(c = m->clients; c; c=c->next) - occ |= c->tags; - do { - /* Do not reserve space for vacant tags */ - if (hidevacanttags && !(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) - continue; - x += TEXTW(tags[i]); - } while (ev->x >= x && ++i < LENGTH(tags)); - if (i < LENGTH(tags)) { - click = ClkTagBar; - arg.ui = 1 << i; - } else if (ev->x < x + blw) - click = ClkLtSymbol; - else if (showtitle != 1 || ev->x > selmon->ww - (int)TEXTW(stext) - getsystraywidth()) - click = ClkStatusText; - else - click = ClkWinTitle; - } else if ((c = wintoclient(ev->window))) { - focus(c); - restack(selmon); - XAllowEvents(dpy, ReplayPointer, CurrentTime); - click = ClkClientWin; - } - for (i = 0; i < LENGTH(buttons); i++) - if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button - && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) - buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); -} - -void -checkotherwm(void) -{ - xerrorxlib = XSetErrorHandler(xerrorstart); - /* this causes an error if some other window manager is running */ - XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask); - XSync(dpy, False); - XSetErrorHandler(xerror); - XSync(dpy, False); -} - -void -cleanup(void) -{ - Arg a = {.ui = ~0}; - Layout foo = { "", NULL }; - Monitor *m; - size_t i; - - view(&a); - selmon->lt[selmon->sellt] = &foo; - for (m = mons; m; m = m->next) - while (m->stack) - unmanage(m->stack, 0); - 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) + 1; i++) - free(scheme[i]); - free(scheme); - XDestroyWindow(dpy, wmcheckwin); - drw_free(drw); - XSync(dpy, False); - XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); - XDeleteProperty(dpy, root, netatom[NetActiveWindow]); -} - -void -cleanupmon(Monitor *mon) -{ - Monitor *m; - - if (mon == mons) - mons = mons->next; - else { - for (m = mons; m && m->next != mon; m = m->next); - m->next = mon->next; - } - XUnmapWindow(dpy, mon->barwin); - XDestroyWindow(dpy, mon->barwin); - free(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]) { - if (cme->data.l[1] == netatom[NetWMFullscreen] - || cme->data.l[2] == netatom[NetWMFullscreen]) - setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ - || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); - } else if (cme->message_type == netatom[NetActiveWindow]) { - if (c != selmon->sel && !c->isurgent) - seturgent(c, 1); - } -} - -void -configure(Client *c) -{ - XConfigureEvent ce; - - ce.type = ConfigureNotify; - ce.display = dpy; - ce.event = c->win; - ce.window = c->win; - ce.x = c->x; - ce.y = c->y; - ce.width = c->w; - ce.height = c->h; - ce.border_width = c->bw; - ce.above = None; - ce.override_redirect = False; - XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce); -} - -void -configurenotify(XEvent *e) -{ - Monitor *m; - Client *c; - XConfigureEvent *ev = &e->xconfigure; - int dirty; - - /* TODO: updategeom handling sucks, needs to be simplified */ - if (ev->window == root) { - dirty = (sw != ev->width || sh != ev->height); - sw = ev->width; - sh = ev->height; - if (updategeom() || dirty) { - drw_resize(drw, sw, bh); - updatebars(); - for (m = mons; m; m = m->next) { - for (c = m->clients; c; c = c->next) - if (c->isfullscreen) - resizeclient(c, m->mx, m->my, m->mw, m->mh); - resizebarwin(m); - } - focus(NULL); - arrange(NULL); - } - } -} - -void -configurerequest(XEvent *e) -{ - Client *c; - Monitor *m; - XConfigureRequestEvent *ev = &e->xconfigurerequest; - XWindowChanges wc; - - if ((c = wintoclient(ev->window))) { - if (ev->value_mask & CWBorderWidth) - c->bw = ev->border_width; - else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) { - m = c->mon; - if (ev->value_mask & CWX) { - c->oldx = c->x; - c->x = m->mx + ev->x; - } - if (ev->value_mask & CWY) { - c->oldy = c->y; - c->y = m->my + ev->y; - } - if (ev->value_mask & CWWidth) { - c->oldw = c->w; - c->w = ev->width; - } - if (ev->value_mask & CWHeight) { - c->oldh = c->h; - c->h = ev->height; - } - if ((c->x + c->w) > m->mx + m->mw && c->isfloating) - c->x = m->mx + (m->mw / 2 - WIDTH(c) / 2); /* center in x direction */ - if ((c->y + c->h) > m->my + m->mh && c->isfloating) - c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */ - if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight))) - configure(c); - if (ISVISIBLE(c)) - XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); - } else - configure(c); - } else { - wc.x = ev->x; - wc.y = ev->y; - wc.width = ev->width; - wc.height = ev->height; - wc.border_width = ev->border_width; - wc.sibling = ev->above; - wc.stack_mode = ev->detail; - XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); - } - XSync(dpy, False); -} - -Monitor * -createmon(void) -{ - Monitor *m; - - m = ecalloc(1, sizeof(Monitor)); - m->tagset[0] = m->tagset[1] = 1; - m->mfact = mfact; - m->nmaster = nmaster; - m->showbar = showbar; - m->topbar = topbar; - m->gappx = gappx; - m->colorfultag = colorfultag ? colorfultag : 0; - m->lt[0] = &layouts[layouts_default]; - m->lt[1] = &layouts[(layouts_default + 1) % LENGTH(layouts)]; - strncpy(m->ltsymbol, layouts[layouts_default].symbol, sizeof m->ltsymbol); - return m; -} - -void -cyclelayout(const Arg *arg) { - Layout *l; - for(l = (Layout *)layouts; l != selmon->lt[selmon->sellt]; l++); - if(arg->i > 0) { - if(l->symbol && (l + 1)->symbol) - setlayout(&((Arg) { .v = (l + 1) })); - else - setlayout(&((Arg) { .v = layouts })); - } else { - if(l != layouts && (l - 1)->symbol) - setlayout(&((Arg) { .v = (l - 1) })); - else - setlayout(&((Arg) { .v = &layouts[LENGTH(layouts) - 2] })); - } -} - -void -destroynotify(XEvent *e) -{ - Client *c; - XDestroyWindowEvent *ev = &e->xdestroywindow; - - if ((c = wintoclient(ev->window))) - unmanage(c, 1); - else if ((c = wintosystrayicon(ev->window))) { - removesystrayicon(c); - resizebarwin(selmon); - updatesystray(); - } -} - -void -detach(Client *c) -{ - Client **tc; - - for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); - *tc = c->next; -} - -void -detachstack(Client *c) -{ - Client **tc, *t; - - for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext); - *tc = c->snext; - - if (c == c->mon->sel) { - for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext); - c->mon->sel = t; - } -} - -Monitor * -dirtomon(int dir) -{ - Monitor *m = NULL; - - if (dir > 0) { - if (!(m = selmon->next)) - m = mons; - } else if (selmon == mons) - for (m = mons; m->next; m = m->next); - else - for (m = mons; m->next != selmon; m = m->next); - return m; -} - -int -drawstatusbar(Monitor *m, int bh, char* stext) { - int ret, i, w, x, len; - short isCode = 0; - char *text; - char *p; - - len = strlen(stext) + 1 ; - if (!(text = (char*) malloc(sizeof(char)*len))) - die("malloc"); - p = text; - memcpy(text, stext, len); - - /* compute width of the status text */ - w = 0; - i = -1; - while (text[++i]) { - if (text[i] == '^') { - if (!isCode) { - isCode = 1; - text[i] = '\0'; - w += TEXTW(text) - lrpad; - text[i] = '^'; - if (text[++i] == 'f') - w += atoi(text + ++i); - } else { - isCode = 0; - text = text + i + 1; - i = -1; - } - } - } - if (!isCode) - w += TEXTW(text) - lrpad; - else - isCode = 0; - text = p; - if (showsystray) - /* Xpx padding on both sides */ - w += systraypadding * 2; - ret = m->ww - w; - x = m->ww - w - getsystraywidth(); - - drw_setscheme(drw, scheme[LENGTH(colors)]); - drw->scheme[ColFg] = scheme[SchemeNorm][ColFg]; - drw->scheme[ColBg] = scheme[SchemeNorm][ColBg]; - drw_rect(drw, x, 0, w, bh, 1, 1); - x++; - - /* process status text */ - i = -1; - while (text[++i]) { - if (text[i] == '^' && !isCode) { - isCode = 1; - - text[i] = '\0'; - w = TEXTW(text) - lrpad; - drw_text(drw, x, 0, w, bh, 0, text, 0); - - x += w; - - /* process code */ - while (text[++i] != '^') { - if (text[i] == 'c') { - char buf[8]; - memcpy(buf, (char*)text+i+1, 7); - buf[7] = '\0'; - drw_clr_create(drw, &drw->scheme[ColFg], buf); - i += 7; - } else if (text[i] == 'b') { - char buf[8]; - memcpy(buf, (char*)text+i+1, 7); - buf[7] = '\0'; - drw_clr_create(drw, &drw->scheme[ColBg], buf); - i += 7; - } else if (text[i] == 'd') { - drw->scheme[ColFg] = scheme[SchemeNorm][ColFg]; - drw->scheme[ColBg] = scheme[SchemeNorm][ColBg]; - } else if (text[i] == 'r') { - int rx = atoi(text + ++i); - while (text[++i] != ','); - int ry = atoi(text + ++i); - while (text[++i] != ','); - int rw = atoi(text + ++i); - while (text[++i] != ','); - int rh = atoi(text + ++i); - - drw_rect(drw, rx + x, ry, rw, rh, 1, 0); - } else if (text[i] == 'f') { - x += atoi(text + ++i); - } - } - - text = text + i + 1; - i=-1; - isCode = 0; - } - } - - if (!isCode) { - w = TEXTW(text) - lrpad; - drw_text(drw, x, 0, w, bh, 0, text, 0); - } - - drw_setscheme(drw, scheme[SchemeNorm]); - free(p); - - return ret; -} - -Monitor * -numtomon(int num) -{ - Monitor *m = NULL; - int i = 0; - - for(m = mons, i=0; m->next && i < num; m = m->next){ - i++; - } - return m; -} - -void -drawbar(Monitor *m) -{ - 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 (!m->showbar) - return; - - if (showsystray && m == systraytomon(m) && !systrayonleft) - stw = getsystraywidth(); - - /* draw status first so it can be overdrawn by tags later */ - if (m == selmon || 1) { /* status is drawn on all monitors */ - //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); - apply_fribidi(stext); - tw = m->ww - drawstatusbar(m, bh, fribidi_text); - } - - resizebarwin(m); - - for (c = m->clients; c; c = c->next) { - occ |= c->tags; - if (c->isurgent) - urg |= c->tags; - } - x = 0; - for (i = 0; i < LENGTH(tags); i++) { - if (hidevacanttags) /* Do not draw vacant tags */ - if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) continue; - if (colorfultag) - //drw_setscheme(drw, (m->tagset[m->seltags] & 1 << i ? tagscheme[i] : scheme[SchemeNorm])); - //drw_setscheme(drw, (m->tagset[m->seltags] & 1 << i ? tagscheme_sel[i] : tagscheme[i])); - drw_setscheme(drw, (occ & 1 << i ? (m->tagset[m->seltags] & 1 << i ? tagscheme_sel[i] : tagscheme[i]) : scheme[SchemeNorm])); - else - drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); - apply_fribidi(tags[i]); - w = TEXTW(fribidi_text); - drw_text(drw, x, 0, w, bh, lrpad / 2, fribidi_text, urg & 1 << i); - if (!hidetagindicator) /* Do not draw top-left tag indicators */ - if (occ & 1 << i) - drw_rect(drw, x + boxs, boxs, boxw, boxw, - m == selmon && selmon->sel && selmon->sel->tags & 1 << i, - urg & 1 << i); - x += w; - } - apply_fribidi(m->ltsymbol); - w = blw = TEXTW(fribidi_text); - drw_setscheme(drw, scheme[SchemeLayout]); - x = drw_text(drw, x, 0, w, bh, lrpad / 2, fribidi_text, 0); - - if ((w = m->ww - tw - stw - x) > bh) { - if (showtitle && m->sel) { - drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); - apply_fribidi(m->sel->name); - int mid = lrpad / 2; - if (truecenteredtitle && TEXTW(fribidi_text) <= w) - mid = (w - TEXTW(fribidi_text)) / 2; - //mid = lrpad / 2; - drw_text(drw, x, 0, w, bh, mid, fribidi_text, 0); - if (m->sel->isfloating && !hidetagindicator) - drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); - } else { - drw_setscheme(drw, scheme[SchemeNorm]); - drw_rect(drw, x, 0, w, bh, 1, 1); - } - } - drw_map(drw, m->barwin, 0, 0, m->ww - stw, bh); -} - -void -drawbars(void) -{ - Monitor *m; - - for (m = mons; m; m = m->next) - drawbar(m); -} - -void -enternotify(XEvent *e) -{ - Client *c; - Monitor *m; - XCrossingEvent *ev = &e->xcrossing; - - if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) - return; - c = wintoclient(ev->window); - m = c ? c->mon : wintomon(ev->window); - if (m != selmon) { - unfocus(selmon->sel, 1); - selmon = m; - } else if (!c || c == selmon->sel) - return; - focus(c); -} - -void -expose(XEvent *e) -{ - Monitor *m; - XExposeEvent *ev = &e->xexpose; - - if (ev->count == 0 && (m = wintomon(ev->window))) { - drawbar(m); - if (m == selmon) - updatesystray(); - } -} - -void -focus(Client *c) -{ - if (!c || !ISVISIBLE(c)) - for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); - if (selmon->sel && selmon->sel != c) - unfocus(selmon->sel, 0); - if (c) { - if (c->mon != selmon) - selmon = c->mon; - if (c->isurgent) - seturgent(c, 0); - detachstack(c); - attachstack(c); - grabbuttons(c, 1); - XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); - setfocus(c); - } else { - XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); - XDeleteProperty(dpy, root, netatom[NetActiveWindow]); - } - selmon->sel = c; - drawbars(); -} - -/* there are some broken focus acquiring clients needing extra handling */ -void -focusin(XEvent *e) -{ - XFocusChangeEvent *ev = &e->xfocus; - - if (selmon->sel && ev->window != selmon->sel->win) - setfocus(selmon->sel); -} - -void -focusmon(const Arg *arg) -{ - Monitor *m; - - if (!mons->next) - return; - if ((m = dirtomon(arg->i)) == selmon) - return; - unfocus(selmon->sel, 0); - selmon = m; - focus(NULL); - warp(selmon->sel); -} - -void -focusnthmon(const Arg *arg) -{ - Monitor *m; - - if (!mons->next) - return; - - if ((m = numtomon(arg->i)) == selmon) - return; - unfocus(selmon->sel, 0); - selmon = m; - focus(NULL); - warp(selmon->sel); -} - -void -focusstack(const Arg *arg) -{ - Client *c = NULL, *i; - - if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen)) - return; - if (arg->i > 0) { - for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); - if (!c) - for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); - } else { - for (i = selmon->clients; i != selmon->sel; i = i->next) - if (ISVISIBLE(i)) - c = i; - if (!c) - for (; i; i = i->next) - if (ISVISIBLE(i)) - c = i; - } - if (c) { - focus(c); - restack(selmon); - } -} - -Atom -getatomprop(Client *c, Atom prop) -{ - int di; - unsigned long dl; - unsigned char *p = NULL; - Atom da, atom = None; - - /* FIXME getatomprop should return the number of items and a pointer to - * the stored data instead of this workaround */ - Atom req = XA_ATOM; - if (prop == xatom[XembedInfo]) - req = xatom[XembedInfo]; - - 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; -} - -int -getrootptr(int *x, int *y) -{ - int di; - unsigned int dui; - Window dummy; - - return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui); -} - -long -getstate(Window w) -{ - int format; - long result = -1; - unsigned char *p = NULL; - unsigned long n, extra; - Atom real; - - if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], - &real, &format, &n, &extra, (unsigned char **)&p) != Success) - return -1; - if (n != 0) - result = *p; - XFree(p); - return result; -} - -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) -{ - char **list = NULL; - int n; - XTextProperty name; - - if (!text || size == 0) - return 0; - text[0] = '\0'; - if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems) - return 0; - if (name.encoding == XA_STRING) - strncpy(text, (char *)name.value, size - 1); - else { - if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) { - strncpy(text, *list, size - 1); - XFreeStringList(list); - } - } - text[size - 1] = '\0'; - XFree(name.value); - return 1; -} - -void -grabbuttons(Client *c, int focused) -{ - updatenumlockmask(); - { - unsigned int i, j; - unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; - XUngrabButton(dpy, AnyButton, AnyModifier, c->win); - if (!focused) - XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, - BUTTONMASK, GrabModeSync, GrabModeSync, None, None); - for (i = 0; i < LENGTH(buttons); i++) - if (buttons[i].click == ClkClientWin) - for (j = 0; j < LENGTH(modifiers); j++) - XGrabButton(dpy, buttons[i].button, - buttons[i].mask | modifiers[j], - c->win, False, BUTTONMASK, - GrabModeAsync, GrabModeSync, None, None); - } -} - -void -grabkeys(void) -{ - updatenumlockmask(); - { - unsigned int i, j; - unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; - KeyCode code; - - XUngrabKey(dpy, AnyKey, AnyModifier, root); - for (i = 0; i < LENGTH(keys); i++) - if ((code = XKeysymToKeycode(dpy, keys[i].keysym))) - for (j = 0; j < LENGTH(modifiers); j++) - XGrabKey(dpy, code, keys[i].mod | modifiers[j], root, - True, GrabModeAsync, GrabModeAsync); - } -} - -void -incnmaster(const Arg *arg) -{ - selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); - arrange(selmon); -} - -#ifdef XINERAMA -static int -isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) -{ - while (n--) - if (unique[n].x_org == info->x_org && unique[n].y_org == info->y_org - && unique[n].width == info->width && unique[n].height == info->height) - return 0; - return 1; -} -#endif /* XINERAMA */ - -void -keypress(XEvent *e) -{ - unsigned int i; - KeySym keysym; - XKeyEvent *ev; - - ev = &e->xkey; - keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); - for (i = 0; i < LENGTH(keys); i++) - if (keysym == keys[i].keysym - && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) - && keys[i].func) - keys[i].func(&(keys[i].arg)); -} - -void -killclient(const Arg *arg) -{ - if (!selmon->sel) - return; - - if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0 , 0, 0)) { - XGrabServer(dpy); - XSetErrorHandler(xerrordummy); - XSetCloseDownMode(dpy, DestroyAll); - XKillClient(dpy, selmon->sel->win); - XSync(dpy, False); - XSetErrorHandler(xerror); - XUngrabServer(dpy); - } -} - -void -manage(Window w, XWindowAttributes *wa) -{ - Client *c, *t = NULL; - Window trans = None; - XWindowChanges wc; - - c = ecalloc(1, sizeof(Client)); - c->win = w; - /* geometry */ - c->x = c->oldx = wa->x; - c->y = c->oldy = wa->y; - c->w = c->oldw = wa->width; - c->h = c->oldh = wa->height; - c->oldbw = wa->border_width; - - updatetitle(c); - if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { - c->mon = t->mon; - c->tags = t->tags; - } else { - c->mon = selmon; - applyrules(c); - } - - if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) - c->x = c->mon->mx + c->mon->mw - WIDTH(c); - if (c->y + HEIGHT(c) > c->mon->my + c->mon->mh) - c->y = c->mon->my + c->mon->mh - HEIGHT(c); - c->x = MAX(c->x, c->mon->mx); - /* only fix client y-offset, if the client center might cover the bar */ - c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx) - && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); - c->bw = borderpx; - - wc.border_width = c->bw; - XConfigureWindow(dpy, w, CWBorderWidth, &wc); - XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); - configure(c); /* propagates border_width, if size doesn't change */ - updatewindowtype(c); - updatesizehints(c); - updatewmhints(c); - { - int format; - unsigned long *data, n, extra; - Monitor *m; - Atom atom; - if (XGetWindowProperty(dpy, c->win, netatom[NetClientInfo], 0L, 2L, False, XA_CARDINAL, - &atom, &format, &n, &extra, (unsigned char **)&data) == Success && n == 2) { - c->tags = *data; - for (m = mons; m; m = m->next) { - if (m->num == *(data+1)) { - c->mon = m; - break; - } - } - } - if (n > 0) - XFree(data); - } - setclienttagprop(c); - - c->x = c->mon->mx + (c->mon->mw - WIDTH(c)) / 2; - c->y = c->mon->my + (c->mon->mh - HEIGHT(c)) / 2; - XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); - grabbuttons(c, 0); - if (!c->isfloating) - c->isfloating = c->oldstate = trans != None || c->isfixed; - if (c->isfloating) - XRaiseWindow(dpy, c->win); - attachbottom(c); - attachstack(c); - setclienttagprop(c); - XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); - XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ - setclientstate(c, NormalState); - if (c->mon == selmon) - unfocus(selmon->sel, 0); - c->mon->sel = c; - arrange(c->mon); - XMapWindow(dpy, c->win); - focus(NULL); -} - -void -mappingnotify(XEvent *e) -{ - XMappingEvent *ev = &e->xmapping; - - XRefreshKeyboardMapping(ev); - if (ev->request == MappingKeyboard) - grabkeys(); -} - -void -maprequest(XEvent *e) -{ - static XWindowAttributes wa; - XMapRequestEvent *ev = &e->xmaprequest; - - 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; - if (wa.override_redirect) - return; - if (!wintoclient(ev->window)) - manage(ev->window, &wa); -} - -void -monocle(Monitor *m) -{ - unsigned int n = 0; - Client *c; - - for (c = m->clients; c; c = c->next) - if (ISVISIBLE(c)) - n++; - if (n > 0) /* override layout symbol */ - snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); - for (c = nexttiled(m->clients); c; c = nexttiled(c->next)) - resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0); -} - -void -motionnotify(XEvent *e) -{ - static Monitor *mon = NULL; - Monitor *m; - XMotionEvent *ev = &e->xmotion; - - if (ev->window != root) - return; - if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { - unfocus(selmon->sel, 1); - selmon = m; - focus(NULL); - } - mon = m; -} - -void -moveorplace(const Arg *arg) { - if ((!selmon->lt[selmon->sellt]->arrange || (selmon->sel && selmon->sel->isfloating))) - movemouse(arg); - else - placemouse(arg); -} - -void -movemouse(const Arg *arg) -{ - int x, y, ocx, ocy, nx, ny; - Client *c; - Monitor *m; - XEvent ev; - Time lasttime = 0; - - if (!(c = selmon->sel)) - return; - if (c->isfullscreen) /* no support moving fullscreen windows by mouse */ - return; - restack(selmon); - ocx = c->x; - ocy = c->y; - if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) - return; - if (!getrootptr(&x, &y)) - return; - do { - XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); - switch(ev.type) { - case ConfigureRequest: - case Expose: - case MapRequest: - handler[ev.type](&ev); - break; - case MotionNotify: - if ((ev.xmotion.time - lasttime) <= (100 / 60)) - continue; - lasttime = ev.xmotion.time; - - nx = ocx + (ev.xmotion.x - x); - ny = ocy + (ev.xmotion.y - y); - if (abs(selmon->wx - nx) < snap) - nx = selmon->wx; - else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) - nx = selmon->wx + selmon->ww - WIDTH(c); - if (abs(selmon->wy - ny) < snap) - ny = selmon->wy; - else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap) - ny = selmon->wy + selmon->wh - HEIGHT(c); - if (!c->isfloating && selmon->lt[selmon->sellt]->arrange - && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) - togglefloating(NULL); - if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, nx, ny, c->w, c->h, 1); - break; - } - } while (ev.type != ButtonRelease); - XUngrabPointer(dpy, CurrentTime); - if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { - sendmon(c, m); - selmon = m; - focus(NULL); - } -} - -Client * -nexttiled(Client *c) -{ - for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); - return c; -} - -void -placemouse(const Arg *arg) -{ - int x, y, px, py, ocx, ocy, nx = -9999, ny = -9999, freemove = 0; - Client *c, *r = NULL, *at, *prevr; - Monitor *m; - XEvent ev; - XWindowAttributes wa; - Time lasttime = 0; - int attachmode, prevattachmode; - attachmode = prevattachmode = -1; - - if (!(c = selmon->sel) || !c->mon->lt[c->mon->sellt]->arrange) /* no support for placemouse when floating layout is used */ - return; - if (c->isfullscreen) /* no support placing fullscreen windows by mouse */ - return; - restack(selmon); - prevr = c; - if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) - return; - - c->isfloating = 0; - c->beingmoved = 1; - - XGetWindowAttributes(dpy, c->win, &wa); - ocx = wa.x; - ocy = wa.y; - - if (arg->i == 2) // warp cursor to client center - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, WIDTH(c) / 2, HEIGHT(c) / 2); - - if (!getrootptr(&x, &y)) - return; - - do { - XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); - switch (ev.type) { - case ConfigureRequest: - case Expose: - case MapRequest: - handler[ev.type](&ev); - break; - case MotionNotify: - if ((ev.xmotion.time - lasttime) <= (100 / 60)) - continue; - lasttime = ev.xmotion.time; - - nx = ocx + (ev.xmotion.x - x); - ny = ocy + (ev.xmotion.y - y); - - if (!freemove && (abs(nx - ocx) > snap || abs(ny - ocy) > snap)) - freemove = 1; - - if (freemove) - XMoveWindow(dpy, c->win, nx, ny); - - if ((m = recttomon(ev.xmotion.x, ev.xmotion.y, 1, 1)) && m != selmon) - selmon = m; - - if (arg->i == 1) { // tiled position is relative to the client window center point - px = nx + wa.width / 2; - py = ny + wa.height / 2; - } else { // tiled position is relative to the mouse cursor - px = ev.xmotion.x; - py = ev.xmotion.y; - } - - r = recttoclient(px, py, 1, 1); - - if (!r || r == c) - break; - - attachmode = 0; // below - if (((float)(r->y + r->h - py) / r->h) > ((float)(r->x + r->w - px) / r->w)) { - if (abs(r->y - py) < r->h / 2) - attachmode = 1; // above - } else if (abs(r->x - px) < r->w / 2) - attachmode = 1; // above - - if ((r && r != prevr) || (attachmode != prevattachmode)) { - detachstack(c); - detach(c); - if (c->mon != r->mon) { - arrangemon(c->mon); - c->tags = r->mon->tagset[r->mon->seltags]; - } - - c->mon = r->mon; - r->mon->sel = r; - - if (attachmode) { - if (r == r->mon->clients) - attach(c); - else { - for (at = r->mon->clients; at->next != r; at = at->next); - c->next = at->next; - at->next = c; - } - } else { - c->next = r->next; - r->next = c; - } - - attachstack(c); - arrangemon(r->mon); - prevr = r; - prevattachmode = attachmode; - } - break; - } - } while (ev.type != ButtonRelease); - XUngrabPointer(dpy, CurrentTime); - - if ((m = recttomon(ev.xmotion.x, ev.xmotion.y, 1, 1)) && m != c->mon) { - detach(c); - detachstack(c); - arrangemon(c->mon); - c->mon = m; - c->tags = m->tagset[m->seltags]; - attach(c); - attachstack(c); - selmon = m; - } - - focus(c); - c->beingmoved = 0; - - if (nx != -9999) - resize(c, nx, ny, c->w, c->h, 0); - arrangemon(c->mon); -} - -void -pop(Client *c) -{ - detach(c); - attach(c); - focus(c); - arrange(c->mon); -} - -void -propertynotify(XEvent *e) -{ - Client *c; - Window trans; - XPropertyEvent *ev = &e->xproperty; - - if ((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) - return; /* ignore */ - else if ((c = wintoclient(ev->window))) { - switch(ev->atom) { - default: break; - case XA_WM_TRANSIENT_FOR: - if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) && - (c->isfloating = (wintoclient(trans)) != NULL)) - arrange(c->mon); - break; - case XA_WM_NORMAL_HINTS: - updatesizehints(c); - break; - case XA_WM_HINTS: - updatewmhints(c); - drawbars(); - break; - } - if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { - updatetitle(c); - if (showtitle && c == c->mon->sel) - drawbar(c->mon); - } - if (ev->atom == netatom[NetWMWindowType]) - updatewindowtype(c); - } -} - -void -restart(const Arg *arg) -{ - restartsig = 1; - quit(arg); -} - -void -quit(const Arg *arg) -{ - running = 0; -} - -Client * -recttoclient(int x, int y, int w, int h) -{ - Client *c, *r = NULL; - int a, area = 0; - - for (c = nexttiled(selmon->clients); c; c = nexttiled(c->next)) { - if ((a = INTERSECTC(x, y, w, h, c)) > area) { - area = a; - r = c; - } - } - return r; -} - -Monitor * -recttomon(int x, int y, int w, int h) -{ - Monitor *m, *r = selmon; - int a, area = 0; - - for (m = mons; m; m = m->next) - if ((a = INTERSECT(x, y, w, h, m)) > area) { - area = a; - r = m; - } - return r; -} - -void -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) -{ - if (applysizehints(c, &x, &y, &w, &h, interact)) - resizeclient(c, x, y, w, h); -} - -void -resizebarwin(Monitor *m) { - unsigned int w = m->ww; - if (showsystray && m == systraytomon(m) && !systrayonleft) - w -= getsystraywidth(); - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh); -} - -void -resizeclient(Client *c, int x, int y, int w, int h) -{ - XWindowChanges wc; - - c->oldx = c->x; c->x = wc.x = x; - c->oldy = c->y; c->y = wc.y = y; - c->oldw = c->w; c->w = wc.width = w; - c->oldh = c->h; c->h = wc.height = h; - - if (c->beingmoved) - return; - - wc.border_width = c->bw; - if (((nexttiled(c->mon->clients) == c && !nexttiled(c->next)) - || &monocle == c->mon->lt[c->mon->sellt]->arrange) - && !c->isfullscreen && !c->isfloating - && NULL != c->mon->lt[c->mon->sellt]->arrange) { - c->w = wc.width += c->bw * 2; - c->h = wc.height += c->bw * 2; - wc.border_width = 0; - } - XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); - configure(c); - XSync(dpy, False); -} - -void -resizemouse(const Arg *arg) -{ - int ocx, ocy, nw, nh; - Client *c; - Monitor *m; - XEvent ev; - Time lasttime = 0; - - if (!(c = selmon->sel)) - return; - if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ - return; - restack(selmon); - ocx = c->x; - ocy = c->y; - if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) - return; - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); - do { - XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); - switch(ev.type) { - case ConfigureRequest: - case Expose: - case MapRequest: - handler[ev.type](&ev); - break; - case MotionNotify: - if ((ev.xmotion.time - lasttime) <= (1000 / 60)) - continue; - lasttime = ev.xmotion.time; - - nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); - nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); - if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww - && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh) - { - if (!c->isfloating && selmon->lt[selmon->sellt]->arrange - && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) - togglefloating(NULL); - } - if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, c->x, c->y, nw, nh, 1); - break; - } - } while (ev.type != ButtonRelease); - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); - XUngrabPointer(dpy, CurrentTime); - while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); - if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { - sendmon(c, m); - selmon = m; - focus(NULL); - } -} - -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) -{ - Client *c; - XEvent ev; - XWindowChanges wc; - - drawbar(m); - if (!m->sel) - return; - if (m->sel->isfloating || !m->lt[m->sellt]->arrange) - XRaiseWindow(dpy, m->sel->win); - if (m->lt[m->sellt]->arrange) { - wc.stack_mode = Below; - wc.sibling = m->barwin; - for (c = m->stack; c; c = c->snext) - if (!c->isfloating && ISVISIBLE(c)) { - XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); - wc.sibling = c->win; - } - } - XSync(dpy, False); - while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); - if (m == selmon && (m->tagset[m->seltags] & m->sel->tags) && selmon->lt[selmon->sellt] != &layouts[2]) - warp(m->sel); -} - -void -run(void) -{ - XEvent ev; - /* main event loop */ - XSync(dpy, False); - while (running && !XNextEvent(dpy, &ev)) - if (handler[ev.type]) - handler[ev.type](&ev); /* call handler */ -} - -void -scan(void) -{ - unsigned int i, num; - Window d1, d2, *wins = NULL; - XWindowAttributes wa; - - if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { - for (i = 0; i < num; i++) { - if (!XGetWindowAttributes(dpy, wins[i], &wa) - || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) - continue; - if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) - manage(wins[i], &wa); - } - for (i = 0; i < num; i++) { /* now the transients */ - if (!XGetWindowAttributes(dpy, wins[i], &wa)) - continue; - if (XGetTransientForHint(dpy, wins[i], &d1) - && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)) - manage(wins[i], &wa); - } - if (wins) - XFree(wins); - } -} - -void -sendmon(Client *c, Monitor *m) -{ - if (c->mon == m) - return; - unfocus(c, 1); - detach(c); - detachstack(c); - c->mon = m; - c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ - attachbottom(c); - attachstack(c); - focus(NULL); - arrange(NULL); -} - -void -setclientstate(Client *c, long state) -{ - long data[] = { state, None }; - - XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, - PropModeReplace, (unsigned char *)data, 2); -} - -int -sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4) -{ - int n; - Atom *protocols, mt; - int exists = 0; - XEvent ev; - - 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 = w; - ev.xclient.message_type = mt; - ev.xclient.format = 32; - 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; -} - -void -setfocus(Client *c) -{ - if (!c->neverfocus) { - XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); - XChangeProperty(dpy, root, netatom[NetActiveWindow], - XA_WINDOW, 32, PropModeReplace, - (unsigned char *) &(c->win), 1); - } - sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0); -} - -void -setfullscreen(Client *c, int fullscreen) -{ - if (fullscreen && !c->isfullscreen) { - XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); - c->isfullscreen = 1; - c->oldstate = c->isfloating; - c->oldbw = c->bw; - c->bw = 0; - c->isfloating = 1; - resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); - XRaiseWindow(dpy, c->win); - } else if (!fullscreen && c->isfullscreen){ - XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)0, 0); - c->isfullscreen = 0; - c->isfloating = c->oldstate; - c->bw = c->oldbw; - c->x = c->oldx; - c->y = c->oldy; - c->w = c->oldw; - c->h = c->oldh; - resizeclient(c, c->x, c->y, c->w, c->h); - arrange(c->mon); - } -} - -void -setgaps(const Arg *arg) -{ - if ((arg->i == 0) || (selmon->gappx + arg->i < 0)) - selmon->gappx = 0; - else - selmon->gappx += arg->i; - arrange(selmon); -} - -void -setlayout(const Arg *arg) -{ - if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) - selmon->sellt ^= 1; - if (arg && arg->v) - selmon->lt[selmon->sellt] = (Layout *)arg->v; - strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); - if (selmon->sel) - arrange(selmon); - else - drawbar(selmon); -} - -/* arg > 1.0 will set mfact absolutely */ -void -setmfact(const Arg *arg) -{ - float f; - - if (!arg || !selmon->lt[selmon->sellt]->arrange) - return; - f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; - if (f < 0.05 || f > 0.95) - return; - selmon->mfact = f; - arrange(selmon); -} - -void -setup(void) -{ - int i; - XSetWindowAttributes wa; - Atom utf8string; - - /* clean up any zombies immediately */ - sigchld(0); - - signal(SIGHUP, sighup); - signal(SIGTERM, sigterm); - - /* init screen */ - screen = DefaultScreen(dpy); - sw = DisplayWidth(dpy, screen); - sh = DisplayHeight(dpy, screen); - root = RootWindow(dpy, screen); - drw = drw_create(dpy, screen, root, sw, sh); - if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) - die("no fonts could be loaded."); - lrpad = drw->fonts->h; - bh = drw->fonts->h + barheight * 2; - updategeom(); - /* init atoms */ - utf8string = XInternAtom(dpy, "UTF8_STRING", False); - wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); - wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); - wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); - wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); - netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); - netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); - netatom[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); - netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); - 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); - netatom[NetClientInfo] = XInternAtom(dpy, "_NET_CLIENT_INFO", 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); - cursor[CurMove] = drw_cur_create(drw, XC_fleur); - /* init appearance */ - if (colorfultag) { - if (LENGTH(tags) > LENGTH(colortags) || LENGTH(tags) > LENGTH(colortags_sel)) - die("too few color schemes for the tags"); - tagscheme = ecalloc(LENGTH(colortags), sizeof(Clr *)); - for (i = 0; i < LENGTH(colortags); i++) - tagscheme[i] = drw_scm_create(drw, colortags[i], 2); - tagscheme_sel = ecalloc(LENGTH(colortags_sel), sizeof(Clr *)); - for (i = 0; i < LENGTH(colortags_sel); i++) - tagscheme_sel[i] = drw_scm_create(drw, colortags_sel[i], 2); - } - scheme = ecalloc(LENGTH(colors) + 1, sizeof(Clr *)); - scheme[LENGTH(colors)] = drw_scm_create(drw, colors[0], 3); - for (i = 0; i < LENGTH(colors); i++) - scheme[i] = drw_scm_create(drw, colors[i], 3); - /* init system tray */ - updatesystray(); - /* init bars */ - updatebars(); - updatestatus(); - /* supporting window for NetWMCheck */ - wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0); - XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32, - PropModeReplace, (unsigned char *) &wmcheckwin, 1); - XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8, - PropModeReplace, (unsigned char *) "dwm", 3); - XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32, - PropModeReplace, (unsigned char *) &wmcheckwin, 1); - /* EWMH support per view */ - XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, - PropModeReplace, (unsigned char *) netatom, NetLast); - XDeleteProperty(dpy, root, netatom[NetClientList]); - XDeleteProperty(dpy, root, netatom[NetClientInfo]); - /* select events */ - wa.cursor = cursor[CurNormal]->cursor; - wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask - |ButtonPressMask|PointerMotionMask|EnterWindowMask - |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; - XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); - XSelectInput(dpy, root, wa.event_mask); - grabkeys(); - focus(NULL); -} - - -void -seturgent(Client *c, int urg) -{ - XWMHints *wmh; - - c->isurgent = urg; - if (!(wmh = XGetWMHints(dpy, c->win))) - return; - wmh->flags = urg ? (wmh->flags | XUrgencyHint) : (wmh->flags & ~XUrgencyHint); - XSetWMHints(dpy, c->win, wmh); - XFree(wmh); -} - -void -showhide(Client *c) -{ - if (!c) - return; - if (ISVISIBLE(c)) { - /* show clients top down */ - XMoveWindow(dpy, c->win, c->x, c->y); - if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) - resize(c, c->x, c->y, c->w, c->h, 0); - showhide(c->snext); - } else { - /* hide clients bottom up */ - showhide(c->snext); - XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y); - } -} - -void -sigchld(int unused) -{ - if (signal(SIGCHLD, sigchld) == SIG_ERR) - die("can't install SIGCHLD handler:"); - while (0 < waitpid(-1, NULL, WNOHANG)); -} - -void -sighup(int unused) -{ - Arg a = {.i = 1}; - quit(&a); -} - -void -sigterm(int unused) -{ - Arg a = {.i = 0}; - quit(&a); -} - -void -spawn(const Arg *arg) -{ - if (arg->v == dmenucmd) - dmenumon[0] = '0' + selmon->num; - if (fork() == 0) { - if (dpy) - close(ConnectionNumber(dpy)); - setsid(); - execvp(((char **)arg->v)[0], (char **)arg->v); - die("dwm: execvp '%s' failed:", ((char **)arg->v)[0]); - } -} - -void -setclienttagprop(Client *c) -{ - long data[] = { (long) c->tags, (long) c->mon->num }; - XChangeProperty(dpy, c->win, netatom[NetClientInfo], XA_CARDINAL, 32, - PropModeReplace, (unsigned char *) data, 2); -} - - -void -tag(const Arg *arg) -{ - Client *c; - if (selmon->sel && arg->ui & TAGMASK) { - c = selmon->sel; - selmon->sel->tags = arg->ui & TAGMASK; - setclienttagprop(c); - focus(NULL); - arrange(selmon); - } -} - -void -tagmon(const Arg *arg) -{ - if (!selmon->sel || !mons->next) - return; - sendmon(selmon->sel, dirtomon(arg->i)); -} - -void -tagnthmon(const Arg *arg) -{ - if (!selmon->sel || !mons->next) - return; - sendmon(selmon->sel, numtomon(arg->i)); -} - -void -tile(Monitor *m) -{ - unsigned int i, n, h, mw, my, ty; - Client *c; - - for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); - if (n == 0) - return; - - if (n > m->nmaster) - mw = m->nmaster ? m->ww * m->mfact : 0; - else - mw = m->ww - m->gappx; - for (i = 0, my = ty = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) - if (i < m->nmaster) { - h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx; - resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0); - if (my + HEIGHT(c) + m->gappx < m->wh) - my += HEIGHT(c) + m->gappx; - } else { - h = (m->wh - ty) / (n - i) - m->gappx; - resize(c, m->wx + mw + m->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappx, h - (2*c->bw), 0); - if (ty + HEIGHT(c) + m->gappx < m->wh) - ty += HEIGHT(c) + m->gappx; - } -} - -void -togglebar(const Arg *arg) -{ - selmon->showbar = !selmon->showbar; - updatebarpos(selmon); - 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); -} - -void -togglefloating(const Arg *arg) -{ - if (!selmon->sel) - return; - if (selmon->sel->isfullscreen) /* no support for fullscreen windows */ - return; - selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; - if (selmon->sel->isfloating) - resize(selmon->sel, selmon->sel->x, selmon->sel->y, - selmon->sel->w, selmon->sel->h, 0); - arrange(selmon); -} - -void -togglesticky(const Arg *arg) -{ - if (!selmon->sel) - return; - selmon->sel->issticky = !selmon->sel->issticky; - arrange(selmon); -} - -void -togglefullscr(const Arg *arg) -{ - if(selmon->sel) - setfullscreen(selmon->sel, !selmon->sel->isfullscreen); -} - -void -toggletag(const Arg *arg) -{ - unsigned int newtags; - - if (!selmon->sel) - return; - newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); - if (newtags) { - selmon->sel->tags = newtags; - setclienttagprop(selmon->sel); - focus(NULL); - arrange(selmon); - } -} - -void -toggleview(const Arg *arg) -{ - unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); - - if (newtagset) { - selmon->tagset[selmon->seltags] = newtagset; - focus(NULL); - arrange(selmon); - } -} - -void -unfocus(Client *c, int setfocus) -{ - if (!c) - return; - grabbuttons(c, 0); - XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); - if (setfocus) { - XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); - XDeleteProperty(dpy, root, netatom[NetActiveWindow]); - } -} - -void -unmanage(Client *c, int destroyed) -{ - Monitor *m = c->mon; - XWindowChanges wc; - - detach(c); - detachstack(c); - if (!destroyed) { - wc.border_width = c->oldbw; - XGrabServer(dpy); /* avoid race conditions */ - XSetErrorHandler(xerrordummy); - XSelectInput(dpy, c->win, NoEventMask); - XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ - XUngrabButton(dpy, AnyButton, AnyModifier, c->win); - setclientstate(c, WithdrawnState); - XSync(dpy, False); - XSetErrorHandler(xerror); - XUngrabServer(dpy); - } - free(c); - focus(NULL); - updateclientlist(); - arrange(m); -} - -void -unmapnotify(XEvent *e) -{ - Client *c; - XUnmapEvent *ev = &e->xunmap; - - if ((c = wintoclient(ev->window))) { - if (ev->send_event) - setclientstate(c, WithdrawnState); - else - unmanage(c, 0); - } - 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, - .background_pixmap = ParentRelative, - .event_mask = ButtonPressMask|ExposureMask - }; - XClassHint ch = {"dwm", "dwm"}; - for (m = mons; m; m = m->next) { - if (m->barwin) - continue; - 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); - } -} - -void -updatebarpos(Monitor *m) -{ - m->wy = m->my; - m->wh = m->mh; - if (m->showbar) { - m->wh -= bh; - m->by = m->topbar ? m->wy : m->wy + m->wh; - m->wy = m->topbar ? m->wy + bh : m->wy; - } else - m->by = -bh; -} - -void -updateclientlist() -{ - Client *c; - Monitor *m; - - XDeleteProperty(dpy, root, netatom[NetClientList]); - for (m = mons; m; m = m->next) - for (c = m->clients; c; c = c->next) - XChangeProperty(dpy, root, netatom[NetClientList], - XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); -} - -int -updategeom(void) -{ - int dirty = 0; - -#ifdef XINERAMA - if (XineramaIsActive(dpy)) { - int i, j, n, nn; - Client *c; - Monitor *m; - XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); - XineramaScreenInfo *unique = NULL; - - for (n = 0, m = mons; m; m = m->next, n++); - /* only consider unique geometries as separate screens */ - unique = ecalloc(nn, sizeof(XineramaScreenInfo)); - for (i = 0, j = 0; i < nn; i++) - if (isuniquegeom(unique, j, &info[i])) - memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); - XFree(info); - nn = j; - if (n <= nn) { /* new monitors available */ - for (i = 0; i < (nn - n); i++) { - for (m = mons; m && m->next; m = m->next); - if (m) - m->next = createmon(); - else - mons = createmon(); - } - for (i = 0, m = mons; i < nn && m; m = m->next, i++) - if (i >= n - || unique[i].x_org != m->mx || unique[i].y_org != m->my - || unique[i].width != m->mw || unique[i].height != m->mh) - { - dirty = 1; - m->num = i; - m->mx = m->wx = unique[i].x_org; - m->my = m->wy = unique[i].y_org; - m->mw = m->ww = unique[i].width; - m->mh = m->wh = unique[i].height; - updatebarpos(m); - } - } else { /* less monitors available nn < n */ - for (i = nn; i < n; i++) { - for (m = mons; m && m->next; m = m->next); - while ((c = m->clients)) { - dirty = 1; - m->clients = c->next; - detachstack(c); - c->mon = mons; - attachbottom(c); - attachstack(c); - } - if (m == selmon) - selmon = mons; - cleanupmon(m); - } - } - free(unique); - } else -#endif /* XINERAMA */ - { /* default monitor setup */ - if (!mons) - mons = createmon(); - if (mons->mw != sw || mons->mh != sh) { - dirty = 1; - mons->mw = mons->ww = sw; - mons->mh = mons->wh = sh; - updatebarpos(mons); - } - } - if (dirty) { - selmon = mons; - selmon = wintomon(root); - } - return dirty; -} - -void -updatenumlockmask(void) -{ - unsigned int i, j; - XModifierKeymap *modmap; - - numlockmask = 0; - modmap = XGetModifierMapping(dpy); - for (i = 0; i < 8; i++) - for (j = 0; j < modmap->max_keypermod; j++) - if (modmap->modifiermap[i * modmap->max_keypermod + j] - == XKeysymToKeycode(dpy, XK_Num_Lock)) - numlockmask = (1 << i); - XFreeModifiermap(modmap); -} - -void -updatesizehints(Client *c) -{ - long msize; - XSizeHints size; - - if (!XGetWMNormalHints(dpy, c->win, &size, &msize)) - /* size is uninitialized, ensure that size.flags aren't used */ - size.flags = PSize; - if (size.flags & PBaseSize) { - c->basew = size.base_width; - c->baseh = size.base_height; - } else if (size.flags & PMinSize) { - c->basew = size.min_width; - c->baseh = size.min_height; - } else - c->basew = c->baseh = 0; - if (size.flags & PResizeInc) { - c->incw = size.width_inc; - c->inch = size.height_inc; - } else - c->incw = c->inch = 0; - if (size.flags & PMaxSize) { - c->maxw = size.max_width; - c->maxh = size.max_height; - } else - c->maxw = c->maxh = 0; - if (size.flags & PMinSize) { - c->minw = size.min_width; - c->minh = size.min_height; - } else if (size.flags & PBaseSize) { - c->minw = size.base_width; - c->minh = size.base_height; - } else - c->minw = c->minh = 0; - if (size.flags & PAspect) { - c->mina = (float)size.min_aspect.y / size.min_aspect.x; - c->maxa = (float)size.max_aspect.x / size.max_aspect.y; - } else - c->maxa = c->mina = 0.0; - c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh); -} - -void -updatestatus(void) -{ - Monitor* m; - if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) - strcpy(stext, "dwm-"VERSION); - for(m = mons; m; m = m->next) { - drawbar(m); - 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 sw = TEXTW(stext) - lrpad + systrayspacing; - unsigned int w = 1; - - if (!showsystray) - return; - if (systrayonleft) - x -= sw + lrpad / 2; - 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 -updatetitle(Client *c) -{ - if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) - gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name); - if (c->name[0] == '\0') /* hack to mark broken clients */ - strcpy(c->name, broken); -} - -void -updatewindowtype(Client *c) -{ - Atom state = getatomprop(c, netatom[NetWMState]); - Atom wtype = getatomprop(c, netatom[NetWMWindowType]); - - if (state == netatom[NetWMFullscreen]) - setfullscreen(c, 1); - if (wtype == netatom[NetWMWindowTypeDialog]) - c->isfloating = 1; -} - -void -updatewmhints(Client *c) -{ - XWMHints *wmh; - - if ((wmh = XGetWMHints(dpy, c->win))) { - if (c == selmon->sel && wmh->flags & XUrgencyHint) { - wmh->flags &= ~XUrgencyHint; - XSetWMHints(dpy, c->win, wmh); - } else - c->isurgent = (wmh->flags & XUrgencyHint) ? 1 : 0; - if (wmh->flags & InputHint) - c->neverfocus = !wmh->input; - else - c->neverfocus = 0; - XFree(wmh); - } -} - -void -view(const Arg *arg) -{ - if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) - return; - selmon->seltags ^= 1; /* toggle sel tagset */ - if (arg->ui & TAGMASK) - selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; - focus(NULL); - arrange(selmon); -} - -void -warp(const Client *c) -{ - int x, y; - - if (!c) { - XWarpPointer(dpy, None, root, 0, 0, 0, 0, selmon->wx + selmon->ww/2, selmon->wy + selmon->wh/2); - return; - } - - if (!getrootptr(&x, &y) || - (x > c->x - c->bw && - y > c->y - c->bw && - x < c->x + c->w + c->bw*2 && - y < c->y + c->h + c->bw*2) || - (y > c->mon->by && y < c->mon->by + bh) || - (c->mon->topbar && !y)) - return; - - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); -} - -Client * -wintoclient(Window w) -{ - Client *c; - Monitor *m; - - for (m = mons; m; m = m->next) - for (c = m->clients; c; c = c->next) - if (c->win == w) - return c; - return NULL; -} - -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) -{ - int x, y; - Client *c; - Monitor *m; - - if (w == root && getrootptr(&x, &y)) - return recttomon(x, y, 1, 1); - for (m = mons; m; m = m->next) - if (w == m->barwin) - return m; - if ((c = wintoclient(w))) - return c->mon; - return selmon; -} - -/* There's no way to check accesses to destroyed windows, thus those cases are - * ignored (especially on UnmapNotify's). Other types of errors call Xlibs - * default error handler, which may call exit. */ -int -xerror(Display *dpy, XErrorEvent *ee) -{ - if (ee->error_code == BadWindow - || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) - || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) - || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) - || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable) - || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch) - || (ee->request_code == X_GrabButton && ee->error_code == BadAccess) - || (ee->request_code == X_GrabKey && ee->error_code == BadAccess) - || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) - return 0; - fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", - ee->request_code, ee->error_code); - return xerrorxlib(dpy, ee); /* may call exit */ -} - -int -xerrordummy(Display *dpy, XErrorEvent *ee) -{ - return 0; -} - -/* Startup Error handler to check if another window manager - * is already running. */ -int -xerrorstart(Display *dpy, XErrorEvent *ee) -{ - die("dwm: another window manager is already running"); - return -1; -} - -void -movestack(const Arg *arg) { - Client *c = NULL, *p = NULL, *pc = NULL, *i; - - if(arg->i > 0) { - /* find the client after selmon->sel */ - for(c = selmon->sel->next; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); - if(!c) - for(c = selmon->clients; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); - - } - else { - /* find the client before selmon->sel */ - for(i = selmon->clients; i != selmon->sel; i = i->next) - if(ISVISIBLE(i) && !i->isfloating) - c = i; - if(!c) - for(; i; i = i->next) - if(ISVISIBLE(i) && !i->isfloating) - c = i; - } - /* find the client before selmon->sel and c */ - for(i = selmon->clients; i && (!p || !pc); i = i->next) { - if(i->next == selmon->sel) - p = i; - if(i->next == c) - pc = i; - } - - /* swap c and selmon->sel selmon->clients in the selmon->clients list */ - if(c && c != selmon->sel) { - Client *temp = selmon->sel->next==c?selmon->sel:selmon->sel->next; - selmon->sel->next = c->next==selmon->sel?c:c->next; - c->next = temp; - - if(p && p != c) - p->next = c; - if(pc && pc != selmon->sel) - pc->next = selmon->sel; - - if(selmon->sel == selmon->clients) - selmon->clients = c; - else if(c == selmon->clients) - selmon->clients = selmon->sel; - - arrange(selmon); - } -} - -void -shiftview(const Arg *arg) -{ - Arg a; - Client *c; - unsigned visible = 0; - int i = arg->i; - int count = 0; - int nextseltags, curseltags = selmon->tagset[selmon->seltags]; - - do { - if(i > 0) // left circular shift - nextseltags = (curseltags << i) | (curseltags >> (LENGTH(tags) - i)); - else // right circular shift - nextseltags = curseltags >> (- i) | (curseltags << (LENGTH(tags) + i)); - - // Check if tag is visible - for (c = selmon->clients; c && !visible; c = c->next) - if (nextseltags & c->tags) { visible = 1; break; } - - i += arg->i; - } while (!visible && ++count < LENGTH(tags)); - - if (count < LENGTH(tags)) { - a.i = nextseltags; - view(&a); - } -} - -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) -{ - Client *c = selmon->sel; - - if (!selmon->lt[selmon->sellt]->arrange - || (selmon->sel && selmon->sel->isfloating)) - return; - if (c == nexttiled(selmon->clients)) - if (!c || !(c = nexttiled(c->next))) - return; - pop(c); -} - -void -resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst) -{ - char *sdst = NULL; - int *idst = NULL; - float *fdst = NULL; - - sdst = dst; - idst = dst; - fdst = dst; - - char fullname[256]; - char *type; - XrmValue ret; - - snprintf(fullname, sizeof(fullname), "%s.%s", "dwm", name); - fullname[sizeof(fullname) - 1] = '\0'; - - XrmGetResource(db, fullname, "*", &type, &ret); - if (!(ret.addr == NULL || strncmp("String", type, 64))) - { - switch (rtype) { - case STRING: - strcpy(sdst, ret.addr); - break; - case INTEGER: - *idst = strtoul(ret.addr, NULL, 10); - break; - case FLOAT: - *fdst = strtof(ret.addr, NULL); - break; - } - } -} - -void -live_reload_xresources(const Arg *arg) -{ - load_xresources(); - - Monitor *m; - XSetWindowAttributes wa; - unsigned int i; - - for (m = mons; m; m = m->next) { - - for(Client *c = m->clients; c; c = c->next) { - XWindowChanges wc; - wc.border_width = borderpx; - XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); - } - - } - for (i = 0; i < LENGTH(colors); i++) - scheme[i] = drw_scm_create(drw, colors[i], 3); - - focus(NULL); - arrange(NULL); -} - -void -load_xresources(void) -{ - Display *display; - char *resm; - XrmDatabase db; - ResourcePref *p; - - display = XOpenDisplay(NULL); - resm = XResourceManagerString(display); - if (!resm) - return; - db = XrmGetStringDatabase(resm); - for ( p = resources; p < resources + LENGTH(resources); p++) - resource_load(db, p->name, p->type, p->dst); - XCloseDisplay(display); -} - - -int -main(int argc, char *argv[]) -{ - if (argc == 2 && !strcmp("-v", argv[1])) - die("dwm-"VERSION); - else if (argc == 2 && !strcmp("-f", argv[1])) - layouts_default = layouts_floating; - else if (argc != 1 && strcmp("-s", argv[1])) - die("usage: dwm [-fvh] [-s STATUS_TEXT]"); - if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) - fputs("warning: no locale support\n", stderr); - if (!(dpy = XOpenDisplay(NULL))) - die("dwm: cannot open display"); - if (argc > 1 && !strcmp("-s", argv[1])) { - XStoreName(dpy, RootWindow(dpy, DefaultScreen(dpy)), argv[2]); - XCloseDisplay(dpy); - return 0; - } - checkotherwm(); - XrmInitialize(); - load_xresources(); - setup(); -#ifdef __OpenBSD__ - if (pledge("stdio rpath proc exec", NULL) == -1) - die("pledge"); -#endif /* __OpenBSD__ */ - scan(); - run(); - if(restartsig) - execvp(argv[0], argv); - cleanup(); - XCloseDisplay(dpy); - return EXIT_SUCCESS; -} - diff --git a/.local/src/dwm/dwm.png b/.local/src/dwm/dwm.png Binary files differ. diff --git a/.local/src/dwm/patches/accessnthmon.diff b/.local/src/dwm/patches/accessnthmon.diff @@ -1,100 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 1c0b587..8595a71 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -49,7 +49,10 @@ static const Layout layouts[] = { - { 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} }, -+ { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, \ -+ { ALTMOD, KEY, focusnthmon, {.i = TAG } }, \ -+ { ALTMOD|ShiftMask, KEY, tagnthmon, {.i = TAG } }, -+ - - /* helper for spawning shell commands in the pre dwm-5.0 fashion */ - #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } -diff --git a/dwm.c b/dwm.c -index b0b3466..96fa0bd 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -161,6 +161,7 @@ static void destroynotify(XEvent *e); - static void detach(Client *c); - static void detachstack(Client *c); - static Monitor *dirtomon(int dir); -+static Monitor *numtomon(int num); - static void drawbar(Monitor *m); - static void drawbars(void); - static void enternotify(XEvent *e); -@@ -168,6 +169,7 @@ static void expose(XEvent *e); - static void focus(Client *c); - static void focusin(XEvent *e); - static void focusmon(const Arg *arg); -+static void focusnthmon(const Arg *arg); - static void focusstack(const Arg *arg); - static Atom getatomprop(Client *c, Atom prop); - static int getrootptr(int *x, int *y); -@@ -209,6 +211,7 @@ static void sigchld(int unused); - static void spawn(const Arg *arg); - static void tag(const Arg *arg); - static void tagmon(const Arg *arg); -+static void tagnthmon(const Arg *arg); - static void tile(Monitor *); - static void togglebar(const Arg *arg); - static void togglefloating(const Arg *arg); -@@ -693,6 +696,18 @@ dirtomon(int dir) - return m; - } - -+Monitor * -+numtomon(int num) -+{ -+ Monitor *m = NULL; -+ int i = 0; -+ -+ for(m = mons, i=0; m->next && i < num; m = m->next){ -+ i++; -+ } -+ return m; -+} -+ - void - drawbar(Monitor *m) - { -@@ -830,6 +845,21 @@ focusmon(const Arg *arg) - focus(NULL); - } - -+void -+focusnthmon(const Arg *arg) -+{ -+ Monitor *m; -+ -+ if (!mons->next) -+ return; -+ -+ if ((m = numtomon(arg->i)) == selmon) -+ return; -+ unfocus(selmon->sel, 0); -+ selmon = m; -+ focus(NULL); -+} -+ - void - focusstack(const Arg *arg) - { -@@ -1671,6 +1701,14 @@ tagmon(const Arg *arg) - sendmon(selmon->sel, dirtomon(arg->i)); - } - -+void -+tagnthmon(const Arg *arg) -+{ -+ if (!selmon->sel || !mons->next) -+ return; -+ sendmon(selmon->sel, numtomon(arg->i)); -+} -+ - void - tile(Monitor *m) - { diff --git a/.local/src/dwm/patches/dwm-actualfullscreen-20211013-cb3f58a.diff b/.local/src/dwm/patches/dwm-actualfullscreen-20211013-cb3f58a.diff @@ -1,68 +0,0 @@ -From eea13010ffc3983392857ee1e3804e3aa1064d7a Mon Sep 17 00:00:00 2001 -From: Soenke Lambert <s.lambert@mittwald.de> -Date: Wed, 13 Oct 2021 18:21:09 +0200 -Subject: [PATCH] Fullscreen current window with [Alt]+[Shift]+[f] - -This actually fullscreens a window, instead of just hiding the statusbar -and applying the monocle layout. ---- - config.def.h | 1 + - dwm.1 | 3 +++ - dwm.c | 8 ++++++++ - 3 files changed, 12 insertions(+) - -diff --git a/config.def.h b/config.def.h -index 1c0b587..8cd3204 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -78,6 +78,7 @@ static Key keys[] = { - { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, - { MODKEY, XK_space, setlayout, {0} }, - { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, -+ { MODKEY|ShiftMask, XK_f, togglefullscr, {0} }, - { MODKEY, XK_0, view, {.ui = ~0 } }, - { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, - { MODKEY, XK_comma, focusmon, {.i = -1 } }, -diff --git a/dwm.1 b/dwm.1 -index 13b3729..a368d05 100644 ---- a/dwm.1 -+++ b/dwm.1 -@@ -116,6 +116,9 @@ Zooms/cycles focused window to/from master area (tiled layouts only). - .B Mod1\-Shift\-c - Close focused window. - .TP -+.B Mod1\-Shift\-f -+Toggle fullscreen for focused window. -+.TP - .B Mod1\-Shift\-space - Toggle focused window between tiled and floating state. - .TP -diff --git a/dwm.c b/dwm.c -index 4465af1..c1b899a 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -211,6 +211,7 @@ static void tagmon(const Arg *arg); - static void tile(Monitor *); - static void togglebar(const Arg *arg); - static void togglefloating(const Arg *arg); -+static void togglefullscr(const Arg *arg); - static void toggletag(const Arg *arg); - static void toggleview(const Arg *arg); - static void unfocus(Client *c, int setfocus); -@@ -1719,6 +1720,13 @@ togglefloating(const Arg *arg) - arrange(selmon); - } - -+void -+togglefullscr(const Arg *arg) -+{ -+ if(selmon->sel) -+ setfullscreen(selmon->sel, !selmon->sel->isfullscreen); -+} -+ - void - toggletag(const Arg *arg) - { --- -2.30.2 - diff --git a/.local/src/dwm/patches/dwm-attachbottom-20201227-61bb8b2.diff b/.local/src/dwm/patches/dwm-attachbottom-20201227-61bb8b2.diff @@ -1,67 +0,0 @@ -From eea05f94baf707114ea882e8755520ba30d73cb2 Mon Sep 17 00:00:00 2001 -From: Szabolcs Szucs <contact@szabolcsszucs.com> -Date: Sat, 26 Dec 2020 21:17:40 +0100 -Subject: [PATCH] attachbottom patch - ---- - dwm.c | 16 +++++++++++++--- - 1 file changed, 13 insertions(+), 3 deletions(-) - -diff --git a/dwm.c b/dwm.c -index 664c527..7ee3566 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -147,6 +147,7 @@ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interac - static void arrange(Monitor *m); - static void arrangemon(Monitor *m); - static void attach(Client *c); -+static void attachbottom(Client *c); - static void attachstack(Client *c); - static void buttonpress(XEvent *e); - static void checkotherwm(void); -@@ -407,6 +408,15 @@ attach(Client *c) - c->mon->clients = c; - } - -+void -+attachbottom(Client *c) -+{ -+ Client **tc; -+ c->next = NULL; -+ for (tc = &c->mon->clients; *tc; tc = &(*tc)->next); -+ *tc = c; -+} -+ - void - attachstack(Client *c) - { -@@ -1063,7 +1073,7 @@ manage(Window w, XWindowAttributes *wa) - c->isfloating = c->oldstate = trans != None || c->isfixed; - if (c->isfloating) - XRaiseWindow(dpy, c->win); -- attach(c); -+ attachbottom(c); - attachstack(c); - XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); -@@ -1418,7 +1428,7 @@ sendmon(Client *c, Monitor *m) - detachstack(c); - c->mon = m; - c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ -- attach(c); -+ attachbottom(c); - attachstack(c); - focus(NULL); - arrange(NULL); -@@ -1900,7 +1910,7 @@ updategeom(void) - m->clients = c->next; - detachstack(c); - c->mon = mons; -- attach(c); -+ attachbottom(c); - attachstack(c); - } - if (m == selmon) --- -2.29.2 - diff --git a/.local/src/dwm/patches/dwm-bidi-20220309-0386419.diff b/.local/src/dwm/patches/dwm-bidi-20220309-0386419.diff @@ -1,132 +0,0 @@ -From 0386419cfb5311d4a7516ece8f3f8fe923c43098 Mon Sep 17 00:00:00 2001 -From: MahdiMirzade <me@mahdym.ir> -Date: Wed, 9 Mar 2022 17:44:42 +0330 -Subject: [PATCH] [PATCH] Added support for RTL languages (Farsi, Arabic and - Hebrew using the FriBiDi library) - 9th Mar 2022 Fix - ---- - config.mk | 8 ++++++-- - dwm.c | 40 +++++++++++++++++++++++++++++++++------- - 2 files changed, 39 insertions(+), 9 deletions(-) - -diff --git a/config.mk b/config.mk -index b6eb7e0..5b60a24 100644 ---- a/config.mk -+++ b/config.mk -@@ -10,6 +10,8 @@ MANPREFIX = ${PREFIX}/share/man - X11INC = /usr/X11R6/include - X11LIB = /usr/X11R6/lib - -+BDINC = /usr/include/fribidi -+ - # Xinerama, comment if you don't want it - XINERAMALIBS = -lXinerama - XINERAMAFLAGS = -DXINERAMA -@@ -20,9 +22,11 @@ FREETYPEINC = /usr/include/freetype2 - # OpenBSD (uncomment) - #FREETYPEINC = ${X11INC}/freetype2 - -+BDLIBS = -lfribidi -+ - # includes and libs --INCS = -I${X11INC} -I${FREETYPEINC} --LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -+INCS = -I${X11INC} -I${FREETYPEINC} -I$(BDINC) -+LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} $(BDLIBS) - - # flags - CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -diff --git a/dwm.c b/dwm.c -index a96f33c..4f11fa0 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -40,6 +40,7 @@ - #include <X11/extensions/Xinerama.h> - #endif /* XINERAMA */ - #include <X11/Xft/Xft.h> -+#include <fribidi.h> - - #include "drw.h" - #include "util.h" -@@ -238,6 +239,7 @@ static void zoom(const Arg *arg); - /* variables */ - static const char broken[] = "broken"; - static char stext[256]; -+static char fribidi_text[BUFSIZ] = ""; - static int screen; - static int sw, sh; /* X display screen geometry width, height */ - static int bh, blw = 0; /* bar geometry */ -@@ -276,6 +278,26 @@ static Window root, wmcheckwin; - struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; - - /* function implementations */ -+static void -+apply_fribidi(char *str) -+{ -+ FriBidiStrIndex len = strlen(str); -+ FriBidiChar logical[BUFSIZ]; -+ FriBidiChar visual[BUFSIZ]; -+ FriBidiParType base = FRIBIDI_PAR_ON; -+ FriBidiCharSet charset; -+ fribidi_boolean result; -+ -+ fribidi_text[0] = 0; -+ if (len>0) -+ { -+ charset = fribidi_parse_charset("UTF-8"); -+ len = fribidi_charset_to_unicode(charset, str, len, logical); -+ result = fribidi_log2vis(logical, len, &base, visual, NULL, NULL, NULL); -+ len = fribidi_unicode_to_charset(charset, visual, len, fribidi_text); -+ } -+} -+ - void - applyrules(Client *c) - { -@@ -708,8 +730,9 @@ drawbar(Monitor *m) - /* 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); -+ apply_fribidi(stext); -+ tw = TEXTW(fribidi_text) - lrpad + 2; /* 2px right padding */ -+ drw_text(drw, m->ww - tw, 0, tw, bh, 0, fribidi_text, 0); - } - - for (c = m->clients; c; c = c->next) { -@@ -719,23 +742,26 @@ drawbar(Monitor *m) - } - x = 0; - for (i = 0; i < LENGTH(tags); i++) { -- w = TEXTW(tags[i]); -+ apply_fribidi(tags[i]); -+ w = TEXTW(fribidi_text); - drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); -- drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); -+ drw_text(drw, x, 0, w, bh, lrpad / 2, fribidi_text, urg & 1 << i); - if (occ & 1 << i) - drw_rect(drw, x + boxs, boxs, boxw, boxw, - m == selmon && selmon->sel && selmon->sel->tags & 1 << i, - urg & 1 << i); - x += w; - } -- w = blw = TEXTW(m->ltsymbol); -+ apply_fribidi(m->ltsymbol); -+ w = blw = TEXTW(fribidi_text); - drw_setscheme(drw, scheme[SchemeNorm]); -- x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); -+ x = drw_text(drw, x, 0, w, bh, lrpad / 2, fribidi_text, 0); - - if ((w = m->ww - tw - 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); -+ apply_fribidi(m->sel->name); -+ drw_text(drw, x, 0, w, bh, lrpad / 2, fribidi_text, 0); - if (m->sel->isfloating) - drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); - } else { --- -2.35.1 - diff --git a/.local/src/dwm/patches/dwm-centeredwindowname-20200723-f035e1e.diff b/.local/src/dwm/patches/dwm-centeredwindowname-20200723-f035e1e.diff @@ -1,30 +0,0 @@ -From f035e1e5abb19df5dced9c592ca986deac460435 Mon Sep 17 00:00:00 2001 -From: bastila <20937049+silentfault@users.noreply.github.com> -Date: Thu, 23 Jul 2020 02:45:12 +0300 -Subject: [PATCH] Fix overflow when window name is bigger than window width - ---- - dwm.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/dwm.c b/dwm.c -index 9fd0286..42cb8dd 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -731,8 +731,12 @@ drawbar(Monitor *m) - - if ((w = m->ww - tw - x) > bh) { - if (m->sel) { -+ /* fix overflow when window name is bigger than window width */ -+ int mid = (m->ww - (int)TEXTW(m->sel->name)) / 2 - x; -+ /* make sure name will not overlap on tags even when it is very long */ -+ mid = mid >= lrpad / 2 ? mid : lrpad / 2; - drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); -- drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); -+ drw_text(drw, x, 0, w, bh, mid, m->sel->name, 0); - if (m->sel->isfloating) - drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); - } else { --- -2.27.0 - diff --git a/.local/src/dwm/patches/dwm-cyclelayouts-20180524-6.2.diff b/.local/src/dwm/patches/dwm-cyclelayouts-20180524-6.2.diff @@ -1,93 +0,0 @@ -From a09e766a4342f580582082a92b2de65f33208eb4 Mon Sep 17 00:00:00 2001 -From: Christopher Drelich <cd@cdrakka.com> -Date: Thu, 24 May 2018 00:56:56 -0400 -Subject: [PATCH] Function to cycle through available layouts. - -MOD-CTRL-, and MOD-CTRL-. -cycle backwards and forwards through available layouts. -Probably only useful if you have a lot of additional layouts. -The NULL, NULL layout should always be the last layout in your list, -in order to guarantee consistent behavior. ---- - config.def.h | 3 +++ - dwm.1 | 6 ++++++ - dwm.c | 18 ++++++++++++++++++ - 3 files changed, 27 insertions(+) - -diff --git a/config.def.h b/config.def.h -index a9ac303..153b880 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -41,6 +41,7 @@ static const Layout layouts[] = { - { "[]=", tile }, /* first entry is default */ - { "><>", NULL }, /* no layout function means floating behavior */ - { "[M]", monocle }, -+ { NULL, NULL }, - }; - - /* key definitions */ -@@ -76,6 +77,8 @@ static Key keys[] = { - { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, - { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, - { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, -+ { MODKEY|ControlMask, XK_comma, cyclelayout, {.i = -1 } }, -+ { MODKEY|ControlMask, XK_period, cyclelayout, {.i = +1 } }, - { MODKEY, XK_space, setlayout, {0} }, - { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, - { MODKEY, XK_0, view, {.ui = ~0 } }, -diff --git a/dwm.1 b/dwm.1 -index 13b3729..165891b 100644 ---- a/dwm.1 -+++ b/dwm.1 -@@ -92,6 +92,12 @@ 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 -diff --git a/dwm.c b/dwm.c -index bb95e26..db73000 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -157,6 +157,7 @@ static void configure(Client *c); - static void configurenotify(XEvent *e); - static void configurerequest(XEvent *e); - static Monitor *createmon(void); -+static void cyclelayout(const Arg *arg); - static void destroynotify(XEvent *e); - static void detach(Client *c); - static void detachstack(Client *c); -@@ -645,6 +646,23 @@ createmon(void) - } - - void -+cyclelayout(const Arg *arg) { -+ Layout *l; -+ for(l = (Layout *)layouts; l != selmon->lt[selmon->sellt]; l++); -+ if(arg->i > 0) { -+ if(l->symbol && (l + 1)->symbol) -+ setlayout(&((Arg) { .v = (l + 1) })); -+ else -+ setlayout(&((Arg) { .v = layouts })); -+ } else { -+ if(l != layouts && (l - 1)->symbol) -+ setlayout(&((Arg) { .v = (l - 1) })); -+ else -+ setlayout(&((Arg) { .v = &layouts[LENGTH(layouts) - 2] })); -+ } -+} -+ -+void - destroynotify(XEvent *e) - { - Client *c; --- -2.7.4 - diff --git a/.local/src/dwm/patches/dwm-fullgaps-20200508-7b77734.diff b/.local/src/dwm/patches/dwm-fullgaps-20200508-7b77734.diff @@ -1,138 +0,0 @@ -From 7b7773458c072e4b24d6ea32d0364a8e402e4a43 Mon Sep 17 00:00:00 2001 -From: swy7ch <swy7ch@protonmail.com> -Date: Fri, 8 May 2020 19:07:24 +0200 -Subject: [PATCH] [PATCH] update dwm-fullgaps patch to be used with tile layout - update - -the recent tile layout changes in commit HEAD~1 (f09418b) broke the -patch - -this patch adapt the new `if` statements to take gaps into account - -this patch also provides manpage entries for the keybindings ---- - config.def.h | 4 ++++ - dwm.1 | 10 ++++++++++ - dwm.c | 33 +++++++++++++++++++++++---------- - 3 files changed, 37 insertions(+), 10 deletions(-) - -diff --git a/config.def.h b/config.def.h -index 1c0b587..38d2f6c 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -2,6 +2,7 @@ - - /* appearance */ - static const unsigned int borderpx = 1; /* border pixel of windows */ -+static const unsigned int gappx = 5; /* gaps between windows */ - static const unsigned int snap = 32; /* snap pixel */ - static const int showbar = 1; /* 0 means no bar */ - static const int topbar = 1; /* 0 means bottom bar */ -@@ -84,6 +85,9 @@ static Key keys[] = { - { MODKEY, XK_period, focusmon, {.i = +1 } }, - { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, - { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, -+ { MODKEY, XK_minus, setgaps, {.i = -1 } }, -+ { MODKEY, XK_equal, setgaps, {.i = +1 } }, -+ { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } }, - TAGKEYS( XK_1, 0) - TAGKEYS( XK_2, 1) - TAGKEYS( XK_3, 2) -diff --git a/dwm.1 b/dwm.1 -index 13b3729..0202d96 100644 ---- a/dwm.1 -+++ b/dwm.1 -@@ -140,6 +140,16 @@ View all windows with any tag. - .B Mod1\-Control\-[1..n] - Add/remove all windows with nth tag to/from the view. - .TP -+.B Mod1\-- -+Decrease the gaps around windows. -+.TP -+.B Mod1\-= -+Increase the gaps around windows. -+.TP -+.B Mod1\-Shift-= -+Reset the gaps around windows to -+.BR 0 . -+.TP - .B Mod1\-Shift\-q - Quit dwm. - .SS Mouse commands -diff --git a/dwm.c b/dwm.c -index 9fd0286..45a58f3 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -119,6 +119,7 @@ struct Monitor { - int by; /* bar geometry */ - int mx, my, mw, mh; /* screen size */ - int wx, wy, ww, wh; /* window area */ -+ int gappx; /* gaps between windows */ - unsigned int seltags; - unsigned int sellt; - unsigned int tagset[2]; -@@ -200,6 +201,7 @@ static void sendmon(Client *c, Monitor *m); - static void setclientstate(Client *c, long state); - static void setfocus(Client *c); - static void setfullscreen(Client *c, int fullscreen); -+static void setgaps(const Arg *arg); - static void setlayout(const Arg *arg); - static void setmfact(const Arg *arg); - static void setup(void); -@@ -639,6 +641,7 @@ createmon(void) - m->nmaster = nmaster; - m->showbar = showbar; - m->topbar = topbar; -+ m->gappx = gappx; - m->lt[0] = &layouts[0]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); -@@ -1498,6 +1501,16 @@ setfullscreen(Client *c, int fullscreen) - } - } - -+void -+setgaps(const Arg *arg) -+{ -+ if ((arg->i == 0) || (selmon->gappx + arg->i < 0)) -+ selmon->gappx = 0; -+ else -+ selmon->gappx += arg->i; -+ arrange(selmon); -+} -+ - void - setlayout(const Arg *arg) - { -@@ -1684,18 +1697,18 @@ tile(Monitor *m) - if (n > m->nmaster) - mw = m->nmaster ? m->ww * m->mfact : 0; - else -- mw = m->ww; -- for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) -+ mw = m->ww - m->gappx; -+ for (i = 0, my = ty = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) - if (i < m->nmaster) { -- h = (m->wh - my) / (MIN(n, m->nmaster) - i); -- resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); -- if (my + HEIGHT(c) < m->wh) -- my += HEIGHT(c); -+ h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx; -+ resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0); -+ if (my + HEIGHT(c) + m->gappx < m->wh) -+ my += HEIGHT(c) + m->gappx; - } else { -- h = (m->wh - ty) / (n - i); -- resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); -- if (ty + HEIGHT(c) < m->wh) -- ty += HEIGHT(c); -+ h = (m->wh - ty) / (n - i) - m->gappx; -+ resize(c, m->wx + mw + m->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappx, h - (2*c->bw), 0); -+ if (ty + HEIGHT(c) + m->gappx < m->wh) -+ ty += HEIGHT(c) + m->gappx; - } - } - --- -2.26.2 - diff --git a/.local/src/dwm/patches/dwm-hide_vacant_tags-6.3.diff b/.local/src/dwm/patches/dwm-hide_vacant_tags-6.3.diff @@ -1,39 +0,0 @@ -diff --git a/dwm.c b/dwm.c -index a96f33c..f2da729 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -432,9 +432,15 @@ buttonpress(XEvent *e) - } - if (ev->window == selmon->barwin) { - i = x = 0; -- do -+ unsigned int occ = 0; -+ for(c = m->clients; c; c=c->next) -+ occ |= c->tags; -+ do { -+ /* Do not reserve space for vacant tags */ -+ if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) -+ continue; - x += TEXTW(tags[i]); -- while (ev->x >= x && ++i < LENGTH(tags)); -+ } while (ev->x >= x && ++i < LENGTH(tags)); - if (i < LENGTH(tags)) { - click = ClkTagBar; - arg.ui = 1 << i; -@@ -719,13 +725,12 @@ drawbar(Monitor *m) - } - x = 0; - for (i = 0; i < LENGTH(tags); i++) { -+ /* Do not draw vacant tags */ -+ if(!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) -+ continue; - w = TEXTW(tags[i]); - drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); - drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); -- if (occ & 1 << i) -- drw_rect(drw, x + boxs, boxs, boxw, boxw, -- m == selmon && selmon->sel && selmon->sel->tags & 1 << i, -- urg & 1 << i); - x += w; - } - w = blw = TEXTW(m->ltsymbol); diff --git a/.local/src/dwm/patches/dwm-movestack-20211115-a786211.diff b/.local/src/dwm/patches/dwm-movestack-20211115-a786211.diff @@ -1,95 +0,0 @@ -From 9a4037dc0ef56f91c009317e78e9e3790dafbb58 Mon Sep 17 00:00:00 2001 -From: BrunoCooper17 <BrunoCooper17@outlook.com> -Date: Mon, 15 Nov 2021 14:04:53 -0600 -Subject: [PATCH] MoveStack patch - -This plugin allows you to move clients around in the stack and swap them -with the master. It emulates the behavior off mod+shift+j and mod+shift+k -in Xmonad. movestack(+1) will swap the client with the current focus with -the next client. movestack(-1) will swap the client with the current focus -with the previous client. ---- - config.def.h | 3 +++ - movestack.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 51 insertions(+) - create mode 100644 movestack.c - -diff --git a/config.def.h b/config.def.h -index a2ac963..33efa5b 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -60,6 +60,7 @@ static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() - static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; - static const char *termcmd[] = { "st", NULL }; - -+#include "movestack.c" - static Key keys[] = { - /* modifier key function argument */ - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, -@@ -71,6 +72,8 @@ static Key keys[] = { - { MODKEY, XK_d, incnmaster, {.i = -1 } }, - { MODKEY, XK_h, setmfact, {.f = -0.05} }, - { MODKEY, XK_l, setmfact, {.f = +0.05} }, -+ { MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } }, -+ { MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } }, - { MODKEY, XK_Return, zoom, {0} }, - { MODKEY, XK_Tab, view, {0} }, - { MODKEY|ShiftMask, XK_c, killclient, {0} }, -diff --git a/movestack.c b/movestack.c -new file mode 100644 -index 0000000..520f4ae ---- /dev/null -+++ b/movestack.c -@@ -0,0 +1,48 @@ -+void -+movestack(const Arg *arg) { -+ Client *c = NULL, *p = NULL, *pc = NULL, *i; -+ -+ if(arg->i > 0) { -+ /* find the client after selmon->sel */ -+ for(c = selmon->sel->next; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); -+ if(!c) -+ for(c = selmon->clients; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); -+ -+ } -+ else { -+ /* find the client before selmon->sel */ -+ for(i = selmon->clients; i != selmon->sel; i = i->next) -+ if(ISVISIBLE(i) && !i->isfloating) -+ c = i; -+ if(!c) -+ for(; i; i = i->next) -+ if(ISVISIBLE(i) && !i->isfloating) -+ c = i; -+ } -+ /* find the client before selmon->sel and c */ -+ for(i = selmon->clients; i && (!p || !pc); i = i->next) { -+ if(i->next == selmon->sel) -+ p = i; -+ if(i->next == c) -+ pc = i; -+ } -+ -+ /* swap c and selmon->sel selmon->clients in the selmon->clients list */ -+ if(c && c != selmon->sel) { -+ Client *temp = selmon->sel->next==c?selmon->sel:selmon->sel->next; -+ selmon->sel->next = c->next==selmon->sel?c:c->next; -+ c->next = temp; -+ -+ if(p && p != c) -+ p->next = c; -+ if(pc && pc != selmon->sel) -+ pc->next = selmon->sel; -+ -+ if(selmon->sel == selmon->clients) -+ selmon->clients = c; -+ else if(c == selmon->clients) -+ selmon->clients = selmon->sel; -+ -+ arrange(selmon); -+ } -+} -\ No newline at end of file --- -2.33.1 - diff --git a/.local/src/dwm/patches/dwm-noborderfloatingfix-6.2.diff b/.local/src/dwm/patches/dwm-noborderfloatingfix-6.2.diff @@ -1,31 +0,0 @@ -From 700b0bdea872f4c00182b2bd925b41fe03f8d222 Mon Sep 17 00:00:00 2001 -From: Aidan Hall <aidan.hall@outlook.com> -Date: Tue, 2 Jun 2020 14:41:53 +0000 -Subject: [PATCH] Prevents hiding the border if layout is floating. - ---- - dwm.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/dwm.c b/dwm.c -index 4465af1..2dd959d 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -1282,6 +1282,14 @@ resizeclient(Client *c, int x, int y, int w, int h) - c->oldw = c->w; c->w = wc.width = w; - c->oldh = c->h; c->h = wc.height = h; - wc.border_width = c->bw; -+ if (((nexttiled(c->mon->clients) == c && !nexttiled(c->next)) -+ || &monocle == c->mon->lt[c->mon->sellt]->arrange) -+ && !c->isfullscreen && !c->isfloating -+ && NULL != c->mon->lt[c->mon->sellt]->arrange) { -+ c->w = wc.width += c->bw * 2; -+ c->h = wc.height += c->bw * 2; -+ wc.border_width = 0; -+ } - XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); - configure(c); - XSync(dpy, False); --- -2.26.2 - diff --git a/.local/src/dwm/patches/dwm-placemouse-6.3.diff b/.local/src/dwm/patches/dwm-placemouse-6.3.diff @@ -1,259 +0,0 @@ -From 399cb51f86d259d0d15d2db767d31c9e030c0528 Mon Sep 17 00:00:00 2001 -From: Bakkeby <bakkeby@gmail.com> -Date: Mon, 10 Jan 2022 13:18:37 +0100 -Subject: [PATCH] Adding placemouse patch - ---- - config.def.h | 12 +++- - dwm.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 177 insertions(+), 1 deletion(-) - -diff --git a/config.def.h b/config.def.h -index a2ac963..caaebf6 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -105,7 +105,17 @@ static Button buttons[] = { - { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, - { ClkWinTitle, 0, Button2, zoom, {0} }, - { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, -- { ClkClientWin, MODKEY, Button1, movemouse, {0} }, -+ /* placemouse options, choose which feels more natural: -+ * 0 - tiled position is relative to mouse cursor -+ * 1 - tiled postiion is relative to window center -+ * 2 - mouse pointer warps to window center -+ * -+ * The moveorplace uses movemouse or placemouse depending on the floating state -+ * of the selected client. Set up individual keybindings for the two if you want -+ * to control these separately (i.e. to retain the feature to move a tiled window -+ * into a floating position). -+ */ -+ { ClkClientWin, MODKEY, Button1, moveorplace, {.i = 1} }, - { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, - { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, - { ClkTagBar, 0, Button1, view, {0} }, -diff --git a/dwm.c b/dwm.c -index a96f33c..5d57e18 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -49,6 +49,8 @@ - #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) - #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ - * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) -+#define INTERSECTC(x,y,w,h,z) (MAX(0, MIN((x)+(w),(z)->x+(z)->w) - MAX((x),(z)->x)) \ -+ * MAX(0, MIN((y)+(h),(z)->y+(z)->h) - MAX((y),(z)->y))) - #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) - #define LENGTH(X) (sizeof X / sizeof X[0]) - #define MOUSEMASK (BUTTONMASK|PointerMotionMask) -@@ -93,6 +95,7 @@ struct Client { - int bw, oldbw; - unsigned int tags; - int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; -+ int beingmoved; - Client *next; - Client *snext; - Monitor *mon; -@@ -184,10 +187,13 @@ static void maprequest(XEvent *e); - static void monocle(Monitor *m); - static void motionnotify(XEvent *e); - static void movemouse(const Arg *arg); -+static void moveorplace(const Arg *arg); - static Client *nexttiled(Client *c); -+static void placemouse(const Arg *arg); - static void pop(Client *); - static void propertynotify(XEvent *e); - static void quit(const Arg *arg); -+static Client *recttoclient(int x, int y, int w, int h); - static Monitor *recttomon(int x, int y, int w, int h); - static void resize(Client *c, int x, int y, int w, int h, int interact); - static void resizeclient(Client *c, int x, int y, int w, int h); -@@ -1136,6 +1142,14 @@ motionnotify(XEvent *e) - mon = m; - } - -+void -+moveorplace(const Arg *arg) { -+ if ((!selmon->lt[selmon->sellt]->arrange || (selmon->sel && selmon->sel->isfloating))) -+ movemouse(arg); -+ else -+ placemouse(arg); -+} -+ - void - movemouse(const Arg *arg) - { -@@ -1203,6 +1217,139 @@ nexttiled(Client *c) - return c; - } - -+void -+placemouse(const Arg *arg) -+{ -+ int x, y, px, py, ocx, ocy, nx = -9999, ny = -9999, freemove = 0; -+ Client *c, *r = NULL, *at, *prevr; -+ Monitor *m; -+ XEvent ev; -+ XWindowAttributes wa; -+ Time lasttime = 0; -+ int attachmode, prevattachmode; -+ attachmode = prevattachmode = -1; -+ -+ if (!(c = selmon->sel) || !c->mon->lt[c->mon->sellt]->arrange) /* no support for placemouse when floating layout is used */ -+ return; -+ if (c->isfullscreen) /* no support placing fullscreen windows by mouse */ -+ return; -+ restack(selmon); -+ prevr = c; -+ if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, -+ None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) -+ return; -+ -+ c->isfloating = 0; -+ c->beingmoved = 1; -+ -+ XGetWindowAttributes(dpy, c->win, &wa); -+ ocx = wa.x; -+ ocy = wa.y; -+ -+ if (arg->i == 2) // warp cursor to client center -+ XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, WIDTH(c) / 2, HEIGHT(c) / 2); -+ -+ if (!getrootptr(&x, &y)) -+ return; -+ -+ do { -+ XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); -+ switch (ev.type) { -+ case ConfigureRequest: -+ case Expose: -+ case MapRequest: -+ handler[ev.type](&ev); -+ break; -+ case MotionNotify: -+ if ((ev.xmotion.time - lasttime) <= (1000 / 60)) -+ continue; -+ lasttime = ev.xmotion.time; -+ -+ nx = ocx + (ev.xmotion.x - x); -+ ny = ocy + (ev.xmotion.y - y); -+ -+ if (!freemove && (abs(nx - ocx) > snap || abs(ny - ocy) > snap)) -+ freemove = 1; -+ -+ if (freemove) -+ XMoveWindow(dpy, c->win, nx, ny); -+ -+ if ((m = recttomon(ev.xmotion.x, ev.xmotion.y, 1, 1)) && m != selmon) -+ selmon = m; -+ -+ if (arg->i == 1) { // tiled position is relative to the client window center point -+ px = nx + wa.width / 2; -+ py = ny + wa.height / 2; -+ } else { // tiled position is relative to the mouse cursor -+ px = ev.xmotion.x; -+ py = ev.xmotion.y; -+ } -+ -+ r = recttoclient(px, py, 1, 1); -+ -+ if (!r || r == c) -+ break; -+ -+ attachmode = 0; // below -+ if (((float)(r->y + r->h - py) / r->h) > ((float)(r->x + r->w - px) / r->w)) { -+ if (abs(r->y - py) < r->h / 2) -+ attachmode = 1; // above -+ } else if (abs(r->x - px) < r->w / 2) -+ attachmode = 1; // above -+ -+ if ((r && r != prevr) || (attachmode != prevattachmode)) { -+ detachstack(c); -+ detach(c); -+ if (c->mon != r->mon) { -+ arrangemon(c->mon); -+ c->tags = r->mon->tagset[r->mon->seltags]; -+ } -+ -+ c->mon = r->mon; -+ r->mon->sel = r; -+ -+ if (attachmode) { -+ if (r == r->mon->clients) -+ attach(c); -+ else { -+ for (at = r->mon->clients; at->next != r; at = at->next); -+ c->next = at->next; -+ at->next = c; -+ } -+ } else { -+ c->next = r->next; -+ r->next = c; -+ } -+ -+ attachstack(c); -+ arrangemon(r->mon); -+ prevr = r; -+ prevattachmode = attachmode; -+ } -+ break; -+ } -+ } while (ev.type != ButtonRelease); -+ XUngrabPointer(dpy, CurrentTime); -+ -+ if ((m = recttomon(ev.xmotion.x, ev.xmotion.y, 1, 1)) && m != c->mon) { -+ detach(c); -+ detachstack(c); -+ arrangemon(c->mon); -+ c->mon = m; -+ c->tags = m->tagset[m->seltags]; -+ attach(c); -+ attachstack(c); -+ selmon = m; -+ } -+ -+ focus(c); -+ c->beingmoved = 0; -+ -+ if (nx != -9999) -+ resize(c, nx, ny, c->w, c->h, 0); -+ arrangemon(c->mon); -+} -+ - void - pop(Client *c) - { -@@ -1255,6 +1402,21 @@ quit(const Arg *arg) - running = 0; - } - -+Client * -+recttoclient(int x, int y, int w, int h) -+{ -+ Client *c, *r = NULL; -+ int a, area = 0; -+ -+ for (c = nexttiled(selmon->clients); c; c = nexttiled(c->next)) { -+ if ((a = INTERSECTC(x, y, w, h, c)) > area) { -+ area = a; -+ r = c; -+ } -+ } -+ return r; -+} -+ - Monitor * - recttomon(int x, int y, int w, int h) - { -@@ -1285,6 +1447,10 @@ resizeclient(Client *c, int x, int y, int w, int h) - c->oldy = c->y; c->y = wc.y = y; - c->oldw = c->w; c->w = wc.width = w; - c->oldh = c->h; c->h = wc.height = h; -+ -+ if (c->beingmoved) -+ return; -+ - wc.border_width = c->bw; - XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); - configure(c); --- -2.19.1 - diff --git a/.local/src/dwm/patches/dwm-rainbowtags-6.2.diff b/.local/src/dwm/patches/dwm-rainbowtags-6.2.diff @@ -1,59 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 1c0b587..3fb5cf8 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -21,6 +21,18 @@ static const char *colors[][3] = { - /* tagging */ - static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; - -+static const char *tagsel[][2] = { -+ { "#ffffff", "#ff0000" }, -+ { "#ffffff", "#ff7f00" }, -+ { "#000000", "#ffff00" }, -+ { "#000000", "#00ff00" }, -+ { "#ffffff", "#0000ff" }, -+ { "#ffffff", "#4b0082" }, -+ { "#ffffff", "#9400d3" }, -+ { "#000000", "#ffffff" }, -+ { "#ffffff", "#000000" }, -+}; -+ - static const Rule rules[] = { - /* xprop(1): - * WM_CLASS(STRING) = instance, class -diff --git a/dwm.c b/dwm.c -index b0b3466..c16d5f5 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -264,6 +264,7 @@ static Atom wmatom[WMLast], netatom[NetLast]; - static int running = 1; - static Cur *cursor[CurLast]; - static Clr **scheme; -+static Clr **tagscheme; - static Display *dpy; - static Drw *drw; - static Monitor *mons, *selmon; -@@ -717,7 +718,7 @@ drawbar(Monitor *m) - x = 0; - for (i = 0; i < LENGTH(tags); i++) { - w = TEXTW(tags[i]); -- drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); -+ drw_setscheme(drw, (m->tagset[m->seltags] & 1 << i ? tagscheme[i] : scheme[SchemeNorm])); - drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); - if (occ & 1 << i) - drw_rect(drw, x + boxs, boxs, boxw, boxw, -@@ -1568,9 +1569,14 @@ setup(void) - cursor[CurResize] = drw_cur_create(drw, XC_sizing); - cursor[CurMove] = drw_cur_create(drw, XC_fleur); - /* init appearance */ -+ if (LENGTH(tags) > LENGTH(tagsel)) -+ die("too few color schemes for the tags"); - scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); - for (i = 0; i < LENGTH(colors); i++) - scheme[i] = drw_scm_create(drw, colors[i], 3); -+ tagscheme = ecalloc(LENGTH(tagsel), sizeof(Clr *)); -+ for (i = 0; i < LENGTH(tagsel); i++) -+ tagscheme[i] = drw_scm_create(drw, tagsel[i], 2); - /* init bars */ - updatebars(); - updatestatus(); diff --git a/.local/src/dwm/patches/dwm-restartsig-20180523-6.2.diff b/.local/src/dwm/patches/dwm-restartsig-20180523-6.2.diff @@ -1,139 +0,0 @@ -From 2991f37f0aaf44b9f9b11e7893ff0af8eb88f649 Mon Sep 17 00:00:00 2001 -From: Christopher Drelich <cd@cdrakka.com> -Date: Wed, 23 May 2018 22:50:38 -0400 -Subject: [PATCH] Modifies quit to handle restarts and adds SIGHUP and SIGTERM - handlers. - -Modified quit() to restart if it receives arg .i = 1 -MOD+CTRL+SHIFT+Q was added to confid.def.h to do just that. - -Signal handlers were handled for SIGHUP and SIGTERM. -If dwm receives these signals it calls quit() with -arg .i = to 1 or 0, respectively. - -To restart dwm: -MOD+CTRL+SHIFT+Q -or -kill -HUP dwmpid - -To quit dwm cleanly: -MOD+SHIFT+Q -or -kill -TERM dwmpid ---- - config.def.h | 1 + - dwm.1 | 10 ++++++++++ - dwm.c | 22 ++++++++++++++++++++++ - 3 files changed, 33 insertions(+) - -diff --git a/config.def.h b/config.def.h -index a9ac303..e559429 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -94,6 +94,7 @@ static Key keys[] = { - TAGKEYS( XK_8, 7) - TAGKEYS( XK_9, 8) - { MODKEY|ShiftMask, XK_q, quit, {0} }, -+ { MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} }, - }; - - /* button definitions */ -diff --git a/dwm.1 b/dwm.1 -index 13b3729..36a331c 100644 ---- a/dwm.1 -+++ b/dwm.1 -@@ -142,6 +142,9 @@ Add/remove all windows with nth tag to/from the view. - .TP - .B Mod1\-Shift\-q - Quit dwm. -+.TP -+.B Mod1\-Control\-Shift\-q -+Restart dwm. - .SS Mouse commands - .TP - .B Mod1\-Button1 -@@ -155,6 +158,13 @@ Resize focused window while dragging. Tiled windows will be toggled to the float - .SH CUSTOMIZATION - dwm is customized by creating a custom config.h and (re)compiling the source - code. This keeps it fast, secure and simple. -+.SH SIGNALS -+.TP -+.B SIGHUP - 1 -+Restart the dwm process. -+.TP -+.B SIGTERM - 15 -+Cleanly terminate the dwm process. - .SH SEE ALSO - .BR dmenu (1), - .BR st (1) -diff --git a/dwm.c b/dwm.c -index bb95e26..286eecd 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -205,6 +205,8 @@ static void setup(void); - static void seturgent(Client *c, int urg); - static void showhide(Client *c); - static void sigchld(int unused); -+static void sighup(int unused); -+static void sigterm(int unused); - static void spawn(const Arg *arg); - static void tag(const Arg *arg); - static void tagmon(const Arg *arg); -@@ -260,6 +262,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { - [UnmapNotify] = unmapnotify - }; - static Atom wmatom[WMLast], netatom[NetLast]; -+static int restart = 0; - static int running = 1; - static Cur *cursor[CurLast]; - static Clr **scheme; -@@ -1248,6 +1251,7 @@ propertynotify(XEvent *e) - void - quit(const Arg *arg) - { -+ if(arg->i) restart = 1; - running = 0; - } - -@@ -1536,6 +1540,9 @@ setup(void) - /* clean up any zombies immediately */ - sigchld(0); - -+ signal(SIGHUP, sighup); -+ signal(SIGTERM, sigterm); -+ - /* init screen */ - screen = DefaultScreen(dpy); - sw = DisplayWidth(dpy, screen); -@@ -1637,6 +1644,20 @@ sigchld(int unused) - } - - void -+sighup(int unused) -+{ -+ Arg a = {.i = 1}; -+ quit(&a); -+} -+ -+void -+sigterm(int unused) -+{ -+ Arg a = {.i = 0}; -+ quit(&a); -+} -+ -+void - spawn(const Arg *arg) - { - if (arg->v == dmenucmd) -@@ -2139,6 +2160,7 @@ main(int argc, char *argv[]) - setup(); - scan(); - run(); -+ if(restart) execvp(argv[0], argv); - cleanup(); - XCloseDisplay(dpy); - return EXIT_SUCCESS; --- -2.7.4 - diff --git a/.local/src/dwm/patches/dwm-setstatus-6.2.diff b/.local/src/dwm/patches/dwm-setstatus-6.2.diff @@ -1,49 +0,0 @@ -From dbfb346a86c79b50bfa27c75547b42e34cb54715 Mon Sep 17 00:00:00 2001 -From: aleks <aleks.stier@icloud.com> -Date: Fri, 11 Sep 2020 17:42:50 +0200 -Subject: [PATCH] Apply setstatus-6.2 - -Enables to set the status with dwm itself. No more xsetroot bloat! -To change the status to `foo bar` execute: - - dwm -s "foo bar" - -Piping into `dwm -s` is currently not supported but you can set the -status to the output of any command by doing something like: - - dwm -s "$(run_command_which_outputs_the_status)" - -For example to set the status to the current date run: - - dwm -s "$(date)" - ---- - dwm.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/dwm.c b/dwm.c -index 4465af1..b3c8f71 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -2129,12 +2129,17 @@ main(int argc, char *argv[]) - { - if (argc == 2 && !strcmp("-v", argv[1])) - die("dwm-"VERSION); -- else if (argc != 1) -+ else if (argc != 1 && strcmp("-s", argv[1])) - die("usage: dwm [-v]"); - if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) - fputs("warning: no locale support\n", stderr); - if (!(dpy = XOpenDisplay(NULL))) - die("dwm: cannot open display"); -+ if (argc > 1 && !strcmp("-s", argv[1])) { -+ XStoreName(dpy, RootWindow(dpy, DefaultScreen(dpy)), argv[2]); -+ XCloseDisplay(dpy); -+ return 0; -+ } - checkotherwm(); - setup(); - #ifdef __OpenBSD__ --- -2.28.0 - diff --git a/.local/src/dwm/patches/dwm-status2d-systray-6.3.diff b/.local/src/dwm/patches/dwm-status2d-systray-6.3.diff @@ -1,888 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index a2ac963..86fcc84 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -3,8 +3,13 @@ - /* appearance */ - static const unsigned int borderpx = 1; /* border pixel of windows */ - static const unsigned int snap = 32; /* snap pixel */ --static const int showbar = 1; /* 0 means no bar */ --static const int topbar = 1; /* 0 means bottom bar */ -+static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */ -+static const unsigned int systrayonleft = 0; /* 0: systray in the right corner, >0: systray on left of status text */ -+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" }; - static const char dmenufont[] = "monospace:size=10"; - static const char col_gray1[] = "#222222"; -@@ -101,8 +106,8 @@ static Key keys[] = { - /* 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]} }, -+ { ClkTagBar, MODKEY, Button1, tag, {0} }, -+ { ClkTagBar, MODKEY, Button3, toggletag, {0} }, - { ClkWinTitle, 0, Button2, zoom, {0} }, - { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, - { ClkClientWin, MODKEY, Button1, movemouse, {0} }, -diff --git a/dwm.c b/dwm.c -index a96f33c..8153bfe 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -57,12 +57,27 @@ - #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 +156,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); -@@ -163,6 +184,7 @@ static void detachstack(Client *c); - static Monitor *dirtomon(int dir); - static void drawbar(Monitor *m); - static void drawbars(void); -+static int drawstatusbar(Monitor *m, int bh, char* text); - static void enternotify(XEvent *e); - static void expose(XEvent *e); - static void focus(Client *c); -@@ -172,6 +194,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 +212,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 +233,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,20 +251,25 @@ 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 char stext[1024]; - static int screen; - static int sw, sh; /* X display screen geometry width, height */ - static int bh, blw = 0; /* bar geometry */ -@@ -258,9 +290,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 +473,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,9 +516,16 @@ cleanup(void) - XUngrabKey(dpy, AnyKey, AnyModifier, root); - while (mons) - cleanupmon(mons); -- for (i = 0; i < CurLast; i++) -+ -+ 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++) -+ for (i = 0; i < LENGTH(colors) + 1; i++) - free(scheme[i]); - XDestroyWindow(dpy, wmcheckwin); - drw_free(drw); -@@ -513,9 +553,58 @@ 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 +657,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 +742,11 @@ destroynotify(XEvent *e) - - if ((c = wintoclient(ev->window))) - unmanage(c, 1); -+ else if ((c = wintosystrayicon(ev->window))) { -+ removesystrayicon(c); -+ resizebarwin(selmon); -+ updatesystray(); -+ } - } - - void -@@ -693,10 +787,119 @@ dirtomon(int dir) - return m; - } - -+int -+drawstatusbar(Monitor *m, int bh, char* stext) { -+ int ret, i, w, x, len; -+ short isCode = 0; -+ char *text; -+ char *p; -+ -+ len = strlen(stext) + 1 ; -+ if (!(text = (char*) malloc(sizeof(char)*len))) -+ die("malloc"); -+ p = text; -+ memcpy(text, stext, len); -+ -+ /* compute width of the status text */ -+ w = 0; -+ i = -1; -+ while (text[++i]) { -+ if (text[i] == '^') { -+ if (!isCode) { -+ isCode = 1; -+ text[i] = '\0'; -+ w += TEXTW(text) - lrpad; -+ text[i] = '^'; -+ if (text[++i] == 'f') -+ w += atoi(text + ++i); -+ } else { -+ isCode = 0; -+ text = text + i + 1; -+ i = -1; -+ } -+ } -+ } -+ if (!isCode) -+ w += TEXTW(text) - lrpad; -+ else -+ isCode = 0; -+ text = p; -+ -+ w += 2; /* 1px padding on both sides */ -+ ret = m->ww - w; -+ x = m->ww - w - getsystraywidth(); -+ -+ drw_setscheme(drw, scheme[LENGTH(colors)]); -+ drw->scheme[ColFg] = scheme[SchemeNorm][ColFg]; -+ drw->scheme[ColBg] = scheme[SchemeNorm][ColBg]; -+ drw_rect(drw, x, 0, w, bh, 1, 1); -+ x++; -+ -+ /* process status text */ -+ i = -1; -+ while (text[++i]) { -+ if (text[i] == '^' && !isCode) { -+ isCode = 1; -+ -+ text[i] = '\0'; -+ w = TEXTW(text) - lrpad; -+ drw_text(drw, x, 0, w, bh, 0, text, 0); -+ -+ x += w; -+ -+ /* process code */ -+ while (text[++i] != '^') { -+ if (text[i] == 'c') { -+ char buf[8]; -+ memcpy(buf, (char*)text+i+1, 7); -+ buf[7] = '\0'; -+ drw_clr_create(drw, &drw->scheme[ColFg], buf); -+ i += 7; -+ } else if (text[i] == 'b') { -+ char buf[8]; -+ memcpy(buf, (char*)text+i+1, 7); -+ buf[7] = '\0'; -+ drw_clr_create(drw, &drw->scheme[ColBg], buf); -+ i += 7; -+ } else if (text[i] == 'd') { -+ drw->scheme[ColFg] = scheme[SchemeNorm][ColFg]; -+ drw->scheme[ColBg] = scheme[SchemeNorm][ColBg]; -+ } else if (text[i] == 'r') { -+ int rx = atoi(text + ++i); -+ while (text[++i] != ','); -+ int ry = atoi(text + ++i); -+ while (text[++i] != ','); -+ int rw = atoi(text + ++i); -+ while (text[++i] != ','); -+ int rh = atoi(text + ++i); -+ -+ drw_rect(drw, rx + x, ry, rw, rh, 1, 0); -+ } else if (text[i] == 'f') { -+ x += atoi(text + ++i); -+ } -+ } -+ -+ text = text + i + 1; -+ i=-1; -+ isCode = 0; -+ } -+ } -+ -+ if (!isCode) { -+ w = TEXTW(text) - lrpad; -+ drw_text(drw, x, 0, w, bh, 0, text, 0); -+ } -+ -+ drw_setscheme(drw, scheme[SchemeNorm]); -+ free(p); -+ -+ return ret; -+} -+ - 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; -@@ -705,13 +908,15 @@ drawbar(Monitor *m) - if (!m->showbar) - return; - -+ if(showsystray && m == systraytomon(m) && !systrayonleft) -+ 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 = m->ww - drawstatusbar(m, bh, stext); - } - -+ resizebarwin(m); - for (c = m->clients; c; c = c->next) { - occ |= c->tags; - if (c->isurgent) -@@ -732,7 +937,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); -@@ -743,7 +948,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 -@@ -780,8 +985,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 -@@ -867,9 +1075,17 @@ getatomprop(Client *c, Atom prop) - unsigned char *p = NULL; - Atom da, atom = None; - -- if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, -+ /* 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, 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; -@@ -903,6 +1119,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) - { -@@ -1007,7 +1233,8 @@ 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); -@@ -1096,6 +1323,13 @@ 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; - if (wa.override_redirect) -@@ -1219,7 +1453,18 @@ propertynotify(XEvent *e) - Window trans; - XPropertyEvent *ev = &e->xproperty; - -- if ((ev->window == root) && (ev->atom == XA_WM_NAME)) -+ 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) - return; /* ignore */ -@@ -1269,6 +1514,19 @@ 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) - { -@@ -1276,6 +1534,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) && !systrayonleft) -+ w -= getsystraywidth(); -+ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh); -+} -+ - void - resizeclient(Client *c, int x, int y, int w, int h) - { -@@ -1348,6 +1614,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) - { -@@ -1437,26 +1716,37 @@ 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; - } -@@ -1470,7 +1760,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 -@@ -1558,22 +1848,32 @@ setup(void) - wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); - wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); - netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); -- netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); -- netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); -+ netatom[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); - netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); - 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); -- /* init cursors */ -+ 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); - cursor[CurMove] = drw_cur_create(drw, XC_fleur); - /* init appearance */ -- scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); -+ scheme = ecalloc(LENGTH(colors) + 1, sizeof(Clr *)); -+ scheme[LENGTH(colors)] = drw_scm_create(drw, colors[0], 3); - for (i = 0; i < LENGTH(colors); i++) - scheme[i] = drw_scm_create(drw, colors[i], 3); -+ /* init system tray */ -+ updatesystray(); - /* init bars */ - updatebars(); - updatestatus(); -@@ -1707,7 +2007,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); - } - -@@ -1802,11 +2113,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, -@@ -1817,10 +2135,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); - } -@@ -1996,6 +2319,125 @@ 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 sw = TEXTW(stext) - lrpad + systrayspacing; -+ unsigned int w = 1; -+ -+ if (!showsystray) -+ return; -+ if (systrayonleft) -+ x -= sw + lrpad / 2; -+ 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 -@@ -2063,6 +2505,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) - { -@@ -2116,6 +2568,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) - { diff --git a/.local/src/dwm/patches/dwm-statusallmons-6.2.diff b/.local/src/dwm/patches/dwm-statusallmons-6.2.diff @@ -1,25 +0,0 @@ -diff -up a/dwm.c b/dwm.c ---- a/dwm.c 2020-07-09 16:49:10.023585649 +0200 -+++ b/dwm.c 2020-07-09 16:49:43.497542191 +0200 -@@ -702,7 +702,7 @@ drawbar(Monitor *m) - Client *c; - - /* draw status first so it can be overdrawn by tags later */ -- if (m == selmon) { /* status is only drawn on selected monitor */ -+ if (m == selmon || 1) { /* status is only drawn on selected monitor */ - drw_setscheme(drw, scheme[SchemeNorm]); - sw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ - drw_text(drw, m->ww - sw, 0, sw, bh, 0, stext, 0); -@@ -1987,9 +1987,11 @@ updatesizehints(Client *c) - void - updatestatus(void) - { -+ Monitor* m; - if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) - strcpy(stext, "dwm-"VERSION); -- drawbar(selmon); -+ for(m = mons; m; m = m->next) -+ drawbar(m); - } - - void diff --git a/.local/src/dwm/patches/dwm-sticky-6.1.diff b/.local/src/dwm/patches/dwm-sticky-6.1.diff @@ -1,58 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 7054c06..9b5d5b8 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -76,6 +76,7 @@ static Key keys[] = { - { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, - { MODKEY, XK_space, setlayout, {0} }, - { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, -+ { MODKEY, XK_s, togglesticky, {0} }, - { MODKEY, XK_0, view, {.ui = ~0 } }, - { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, - { MODKEY, XK_comma, focusmon, {.i = -1 } }, -diff --git a/dwm.c b/dwm.c -index 0362114..0ef5c7f 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -49,7 +49,7 @@ - #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) - #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ - * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) --#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) -+#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]) || C->issticky) - #define LENGTH(X) (sizeof X / sizeof X[0]) - #define MOUSEMASK (BUTTONMASK|PointerMotionMask) - #define WIDTH(X) ((X)->w + 2 * (X)->bw) -@@ -92,7 +92,7 @@ struct Client { - int basew, baseh, incw, inch, maxw, maxh, minw, minh; - int bw, oldbw; - unsigned int tags; -- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; -+ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, issticky; - Client *next; - Client *snext; - Monitor *mon; -@@ -211,6 +211,7 @@ static void tagmon(const Arg *arg); - static void tile(Monitor *); - static void togglebar(const Arg *arg); - static void togglefloating(const Arg *arg); -+static void togglesticky(const Arg *arg); - static void toggletag(const Arg *arg); - static void toggleview(const Arg *arg); - static void unfocus(Client *c, int setfocus); -@@ -1713,6 +1714,15 @@ togglefloating(const Arg *arg) - } - - void -+togglesticky(const Arg *arg) -+{ -+ if (!selmon->sel) -+ return; -+ selmon->sel->issticky = !selmon->sel->issticky; -+ arrange(selmon); -+} -+ -+void - toggletag(const Arg *arg) - { - unsigned int newtags; diff --git a/.local/src/dwm/patches/dwm-warp-6.2.diff b/.local/src/dwm/patches/dwm-warp-6.2.diff @@ -1,58 +0,0 @@ -diff --git a/dwm.c b/dwm.c -index 4465af1..bf74f60 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -227,6 +227,7 @@ static void updatetitle(Client *c); - static void updatewindowtype(Client *c); - static void updatewmhints(Client *c); - static void view(const Arg *arg); -+static void warp(const Client *c); - static Client *wintoclient(Window w); - static Monitor *wintomon(Window w); - static int xerror(Display *dpy, XErrorEvent *ee); -@@ -827,6 +828,7 @@ focusmon(const Arg *arg) - unfocus(selmon->sel, 0); - selmon = m; - focus(NULL); -+ warp(selmon->sel); - } - - void -@@ -1367,6 +1369,8 @@ restack(Monitor *m) - } - XSync(dpy, False); - while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); -+ if (m == selmon && (m->tagset[m->seltags] & m->sel->tags) && selmon->lt[selmon->sellt] != &layouts[2]) -+ warp(m->sel); - } - - void -@@ -2044,6 +2048,28 @@ view(const Arg *arg) - arrange(selmon); - } - -+void -+warp(const Client *c) -+{ -+ int x, y; -+ -+ if (!c) { -+ XWarpPointer(dpy, None, root, 0, 0, 0, 0, selmon->wx + selmon->ww/2, selmon->wy + selmon->wh/2); -+ return; -+ } -+ -+ if (!getrootptr(&x, &y) || -+ (x > c->x - c->bw && -+ y > c->y - c->bw && -+ x < c->x + c->w + c->bw*2 && -+ y < c->y + c->h + c->bw*2) || -+ (y > c->mon->by && y < c->mon->by + bh) || -+ (c->mon->topbar && !y)) -+ return; -+ -+ XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); -+} -+ - Client * - wintoclient(Window w) - { diff --git a/.local/src/dwm/patches/dwm-xrdb-6.2.diff b/.local/src/dwm/patches/dwm-xrdb-6.2.diff @@ -1,188 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 1c0b587..5db7d05 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -7,15 +7,16 @@ 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" }; - static const char dmenufont[] = "monospace:size=10"; --static const char col_gray1[] = "#222222"; --static const char col_gray2[] = "#444444"; --static const char col_gray3[] = "#bbbbbb"; --static const char col_gray4[] = "#eeeeee"; --static const char col_cyan[] = "#005577"; --static const char *colors[][3] = { -- /* fg bg border */ -- [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, -- [SchemeSel] = { col_gray4, col_cyan, col_cyan }, -+static char normbgcolor[] = "#222222"; -+static char normbordercolor[] = "#444444"; -+static char normfgcolor[] = "#bbbbbb"; -+static char selfgcolor[] = "#eeeeee"; -+static char selbordercolor[] = "#005577"; -+static char selbgcolor[] = "#005577"; -+static char *colors[][3] = { -+ /* fg bg border */ -+ [SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor }, -+ [SchemeSel] = { selfgcolor, selbgcolor, selbordercolor }, - }; - - /* tagging */ -@@ -56,7 +57,7 @@ static const Layout layouts[] = { - - /* commands */ - static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ --static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; -+static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbordercolor, "-sf", selfgcolor, NULL }; - static const char *termcmd[] = { "st", NULL }; - - static Key keys[] = { -@@ -84,6 +85,7 @@ static Key keys[] = { - { MODKEY, XK_period, focusmon, {.i = +1 } }, - { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, - { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, -+ { MODKEY, XK_F5, xrdb, {.v = NULL } }, - TAGKEYS( XK_1, 0) - TAGKEYS( XK_2, 1) - TAGKEYS( XK_3, 2) -diff --git a/drw.c b/drw.c -index 8fd1ca4..e4968a0 100644 ---- a/drw.c -+++ b/drw.c -@@ -207,7 +207,7 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname) - /* 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[], size_t clrcount) - { - size_t i; - Clr *ret; -diff --git a/drw.h b/drw.h -index 4bcd5ad..42b04ce 100644 ---- a/drw.h -+++ b/drw.h -@@ -39,7 +39,7 @@ void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned in - - /* 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); -+Clr *drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount); - - /* Cursor abstraction */ - Cur *drw_cur_create(Drw *drw, int shape); -diff --git a/dwm.c b/dwm.c -index 4465af1..7fa45c5 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -35,6 +35,7 @@ - #include <X11/Xatom.h> - #include <X11/Xlib.h> - #include <X11/Xproto.h> -+#include <X11/Xresource.h> - #include <X11/Xutil.h> - #ifdef XINERAMA - #include <X11/extensions/Xinerama.h> -@@ -56,6 +57,21 @@ - #define HEIGHT(X) ((X)->h + 2 * (X)->bw) - #define TAGMASK ((1 << LENGTH(tags)) - 1) - #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) -+#define XRDB_LOAD_COLOR(R,V) if (XrmGetResource(xrdb, R, NULL, &type, &value) == True) { \ -+ if (value.addr != NULL && strnlen(value.addr, 8) == 7 && value.addr[0] == '#') { \ -+ int i = 1; \ -+ for (; i <= 6; i++) { \ -+ if (value.addr[i] < 48) break; \ -+ if (value.addr[i] > 57 && value.addr[i] < 65) break; \ -+ if (value.addr[i] > 70 && value.addr[i] < 97) break; \ -+ if (value.addr[i] > 102) break; \ -+ } \ -+ if (i == 7) { \ -+ strncpy(V, value.addr, 7); \ -+ V[7] = '\0'; \ -+ } \ -+ } \ -+ } - - /* enums */ - enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ -@@ -177,6 +193,7 @@ static void grabkeys(void); - static void incnmaster(const Arg *arg); - static void keypress(XEvent *e); - static void killclient(const Arg *arg); -+static void loadxrdb(void); - static void manage(Window w, XWindowAttributes *wa); - static void mappingnotify(XEvent *e); - static void maprequest(XEvent *e); -@@ -232,6 +249,7 @@ static Monitor *wintomon(Window w); - static int xerror(Display *dpy, XErrorEvent *ee); - static int xerrordummy(Display *dpy, XErrorEvent *ee); - static int xerrorstart(Display *dpy, XErrorEvent *ee); -+static void xrdb(const Arg *arg); - static void zoom(const Arg *arg); - - /* variables */ -@@ -1014,6 +1032,37 @@ killclient(const Arg *arg) - } - } - -+void -+loadxrdb() -+{ -+ Display *display; -+ char * resm; -+ XrmDatabase xrdb; -+ char *type; -+ XrmValue value; -+ -+ display = XOpenDisplay(NULL); -+ -+ if (display != NULL) { -+ resm = XResourceManagerString(display); -+ -+ if (resm != NULL) { -+ xrdb = XrmGetStringDatabase(resm); -+ -+ if (xrdb != NULL) { -+ XRDB_LOAD_COLOR("dwm.normbordercolor", normbordercolor); -+ XRDB_LOAD_COLOR("dwm.normbgcolor", normbgcolor); -+ XRDB_LOAD_COLOR("dwm.normfgcolor", normfgcolor); -+ XRDB_LOAD_COLOR("dwm.selbordercolor", selbordercolor); -+ XRDB_LOAD_COLOR("dwm.selbgcolor", selbgcolor); -+ XRDB_LOAD_COLOR("dwm.selfgcolor", selfgcolor); -+ } -+ } -+ } -+ -+ XCloseDisplay(display); -+} -+ - void - manage(Window w, XWindowAttributes *wa) - { -@@ -2110,6 +2159,17 @@ xerrorstart(Display *dpy, XErrorEvent *ee) - return -1; - } - -+void -+xrdb(const Arg *arg) -+{ -+ loadxrdb(); -+ int i; -+ for (i = 0; i < LENGTH(colors); i++) -+ scheme[i] = drw_scm_create(drw, colors[i], 3); -+ focus(NULL); -+ arrange(NULL); -+} -+ - void - zoom(const Arg *arg) - { -@@ -2136,6 +2196,8 @@ main(int argc, char *argv[]) - if (!(dpy = XOpenDisplay(NULL))) - die("dwm: cannot open display"); - checkotherwm(); -+ XrmInitialize();