├── .gitignore ├── terminfo └── s │ └── screen-it ├── xinitrc ├── dwm ├── dwm.desktop ├── config.h └── dwm-systray.diff ├── gitconfig ├── lidlock.service ├── xserverrc ├── st ├── no_bold.patch ├── extpipe.patch └── config.h ├── conkyrc ├── packages ├── coc-settings.json ├── urlview ├── Dockerfile ├── tmux.conf ├── irssi ├── config └── solarized-universal.theme ├── Makefile ├── vimrc ├── zshrc └── dircolors.256dark /.gitignore: -------------------------------------------------------------------------------- 1 | syntax: glob 2 | 3 | *.pyc 4 | *.swp 5 | *.swo 6 | tmp/ 7 | -------------------------------------------------------------------------------- /terminfo/s/screen-it: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LK4D4/dotfiles/HEAD/terminfo/s/screen-it -------------------------------------------------------------------------------- /xinitrc: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | (conky | while read LINE; do xsetroot -name "$LINE"; done) & 3 | eval $(ssh-agent) 4 | exec dwm 5 | -------------------------------------------------------------------------------- /dwm/dwm.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Encoding=UTF-8 3 | Name=Dwm 4 | Comment=Dynamic window manager 5 | Exec=/home/lk4d4/.xinitrc 6 | Icon=dwm 7 | Type=XSession 8 | -------------------------------------------------------------------------------- /gitconfig: -------------------------------------------------------------------------------- 1 | [user] 2 | name = Alexander Morozov 3 | email = lk4d4math@gmail.com 4 | [core] 5 | editor = vim 6 | [http] 7 | cookiefile = /home/lk4d4/.gitcookies 8 | -------------------------------------------------------------------------------- /lidlock.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Lock the screen on resume from suspend 3 | 4 | [Service] 5 | User=lk4d4 6 | Environment=DISPLAY=:0 7 | ExecStart=/usr/bin/slock 8 | 9 | [Install] 10 | WantedBy=sleep.target 11 | -------------------------------------------------------------------------------- /xserverrc: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | TTY=${TTY:-$(tty)} 4 | TTY=${TTY#/dev/} 5 | 6 | if [[ $TTY != tty* ]]; then 7 | printf '==> ERROR: invalid TTY\n' >&2 8 | exit 1 9 | fi 10 | 11 | printf -v vt 'vt%02d' "${TTY#tty}" 12 | 13 | exec /usr/bin/X -nolisten tcp "$vt" "$@" 14 | -------------------------------------------------------------------------------- /st/no_bold.patch: -------------------------------------------------------------------------------- 1 | diff --git a/x.c b/x.c 2 | index fbfd350..110f3cc 100644 3 | --- a/x.c 4 | +++ b/x.c 5 | @@ -1158,7 +1158,7 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i 6 | 7 | /* Change basic system colors [0-7] to bright system colors [8-15] */ 8 | if ((base.mode & ATTR_BOLD_FAINT) == ATTR_BOLD && BETWEEN(base.fg, 0, 7)) 9 | - fg = &dc.col[base.fg + 8]; 10 | + fg = &dc.col[base.fg]; 11 | 12 | if (IS_SET(MODE_REVERSE)) { 13 | if (fg == &dc.col[defaultfg]) { 14 | -------------------------------------------------------------------------------- /conkyrc: -------------------------------------------------------------------------------- 1 | conky.config = { 2 | out_to_x = false, 3 | out_to_console = true, 4 | background = false, 5 | cpu_avg_samples = 2, 6 | net_avg_samples = 2, 7 | no_buffers = true, 8 | out_to_stderr = false, 9 | update_interval = 1.0, 10 | uppercase = false, 11 | use_spacer = 'none', 12 | }; 13 | 14 | conky.text = 15 | [[RAM: $memperc% :: CPU Usage: $cpu% :: Bat: ${battery BAT0} :: Vol: ${exec amixer get Master -M | awk '/^ Front Left/ {print $5}'} :: ${time %D %H:%M} :: [${exec skb 1}] ]]; 16 | -------------------------------------------------------------------------------- /packages: -------------------------------------------------------------------------------- 1 | app-admin/conky 2 | app-admin/lastpass-cli 3 | app-arch/lzop 4 | app-editors/neovim 5 | app-misc/tmux 6 | app-portage/eix 7 | app-portage/flaggie 8 | app-shells/gentoo-zsh-completions 9 | app-shells/zsh 10 | app-shells/zsh-completions 11 | dev-python/virtualenvwrapper 12 | dev-vcs/git 13 | media-fonts/terminus-font 14 | media-sound/alsa-utils 15 | media-sound/pulseaudio 16 | net-misc/urlview 17 | net-wireless/wpa_supplicant 18 | www-client/google-chrome 19 | x11-apps/xsetroot 20 | x11-base/xorg-server 21 | x11-misc/dmenu 22 | x11-misc/slock 23 | -------------------------------------------------------------------------------- /coc-settings.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | "languageserver": { 4 | "golang": { 5 | "command": "gopls", 6 | "rootPatterns": [".git", "go.mod"], 7 | "filetypes": ["go"], 8 | "initializationOptions": { 9 | "staticcheck": true 10 | } 11 | } 12 | }, 13 | "python.formatting.provider": "black", 14 | "python.formatting.blackPath": "/home/lk4d4/.local/bin/black", 15 | "python.linting.mypyPath": "/home/lk4d4/src/server/mypy/mypy-daemon-all", 16 | "python.linting.mypyEnabled": true, 17 | "coc.preferences.formatOnSaveFiletypes": ["python", "go"], 18 | } 19 | -------------------------------------------------------------------------------- /urlview: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Urlview configuration file. 3 | # man urlview 4 | # 5 | # Put this file in: $HOME/.urlview 6 | # Put url_handler.sh in: /usr/bin 7 | # 8 | # You can call 'urlview' while in 'mutt' by pressing the Ctrl b keys. 9 | # Put these macros in your $HOME/.muttrc file. 10 | # 11 | # macro index \cb |urlview\n 12 | # macro pager \cb |urlview\n 13 | # 14 | # You can call 'urlview' while in 'tin' by pressing | then a for article, 15 | # put urlview as the pipe command. 16 | # 17 | # Regular expression to use to match URLs. 18 | 19 | #REGEXP (((http|https|ftp|gopher)|mailto):(//)?[^ >"\t]*|www\.[-a-z0-9.]+)[^ .,;\t>">\):] 20 | REGEXP (((http|https|ftp|gopher)|mailto)[.:][^ >"\t]*|www\.[-a-z0-9.]+)[^ .,;\t>">\):] 21 | 22 | # Command to invoke for selected URL. Use lynx, netscape, or url_handler.sh 23 | # shell script. 24 | 25 | #COMMAND lynx %s 26 | #COMMAND netscape -remote 'openURL(%s)' 27 | #COMMAND url_handler.sh 28 | COMMAND google-chrome-stable %s 29 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | from ubuntu:14.04 2 | 3 | run apt-get update -y 4 | run apt-get install -y mercurial 5 | run apt-get install -y git 6 | run apt-get install -y bzr 7 | run apt-get install -y python 8 | run apt-get install -y httpie 9 | run apt-get install -y curl 10 | run apt-get install -y vim 11 | run apt-get install -y strace 12 | run apt-get install -y diffstat 13 | run apt-get install -y build-essential 14 | run apt-get install -y tcpdump 15 | run apt-get install -y tmux 16 | run apt-get install -y zsh 17 | run apt-get install -y python-pip 18 | run pip install virtualenv 19 | run apt-get install -y virtualenvwrapper 20 | 21 | # Install go 22 | run curl https://storage.googleapis.com/golang/go1.3beta2.linux-amd64.tar.gz | tar -C /usr/local -zx 23 | env GOROOT /usr/local/go 24 | env PATH /usr/local/go/bin:$PATH 25 | 26 | # Setup home environment 27 | run useradd dev 28 | run mkdir /home/dev && chown -R dev: /home/dev 29 | run mkdir -p /home/dev/go /home/dev/bin /home/dev/lib /home/dev/include 30 | env PATH /home/dev/bin:$PATH 31 | env PKG_CONFIG_PATH /home/dev/lib/pkgconfig 32 | env LD_LIBRARY_PATH /home/dev/lib 33 | env GOPATH /home/dev/go 34 | 35 | run mkdir /var/shared/ 36 | run touch /var/shared/placeholder 37 | run chown -R dev:dev /var/shared 38 | volume /var/shared 39 | 40 | workdir /home/dev 41 | env HOME /home/dev 42 | add . /home/dev/dotfiles 43 | run make -C /home/dev/dotfiles dockerenv 44 | run ln -s /var/shared/.ssh 45 | 46 | run chown -R dev: /home/dev 47 | user dev 48 | 49 | entrypoint ["/bin/zsh", "-l"] 50 | -------------------------------------------------------------------------------- /tmux.conf: -------------------------------------------------------------------------------- 1 | # --- colors (solarized dark) 2 | # default statusbar colors 3 | set -g status-bg black 4 | set -g status-fg yellow 5 | set -g status-attr default 6 | 7 | # default window title colors 8 | setw -g window-status-fg brightblue 9 | setw -g window-status-bg default 10 | 11 | # active window title colors 12 | setw -g window-status-current-fg yellow 13 | setw -g window-status-current-bg default 14 | setw -g window-status-current-attr dim 15 | 16 | # pane border 17 | set -g pane-border-fg black 18 | set -g pane-border-bg default 19 | set -g pane-active-border-fg yellow 20 | set -g pane-active-border-bg default 21 | 22 | # command line/message text 23 | set -g message-bg black 24 | set -g message-fg yellow 25 | 26 | # pane number display 27 | set -g display-panes-active-colour yellow 28 | set -g display-panes-colour brightblue 29 | 30 | # clock 31 | setw -g clock-mode-colour yellow 32 | # --- end colors 33 | 34 | set-window-option -g mode-keys vi 35 | set-option -g status-keys vi 36 | 37 | set-option -g set-titles on 38 | set-option -g set-titles-string '#S:#I.#P #W' 39 | set-window-option -g automatic-rename on 40 | 41 | set -g prefix ` 42 | bind ` send-prefix 43 | set -g default-terminal "screen-256color" 44 | set -g terminal-overrides 'screen*:sitm@,ritm@' 45 | set -g escape-time 20 46 | 47 | unbind k 48 | unbind j 49 | unbind h 50 | unbind l 51 | 52 | bind-key j select-pane -D 53 | bind-key k select-pane -U 54 | bind-key h select-pane -L 55 | bind-key l select-pane -R 56 | 57 | bind-key u capture-pane \; save-buffer /tmp/tmux-buffer \; new-window -n "urlview" '$SHELL -c "urlview < /tmp/tmux-buffer"' 58 | bind-key y run "tmux save-buffer - | xclip -i" 59 | 60 | #bind-key -t vi-copy 'v' begin-selection 61 | #bind-key -t vi-copy 'y' copy-selection 62 | 63 | bind % split-window -h -c "#{pane_current_path}" 64 | bind '"' split-window -c "#{pane_current_path}" 65 | bind c new-window -c "#{pane_current_path}" 66 | -------------------------------------------------------------------------------- /st/extpipe.patch: -------------------------------------------------------------------------------- 1 | diff --git a/st.c b/st.c 2 | index 46c954b..35cd7de 100644 3 | --- a/st.c 4 | +++ b/st.c 5 | @@ -1972,6 +1972,59 @@ tprinter(char *s, size_t len) 6 | } 7 | } 8 | 9 | +void 10 | +externalpipe(const Arg *arg) 11 | +{ 12 | + int to[2]; 13 | + char buf[UTF_SIZ]; 14 | + void (*oldsigpipe)(int); 15 | + Glyph *bp, *end; 16 | + int lastpos, n, newline; 17 | + 18 | + if (pipe(to) == -1) 19 | + return; 20 | + 21 | + switch (fork()) { 22 | + case -1: 23 | + close(to[0]); 24 | + close(to[1]); 25 | + return; 26 | + case 0: 27 | + dup2(to[0], STDIN_FILENO); 28 | + close(to[0]); 29 | + close(to[1]); 30 | + execvp(((char **)arg->v)[0], (char **)arg->v); 31 | + fprintf(stderr, "st: execvp %s\n", ((char **)arg->v)[0]); 32 | + perror("failed"); 33 | + exit(0); 34 | + } 35 | + 36 | + close(to[0]); 37 | + /* ignore sigpipe for now, in case child exists early */ 38 | + oldsigpipe = signal(SIGPIPE, SIG_IGN); 39 | + newline = 0; 40 | + for (n = 0; n < term.row; n++) { 41 | + bp = term.line[n]; 42 | + lastpos = MIN(tlinelen(n) + 1, term.col) - 1; 43 | + if (lastpos < 0) 44 | + break; 45 | + end = &bp[lastpos + 1]; 46 | + for (; bp < end; ++bp) 47 | + if (xwrite(to[1], buf, utf8encode(bp->u, buf)) < 0) 48 | + break; 49 | + if ((newline = term.line[n][lastpos].mode & ATTR_WRAP)) 50 | + continue; 51 | + if (xwrite(to[1], "\n", 1) < 0) 52 | + break; 53 | + newline = 0; 54 | + } 55 | + if (newline) 56 | + (void)xwrite(to[1], "\n", 1); 57 | + close(to[1]); 58 | + /* restore */ 59 | + signal(SIGPIPE, oldsigpipe); 60 | +} 61 | + 62 | void 63 | iso14755(const Arg *arg) 64 | { 65 | diff --git a/st.h b/st.h 66 | index dac64d8..86cd646 100644 67 | --- a/st.h 68 | +++ b/st.h 69 | @@ -80,6 +80,7 @@ void die(const char *, ...); 70 | void redraw(void); 71 | void draw(void); 72 | 73 | +void externalpipe(const Arg *); 74 | void iso14755(const Arg *); 75 | void printscreen(const Arg *); 76 | void printsel(const Arg *); 77 | -------------------------------------------------------------------------------- /irssi/config: -------------------------------------------------------------------------------- 1 | servers = ( 2 | { 3 | address = "chat.freenode.net"; 4 | chatnet = "Freenode"; 5 | port = "6667"; 6 | autoconnect = "yes"; 7 | password = "*****"; 8 | }, 9 | ); 10 | 11 | chatnets = { 12 | Freenode = { 13 | type = "IRC"; 14 | max_kicks = "1"; 15 | max_msgs = "4"; 16 | max_whois = "1"; 17 | }; 18 | }; 19 | 20 | channels = ( 21 | { name = "#docker-dev"; chatnet = "Freenode"; autojoin = "Yes"; }, 22 | { name = "#docker-maintainers"; chatnet = "Freenode"; autojoin = "Yes"; }, 23 | { name = "#opencontainers"; chatnet = "Freenode"; autojoin = "Yes"; }, 24 | { name = "#go-nuts"; chatnet = "Freenode"; autojoin = "Yes"; }, 25 | ); 26 | 27 | aliases = { 28 | J = "join"; 29 | WJOIN = "join -window"; 30 | WQUERY = "query -window"; 31 | LEAVE = "part"; 32 | BYE = "quit"; 33 | EXIT = "quit"; 34 | SIGNOFF = "quit"; 35 | DESCRIBE = "action"; 36 | DATE = "time"; 37 | HOST = "userhost"; 38 | LAST = "lastlog"; 39 | SAY = "msg *"; 40 | WI = "whois"; 41 | WII = "whois $0 $0"; 42 | WW = "whowas"; 43 | W = "who"; 44 | N = "names"; 45 | M = "msg"; 46 | T = "topic"; 47 | C = "clear"; 48 | CL = "clear"; 49 | K = "kick"; 50 | KB = "kickban"; 51 | KN = "knockout"; 52 | BANS = "ban"; 53 | B = "ban"; 54 | MUB = "unban *"; 55 | UB = "unban"; 56 | IG = "ignore"; 57 | UNIG = "unignore"; 58 | SB = "scrollback"; 59 | UMODE = "mode $N"; 60 | WC = "window close"; 61 | WN = "window new hide"; 62 | SV = "say Irssi $J ($V) - http://irssi.org/"; 63 | GOTO = "sb goto"; 64 | CHAT = "dcc chat"; 65 | RUN = "SCRIPT LOAD"; 66 | CALC = "exec - if command -v bc >/dev/null 2>&1\\; then printf '%s=' '$*'\\; echo '$*' | bc -l\\; else echo bc was not found\\; fi"; 67 | SBAR = "STATUSBAR"; 68 | INVITELIST = "mode $C +I"; 69 | Q = "QUERY"; 70 | "MANUAL-WINDOWS" = "set use_status_window off;set autocreate_windows off;set autocreate_query_level none;set autoclose_windows off;set reuse_unused_windows on;save"; 71 | EXEMPTLIST = "mode $C +e"; 72 | ATAG = "WINDOW SERVER"; 73 | UNSET = "set -clear"; 74 | RESET = "set -default"; 75 | }; 76 | 77 | settings = { 78 | core = { 79 | real_name = "Alexander Morozov"; 80 | user_name = "lk4d4"; 81 | nick = "lk4d4"; 82 | }; 83 | "fe-text" = { actlist_sort = "refnum"; }; 84 | "fe-common/core" = { 85 | bell_beeps = "yes"; 86 | beep_msg_level = "MSGS NOTICES INVITES DCC DCCMSGS HILIGHT"; 87 | theme = "solarized-universal"; 88 | }; 89 | }; 90 | ignores = ( 91 | { 92 | level = "JOINS PARTS QUITS MODES"; 93 | channels = ( "#libcontainer", "#docker-dev", "#go-nuts" ); 94 | }, 95 | { level = "JOINS PARTS QUITS NICKS"; channels = ( "#docker" ); } 96 | ); 97 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CWD=$(shell pwd) 2 | BINDIR=$(HOME)/bin 3 | 4 | all: vim zsh tmux st dwm 5 | 6 | vim: goinstall rls 7 | mkdir -p $(HOME)/.config/nvim 8 | test -L $(HOME)/.vimrc || ln -s $(CWD)/vimrc $(HOME)/.vimrc 9 | test -L $(HOME)/.config/nvim/init.vim || ln -s $(CWD)/vimrc $(HOME)/.config/nvim/init.vim 10 | 11 | rg: 12 | rm -rf $(CWD)/tmp/ripgrep 13 | git clone https://github.com/BurntSushi/ripgrep $(CWD)/tmp/ripgrep 14 | cd $(CWD)/tmp/ripgrep && cargo build --release 15 | test -L $(HOME)/bin/rg || ln -s $(CWD)/tmp/ripgrep/target/release/rg $(HOME)/bin/rg 16 | 17 | rls: 18 | rustup component add rls-preview rust-analysis rust-src 19 | 20 | rust: 21 | curl https://sh.rustup.rs -sSf | sh 22 | 23 | zsh: dircolors 24 | ln -s $(CWD)/zshrc $(HOME)/.zshrc 25 | 26 | tmux: 27 | ln -s $(CWD)/tmux.conf $(HOME)/.tmux.conf 28 | ln -s $(CWD)/urlview $(HOME)/.urlview 29 | 30 | terminfo: 31 | rm -rf $(HOME)/.terminfo 32 | ln -s $(CWD)/terminfo $(HOME)/.terminfo 33 | 34 | conky: skb 35 | rm -rf $(HOME)/.conkyrc 36 | ln -s $(CWD)/conkyrc $(HOME)/.conkyrc 37 | 38 | git: 39 | rm -rf $(HOME)/.gitconfig 40 | ln -s $(CWD)/gitconfig $(HOME)/.gitconfig 41 | 42 | tmp: 43 | mkdir $(CWD)/tmp 44 | 45 | PACKAGES = golang.org/x/tools/cmd/goimports \ 46 | github.com/mdempsky/gocode \ 47 | github.com/rogpeppe/godef \ 48 | golang.org/x/tools/cmd/gorename \ 49 | github.com/google/pprof \ 50 | golang.org/x/tools/cmd/guru \ 51 | github.com/sourcegraph/go-langserver 52 | 53 | 54 | goinstall: 55 | $(foreach pkg,$(PACKAGES),go get -u $(pkg);) 56 | $(foreach pkg,$(notdir $(PACKAGES)),rm -rf $(BINDIR)/$(pkg) && ln -s $(shell go env GOPATH)/bin/$(pkg) $(BINDIR)/$(pkg);) 57 | 58 | dircolors: 59 | test -L $(HOME)/.dir_colors || ln -s $(CWD)/dircolors.256dark $(HOME)/.dir_colors 60 | 61 | st: terminfo tmp dircolors 62 | rm -rf $(CWD)/tmp/st 63 | git clone http://git.suckless.org/st $(CWD)/tmp/st 64 | cp $(CWD)/st/config.h $(CWD)/tmp/st 65 | cd $(CWD)/tmp/st && git apply --ignore-space-change --ignore-whitespace $(CWD)/st/no_bold.patch 66 | cd $(CWD)/tmp/st && git apply --ignore-space-change --ignore-whitespace $(CWD)/st/extpipe.patch 67 | $(MAKE) -C $(CWD)/tmp/st all 68 | test -L $(HOME)/bin/st || ln -s $(CWD)/tmp/st/st $(HOME)/bin/st 69 | 70 | dwm: tmp conky 71 | rm -rf $(CWD)/tmp/dwm 72 | git clone http://git.suckless.org/dwm $(CWD)/tmp/dwm 73 | cp $(CWD)/dwm/config.h $(CWD)/tmp/dwm 74 | cd $(CWD)/tmp/dwm && git apply --ignore-space-change --ignore-whitespace $(CWD)/dwm/dwm-systray.diff 75 | $(MAKE) -C $(CWD)/tmp/dwm all 76 | test -L $(HOME)/bin/dwm || ln -s $(CWD)/tmp/dwm/dwm $(HOME)/bin/dwm 77 | test -L $(HOME)/.xserverrc || ln -s $(CWD)/xserverrc $(HOME)/.xserverrc 78 | test -L $(HOME)/.xinitrc || ln -s $(CWD)/xinitrc $(HOME)/.xinitrc 79 | 80 | skb: 81 | rm -rf $(CWD)/tmp/skb 82 | git clone https://github.com/polachok/skb.git $(CWD)/tmp/skb 83 | cd $(CWD)/tmp/skb 84 | $(MAKE) -C $(CWD)/tmp/skb 85 | test -L $(HOME)/bin/skb || ln -s $(CWD)/tmp/skb/skb $(HOME)/bin/skb 86 | 87 | .PHONY: st terminfo dwm 88 | -------------------------------------------------------------------------------- /vimrc: -------------------------------------------------------------------------------- 1 | set nocompatible 2 | 3 | let s:plug_path = '~/.vim/autoload/plug.vim' 4 | let s:plug_dir = '~/.vim/plugged' 5 | 6 | if empty(glob(s:plug_path)) 7 | silent execute '!curl -fLo '.s:plug_path.' --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim' 8 | autocmd VimEnter * PlugInstall | source $MYVIMRC 9 | endif 10 | 11 | call plug#begin(s:plug_dir) 12 | 13 | Plug 'neoclide/coc.nvim', {'branch': 'release'} 14 | 15 | Plug 'altercation/vim-colors-solarized' 16 | 17 | Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --all' } 18 | Plug 'junegunn/fzf.vim' 19 | Plug 'tweekmonster/fzf-filemru' 20 | Plug 'easymotion/vim-easymotion' 21 | Plug 'scrooloose/nerdcommenter' 22 | 23 | Plug 'tpope/vim-markdown', { 'for': 'md' } 24 | 25 | Plug 'tpope/vim-fugitive' 26 | Plug 'jplaut/vim-arduino-ino' 27 | Plug 'fcpg/vim-osc52' 28 | 29 | set hidden 30 | 31 | call plug#end() 32 | 33 | filetype plugin indent on 34 | 35 | syntax on 36 | 37 | let mapleader = "\" 38 | 39 | set paste 40 | set incsearch hlsearch 41 | 42 | set nolist 43 | set listchars=tab:▹\ ,trail:▿ 44 | 45 | set keymap=russian-jcukenwin 46 | set iminsert=0 47 | set imsearch=0 48 | set wildmode=longest,list,full 49 | set wildmenu 50 | set cursorline 51 | set laststatus=2 52 | imap jj 53 | set noexpandtab shiftwidth=4 softtabstop=4 tabstop=4 54 | 55 | set updatetime=300 56 | set shortmess+=c 57 | set signcolumn=yes 58 | 59 | inoremap 60 | \ pumvisible() ? "\" : 61 | \ check_back_space() ? "\" : 62 | \ coc#refresh() 63 | 64 | function! s:check_back_space() abort 65 | let col = col('.') - 1 66 | return !col || getline('.')[col - 1] =~# '\s' 67 | endfunction 68 | 69 | inoremap pumvisible() ? "\" : "\u\" 70 | 71 | xmap y:call SendViaOSC52(getreg('"')) 72 | 73 | set statusline=%F%m%r%h%w 74 | set statusline+=%=%{fugitive#statusline()} 75 | set statusline+=[%{strlen(&fenc)?&fenc:&enc}] 76 | set statusline+=\ [line\ %l\/%L] 77 | 78 | " easymotion 79 | nmap s (easymotion-overwin-f2) 80 | let g:EasyMotion_smartcase = 1 81 | map j (easymotion-j) 82 | map k (easymotion-k) 83 | 84 | autocmd BufWritePre *.go :CocCommand editor.action.organizeImport 85 | nmap [c (coc-diagnostic-prev) 86 | nmap ]c (coc-diagnostic-next) 87 | 88 | nmap gd (coc-definition) 89 | nmap gy (coc-type-definition) 90 | nmap gi (coc-implementation) 91 | nmap gr (coc-references) 92 | nmap rn (coc-rename) 93 | 94 | set colorcolumn=120 95 | 96 | " Press space to clear search highlighting 97 | nnoremap n :noh 98 | nnoremap i 99 | nnoremap :FilesMru --tiebreak=end 100 | nnoremap / :Rg 101 | 102 | " Map toggling paste mode 103 | nnoremap :set invpaste paste? 104 | set pastetoggle= 105 | set invpaste 106 | set mouse=a 107 | nnoremap s :exec "normal i".nr2char(getchar())."\e" 108 | nnoremap S :exec "normal a".nr2char(getchar())."\e" 109 | nnoremap :set pastem`o``:set nopaste 110 | nnoremap :set pastem`O``:set nopaste 111 | 112 | nnoremap w :w 113 | 114 | vmap y "*y 115 | nmap yy "*yy 116 | vmap d "*d 117 | nmap p "*p 118 | nmap P "*P 119 | vmap p "*p 120 | vmap P "*P 121 | 122 | "disable arrows 123 | inoremap 124 | inoremap 125 | inoremap 126 | inoremap 127 | noremap 128 | noremap 129 | noremap 130 | noremap 131 | 132 | set background="dark" 133 | let g:solarized_visibility = "high" 134 | colorscheme solarized 135 | -------------------------------------------------------------------------------- /zshrc: -------------------------------------------------------------------------------- 1 | export GOARCH=amd64 2 | export GOOS=linux 3 | export PATH=$PATH:$HOME/bin 4 | export GPG_TTY=$(tty) 5 | export LPASS_CLIPBOARD_COMMAND="xclip -selection primary -in -l 1" 6 | 7 | #Set LS_COLORS 8 | if [[ -f ~/.dir_colors ]]; then 9 | eval `dircolors -b ~/.dir_colors` 10 | else 11 | eval `dircolors -b /etc/DIR_COLORS` 12 | fi 13 | 14 | # History settings 15 | HISTFILE=~/.histfile 16 | HISTSIZE=3000 17 | SAVEHIST=3000 18 | setopt APPEND_HISTORY 19 | setopt INC_APPEND_HISTORY 20 | setopt NO_HIST_BEEP 21 | setopt HIST_IGNORE_DUPS 22 | setopt HIST_IGNORE_ALL_DUPS 23 | setopt HIST_EXPIRE_DUPS_FIRST 24 | setopt HIST_SAVE_NO_DUPS 25 | setopt HIST_FIND_NO_DUPS 26 | # Use the same history file for all sessions 27 | setopt SHARE_HISTORY 28 | # Let the user edit the command line after history expansion (e.g. !ls) instead of immediately running it 29 | setopt hist_verify 30 | 31 | setopt extended_glob 32 | setopt noequals 33 | setopt nobeep 34 | setopt CORRECT 35 | setopt autocd 36 | setopt nohup 37 | setopt HASH_CMDS 38 | 39 | # Don't fail on unsuccessful globbing 40 | unsetopt NOMATCH 41 | 42 | bindkey -e 43 | 44 | # The following lines were added by compinstall 45 | zstyle :compinstall filename '~/.zshrc' 46 | 47 | autoload -Uz compinit 48 | compinit 49 | # End of lines added by compinstall 50 | 51 | bindkey "^[[2~" yank 52 | bindkey "^[[3~" delete-char 53 | bindkey "^[[5~" history-beginning-search-backward 54 | bindkey "^[[6~" history-beginning-search-forward 55 | bindkey "^[[7~" beginning-of-line 56 | bindkey "^[[8~" end-of-line 57 | bindkey "^[[A" up-line-or-history 58 | bindkey "^[[B" down-line-or-history 59 | bindkey "^[[H" beginning-of-line 60 | bindkey "^[[F" end-of-line 61 | bindkey "^[e" expand-cmd-path 62 | bindkey "^[[1~" beginning-of-line # Pos1 63 | bindkey "^[[4~" end-of-line 64 | bindkey " " magic-space 65 | bindkey "^[u" undo 66 | bindkey "^[r" redo 67 | 68 | bindkey "^R" history-incremental-search-backward 69 | 70 | alias ls='ls -h --color=auto --group-directories-first' 71 | alias flash='mount /mnt/flash' 72 | alias df='df -m' 73 | alias lsl='ls -hl --color=auto --group-directories-first' 74 | 75 | alias mv='nocorrect mv -i' 76 | alias cp='nocorrect cp -Ri' 77 | alias rm='nocorrect rm -rI' 78 | alias rmf='nocorrect rm -f' 79 | alias rmrf='nocorrect rm -fR' 80 | alias mkdir='nocorrect mkdir' 81 | 82 | # Convenient ones 83 | alias tmux="tmux -u2" 84 | alias wget="wget --continue --content-disposition" 85 | alias vim="nvim" 86 | alias grep="grep --colour" 87 | alias pt="GOGC=off pt" 88 | 89 | function zle-line-init () { 90 | if (( ${+terminfo[smkx]} )); then 91 | echoti smkx 92 | fi 93 | } 94 | function zle-line-finish () { 95 | if (( ${+terminfo[rmkx]} )); then 96 | echoti rmkx 97 | fi 98 | } 99 | zle -N zle-line-init 100 | zle -N zle-line-finish 101 | 102 | ## Shell functions 103 | # Watch YouTube video with Mplayer 104 | youmplayer () { mplayer `youtube-dl -g $1` } 105 | 106 | # Coloured and lessed diff 107 | udiff() { 108 | difflength=`diff -u $1 $2 | wc -l` 109 | cmd="diff -u $1 $2 | pygmentize-3.1 -g" 110 | if [[ LINES -lt difflength ]] then 111 | cmd="${cmd} | less" 112 | fi 113 | eval $cmd 114 | } 115 | 116 | # Open package homepage 117 | urlix () { 118 | for url in `eix -e --pure-packages $1 --format ''`; do 119 | $BROWSER "$url" > /dev/null; 120 | done 121 | } 122 | 123 | # Open package's ebuild in editor 124 | ebldopen () { 125 | $EDITOR `equery which $1` 126 | } 127 | 128 | # Open package changelog 129 | ebldlog () { 130 | $EDITOR $(dirname `equery which $1`)/ChangeLog 131 | } 132 | 133 | compdef "_gentoo_packages available" urlix ebldopen ebldlog 134 | 135 | # Auto-completion from `cmd --help` 136 | compdef _gnu_generic feh 137 | 138 | # Complete pumount like umount 139 | compdef _mount pumount 140 | 141 | # Set LCD brightness (root access required, obviously) 142 | bright () { 143 | BRIGHTFILE="/sys/devices/virtual/backlight/acpi_video0/brightness" 144 | if [[ -n $1 ]] then 145 | echo $1 > $BRIGHTFILE; 146 | return 0; 147 | fi 148 | local list 149 | list=("1" "5") 150 | bright=`cat $BRIGHTFILE` 151 | if [[ $bright != $list[1] ]] then 152 | echo $list[1] > $BRIGHTFILE 153 | else 154 | echo $list[2] > $BRIGHTFILE 155 | fi 156 | } 157 | 158 | # Imguring 159 | imgur() { 160 | curl -sS -H 'Authorization: Client-ID 9657b96ca0b7f38' -H 'Expect: ' -F "image=@$1" https://api.imgur.com/3/image | jq ".data.link" | sed -e 's/"//g' 161 | } 162 | 163 | # prompt 164 | autoload -U promptinit 165 | promptinit 166 | 167 | # gentoovcs prompt theme 168 | autoload -Uz vcs_info 169 | zstyle ':vcs_info:*' enable git svn hg 170 | zstyle ':vcs_info:git:*' formats '[±:%b]' 171 | zstyle ':vcs_info:hg:*' formats '[☿:%b]' 172 | setopt PROMPT_SUBST 173 | 174 | prompt_gentoovcs_help () { 175 | cat <<'EOF' 176 | Standard Gentoo prompt theme with VCS info. Like original, it's color-scheme-able: 177 | 178 | prompt gentoovcs [ [ [ []]]] 179 | 180 | EOF 181 | 182 | } 183 | 184 | prompt_gentoovcs_setup () { 185 | prompt_gentoo_prompt=${1:-'blue'} 186 | prompt_gentoo_user=${2:-'green'} 187 | prompt_gentoo_root=${3:-'red'} 188 | prompt_gentoo_vcs=${4:-'white'} 189 | 190 | if [ "$USER" = 'root' ] 191 | then 192 | base_prompt="%B%F{$prompt_gentoo_root}%m%k " 193 | else 194 | base_prompt="%B%F{$prompt_gentoo_user}%n@%m%k " 195 | fi 196 | post_prompt="%b%f%k" 197 | 198 | path_prompt="%B%F{$prompt_gentoo_prompt}%1~" 199 | PS1="$base_prompt"'%B%F{$prompt_gentoo_vcs}${vcs_info_msg_0_:+${vcs_info_msg_0_} }'"$path_prompt %# $post_prompt" 200 | PS2="$base_prompt$path_prompt %_> $post_prompt" 201 | PS3="$base_prompt$path_prompt ?# $post_prompt" 202 | 203 | add-zsh-hook precmd vcs_info 204 | } 205 | 206 | if [[ $TERM == "screen" ]] then 207 | prompt clint 208 | else 209 | prompt_gentoovcs_setup "$@" 210 | fi 211 | 212 | # Zmv! 213 | autoload -U zmv 214 | # Zcalc! 215 | autoload -U zcalc 216 | 217 | # Cache completion 218 | zstyle ':completion::complete:*' use-cache 1 219 | 220 | # List completions 221 | zmodload zsh/complist 222 | zstyle ':completion:*' menu select 223 | zstyle ':completion:*:default' list-colors ${(s.:.)LS_COLORS} 224 | 225 | # Kill processes with completion 226 | zstyle ':completion:*:processes' command 'ps -xuf' 227 | zstyle ':completion:*:processes' sort false 228 | zstyle ':completion:*:processes-names' command 'ps xho command' 229 | zstyle '*' hosts $hosts 230 | 231 | # Force rehashing 232 | _force_rehash() { 233 | (( CURRENT == 1 )) && rehash 234 | return 1 235 | } 236 | 237 | # Load forced rehash 238 | zstyle ':completion:*' completer _oldlist _expand _force_rehash _complete 239 | 240 | 241 | [ -f ~/.fzf.zsh ] && source ~/.fzf.zsh 242 | -------------------------------------------------------------------------------- /dircolors.256dark: -------------------------------------------------------------------------------- 1 | 2 | # Dark 256 color solarized theme for the color GNU ls utility. 3 | # Used and tested with dircolors (GNU coreutils) 8.5 4 | # 5 | # @author {@link http://sebastian.tramp.name Sebastian Tramp} 6 | # @license http://sam.zoy.org/wtfpl/ Do What The Fuck You Want To Public License (WTFPL) 7 | # 8 | # More Information at 9 | # https://github.com/seebi/dircolors-solarized 10 | 11 | # Term Section 12 | TERM Eterm 13 | TERM ansi 14 | TERM color-xterm 15 | TERM con132x25 16 | TERM con132x30 17 | TERM con132x43 18 | TERM con132x60 19 | TERM con80x25 20 | TERM con80x28 21 | TERM con80x30 22 | TERM con80x43 23 | TERM con80x50 24 | TERM con80x60 25 | TERM cons25 26 | TERM console 27 | TERM cygwin 28 | TERM dtterm 29 | TERM eterm-color 30 | TERM gnome 31 | TERM gnome-256color 32 | TERM jfbterm 33 | TERM konsole 34 | TERM kterm 35 | TERM linux 36 | TERM linux-c 37 | TERM mach-color 38 | TERM mlterm 39 | TERM putty 40 | TERM rxvt 41 | TERM rxvt-256color 42 | TERM rxvt-cygwin 43 | TERM rxvt-cygwin-native 44 | TERM rxvt-unicode 45 | TERM rxvt-unicode256 46 | TERM rxvt-unicode-256color 47 | TERM screen 48 | TERM screen-256color 49 | TERM screen-256color-bce 50 | TERM screen-256color-s 51 | TERM screen-256color-bce-s 52 | TERM screen-bce 53 | TERM screen-w 54 | TERM screen.linux 55 | TERM vt100 56 | TERM xterm 57 | TERM xterm-16color 58 | TERM xterm-256color 59 | TERM xterm-88color 60 | TERM xterm-color 61 | TERM xterm-debian 62 | 63 | ## Documentation 64 | # 65 | # standard colors 66 | # 67 | # Below are the color init strings for the basic file types. A color init 68 | # string consists of one or more of the following numeric codes: 69 | # Attribute codes: 70 | # 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed 71 | # Text color codes: 72 | # 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white 73 | # Background color codes: 74 | # 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white 75 | # 76 | # 77 | # 256 color support 78 | # see here: http://www.mail-archive.com/bug-coreutils@gnu.org/msg11030.html) 79 | # 80 | # Text 256 color coding: 81 | # 38;5;COLOR_NUMBER 82 | # Background 256 color coding: 83 | # 48;5;COLOR_NUMBER 84 | 85 | ## Special files 86 | 87 | NORMAL 00;38;5;244 # no color code at all 88 | #FILE 00 # regular file: use no color at all 89 | RESET 0 # reset to "normal" color 90 | DIR 00;38;5;33 # directory 01;34 91 | LINK 01;38;5;37 # symbolic link. (If you set this to 'target' instead of a 92 | # numerical value, the color is as for the file pointed to.) 93 | MULTIHARDLINK 00 # regular file with more than one link 94 | FIFO 48;5;230;38;5;136;01 # pipe 95 | SOCK 48;5;230;38;5;136;01 # socket 96 | DOOR 48;5;230;38;5;136;01 # door 97 | BLK 48;5;230;38;5;244;01 # block device driver 98 | CHR 48;5;230;38;5;244;01 # character device driver 99 | ORPHAN 48;5;235;38;5;160 # symlink to nonexistent file, or non-stat'able file 100 | SETUID 48;5;160;38;5;230 # file that is setuid (u+s) 101 | SETGID 48;5;136;38;5;230 # file that is setgid (g+s) 102 | CAPABILITY 30;41 # file with capability 103 | STICKY_OTHER_WRITABLE 48;5;64;38;5;230 # dir that is sticky and other-writable (+t,o+w) 104 | OTHER_WRITABLE 48;5;235;38;5;33 # dir that is other-writable (o+w) and not sticky 105 | STICKY 48;5;33;38;5;230 # dir with the sticky bit set (+t) and not other-writable 106 | # This is for files with execute permission: 107 | EXEC 01;38;5;64 108 | 109 | ## Archives or compressed (violet + bold for compression) 110 | .tar 00;38;5;61 111 | .tgz 01;38;5;61 112 | .arj 01;38;5;61 113 | .taz 01;38;5;61 114 | .lzh 01;38;5;61 115 | .lzma 01;38;5;61 116 | .tlz 01;38;5;61 117 | .txz 01;38;5;61 118 | .zip 01;38;5;61 119 | .z 01;38;5;61 120 | .Z 01;38;5;61 121 | .dz 01;38;5;61 122 | .gz 01;38;5;61 123 | .lz 01;38;5;61 124 | .xz 01;38;5;61 125 | .bz2 01;38;5;61 126 | .bz 01;38;5;61 127 | .tbz 01;38;5;61 128 | .tbz2 01;38;5;61 129 | .tz 01;38;5;61 130 | .deb 01;38;5;61 131 | .rpm 01;38;5;61 132 | .jar 01;38;5;61 133 | .rar 01;38;5;61 134 | .ace 01;38;5;61 135 | .zoo 01;38;5;61 136 | .cpio 01;38;5;61 137 | .7z 01;38;5;61 138 | .rz 01;38;5;61 139 | .apk 01;38;5;61 140 | .gem 01;38;5;61 141 | 142 | # Image formats (yellow) 143 | .jpg 00;38;5;136 144 | .JPG 00;38;5;136 #stupid but needed 145 | .jpeg 00;38;5;136 146 | .gif 00;38;5;136 147 | .bmp 00;38;5;136 148 | .pbm 00;38;5;136 149 | .pgm 00;38;5;136 150 | .ppm 00;38;5;136 151 | .tga 00;38;5;136 152 | .xbm 00;38;5;136 153 | .xpm 00;38;5;136 154 | .tif 00;38;5;136 155 | .tiff 00;38;5;136 156 | .png 00;38;5;136 157 | .svg 00;38;5;136 158 | .svgz 00;38;5;136 159 | .mng 00;38;5;136 160 | .pcx 00;38;5;136 161 | .dl 00;38;5;136 162 | .xcf 00;38;5;136 163 | .xwd 00;38;5;136 164 | .yuv 00;38;5;136 165 | .cgm 00;38;5;136 166 | .emf 00;38;5;136 167 | .eps 00;38;5;136 168 | .CR2 00;38;5;136 169 | .ico 00;38;5;136 170 | 171 | # Files of special interest (base1 + bold) 172 | .tex 01;38;5;245 173 | .rdf 01;38;5;245 174 | .owl 01;38;5;245 175 | .n3 01;38;5;245 176 | .ttl 01;38;5;245 177 | .nt 01;38;5;245 178 | .torrent 01;38;5;245 179 | .xml 01;38;5;245 180 | *Makefile 01;38;5;245 181 | *Rakefile 01;38;5;245 182 | *build.xml 01;38;5;245 183 | *rc 01;38;5;245 184 | *1 01;38;5;245 185 | .nfo 01;38;5;245 186 | *README 01;38;5;245 187 | *README.txt 01;38;5;245 188 | *readme.txt 01;38;5;245 189 | .md 01;38;5;245 190 | *README.markdown 01;38;5;245 191 | .ini 01;38;5;245 192 | .yml 01;38;5;245 193 | .cfg 01;38;5;245 194 | .conf 01;38;5;245 195 | .c 01;38;5;245 196 | .cpp 01;38;5;245 197 | .cc 01;38;5;245 198 | 199 | # "unimportant" files as logs and backups (base01) 200 | .log 00;38;5;240 201 | .bak 00;38;5;240 202 | .aux 00;38;5;240 203 | .bbl 00;38;5;240 204 | .blg 00;38;5;240 205 | *~ 00;38;5;240 206 | *# 00;38;5;240 207 | .part 00;38;5;240 208 | .incomplete 00;38;5;240 209 | .swp 00;38;5;240 210 | .tmp 00;38;5;240 211 | .temp 00;38;5;240 212 | .o 00;38;5;240 213 | .pyc 00;38;5;240 214 | .class 00;38;5;240 215 | .cache 00;38;5;240 216 | 217 | # Audio formats (orange) 218 | .aac 00;38;5;166 219 | .au 00;38;5;166 220 | .flac 00;38;5;166 221 | .mid 00;38;5;166 222 | .midi 00;38;5;166 223 | .mka 00;38;5;166 224 | .mp3 00;38;5;166 225 | .mpc 00;38;5;166 226 | .ogg 00;38;5;166 227 | .ra 00;38;5;166 228 | .wav 00;38;5;166 229 | .m4a 00;38;5;166 230 | # http://wiki.xiph.org/index.php/MIME_Types_and_File_Extensions 231 | .axa 00;38;5;166 232 | .oga 00;38;5;166 233 | .spx 00;38;5;166 234 | .xspf 00;38;5;166 235 | 236 | # Video formats (as audio + bold) 237 | .mov 01;38;5;166 238 | .mpg 01;38;5;166 239 | .mpeg 01;38;5;166 240 | .m2v 01;38;5;166 241 | .mkv 01;38;5;166 242 | .ogm 01;38;5;166 243 | .mp4 01;38;5;166 244 | .m4v 01;38;5;166 245 | .mp4v 01;38;5;166 246 | .vob 01;38;5;166 247 | .qt 01;38;5;166 248 | .nuv 01;38;5;166 249 | .wmv 01;38;5;166 250 | .asf 01;38;5;166 251 | .rm 01;38;5;166 252 | .rmvb 01;38;5;166 253 | .flc 01;38;5;166 254 | .avi 01;38;5;166 255 | .fli 01;38;5;166 256 | .flv 01;38;5;166 257 | .gl 01;38;5;166 258 | .m2ts 01;38;5;166 259 | .divx 01;38;5;166 260 | .webm 01;38;5;166 261 | # http://wiki.xiph.org/index.php/MIME_Types_and_File_Extensions 262 | .axv 01;38;5;166 263 | .anx 01;38;5;166 264 | .ogv 01;38;5;166 265 | .ogx 01;38;5;166 266 | 267 | 268 | -------------------------------------------------------------------------------- /dwm/config.h: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | /* appearance */ 5 | static const unsigned int borderpx = 1; /* border pixel of windows */ 6 | static const unsigned int snap = 32; /* snap pixel */ 7 | static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */ 8 | static const unsigned int systrayspacing = 2; /* systray spacing */ 9 | static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/ 10 | static const int showsystray = 1; /* 0 means no systray */ 11 | static const int showbar = 1; /* 0 means no bar */ 12 | static const int topbar = 1; /* 0 means bottom bar */ 13 | static const char *fonts[] = { "terminus:size=12" }; 14 | static const char dmenufont[] = "terminus:size=12"; 15 | 16 | static const char normfgcolor[] = "#839496"; 17 | static const char normbgcolor[] = "#002b36"; 18 | static const char normbordercolor[] = "#073642"; 19 | 20 | static const char selfgcolor[] = "#839496"; 21 | static const char selbgcolor[] = "#073642"; 22 | static const char selbordercolor[] = "#586e75"; 23 | 24 | static const char *colors[][3] = { 25 | /* fg bg border */ 26 | [SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor }, 27 | [SchemeSel] = { selfgcolor, selbgcolor, selbordercolor }, 28 | }; 29 | 30 | /* tagging */ 31 | static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; 32 | 33 | static const Rule rules[] = { 34 | /* xprop(1): 35 | * WM_CLASS(STRING) = instance, class 36 | * WM_NAME(STRING) = title 37 | */ 38 | /* class instance title tags mask isfloating monitor */ 39 | { "Google-chrome-stable", NULL, NULL, 1 << 1, 0, -1 }, 40 | { "Skype", NULL, NULL, 1 << 5, 0, -1 }, 41 | { "Telegram", NULL, NULL, 1 << 5, 0, -1 }, 42 | }; 43 | 44 | /* layout(s) */ 45 | static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ 46 | static const int nmaster = 2; /* number of clients in master area */ 47 | static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ 48 | 49 | static const Layout layouts[] = { 50 | /* symbol arrange function */ 51 | { "[]=", tile }, /* first entry is default */ 52 | { "><>", NULL }, /* no layout function means floating behavior */ 53 | { "[M]", monocle }, 54 | }; 55 | 56 | /* key definitions */ 57 | #define MODKEY Mod4Mask 58 | #define TAGKEYS(KEY,TAG) \ 59 | { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ 60 | { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ 61 | { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ 62 | { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, 63 | 64 | /* helper for spawning shell commands in the pre dwm-5.0 fashion */ 65 | #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } 66 | 67 | /* commands */ 68 | static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ 69 | static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL }; 70 | static const char *termcmd[] = { "st", "-e", "tmux", NULL }; 71 | /* Sound keys */ 72 | static const char *upvol[] = { "amixer", "-q", "sset", "Master", "3%+", NULL }; 73 | static const char *downvol[] = { "amixer", "-q", "sset", "Master", "3%-", NULL }; 74 | static const char *mute[] = { "amixer", "-q", "sset", "Master", "toggle", NULL }; 75 | static const char *micmute[] = { "amixer", "-q", "sset", "Capture", "toggle", NULL }; 76 | 77 | static Key keys[] = { 78 | /* modifier key function argument */ 79 | { MODKEY, XK_p, spawn, {.v = dmenucmd } }, 80 | { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, 81 | { MODKEY, XK_b, togglebar, {0} }, 82 | { MODKEY, XK_j, focusstack, {.i = +1 } }, 83 | { MODKEY, XK_k, focusstack, {.i = -1 } }, 84 | { MODKEY, XK_i, incnmaster, {.i = +1 } }, 85 | { MODKEY, XK_d, incnmaster, {.i = -1 } }, 86 | { MODKEY, XK_h, setmfact, {.f = -0.05} }, 87 | { MODKEY, XK_l, setmfact, {.f = +0.05} }, 88 | { MODKEY, XK_Return, zoom, {0} }, 89 | { MODKEY, XK_Tab, view, {0} }, 90 | { MODKEY|ShiftMask, XK_c, killclient, {0} }, 91 | { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, 92 | { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, 93 | { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, 94 | { MODKEY, XK_space, setlayout, {0} }, 95 | { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, 96 | { MODKEY, XK_0, view, {.ui = ~0 } }, 97 | { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, 98 | { MODKEY, XK_comma, focusmon, {.i = -1 } }, 99 | { MODKEY, XK_period, focusmon, {.i = +1 } }, 100 | { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, 101 | { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, 102 | TAGKEYS( XK_1, 0) 103 | TAGKEYS( XK_2, 1) 104 | TAGKEYS( XK_3, 2) 105 | TAGKEYS( XK_4, 3) 106 | TAGKEYS( XK_5, 4) 107 | TAGKEYS( XK_6, 5) 108 | TAGKEYS( XK_7, 6) 109 | TAGKEYS( XK_8, 7) 110 | TAGKEYS( XK_9, 8) 111 | { MODKEY|ShiftMask, XK_q, quit, {0} }, 112 | { 0, XF86XK_AudioRaiseVolume, spawn, {.v = upvol } }, 113 | { 0, XF86XK_AudioLowerVolume, spawn, {.v = downvol } }, 114 | { 0, XF86XK_AudioMute, spawn, {.v = mute } }, 115 | { 0, XF86XK_AudioMicMute, spawn, {.v = micmute } }, 116 | }; 117 | 118 | /* button definitions */ 119 | /* click can be ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ 120 | static Button buttons[] = { 121 | /* click event mask button function argument */ 122 | { ClkLtSymbol, 0, Button1, setlayout, {0} }, 123 | { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, 124 | { ClkWinTitle, 0, Button2, zoom, {0} }, 125 | { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, 126 | { ClkClientWin, MODKEY, Button1, movemouse, {0} }, 127 | { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, 128 | { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, 129 | { ClkTagBar, 0, Button1, view, {0} }, 130 | { ClkTagBar, 0, Button3, toggleview, {0} }, 131 | { ClkTagBar, MODKEY, Button1, tag, {0} }, 132 | { ClkTagBar, MODKEY, Button3, toggletag, {0} }, 133 | }; 134 | 135 | -------------------------------------------------------------------------------- /irssi/solarized-universal.theme: -------------------------------------------------------------------------------- 1 | # irssi theme for the Solarized color palette 2 | # (Adapted from default theme distributed with irssi 0.8.15 circa 2011-04-25) 3 | # 4 | # Adaptation by: Huy Z 5 | # Source: https://github.com/huyz/irssi-colors-solarized 6 | # 7 | 8 | # When testing changes, the easiest way to reload the theme is with /RELOAD. 9 | # This reloads the configuration file too, so if you did any changes remember 10 | # to /SAVE it first. Remember also that /SAVE overwrites the theme file with 11 | # old data so keep backups :) 12 | 13 | # TEMPLATES: 14 | 15 | # The real text formats that irssi uses are the ones you can find with 16 | # /FORMAT command. Back in the old days all the colors and texts were mixed 17 | # up in those formats, and it was really hard to change the colors since you 18 | # might have had to change them in tens of different places. So, then came 19 | # this templating system. 20 | 21 | # Now the /FORMATs don't have any colors in them, and they also have very 22 | # little other styling. Most of the stuff you need to change is in this 23 | # theme file. If you can't change something here, you can always go back 24 | # to change the /FORMATs directly, they're also saved in these .theme files. 25 | 26 | # So .. the templates. They're those {blahblah} parts you see all over the 27 | # /FORMATs and here. Their usage is simply {name parameter1 parameter2}. 28 | # When irssi sees this kind of text, it goes to find "name" from abstracts 29 | # block below and sets "parameter1" into $0 and "parameter2" into $1 (you 30 | # can have more parameters of course). Templates can have subtemplates. 31 | # Here's a small example: 32 | # /FORMAT format hello {colorify {underline world}} 33 | # abstracts = { colorify = "%G$0-%n"; underline = "%U$0-%U"; } 34 | # When irssi expands the templates in "format", the final string would be: 35 | # hello %G%Uworld%U%n 36 | # ie. underlined bright green "world" text. 37 | # and why "$0-", why not "$0"? $0 would only mean the first parameter, 38 | # $0- means all the parameters. With {underline hello world} you'd really 39 | # want to underline both of the words, not just the hello (and world would 40 | # actually be removed entirely). 41 | 42 | # COLORS: 43 | 44 | # You can find definitions for the color format codes in docs/formats.txt. 45 | 46 | # There's one difference here though. %n format. Normally it means the 47 | # default color of the terminal (white mostly), but here it means the 48 | # "reset color back to the one it was in higher template". For example 49 | # if there was /FORMAT test %g{foo}bar, and foo = "%Y$0%n", irssi would 50 | # print yellow "foo" (as set with %Y) but "bar" would be green, which was 51 | # set at the beginning before the {foo} template. If there wasn't the %g 52 | # at start, the normal behaviour of %n would occur. If you _really_ want 53 | # to use the terminal's default color, use %N. 54 | 55 | ############################################################################# 56 | 57 | # default foreground color (%N) - -1 is the "default terminal color" 58 | default_color = "-1"; 59 | 60 | # print timestamp/servertag at the end of line, not at beginning 61 | info_eol = "false"; 62 | 63 | # these characters are automatically replaced with specified color 64 | # (dark grey by default) 65 | replaces = { "[]=" = "%_$*%_"; }; 66 | 67 | abstracts = { 68 | ## 69 | ## generic 70 | ## 71 | 72 | # text to insert at the beginning of each non-message line 73 | # %G = brightgreen (Solarized: base01, i.e. darkest gray) 74 | # %| probably right-aligns 75 | line_start = " %G-!- "; 76 | 77 | # timestamp styling, nothing by default 78 | # %Y = brightyellow (Solarized: base00, i.e. 2nd darkest gray) 79 | timestamp = "%Y$*%n"; 80 | 81 | # any kind of text that needs hilighting, default is to bold 82 | hilight = "%_$*%_"; 83 | 84 | # any kind of error message, default is bright red 85 | # %r = red 86 | error = "%r$*%n"; 87 | 88 | # channel name is printed 89 | channel = "%_$*%_"; 90 | 91 | # nick is printed 92 | nick = "%_$*%_"; 93 | 94 | # nick host is printed 95 | # (that's the "email" address of a user) 96 | nickhost = "<$*>"; 97 | 98 | # server name is printed 99 | server = "%_$*%_"; 100 | 101 | # some kind of comment is printed 102 | comment = "($*)"; 103 | 104 | # reason for something is printed (part, quit, kick, ..) 105 | reason = "{comment $*}"; 106 | 107 | # mode change is printed ([+o nick]) 108 | mode = "{comment $*}"; 109 | 110 | ## 111 | ## channel specific messages 112 | ## 113 | 114 | # highlighted nick/host is printed (joins) 115 | # %c = cyan 116 | # NOTE: %n doesn't work in irssi v0.8.15 for some reason. So we have to end with the same color as line_start 117 | #channick_hilight = "%C$*%n"; 118 | channick_hilight = "%c$*%G"; 119 | chanhost_hilight = "{nickhost $*}"; 120 | 121 | # nick/host is printed (parts, quits, etc.) 122 | #channick = "%c$*%n"; 123 | channick = "$*"; 124 | chanhost = "{nickhost $*}"; 125 | 126 | # highlighted channel name is printed 127 | channelhilight = "%c$*%n"; 128 | 129 | # ban/ban exception/invite list mask is printed 130 | # %R = brightred (Solarized: orange) 131 | ban = "%R$*%n"; 132 | 133 | ## 134 | ## messages 135 | ## 136 | 137 | # the basic styling of how to print message, $0 = nick mode, $1 = nick 138 | msgnick = "%_<%_$0$1-%_>%_ %|"; 139 | 140 | # message from you is printed. "msgownnick" specifies the styling of the 141 | # nick ($0 part in msgnick) and "ownmsgnick" specifies the styling of the 142 | # whole line. 143 | 144 | # Example1: You want the message text to be green: 145 | # ownmsgnick = "{msgnick $0 $1-}%g"; 146 | # Example2.1: You want < and > chars to be yellow: 147 | # ownmsgnick = "%Y{msgnick $0 $1-%Y}%n"; 148 | # (you'll also have to remove <> from replaces list above) 149 | # Example2.2: But you still want to keep <> grey for other messages: 150 | # pubmsgnick = "%K{msgnick $0 $1-%K}%n"; 151 | # pubmsgmenick = "%K{msgnick $0 $1-%K}%n"; 152 | # pubmsghinick = "%K{msgnick $1 $0$2-%n%K}%n"; 153 | # ownprivmsgnick = "%K{msgnick $*%K}%n"; 154 | # privmsgnick = "%K{msgnick %R$*%K}%n"; 155 | 156 | # $0 = nick mode, $1 = nick 157 | ownmsgnick = "{msgnick $0 $1-}%b"; 158 | ownnick = "%b$*%n"; 159 | 160 | # public message in channel, $0 = nick mode, $1 = nick 161 | pubmsgnick = "{msgnick $0 $1-}"; 162 | pubnick = "%N%_$*%_%n"; 163 | 164 | # public message in channel meant for me, $0 = nick mode, $1 = nick 165 | pubmsgmenick = "{msgnick $0 $1-}"; 166 | # %m = magenta 167 | menick = "%m$*%n"; 168 | 169 | # public highlighted message in channel 170 | # $0 = highlight color, $1 = nick mode, $2 = nick 171 | pubmsghinick = "{msgnick $1 $0$2-%n}"; 172 | 173 | # channel name is printed with message 174 | # This is printed whenever the channel name is printed for disambiguation, e.g. 175 | # while there is a query in the same window. Example: <+funnyuser:#test> hello 176 | msgchannel = "%G:%c$*%n"; 177 | 178 | # private message, $0 = nick, $1 = host 179 | # TODO: To test for Solarized 180 | #privmsg = "[%m$0%K<%M$1-%K>%n] "; 181 | privmsg = "[%m$0%G<%n$1-%G>%n] "; 182 | 183 | # private message from you, $0 = "msg", $1 = target nick 184 | # TODO: To test for Solarized 185 | #ownprivmsg = "[%b$0%K<%B$1-%K>%n] "; 186 | ownprivmsg = "[%b$0%G<%B$1-%G>%n] "; 187 | 188 | # own private message in query 189 | ownprivmsgnick = "{msgnick $*}%b"; 190 | ownprivnick = "%b$*%n"; 191 | 192 | # private message in query 193 | # NOTE: for some reason, we gotta handle both the nick & msg on in this line 194 | privmsgnick = "{msgnick %m$*%n}%m"; 195 | 196 | ## 197 | ## Actions (/ME stuff) 198 | ## 199 | 200 | # used internally by this theme 201 | action_core = "%_*%n $*"; 202 | 203 | # generic one that's used by most actions 204 | action = "{action_core %_$*%n} "; 205 | 206 | # own action, both private/public 207 | ownaction = "{action_core %b$*%n} "; 208 | 209 | # own action with target, both private/public 210 | # NOTE: to test: /action NICK farted. (This will tell NICK that you farted) 211 | # This is like a /me but only you and NICK will see 212 | # TODO: To test for Solarized 213 | ownaction_target = "{action_core $0}%G:%b$1%n "; 214 | 215 | # private action sent by others 216 | # TODO: To test for Solarized 217 | # %M = brightmagenta (Solarized: violet) 218 | pvtaction = "%M (*) $*%n "; 219 | pvtaction_query = "{action $*}"; 220 | 221 | # public action sent by others 222 | pubaction = "{action $*}"; 223 | 224 | 225 | ## 226 | ## other IRC events 227 | ## 228 | 229 | # whois 230 | whois = "%# $[8]0 : $1-"; 231 | 232 | # notices 233 | # TODO: To adapt for Solarized 234 | ownnotice = "[%b$0%G(%b$1-%G)]%n "; 235 | notice = "%G-%M$*%G-%n "; 236 | pubnotice_channel = "%G:%m$*"; 237 | pvtnotice_host = "%G(%m$*%G)"; 238 | servernotice = "%g!$*%n "; 239 | 240 | # CTCPs 241 | # TODO: To adapt for Solarized 242 | ownctcp = "[%b$0%G(%b$1-%G)] "; 243 | ctcp = "%g$*%n"; 244 | 245 | # wallops 246 | wallop = "%c$*%n: "; 247 | wallop_nick = "%n$*"; 248 | wallop_action = "%c * $*%n "; 249 | 250 | # netsplits 251 | netsplit = "%r$*%n"; 252 | netjoin = "%g$*%n"; 253 | 254 | # /names list 255 | names_prefix = ""; 256 | names_nick = "[%_$0%_$1-] "; 257 | names_nick_op = "{names_nick $*}"; 258 | names_nick_halfop = "{names_nick $*}"; 259 | names_nick_voice = "{names_nick $*}"; 260 | names_users = "[%g$*%n]"; 261 | names_channel = "%c$*%n"; 262 | 263 | # DCC 264 | dcc = "%g$*%n"; 265 | dccfile = "%_$*%_"; 266 | 267 | # DCC chat, own msg/action 268 | #dccownmsg = "[%r$0%K($1-%K)%n] "; 269 | dccownmsg = "[%b$0%G($1-%G)%n] "; 270 | dccownnick = "%b$*%n"; 271 | dccownquerynick = "%c$*%n"; 272 | dccownaction = "{action $*}"; 273 | dccownaction_target = "{action_core $0}%G:%c$1%n "; 274 | 275 | # DCC chat, others 276 | #dccmsg = "[%G$1-%K(%g$0%K)%n] "; 277 | dccmsg = "[%g$1-%G($0%G)%n] "; 278 | dccquerynick = "%g$*%n"; 279 | dccaction = "%c (*dcc*) $*%n %|"; 280 | 281 | ## 282 | ## statusbar 283 | ## 284 | 285 | # default background for all statusbars. You can also give 286 | # the default foreground color for statusbar items. 287 | # NOTE: if all the other overriding settings below are set, this only seems to affect 288 | # the content parts of the adv_windowlist. Default seems to be blue 289 | # NOTE: if not set, the default background seems to be %w%4 = white on blue 290 | # %4 = blue 291 | sb_background = "%k%6"; 292 | 293 | # default backround for "default" statusbar group 294 | # NOTE: this impacts the statusbar of an inactive window and the edges of adv_windowlist 295 | # %7 = white (wich looks gray on a regular terminal with white bg) 296 | #sb_default_bg = "%k%7"; 297 | 298 | # background for topicbar at the top (defaults to sb_default_bg) 299 | #sb_topic_bg = "%W%4"; 300 | 301 | # background for the statusbar of active window. You can also give 302 | # the foreground color. 303 | # %2 = green 304 | #sb_window_bg = "%2"; 305 | 306 | # background for prompt / input line 307 | sb_prompt_bg = "%n"; 308 | # background for info statusbar 309 | # %8 = reverse window 310 | # TODO: To test for Solarized 311 | sb_info_bg = "%8"; 312 | 313 | # text at the beginning of statusbars. sb-item already puts 314 | # space there,so we don't use anything by default. 315 | sbstart = ""; 316 | # text at the end of statusbars. Use space so that it's never 317 | # used for anything. 318 | sbend = " "; 319 | 320 | topicsbstart = "{sbstart $*}"; 321 | topicsbend = "{sbend $*}"; 322 | 323 | prompt = "$c$*%n> "; 324 | 325 | # This controls each part of a statusbor, including the outer brackets of adv_windowlist 326 | sb = " $* %M|%n"; 327 | # The mode is next to your NICK and the channel 328 | # %Y = brightyellow (Solarized: base00, i.e. 2nd darkest gray) 329 | sbmode = "%b(%n+$*%b)%n"; 330 | sbaway = " (%GzZzZ%n)"; 331 | # %Y = brightyellow (Solarized: base00, i.e. 2nd darkest gray) 332 | sbservertag = ":$0 %b(change with ^X)%n"; 333 | sbnickmode = "$0"; 334 | 335 | # activity in statusbar 336 | 337 | # ',' separator between the window numbers 338 | # %g = green (same color as the active statusbar so we dont' see it) 339 | sb_act_sep = "%g$*"; 340 | # normal text 341 | # This also affects the color of the window with activity in adv_windowlist 342 | sb_act_text = "%w$*"; 343 | # public message (ordinary messages) 344 | sb_act_msg = "%R$*"; 345 | # hilight (when people actually chat) 346 | # This also affects the color of the window with direct message in adv_windowlist 347 | sb_act_hilight = "%m$*"; 348 | # hilight with specified color, $0 = color, $1 = text 349 | sb_act_hilight_color = "$0$1-%n"; 350 | 351 | ### For usercount.pl script 352 | 353 | #sb_usercount = "{sb %_$0%_ nicks ($1-)}"; 354 | sb_usercount = "{sb %_$0%_ users %Y(%n$1-%Y)%n}"; 355 | sb_uc_ircops = "%k*%n$*"; 356 | sb_uc_ops = "%k@%n$*"; 357 | sb_uc_halfops = "%k%%%n$*"; 358 | sb_uc_voices = "%k+%n$*"; 359 | sb_uc_normal = "$*"; 360 | # sb_uc_space = " "; 361 | 362 | ### For adv_windowlist.pl script 363 | 364 | # Mentioned in adv_windowlist but not default_theme 365 | #sb_act_none = "%0%W"; 366 | }; 367 | 368 | formats = { 369 | "fe-common/core" = { 370 | daychange = " %g-----%w-%W-%n Day changed to %%D %W-%w-%g-----%n"; 371 | }; 372 | }; 373 | -------------------------------------------------------------------------------- /st/config.h: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | 3 | /* 4 | * appearance 5 | * 6 | * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html 7 | */ 8 | static char *font = "xos4 Terminus:pixelsize=32:antialias=true:autohint=true"; 9 | static int borderpx = 2; 10 | 11 | /* 12 | * What program is execed by st depends of these precedence rules: 13 | * 1: program passed with -e 14 | * 2: utmp option 15 | * 3: SHELL environment variable 16 | * 4: value of shell in /etc/passwd 17 | * 5: value of shell in config.h 18 | */ 19 | static char *shell = "/bin/sh"; 20 | char *utmp = NULL; 21 | char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; 22 | 23 | /* identification sequence returned in DA and DECID */ 24 | char *vtiden = "\033[?6c"; 25 | 26 | /* Kerning / character bounding-box multipliers */ 27 | static float cwscale = 1.0; 28 | static float chscale = 1.0; 29 | 30 | /* 31 | * word delimiter string 32 | * 33 | * More advanced example: " `'\"()[]{}" 34 | */ 35 | char *worddelimiters = " "; 36 | 37 | /* selection timeouts (in milliseconds) */ 38 | static unsigned int doubleclicktimeout = 300; 39 | static unsigned int tripleclicktimeout = 600; 40 | 41 | /* alt screens */ 42 | int allowaltscreen = 1; 43 | 44 | /* frames per second st should at maximum draw to the screen */ 45 | static unsigned int xfps = 120; 46 | static unsigned int actionfps = 30; 47 | 48 | /* 49 | * blinking timeout (set to 0 to disable blinking) for the terminal blinking 50 | * attribute. 51 | */ 52 | static unsigned int blinktimeout = 800; 53 | 54 | /* 55 | * thickness of underline and bar cursors 56 | */ 57 | static unsigned int cursorthickness = 2; 58 | 59 | /* 60 | * bell volume. It must be a value between -100 and 100. Use 0 for disabling 61 | * it 62 | */ 63 | static int bellvolume = 0; 64 | 65 | /* default TERM value */ 66 | char *termname = "screen-it"; 67 | 68 | /* 69 | * spaces per tab 70 | * 71 | * When you are changing this value, don't forget to adapt the »it« value in 72 | * the st.info and appropriately install the st.info in the environment where 73 | * you use this st version. 74 | * 75 | * it#$tabspaces, 76 | * 77 | * Secondly make sure your kernel is not expanding tabs. When running `stty 78 | * -a` »tab0« should appear. You can tell the terminal to not expand tabs by 79 | * running following command: 80 | * 81 | * stty tabs 82 | */ 83 | unsigned int tabspaces = 8; 84 | 85 | /* Terminal colors (16 first used in escape sequence) */ 86 | static const char *colorname[] = { 87 | /* 8 normal colors */ 88 | "#073642", /* 0: black */ 89 | "#dc322f", /* 1: red */ 90 | "#859900", /* 2: green */ 91 | "#b58900", /* 3: yellow */ 92 | "#268bd2", /* 4: blue */ 93 | "#d33682", /* 5: magenta */ 94 | "#2aa198", /* 6: cyan */ 95 | "#eee8d5", /* 7: white */ 96 | 97 | "#002b36", /* 8: brblack */ 98 | "#cb4b16", /* 9: brred */ 99 | "#586e75", /* 10: brgreen */ 100 | "#657b83", /* 11: bryellow */ 101 | "#839496", /* 12: brblue */ 102 | "#6c71c4", /* 13: brmagenta */ 103 | "#93a1a1", /* 14: brcyan */ 104 | "#fdf6e3", /* 15: brwhite */ 105 | 106 | }; 107 | 108 | 109 | /* 110 | * Default colors (colorname index) 111 | * foreground, background, cursor, reverse cursor 112 | */ 113 | unsigned int defaultfg = 12; 114 | unsigned int defaultbg = 8; 115 | static unsigned int defaultcs = 14; 116 | static unsigned int defaultrcs = 257; 117 | 118 | /* 119 | * Default shape of cursor 120 | * 2: Block ("█") 121 | * 4: Underline ("_") 122 | * 6: Bar ("|") 123 | * 7: Snowman ("☃") 124 | */ 125 | static unsigned int cursorshape = 2; 126 | 127 | /* 128 | * Default columns and rows numbers 129 | */ 130 | 131 | static unsigned int cols = 80; 132 | static unsigned int rows = 24; 133 | 134 | /* 135 | * Default colour and shape of the mouse cursor 136 | */ 137 | static unsigned int mouseshape = XC_xterm; 138 | static unsigned int mousefg = 7; 139 | static unsigned int mousebg = 0; 140 | 141 | /* 142 | * Color used to display font attributes when fontconfig selected a font which 143 | * doesn't match the ones requested. 144 | */ 145 | static unsigned int defaultattr = 11; 146 | 147 | /* 148 | * Internal mouse shortcuts. 149 | * Beware that overloading Button1 will disable the selection. 150 | */ 151 | static MouseShortcut mshortcuts[] = { 152 | /* button mask string */ 153 | { Button4, XK_ANY_MOD, "\031" }, 154 | { Button5, XK_ANY_MOD, "\005" }, 155 | }; 156 | 157 | /* Internal keyboard shortcuts. */ 158 | #define MODKEY Mod4Mask 159 | #define TERMMOD (ControlMask|ShiftMask) 160 | 161 | static char *openurlcmd[] = { "/bin/sh", "-c", 162 | "xurls | dmenu -l 10 -w $WINDOWID | xargs -r xdg-open", 163 | "externalpipe", NULL }; 164 | 165 | static Shortcut shortcuts[] = { 166 | /* mask keysym function argument */ 167 | { XK_ANY_MOD, XK_Break, sendbreak, {.i = 0} }, 168 | { ControlMask, XK_Print, toggleprinter, {.i = 0} }, 169 | { ShiftMask, XK_Print, printscreen, {.i = 0} }, 170 | { XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, 171 | { TERMMOD, XK_Prior, zoom, {.f = +1} }, 172 | { TERMMOD, XK_Next, zoom, {.f = -1} }, 173 | { TERMMOD, XK_Home, zoomreset, {.f = 0} }, 174 | { TERMMOD, XK_C, clipcopy, {.i = 0} }, 175 | { TERMMOD, XK_V, clippaste, {.i = 0} }, 176 | { TERMMOD, XK_Y, selpaste, {.i = 0} }, 177 | { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, 178 | { TERMMOD, XK_I, iso14755, {.i = 0} }, 179 | { TERMMOD, XK_U, externalpipe, {.v = openurlcmd } }, 180 | }; 181 | 182 | /* 183 | * Special keys (change & recompile st.info accordingly) 184 | * 185 | * Mask value: 186 | * * Use XK_ANY_MOD to match the key no matter modifiers state 187 | * * Use XK_NO_MOD to match the key alone (no modifiers) 188 | * appkey value: 189 | * * 0: no value 190 | * * > 0: keypad application mode enabled 191 | * * = 2: term.numlock = 1 192 | * * < 0: keypad application mode disabled 193 | * appcursor value: 194 | * * 0: no value 195 | * * > 0: cursor application mode enabled 196 | * * < 0: cursor application mode disabled 197 | * crlf value 198 | * * 0: no value 199 | * * > 0: crlf mode is enabled 200 | * * < 0: crlf mode is disabled 201 | * 202 | * Be careful with the order of the definitions because st searches in 203 | * this table sequentially, so any XK_ANY_MOD must be in the last 204 | * position for a key. 205 | */ 206 | 207 | /* 208 | * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) 209 | * to be mapped below, add them to this array. 210 | */ 211 | static KeySym mappedkeys[] = { -1 }; 212 | 213 | /* 214 | * State bits to ignore when matching key or button events. By default, 215 | * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. 216 | */ 217 | static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; 218 | 219 | /* 220 | * Override mouse-select while mask is active (when MODE_MOUSE is set). 221 | * Note that if you want to use ShiftMask with selmasks, set this to an other 222 | * modifier, set to 0 to not use it. 223 | */ 224 | static uint forceselmod = ShiftMask; 225 | 226 | /* 227 | * This is the huge key array which defines all compatibility to the Linux 228 | * world. Please decide about changes wisely. 229 | */ 230 | static Key key[] = { 231 | /* keysym mask string appkey appcursor */ 232 | { XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, 233 | { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, 234 | { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, 235 | { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, 236 | { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, 237 | { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, 238 | { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, 239 | { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, 240 | { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, 241 | { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, 242 | { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, 243 | { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, 244 | { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, 245 | { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, 246 | { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, 247 | { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, 248 | { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, 249 | { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, 250 | { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, 251 | { XK_KP_End, ControlMask, "\033[J", -1, 0}, 252 | { XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, 253 | { XK_KP_End, ShiftMask, "\033[K", -1, 0}, 254 | { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, 255 | { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, 256 | { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, 257 | { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, 258 | { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, 259 | { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, 260 | { XK_KP_Insert, ControlMask, "\033[L", -1, 0}, 261 | { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, 262 | { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, 263 | { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, 264 | { XK_KP_Delete, ControlMask, "\033[M", -1, 0}, 265 | { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, 266 | { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, 267 | { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, 268 | { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, 269 | { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, 270 | { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, 271 | { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, 272 | { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, 273 | { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, 274 | { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, 275 | { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, 276 | { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, 277 | { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, 278 | { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, 279 | { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, 280 | { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, 281 | { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, 282 | { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, 283 | { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, 284 | { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, 285 | { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, 286 | { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, 287 | { XK_Up, ShiftMask, "\033[1;2A", 0, 0}, 288 | { XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, 289 | { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0}, 290 | { XK_Up, ControlMask, "\033[1;5A", 0, 0}, 291 | { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0}, 292 | { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0}, 293 | { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0}, 294 | { XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, 295 | { XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, 296 | { XK_Down, ShiftMask, "\033[1;2B", 0, 0}, 297 | { XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, 298 | { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0}, 299 | { XK_Down, ControlMask, "\033[1;5B", 0, 0}, 300 | { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0}, 301 | { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0}, 302 | { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0}, 303 | { XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, 304 | { XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, 305 | { XK_Left, ShiftMask, "\033[1;2D", 0, 0}, 306 | { XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, 307 | { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0}, 308 | { XK_Left, ControlMask, "\033[1;5D", 0, 0}, 309 | { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0}, 310 | { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0}, 311 | { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0}, 312 | { XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, 313 | { XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, 314 | { XK_Right, ShiftMask, "\033[1;2C", 0, 0}, 315 | { XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, 316 | { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0}, 317 | { XK_Right, ControlMask, "\033[1;5C", 0, 0}, 318 | { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0}, 319 | { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0}, 320 | { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0}, 321 | { XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, 322 | { XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, 323 | { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, 324 | { XK_Return, Mod1Mask, "\033\r", 0, 0}, 325 | { XK_Return, XK_ANY_MOD, "\r", 0, 0}, 326 | { XK_Insert, ShiftMask, "\033[4l", -1, 0}, 327 | { XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, 328 | { XK_Insert, ControlMask, "\033[L", -1, 0}, 329 | { XK_Insert, ControlMask, "\033[2;5~", +1, 0}, 330 | { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, 331 | { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, 332 | { XK_Delete, ControlMask, "\033[M", -1, 0}, 333 | { XK_Delete, ControlMask, "\033[3;5~", +1, 0}, 334 | { XK_Delete, ShiftMask, "\033[2K", -1, 0}, 335 | { XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, 336 | { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, 337 | { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, 338 | { XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, 339 | { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, 340 | { XK_Home, ShiftMask, "\033[2J", 0, -1}, 341 | { XK_Home, ShiftMask, "\033[1;2H", 0, +1}, 342 | { XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, 343 | { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, 344 | { XK_End, ControlMask, "\033[J", -1, 0}, 345 | { XK_End, ControlMask, "\033[1;5F", +1, 0}, 346 | { XK_End, ShiftMask, "\033[K", -1, 0}, 347 | { XK_End, ShiftMask, "\033[1;2F", +1, 0}, 348 | { XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, 349 | { XK_Prior, ControlMask, "\033[5;5~", 0, 0}, 350 | { XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, 351 | { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, 352 | { XK_Next, ControlMask, "\033[6;5~", 0, 0}, 353 | { XK_Next, ShiftMask, "\033[6;2~", 0, 0}, 354 | { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, 355 | { XK_F1, XK_NO_MOD, "\033OP" , 0, 0}, 356 | { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, 357 | { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, 358 | { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, 359 | { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, 360 | { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, 361 | { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0}, 362 | { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, 363 | { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, 364 | { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, 365 | { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, 366 | { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, 367 | { XK_F3, XK_NO_MOD, "\033OR" , 0, 0}, 368 | { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, 369 | { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, 370 | { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, 371 | { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, 372 | { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, 373 | { XK_F4, XK_NO_MOD, "\033OS" , 0, 0}, 374 | { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, 375 | { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, 376 | { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, 377 | { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, 378 | { XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, 379 | { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, 380 | { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, 381 | { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, 382 | { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, 383 | { XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, 384 | { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, 385 | { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, 386 | { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, 387 | { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, 388 | { XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, 389 | { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, 390 | { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, 391 | { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, 392 | { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, 393 | { XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, 394 | { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, 395 | { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, 396 | { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, 397 | { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, 398 | { XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, 399 | { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, 400 | { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, 401 | { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, 402 | { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, 403 | { XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, 404 | { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, 405 | { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, 406 | { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, 407 | { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, 408 | { XK_F11, XK_NO_MOD, "\033[23~", 0, 0}, 409 | { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0}, 410 | { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0}, 411 | { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0}, 412 | { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0}, 413 | { XK_F12, XK_NO_MOD, "\033[24~", 0, 0}, 414 | { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0}, 415 | { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0}, 416 | { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0}, 417 | { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0}, 418 | { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0}, 419 | { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0}, 420 | { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0}, 421 | { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0}, 422 | { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0}, 423 | { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0}, 424 | { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0}, 425 | { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0}, 426 | { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0}, 427 | { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0}, 428 | { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0}, 429 | { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0}, 430 | { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0}, 431 | { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0}, 432 | { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0}, 433 | { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0}, 434 | { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0}, 435 | { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0}, 436 | { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0}, 437 | { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0}, 438 | { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0}, 439 | { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0}, 440 | { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0}, 441 | }; 442 | 443 | /* 444 | * Selection types' masks. 445 | * Use the same masks as usual. 446 | * Button1Mask is always unset, to make masks match between ButtonPress. 447 | * ButtonRelease and MotionNotify. 448 | * If no match is found, regular selection is used. 449 | */ 450 | static uint selmasks[] = { 451 | [SEL_RECTANGULAR] = Mod1Mask, 452 | }; 453 | 454 | /* 455 | * Printable characters in ASCII, used to estimate the advance width 456 | * of single wide characters. 457 | */ 458 | static char ascii_printable[] = 459 | " !\"#$%&'()*+,-./0123456789:;<=>?" 460 | "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" 461 | "`abcdefghijklmnopqrstuvwxyz{|}~"; 462 | 463 | -------------------------------------------------------------------------------- /dwm/dwm-systray.diff: -------------------------------------------------------------------------------- 1 | diff --git a/config.def.h b/config.def.h 2 | index ba9a240..fba8f78 100644 3 | --- a/config.def.h 4 | +++ b/config.def.h 5 | @@ -3,6 +3,10 @@ 6 | /* appearance */ 7 | static const unsigned int borderpx = 1; /* border pixel of windows */ 8 | static const unsigned int snap = 32; /* snap pixel */ 9 | +static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */ 10 | +static const unsigned int systrayspacing = 2; /* systray spacing */ 11 | +static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/ 12 | +static const int showsystray = 1; /* 0 means no systray */ 13 | static const int showbar = 1; /* 0 means no bar */ 14 | static const int topbar = 1; /* 0 means bottom bar */ 15 | static const char *fonts[] = { "monospace:size=10" }; 16 | diff --git a/dwm.c b/dwm.c 17 | index d27cb67..9d48d08 100644 18 | --- a/dwm.c 19 | +++ b/dwm.c 20 | @@ -58,12 +58,30 @@ 21 | #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) 22 | #define ColBorder 2 23 | 24 | +#define SYSTEM_TRAY_REQUEST_DOCK 0 25 | + 26 | +/* XEMBED messages */ 27 | +#define XEMBED_EMBEDDED_NOTIFY 0 28 | +#define XEMBED_WINDOW_ACTIVATE 1 29 | +#define XEMBED_FOCUS_IN 4 30 | +#define XEMBED_MODALITY_ON 10 31 | + 32 | +#define XEMBED_MAPPED (1 << 0) 33 | +#define XEMBED_WINDOW_ACTIVATE 1 34 | +#define XEMBED_WINDOW_DEACTIVATE 2 35 | + 36 | +#define VERSION_MAJOR 0 37 | +#define VERSION_MINOR 0 38 | +#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR 39 | + 40 | /* enums */ 41 | enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ 42 | enum { SchemeNorm, SchemeSel }; /* color schemes */ 43 | enum { NetSupported, NetWMName, NetWMState, NetWMCheck, 44 | + NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, NetSystemTrayOrientationHorz, 45 | NetWMFullscreen, NetActiveWindow, NetWMWindowType, 46 | NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ 47 | +enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */ 48 | enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ 49 | enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, 50 | ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ 51 | @@ -142,6 +160,12 @@ typedef struct { 52 | int monitor; 53 | } Rule; 54 | 55 | +typedef struct Systray Systray; 56 | +struct Systray { 57 | + Window win; 58 | + Client *icons; 59 | +}; 60 | + 61 | /* function declarations */ 62 | static void applyrules(Client *c); 63 | static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); 64 | @@ -170,8 +194,10 @@ static void focus(Client *c); 65 | static void focusin(XEvent *e); 66 | static void focusmon(const Arg *arg); 67 | static void focusstack(const Arg *arg); 68 | +static Atom getatomprop(Client *c, Atom prop); 69 | static int getrootptr(int *x, int *y); 70 | static long getstate(Window w); 71 | +static unsigned int getsystraywidth(); 72 | static int gettextprop(Window w, Atom atom, char *text, unsigned int size); 73 | static void grabbuttons(Client *c, int focused); 74 | static void grabkeys(void); 75 | @@ -189,13 +215,16 @@ static void pop(Client *); 76 | static void propertynotify(XEvent *e); 77 | static void quit(const Arg *arg); 78 | static Monitor *recttomon(int x, int y, int w, int h); 79 | +static void removesystrayicon(Client *i); 80 | static void resize(Client *c, int x, int y, int w, int h, int interact); 81 | +static void resizebarwin(Monitor *m); 82 | static void resizeclient(Client *c, int x, int y, int w, int h); 83 | static void resizemouse(const Arg *arg); 84 | +static void resizerequest(XEvent *e); 85 | static void restack(Monitor *m); 86 | static void run(void); 87 | static void scan(void); 88 | -static int sendevent(Client *c, Atom proto); 89 | +static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4); 90 | static void sendmon(Client *c, Monitor *m); 91 | static void setclientstate(Client *c, long state); 92 | static void setfocus(Client *c); 93 | @@ -207,6 +236,7 @@ static void seturgent(Client *c, int urg); 94 | static void showhide(Client *c); 95 | static void sigchld(int unused); 96 | static void spawn(const Arg *arg); 97 | +static Monitor *systraytomon(Monitor *m); 98 | static void tag(const Arg *arg); 99 | static void tagmon(const Arg *arg); 100 | static void tile(Monitor *); 101 | @@ -224,18 +254,23 @@ static void updateclientlist(void); 102 | static void updatenumlockmask(void); 103 | static void updatesizehints(Client *c); 104 | static void updatestatus(void); 105 | +static void updatesystray(void); 106 | +static void updatesystrayicongeom(Client *i, int w, int h); 107 | +static void updatesystrayiconstate(Client *i, XPropertyEvent *ev); 108 | static void updatewindowtype(Client *c); 109 | static void updatetitle(Client *c); 110 | static void updatewmhints(Client *c); 111 | static void view(const Arg *arg); 112 | static Client *wintoclient(Window w); 113 | static Monitor *wintomon(Window w); 114 | +static Client *wintosystrayicon(Window w); 115 | static int xerror(Display *dpy, XErrorEvent *ee); 116 | static int xerrordummy(Display *dpy, XErrorEvent *ee); 117 | static int xerrorstart(Display *dpy, XErrorEvent *ee); 118 | static void zoom(const Arg *arg); 119 | 120 | /* variables */ 121 | +static Systray *systray = NULL; 122 | static const char broken[] = "broken"; 123 | static char stext[256]; 124 | static int screen; 125 | @@ -258,9 +293,10 @@ static void (*handler[LASTEvent]) (XEvent *) = { 126 | [MapRequest] = maprequest, 127 | [MotionNotify] = motionnotify, 128 | [PropertyNotify] = propertynotify, 129 | + [ResizeRequest] = resizerequest, 130 | [UnmapNotify] = unmapnotify 131 | }; 132 | -static Atom wmatom[WMLast], netatom[NetLast]; 133 | +static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast]; 134 | static int running = 1; 135 | static Cur *cursor[CurLast]; 136 | static Scm *scheme; 137 | @@ -481,6 +517,11 @@ cleanup(void) 138 | XUngrabKey(dpy, AnyKey, AnyModifier, root); 139 | while (mons) 140 | cleanupmon(mons); 141 | + if (showsystray) { 142 | + XUnmapWindow(dpy, systray->win); 143 | + XDestroyWindow(dpy, systray->win); 144 | + free(systray); 145 | + } 146 | for (i = 0; i < CurLast; i++) 147 | drw_cur_free(drw, cursor[i]); 148 | for (i = 0; i < LENGTH(colors); i++) 149 | @@ -511,9 +552,52 @@ cleanupmon(Monitor *mon) 150 | void 151 | clientmessage(XEvent *e) 152 | { 153 | + XWindowAttributes wa; 154 | + XSetWindowAttributes swa; 155 | XClientMessageEvent *cme = &e->xclient; 156 | Client *c = wintoclient(cme->window); 157 | 158 | + if (showsystray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) { 159 | + /* add systray icons */ 160 | + if (cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) { 161 | + if (!(c = (Client *)calloc(1, sizeof(Client)))) 162 | + die("fatal: could not malloc() %u bytes\n", sizeof(Client)); 163 | + if (!(c->win = cme->data.l[2])) { 164 | + free(c); 165 | + return; 166 | + } 167 | + c->mon = selmon; 168 | + c->next = systray->icons; 169 | + systray->icons = c; 170 | + XGetWindowAttributes(dpy, c->win, &wa); 171 | + c->x = c->oldx = c->y = c->oldy = 0; 172 | + c->w = c->oldw = wa.width; 173 | + c->h = c->oldh = wa.height; 174 | + c->oldbw = wa.border_width; 175 | + c->bw = 0; 176 | + c->isfloating = True; 177 | + /* reuse tags field as mapped status */ 178 | + c->tags = 1; 179 | + updatesizehints(c); 180 | + updatesystrayicongeom(c, wa.width, wa.height); 181 | + XAddToSaveSet(dpy, c->win); 182 | + XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask); 183 | + XReparentWindow(dpy, c->win, systray->win, 0, 0); 184 | + /* use parents background color */ 185 | + swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; 186 | + XChangeWindowAttributes(dpy, c->win, CWBackPixel, &swa); 187 | + sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION); 188 | + /* FIXME not sure if I have to send these events, too */ 189 | + sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_FOCUS_IN, 0 , systray->win, XEMBED_EMBEDDED_VERSION); 190 | + sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0 , systray->win, XEMBED_EMBEDDED_VERSION); 191 | + sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_MODALITY_ON, 0 , systray->win, XEMBED_EMBEDDED_VERSION); 192 | + XSync(dpy, False); 193 | + resizebarwin(selmon); 194 | + updatesystray(); 195 | + setclientstate(c, NormalState); 196 | + } 197 | + return; 198 | + } 199 | if (!c) 200 | return; 201 | if (cme->message_type == netatom[NetWMState]) { 202 | @@ -565,7 +649,7 @@ configurenotify(XEvent *e) 203 | for (c = m->clients; c; c = c->next) 204 | if (c->isfullscreen) 205 | resizeclient(c, m->mx, m->my, m->mw, m->mh); 206 | - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); 207 | + resizebarwin(m); 208 | } 209 | focus(NULL); 210 | arrange(NULL); 211 | @@ -650,6 +734,11 @@ destroynotify(XEvent *e) 212 | 213 | if ((c = wintoclient(ev->window))) 214 | unmanage(c, 1); 215 | + else if ((c = wintosystrayicon(ev->window))) { 216 | + removesystrayicon(c); 217 | + resizebarwin(selmon); 218 | + updatesystray(); 219 | + } 220 | } 221 | 222 | void 223 | @@ -693,19 +782,23 @@ dirtomon(int dir) 224 | void 225 | drawbar(Monitor *m) 226 | { 227 | - int x, w, sw = 0; 228 | + int x, w, sw = 0, stw = 0; 229 | int boxs = drw->fonts->h / 9; 230 | int boxw = drw->fonts->h / 6 + 2; 231 | unsigned int i, occ = 0, urg = 0; 232 | Client *c; 233 | 234 | + if(showsystray && m == systraytomon(m)) 235 | + stw = getsystraywidth(); 236 | + 237 | /* draw status first so it can be overdrawn by tags later */ 238 | if (m == selmon) { /* status is only drawn on selected monitor */ 239 | drw_setscheme(drw, scheme[SchemeNorm]); 240 | - sw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ 241 | - drw_text(drw, m->ww - sw, 0, sw, bh, 0, stext, 0); 242 | + sw = TEXTW(stext) - lrpad / 2 + 2; /* 2px right padding */ 243 | + drw_text(drw, m->ww - sw - stw, 0, sw, bh, lrpad / 2 - 2, stext, 0); 244 | } 245 | 246 | + resizebarwin(m); 247 | for (c = m->clients; c; c = c->next) { 248 | occ |= c->tags; 249 | if (c->isurgent) 250 | @@ -726,7 +819,7 @@ drawbar(Monitor *m) 251 | drw_setscheme(drw, scheme[SchemeNorm]); 252 | x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); 253 | 254 | - if ((w = m->ww - sw - x) > bh) { 255 | + if ((w = m->ww - sw - stw - x) > bh) { 256 | if (m->sel) { 257 | drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); 258 | drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); 259 | @@ -737,7 +830,7 @@ drawbar(Monitor *m) 260 | drw_rect(drw, x, 0, w, bh, 1, 1); 261 | } 262 | } 263 | - drw_map(drw, m->barwin, 0, 0, m->ww, bh); 264 | + drw_map(drw, m->barwin, 0, 0, m->ww - stw, bh); 265 | } 266 | 267 | void 268 | @@ -774,8 +867,11 @@ expose(XEvent *e) 269 | Monitor *m; 270 | XExposeEvent *ev = &e->xexpose; 271 | 272 | - if (ev->count == 0 && (m = wintomon(ev->window))) 273 | + if (ev->count == 0 && (m = wintomon(ev->window))) { 274 | drawbar(m); 275 | + if (m == selmon) 276 | + updatesystray(); 277 | + } 278 | } 279 | 280 | void 281 | @@ -862,10 +958,17 @@ getatomprop(Client *c, Atom prop) 282 | unsigned long dl; 283 | unsigned char *p = NULL; 284 | Atom da, atom = None; 285 | + /* FIXME getatomprop should return the number of items and a pointer to 286 | + * the stored data instead of this workaround */ 287 | + Atom req = XA_ATOM; 288 | + if (prop == xatom[XembedInfo]) 289 | + req = xatom[XembedInfo]; 290 | 291 | - if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, 292 | + if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req, 293 | &da, &di, &dl, &dl, &p) == Success && p) { 294 | atom = *(Atom *)p; 295 | + if (da == xatom[XembedInfo] && dl == 2) 296 | + atom = ((Atom *)p)[1]; 297 | XFree(p); 298 | } 299 | return atom; 300 | @@ -899,6 +1002,16 @@ getstate(Window w) 301 | return result; 302 | } 303 | 304 | +unsigned int 305 | +getsystraywidth() 306 | +{ 307 | + unsigned int w = 0; 308 | + Client *i; 309 | + if(showsystray) 310 | + for(i = systray->icons; i; w += i->w + systrayspacing, i = i->next) ; 311 | + return w ? w + systrayspacing : 1; 312 | +} 313 | + 314 | int 315 | gettextprop(Window w, Atom atom, char *text, unsigned int size) 316 | { 317 | @@ -1005,7 +1118,7 @@ killclient(const Arg *arg) 318 | { 319 | if (!selmon->sel) 320 | return; 321 | - if (!sendevent(selmon->sel, wmatom[WMDelete])) { 322 | + if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0 , 0, 0)) { 323 | XGrabServer(dpy); 324 | XSetErrorHandler(xerrordummy); 325 | XSetCloseDownMode(dpy, DestroyAll); 326 | @@ -1093,6 +1206,12 @@ maprequest(XEvent *e) 327 | { 328 | static XWindowAttributes wa; 329 | XMapRequestEvent *ev = &e->xmaprequest; 330 | + Client *i; 331 | + if ((i = wintosystrayicon(ev->window))) { 332 | + sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION); 333 | + resizebarwin(selmon); 334 | + updatesystray(); 335 | + } 336 | 337 | if (!XGetWindowAttributes(dpy, ev->window, &wa)) 338 | return; 339 | @@ -1220,6 +1339,16 @@ propertynotify(XEvent *e) 340 | Window trans; 341 | XPropertyEvent *ev = &e->xproperty; 342 | 343 | + if ((c = wintosystrayicon(ev->window))) { 344 | + if (ev->atom == XA_WM_NORMAL_HINTS) { 345 | + updatesizehints(c); 346 | + updatesystrayicongeom(c, c->w, c->h); 347 | + } 348 | + else 349 | + updatesystrayiconstate(c, ev); 350 | + resizebarwin(selmon); 351 | + updatesystray(); 352 | + } 353 | if ((ev->window == root) && (ev->atom == XA_WM_NAME)) 354 | updatestatus(); 355 | else if (ev->state == PropertyDelete) 356 | @@ -1271,6 +1400,20 @@ recttomon(int x, int y, int w, int h) 357 | } 358 | 359 | void 360 | +removesystrayicon(Client *i) 361 | +{ 362 | + Client **ii; 363 | + 364 | + if (!showsystray || !i) 365 | + return; 366 | + for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next); 367 | + if (ii) 368 | + *ii = i->next; 369 | + free(i); 370 | +} 371 | + 372 | + 373 | +void 374 | resize(Client *c, int x, int y, int w, int h, int interact) 375 | { 376 | if (applysizehints(c, &x, &y, &w, &h, interact)) 377 | @@ -1278,6 +1421,14 @@ resize(Client *c, int x, int y, int w, int h, int interact) 378 | } 379 | 380 | void 381 | +resizebarwin(Monitor *m) { 382 | + unsigned int w = m->ww; 383 | + if (showsystray && m == systraytomon(m)) 384 | + w -= getsystraywidth(); 385 | + XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh); 386 | +} 387 | + 388 | +void 389 | resizeclient(Client *c, int x, int y, int w, int h) 390 | { 391 | XWindowChanges wc; 392 | @@ -1350,6 +1501,19 @@ resizemouse(const Arg *arg) 393 | } 394 | 395 | void 396 | +resizerequest(XEvent *e) 397 | +{ 398 | + XResizeRequestEvent *ev = &e->xresizerequest; 399 | + Client *i; 400 | + 401 | + if ((i = wintosystrayicon(ev->window))) { 402 | + updatesystrayicongeom(i, ev->width, ev->height); 403 | + resizebarwin(selmon); 404 | + updatesystray(); 405 | + } 406 | +} 407 | + 408 | +void 409 | restack(Monitor *m) 410 | { 411 | Client *c; 412 | @@ -1438,26 +1602,36 @@ setclientstate(Client *c, long state) 413 | } 414 | 415 | int 416 | -sendevent(Client *c, Atom proto) 417 | +sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4) 418 | { 419 | int n; 420 | - Atom *protocols; 421 | + Atom *protocols, mt; 422 | int exists = 0; 423 | XEvent ev; 424 | 425 | - if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { 426 | - while (!exists && n--) 427 | - exists = protocols[n] == proto; 428 | - XFree(protocols); 429 | + if (proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) { 430 | + mt = wmatom[WMProtocols]; 431 | + if (XGetWMProtocols(dpy, w, &protocols, &n)) { 432 | + while (!exists && n--) 433 | + exists = protocols[n] == proto; 434 | + XFree(protocols); 435 | + } 436 | + } 437 | + else { 438 | + exists = True; 439 | + mt = proto; 440 | } 441 | if (exists) { 442 | ev.type = ClientMessage; 443 | - ev.xclient.window = c->win; 444 | - ev.xclient.message_type = wmatom[WMProtocols]; 445 | + ev.xclient.window = w; 446 | + ev.xclient.message_type = mt; 447 | ev.xclient.format = 32; 448 | - ev.xclient.data.l[0] = proto; 449 | - ev.xclient.data.l[1] = CurrentTime; 450 | - XSendEvent(dpy, c->win, False, NoEventMask, &ev); 451 | + ev.xclient.data.l[0] = d0; 452 | + ev.xclient.data.l[1] = d1; 453 | + ev.xclient.data.l[2] = d2; 454 | + ev.xclient.data.l[3] = d3; 455 | + ev.xclient.data.l[4] = d4; 456 | + XSendEvent(dpy, w, False, mask, &ev); 457 | } 458 | return exists; 459 | } 460 | @@ -1471,7 +1645,7 @@ setfocus(Client *c) 461 | XA_WINDOW, 32, PropModeReplace, 462 | (unsigned char *) &(c->win), 1); 463 | } 464 | - sendevent(c, wmatom[WMTakeFocus]); 465 | + sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0); 466 | } 467 | 468 | void 469 | @@ -1560,6 +1734,10 @@ setup(void) 470 | wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); 471 | netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); 472 | netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); 473 | + netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False); 474 | + netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False); 475 | + netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False); 476 | + netatom[NetSystemTrayOrientationHorz] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION_HORZ", False); 477 | netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); 478 | netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); 479 | netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); 480 | @@ -1567,6 +1745,9 @@ setup(void) 481 | netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); 482 | netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); 483 | netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); 484 | + xatom[Manager] = XInternAtom(dpy, "MANAGER", False); 485 | + xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False); 486 | + xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False); 487 | /* init cursors */ 488 | cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); 489 | cursor[CurResize] = drw_cur_create(drw, XC_sizing); 490 | @@ -1575,6 +1756,8 @@ setup(void) 491 | scheme = ecalloc(LENGTH(colors), sizeof(Scm)); 492 | for (i = 0; i < LENGTH(colors); i++) 493 | scheme[i] = drw_scm_create(drw, colors[i], 3); 494 | + /* init system tray */ 495 | + updatesystray(); 496 | /* init bars */ 497 | updatebars(); 498 | updatestatus(); 499 | @@ -1705,7 +1888,18 @@ togglebar(const Arg *arg) 500 | { 501 | selmon->showbar = !selmon->showbar; 502 | updatebarpos(selmon); 503 | - XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); 504 | + resizebarwin(selmon); 505 | + if (showsystray) { 506 | + XWindowChanges wc; 507 | + if (!selmon->showbar) 508 | + wc.y = -bh; 509 | + else if (selmon->showbar) { 510 | + wc.y = 0; 511 | + if (!selmon->topbar) 512 | + wc.y = selmon->mh - bh; 513 | + } 514 | + XConfigureWindow(dpy, systray->win, CWY, &wc); 515 | + } 516 | arrange(selmon); 517 | } 518 | 519 | @@ -1801,11 +1995,18 @@ unmapnotify(XEvent *e) 520 | else 521 | unmanage(c, 0); 522 | } 523 | + else if ((c = wintosystrayicon(ev->window))) { 524 | + /* KLUDGE! sometimes icons occasionally unmap their windows, but do 525 | + * _not_ destroy them. We map those windows back */ 526 | + XMapRaised(dpy, c->win); 527 | + updatesystray(); 528 | + } 529 | } 530 | 531 | void 532 | updatebars(void) 533 | { 534 | + unsigned int w; 535 | Monitor *m; 536 | XSetWindowAttributes wa = { 537 | .override_redirect = True, 538 | @@ -1815,10 +2016,15 @@ updatebars(void) 539 | for (m = mons; m; m = m->next) { 540 | if (m->barwin) 541 | continue; 542 | - m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), 543 | + w = m->ww; 544 | + if (showsystray && m == systraytomon(m)) 545 | + w -= getsystraywidth(); 546 | + m->barwin = XCreateWindow(dpy, root, m->wx, m->by, w, bh, 0, DefaultDepth(dpy, screen), 547 | CopyFromParent, DefaultVisual(dpy, screen), 548 | CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); 549 | XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); 550 | + if (showsystray && m == systraytomon(m)) 551 | + XMapRaised(dpy, systray->win); 552 | XMapRaised(dpy, m->barwin); 553 | } 554 | } 555 | @@ -2006,6 +2212,121 @@ updatestatus(void) 556 | if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) 557 | strcpy(stext, "dwm-"VERSION); 558 | drawbar(selmon); 559 | + updatesystray(); 560 | +} 561 | + 562 | +void 563 | +updatesystrayicongeom(Client *i, int w, int h) 564 | +{ 565 | + if (i) { 566 | + i->h = bh; 567 | + if (w == h) 568 | + i->w = bh; 569 | + else if (h == bh) 570 | + i->w = w; 571 | + else 572 | + i->w = (int) ((float)bh * ((float)w / (float)h)); 573 | + applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False); 574 | + /* force icons into the systray dimenons if they don't want to */ 575 | + if (i->h > bh) { 576 | + if (i->w == i->h) 577 | + i->w = bh; 578 | + else 579 | + i->w = (int) ((float)bh * ((float)i->w / (float)i->h)); 580 | + i->h = bh; 581 | + } 582 | + } 583 | +} 584 | + 585 | +void 586 | +updatesystrayiconstate(Client *i, XPropertyEvent *ev) 587 | +{ 588 | + long flags; 589 | + int code = 0; 590 | + 591 | + if (!showsystray || !i || ev->atom != xatom[XembedInfo] || 592 | + !(flags = getatomprop(i, xatom[XembedInfo]))) 593 | + return; 594 | + 595 | + if (flags & XEMBED_MAPPED && !i->tags) { 596 | + i->tags = 1; 597 | + code = XEMBED_WINDOW_ACTIVATE; 598 | + XMapRaised(dpy, i->win); 599 | + setclientstate(i, NormalState); 600 | + } 601 | + else if (!(flags & XEMBED_MAPPED) && i->tags) { 602 | + i->tags = 0; 603 | + code = XEMBED_WINDOW_DEACTIVATE; 604 | + XUnmapWindow(dpy, i->win); 605 | + setclientstate(i, WithdrawnState); 606 | + } 607 | + else 608 | + return; 609 | + sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0, 610 | + systray->win, XEMBED_EMBEDDED_VERSION); 611 | +} 612 | + 613 | +void 614 | +updatesystray(void) 615 | +{ 616 | + XSetWindowAttributes wa; 617 | + XWindowChanges wc; 618 | + Client *i; 619 | + Monitor *m = systraytomon(NULL); 620 | + unsigned int x = m->mx + m->mw; 621 | + unsigned int w = 1; 622 | + 623 | + if (!showsystray) 624 | + return; 625 | + if (!systray) { 626 | + /* init systray */ 627 | + if (!(systray = (Systray *)calloc(1, sizeof(Systray)))) 628 | + die("fatal: could not malloc() %u bytes\n", sizeof(Systray)); 629 | + systray->win = XCreateSimpleWindow(dpy, root, x, m->by, w, bh, 0, 0, scheme[SchemeSel][ColBg].pixel); 630 | + wa.event_mask = ButtonPressMask | ExposureMask; 631 | + wa.override_redirect = True; 632 | + wa.background_pixel = scheme[SchemeNorm][ColBg].pixel; 633 | + XSelectInput(dpy, systray->win, SubstructureNotifyMask); 634 | + XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32, 635 | + PropModeReplace, (unsigned char *)&netatom[NetSystemTrayOrientationHorz], 1); 636 | + XChangeWindowAttributes(dpy, systray->win, CWEventMask|CWOverrideRedirect|CWBackPixel, &wa); 637 | + XMapRaised(dpy, systray->win); 638 | + XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime); 639 | + if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) { 640 | + sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0); 641 | + XSync(dpy, False); 642 | + } 643 | + else { 644 | + fprintf(stderr, "dwm: unable to obtain system tray.\n"); 645 | + free(systray); 646 | + systray = NULL; 647 | + return; 648 | + } 649 | + } 650 | + for (w = 0, i = systray->icons; i; i = i->next) { 651 | + /* make sure the background color stays the same */ 652 | + wa.background_pixel = scheme[SchemeNorm][ColBg].pixel; 653 | + XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa); 654 | + XMapRaised(dpy, i->win); 655 | + w += systrayspacing; 656 | + i->x = w; 657 | + XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h); 658 | + w += i->w; 659 | + if (i->mon != m) 660 | + i->mon = m; 661 | + } 662 | + w = w ? w + systrayspacing : 1; 663 | + x -= w; 664 | + XMoveResizeWindow(dpy, systray->win, x, m->by, w, bh); 665 | + wc.x = x; wc.y = m->by; wc.width = w; wc.height = bh; 666 | + wc.stack_mode = Above; wc.sibling = m->barwin; 667 | + XConfigureWindow(dpy, systray->win, CWX|CWY|CWWidth|CWHeight|CWSibling|CWStackMode, &wc); 668 | + XMapWindow(dpy, systray->win); 669 | + XMapSubwindows(dpy, systray->win); 670 | + /* redraw background */ 671 | + XSetForeground(dpy, drw->gc, scheme[SchemeNorm][ColBg].pixel); 672 | + XFillRectangle(dpy, systray->win, drw->gc, 0, 0, w, bh); 673 | + XSync(dpy, False); 674 | } 675 | 676 | void 677 | @@ -2064,6 +2385,16 @@ wintoclient(Window w) 678 | return NULL; 679 | } 680 | 681 | +Client * 682 | +wintosystrayicon(Window w) { 683 | + Client *i = NULL; 684 | + 685 | + if (!showsystray || !w) 686 | + return i; 687 | + for (i = systray->icons; i && i->win != w; i = i->next) ; 688 | + return i; 689 | +} 690 | + 691 | Monitor * 692 | wintomon(Window w) 693 | { 694 | @@ -2117,6 +2448,22 @@ xerrorstart(Display *dpy, XErrorEvent *ee) 695 | return -1; 696 | } 697 | 698 | +Monitor * 699 | +systraytomon(Monitor *m) { 700 | + Monitor *t; 701 | + int i, n; 702 | + if(!systraypinning) { 703 | + if(!m) 704 | + return selmon; 705 | + return m == selmon ? m : NULL; 706 | + } 707 | + for(n = 1, t = mons; t && t->next; n++, t = t->next) ; 708 | + for(i = 1, t = mons; t && t->next && i < systraypinning; i++, t = t->next) ; 709 | + if(systraypinningfailfirst && n < systraypinning) 710 | + return mons; 711 | + return t; 712 | +} 713 | + 714 | void 715 | zoom(const Arg *arg) 716 | { 717 | --------------------------------------------------------------------------------